1 /* At entry, the processor is in 16 bit real mode and the code is being
2 * executed from an address it was not linked to. Code must be pic and
3 * 32 bit sensitive until things are fixed up.
5 * Also be very careful as the stack is at the rear end of the interrupt
6 * table so using a noticeable amount of stack space is a no-no.
9 #define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
10 #define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
11 #define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
12 #define PNP_GET_BBS_VERSION 0x60
17 .section ".prefix", "ax", @progbits
21 .word 0xAA55 /* BIOS extension signature */
22 romheader_size: .byte _load_size_sect /* Size in 512-byte blocks */
23 jmp init /* Initialisation vector */
32 .size romheader, . - romheader
34 .section ".zinfo.fixup", "a" /* Compressor fixup information */
42 .ascii "PCIR" /* Signature */
43 .word pci_vendor_id /* Vendor ID */
44 .word pci_device_id /* Device ID */
45 .word 0x0000 /* pointer to vital product data */
46 .word pciheader_len /* PCI data structure length */
47 .byte 0x00 /* PCI data structure revision */
48 .byte 0x02 /* Device Base Type code */
49 .byte 0x00 /* Device Sub-Type code */
50 .byte 0x00 /* Device Interface Type code */
51 pciheader_size: .word _load_size_sect /* Image length same as offset 02h */
52 .word 0x0001 /* revision level of code/data */
53 .byte 0x00 /* code type */
54 .byte 0x80 /* Flags (last PCI data structure) */
55 .word 0x0000 /* reserved */
56 .equ pciheader_len, . - pciheader
57 .size pciheader, . - pciheader
59 .section ".zinfo.fixup", "a" /* Compressor fixup information */
67 .ascii "$PnP" /* Signature */
68 .byte 0x01 /* Structure revision */
69 .byte ( pnpheader_len / 16 ) /* Length (in 16 byte increments) */
70 .word 0x0000 /* Offset of next header */
71 .byte 0x00 /* Reserved */
72 .byte 0x00 /* Checksum */
73 .long 0x00000000 /* Device identifier */
74 .word mfgstr /* Manufacturer string */
75 .word prodstr /* Product name */
76 .byte 0x02 /* Device base type code */
77 .byte 0x00 /* Device sub-type code */
78 .byte 0x00 /* Device interface type code */
79 .byte 0x54 /* Device indicator */
80 .word 0x0000 /* Boot connection vector */
81 .word 0x0000 /* Disconnect vector */
82 .word bev_entry /* Boot execution vector */
83 .word 0x0000 /* Reserved */
84 .word 0x0000 /* Static resource information vector*/
85 .equ pnpheader_len, . - pnpheader
86 .size pnpheader, . - pnpheader
89 .asciz "http://etherboot.org"
90 .size mfgstr, . - mfgstr
93 .size prodstr, . - prodstr
96 .ascii "UNDI" /* Signature */
97 .byte undiheader_len /* Length of structure */
98 .byte 0 /* Checksum */
99 .byte 0 /* Structure revision */
100 .byte 0,1,2 /* PXE version: 2.1.0 */
101 .word undiloader /* Offset to loader routine */
102 .word _data16_size /* Stack segment size */
103 .word _data16_size /* Data segment size */
104 .word _text16_size /* Code segment size */
105 .equ undiheader_len, . - undiheader
106 .size undiheader, . - undiheader
108 /* Initialisation (called once during POST)
110 * Determine whether or not this is a PnP system via a signature
111 * check. If it is PnP, return to the PnP BIOS indicating that we are
112 * a boot-capable device; the BIOS will call our boot execution vector
113 * if it wants to boot us. If it is not PnP, hook INT 19.
116 /* Preserve registers, clear direction flag, set %ds=%cs */
123 /* Print message as early as possible */
124 movw $init_message, %si
126 /* Check for PnP BIOS */
127 testw $0x0f, %di /* PnP signature must be aligned - bochs */
128 jnz hook_int19 /* uses unalignment to indicate 'fake' PnP. */
129 cmpl $PNP_SIGNATURE, %es:0(%di)
131 /* Is PnP: print PnP message */
132 movw $init_message_pnp, %si
136 pushw %es:0x1b(%di) /* Real-mode data segment */
137 pushw %ds /* &(bbs_version) */
139 pushw $PNP_GET_BBS_VERSION
144 movw $init_message_bbs, %si
147 /* Not BBS-compliant - must hook INT 19 */
149 movw $init_message_int19, %si
155 popl %es:( 0x19 * 4 )
158 movw $( 0xe000 - 1 ), %di
163 cmpl $PMM_SIGNATURE, %es:0
172 /* PMM found: print PMM message */
173 movw $init_message_pmm, %si
175 /* Try to allocate 2MB block via PMM */
176 pushw $0x0006 /* Aligned, extended memory */
177 pushl $0xffffffff /* No handle */
178 pushl $( 0x00200000 / 16 ) /* 2MB in paragraphs */
179 pushw $0x0000 /* pmmAllocate */
182 testw %dx, %dx /* %ax==0 even on success, since align=2MB */
184 movw $init_message_pmm_failed, %si
187 gotpmm: /* PMM allocation succeeded: copy ROM to PMM block */
188 pushal /* PMM presence implies 1kB stack */
189 movw %ax, %es /* %ax=0 already - see above */
193 movl %edi, image_source
195 movzbl romheader_size, %ecx
197 addr32 rep movsb /* PMM presence implies flat real mode */
198 movl %edi, decompress_to
199 /* Shrink ROM and update checksum */
202 movw $_prefix_size_sect, %cx
203 movb %cl, romheader_size
211 /* Print CRLF to terminate messages */
214 /* Restore registers */
218 /* Indicate boot capability to PnP BIOS, if present */
224 .asciz "gPXE (http://etherboot.org) -"
225 .size init_message, . - init_message
228 .size init_message_pnp, . - init_message_pnp
231 .size init_message_bbs, . - init_message_bbs
234 .size init_message_pmm, . - init_message_pmm
235 init_message_pmm_failed:
237 .size init_message_pmm_failed, . - init_message_pmm_failed
240 .size init_message_int19, . - init_message_int19
242 /* ROM image location
244 * May be either within option ROM space, or within PMM-allocated block.
248 .size image_source, . - image_source
250 /* Temporary decompression area
252 * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block.
255 .long HIGHMEM_LOADPOINT
256 .size decompress_to, . - decompress_to
260 * Filled in by BBS BIOS. We ignore the value.
265 /* Boot Execution Vector entry point
267 * Called by the PnP BIOS when it wants to boot us.
273 .size bev_entry, . - bev_entry
277 * Called via the hooked INT 19 if we detected a non-PnP BIOS.
282 /* No real way to return from INT19 */
284 .size int19_entry, . - int19_entry
286 /* Execute as a boot device
289 exec: /* Set %ds = %cs */
293 /* Print message as soon as possible */
294 movw $exec_message, %si
297 /* Store magic word on BIOS stack and remember BIOS %ss:sp */
302 /* Obtain a reasonably-sized temporary stack */
308 movl image_source, %esi
309 movl decompress_to, %edi
311 call install_prealloc
313 /* Set up real-mode stack */
317 /* Jump to .text16 segment */
321 .section ".text16", "awx", @progbits
326 /* No need to clean up stack; we are about to reload %ss:sp */
328 /* Restore BIOS stack */
332 /* Check magic word on BIOS stack */
334 cmpl $STACK_MAGIC, %eax
336 /* BIOS stack OK: return to caller */
338 1: /* BIOS stack corrupt: use INT 18 */
343 .asciz "gPXE starting boot\n"
344 .size exec_message, . - exec_message
348 * Called by an external program to load our PXE stack.
356 /* UNDI loader parameter structure address into %es:%di */
358 movw %ss:12(%bx), %di
359 movw %ss:14(%bx), %es
360 /* Install to specified real-mode addresses */
362 movw %es:12(%di), %bx
363 movw %es:14(%di), %ax
364 movl %cs:image_source, %esi
365 movl %cs:decompress_to, %edi
366 call install_prealloc
368 /* Call UNDI loader C code */
369 pushl $pxe_loader_call
375 1: popw %bx /* discard */
376 popw %bx /* discard */
377 /* Restore registers and return */
383 .size undiloader, . - undiloader