Author: myles
Date: 2008-12-23 20:21:54 +0100 (Tue, 23 Dec 2008)
New Revision: 1086

Added:
   coreboot-v3/util/x86emu/yabel/pmm.c
   coreboot-v3/util/x86emu/yabel/pmm.h
Modified:
   coreboot-v3/util/x86emu/Makefile
   coreboot-v3/util/x86emu/yabel/biosemu.c
   coreboot-v3/util/x86emu/yabel/interrupt.c
Log:
Subject: [PATCH] YABEL: add PMM functionality.

Signed-off-by: Pattrick Hueper <[email protected]>
Acked-by: Myles Watson <[email protected]>


Modified: coreboot-v3/util/x86emu/Makefile
===================================================================
--- coreboot-v3/util/x86emu/Makefile    2008-12-23 19:02:44 UTC (rev 1085)
+++ coreboot-v3/util/x86emu/Makefile    2008-12-23 19:21:54 UTC (rev 1086)
@@ -29,6 +29,7 @@
 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

Modified: coreboot-v3/util/x86emu/yabel/biosemu.c
===================================================================
--- coreboot-v3/util/x86emu/yabel/biosemu.c     2008-12-23 19:02:44 UTC (rev 
1085)
+++ coreboot-v3/util/x86emu/yabel/biosemu.c     2008-12-23 19:21:54 UTC (rev 
1086)
@@ -26,6 +26,7 @@
 #include "mem.h"
 #include "interrupt.h"
 #include "device.h"
+#include "pmm.h"
 
 #include <rtas.h>
 
@@ -56,7 +57,9 @@
        u8 *rom_image;
        int i = 0;
 #ifdef DEBUG
-       debug_flags = DEBUG_PRINT_INT10 | DEBUG_PNP | DEBUG_PMM | DEBUG_INTR;// 
| DEBUG_CHECK_VMEM_ACCESS | DEBUG_MEM | DEBUG_IO;// | DEBUG_TRACE_X86EMU | 
DEBUG_JMP;
+       debug_flags = DEBUG_PRINT_INT10 | DEBUG_PNP | DEBUG_PMM | DEBUG_INTR;
+               // | DEBUG_CHECK_VMEM_ACCESS | DEBUG_MEM | DEBUG_IO;
+               // | DEBUG_TRACE_X86EMU | DEBUG_JMP;
 #endif
        if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
                printf("Error: Not enough virtual memory: %x, required: %x!\n",
@@ -209,6 +212,20 @@
        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;
@@ -248,8 +265,9 @@
        X86EMU_exec();
        DEBUG_PRINTF("done\n");
 
-       // according to PNP BIOS Spec, Option ROMs should upon exit, return 
some boot device status in
-       // AX (see PNP BIOS Spec Section 3.3
+       /* According to the PNP BIOS Spec, Option ROMs should upon exit, return
+        * some boot device status in AX (see PNP BIOS Spec Section 3.3
+        */
        DEBUG_PRINTF_CS_IP("Option ROM Exit Status: %04x\n", M.x86.R_AX);
 #ifdef DEBUG
        DEBUG_PRINTF("Exit Status Decode:\n");

Modified: coreboot-v3/util/x86emu/yabel/interrupt.c
===================================================================
--- coreboot-v3/util/x86emu/yabel/interrupt.c   2008-12-23 19:02:44 UTC (rev 
1085)
+++ coreboot-v3/util/x86emu/yabel/interrupt.c   2008-12-23 19:21:54 UTC (rev 
1086)
@@ -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 @@
                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));

Added: coreboot-v3/util/x86emu/yabel/pmm.c
===================================================================
--- coreboot-v3/util/x86emu/yabel/pmm.c                         (rev 0)
+++ coreboot-v3/util/x86emu/yabel/pmm.c 2008-12-23 19:21:54 UTC (rev 1086)
@@ -0,0 +1,437 @@
+/****************************************************************************
+ * YABEL BIOS Emulator
+ *
+ * Copyright 2008 Pattrick Hueper <[email protected]>
+ ****************************************************************************/
+
+#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);
+}

Added: coreboot-v3/util/x86emu/yabel/pmm.h
===================================================================
--- coreboot-v3/util/x86emu/yabel/pmm.h                         (rev 0)
+++ coreboot-v3/util/x86emu/yabel/pmm.h 2008-12-23 19:21:54 UTC (rev 1086)
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * YABEL BIOS Emulator
+ *
+ * Copyright 2008 Pattrick Hueper <[email protected]>
+ ****************************************************************************/
+
+#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 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, called by my special PMM INT. */
+void pmm_handleInt(void);
+
+void pmm_test(void);
+
+#endif                         // _YABEL_PMM_H


--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to