summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-11-18 20:43:13 +0100
committerMichael Brown2008-11-18 20:43:13 +0100
commit0a8a17e66944da38de3cf3c1bd1d08aef3a2f5ad (patch)
tree876afe5d4b1c9073c8c0b964bdc094b48300b1f2
parent[r8169] New rtl8169 family driver (diff)
downloadipxe-0a8a17e66944da38de3cf3c1bd1d08aef3a2f5ad.tar.gz
ipxe-0a8a17e66944da38de3cf3c1bd1d08aef3a2f5ad.tar.xz
ipxe-0a8a17e66944da38de3cf3c1bd1d08aef3a2f5ad.zip
[i386] Free allocated base memory on exit, if possible
Code paths that automatically allocate memory from the FBMS at 40:13 should also free it, if possible. Freeing this memory will not be possible if either 1. The FBMS has been modified since our allocation, or 2. We have not been able to unhook one or more BIOS interrupt vectors.
-rw-r--r--src/arch/i386/include/biosint.h15
-rw-r--r--src/arch/i386/interface/pcbios/biosint.c11
-rw-r--r--src/arch/i386/prefix/dskprefix.S6
-rw-r--r--src/arch/i386/prefix/hdprefix.S6
-rw-r--r--src/arch/i386/prefix/libprefix.S91
-rw-r--r--src/arch/i386/prefix/lkrnprefix.S6
-rw-r--r--src/arch/i386/prefix/nbiprefix.S7
-rw-r--r--src/arch/i386/prefix/pxeprefix.S13
-rw-r--r--src/arch/i386/prefix/romprefix.S7
9 files changed, 133 insertions, 29 deletions
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 <realmode.h>
+
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
@@ -8,17 +8,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
*
* @v interrupt INT number
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,13 +558,68 @@ 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)
*
* Install all text and data segments.
@@ -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