1 #define PXENV_STOP_UNDI 0x15
2 #define PXENV_UNLOAD_STACK 0x70
3 #define PXENV_STOP_BASE 0x76
5 #define PXE_STACK_MAGIC 0x57ac /* 'STac' */
11 .section ".prefix", "ax", @progbits
12 /*****************************************************************************
13 * Entry point: set cs, ds, bp, print welcome message
14 *****************************************************************************
16 jmp $0x7c0, $code_start
19 /* Preserve registers for return to PXE stack */
28 pushw $PXE_STACK_MAGIC /* PXE stack magic marker */
29 /* Set up stack just below 0x7c00 */
36 pushw %es /* Save old PXE stack pointer */
38 /* Set up our other segment registers */
41 movw $0x40, %ax /* BIOS data segment access */
43 /* Print welcome message */
47 /*****************************************************************************
48 * Detect type of PXE available (!PXE, PXENV+ or none)
49 *****************************************************************************
52 les %es:54(%di), %di /* !PXE structure */
53 cmpl $0x45585021, %es:(%di) /* '!PXE' signature */
59 cmpl $0x4e455850, %es:(%bx) /* 'PXEN' signature */
61 cmpw $0x2b56, %es:4(%bx) /* 'V+' signature */
67 jmp finished_with_error
70 detected_pxenv: /* es:bx points to PXENV+ structure */
73 pushw %es:0x24(%bx) /* UNDI code segment */
74 pushw %es:0x26(%bx) /* UNDI code size */
75 pushw %es:0x20(%bx) /* UNDI data segment */
76 pushw %es:0x22(%bx) /* UNDI data size */
77 les %es:0x0a(%bx), %di /* Entry point to %es:%di */
82 detected_pxe: /* es:di points to !PXE structure */
85 pushw %es:0x30(%di) /* UNDI code segment */
86 pushw %es:0x36(%di) /* UNDI code size */
87 pushw %es:0x28(%di) /* UNDI data segment */
88 pushw %es:0x2e(%di) /* UNDI data size */
89 les %es:0x10(%di), %di /* Entry point to %es:%di */
95 movw %es, pxe_entry_segment
96 movw %di, pxe_entry_offset
98 popw undi_data_segment
100 popw undi_code_segment
103 popw %es /* Exit with %es:%di containing structure address */
105 /*****************************************************************************
106 * Print information about located structure
107 *****************************************************************************
109 print_structure_information:
110 call print_segoff /* %es:%di contains address of structure */
111 les pxe_entry_segoff, %di
113 les undi_code_segoff, %di
115 les undi_data_segoff, %di
118 /*****************************************************************************
119 * Calculate base memory usage by UNDI
120 *****************************************************************************
122 find_undi_basemem_usage:
123 movw undi_code_segment, %ax
124 movw undi_code_size, %bx
125 movw undi_data_segment, %cx
126 movw undi_data_size, %dx
131 1: /* %ax:%bx now describes the lower region, %cx:%dx the higher */
132 shrw $6, %ax /* Round down to nearest kB */
133 movw %ax, undi_fbms_start
134 addw $0x0f, %dx /* Round up to next segment */
137 addw $((1024 / 16) - 1), %cx /* Round up to next kB */
139 movw %cx, undi_fbms_end
141 /*****************************************************************************
142 * Unload PXE base code
143 *****************************************************************************
146 movw $PXENV_STOP_BASE, %bx
148 movw $PXENV_UNLOAD_STACK, %bx
150 jnz do_not_free_base_code
153 movw undi_fbms_start, %di
155 do_not_free_base_code:
157 /*****************************************************************************
159 *****************************************************************************
162 movw $PXENV_STOP_UNDI, %bx
164 #ifndef PXELOADER_KEEP_UNDI
167 movw undi_fbms_start, %si
168 movw undi_fbms_end, %di
171 #endif /* PXELOADER_KEEP_UNDI */
173 /*****************************************************************************
175 *****************************************************************************
179 movw pxe_overall_status, %ax
190 /*****************************************************************************
191 * Subroutine: print character in %al (with LF -> LF,CR translation)
192 *****************************************************************************
195 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
196 movb $0x0e, %ah /* write char, tty mode */
197 cmpb $0x0a, %al /* '\n'? */
204 /*****************************************************************************
205 * Subroutine: print a zero-terminated message starting at %si
206 *****************************************************************************
216 /*****************************************************************************
217 * Subroutine: print hex word in %ax
218 *****************************************************************************
225 /* Courtesy of Norbert Juffa <norbert.juffa@amd.com> */
235 /*****************************************************************************
236 * Subroutine: print segment:offset address in %es:%di
237 *****************************************************************************
244 movb $0x3a,%al /* ':' */
248 movb $0x20, %al /* ' ' */
252 /*****************************************************************************
253 * Subroutine: free and zero base memory from %si kB to %di kB
254 *****************************************************************************
257 movw %fs:(0x13), %ax /* Current FBMS to %ax */
258 cmpw %ax, %si /* Update FBMS only if "old" value */
259 jne 1f /* is correct */
263 movw %si, %ax /* Zero kB at %si */
270 incw %si /* Move to next kB */
272 jne zero_kb /* Loop until done */
273 movw %fs:(0x13), %ax /* Print free base memory */
275 movb $0x20, %al /* ' ' */
279 /*****************************************************************************
280 * Make a PXE API call. Works with either !PXE or PXENV+ API.
281 * Opcode in %bx. pxe_parameter_structure always used.
283 * Returns status code (not exit code) in %bx and prints it. Returns
284 * with zero flag set if status code is zero (PXENV_STATUS_SUCCESS).
285 *****************************************************************************
288 /* Set up registers for PXENV+ API. %bx already set up */
291 movw $pxe_parameter_structure, %di
292 /* Set up stack for !PXE API */
296 /* Make the API call */
297 lcall *pxe_entry_segoff
298 /* Reset the stack */
300 movw pxe_parameter_structure, %ax
303 movw $0x20, %ax /* ' ' */
306 orw %bx, pxe_overall_status
310 /*****************************************************************************
311 * PXE data structures
312 *****************************************************************************
316 pxe_entry_offset: .word 0
317 pxe_entry_segment: .word 0
320 undi_code_size: .word 0
321 undi_code_segment: .word 0
324 undi_data_size: .word 0
325 undi_data_segment: .word 0
327 undi_fbms_start: .word 0
328 undi_fbms_end: .word 0
330 pxe_parameter_structure:
334 pxe_overall_status: .word 0
336 /*****************************************************************************
337 * Run Etherboot main code
338 *****************************************************************************
341 /* Install Etherboot */
344 /* Jump to .text16 segment with %ds pointing to .data16*/
349 .section ".text16", "ax", @progbits
351 /* Original PXE stack pointer to es:di. We must hold it in
352 * registers, because our current stack may be vapourised by
353 * the time main() returns. (main() will still be able to
354 * return, because prot_call() transfers the return address to
355 * the internal stack and back again).
360 /* Run main program */
364 popl %eax /* discard */
366 /* If original PXE stack is intact, return via PXE, else via INT 18 */
367 cmpw $PXE_STACK_MAGIC, %es:0(%di)
369 exit_via_pxe: /* Stack OK, return to PXE */
370 movw $exit_via_pxe_message, %si
371 call print_exit_message
372 pushw %es /* Restore original PXE stack */
375 popw %ax /* discard PXE_STACK_MAGIC */
376 popw %ax /* discard %cs */
377 popw %ax /* discard %ss */
384 xorw %ax, %ax /* Return PXENV_STATUS_SUCCESS */
386 exit_via_int18: /* Stack damaged, do int 18 */
387 movw $exit_via_int18_message, %si
388 call print_exit_message
392 movw $0x0007, %bx /* page 0, attribute 7 (normal) */
393 movb $0x0e, %ah /* write char, tty mode */
401 .section ".data16", "aw", @progbits
402 exit_via_pxe_message:
404 exit_via_int18_message:
405 .asciz "EB->BIOS\r\n"