]> xenbits.xensource.com Git - seabios.git/commitdiff
Add Post Memory Manager (PMM) support.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 1 Aug 2009 15:45:37 +0000 (11:45 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 1 Aug 2009 15:45:37 +0000 (11:45 -0400)
Complete the initial implementation of PMM.
Default new PMM code to be enabled.
Move malloc code from memmap.c to pmm.c.
Define new malloc zones for PMM (ZoneTmpLow and ZoneTmpHigh).
Change default READ/WRITE_SEG macros to use 32bit pointers (the 16bit
    PMM code use "big real" mode and requires 32bit accesses).
Allow pmm allocations to occur during bcv executions also.
Add low-memory clearing before boot.
Also, align the default f-seg memory.

14 files changed:
src/acpi.c
src/biosvar.h
src/config.h
src/coreboot.c
src/farptr.h
src/memmap.c
src/memmap.h
src/misc.c
src/mptable.c
src/pmm.c
src/post.c
src/smbios.c
src/types.h
src/util.h

index ef4eaf938f41cb3d3560189dce7f001e096bf8b5..2198805c69f0a1ee3349b1bf4c9682a5e65cd61d 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "acpi.h" // struct rsdp_descriptor
 #include "util.h" // memcpy
-#include "memmap.h" // malloc_fseg
 #include "pci.h" // pci_find_device
 #include "biosvar.h" // GET_EBDA
 #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
index 821aa3572992304b406fd504c27ff4b3dd4ed4c3..0d175efd9f01989d66d23f55735f93d4d6db230e 100644 (file)
@@ -1,6 +1,6 @@
 // Variable layouts of bios.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 #ifndef __BIOSVAR_H
@@ -240,6 +240,8 @@ struct extended_bios_data_area_s {
     DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024)
 #define EBDA_SEGMENT_START \
     FLATPTR_TO_SEG((640 - EBDA_SIZE_START) * 1024)
+#define EBDA_SEGMENT_MINIMUM \
+    FLATPTR_TO_SEG((640 - 256) * 1024)
 
 // Accessor functions
 static inline u16 get_ebda_seg() {
index 36f2a728dab674fb241580e76ec966e761bfb6f8..20e74c768197fc66b2930f95832ae16b90a3c4da 100644 (file)
@@ -40,7 +40,7 @@
 // Support PnP BIOS entry point.
 #define CONFIG_PNPBIOS 1
 // Support Post Memory Manager (PMM) entry point.
-#define CONFIG_PMM 0
+#define CONFIG_PMM 1
 // Support int 19/18 system bootup support
 #define CONFIG_BOOT 1
 // Support an interactive boot menu at end of post.
index 4ab2a7a8f6f331080eb69efcb64415ea4cdb8511..82c9f8a5499ebf6e9cda11424582e97ff63d926c 100644 (file)
@@ -11,7 +11,6 @@
 #include "mptable.h" // MPTABLE_SIGNATURE
 #include "biosvar.h" // GET_EBDA
 #include "lzmadecode.h" // LzmaDecode
-#include "memmap.h" // malloc_fseg
 
 
 /****************************************************************
index a270f87a229456389052622bb95e7c9fdcbb61c0..1f3df9d2bd00bb15a95d707eaa6932eced9112e2 100644 (file)
@@ -1,6 +1,6 @@
 // Code to access multiple segments within gcc.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 #ifndef __FARPTR_H
@@ -15,13 +15,13 @@ extern u16 __segment_FS, __segment_GS;
 
 // Low level macros for reading/writing memory via a segment selector.
 #define READ8_SEG(SEG, value, var)                      \
-    __asm__("movb %%" #SEG ":%1, %b0" : "=Qi"(value)    \
+    __asm__("addr32 movb %%" #SEG ":%1, %b0" : "=Qi"(value)    \
             : "m"(var), "m"(__segment_ ## SEG))
 #define READ16_SEG(SEG, value, var)                     \
-    __asm__("movw %%" #SEG ":%1, %w0" : "=ri"(value)    \
+    __asm__("addr32 movw %%" #SEG ":%1, %w0" : "=ri"(value)    \
             : "m"(var), "m"(__segment_ ## SEG))
 #define READ32_SEG(SEG, value, var)                     \
-    __asm__("movl %%" #SEG ":%1, %0" : "=ri"(value)     \
+    __asm__("addr32 movl %%" #SEG ":%1, %0" : "=ri"(value)     \
             : "m"(var), "m"(__segment_ ## SEG))
 #define READ64_SEG(SEG, value, var) do {                        \
         union u64_u32_u __value;                                \
@@ -31,18 +31,19 @@ extern u16 __segment_FS, __segment_GS;
         *(u64*)&(value) = __value.val;                          \
     } while (0)
 #define WRITE8_SEG(SEG, var, value)                             \
-    __asm__("movb %b1, %%" #SEG ":%0" : "=m"(var)               \
+    __asm__("addr32 movb %b1, %%" #SEG ":%0" : "=m"(var)               \
             : "Q"(value), "m"(__segment_ ## SEG))
 #define WRITE16_SEG(SEG, var, value)                            \
-    __asm__("movw %w1, %%" #SEG ":%0" : "=m"(var)               \
+    __asm__("addr32 movw %w1, %%" #SEG ":%0" : "=m"(var)               \
             : "r"(value), "m"(__segment_ ## SEG))
 #define WRITE32_SEG(SEG, var, value)                            \
-    __asm__("movl %1, %%" #SEG ":%0" : "=m"(var)                \
+    __asm__("addr32 movl %1, %%" #SEG ":%0" : "=m"(var)                \
             : "r"(value), "m"(__segment_ ## SEG))
 #define WRITE64_SEG(SEG, var, value) do {                       \
         union u64_u32_u __value;                                \
         union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \
-        __value.val = (value);                                  \
+        typeof(var) __value_tmp = (value);                      \
+        __value.val = *(u64*)&__value_tmp;                      \
         WRITE32_SEG(SEG, __w64_ptr->hi, __value.hi);            \
         WRITE32_SEG(SEG, __w64_ptr->lo, __value.lo);            \
     } while (0)
index 9fc3626fcdb7108364a10670b753c333b9538b71..005c474cc7b660a10f57f0dacacbe43698b974db 100644 (file)
@@ -132,93 +132,3 @@ memmap_finalize()
 {
     dump_map();
 }
-
-
-/****************************************************************
- * malloc
- ****************************************************************/
-
-#define MINALIGN 16
-
-struct zone_s {
-    u32 top, bottom, cur;
-};
-
-static struct zone_s ZoneHigh, ZoneFSeg;
-
-static void *
-__malloc(struct zone_s *zone, u32 size)
-{
-    u32 newpos = (zone->cur - size) / MINALIGN * MINALIGN;
-    if ((s32)(newpos - zone->bottom) < 0)
-        // No space
-        return NULL;
-    zone->cur = newpos;
-    return (void*)newpos;
-}
-
-// Allocate memory at the top of 32bit ram.
-void *
-malloc_high(u32 size)
-{
-    return __malloc(&ZoneHigh, size);
-}
-
-// Allocate memory in the 0xf0000-0x100000 area of ram.
-void *
-malloc_fseg(u32 size)
-{
-    return __malloc(&ZoneFSeg, size);
-}
-
-void
-malloc_setup()
-{
-    dprintf(3, "malloc setup\n");
-
-    // Memory in 0xf0000 area.
-    memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
-    ZoneFSeg.bottom = (u32)BiosTableSpace;
-    ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE;
-
-    // Find memory at the top of ram.
-    u32 top = 0;
-    int i;
-    for (i=e820_count-1; i>=0; i--) {
-        struct e820entry *e = &e820_list[i];
-        u64 end = e->start + e->size;
-        if (e->type != E820_RAM || end > 0xffffffff
-            || e->size < CONFIG_MAX_HIGHTABLE)
-            continue;
-        top = end;
-        break;
-    }
-    if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) {
-        // No memory above 1Meg
-        memset(&ZoneHigh, 0, sizeof(ZoneHigh));
-        return;
-    }
-    ZoneHigh.bottom = top - CONFIG_MAX_HIGHTABLE;
-    ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE;
-    add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
-}
-
-void
-malloc_finalize()
-{
-    dprintf(3, "malloc finalize\n");
-
-    // Give back unused high ram.
-    u32 giveback = (ZoneHigh.cur - ZoneHigh.bottom) / 4096 * 4096;
-    add_e820(ZoneHigh.bottom, giveback, E820_RAM);
-
-    // Report statistics
-    u32 used = ZoneFSeg.top - ZoneFSeg.cur;
-    u32 avail = ZoneFSeg.top - ZoneFSeg.bottom;
-    dprintf(1, "malloc_fseg used=%d (%d%%)\n"
-            , used, (100 * used) / avail);
-    used = ZoneHigh.top - ZoneHigh.cur;
-    avail = ZoneHigh.top - ZoneHigh.bottom;
-    dprintf(1, "malloc_high used=%d (%d%%) (returned %d)\n"
-            , used, (100 * used) / avail, giveback);
-}
index 8df9ed09f7bf875d713a14b8a728442e067fe17c..51471d6927a648f0c94b6ed63d839c7b4cb25fb8 100644 (file)
@@ -20,11 +20,6 @@ void add_e820(u64 start, u64 size, u32 type);
 void memmap_setup();
 void memmap_finalize();
 
-void *malloc_high(u32 size);
-void *malloc_fseg(u32 size);
-void malloc_setup();
-void malloc_finalize();
-
 // e820 map storage (defined in system.c)
 extern struct e820entry e820_list[];
 extern int e820_count;
index 956e545dbb2ee236b1c98382809006fbd5c9d2f1..167dfe5e4c97e170618da270f73ca40fd026ac13 100644 (file)
@@ -15,7 +15,7 @@ u32 RamSize VAR16_32;
 // Amount of continuous ram >4Gig
 u64 RamSizeOver4G;
 // Space for bios tables built an run-time.
-char BiosTableSpace[CONFIG_MAX_BIOSTABLE] VAR16_32;
+char BiosTableSpace[CONFIG_MAX_BIOSTABLE] __aligned(MALLOC_MIN_ALIGN) VAR16_32;
 
 
 /****************************************************************
index 8f622fffbb2d43fd8d35f1000d143f7da9bab683..aeb1f94e031692b1db8d53dc6790617a22e1e1d3 100644 (file)
@@ -6,7 +6,6 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "util.h" // dprintf
-#include "memmap.h" // malloc_fseg
 #include "config.h" // CONFIG_*
 #include "mptable.h" // MPTABLE_SIGNATURE
 
index bf53e3b52f969903ba6ea124f704665367231068..3e08da1f73f907362cc78e76e0aebb6abe8f38d7 100644 (file)
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -6,6 +6,270 @@
 
 #include "util.h" // checksum
 #include "config.h" // BUILD_BIOS_ADDR
+#include "memmap.h" // e820_list
+#include "farptr.h" // GET_FARVAR
+#include "biosvar.h" // EBDA_SEGMENT_MINIMUM
+
+
+/****************************************************************
+ * malloc
+ ****************************************************************/
+
+#if MODE16
+// The 16bit pmm entry points runs in "big real" mode, and can
+// therefore read/write to the 32bit malloc variables.
+#define GET_PMMVAR(var) GET_FARVAR(0, (var))
+#define SET_PMMVAR(var, val) SET_FARVAR(0, (var), (val))
+#else
+#define GET_PMMVAR(var) (var)
+#define SET_PMMVAR(var, val) do { (var) = (val); } while (0)
+#endif
+
+// Zone definitions
+struct zone_s {
+    u32 top, bottom, cur;
+};
+
+struct zone_s ZoneHigh VAR32VISIBLE, ZoneFSeg VAR32VISIBLE;
+struct zone_s ZoneTmpLow VAR32VISIBLE, ZoneTmpHigh VAR32VISIBLE;
+
+struct zone_s *Zones[] VAR32VISIBLE = {
+    &ZoneTmpLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh
+};
+
+// Obtain memory from a given zone.
+static void *
+zone_malloc(struct zone_s *zone, u32 size, u32 align)
+{
+    u32 newpos = (GET_PMMVAR(zone->cur) - size) / align * align;
+    if ((s32)(newpos - GET_PMMVAR(zone->bottom)) < 0)
+        // No space
+        return NULL;
+    SET_PMMVAR(zone->cur, newpos);
+    return (void*)newpos;
+}
+
+// Return memory to a zone (if it was the last to be allocated).
+static void
+zone_free(struct zone_s *zone, void *data, u32 olddata)
+{
+    if (! data || GET_PMMVAR(zone->cur) != (u32)data)
+        return;
+    SET_PMMVAR(zone->cur, olddata);
+}
+
+// Find the zone that contains the given data block.
+static struct zone_s *
+zone_find(void *data)
+{
+    int i;
+    for (i=0; i<ARRAY_SIZE(Zones); i++) {
+        struct zone_s *zone = GET_PMMVAR(Zones[i]);
+        if ((u32)data >= GET_PMMVAR(zone->cur)
+            && (u32)data < GET_PMMVAR(zone->top))
+            return zone;
+    }
+    return NULL;
+}
+
+// Report the status of all the zones.
+static void
+dumpZones()
+{
+    int i;
+    for (i=0; i<ARRAY_SIZE(Zones); i++) {
+        struct zone_s *zone = Zones[i];
+        u32 used = zone->top - zone->cur;
+        u32 avail = zone->top - zone->bottom;
+        dprintf(2, "zone %d: %08x-%08x used=%d (%d%%)\n"
+                , i, zone->bottom, zone->top, used, (100 * used) / avail);
+    }
+}
+
+// Allocate memory at the top of 32bit ram.
+void *
+malloc_high(u32 size)
+{
+    return zone_malloc(&ZoneHigh, size, MALLOC_MIN_ALIGN);
+}
+
+// Allocate memory in the 0xf0000-0x100000 area of ram.
+void *
+malloc_fseg(u32 size)
+{
+    return zone_malloc(&ZoneFSeg, size, MALLOC_MIN_ALIGN);
+}
+
+void
+malloc_setup()
+{
+    ASSERT32();
+    dprintf(3, "malloc setup\n");
+
+    // Memory in 0xf0000 area.
+    memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
+    ZoneFSeg.bottom = (u32)BiosTableSpace;
+    ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE;
+
+    // Memory under 1Meg.
+    ZoneTmpLow.bottom = BUILD_STACK_ADDR;
+    ZoneTmpLow.top = ZoneTmpLow.cur = (u32)MAKE_FLATPTR(EBDA_SEGMENT_MINIMUM, 0);
+
+    // Find memory at the top of ram.
+    u32 top = 0, bottom = 0;
+    int i;
+    for (i=e820_count-1; i>=0; i--) {
+        struct e820entry *e = &e820_list[i];
+        u64 end = e->start + e->size;
+        if (e->type != E820_RAM || end > 0xffffffff
+            || e->size < CONFIG_MAX_HIGHTABLE)
+            continue;
+        top = end;
+        bottom = e->start;
+        break;
+    }
+    if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) {
+        // No memory above 1Meg
+        memset(&ZoneHigh, 0, sizeof(ZoneHigh));
+        return;
+    }
+
+    // Memory at top of ram.
+    ZoneHigh.bottom = top - CONFIG_MAX_HIGHTABLE;
+    ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE;
+    add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
+
+    // Memory above 1Meg
+    ZoneTmpHigh.bottom = bottom;
+    ZoneTmpHigh.top = ZoneTmpHigh.cur = ZoneHigh.bottom;
+}
+
+void
+malloc_finalize()
+{
+    dprintf(3, "malloc finalize\n");
+
+    dumpZones();
+
+    // Give back unused high ram.
+    u32 giveback = (ZoneHigh.cur - ZoneHigh.bottom) / 4096 * 4096;
+    add_e820(ZoneHigh.bottom, giveback, E820_RAM);
+    dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback);
+
+    // Clear low-memory allocations.
+    memset((void*)ZoneTmpLow.bottom, 0, ZoneTmpLow.top - ZoneTmpLow.bottom);
+}
+
+
+/****************************************************************
+ * pmm allocation
+ ****************************************************************/
+
+// Information on PMM tracked allocations
+struct pmmalloc_s {
+    void *data;
+    u32 olddata;
+    u32 handle;
+    struct pmmalloc_s *next;
+};
+
+struct pmmalloc_s *PMMAllocs VAR32VISIBLE;
+
+#define PMMALLOCSIZE ALIGN(sizeof(struct pmmalloc_s), MALLOC_MIN_ALIGN)
+
+// Allocate memory from the given zone and track it as a PMM allocation
+static void *
+pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align)
+{
+    struct pmmalloc_s *info = zone_malloc(&ZoneTmpHigh, sizeof(*info)
+                                          , MALLOC_MIN_ALIGN);
+    if (!info)
+        return NULL;
+    u32 olddata = GET_PMMVAR(zone->cur);
+    void *data = zone_malloc(zone, size, align);
+    if (! data) {
+        zone_free(&ZoneTmpHigh, info, (u32)info + PMMALLOCSIZE);
+        return NULL;
+    }
+    dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x"
+            " ret=%p (info=%p)\n"
+            , zone, handle, size, align
+            , data, info);
+    SET_PMMVAR(info->data, data);
+    SET_PMMVAR(info->olddata, olddata);
+    SET_PMMVAR(info->handle, handle);
+    SET_PMMVAR(info->next, GET_PMMVAR(PMMAllocs));
+    SET_PMMVAR(PMMAllocs, info);
+    return data;
+}
+
+// Free a raw data block (either from a zone or from pmm alloc list).
+static void
+pmm_free_data(struct zone_s *zone, void *data, u32 olddata)
+{
+    if (GET_PMMVAR(zone->cur) == (u32)data) {
+        zone_free(zone, data, olddata);
+        return;
+    }
+    struct pmmalloc_s *info;
+    for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next))
+        if (GET_PMMVAR(info->olddata) == (u32)data) {
+            SET_PMMVAR(info->olddata, olddata);
+            return;
+        }
+}
+
+// Free a data block allocated with pmm_malloc
+static int
+pmm_free(void *data)
+{
+    struct zone_s *zone = zone_find(GET_PMMVAR(data));
+    if (!zone)
+        return -1;
+    struct pmmalloc_s **pinfo = &PMMAllocs;
+    for (;;) {
+        struct pmmalloc_s *info = GET_PMMVAR(*pinfo);
+        if (!info)
+            return -1;
+        if (GET_PMMVAR(info->data) == data) {
+            SET_PMMVAR(*pinfo, GET_PMMVAR(info->next));
+            u32 olddata = GET_PMMVAR(info->olddata);
+            pmm_free_data(zone, data, olddata);
+            pmm_free_data(&ZoneTmpHigh, info, (u32)info + PMMALLOCSIZE);
+            dprintf(8, "pmm_free data=%p zone=%p olddata=%p info=%p\n"
+                    , data, zone, (void*)olddata, info);
+            return 0;
+        }
+        pinfo = &info->next;
+    }
+    return -1;
+}
+
+// Find the amount of free space in a given zone.
+static u32
+pmm_getspace(struct zone_s *zone)
+{
+    u32 space = GET_PMMVAR(zone->cur) - GET_PMMVAR(zone->bottom);
+    if (space <= PMMALLOCSIZE)
+        return 0;
+    return space - PMMALLOCSIZE;
+}
+
+// Find the data block allocated with pmm_malloc with a given handle.
+static void *
+pmm_find(u32 handle)
+{
+    struct pmmalloc_s *info;
+    for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next))
+        if (GET_PMMVAR(info->handle) == handle)
+            return GET_PMMVAR(info->data);
+    return NULL;
+}
+
+
+/****************************************************************
+ * pmm interface
+ ****************************************************************/
 
 struct pmmheader {
     u32 signature;
@@ -29,7 +293,7 @@ struct pmmheader PMMHEADER __aligned(16) VAR16EXPORT = {
 };
 #endif
 
-#define FUNCTION_NOT_SUPPORTED 0xffffffff
+#define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff
 
 // PMM - allocate
 static u32
@@ -37,10 +301,51 @@ handle_pmm00(u16 *args)
 {
     u32 length = *(u32*)&args[1], handle = *(u32*)&args[3];
     u16 flags = args[5];
-    dprintf(1, "pmm00: length=%x handle=%x flags=%x\n"
+    dprintf(3, "pmm00: length=%x handle=%x flags=%x\n"
             , length, handle, flags);
-    // XXX
-    return 0;
+    if (!length) {
+        // Memory size request
+        switch (flags & 3) {
+        default:
+        case 0:
+            return 0;
+        case 1:
+            return pmm_getspace(&ZoneTmpLow);
+        case 2:
+            return pmm_getspace(&ZoneTmpHigh);
+        case 3: {
+            u32 spacelow = pmm_getspace(&ZoneTmpLow);
+            u32 spacehigh = pmm_getspace(&ZoneTmpHigh);
+            if (spacelow > spacehigh)
+                return spacelow;
+            return spacehigh;
+        }
+        }
+    }
+    u32 size = length * 16;
+    if ((s32)size <= 0)
+        return 0;
+    u32 align = MALLOC_MIN_ALIGN;
+    if (flags & 4) {
+        align = 1<<__ffs(size);
+        if (align < MALLOC_MIN_ALIGN)
+            align = MALLOC_MIN_ALIGN;
+    }
+    switch (flags & 3) {
+    default:
+    case 0:
+        return 0;
+    case 1:
+        return (u32)pmm_malloc(&ZoneTmpLow, handle, size, align);
+    case 2:
+        return (u32)pmm_malloc(&ZoneTmpHigh, handle, size, align);
+    case 3: {
+        void *data = pmm_malloc(&ZoneTmpLow, handle, size, align);
+        if (data)
+            return (u32)data;
+        return (u32)pmm_malloc(&ZoneTmpHigh, handle, size, align);
+    }
+    }
 }
 
 // PMM - find
@@ -48,9 +353,10 @@ static u32
 handle_pmm01(u16 *args)
 {
     u32 handle = *(u32*)&args[1];
-    dprintf(1, "pmm01: handle=%x\n", handle);
-    // XXX
-    return 0;
+    dprintf(3, "pmm01: handle=%x\n", handle);
+    if (handle == 0xFFFFFFFF)
+        return 0;
+    return (u32)pmm_find(handle);
 }
 
 // PMM - deallocate
@@ -58,22 +364,25 @@ static u32
 handle_pmm02(u16 *args)
 {
     u32 buffer = *(u32*)&args[1];
-    dprintf(1, "pmm02: buffer=%x\n", buffer);
-    // XXX
+    dprintf(3, "pmm02: buffer=%x\n", buffer);
+    int ret = pmm_free((void*)buffer);
+    if (ret)
+        // Error
+        return 1;
     return 0;
 }
 
 static u32
 handle_pmmXX(u16 *args)
 {
-    return FUNCTION_NOT_SUPPORTED;
+    return PMM_FUNCTION_NOT_SUPPORTED;
 }
 
 u32 VISIBLE16
 handle_pmm(u16 *args)
 {
     if (! CONFIG_PMM)
-        return FUNCTION_NOT_SUPPORTED;
+        return PMM_FUNCTION_NOT_SUPPORTED;
 
     u16 arg1 = args[0];
     dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1);
@@ -112,6 +421,4 @@ pmm_finalize()
 
     PMMHEADER.signature = 0;
     PMMHEADER.entry_offset = 0;
-
-    // XXX - zero low-memory allocations.
 }
index e80146f68efd16b471999d7ba889aa36b41dd283..32d22c88e89df459beea28a1b1504aa1a987a0c9 100644 (file)
@@ -190,6 +190,9 @@ post()
 
     optionrom_setup();
 
+    // Run BCVs
+    boot_prep();
+
     pmm_finalize();
     malloc_finalize();
     memmap_finalize();
@@ -210,13 +213,10 @@ _start()
     // Perform main setup code.
     post();
 
-    // Run BCVs
-    boot_prep();
-
     // Setup bios checksum.
     BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE);
 
