summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/interface/pcbios/int13.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-09 15:13:59 +0100
committerMichael Brown2007-01-09 15:13:59 +0100
commita2ffe8c123337d0ae9102fd9ad3d5a212cbdd426 (patch)
tree78c3f8138807be8c9913ae67f8c86523b31d1742 /src/arch/i386/interface/pcbios/int13.c
parentLeave protected-mode return address on PM stack when issuing a (diff)
downloadipxe-a2ffe8c123337d0ae9102fd9ad3d5a212cbdd426.tar.gz
ipxe-a2ffe8c123337d0ae9102fd9ad3d5a212cbdd426.tar.xz
ipxe-a2ffe8c123337d0ae9102fd9ad3d5a212cbdd426.zip
Allow boot sector to completely destroy real-mode stack, but still
manage to return control.
Diffstat (limited to 'src/arch/i386/interface/pcbios/int13.c')
-rw-r--r--src/arch/i386/interface/pcbios/int13.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c
index 798fb6df..8796f9a7 100644
--- a/src/arch/i386/interface/pcbios/int13.c
+++ b/src/arch/i386/interface/pcbios/int13.c
@@ -599,27 +599,32 @@ int int13_boot ( unsigned int drive ) {
hook_bios_interrupt ( 0x19, ( unsigned int ) int13_exec_fail,
&int19_vector );
- /* Boot the loaded sector */
- __asm__ __volatile__ ( REAL_CODE ( /* Save segment registers */
- "pushw %%ds\n\t"
- "pushw %%es\n\t"
- "pushw %%fs\n\t"
- "pushw %%gs\n\t"
+ /* Boot the loaded sector
+ *
+ * We assume that the boot sector may completely destroy our
+ * real-mode stack, so we preserve everything we need in
+ * static storage.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
+ "popw %%cs:int13_saved_retaddr\n\t"
/* Save stack pointer */
"movw %%ss, %%ax\n\t"
"movw %%ax, %%cs:int13_saved_ss\n\t"
"movw %%sp, %%cs:int13_saved_sp\n\t"
+ /* Jump to boot sector */
"ljmp $0, $0x7c00\n\t"
+ /* Preserved variables */
"\nint13_saved_ss: .word 0\n\t"
"\nint13_saved_sp: .word 0\n\t"
+ "\nint13_saved_retaddr: .word 0\n\t"
+ /* Boot failure return point */
"\nint13_exec_fail:\n\t"
+ /* Restore stack pointer */
"movw %%cs:int13_saved_ss, %%ax\n\t"
"movw %%ax, %%ss\n\t"
"movw %%cs:int13_saved_sp, %%sp\n\t"
- "popw %%gs\n\t"
- "popw %%fs\n\t"
- "popw %%es\n\t"
- "popw %%ds\n\t" )
+ /* Return via saved address */
+ "jmp *%%cs:int13_saved_retaddr\n\t")
: "=d" ( discard_d ) : "d" ( drive )
: "eax", "ebx", "ecx", "esi", "edi", "ebp" );