diff options
Diffstat (limited to 'util/x86emu/yabel/pmm.c')
-rw-r--r-- | util/x86emu/yabel/pmm.c | 442 |
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); -} |