2007-01-09 01:42:28 +00:00
|
|
|
#define PXENV_UNDI_SHUTDOWN 0x0005
|
|
|
|
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
|
|
|
|
#define PXENV_STOP_UNDI 0x0015
|
|
|
|
#define PXENV_UNLOAD_STACK 0x0070
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
#define PXE_STACK_MAGIC 0x57ac /* 'STac' */
|
|
|
|
|
|
|
|
.text
|
|
|
|
.arch i386
|
|
|
|
.org 0
|
|
|
|
.section ".prefix", "ax", @progbits
|
2007-01-09 01:42:28 +00:00
|
|
|
.section ".prefix.data", "aw", @progbits
|
|
|
|
.code16
|
|
|
|
|
2005-03-08 18:53:11 +00:00
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Entry point: set operating context, print welcome message
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
*/
|
|
|
|
.section ".prefix"
|
|
|
|
jmp $0x7c0, $1f
|
|
|
|
1: /* Preserve registers for return to PXE stack */
|
2006-05-25 22:04:47 +00:00
|
|
|
pushfl
|
|
|
|
pushal
|
|
|
|
pushw %gs
|
|
|
|
pushw %fs
|
|
|
|
pushw %es
|
|
|
|
pushw %ds
|
|
|
|
pushw %ss
|
|
|
|
pushw %cs
|
|
|
|
pushw $PXE_STACK_MAGIC /* PXE stack magic marker */
|
|
|
|
/* Set up stack just below 0x7c00 */
|
|
|
|
pushw %ss
|
2007-01-09 01:42:28 +00:00
|
|
|
popw %gs
|
|
|
|
movw %sp, %bp /* %gs:%bp points to old PXE stack */
|
2006-05-25 22:04:47 +00:00
|
|
|
xorw %ax, %ax
|
|
|
|
movw %ax, %ss
|
|
|
|
movw $0x7c00, %sp
|
2007-01-09 01:42:28 +00:00
|
|
|
pushw %gs /* Save old PXE stack pointer */
|
|
|
|
pushw %bp
|
2006-05-25 22:04:47 +00:00
|
|
|
/* Set up our other segment registers */
|
|
|
|
pushw %cs
|
|
|
|
popw %ds
|
|
|
|
movw $0x40, %ax /* BIOS data segment access */
|
|
|
|
movw %ax, %fs
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Clear direction flag, for the sake of sanity */
|
|
|
|
cld
|
2006-05-25 22:04:47 +00:00
|
|
|
/* Print welcome message */
|
2007-01-09 01:42:28 +00:00
|
|
|
movw $10f, %si
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_message
|
2007-01-09 01:42:28 +00:00
|
|
|
.section ".prefix.data"
|
|
|
|
10: .asciz "PXE->EB:"
|
|
|
|
.previous
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Verify PXENV+ structure and record parameters of interest
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2007-01-09 01:42:28 +00:00
|
|
|
detect_pxenv:
|
|
|
|
/* Signature check */
|
2005-03-08 18:53:11 +00:00
|
|
|
cmpl $0x4e455850, %es:(%bx) /* 'PXEN' signature */
|
2007-01-09 01:42:28 +00:00
|
|
|
jne 99f
|
2005-03-08 18:53:11 +00:00
|
|
|
cmpw $0x2b56, %es:4(%bx) /* 'V+' signature */
|
2007-01-09 01:42:28 +00:00
|
|
|
jne 99f
|
|
|
|
/* Record structure address, entry point, and UNDI segments */
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es
|
2007-01-09 01:42:28 +00:00
|
|
|
popw pxenv_segment
|
|
|
|
movw %bx, pxenv_offset
|
|
|
|
pushl %es:0x0a(%bx) /* Entry point */
|
|
|
|
popl entry_segoff
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es:0x24(%bx) /* UNDI code segment */
|
|
|
|
pushw %es:0x26(%bx) /* UNDI code size */
|
2007-01-09 01:42:28 +00:00
|
|
|
popl undi_code_segoff
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es:0x20(%bx) /* UNDI data segment */
|
|
|
|
pushw %es:0x22(%bx) /* UNDI data size */
|
2007-01-09 01:42:28 +00:00
|
|
|
popl undi_data_segoff
|
|
|
|
/* Print "PXENV+ at <address>" */
|
2006-05-25 22:04:47 +00:00
|
|
|
movw $10f, %si
|
2007-01-09 01:42:28 +00:00
|
|
|
call print_message
|
|
|
|
movw %bx, %di
|
|
|
|
call print_segoff
|
|
|
|
movb $',', %al
|
|
|
|
call print_character
|
|
|
|
.section ".prefix.data"
|
|
|
|
10: .asciz " PXENV+ at "
|
|
|
|
.previous
|
|
|
|
99:
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Verify !PXE structure and record parameters of interest
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
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 */
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es
|
2007-01-09 01:42:28 +00:00
|
|
|
popw ppxe_segment
|
|
|
|
movw %di, ppxe_offset
|
|
|
|
pushl %es:0x10(%di) /* Entry point */
|
|
|
|
popl entry_segoff
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es:0x30(%di) /* UNDI code segment */
|
|
|
|
pushw %es:0x36(%di) /* UNDI code size */
|
2007-01-09 01:42:28 +00:00
|
|
|
popl undi_code_segoff
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %es:0x28(%di) /* UNDI data segment */
|
|
|
|
pushw %es:0x2e(%di) /* UNDI data size */
|
2007-01-09 01:42:28 +00:00
|
|
|
popl undi_data_segoff
|
|
|
|
/* Print "!PXE at <address>" */
|
2006-05-25 22:04:47 +00:00
|
|
|
movw $10f, %si
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_message
|
2007-01-09 01:42:28 +00:00
|
|
|
call print_segoff
|
|
|
|
movb $',', %al
|
|
|
|
call print_character
|
|
|
|
.section ".prefix.data"
|
|
|
|
10: .asciz " !PXE at "
|
|
|
|
.previous
|
|
|
|
99:
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Sanity check: we must have an entry point
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2007-01-09 01:42:28 +00:00
|
|
|
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:
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-08 03:48:26 +00:00
|
|
|
* Calculate base memory usage by UNDI
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2007-01-08 03:48:26 +00:00
|
|
|
find_undi_basemem_usage:
|
|
|
|
movw undi_code_segment, %ax
|
|
|
|
movw undi_code_size, %bx
|
|
|
|
movw undi_data_segment, %cx
|
|
|
|
movw undi_data_size, %dx
|
|
|
|
cmpw %ax, %cx
|
|
|
|
ja 1f
|
|
|
|
xchgw %ax, %cx
|
|
|
|
xchgw %bx, %dx
|
|
|
|
1: /* %ax:%bx now describes the lower region, %cx:%dx the higher */
|
|
|
|
shrw $6, %ax /* Round down to nearest kB */
|
|
|
|
movw %ax, undi_fbms_start
|
|
|
|
addw $0x0f, %dx /* Round up to next segment */
|
|
|
|
shrw $4, %dx
|
|
|
|
addw %dx, %cx
|
|
|
|
addw $((1024 / 16) - 1), %cx /* Round up to next kB */
|
|
|
|
shrw $6, %cx
|
|
|
|
movw %cx, undi_fbms_end
|
|
|
|
|
2007-01-09 01:42:28 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* 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:
|
|
|
|
|
2007-01-08 05:06:26 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* Leave NIC in a safe state
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
shutdown_nic:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Issue PXENV_UNDI_SHUTDOWN */
|
2007-01-08 05:06:26 +00:00
|
|
|
movw $PXENV_UNDI_SHUTDOWN, %bx
|
|
|
|
call pxe_call
|
2007-01-09 01:42:28 +00:00
|
|
|
jnc 1f
|
|
|
|
call print_pxe_error
|
|
|
|
1:
|
2007-01-08 05:06:26 +00:00
|
|
|
|
2007-01-08 03:48:26 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* Unload PXE base code
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
unload_base_code:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Issue PXENV_UNLOAD_STACK */
|
2007-01-08 03:48:26 +00:00
|
|
|
movw $PXENV_UNLOAD_STACK, %bx
|
2005-03-08 18:53:11 +00:00
|
|
|
call pxe_call
|
2007-01-09 01:42:28 +00:00
|
|
|
jnc 1f
|
|
|
|
call print_pxe_error
|
|
|
|
jmp 99f
|
|
|
|
1: /* Free base memory used by PXE base code */
|
2007-01-08 03:48:26 +00:00
|
|
|
movw %fs:(0x13), %si
|
|
|
|
movw undi_fbms_start, %di
|
|
|
|
call free_basemem
|
2007-01-09 01:42:28 +00:00
|
|
|
99:
|
2007-01-08 03:48:26 +00:00
|
|
|
|
2005-03-08 18:53:11 +00:00
|
|
|
/*****************************************************************************
|
2007-01-08 03:48:26 +00:00
|
|
|
* Unload UNDI driver
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2007-01-08 03:48:26 +00:00
|
|
|
unload_undi:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Issue PXENV_STOP_UNDI */
|
2007-01-08 03:48:26 +00:00
|
|
|
movw $PXENV_STOP_UNDI, %bx
|
|
|
|
call pxe_call
|
2007-01-09 01:42:28 +00:00
|
|
|
jnc 1f
|
|
|
|
call print_pxe_error
|
|
|
|
jmp 99f
|
|
|
|
1: /* Free base memory used by UNDI */
|
2007-01-08 03:48:26 +00:00
|
|
|
#ifndef PXELOADER_KEEP_UNDI
|
|
|
|
movw undi_fbms_start, %si
|
|
|
|
movw undi_fbms_end, %di
|
|
|
|
call free_basemem
|
|
|
|
#endif /* PXELOADER_KEEP_UNDI */
|
2007-01-09 01:42:28 +00:00
|
|
|
99:
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Print remaining free base memory
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
*/
|
|
|
|
print_free_basemem:
|
2006-05-25 22:04:47 +00:00
|
|
|
movw $10f, %si
|
2007-01-09 01:42:28 +00:00
|
|
|
call print_message
|
|
|
|
movw %fs:(0x13), %ax
|
|
|
|
call print_word
|
2006-05-25 22:04:47 +00:00
|
|
|
movw $20f, %si
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_message
|
2007-01-09 01:42:28 +00:00
|
|
|
.section ".prefix.data"
|
|
|
|
10: .asciz " "
|
|
|
|
20: .asciz "kB free base memory after PXE unload\n"
|
|
|
|
.previous
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Exit point
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
finished:
|
2006-05-25 22:04:47 +00:00
|
|
|
jmp run_etherboot
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: print character (with LF -> LF,CR translation)
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %al : character to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_character:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
pushw %bx
|
|
|
|
pushw %bp
|
|
|
|
/* Print character */
|
2005-03-08 18:53:11 +00:00
|
|
|
movw $0x0007, %bx /* page 0, attribute 7 (normal) */
|
|
|
|
movb $0x0e, %ah /* write char, tty mode */
|
|
|
|
cmpb $0x0a, %al /* '\n'? */
|
|
|
|
jne 1f
|
|
|
|
int $0x10
|
|
|
|
movb $0x0d, %al
|
|
|
|
1: int $0x10
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Restore registers and return */
|
|
|
|
popw %bp
|
|
|
|
popw %bx
|
|
|
|
popw %ax
|
2005-03-08 18:53:11 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: print a NUL-terminated string
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %ds:%si : string to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_message:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
pushw %si
|
|
|
|
/* Print string */
|
2005-03-08 18:53:11 +00:00
|
|
|
1: lodsb
|
|
|
|
testb %al, %al
|
|
|
|
je 2f
|
|
|
|
call print_character
|
|
|
|
jmp 1b
|
2007-01-09 01:42:28 +00:00
|
|
|
2: /* Restore registers and return */
|
|
|
|
popw %si
|
|
|
|
popw %ax
|
|
|
|
ret
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: print hex digit
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %al (low nibble) : digit to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2007-01-09 01:42:28 +00:00
|
|
|
print_hex_nibble:
|
|
|
|
/* Preserve registers */
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %ax
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
|
|
|
|
andb $0x0f, %al
|
|
|
|
cmpb $10, %al
|
2006-05-25 22:04:47 +00:00
|
|
|
sbbb $0x69, %al
|
2005-03-08 18:53:11 +00:00
|
|
|
das
|
|
|
|
call print_character
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Restore registers and return */
|
2006-05-25 22:04:47 +00:00
|
|
|
popw %ax
|
2007-01-09 01:42:28 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: print hex byte
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %al : byte to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_hex_byte:
|
|
|
|
rorb $4, %al
|
|
|
|
call print_hex_nibble
|
|
|
|
rorb $4, %al
|
|
|
|
call print_hex_nibble
|
2005-03-08 18:53:11 +00:00
|
|
|
ret
|
2007-01-09 01:42:28 +00:00
|
|
|
|
2005-03-08 18:53:11 +00:00
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: print hex word
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %ax : word to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_hex_word:
|
|
|
|
xchgb %al, %ah
|
|
|
|
call print_hex_byte
|
|
|
|
xchgb %al, %ah
|
|
|
|
call print_hex_byte
|
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: print segment:offset address
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %es:%di : segment:offset address to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_segoff:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
/* Print "<segment>:offset" */
|
|
|
|
movw %es, %ax
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_hex_word
|
2007-01-09 01:42:28 +00:00
|
|
|
movb $':', %al
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_character
|
2007-01-09 01:42:28 +00:00
|
|
|
movw %di, %ax
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_hex_word
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Restore registers and return */
|
|
|
|
popw %ax
|
2005-03-08 18:53:11 +00:00
|
|
|
ret
|
2007-01-08 03:48:26 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: print decimal word
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %ax : word to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_word:
|
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
pushw %bx
|
|
|
|
pushw %cx
|
|
|
|
pushw %dx
|
|
|
|
/* Build up digit sequence on stack */
|
|
|
|
movw $10, %bx
|
|
|
|
xorw %cx, %cx
|
|
|
|
1: xorw %dx, %dx
|
|
|
|
divw %bx, %ax
|
|
|
|
pushw %dx
|
|
|
|
incw %cx
|
|
|
|
testw %ax, %ax
|
|
|
|
jnz 1b
|
|
|
|
/* Print digit sequence */
|
|
|
|
1: popw %ax
|
|
|
|
call print_hex_nibble
|
|
|
|
loop 1b
|
|
|
|
/* Restore registers and return */
|
|
|
|
popw %dx
|
|
|
|
popw %cx
|
|
|
|
popw %bx
|
|
|
|
popw %ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: print PCI bus:dev.fn
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %ax : PCI bus:dev.fn to print
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_pci_busdevfn:
|
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
/* Print bus */
|
|
|
|
xchgb %al, %ah
|
|
|
|
call print_hex_byte
|
|
|
|
/* Print ":" */
|
|
|
|
movb $':', %al
|
|
|
|
call print_character
|
|
|
|
/* Print device */
|
|
|
|
movb %ah, %al
|
|
|
|
shrb $3, %al
|
|
|
|
call print_hex_byte
|
|
|
|
/* Print "." */
|
|
|
|
movb $'.', %al
|
|
|
|
call print_character
|
|
|
|
/* Print function */
|
|
|
|
movb %ah, %al
|
|
|
|
andb $0x07, %al
|
|
|
|
call print_hex_nibble
|
|
|
|
/* Restore registers and return */
|
|
|
|
popw %ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: zero 1kB block of base memory
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %si : block to zero (in kB)
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
2007-01-08 03:48:26 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
zero_kb:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Preserve registers */
|
|
|
|
pushw %ax
|
|
|
|
pushw %cx
|
|
|
|
pushw %di
|
|
|
|
pushw %es
|
|
|
|
/* Zero block */
|
|
|
|
movw %si, %ax
|
2007-01-08 03:48:26 +00:00
|
|
|
shlw $6, %ax
|
|
|
|
movw %ax, %es
|
|
|
|
movw $0x400, %cx
|
2007-01-09 01:42:28 +00:00
|
|
|
xorw %di, %di
|
|
|
|
xorw %ax, %ax
|
2007-01-08 03:48:26 +00:00
|
|
|
rep stosb
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Restore registers and return */
|
|
|
|
popw %es
|
|
|
|
popw %di
|
|
|
|
popw %cx
|
|
|
|
popw %ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: free and zero base memory
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %si : Expected current free base memory counter (in kB)
|
|
|
|
* %di : Desired new free base memory counter (in kB)
|
|
|
|
* %fs : BIOS data segment (0x40)
|
|
|
|
* Returns:
|
|
|
|
* %ax : Actual new free base memory counter (in kB)
|
|
|
|
*
|
|
|
|
* The base memory from %si kB to %di kB is unconditionally zeroed.
|
|
|
|
* It will be freed if and only if the expected current free base
|
|
|
|
* memory counter (%si) matches the actual current free base memory
|
|
|
|
* counter in 0x40:0x13; if this does not match then the memory will
|
|
|
|
* be leaked.
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
free_basemem:
|
|
|
|
/* Zero base memory */
|
|
|
|
pushw %si
|
|
|
|
1: cmpw %si, %di
|
|
|
|
je 2f
|
|
|
|
call zero_kb
|
|
|
|
incw %si
|
|
|
|
jmp 1b
|
|
|
|
2: popw %si
|
|
|
|
/* Free base memory */
|
|
|
|
movw %fs:(0x13), %ax /* Current FBMS to %ax */
|
|
|
|
cmpw %ax, %si /* Update FBMS only if "old" value */
|
|
|
|
jne 1f /* is correct */
|
|
|
|
movw %di, %ax
|
|
|
|
1: movw %ax, %fs:(0x13)
|
2007-01-08 03:48:26 +00:00
|
|
|
ret
|
|
|
|
|
2005-03-08 18:53:11 +00:00
|
|
|
/*****************************************************************************
|
2007-01-09 01:42:28 +00:00
|
|
|
* Subroutine: make a PXE API call. Works with either !PXE or PXENV+ API.
|
2007-01-08 03:48:26 +00:00
|
|
|
*
|
2007-01-09 01:42:28 +00:00
|
|
|
* Parameters:
|
|
|
|
* %bx : PXE API call number
|
|
|
|
* %ds:pxe_parameter_structure : Parameters for PXE API call
|
|
|
|
* Returns:
|
|
|
|
* %ax : PXE status code (not exit code)
|
|
|
|
* CF set if %ax is non-zero
|
2005-03-08 18:53:11 +00:00
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
pxe_call:
|
2007-01-09 01:42:28 +00:00
|
|
|
/* Preserve registers */
|
|
|
|
pushw %di
|
|
|
|
pushw %es
|
2005-03-08 18:53:11 +00:00
|
|
|
/* Set up registers for PXENV+ API. %bx already set up */
|
2006-05-25 22:04:47 +00:00
|
|
|
pushw %ds
|
|
|
|
popw %es
|
|
|
|
movw $pxe_parameter_structure, %di
|
2005-03-08 18:53:11 +00:00
|
|
|
/* Set up stack for !PXE API */
|
2007-01-09 01:42:28 +00:00
|
|
|
pushw %es
|
2005-03-08 18:53:11 +00:00
|
|
|
pushw %di
|
|
|
|
pushw %bx
|
|
|
|
/* Make the API call */
|
2007-01-09 01:42:28 +00:00
|
|
|
lcall *entry_segoff
|
2005-03-08 18:53:11 +00:00
|
|
|
/* Reset the stack */
|
2006-05-25 22:04:47 +00:00
|
|
|
addw $6, %sp
|
|
|
|
movw pxe_parameter_structure, %ax
|
2007-01-09 01:42:28 +00:00
|
|
|
clc
|
|
|
|
testw %ax, %ax
|
|
|
|
jz 1f
|
|
|
|
stc
|
|
|
|
1: /* Restore registers and return */
|
|
|
|
popw %es
|
|
|
|
popw %di
|
|
|
|
ret
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Subroutine: print PXE API call error message
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* %ax : PXE status code
|
|
|
|
* %bx : PXE API call number
|
|
|
|
* Returns:
|
|
|
|
* Nothing
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
print_pxe_error:
|
|
|
|
pushw %si
|
|
|
|
movw $10f, %si
|
|
|
|
call print_message
|
|
|
|
xchgw %ax, %bx
|
2005-03-08 18:53:11 +00:00
|
|
|
call print_hex_word
|
2007-01-09 01:42:28 +00:00
|
|
|
movw $20f, %si
|
|
|
|
call print_message
|
|
|
|
xchgw %ax, %bx
|
|
|
|
call print_hex_word
|
|
|
|
movw $30f, %si
|
|
|
|
call print_message
|
|
|
|
popw %si
|
2005-03-08 18:53:11 +00:00
|
|
|
ret
|
2007-01-09 01:42:28 +00:00
|
|
|
.section ".prefix.data"
|
|
|
|
10: .asciz " UNDI API call "
|
|
|
|
20: .asciz " failed: status code "
|
|
|
|
30: .asciz "\n"
|
|
|
|
.previous
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* PXE data structures
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
|
2007-01-09 01:42:28 +00:00
|
|
|
pxe_parameter_structure: .fill 20
|
2005-03-08 18:53:11 +00:00
|
|
|
|
|
|
|
undi_code_segoff:
|
|
|
|
undi_code_size: .word 0
|
|
|
|
undi_code_segment: .word 0
|
|
|
|
|
|
|
|
undi_data_segoff:
|
|
|
|
undi_data_size: .word 0
|
|
|
|
undi_data_segment: .word 0
|
|
|
|
|
2007-01-09 01:42:28 +00:00
|
|
|
/* The following fields are part of a struct undi_device */
|
|
|
|
|
|
|
|
undi_device:
|
|
|
|
|
|
|
|
pxenv_segoff:
|
|
|
|
pxenv_offset: .word 0
|
|
|
|
pxenv_segment: .word 0
|
|
|
|
|
|
|
|
ppxe_segoff:
|
|
|
|
ppxe_offset: .word 0
|
|
|
|
ppxe_segment: .word 0
|
|
|
|
|
|
|
|
entry_segoff:
|
|
|
|
entry_offset: .word 0
|
|
|
|
entry_segment: .word 0
|
|
|
|
|
2007-01-08 03:48:26 +00:00
|
|
|
undi_fbms_start: .word 0
|
|
|
|
undi_fbms_end: .word 0
|
|
|
|
|
2007-01-09 01:42:28 +00:00
|
|
|
pci_busdevfn: .word 0xffff
|
|
|
|
isapnp_csn: .word 0xffff
|
|
|
|
isapnp_read_port: .word 0xffff
|
2005-03-08 18:53:11 +00:00
|
|
|
|
2007-01-09 01:42:28 +00:00
|
|
|
.equ undi_device_size, ( . - undi_device )
|
2007-01-08 03:48:26 +00:00
|
|
|
|
2006-05-25 22:04:47 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* Run Etherboot main code
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
run_etherboot:
|
|
|
|
/* Install Etherboot */
|
|
|
|
call install
|
|
|
|
|
2007-01-09 02:29:54 +00:00
|
|
|
#ifdef PXELOADER_KEEP_UNDI
|
|
|
|
/* Copy our undi_device structure to the preloaded_undi variable */
|
|
|
|
movw %bx, %es
|
|
|
|
movw $preloaded_undi, %di
|
|
|
|
movw $undi_device, %si
|
|
|
|
movw $undi_device_size, %cx
|
|
|
|
rep movsb
|
|
|
|
#endif
|
|
|
|
|
2006-05-25 22:04:47 +00:00
|
|
|
/* Jump to .text16 segment with %ds pointing to .data16*/
|
|
|
|
movw %bx, %ds
|
|
|
|
pushw %ax
|
|
|
|
pushw $1f
|
|
|
|
lret
|
|
|
|
.section ".text16", "ax", @progbits
|
|
|
|
1:
|
|
|
|
/* Original PXE stack pointer to es:di. We must hold it in
|
|
|
|
* registers, because our current stack may be vapourised by
|
|
|
|
* the time main() returns. (main() will still be able to
|
|
|
|
* return, because prot_call() transfers the return address to
|
|
|
|
* the internal stack and back again).
|
|
|
|
*/
|
|
|
|
popw %di
|
|
|
|
popw %es
|
|
|
|
|
|
|
|
/* Run main program */
|
|
|
|
pushl $main
|
|
|
|
pushw %cs
|
|
|
|
call prot_call
|
|
|
|
popl %eax /* discard */
|
|
|
|
|
|
|
|
/* If original PXE stack is intact, return via PXE, else via INT 18 */
|
|
|
|
cmpw $PXE_STACK_MAGIC, %es:0(%di)
|
|
|
|
jne exit_via_int18
|
|
|
|
exit_via_pxe: /* Stack OK, return to PXE */
|
|
|
|
movw $exit_via_pxe_message, %si
|
|
|
|
call print_exit_message
|
|
|
|
pushw %es /* Restore original PXE stack */
|
|
|
|
popw %ss
|
|
|
|
movw %di, %sp
|
|
|
|
popw %ax /* discard PXE_STACK_MAGIC */
|
|
|
|
popw %ax /* discard %cs */
|
|
|
|
popw %ax /* discard %ss */
|
|
|
|
popw %ds
|
|
|
|
popw %es
|
|
|
|
popw %fs
|
|
|
|
popw %gs
|
|
|
|
popal
|
|
|
|
popfl
|
|
|
|
xorw %ax, %ax /* Return PXENV_STATUS_SUCCESS */
|
|
|
|
lret
|
|
|
|
exit_via_int18: /* Stack damaged, do int 18 */
|
|
|
|
movw $exit_via_int18_message, %si
|
|
|
|
call print_exit_message
|
|
|
|
int $0x18
|
|
|
|
|
|
|
|
print_exit_message:
|
|
|
|
movw $0x0007, %bx /* page 0, attribute 7 (normal) */
|
|
|
|
movb $0x0e, %ah /* write char, tty mode */
|
|
|
|
1: lodsb
|
|
|
|
testb %al, %al
|
|
|
|
je 2f
|
|
|
|
int $0x10
|
|
|
|
jmp 1b
|
|
|
|
2: ret
|
2005-03-08 18:53:11 +00:00
|
|
|
|
2006-05-25 22:04:47 +00:00
|
|
|
.section ".data16", "aw", @progbits
|
|
|
|
exit_via_pxe_message:
|
|
|
|
.asciz "EB->PXE\r\n"
|
|
|
|
exit_via_int18_message:
|
|
|
|
.asciz "EB->BIOS\r\n"
|