aboutsummaryrefslogtreecommitdiffstats
path: root/src/arch/i386/prefix/romprefix.S
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2006-06-06 15:33:39 +0000
committerMichael Brown <mcb30@etherboot.org>2006-06-06 15:33:39 +0000
commitef37f78cbeca351b5b7190a98922405d38687898 (patch)
treefd25f969ac2bb58c55a914a17e0009b5084e7622 /src/arch/i386/prefix/romprefix.S
parente7eca7b7cbd3354916145c36ca88e9e754ef8812 (diff)
downloadipxe-ef37f78cbeca351b5b7190a98922405d38687898.tar.gz
Cut out almost all the optional code paths, drastically simplifying the
flow of control through this code. We now always add PCI and PnP headers even for ISA ROMs; there's no harm in doing so. UNDI loader is still missing.
Diffstat (limited to 'src/arch/i386/prefix/romprefix.S')
-rw-r--r--src/arch/i386/prefix/romprefix.S518
1 files changed, 143 insertions, 375 deletions
diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S
index 4a5bd2e6..ced0f49c 100644
--- a/src/arch/i386/prefix/romprefix.S
+++ b/src/arch/i386/prefix/romprefix.S
@@ -6,412 +6,180 @@
* table so using a noticeable amount of stack space is a no-no.
*/
-/* Define DELAYED_INT when NO_DELAYED_INT is not defined.
- * This allows positive tests instead of tests that contain
- * double negatives, and become confusing.
- */
-#ifndef NO_DELAYED_INT
-#define DELAYED_INT
-#endif
-
-/* We need some unique magic ID, if we defer startup thru the INT18H or INT19H
- * handler. This way, we can check if we have already been installed.
- */
-#ifndef MAGIC
-#define MAGIC 0xE44C
-#endif
-
-/* Hook into INT18H or INT19H handler */
-#ifdef BOOT_INT18H
-#define BOOT_INT 0x18
-#else
-#define BOOT_INT 0x19
-#endif
-
-#define BOOT_INT_VEC BOOT_INT*4
-#define SCRATCHVEC 0x300
-
-/* Prefix exit codes. We store these on the stack so that we will
- * know how to return control to the BIOS when Etherboot exits.
- */
-#define EXIT_VIA_LRET 0x0
-#define EXIT_VIA_INT_18 0x1
-#define EXIT_VIA_BOOT_INT 0x2
-
.text
.code16
.arch i386
- .org 0
.section ".prefix", "ax", @progbits
-_prefix:
- .word 0xAA55 /* BIOS extension signature */
-size: .byte 0 /* number of 512 byte blocks */
- /* = number of 256 word blocks */
- /* filled in by makerom program */
- jmp over /* skip over checksum */
- .byte 0 /* checksum */
- jmp legacyentry /* alternate entry point +6 */
- /* used by mknbi-rom */
-
-#ifdef PCI_PNP_HEADER
-mfgstr:
- .asciz "Etherboot"
-#ifdef PXE_EXPORT
+ .org 0x00
+romheader:
+ .word 0xAA55 /* BIOS extension signature */
+ .byte _rom_size /* Size in 512-byte blocks */
+ jmp init_vector /* Initialisation vector */
.org 0x16
- .word UNDIROMID - _prefix
-#endif /* PXE_EXPORT */
-
+ .word undiheader
.org 0x18
- .word PCI - _prefix
- .word PnP - _prefix
-
-PCI:
- .ascii "PCIR"
- .word 0x0000 /* vendor ID, filled in by makerom */
- .word 0x0000 /* device ID, filled in by makerom */
- .word 0x0000 /* pointer to vital product data */
- .word 0x0018 /* PCI data structure length */
- .byte 0x00 /* PCI data structure revision */
- .byte 0x02 /* Device Base Type code */
- .byte 0x00 /* Device Sub-Type code */
- .byte 0x00 /* Device Interface Type code */
- .word 0x0000 /* Image length same as offset 02h */
- .word 0x0001 /* revision level of code/data */
- .byte 0x00 /* code type */
- .byte 0x80 /* indicator (last PCI data structure) */
- .word 0x0000 /* reserved */
+ .word pciheader
+ .org 0x1a
+ .word pnpheader
+ .size romheader, . - romheader
+
+pciheader:
+ .ascii "PCIR" /* Signature */
+ .word pci_vendor_id /* Vendor ID */
+ .word pci_device_id /* Device ID */
+ .word 0x0000 /* pointer to vital product data */
+ .word pciheader_len /* PCI data structure length */
+ .byte 0x00 /* PCI data structure revision */
+ .byte 0x02 /* Device Base Type code */
+ .byte 0x00 /* Device Sub-Type code */
+ .byte 0x00 /* Device Interface Type code */
+ .word _rom_size /* Image length same as offset 02h */
+ .word 0x0001 /* revision level of code/data */
+ .byte 0x00 /* code type */
+ .byte 0x80 /* Flags (last PCI data structure) */
+ .word 0x0000 /* reserved */
+ .equ pciheader_len, . - pciheader
+ .size pciheader, . - pciheader
+
+pnpheader:
+ .ascii "$PnP" /* Signature */
+ .byte 0x01 /* Structure revision */
+ .byte ( pnpheader_len / 16 ) /* Length (in 16 byte increments) */
+ .word 0x0000 /* Offset of next header */
+ .byte 0x00 /* Reserved */
+ .byte 0x00 /* Checksum */
+ .long 0x00000000 /* Device identifier */
+ .word mfgstr /* Manufacturer string */
+ .word prodstr /* Product name */
+ .byte 0x02 /* Device base type code */
+ .byte 0x00 /* Device sub-type code */
+ .byte 0x00 /* Device interface type code */
+ .byte 0x54 /* Device indicator */
+ .word 0x0000 /* Boot connection vector */
+ .word 0x0000 /* Disconnect vector */
+ .word exec_vector /* Boot execution vector */
+ .word 0x0000 /* Reserved */
+ .word 0x0000 /* Static resource information vector*/
+ .equ pnpheader_len, . - pnpheader
+ .size pnpheader, . - pnpheader
-PnP:
- .ascii "$PnP"
- .byte 0x01 /* structure revision */
- .byte 0x02 /* length (in 16 byte increments) */
- .word 0x0000 /* offset of next header */
- .byte 0x00 /* Reserved */
- .byte 0x00 /* checksum filled by makerom */
- .long 0x00000000 /* Device identifier */
- .word mfgstr - _prefix
- .word 0x0 /* pointer to product name */
- /* filled by makerom */
- .byte 0x02 /* Device Base Type code */
- .byte 0x00 /* Device Sub-Type code */
- .byte 0x00 /* Device Interface Type code */
- .byte 0x14 /* device indicator */
- .word 0x0000 /* boot connection vector */
- .word 0x0000 /* disconnect vector */
- .word pnpentry - _prefix
- .word 0x0000 /* reserved */
- .word 0x0000 /* static resource information vector */
-#ifdef PXE_EXPORT
-UNDIROMID:
- .ascii "UNDI"
- .byte UNDIROMID_end - UNDIROMID /* length of structure */
+mfgstr:
+ .asciz "http://etherboot.org"
+ .size mfgstr, . - mfgstr
+prodstr:
+ .asciz "Etherboot"
+ .size prodstr, . - prodstr
+
+undiheader:
+ .ascii "UNDI" /* Signature */
+ .byte undiheader_len /* Length of structure */
.byte 0 /* Checksum */
.byte 0 /* Structure revision */
- .byte 0,1,2 /* PXE version 2.1.0 */
- .word UNDILoader - _prefix /* Offset to loader routine */
- .word _real_mode_stack_size /* Stack segment size */
- .word _real_mode_stack_size /* Data segment size */
- .word _pxe_stack_size /* Code segment size */
- .ascii "PCIR"
-
- /* The code segment contains our pxe_stack_t plus the PXE and
- * RM callback interfaces. We don't actually use a data
- * segment, but we put a nonzero value here to avoid confusing
- * things. 16k of stack space should be enough.
- *
- * When we claim our own memory, we fill out the data segment
- * with the address and size of the real-mode stack, so that
- * NBPs will free that area of memory for us. When the UNDI
- * loader is used to initialise us, we will never need a
- * real-mode stack because we will only ever be called via the
- * PXE API, hence our stack is already in base memory.
- */
- .equ UNDICodeSize, _pxe_stack_size
- .equ UNDIDataSize, _real_mode_stack_size
- .equ UNDIStackSize, _real_mode_stack_size
-UNDIROMID_end:
-#endif /* PXE_EXPORT */
-
-#endif /* PCI_PNP_HEADER */
-
-/*
- * Explicitly specify DI is wrt ES to avoid problems with some BIOSes
- * Discovered by Eric Biederman
- * In addition, some BIOSes don't point DI to the string $PnP so
- * we need another #define to take care of that.
+ .byte 0,1,2 /* PXE version: 2.1.0 */
+ .word undiloader /* Offset to loader routine */
+ .word _data16_size /* Stack segment size */
+ .word _data16_size /* Data segment size */
+ .word _text16_size /* Code segment size */
+ .equ undiheader_len, . - undiheader
+ .size undiheader, . - undiheader
+
+/* Initialisation vector
+ *
+ * Determine whether or not this is a PnP system via a signature
+ * check. If it is PnP, return to the PnP BIOS indicating that we are
+ * a boot-capable device; the BIOS will call our boot execution vector
+ * if it wants to boot us. If it is not PnP, hook INT 19.
*/
-over:
-#ifdef DEBUG_ROMPREFIX
- call print_bcv
-#endif
-/* Omit this test for ISA cards anyway */
-#ifdef PCI_PNP_HEADER
-/* Accept old name too for backward compatibility */
-#if !defined(BBS_BUT_NOT_PNP_COMPLIANT) && !defined(PNP_BUT_NOT_BBS_COMPLIANT)
- cmpw $'$'+'P'*256,%es:0(%di)
+init_vector:
+ pushw %si
+ cmpw $'$'+'P'*256, %es:0(%di)
jne notpnp
- cmpw $'n'+'P'*256,%es:2(%di)
+ cmpw $'n'+'P'*256, %es:2(%di)
jne notpnp
-#endif /* BBS_BUT_NOT_PNP_COMPLIANT */
- movw $0x20,%ax
- lret
-#endif /* PCI_PNP_HEADER */
+ispnp:
+ movw $ispnp_message, %si
+ jmp 99f
notpnp:
-#ifdef DEBUG_ROMPREFIX
- call print_notpnp
-#endif
-#ifdef DELAYED_INT
- pushw %ax
pushw %ds
- xorw %ax,%ax
- movw %ax,%ds /* access first 64kB segment */
- movw SCRATCHVEC+4, %ax /* check if already installed */
- cmpw $MAGIC, %ax /* check magic word */
- jz installed
- movw BOOT_INT_VEC, %ax /* hook into INT18H or INT19H */
- movw %ax, SCRATCHVEC
- movw BOOT_INT_VEC+2, %ax
- movw %ax, SCRATCHVEC+2
- movw $start_int - _prefix, %ax
- movw %ax, BOOT_INT_VEC
- movw %cs,%ax
- movw %ax, BOOT_INT_VEC+2
- movw $MAGIC, %ax /* set magic word */
- movw %ax, SCRATCHVEC+4
-#ifdef DEBUG_ROMPREFIX
- call print_installed
-#endif
-installed:
+ pushw $0
popw %ds
- popw %ax
- movw $0x20,%ax
+ pushw %cs
+ pushw $exec_vector
+ popl ( 0x19 * 4 )
+ popw %ds
+ movw $notpnp_message, %si
+99:
+ call print_message
+ movw $0x20, %ax
+ popw %si
lret
+ .size init_vector, . - init_vector
-start_int: /* clobber magic id, so that we will */
-#ifdef DEBUG_ROMPREFIX
- call print_start_int
-#endif
- xorw %ax,%ax /* not inadvertendly end up in an */
- movw %ax,%ds /* endless loop */
- movw %ax, SCRATCHVEC+4
- movw SCRATCHVEC+2, %ax /* restore original INT19h handler */
- movw %ax, BOOT_INT_VEC+2
- movw SCRATCHVEC, %ax
- movw %ax, BOOT_INT_VEC
- pushl %eax /* padding */
- pushw $EXIT_VIA_BOOT_INT
- jmp invoke
-#endif /* DELAYED_INT */
-
-
-
-
-legacyentry:
-#ifdef DEBUG_ROMPREFIX
- call print_legacyentry
-#endif
- pushw $EXIT_VIA_LRET
- jmp invoke
+ispnp_message:
+ .asciz "Etherboot detected PnP BIOS\r\n"
+ .size ispnp_message, . - ispnp_message
+notpnp_message:
+ .asciz "Etherboot detected non-PnP BIOS\r\n"
+ .size notpnp_message, . - notpnp_message
+/* Boot execution vector
+ *
+ * Called by the PnP BIOS when it wants to boot us, or via the hooked
+ * INT 19 if we detected a non-PnP BIOS.
+ */
+exec_vector:
+ /* Obtain a reasonably-sized stack */
+ xorw %ax, %ax
+ movw %ax, %ss
+ movw $0x7c00, %sp
-
-#ifdef PCI_PNP_HEADER
-pnpentry:
-#ifdef DEBUG_ROMPREFIX
- call print_bev
-#endif
- pushl %eax /* padding */
- pushw $EXIT_VIA_INT_18
- jmp invoke
-#endif /* PCI_PNP_HEADER */
+ movw $exec_message, %si
+ call print_message
+ call install
-invoke:
- /* Store ROM segment and size on stack */
+ /* Jump to .text16 segment */
pushw %ax
- pushw %ds
+ pushw $1f
+ lret
+ .section ".text16", "awx", @progbits
+1:
+ pushl $main
pushw %cs
- movzbw %cs:(size-_prefix), %ax
- shlw $9, %ax /* 512-byte blocks */
- pushw %ax
- /* Relocate to free base memory, switch stacks */
- pushw $12 /* Preserve exit code & far ret addr */
- call prelocate
- /* We are now running in RAM */
- popw %ax /* padding */
- movw %cs, %ax
- movw %ax, %ds
- popw %ds:(_prefix_rom+2) /* ROM size */
- popw %ds:(_prefix_rom+0) /* ROM segment */
- popw %ds /* Original %ds */
- popw %ax /* Original %ax */
- pushw %ax /* 4-byte alignment */
- pushl $8 /* Preserve exit code & far ret addr */
- pushw $0 /* Set null return address */
- jmp _start
-
+ call prot_call
+ popl %eax /* discard */
- .section ".text16", "ax", @progbits
-prefix_exit:
- popw %ax /* padding */
- popw %ax /* %ax = exit code */
- cmpw $EXIT_VIA_LRET, %ax
- jne 1f
- /* Exit via LRET */
- lret
-1: addw $4, %sp /* Strip padding */
- cmpw $EXIT_VIA_BOOT_INT, %ax
- jne 2f
- /* Exit via int BOOT_INT */
- int $BOOT_INT /* Try original vector */
-2: /* Exit via int $0x18 */
- int $0x18 /* As per BIOS Boot Spec, next dev */
-prefix_exit_end:
+ /* Boot next device */
+ int $0x18
.previous
-
-
-/* UNDI loader needs to be rewritten to use new mechanism */
-#if 0
-
-#ifdef PXE_EXPORT
-
-#define PXENV_UNDI_LOADER 0x104d
+exec_message:
+ .asciz "Etherboot starting boot\r\n"
+ .size exec_message, . - exec_message
- .section ".prefix"
-UNDILoader:
- /* Loader API is different to the usual PXE API; there is no
- * opcode on the stack. We arrange the stack to look like a
- * normal PXE API call; this makes the Etherboot internals
- * cleaner and avoids adding an extra API type just for the
- * PXE loader.
- */
- pushw %bx
- movw %sp, %ax /* Store original %ss:sp */
- pushw %ss
+/* UNDI loader
+ *
+ * Called by an external program to load our PXE stack.
+ */
+undiloader:
+ .size undiloader, . - undiloader
+
+/* Utility function: print string
+ */
+print_message:
pushw %ax
- pushl %eax /* Space for loader structure ptr */
+ pushw %bx
pushw %bp
- movw %sp, %bp
- movw 16(%bp), %ax /* Copy loader structure ptr */
- movw %ax, 2(%bp)
- movw 18(%bp), %ax
- movw %ax, 4(%bp)
- popw %bp
- pushw $PXENV_UNDI_LOADER /* PXE 'opcode' */
- pushl %eax /* dummy return address */
- /* Stack now looks like a normal PXE API call */
- /* Store ROM segment and size on stack */
- pushw %ax
- pushw %cs
- movzbw %cs:(size-_prefix), %ax
- shlw $9, %ax /* 512-byte blocks */
- pushw %ax
- /* Unpack Etherboot into temporarily claimed base memory */
- pushw $20 /* Dummy ret, PXE params, orig ss:sp */
- call prelocate
- popw %ax /* discard */
- popw %cs:(_prefix_rom+2) /* ROM size */
- popw %cs:(_prefix_rom+0) /* ROM segment */
- popw %ax /* Original %ax */
- /* Inhibit automatic deallocation of base memory */
- movl $0, %cs:_prefix_image_basemem
- /* Make PXE API call to Etherboot */
- pushl $0x201 /* PXE API version */
- /* Need to USE_INTERNAL_STACK, since we will call relocate() */
- pushl $(EB_OPCODE_PXE|EB_USE_INTERNAL_STACK) /* PXE API call type */
- call _entry
- addw $18, %sp /* discard */
- popw %bx /* Restore original %ss:sp */
- popw %ss
- movw %bx, %sp
- popw %bx
- call deprelocate
- lret $2 /* Skip our PXE 'opcode' */
-#endif /* PXE_EXPORT */
-
-#endif /* 0 */
-
-#ifdef DEBUG_ROMPREFIX
- .section ".prefix"
-
-print_bcv:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .asciz "ROM detected\r\n"
-
-print_bev:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .asciz "booting\r\n"
-
-print_notpnp:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .asciz ": Non-PnP BIOS detected!\r\n"
-
-print_legacyentry:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .asciz "ROM using legacy boot mechanism\r\n"
-
-print_installed:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .ascii "hooked boot via INT"
-#ifdef BOOT_INT18H
- .asciz "18\r\n"
-#else
- .asciz "19\r\n"
-#endif
-
-print_start_int:
- pushw %si
- movw $1f-_prefix, %si
- call print_message
- popw %si
- ret
-1: .asciz "booting via hooked interrupt\r\n"
-
-print_message:
- pushaw
- pushw %ds
- pushw %cs
- popw %ds
- pushw %si
- movw $1f-_prefix, %si
- call print_string
- popw %si
- call print_string
- popw %ds
- popaw
- ret
-1: .asciz "Etherboot "
-
-print_string:
-1: lodsb
- testb %al,%al
+ movw $0x0007, %bx
+1: cs lodsb
+ testb %al, %al
je 2f
- movw $0x0007, %bx /* page 0, attribute 7 (normal) */
movb $0x0e, %ah /* write char, tty mode */
int $0x10
jmp 1b
-2: ret
-
-#endif
+2: popw %bp
+ popw %bx
+ popw %ax
+ ret
+ .size print_message, . - print_message