summaryrefslogtreecommitdiff
path: root/util/x86emu/yabel/pmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/x86emu/yabel/pmm.c')
-rw-r--r--util/x86emu/yabel/pmm.c442
1 files changed, 0 insertions, 442 deletions
diff --git a/util/x86emu/yabel/pmm.c b/util/x86emu/yabel/pmm.c
deleted file mode 100644
index ad4dc6834c..0000000000
--- a/util/x86emu/yabel/pmm.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/****************************************************************************
- * YABEL BIOS Emulator
- *
- * This program and the accompanying materials
- * are made available under the terms of the BSD License
- * which accompanies this distribution, and is available at
- * http://www.opensource.org/licenses/bsd-license.php
- *
- * Copyright (c) 2008 Pattrick Hueper <phueper@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",
- __func__, 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",
- __func__, 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",
- __func__, 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", __func__,
- 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",
- __func__);
- 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",
- __func__, rval);
- } else {
- rval = 0;
- printf
- ("%s: pmmAllocate: allocation in extended memory not supported!\n",
- __func__);
- }
- goto exit;
- case 1:
- /* function pmmFind */
- handle = pop_long(); /* the handle to lookup */
- DEBUG_PRINTF_PMM("%s: pmmFind: Handle: %x\n", __func__,
- 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",
- __func__, 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",
- __func__, 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",
- __func__, 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",
- __func__, 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",
- __func__, buffer);
- }
- goto exit;
- default:
- /* invalid/unimplemented function */
- printf("%s: invalid PMM function (0x%04x) called!\n",
- __func__, 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",
- __func__);
- 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", __func__,
- 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",
- __func__, 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",
- __func__, 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", __func__,
- 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", __func__,
- 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",
- __func__, 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",
- __func__, 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", __func__,
- 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", __func__,
- 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",
- __func__, 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",
- __func__, M.x86.R_DX, M.x86.R_AX);
-}