-    // Prep for boot process.
+    // Write protect bios memory.
     make_bios_readonly();
 
     // Invoke int 19 to start boot process.
index fb036711c04c59f4156af3a6225e8a9db763abca..6fbddd98da99f6bf5a8bfef0cad3693fc1b6d0eb 100644 (file)
@@ -6,7 +6,6 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "util.h" // dprintf
-#include "memmap.h" // malloc_fseg
 #include "biosvar.h" // GET_EBDA
 
 
index 9f93e0b22186b512af4dda954e4d65bdfb63bf4a..bbb38bbb2e0d12e3ee3139355ca487950bbae485 100644 (file)
@@ -1,6 +1,6 @@
 // Basic type definitions for X86 cpus.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 #ifndef __TYPES_H
@@ -48,6 +48,8 @@ union u64_u32_u {
 # define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE
 // Designate a variable at a specific 16bit address
 # define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr))
+// Designate a 32bit variable also available in 16bit "big real" mode.
+# define VAR32VISIBLE __section(".discard.var32." UNIQSEC) __VISIBLE __weak
 // Designate top-level assembler as 16bit only.
 # define ASM16(code) __ASM(code)
 // Designate top-level assembler as 32bit only.
@@ -59,6 +61,7 @@ union u64_u32_u {
 # define VAR16_32 VAR16 __VISIBLE __weak
 # define VAR16EXPORT VAR16_32
 # define VAR16FIXED(addr) VAR16_32
+# define VAR32VISIBLE __VISIBLE
 # define ASM16(code)
 # define ASM32(code) __ASM(code)
 #endif
@@ -69,6 +72,9 @@ union u64_u32_u {
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
 
 #define NULL ((void *)0)
 
index d369a49c506b3e834784934b94752deab78091fb..c2fc6caef74078a2cce82b5df899d481101e02a2 100644 (file)
@@ -80,6 +80,14 @@ static inline u64 rdtscll(void)
     return val;
 }
 
+static inline u32 __ffs(u32 word)
+{
+    asm("bsf %1,%0"
+        : "=r" (word)
+        : "rm" (word));
+    return word;
+}
+
 #define call16_simpint(nr, peax, pflags) do {                           \
         ASSERT16();                                                     \
         asm volatile(                                                   \
@@ -232,8 +240,14 @@ u16 get_pnp_offset();
 void pnp_setup();
 
 // pmm.c
+void *malloc_high(u32 size);
+void *malloc_fseg(u32 size);
+void malloc_setup();
+void malloc_finalize();
 void pmm_setup();
 void pmm_finalize();
+// Minimum alignment of malloc'd memory
+#define MALLOC_MIN_ALIGN 16
 
 // mtrr.c
 void mtrr_setup(void);