aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi.c1
-rw-r--r--src/biosvar.h4
-rw-r--r--src/config.h2
-rw-r--r--src/coreboot.c1
-rw-r--r--src/farptr.h17
-rw-r--r--src/memmap.c90
-rw-r--r--src/memmap.h5
-rw-r--r--src/misc.c2
-rw-r--r--src/mptable.c1
-rw-r--r--src/pmm.c333
-rw-r--r--src/post.c8
-rw-r--r--src/smbios.c1
-rw-r--r--src/types.h8
-rw-r--r--src/util.h14
14 files changed, 359 insertions, 128 deletions
diff --git a/src/acpi.c b/src/acpi.c
index ef4eaf9..2198805 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -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
diff --git a/src/biosvar.h b/src/biosvar.h
index 821aa35..0d175ef 100644
--- a/src/biosvar.h
+++ b/src/biosvar.h
@@ -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() {
diff --git a/src/config.h b/src/config.h
index 36f2a72..20e74c7 100644
--- a/src/config.h
+++ b/src/config.h
@@ -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.
diff --git a/src/coreboot.c b/src/coreboot.c
index 4ab2a7a..82c9f8a 100644
--- a/src/coreboot.c
+++ b/src/coreboot.c
@@ -11,7 +11,6 @@
#include "mptable.h" // MPTABLE_SIGNATURE
#include "biosvar.h" // GET_EBDA
#include "lzmadecode.h" // LzmaDecode
-#include "memmap.h" // malloc_fseg
/****************************************************************
diff --git a/src/farptr.h b/src/farptr.h
index a270f87..1f3df9d 100644
--- a/src/farptr.h
+++ b/src/farptr.h
@@ -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)
diff --git a/src/memmap.c b/src/memmap.c
index 9fc3626..005c474 100644
--- a/src/memmap.c
+++ b/src/memmap.c
@@ -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);
-}
diff --git a/src/memmap.h b/src/memmap.h
index 8df9ed0..51471d6 100644
--- a/src/memmap.h
+++ b/src/memmap.h
@@ -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;
diff --git a/src/misc.c b/src/misc.c
index 956e545..167dfe5 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -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;
/****************************************************************
diff --git a/src/mptable.c b/src/mptable.c
index 8f622ff..aeb1f94 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -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
diff --git a/src/pmm.c b/src/pmm.c
index bf53e3b..3e08da1 100644
--- 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.
}
diff --git a/src/post.c b/src/post.c
index e80146f..32d22c8 100644
--- a/src/post.c
+++ b/src/post.c
@@ -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.
diff --git a/src/smbios.c b/src/smbios.c
index fb03671..6fbddd9 100644
--- a/src/smbios.c
+++ b/src/smbios.c
@@ -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
diff --git a/src/types.h b/src/types.h
index 9f93e0b..bbb38bb 100644
--- a/src/types.h
+++ b/src/types.h
@@ -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)
diff --git a/src/util.h b/src/util.h
index d369a49..c2fc6ca 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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);