Progress on ghetto memory allocator.

This commit is contained in:
Ben Vanik
2013-01-28 21:36:03 -08:00
parent 0fde6135a0
commit 7b62fa96bd
11 changed files with 6471 additions and 44 deletions

View File

@@ -19,10 +19,14 @@ namespace kernel {
namespace xboxkrnl {
typedef uint32_t X_HANDLE;
#define X_INVALID_HANDLE_VALUE ((X_HANDLE)-1)
// NT_STATUS (STATUS_*)
// http://msdn.microsoft.com/en-us/library/cc704588.aspx
// Adding as needed.
#define X_STAUTS_SUCCESS ((uint32_t)0x00000000L)
#define X_STATUS_SUCCESS ((uint32_t)0x00000000L)
#define X_STATUS_UNSUCCESSFUL ((uint32_t)0xC0000001L)
#define X_STATUS_NOT_IMPLEMENTED ((uint32_t)0xC0000002L)
#define X_STATUS_ACCESS_VIOLATION ((uint32_t)0xC0000005L)
@@ -37,29 +41,32 @@ namespace xboxkrnl {
// MEM_*, used by NtAllocateVirtualMemory
#define X_MEM_COMMIT 0x00001000
#define X_MEM_RESERVE 0x00002000
#define X_MEM_DECOMMIT 0x00004000
#define X_MEM_RELEASE 0x00008000
#define X_MEM_FREE 0x00010000
#define X_MEM_PRIVATE 0x00020000
#define X_MEM_RESET 0x00080000
#define X_MEM_TOP_DOWN 0x00100000
#define X_MEM_NOZERO 0x00800000
#define X_MEM_LARGE_PAGES 0x20000000
#define X_MEM_HEAP 0x40000000
#define X_MEM_16MB_PAGES 0x80000000 // from Valve SDK
#define X_MEM_COMMIT 0x00001000
#define X_MEM_RESERVE 0x00002000
#define X_MEM_DECOMMIT 0x00004000
#define X_MEM_RELEASE 0x00008000
#define X_MEM_FREE 0x00010000
#define X_MEM_PRIVATE 0x00020000
#define X_MEM_RESET 0x00080000
#define X_MEM_TOP_DOWN 0x00100000
#define X_MEM_NOZERO 0x00800000
#define X_MEM_LARGE_PAGES 0x20000000
#define X_MEM_HEAP 0x40000000
#define X_MEM_16MB_PAGES 0x80000000 // from Valve SDK
// PAGE_*, used by NtAllocateVirtualMemory
#define X_PAGE_NOACCESS 0x00000001
#define X_PAGE_READONLY 0x00000002
#define X_PAGE_READWRITE 0x00000004
#define X_PAGE_WRITECOPY 0x00000008
// *_EXECUTE_* bits omitted, as user code can't mark pages as executable.
#define X_PAGE_GUARD 0x00000100
#define X_PAGE_NOCACHE 0x00000200
#define X_PAGE_WRITECOMBINE 0x00000400
#define X_PAGE_NOACCESS 0x00000001
#define X_PAGE_READONLY 0x00000002
#define X_PAGE_READWRITE 0x00000004
#define X_PAGE_WRITECOPY 0x00000008
#define X_PAGE_EXECUTE 0x00000010
#define X_PAGE_EXECUTE_READ 0x00000020
#define X_PAGE_EXECUTE_READWRITE 0x00000040
#define X_PAGE_EXECUTE_WRITECOPY 0x00000080
#define X_PAGE_GUARD 0x00000100
#define X_PAGE_NOCACHE 0x00000200
#define X_PAGE_WRITECOMBINE 0x00000400
// (?), used by KeGetCurrentProcessType

View File

@@ -35,29 +35,65 @@ void NtAllocateVirtualMemory_shim(
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
uint32_t region_size_value = SHIM_MEM_32(region_size_ptr);
// X_MEM_*
uint32_t allocation_type = SHIM_GET_ARG_32(2);
// X_PAGE_*
uint32_t protect_bits = SHIM_GET_ARG_32(3);
uint32_t allocation_type = SHIM_GET_ARG_32(2); // X_MEM_* bitmask
uint32_t protect_bits = SHIM_GET_ARG_32(3); // X_PAGE_* bitmask
uint32_t unknown = SHIM_GET_ARG_32(4);
// I've only seen zero.
XEASSERT(unknown == 0);
XELOGD(
XT("NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)"),
base_addr_ptr, base_addr_value,
region_size_ptr, region_size_value,
allocation_type, protect_bits, unknown);
// TODO(benvanik): alloc memory
// This allocates memory from the kernel heap, which is initialized on startup
// and shared by both the kernel implementation and user code.
// The xe_memory_ref object is used to actually get the memory, and although
// it's simple today we could extend it to do better things in the future.
// Possible return codes:
// X_STATUS_UNSUCCESSFUL
// X_STATUS_INVALID_PAGE_PROTECTION
// X_STATUS_ACCESS_DENIED
// X_STATUS_ALREADY_COMMITTED
// X_STATUS_INVALID_HANDLE
// X_STATUS_INVALID_PAGE_PROTECTION
// X_STATUS_NO_MEMORY
SHIM_SET_RETURN(X_STATUS_UNSUCCESSFUL);
// Must request a size.
if (!region_size_value) {
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
return;
}
// Check allocation type.
if (!(allocation_type & (X_MEM_COMMIT | X_MEM_RESET | X_MEM_RESERVE))) {
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
return;
}
// If MEM_RESET is set only MEM_RESET can be set.
if (allocation_type & X_MEM_RESET && (allocation_type & ~X_MEM_RESET)) {
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
return;
}
// Don't allow games to set execute bits.
if (protect_bits & (X_PAGE_EXECUTE | X_PAGE_EXECUTE_READ |
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
SHIM_SET_RETURN(X_STATUS_ACCESS_DENIED);
return;
}
// Adjust size.
uint32_t adjusted_size = region_size_value;
// TODO(benvanik): adjust based on page size flags/etc?
// Allocate.
uint32_t flags = 0;
uint32_t addr = xe_memory_heap_alloc(
state->memory, base_addr_value, adjusted_size, flags);
if (!addr) {
// Failed - assume no memory available.
SHIM_SET_RETURN(X_STATUS_NO_MEMORY);
return;
}
// Stash back.
// Maybe set X_STATUS_ALREADY_COMMITTED if MEM_COMMIT?
SHIM_SET_MEM_32(base_addr_ptr, addr);
SHIM_SET_MEM_32(region_size_ptr, adjusted_size);
SHIM_SET_RETURN(X_STATUS_SUCCESS);
}
void NtFreeVirtualMemory_shim(
@@ -76,19 +112,28 @@ void NtFreeVirtualMemory_shim(
uint32_t free_type = SHIM_GET_ARG_32(2);
uint32_t unknown = SHIM_GET_ARG_32(3);
// I've only seen zero.
XEASSERT(unknown == 0);
XELOGD(
XT("NtFreeVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X)"),
base_addr_ptr, base_addr_value,
region_size_ptr, region_size_value,
free_type, unknown);
// TODO(benvanik): free memory
// Free.
uint32_t flags = 0;
uint32_t freed_size = xe_memory_heap_free(state->memory, base_addr_value,
flags);
if (!freed_size) {
SHIM_SET_RETURN(X_STATUS_UNSUCCESSFUL);
return;
}
// Possible return codes:
// X_STATUS_UNSUCCESSFUL
// X_STATUS_ACCESS_DENIED
// X_STATUS_INVALID_HANDLE
SHIM_SET_RETURN(X_STATUS_UNSUCCESSFUL);
// Stash back.
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
SHIM_SET_MEM_32(region_size_ptr, freed_size);
SHIM_SET_RETURN(X_STATUS_SUCCESS);
}

View File

@@ -50,9 +50,12 @@ XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
uint8_t* mem = xe_memory_addr(memory, 0);
// KeDebugMonitorData (?*)
// I'm not sure what this is for, but games make sure it's not null and
// exit if it is.
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x00000059,
0x40001000);
0x80102100);
XESETUINT32BE(mem + 0x80102100, 0x1);
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
// flags cpu# ? ? ? ? ? ?

View File

@@ -54,6 +54,8 @@ void RtlImageXexHeaderField_shim(
case XEX_HEADER_DEFAULT_HEAP_SIZE:
// TODO(benvanik): pull from running module
// This is header->exe_heap_size.
//SHIM_SET_MEM_32(0x80101104, [some value]);
//return_value = 0x80101104;
return_value = 0;
break;
default:
@@ -67,6 +69,10 @@ void RtlImageXexHeaderField_shim(
}
//RtlInitializeCriticalSection
//RtlEnterCriticalSection
//RtlLeaveCriticalSection
}