diff --git a/src/arch/i386/include/biosint.h b/src/arch/i386/include/biosint.h index d4e34963..d365cf01 100644 --- a/src/arch/i386/include/biosint.h +++ b/src/arch/i386/include/biosint.h @@ -6,9 +6,22 @@ * */ +#include + struct segoff; -extern int hooked_bios_interrupts; +/** + * Hooked interrupt count + * + * At exit, after unhooking all possible interrupts, this counter + * should be examined. If it is non-zero, it means that we failed to + * unhook at least one interrupt vector, and so must not free up the + * memory we are using. (Note that this also implies that we should + * re-hook INT 15 in order to hide ourselves from the memory map). + */ +extern uint16_t __text16 ( hooked_bios_interrupts ); +#define hooked_bios_interrupts __use_text16 ( hooked_bios_interrupts ) + extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler, struct segoff *chain_vector ); extern int unhook_bios_interrupt ( unsigned int interrupt, diff --git a/src/arch/i386/interface/pcbios/biosint.c b/src/arch/i386/interface/pcbios/biosint.c index 8ef2d7ab..1306f918 100644 --- a/src/arch/i386/interface/pcbios/biosint.c +++ b/src/arch/i386/interface/pcbios/biosint.c @@ -7,17 +7,6 @@ * */ -/** - * Hooked interrupt count - * - * At exit, after unhooking all possible interrupts, this counter - * should be examined. If it is non-zero, it means that we failed to - * unhook at least one interrupt vector, and so must not free up the - * memory we are using. (Note that this also implies that we should - * re-hook INT 15 in order to hide ourselves from the memory map). - */ -int hooked_bios_interrupts = 0; - /** * Hook INT vector * diff --git a/src/arch/i386/prefix/dskprefix.S b/src/arch/i386/prefix/dskprefix.S index e3a39cce..0156812a 100644 --- a/src/arch/i386/prefix/dskprefix.S +++ b/src/arch/i386/prefix/dskprefix.S @@ -353,6 +353,7 @@ msg1end: .word 0xAA55 start_runtime: + /* Install gPXE */ call install /* Set up real-mode stack */ @@ -368,7 +369,10 @@ start_runtime: pushl $main pushw %cs call prot_call - popl %eax /* discard */ + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall /* Boot next device */ int $0x18 diff --git a/src/arch/i386/prefix/hdprefix.S b/src/arch/i386/prefix/hdprefix.S index ffe1ee57..086d7f45 100644 --- a/src/arch/i386/prefix/hdprefix.S +++ b/src/arch/i386/prefix/hdprefix.S @@ -82,6 +82,7 @@ load_failed: .byte 0x55, 0xaa start_image: + /* Install gPXE */ call install /* Set up real-mode stack */ @@ -97,7 +98,10 @@ start_image: pushl $main pushw %cs call prot_call - popl %eax /* discard */ + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall /* Boot next device */ int $0x18 diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index 61549618..56ca64d9 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -537,17 +537,20 @@ install_block: .code16 .globl alloc_basemem alloc_basemem: + /* Preserve registers */ + pushw %fs + /* FBMS => %ax as segment address */ - movw $0x40, %ax - movw %ax, %fs + pushw $0x40 + popw %fs movw %fs:0x13, %ax shlw $6, %ax - /* .data16 segment address */ + /* Calculate .data16 segment address */ subw $_data16_memsz_pgh, %ax pushw %ax - /* .text16 segment address */ + /* Calculate .text16 segment address */ subw $_text16_memsz_pgh, %ax pushw %ax @@ -555,12 +558,67 @@ alloc_basemem: shrw $6, %ax movw %ax, %fs:0x13 - /* Return */ + /* Retrieve .text16 and .data16 segment addresses */ popw %ax popw %bx + + /* Restore registers and return */ + popw %fs ret .size alloc_basemem, . - alloc_basemem +/**************************************************************************** + * free_basemem (real-mode near call) + * + * Free space allocated with alloc_basemem. + * + * Parameters: + * %ax : .text16 segment address + * %bx : .data16 segment address + * Returns: + * %ax : 0 if successfully freed + * Corrupts: + * none + **************************************************************************** + */ + .section ".text16" + .code16 + .globl free_basemem +free_basemem: + /* Preserve registers */ + pushw %fs + + /* Check FBMS counter */ + pushw %ax + shrw $6, %ax + pushw $0x40 + popw %fs + cmpw %ax, %fs:0x13 + popw %ax + jne 1f + + /* Check hooked interrupt count */ + cmpw $0, %cs:hooked_bios_interrupts + jne 1f + + /* OK to free memory */ + addw $_text16_memsz_pgh, %ax + addw $_data16_memsz_pgh, %ax + shrw $6, %ax + movw %ax, %fs:0x13 + xorw %ax, %ax + +1: /* Restore registers and return */ + popw %fs + ret + .size free_basemem, . - free_basemem + + .section ".text16.data" + .globl hooked_bios_interrupts +hooked_bios_interrupts: + .word 0 + .size hooked_bios_interrupts, . - hooked_bios_interrupts + /**************************************************************************** * install (real-mode near call) * @@ -709,6 +767,29 @@ prot_call_vector: .size prot_call_vector, . - prot_call_vector #endif +/**************************************************************************** + * uninstall (real-mode near call) + * + * Uninstall all text and data segments. + * + * Parameters: + * %ax : .text16 segment address + * %bx : .data16 segment address + * Returns: + * none + * Corrupts: + * none + **************************************************************************** + */ + .section ".text16" + .code16 + .globl uninstall +uninstall: + call free_basemem + ret + .size uninstall, . - uninstall + + /* File split information for the compressor */ #if COMPRESS diff --git a/src/arch/i386/prefix/lkrnprefix.S b/src/arch/i386/prefix/lkrnprefix.S index f23e4076..094263d2 100644 --- a/src/arch/i386/prefix/lkrnprefix.S +++ b/src/arch/i386/prefix/lkrnprefix.S @@ -189,6 +189,7 @@ run_gpxe: movw %ax, %ss movw $0x7c00, %sp + /* Install gPXE */ call install /* Set up real-mode stack */ @@ -204,7 +205,10 @@ run_gpxe: pushl $main pushw %cs call prot_call - popl %eax /* discard */ + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall /* Boot next device */ int $0x18 diff --git a/src/arch/i386/prefix/nbiprefix.S b/src/arch/i386/prefix/nbiprefix.S index ec210094..d1753e30 100644 --- a/src/arch/i386/prefix/nbiprefix.S +++ b/src/arch/i386/prefix/nbiprefix.S @@ -52,7 +52,7 @@ memlen: .long _filesz - 512 ***************************************************************************** */ entry: - /* Install low and high memory regions */ + /* Install gPXE */ call install /* Jump to .text16 segment */ @@ -64,7 +64,10 @@ entry: pushl $main pushw %cs call prot_call - popl %eax /* discard */ + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall /* Reboot system */ int $0x19 diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index 32ff2961..d1eb962f 100644 --- a/src/arch/i386/prefix/pxeprefix.S +++ b/src/arch/i386/prefix/pxeprefix.S @@ -318,7 +318,7 @@ print_free_basemem: ***************************************************************************** */ finished: - jmp run_etherboot + jmp run_gpxe /***************************************************************************** * Subroutine: print segment:offset address @@ -554,11 +554,11 @@ flags: .word UNDI_FL_STARTED .equ undi_device_size, ( . - undi_device ) /***************************************************************************** - * Run Etherboot main code + * Run gPXE main code ***************************************************************************** */ -run_etherboot: - /* Install Etherboot */ +run_gpxe: + /* Install gPXE */ call install /* Set up real-mode stack */ @@ -585,7 +585,10 @@ run_etherboot: pushl $main pushw %cs call prot_call - popl %eax /* discard */ + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall /* Boot next device */ int $0x18 diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 7b545f4b..a6431cd9 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -591,8 +591,11 @@ exec: /* Set %ds = %cs */ pushl $main pushw %cs call prot_call - /* No need to clean up stack; we are about to reload %ss:sp */ - + popl %ecx /* discard */ + + /* Uninstall gPXE */ + call uninstall + /* Restore BIOS stack */ movw %dx, %ss movw %bp, %sp