diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index a34bf5f8..8b485e48 100644 --- a/src/arch/i386/prefix/pxeprefix.S +++ b/src/arch/i386/prefix/pxeprefix.S @@ -1,22 +1,24 @@ -#define PXENV_UNDI_SHUTDOWN 0x05 -#define PXENV_STOP_UNDI 0x15 -#define PXENV_UNLOAD_STACK 0x70 +#define PXENV_UNDI_SHUTDOWN 0x0005 +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define PXENV_STOP_UNDI 0x0015 +#define PXENV_UNLOAD_STACK 0x0070 #define PXE_STACK_MAGIC 0x57ac /* 'STac' */ .text - .code16 .arch i386 .org 0 .section ".prefix", "ax", @progbits + .section ".prefix.data", "aw", @progbits + .code16 + /***************************************************************************** - * Entry point: set cs, ds, bp, print welcome message + * Entry point: set operating context, print welcome message ***************************************************************************** - */ - jmp $0x7c0, $code_start -10: .asciz "PXE->EB " -code_start: - /* Preserve registers for return to PXE stack */ + */ + .section ".prefix" + jmp $0x7c0, $1f +1: /* Preserve registers for return to PXE stack */ pushfl pushal pushw %gs @@ -28,92 +30,110 @@ code_start: pushw $PXE_STACK_MAGIC /* PXE stack magic marker */ /* Set up stack just below 0x7c00 */ pushw %ss - popw %es - movw %sp, %di + popw %gs + movw %sp, %bp /* %gs:%bp points to old PXE stack */ xorw %ax, %ax movw %ax, %ss movw $0x7c00, %sp - pushw %es /* Save old PXE stack pointer */ - pushw %di + pushw %gs /* Save old PXE stack pointer */ + pushw %bp /* Set up our other segment registers */ pushw %cs popw %ds movw $0x40, %ax /* BIOS data segment access */ movw %ax, %fs + /* Clear direction flag, for the sake of sanity */ + cld /* Print welcome message */ - movw $10b, %si - call print_message - -/***************************************************************************** - * Detect type of PXE available (!PXE, PXENV+ or none) - ***************************************************************************** - */ -detect_pxe: - les %es:54(%di), %di /* !PXE structure */ - cmpl $0x45585021, %es:(%di) /* '!PXE' signature */ - je detected_pxe - movw $0x5650, %ax - int $0x1a - cmpw $0x564e, %ax - jne detected_nothing - cmpl $0x4e455850, %es:(%bx) /* 'PXEN' signature */ - jne detected_nothing - cmpw $0x2b56, %es:4(%bx) /* 'V+' signature */ - je detected_pxenv - -detected_nothing: movw $10f, %si call print_message - jmp finished_with_error -10: .asciz "No PXE " + .section ".prefix.data" +10: .asciz "PXE->EB:" + .previous -detected_pxenv: /* es:bx points to PXENV+ structure */ +/***************************************************************************** + * Verify PXENV+ structure and record parameters of interest + ***************************************************************************** + */ +detect_pxenv: + /* Signature check */ + cmpl $0x4e455850, %es:(%bx) /* 'PXEN' signature */ + jne 99f + cmpw $0x2b56, %es:4(%bx) /* 'V+' signature */ + jne 99f + /* Record structure address, entry point, and UNDI segments */ pushw %es - pushw %bx + popw pxenv_segment + movw %bx, pxenv_offset + pushl %es:0x0a(%bx) /* Entry point */ + popl entry_segoff pushw %es:0x24(%bx) /* UNDI code segment */ pushw %es:0x26(%bx) /* UNDI code size */ + popl undi_code_segoff pushw %es:0x20(%bx) /* UNDI data segment */ pushw %es:0x22(%bx) /* UNDI data size */ - les %es:0x0a(%bx), %di /* Entry point to %es:%di */ + popl undi_data_segoff + /* Print "PXENV+ at
" */ movw $10f, %si - jmp pxe_setup_done -10: .asciz "PXENV+ " - -detected_pxe: /* es:di points to !PXE structure */ - pushw %es - pushw %di - pushw %es:0x30(%di) /* UNDI code segment */ - pushw %es:0x36(%di) /* UNDI code size */ - pushw %es:0x28(%di) /* UNDI data segment */ - pushw %es:0x2e(%di) /* UNDI data size */ - les %es:0x10(%di), %di /* Entry point to %es:%di */ - movw $10f, %si - jmp pxe_setup_done -10: .asciz "!PXE " - -pxe_setup_done: - movw %es, pxe_entry_segment - movw %di, pxe_entry_offset - popw undi_data_size - popw undi_data_segment - popw undi_code_size - popw undi_code_segment call print_message - popw %di - popw %es /* Exit with %es:%di containing structure address */ - + movw %bx, %di + call print_segoff + movb $',', %al + call print_character + .section ".prefix.data" +10: .asciz " PXENV+ at " + .previous +99: + /***************************************************************************** - * Print information about located structure + * Verify !PXE structure and record parameters of interest ***************************************************************************** */ -print_structure_information: - call print_segoff /* %es:%di contains address of structure */ - les pxe_entry_segoff, %di - call print_segoff - les undi_code_segoff, %di - call print_segoff - les undi_data_segoff, %di +detect_ppxe: + /* Signature check */ + les %gs:54(%bp), %di /* !PXE structure */ + cmpl $0x45585021, %es:(%di) /* '!PXE' signature */ + jne 99f + /* Record structure address, entry point, and UNDI segments */ + pushw %es + popw ppxe_segment + movw %di, ppxe_offset + pushl %es:0x10(%di) /* Entry point */ + popl entry_segoff + pushw %es:0x30(%di) /* UNDI code segment */ + pushw %es:0x36(%di) /* UNDI code size */ + popl undi_code_segoff + pushw %es:0x28(%di) /* UNDI data segment */ + pushw %es:0x2e(%di) /* UNDI data size */ + popl undi_data_segoff + /* Print "!PXE at " */ + movw $10f, %si + call print_message call print_segoff + movb $',', %al + call print_character + .section ".prefix.data" +10: .asciz " !PXE at " + .previous +99: + +/***************************************************************************** + * Sanity check: we must have an entry point + ***************************************************************************** + */ +check_have_stack: + /* Check for entry point */ + movl entry_segoff, %eax + testl %eax, %eax + jnz 99f + /* No entry point: print message and skip everything else */ + movw $10f, %si + call print_message + jmp finished + .section ".prefix.data" +10: .asciz " No PXE stack found!\n" + .previous +99: /***************************************************************************** * Calculate base memory usage by UNDI @@ -138,66 +158,178 @@ find_undi_basemem_usage: shrw $6, %cx movw %cx, undi_fbms_end +/***************************************************************************** + * Print information about detected PXE stack + ***************************************************************************** + */ +print_structure_information: + /* Print entry point */ + movw $10f, %si + call print_message + les entry_segoff, %di + call print_segoff + .section ".prefix.data" +10: .asciz " entry point at " + .previous + /* Print UNDI code segment */ + movw $10f, %si + call print_message + les undi_code_segoff, %di + call print_segoff + .section ".prefix.data" +10: .asciz "\n UNDI code segment " + .previous + /* Print UNDI data segment */ + movw $10f, %si + call print_message + les undi_data_segoff, %di + call print_segoff + .section ".prefix.data" +10: .asciz ", data segment " + .previous + /* Print UNDI memory usage */ + movw $10f, %si + call print_message + movw undi_fbms_start, %ax + call print_word + movb $'-', %al + call print_character + movw undi_fbms_end, %ax + call print_word + movw $20f, %si + call print_message + .section ".prefix.data" +10: .asciz " (" +20: .asciz "kB)\n" + .previous + +/***************************************************************************** + * Determine physical device + ***************************************************************************** + */ +get_physical_device: + /* Issue PXENV_UNDI_GET_NIC_TYPE */ + movw $PXENV_UNDI_GET_NIC_TYPE, %bx + call pxe_call + jnc 1f + call print_pxe_error + jmp no_physical_device +1: /* Determine physical device type */ + movb ( pxe_parameter_structure + 0x02 ), %al + cmpb $2, %al + je pci_physical_device + jmp no_physical_device + +pci_physical_device: + /* Record PCI bus:dev.fn */ + movw ( pxe_parameter_structure + 0x0b ), %ax + movw %ax, pci_busdevfn + movw $10f, %si + call print_message + call print_pci_busdevfn + movb $0x0a, %al + call print_character + jmp 99f + .section ".prefix.data" +10: .asciz " UNDI device is PCI " + .previous + +no_physical_device: + /* No device found, or device type not understood */ + movw $10f, %si + call print_message + .section ".prefix.data" +10: .asciz " Unable to determine UNDI physical device\n" + .previous + +99: + /***************************************************************************** * Leave NIC in a safe state ***************************************************************************** */ shutdown_nic: + /* Issue PXENV_UNDI_SHUTDOWN */ movw $PXENV_UNDI_SHUTDOWN, %bx call pxe_call + jnc 1f + call print_pxe_error +1: /***************************************************************************** * Unload PXE base code ***************************************************************************** */ unload_base_code: + /* Issue PXENV_UNLOAD_STACK */ movw $PXENV_UNLOAD_STACK, %bx call pxe_call - jnz do_not_free_base_code -free_base_code: + jnc 1f + call print_pxe_error + jmp 99f +1: /* Free base memory used by PXE base code */ movw %fs:(0x13), %si movw undi_fbms_start, %di call free_basemem -do_not_free_base_code: +99: /***************************************************************************** * Unload UNDI driver ***************************************************************************** */ unload_undi: + /* Issue PXENV_STOP_UNDI */ movw $PXENV_STOP_UNDI, %bx call pxe_call + jnc 1f + call print_pxe_error + jmp 99f +1: /* Free base memory used by UNDI */ #ifndef PXELOADER_KEEP_UNDI - jnz do_not_free_undi -free_undi: movw undi_fbms_start, %si movw undi_fbms_end, %di call free_basemem -do_not_free_undi: #endif /* PXELOADER_KEEP_UNDI */ +99: +/***************************************************************************** + * Print remaining free base memory + ***************************************************************************** + */ +print_free_basemem: + movw $10f, %si + call print_message + movw %fs:(0x13), %ax + call print_word + movw $20f, %si + call print_message + .section ".prefix.data" +10: .asciz " " +20: .asciz "kB free base memory after PXE unload\n" + .previous + /***************************************************************************** * Exit point ***************************************************************************** */ finished: - movw $10f, %si - movw pxe_overall_status, %ax - testw %ax, %ax - jz 1f -finished_with_error: - movw $20f, %si -1: - call print_message jmp run_etherboot -10: .asciz "ok\n" -20: .asciz "err\n" /***************************************************************************** - * Subroutine: print character in %al (with LF -> LF,CR translation) + * Subroutine: print character (with LF -> LF,CR translation) + * + * Parameters: + * %al : character to print + * Returns: + * Nothing ***************************************************************************** */ print_character: + /* Preserve registers */ + pushw %ax + pushw %bx + pushw %bp + /* Print character */ movw $0x0007, %bx /* page 0, attribute 7 (normal) */ movb $0x0e, %ah /* write char, tty mode */ cmpb $0x0a, %al /* '\n'? */ @@ -205,122 +337,318 @@ print_character: int $0x10 movb $0x0d, %al 1: int $0x10 + /* Restore registers and return */ + popw %bp + popw %bx + popw %ax ret /***************************************************************************** - * Subroutine: print a zero-terminated message starting at %si + * Subroutine: print a NUL-terminated string + * + * Parameters: + * %ds:%si : string to print + * Returns: + * Nothing ***************************************************************************** */ print_message: + /* Preserve registers */ + pushw %ax + pushw %si + /* Print string */ 1: lodsb testb %al, %al je 2f call print_character jmp 1b -2: ret +2: /* Restore registers and return */ + popw %si + popw %ax + ret /***************************************************************************** - * Subroutine: print hex word in %ax + * Subroutine: print hex digit + * + * Parameters: + * %al (low nibble) : digit to print + * Returns: + * Nothing ***************************************************************************** */ -print_hex_word: - movw $4, %cx -1: +print_hex_nibble: + /* Preserve registers */ pushw %ax - shrw $12, %ax - /* Courtesy of Norbert Juffa