[coreboot] [PATCH] YABEL: add PMM functionality

Pattrick Hueper phueper at hueper.net
Mon Dec 22 17:58:57 CET 2008


Uupps... updated patch... i forgot to add the interrupt handler to
actually call the PMM stuff.

Cheers, Patty

Signed-off-by: Pattrick Hueper <phueper at hueper.net>
---
 util/x86emu/Makefile          |    1 +
 util/x86emu/yabel/biosemu.c   |   15 ++
 util/x86emu/yabel/interrupt.c |    8 +
 util/x86emu/yabel/pmm.c       |  384 +++++++++++++++++++++++++++++++++++++++++
 util/x86emu/yabel/pmm.h       |   39 ++++
 5 files changed, 447 insertions(+), 0 deletions(-)
 create mode 100644 util/x86emu/yabel/pmm.c
 create mode 100644 util/x86emu/yabel/pmm.h

diff --git a/util/x86emu/Makefile b/util/x86emu/Makefile
index b50b3b4..02f9f98 100644
--- a/util/x86emu/Makefile
+++ b/util/x86emu/Makefile
@@ -29,6 +29,7 @@ ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
 BIOSEMU_SRC  = biosemu.c debug.c device.c mem.c io.c interrupt.c
 #TODO: add vbe.c, currently not needed...
 #BIOSEMU_SRC +=vbe.c
+BIOSEMU_SRC +=pmm.c
 #PH: TODO: remove the compat files??
 BIOSEMU_SRC  += compat/functions.c
 X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel
diff --git a/util/x86emu/yabel/biosemu.c b/util/x86emu/yabel/biosemu.c
index cc11c0f..ebeb9af 100644
--- a/util/x86emu/yabel/biosemu.c
+++ b/util/x86emu/yabel/biosemu.c
@@ -26,6 +26,7 @@
 #include "mem.h"
 #include "interrupt.h"
 #include "device.h"
+#include "pmm.h"

 #include <rtas.h>

@@ -209,6 +210,20 @@ biosemu(u8 *biosmem, u32 biosmem_size, struct
device * dev, unsigned long rom_ad
 	X86EMU_setupPioFuncs(&my_pio_funcs);
 	X86EMU_setupMemFuncs(&my_mem_funcs);

+	//setup PMM struct in BIOS_DATA_SEGMENT, offset 0x0
+	u8 pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);	
+	if (pmm_length <= 0) {
+		printf ("\nYABEL: Warning: PMM Area could not be setup. PMM not
available (%x)\n",
+		     pmm_length);
+		return 0;
+	} else {
+		CHECK_DBG(DEBUG_PMM) {
+			/* test the PMM */
+			pmm_test();
+			/* and clean it again by calling pmm_setup... */
+			pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);
+		}
+	}
 	// setup the CPU
 	M.x86.R_AH = bios_device.bus;
 	M.x86.R_AL = bios_device.devfn;
diff --git a/util/x86emu/yabel/interrupt.c b/util/x86emu/yabel/interrupt.c
index 442125a..4573150 100644
--- a/util/x86emu/yabel/interrupt.c
+++ b/util/x86emu/yabel/interrupt.c
@@ -16,6 +16,7 @@
 #include "mem.h"
 #include "device.h"
 #include "debug.h"
+#include "pmm.h"

 #include <x86emu/x86emu.h>
 #include <x86emu/prim_ops.h>
@@ -540,6 +541,13 @@ handleInterrupt(int intNum)
 		handleInt1a();
 		int_handled = 1;
 		break;
+	case PMM_INT_NUM:
+		/* the selfdefined PMM INT number, this is called by the code in
PMM struct, it
+		 * is handled by pmm_handleInt()
+		 */
+		pmm_handleInt();
+		int_handled = 1;
+		break;
 	default:
 		printf("Interrupt %#x (Vector: %x) not implemented\n", intNum,
 		       my_rdl(intNum * 4));
