]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[i386] Free allocated base memory on exit, if possible
authorMichael Brown <mcb30@etherboot.org>
Tue, 18 Nov 2008 19:43:13 +0000 (19:43 +0000)
committerMichael Brown <mcb30@etherboot.org>
Tue, 18 Nov 2008 19:43:13 +0000 (19:43 +0000)
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.

src/arch/i386/include/biosint.h
src/arch/i386/interface/pcbios/biosint.c
src/arch/i386/prefix/dskprefix.S
src/arch/i386/prefix/hdprefix.S
src/arch/i386/prefix/libprefix.S
src/arch/i386/prefix/lkrnprefix.S
src/arch/i386/prefix/nbiprefix.S
src/arch/i386/prefix/pxeprefix.S
src/arch/i386/prefix/romprefix.S

index d4e34963da4e5e4738fc64ad5cc32f5cdbdcabfe..d365cf01f393b042af7a880094607643c19c041d 100644 (file)
@@ -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,
index 8ef2d7ab23ab2a7276aec9220c20ae35436be8ce..1306f918661a7f4feb239b006170b0bb221b81fd 100644 (file)
@@ -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
  *
index e3a39cce68096ca7ce253f062673bf69f0417d74..0156812a545735834394ad7099381ac5a2e43a9d 100644 (file)
@@ -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
index ffe1ee573b2c4f4d0dec75f5106576a5ed67fdb5..086d7f454e695f56d9c2795b40fdb3ff64155ab4 100644 (file)
@@ -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
index 61549618a890d92af6f3f1f9e352802607db32ea..56ca64d94b2639ce4cfe1053a3c5c42286474679 100644 (file)
@@ -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
index f23e4076aa917bce2f59892a4174c65d15e1abf9..094263d28f0e1a88bab0543221f274a12985f422 100644 (file)
@@ -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
index ec2100947101e7f323d117a67517d2235f0e2427..d1753e30b6c6765e33704a9638fdd1bd48cd71eb 100644 (file)
@@ -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
index 32ff296147c717e636e4aef03ae4ccc309d0ebcf..d1eb962f58570d5e214a5b6a7f58ebfcfb239a96 100644 (file)
@@ -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
index 7b545f4b1a7a85565a8ed0b44469a7e2996e6c9f..a6431cd9a222e0a79282c4d355528df1cc00bd8e 100644 (file)
@@ -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