diff --git a/util/x86emu/yabel/pmm.c b/util/x86emu/yabel/pmm.c
new file mode 100644
index 0000000..771482e
--- /dev/null
+++ b/util/x86emu/yabel/pmm.c
@@ -0,0 +1,384 @@
+/****************************************************************************
+ * YABEL BIOS Emulator
+ *
+ * Copyright 2008 Pattrick Hueper <phueper at hueper.net>
+ ****************************************************************************/
+
+#include <x86emu/x86emu.h>
+#include <x86emu/prim_ops.h>
+#include <string.h>
+
+#include "biosemu.h"
+#include "pmm.h"
+#include "debug.h"
+#include "device.h"
+
+
+/* this struct is used to remember which PMM spaces
+ * have been assigned. MAX_PMM_AREAS defines how many
+ * PMM areas we can assign.
+ * All areas are assigned in PMM_CONV_SEGMENT
+ */
+typedef struct {
+	u32 handle;	/* handle that is returned to PMM caller */
+	u32 offset;	/* in PMM_CONV_SEGMENT */
+	u32 length;	/* length of this area */
+} pmm_allocation_t;
+
+#define MAX_PMM_AREAS 10
+
+/* array to store the above structs */
+static pmm_allocation_t pmm_allocation_array[MAX_PMM_AREAS];
+
+/* index into pmm_allocation_array */
+static u32 curr_pmm_allocation_index = 0;
+
+/* This function is used to setup the PMM struct in virtual memory
+ * at a certain offset, the length of the PMM struct is returned */
+u8
+pmm_setup(u16 segment, u16 offset)
+{
+	/* setup the PMM structure */
+	pmm_information_t *pis = (pmm_information_t *) (M.mem_base + (((u32)
segment) << 4) + offset);
+	memset(pis, 0, sizeof(pmm_information_t));
+	/* set signature to $PMM */
+	pis->signature[0] = '$';
+	pis->signature[1] = 'P';
+	pis->signature[2] = 'M';
+	pis->signature[3] = 'M';
+	/* revision as specified */
+	pis->struct_rev = 0x01;
+	/* internal length, excluding code */
+	pis->length = ((void *) &(pis->code) - (void *) &(pis->signature));
+	/* the code to be executed, pointed to by entry_point_offset */
+	pis->code[0] = 0xCD;		/* INT */
+	pis->code[1] = PMM_INT_NUM;	/* my selfdefined PMM INT number */
+	pis->code[2] = 0xCB;		/* RETF */
+	/* set the entry_point_offset, it should point to pis->code, segment
is the segment of
+	 * this struct. Since pis->length is the length of the struct
excluding code, offset+pis->length
+	 * points to the code... it's that simple ;-)
+	 */
+	out32le(&(pis->entry_point_offset), (u32) segment << 16 | (u32)
(offset + pis->length));
+	/* checksum calculation */
+	u8 i;
+	u8 checksum = 0;
+	for (i = 0; i < pis->length; i++) {
+		checksum += *(((u8 *) pis) + i);
+	}
+	pis->checksum = ((u8) 0) - checksum;
+	CHECK_DBG(DEBUG_PMM) {
+		DEBUG_PRINTF_PMM("PMM Structure:\n");
+		dump((void *) pis, sizeof(pmm_information_t));
+	}
+	return sizeof(pmm_information_t);
+}
+
+/* handle the selfdefined interrupt, this is executed, when the PMM
Entry Point
+ * is executed, it must handle all PMM requests
+ */
+void
+pmm_handleInt()
+{
+	u32 rval = 0;
+	u16 function, flags;
+	u32 handle, length;
+	u32 i, j;
+	u32 buffer;
+	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	 * according to the PMM Spec "the flags and all registers, except DX and AX
+	 * are preserved across calls to PMM"
+	 * so we save M.x86 and in :exit label we restore it, however, this
means that no
+	 * returns must be used in this function, any exit must use goto exit!
+	 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	 */
+	X86EMU_regs backup_regs = M.x86;
+	pop_long();		/* pop the return address, this is already saved in INT
handler, we don't need
+				   to remember this. */
+	function = pop_word();
+	switch (function) {
+	case 0:
+		/* function pmmAllocate */
+		length = pop_long();
+		length *= 16; /* length is passed in "paragraphs" of 16 bytes each */
+		handle = pop_long();
+		flags = pop_word();
+		DEBUG_PRINTF_PMM("%s: pmmAllocate: Length: %x, Handle: %x, Flags:
%x\n", __FUNCTION__, length, handle, flags);
+		if ((flags & 0x1) != 0) {
+			/* request to allocate in  conventional memory */
+			if (curr_pmm_allocation_index >= MAX_PMM_AREAS) {
+				printf("%s: pmmAllocate: Maximum Number of allocatable areas
reached (%d), cannot allocate more memory!\n",
+				     __FUNCTION__, MAX_PMM_AREAS);
+				rval = 0;
+				goto exit;
+			}
+			/* some ROMs seem to be confused by offset 0, so lets start at 0x100 */
+			u32 next_offset = 0x100;
+			pmm_allocation_t *pmm_alloc =
&(pmm_allocation_array[curr_pmm_allocation_index]);
+			if (curr_pmm_allocation_index != 0) {
+				/* we have already allocated... get the new next_offset
+				 * from the previous pmm_allocation_t */
+				next_offset = pmm_allocation_array[curr_pmm_allocation_index - 1].offset
+				       	+ pmm_allocation_array[curr_pmm_allocation_index - 1].length;
+			}
+			DEBUG_PRINTF_PMM("%s: next_offset: 0x%x\n", __FUNCTION__, next_offset);
+			if (length == 0) {
+				/* largest possible block size requested, we have on segment
+				 * to allocate, so largest possible is segment size (0xFFFF)
+				 * minus next_offset
+				 */
+				rval = 0xFFFF - next_offset;
+				goto exit;
+			}
+			u32 align = 0;
+			if (((flags & 0x4) != 0) && (length > 0)) {
+				/* align to least significant bit set in length param */
+				u8 lsb = 0;
+				while (((length >> lsb) & 0x1) == 0) {
+					lsb++;
+				}
+				align = 1 << lsb;
+			}
+			/* always align at least to paragraph (16byte) boundary
+			 * hm... since the length is always in paragraphs, we cannot
+			 * align outside of paragraphs anyway... so this check might
+			 * be unnecessary...*/
+			if (align < 0x10) {
+				align = 0x10;
+			}
+			DEBUG_PRINTF_PMM("%s: align: 0x%x\n", __FUNCTION__, align);
+			if ((next_offset & (align - 1)) != 0) {
+				/* not yet aligned... align! */
+				next_offset += align;
+				next_offset &= ~(align - 1);
+			}
+			if ((next_offset + length) > 0xFFFF) {
+				rval = 0;
+				printf("%s: pmmAllocate: Not enough memory available for
allocation!\n", __FUNCTION__);
+				goto exit;
+			}
+			curr_pmm_allocation_index++;
+			/* remember the values in pmm_allocation_array */
+			pmm_alloc->handle = handle;
+			pmm_alloc->offset = next_offset;
+			pmm_alloc->length = length;
+			/* return the 32bit "physical" address, i.e. combination of
segment and offset */
+			rval = ((u32) (PMM_CONV_SEGMENT << 16)) | next_offset;
+			DEBUG_PRINTF_PMM("%s: pmmAllocate: allocated memory at %x\n",
__FUNCTION__, rval);
+		} else {
+			rval = 0;
+			printf("%s: pmmAllocate: allocation in extended memory not
supported!\n", __FUNCTION__);
+		}
+		goto exit;
+	case 1:
+		/* function pmmFind */
+		handle = pop_long(); /* the handle to lookup */
+		DEBUG_PRINTF_PMM("%s: pmmFind: Handle: %x\n", __FUNCTION__, handle);
+		i = 0;
+		for (i = 0; i < curr_pmm_allocation_index; i++) {
+			if (pmm_allocation_array[i].handle == handle) {
+				DEBUG_PRINTF_PMM("%s: pmmFind: found allocated memory at %x\n",
__FUNCTION__, rval);
+				/* return the 32bit "physical" address, i.e. combination of
segment and offset */
+				rval = ((u32) (PMM_CONV_SEGMENT << 16)) | pmm_allocation_array[i].offset;
+			}
+		}
+		if (rval == 0) {
+			DEBUG_PRINTF_PMM("%s: pmmFind: handle (%x) not found!\n",
__FUNCTION__, handle);
+		}
+		goto exit;
+	case 2:
+		/* function pmmDeallocate */
+		buffer = pop_long();
+		/* since argument is the address of the PMM block (including the segment,
+		 * we need to remove the segment to get the offset
+		 */
+		buffer = buffer ^ ((u32) PMM_CONV_SEGMENT << 16);
+		DEBUG_PRINTF_PMM("%s: pmmDeallocate: PMM segment offset: %x\n",
__FUNCTION__, buffer);
+		i = 0;
+		/* rval = 0 means we deallocated the buffer, so set it to 1 in case
we dont find it and
+		 * thus cannot deallocate
+		 */
+		rval = 1;
+		for (i = 0; i < curr_pmm_allocation_index; i++) {
+			DEBUG_PRINTF_PMM("%d: %x\n", i, pmm_allocation_array[i].handle);
+			if (pmm_allocation_array[i].offset == buffer) {
+				/* we found the requested buffer, rval = 0 */
+				rval = 0;
+				DEBUG_PRINTF_PMM("%s: pmmDeallocate: found allocated memory at
index: %d\n", __FUNCTION__, i);
+				/* copy the remaining elements in pmm_allocation_array one position up */
+				j = i;
+				for (; j < curr_pmm_allocation_index; j++) {
+					pmm_allocation_array[j] = pmm_allocation_array[j + 1];
+				}
+				/* move curr_pmm_allocation_index one up, too */
+				curr_pmm_allocation_index--;
+				/* finally clean last element */
+				pmm_allocation_array[curr_pmm_allocation_index].handle = 0;
+				pmm_allocation_array[curr_pmm_allocation_index].offset = 0;
+				pmm_allocation_array[curr_pmm_allocation_index].length = 0;
+				break;
+			}
+		}
+		if (rval != 0) {
+			DEBUG_PRINTF_PMM("%s: pmmDeallocate: offset (%x) not found, cannot
deallocate!\n", __FUNCTION__, buffer);
+		}
+		goto exit;
+	default:
+		/* invalid/unimplemented function */
+		printf("%s: invalid PMM function (0x%04x) called!\n", __FUNCTION__,
function);
+		/* PMM spec says if function is invalid, return 0xFFFFFFFF */
+		rval = 0xFFFFFFFF;
+		goto exit;
+	}
+      exit:
+	/* exit handler of this function, restore registers, put return
value in DX:AX */
+	M.x86 = backup_regs;
+	M.x86.R_DX = (u16) ((rval >> 16) & 0xFFFF);
+	M.x86.R_AX = (u16) (rval & 0xFFFF);
+	CHECK_DBG(DEBUG_PMM) {
+		DEBUG_PRINTF_PMM("%s: dump of pmm_allocation_array:\n", __FUNCTION__);
+		for (i = 0; i < MAX_PMM_AREAS; i++) {
+			DEBUG_PRINTF_PMM("%d:\n\thandle: %x\n\toffset: %x\n\tlength: %x\n",
+					i, pmm_allocation_array[i].handle,
pmm_allocation_array[i].offset, pmm_allocation_array[i].length);
+		}
+	}
+	return;
+}
+
+/* This function tests the pmm_handleInt() function above. */
+void
+pmm_test(void) {
+	u32 handle, length, addr;
+	u16 function, flags;
+	/*-------------------- Test simple allocation/find/deallocation
----------------------------- */
+	function = 0; /* pmmAllocate */
+	handle = 0xdeadbeef;
+	length = 16; /* in 16byte paragraphs, so we allocate 256 bytes... */
+	flags = 0x1; /* conventional memory, unaligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
__FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	function = 1; /* pmmFind */
+	push_long(handle);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	DEBUG_PRINTF_PMM("%s: found memory at: %04x:%04x (expected:
%08x)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX, addr);
+	function = 2; /* pmmDeallocate */
+	push_long(addr);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	/*-------------------- Test aligned allocation/deallocation
----------------------------- */
+	function = 0; /* pmmAllocate */
+	handle = 0xdeadbeef;
+	length = 257; /* in 16byte paragraphs, so we allocate 4KB + 16 bytes... */
+	flags = 0x1; /* conventional memory, unaligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
__FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	function = 0; /* pmmAllocate */
+	handle = 0xf00d4b0b;
+	length = 128; /* in 16byte paragraphs, so we allocate 2KB... */
+	flags = 0x5; /* conventional memory, aligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	/* the address should be aligned to 0x800, so probably it is at
offset 0x1800... */
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
__FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	function = 1; /* pmmFind */
+	push_long(handle);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	function = 2; /* pmmDeallocate */
+	push_long(addr);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	handle = 0xdeadbeef;
+	function = 1; /* pmmFind */
+	push_long(handle);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	function = 2; /* pmmDeallocate */
+	push_long(addr);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	/*-------------------- Test out of memory allocation
----------------------------- */
+	function = 0; /* pmmAllocate */
+	handle = 0xdeadbeef;
+	length = 0; /* length zero means, give me the largest possible block */
+	flags = 0x1; /* conventional memory, unaligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	length = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	length /= 16; /* length in paragraphs */
+	DEBUG_PRINTF_PMM("%s: largest possible length: %08x\n", __FUNCTION__, length);
+	function = 0; /* pmmAllocate */
+	flags = 0x1; /* conventional memory, aligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
__FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	function = 0; /* pmmAllocate */
+	length = 1;
+	handle = 0xf00d4b0b;
+	flags = 0x1; /* conventional memory, aligned */
+	/* setup stack for call to pmm_handleInt() */
+	push_word(flags);
+	push_long(handle);
+	push_long(length);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	/* this should fail, so 0x0 should be returned */
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x expected:
0000:0000\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+	handle = 0xdeadbeef;
+	function = 1; /* pmmFind */
+	push_long(handle);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
+	function = 2; /* pmmDeallocate */
+	push_long(addr);
+	push_word(function);
+	push_long(0); /* This is the return address for the ABI, unused in
this implementation */
+	pmm_handleInt();
+	DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
+}
diff --git a/util/x86emu/yabel/pmm.h b/util/x86emu/yabel/pmm.h
new file mode 100644
index 0000000..b3d34ad
--- /dev/null
+++ b/util/x86emu/yabel/pmm.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * YABEL BIOS Emulator
+ *
+ * Copyright 2008 Pattrick Hueper <phueper at hueper.net>
+ ****************************************************************************/
+
+#ifndef _YABEL_PMM_H_
+#define _YABEL_PMM_H_
+
+#include <types.h>
+
+/* PMM Structure see PMM Spec Version 1.01 Chapter 3.1.1 (search web
for specspmm101.pdf) */
+typedef struct {
+	u8 signature[4];
+	u8 struct_rev;
+	u8 length;
+	u8 checksum;
+	u32 entry_point_offset;
+	u8 reserved[5];
+	/* code is not part of the speced PMM struct, however, since i cannot put the
+	 * handling in of PMM in the virtual memory (i dont want to hack it together
+	 * in x86 assembly ;-)) this code array is pointed to by entry_point_offset,
+	 * in code there is only a INT call and a RETF, thus every PMM call will issue
+	 * a PMM INT (only defined in YABEL, see interrupt.c) and the INT Handler
+	 * will do the actual PMM work.
+	 */
+	u8 code[3];
+} __attribute__ ((__packed__)) pmm_information_t;
+
+/* This function is used to setup the PMM struct in virtual memory
+ * at a certain offset */
+u8 pmm_setup(u16 segment, u16 offset);
+
+/* This is the INT Handler mentioned above, it will be called by my
special PMM INT */
+void pmm_handleInt(void);
+
+void pmm_test(void);
+
+#endif // _YABEL_PMM_H
-- 
1.6.0.4



On Mon, Dec 22, 2008 at 5:16 PM, Pattrick Hueper <phueper at hueper.net> wrote:
> Hi,
>
> i am trying to reimplement the functionality, that IBM did not
> opensource of YABEL.
>
> This patch adds PMM (POST Memory Manager) functionality
>
> Since i dont have a board for coreboot available at the moment, i
> cannot test this code, it is written to follow the PMM Spec 1.01
> I have included a pmm_test function that tests the code, so it should
> be functional, but i cannot give any guarantees... i just would like
> to add the code, as long as i still remember the pitfalls i found
> already.
>
> Cheers, Patty
>
>
>
> Signed-off-by: Pattrick Hueper <phueper at hueper.net>
> ---
>  util/x86emu/Makefile        |    1 +
>  util/x86emu/yabel/biosemu.c |   15 ++
>  util/x86emu/yabel/pmm.c     |  384 +++++++++++++++++++++++++++++++++++++++++++
>  util/x86emu/yabel/pmm.h     |   39 +++++
>  4 files changed, 439 insertions(+), 0 deletions(-)
>  create mode 100644 util/x86emu/yabel/pmm.c
>  create mode 100644 util/x86emu/yabel/pmm.h
>
> diff --git a/util/x86emu/Makefile b/util/x86emu/Makefile
> index b50b3b4..02f9f98 100644
> --- a/util/x86emu/Makefile
> +++ b/util/x86emu/Makefile
> @@ -29,6 +29,7 @@ ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
>  BIOSEMU_SRC  = biosemu.c debug.c device.c mem.c io.c interrupt.c
>  #TODO: add vbe.c, currently not needed...
>  #BIOSEMU_SRC +=vbe.c
> +BIOSEMU_SRC +=pmm.c
>  #PH: TODO: remove the compat files??
>  BIOSEMU_SRC  += compat/functions.c
>  X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel
> diff --git a/util/x86emu/yabel/biosemu.c b/util/x86emu/yabel/biosemu.c
> index cc11c0f..ebeb9af 100644
> --- a/util/x86emu/yabel/biosemu.c
> +++ b/util/x86emu/yabel/biosemu.c
> @@ -26,6 +26,7 @@
>  #include "mem.h"
>  #include "interrupt.h"
>  #include "device.h"
> +#include "pmm.h"
>
>  #include <rtas.h>
>
> @@ -209,6 +210,20 @@ biosemu(u8 *biosmem, u32 biosmem_size, struct
> device * dev, unsigned long rom_ad
>        X86EMU_setupPioFuncs(&my_pio_funcs);
>        X86EMU_setupMemFuncs(&my_mem_funcs);
>
> +       //setup PMM struct in BIOS_DATA_SEGMENT, offset 0x0
> +       u8 pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);
> +       if (pmm_length <= 0) {
> +               printf ("\nYABEL: Warning: PMM Area could not be setup. PMM not
> available (%x)\n",
> +                    pmm_length);
> +               return 0;
> +       } else {
> +               CHECK_DBG(DEBUG_PMM) {
> +                       /* test the PMM */
> +                       pmm_test();
> +                       /* and clean it again by calling pmm_setup... */
> +                       pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);
> +               }
> +       }
>        // setup the CPU
>        M.x86.R_AH = bios_device.bus;
>        M.x86.R_AL = bios_device.devfn;
> diff --git a/util/x86emu/yabel/pmm.c b/util/x86emu/yabel/pmm.c
> new file mode 100644
> index 0000000..771482e
> --- /dev/null
> +++ b/util/x86emu/yabel/pmm.c
> @@ -0,0 +1,384 @@
> +/****************************************************************************
> + * YABEL BIOS Emulator
> + *
> + * Copyright 2008 Pattrick Hueper <phueper at hueper.net>
> + ****************************************************************************/
> +
> +#include <x86emu/x86emu.h>
> +#include <x86emu/prim_ops.h>
> +#include <string.h>
> +
> +#include "biosemu.h"
> +#include "pmm.h"
> +#include "debug.h"
> +#include "device.h"
> +
> +
> +/* this struct is used to remember which PMM spaces
> + * have been assigned. MAX_PMM_AREAS defines how many
> + * PMM areas we can assign.
> + * All areas are assigned in PMM_CONV_SEGMENT
> + */
> +typedef struct {
> +       u32 handle;     /* handle that is returned to PMM caller */
> +       u32 offset;     /* in PMM_CONV_SEGMENT */
> +       u32 length;     /* length of this area */
> +} pmm_allocation_t;
> +
> +#define MAX_PMM_AREAS 10
> +
> +/* array to store the above structs */
> +static pmm_allocation_t pmm_allocation_array[MAX_PMM_AREAS];
> +
> +/* index into pmm_allocation_array */
> +static u32 curr_pmm_allocation_index = 0;
> +
> +/* This function is used to setup the PMM struct in virtual memory
> + * at a certain offset, the length of the PMM struct is returned */
> +u8
> +pmm_setup(u16 segment, u16 offset)
> +{
> +       /* setup the PMM structure */
> +       pmm_information_t *pis = (pmm_information_t *) (M.mem_base + (((u32)
> segment) << 4) + offset);
> +       memset(pis, 0, sizeof(pmm_information_t));
> +       /* set signature to $PMM */
> +       pis->signature[0] = '$';
> +       pis->signature[1] = 'P';
> +       pis->signature[2] = 'M';
> +       pis->signature[3] = 'M';
> +       /* revision as specified */
> +       pis->struct_rev = 0x01;
> +       /* internal length, excluding code */
> +       pis->length = ((void *) &(pis->code) - (void *) &(pis->signature));
> +       /* the code to be executed, pointed to by entry_point_offset */
> +       pis->code[0] = 0xCD;            /* INT */
> +       pis->code[1] = PMM_INT_NUM;     /* my selfdefined PMM INT number */
> +       pis->code[2] = 0xCB;            /* RETF */
> +       /* set the entry_point_offset, it should point to pis->code, segment
> is the segment of
> +        * this struct. Since pis->length is the length of the struct
> excluding code, offset+pis->length
> +        * points to the code... it's that simple ;-)
> +        */
> +       out32le(&(pis->entry_point_offset), (u32) segment << 16 | (u32)
> (offset + pis->length));
> +       /* checksum calculation */
> +       u8 i;
> +       u8 checksum = 0;
> +       for (i = 0; i < pis->length; i++) {
> +               checksum += *(((u8 *) pis) + i);
> +       }
> +       pis->checksum = ((u8) 0) - checksum;
> +       CHECK_DBG(DEBUG_PMM) {
> +               DEBUG_PRINTF_PMM("PMM Structure:\n");
> +               dump((void *) pis, sizeof(pmm_information_t));
> +       }
> +       return sizeof(pmm_information_t);
> +}
> +
> +/* handle the selfdefined interrupt, this is executed, when the PMM
> Entry Point
> + * is executed, it must handle all PMM requests
> + */
> +void
> +pmm_handleInt()
> +{
> +       u32 rval = 0;
> +       u16 function, flags;
> +       u32 handle, length;
> +       u32 i, j;
> +       u32 buffer;
> +       /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> +        * according to the PMM Spec "the flags and all registers, except DX and AX
> +        * are preserved across calls to PMM"
> +        * so we save M.x86 and in :exit label we restore it, however, this
> means that no
> +        * returns must be used in this function, any exit must use goto exit!
> +        * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> +        */
> +       X86EMU_regs backup_regs = M.x86;
> +       pop_long();             /* pop the return address, this is already saved in INT
> handler, we don't need
> +                                  to remember this. */
> +       function = pop_word();
> +       switch (function) {
> +       case 0:
> +               /* function pmmAllocate */
> +               length = pop_long();
> +               length *= 16; /* length is passed in "paragraphs" of 16 bytes each */
> +               handle = pop_long();
> +               flags = pop_word();
> +               DEBUG_PRINTF_PMM("%s: pmmAllocate: Length: %x, Handle: %x, Flags:
> %x\n", __FUNCTION__, length, handle, flags);
> +               if ((flags & 0x1) != 0) {
> +                       /* request to allocate in  conventional memory */
> +                       if (curr_pmm_allocation_index >= MAX_PMM_AREAS) {
> +                               printf("%s: pmmAllocate: Maximum Number of allocatable areas
> reached (%d), cannot allocate more memory!\n",
> +                                    __FUNCTION__, MAX_PMM_AREAS);
> +                               rval = 0;
> +                               goto exit;
> +                       }
> +                       /* some ROMs seem to be confused by offset 0, so lets start at 0x100 */
> +                       u32 next_offset = 0x100;
> +                       pmm_allocation_t *pmm_alloc =
> &(pmm_allocation_array[curr_pmm_allocation_index]);
> +                       if (curr_pmm_allocation_index != 0) {
> +                               /* we have already allocated... get the new next_offset
> +                                * from the previous pmm_allocation_t */
> +                               next_offset = pmm_allocation_array[curr_pmm_allocation_index - 1].offset
> +                                       + pmm_allocation_array[curr_pmm_allocation_index - 1].length;
> +                       }
> +                       DEBUG_PRINTF_PMM("%s: next_offset: 0x%x\n", __FUNCTION__, next_offset);
> +                       if (length == 0) {
> +                               /* largest possible block size requested, we have on segment
> +                                * to allocate, so largest possible is segment size (0xFFFF)
> +                                * minus next_offset
> +                                */
> +                               rval = 0xFFFF - next_offset;
> +                               goto exit;
> +                       }
> +                       u32 align = 0;
> +                       if (((flags & 0x4) != 0) && (length > 0)) {
> +                               /* align to least significant bit set in length param */
> +                               u8 lsb = 0;
> +                               while (((length >> lsb) & 0x1) == 0) {
> +                                       lsb++;
> +                               }
> +                               align = 1 << lsb;
> +                       }
> +                       /* always align at least to paragraph (16byte) boundary
> +                        * hm... since the length is always in paragraphs, we cannot
> +                        * align outside of paragraphs anyway... so this check might
> +                        * be unnecessary...*/
> +                       if (align < 0x10) {
> +                               align = 0x10;
> +                       }
> +                       DEBUG_PRINTF_PMM("%s: align: 0x%x\n", __FUNCTION__, align);
> +                       if ((next_offset & (align - 1)) != 0) {
> +                               /* not yet aligned... align! */
> +                               next_offset += align;
> +                               next_offset &= ~(align - 1);
> +                       }
> +                       if ((next_offset + length) > 0xFFFF) {
> +                               rval = 0;
> +                               printf("%s: pmmAllocate: Not enough memory available for
> allocation!\n", __FUNCTION__);
> +                               goto exit;
> +                       }
> +                       curr_pmm_allocation_index++;
> +                       /* remember the values in pmm_allocation_array */
> +                       pmm_alloc->handle = handle;
> +                       pmm_alloc->offset = next_offset;
> +                       pmm_alloc->length = length;
> +                       /* return the 32bit "physical" address, i.e. combination of
> segment and offset */
> +                       rval = ((u32) (PMM_CONV_SEGMENT << 16)) | next_offset;
> +                       DEBUG_PRINTF_PMM("%s: pmmAllocate: allocated memory at %x\n",
> __FUNCTION__, rval);
> +               } else {
> +                       rval = 0;
> +                       printf("%s: pmmAllocate: allocation in extended memory not
> supported!\n", __FUNCTION__);
> +               }
> +               goto exit;
> +       case 1:
> +               /* function pmmFind */
> +               handle = pop_long(); /* the handle to lookup */
> +               DEBUG_PRINTF_PMM("%s: pmmFind: Handle: %x\n", __FUNCTION__, handle);
> +               i = 0;
> +               for (i = 0; i < curr_pmm_allocation_index; i++) {
> +                       if (pmm_allocation_array[i].handle == handle) {
> +                               DEBUG_PRINTF_PMM("%s: pmmFind: found allocated memory at %x\n",
> __FUNCTION__, rval);
> +                               /* return the 32bit "physical" address, i.e. combination of
> segment and offset */
> +                               rval = ((u32) (PMM_CONV_SEGMENT << 16)) | pmm_allocation_array[i].offset;
> +                       }
> +               }
> +               if (rval == 0) {
> +                       DEBUG_PRINTF_PMM("%s: pmmFind: handle (%x) not found!\n",
> __FUNCTION__, handle);
> +               }
> +               goto exit;
> +       case 2:
> +               /* function pmmDeallocate */
> +               buffer = pop_long();
> +               /* since argument is the address of the PMM block (including the segment,
> +                * we need to remove the segment to get the offset
> +                */
> +               buffer = buffer ^ ((u32) PMM_CONV_SEGMENT << 16);
> +               DEBUG_PRINTF_PMM("%s: pmmDeallocate: PMM segment offset: %x\n",
> __FUNCTION__, buffer);
> +               i = 0;
> +               /* rval = 0 means we deallocated the buffer, so set it to 1 in case
> we dont find it and
> +                * thus cannot deallocate
> +                */
> +               rval = 1;
> +               for (i = 0; i < curr_pmm_allocation_index; i++) {
> +                       DEBUG_PRINTF_PMM("%d: %x\n", i, pmm_allocation_array[i].handle);
> +                       if (pmm_allocation_array[i].offset == buffer) {
> +                               /* we found the requested buffer, rval = 0 */
> +                               rval = 0;
> +                               DEBUG_PRINTF_PMM("%s: pmmDeallocate: found allocated memory at
> index: %d\n", __FUNCTION__, i);
> +                               /* copy the remaining elements in pmm_allocation_array one position up */
> +                               j = i;
> +                               for (; j < curr_pmm_allocation_index; j++) {
> +                                       pmm_allocation_array[j] = pmm_allocation_array[j + 1];
> +                               }
> +                               /* move curr_pmm_allocation_index one up, too */
> +                               curr_pmm_allocation_index--;
> +                               /* finally clean last element */
> +                               pmm_allocation_array[curr_pmm_allocation_index].handle = 0;
> +                               pmm_allocation_array[curr_pmm_allocation_index].offset = 0;
> +                               pmm_allocation_array[curr_pmm_allocation_index].length = 0;
> +                               break;
> +                       }
> +               }
> +               if (rval != 0) {
> +                       DEBUG_PRINTF_PMM("%s: pmmDeallocate: offset (%x) not found, cannot
> deallocate!\n", __FUNCTION__, buffer);
> +               }
> +               goto exit;
> +       default:
> +               /* invalid/unimplemented function */
> +               printf("%s: invalid PMM function (0x%04x) called!\n", __FUNCTION__,
> function);
> +               /* PMM spec says if function is invalid, return 0xFFFFFFFF */
> +               rval = 0xFFFFFFFF;
> +               goto exit;
> +       }
> +      exit:
> +       /* exit handler of this function, restore registers, put return
> value in DX:AX */
> +       M.x86 = backup_regs;
> +       M.x86.R_DX = (u16) ((rval >> 16) & 0xFFFF);
> +       M.x86.R_AX = (u16) (rval & 0xFFFF);
> +       CHECK_DBG(DEBUG_PMM) {
> +               DEBUG_PRINTF_PMM("%s: dump of pmm_allocation_array:\n", __FUNCTION__);
> +               for (i = 0; i < MAX_PMM_AREAS; i++) {
> +                       DEBUG_PRINTF_PMM("%d:\n\thandle: %x\n\toffset: %x\n\tlength: %x\n",
> +                                       i, pmm_allocation_array[i].handle,
> pmm_allocation_array[i].offset, pmm_allocation_array[i].length);
> +               }
> +       }
> +       return;
> +}
> +
> +/* This function tests the pmm_handleInt() function above. */
> +void
> +pmm_test(void) {
> +       u32 handle, length, addr;
> +       u16 function, flags;
> +       /*-------------------- Test simple allocation/find/deallocation
> ----------------------------- */
> +       function = 0; /* pmmAllocate */
> +       handle = 0xdeadbeef;
> +       length = 16; /* in 16byte paragraphs, so we allocate 256 bytes... */
> +       flags = 0x1; /* conventional memory, unaligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
> __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       function = 1; /* pmmFind */
> +       push_long(handle);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       DEBUG_PRINTF_PMM("%s: found memory at: %04x:%04x (expected:
> %08x)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX, addr);
> +       function = 2; /* pmmDeallocate */
> +       push_long(addr);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
> 0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       /*-------------------- Test aligned allocation/deallocation
> ----------------------------- */
> +       function = 0; /* pmmAllocate */
> +       handle = 0xdeadbeef;
> +       length = 257; /* in 16byte paragraphs, so we allocate 4KB + 16 bytes... */
> +       flags = 0x1; /* conventional memory, unaligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
> __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       function = 0; /* pmmAllocate */
> +       handle = 0xf00d4b0b;
> +       length = 128; /* in 16byte paragraphs, so we allocate 2KB... */
> +       flags = 0x5; /* conventional memory, aligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       /* the address should be aligned to 0x800, so probably it is at
> offset 0x1800... */
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
> __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       function = 1; /* pmmFind */
> +       push_long(handle);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       function = 2; /* pmmDeallocate */
> +       push_long(addr);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
> 0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       handle = 0xdeadbeef;
> +       function = 1; /* pmmFind */
> +       push_long(handle);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       function = 2; /* pmmDeallocate */
> +       push_long(addr);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
> 0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       /*-------------------- Test out of memory allocation
> ----------------------------- */
> +       function = 0; /* pmmAllocate */
> +       handle = 0xdeadbeef;
> +       length = 0; /* length zero means, give me the largest possible block */
> +       flags = 0x1; /* conventional memory, unaligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       length = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       length /= 16; /* length in paragraphs */
> +       DEBUG_PRINTF_PMM("%s: largest possible length: %08x\n", __FUNCTION__, length);
> +       function = 0; /* pmmAllocate */
> +       flags = 0x1; /* conventional memory, aligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x\n",
> __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       function = 0; /* pmmAllocate */
> +       length = 1;
> +       handle = 0xf00d4b0b;
> +       flags = 0x1; /* conventional memory, aligned */
> +       /* setup stack for call to pmm_handleInt() */
> +       push_word(flags);
> +       push_long(handle);
> +       push_long(length);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       /* this should fail, so 0x0 should be returned */
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       DEBUG_PRINTF_PMM("%s: allocated memory at: %04x:%04x expected:
> 0000:0000\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +       handle = 0xdeadbeef;
> +       function = 1; /* pmmFind */
> +       push_long(handle);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       addr = ((u32)M.x86.R_DX << 16) | M.x86.R_AX;
> +       function = 2; /* pmmDeallocate */
> +       push_long(addr);
> +       push_word(function);
> +       push_long(0); /* This is the return address for the ABI, unused in
> this implementation */
> +       pmm_handleInt();
> +       DEBUG_PRINTF_PMM("%s: freed memory rval: %04x:%04x (expected:
> 0000:0000)\n", __FUNCTION__, M.x86.R_DX, M.x86.R_AX);
> +}
> diff --git a/util/x86emu/yabel/pmm.h b/util/x86emu/yabel/pmm.h
> new file mode 100644
> index 0000000..b3d34ad
> --- /dev/null
> +++ b/util/x86emu/yabel/pmm.h
> @@ -0,0 +1,39 @@
> +/****************************************************************************
> + * YABEL BIOS Emulator
> + *
> + * Copyright 2008 Pattrick Hueper <phueper at hueper.net>
> + ****************************************************************************/
> +
> +#ifndef _YABEL_PMM_H_
> +#define _YABEL_PMM_H_
> +
> +#include <types.h>
> +
> +/* PMM Structure see PMM Spec Version 1.01 Chapter 3.1.1 (search web
> for specspmm101.pdf) */
> +typedef struct {
> +       u8 signature[4];
> +       u8 struct_rev;
> +       u8 length;
> +       u8 checksum;
> +       u32 entry_point_offset;
> +       u8 reserved[5];
> +       /* code is not part of the speced PMM struct, however, since i cannot put the
> +        * handling in of PMM in the virtual memory (i dont want to hack it together
> +        * in x86 assembly ;-)) this code array is pointed to by entry_point_offset,
> +        * in code there is only a INT call and a RETF, thus every PMM call will issue
> +        * a PMM INT (only defined in YABEL, see interrupt.c) and the INT Handler
> +        * will do the actual PMM work.
> +        */
> +       u8 code[3];
> +} __attribute__ ((__packed__)) pmm_information_t;
> +
> +/* This function is used to setup the PMM struct in virtual memory
> + * at a certain offset */
> +u8 pmm_setup(u16 segment, u16 offset);
> +
> +/* This is the INT Handler mentioned above, it will be called by my
> special PMM INT */
> +void pmm_handleInt(void);
> +
> +void pmm_test(void);
> +
> +#endif // _YABEL_PMM_H
> --
> 1.6.0.4
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-YABEL-add-PMM-functionality.patch
Type: text/x-diff
Size: 19992 bytes
Desc: not available
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20081222/f89f2e16/attachment.bin>


More information about the coreboot mailing list