Kernel function work.

This commit is contained in:
Ben Vanik 2013-01-30 14:26:28 -08:00
parent 42009cda88
commit 23378443e8
20 changed files with 616 additions and 134 deletions

View File

@ -9,8 +9,6 @@ Ordered:
```
RtlInitializeCriticalSection/RtlInitializeCriticalSectionAndSpinCount
RtlEnterCriticalSection/RtlLeaveCriticalSection
XexCheckExecutablePrivilege
XGetAVPack
ExGetXConfigSetting
KeTlsAlloc
KeTlsSetValue

View File

@ -11,7 +11,6 @@
#define XENIA_KERNEL_MODULES_H_
#include "kernel/modules/xam/xam_module.h"
#include "kernel/modules/xbdm/xbdm_module.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
#include "kernel/modules/xboxkrnl/module.h"
#endif // XENIA_KERNEL_MODULES_H_

View File

@ -2,7 +2,6 @@
{
'includes': [
'xam/sources.gypi',
'xbdm/sources.gypi',
'xboxkrnl/sources.gypi',
],
}

View File

@ -1,6 +1,8 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'xam_info.cc',
'xam_module.cc',
'xam_state.cc',
],
}

View File

@ -0,0 +1,47 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xam/xam_info.h"
#include "kernel/shim_utils.h"
#include "kernel/modules/xam/xam_module.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xam;
namespace {
void XGetAVPack_shim(
xe_ppc_state_t* ppc_state, XamState* state) {
// DWORD
// Not sure what the values are for this, but 6 is VGA.
// Other likely values are 3/4/8 for HDMI or something.
// Games seem to use this as a PAL check - if the result is not 3/4/6/8
// they explode with errors if not in PAL mode.
SHIM_SET_RETURN(6);
}
}
void xe::kernel::xam::RegisterInfoExports(
ExportResolver* export_resolver, XamState* state) {
#define SHIM_SET_MAPPING(ordinal, shim, impl) \
export_resolver->SetFunctionMapping("xam.xex", ordinal, \
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
SHIM_SET_MAPPING(0x000003CB, XGetAVPack_shim, NULL);
#undef SET_MAPPING
}

View File

@ -7,31 +7,23 @@
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBDM_TABLE_H_
#define XENIA_KERNEL_MODULES_XBDM_TABLE_H_
#ifndef XENIA_KERNEL_MODULES_XAM_INFO_H_
#define XENIA_KERNEL_MODULES_XAM_INFO_H_
#include <xenia/kernel/export.h>
#include "kernel/modules/xam/xam_state.h"
namespace xe {
namespace kernel {
namespace xbdm {
namespace xam {
#define FLAG(t) kXEKernelExportFlag##t
void RegisterInfoExports(ExportResolver* export_resolver, XamState* state);
static KernelExport xbdm_export_table[] = {
{ 0 },
};
#undef FLAG
} // namespace xbdm
} // namespace xam
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBDM_TABLE_H_
#endif // XENIA_KERNEL_MODULES_XAM_INFO_H_

View File

@ -9,6 +9,8 @@
#include "kernel/modules/xam/xam_module.h"
#include "kernel/modules/xam/xam_info.h"
#include "kernel/modules/xam/xam_table.h"
@ -22,6 +24,12 @@ XamModule::XamModule(xe_pal_ref pal, xe_memory_ref memory,
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xam.xex", xam_export_table, XECOUNT(xam_export_table));
// Setup the xam state instance.
xam_state = auto_ptr<XamState>(new XamState(pal, memory, resolver));
// Register all exported functions.
RegisterInfoExports(resolver.get(), xam_state.get());
}
XamModule::~XamModule() {

View File

@ -21,12 +21,17 @@ namespace xe {
namespace kernel {
namespace xam {
class XamState;
class XamModule : public KernelModule {
public:
XamModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XamModule();
private:
auto_ptr<XamState> xam_state;
};

View File

@ -7,22 +7,27 @@
******************************************************************************
*/
#include "kernel/modules/xbdm/xbdm_module.h"
#include "kernel/modules/xbdm/xbdm_table.h"
#include "kernel/modules/xam/xam_state.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xbdm;
using namespace xe::kernel::xam;
XbdmModule::XbdmModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xbdm.exe", xbdm_export_table, XECOUNT(xbdm_export_table));
namespace {
}
XbdmModule::~XbdmModule() {
XamState::XamState(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> export_resolver) {
this->pal = xe_pal_retain(pal);
this->memory = xe_memory_retain(memory);
export_resolver_ = export_resolver;
}
XamState::~XamState() {
xe_memory_release(memory);
xe_pal_release(pal);
}

View File

@ -7,8 +7,8 @@
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBDM_MODULE_H_
#define XENIA_KERNEL_MODULES_XBDM_MODULE_H_
#ifndef XENIA_KERNEL_MODULES_XAM_XAM_STATE_H_
#define XENIA_KERNEL_MODULES_XAM_XAM_STATE_H_
#include <xenia/common.h>
#include <xenia/core.h>
@ -19,20 +19,26 @@
namespace xe {
namespace kernel {
namespace xbdm {
namespace xam {
class XbdmModule : public KernelModule {
class XamState {
public:
XbdmModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XbdmModule();
XamState(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> export_resolver);
~XamState();
xe_pal_ref pal;
xe_memory_ref memory;
private:
shared_ptr<ExportResolver> export_resolver_;
};
} // namespace xbdm
} // namespace xam
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBDM_MODULE_H_
#endif // XENIA_KERNEL_MODULES_XAM_XAM_STATE_H_

View File

@ -1,6 +0,0 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'xbdm_module.cc',
],
}

View File

@ -0,0 +1,102 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "kernel/modules/xboxkrnl/module.h"
#include "kernel/modules/xboxkrnl/kernel_state.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_hal.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_memory.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_rtl.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_threading.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xboxkrnl;
namespace {
}
XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
// Setup the kernel state instance.
// This is where all kernel objects are kept while running.
kernel_state = auto_ptr<KernelState>(new KernelState(pal, memory, resolver));
// Register all exported functions.
RegisterHalExports(resolver.get(), kernel_state.get());
RegisterMemoryExports(resolver.get(), kernel_state.get());
RegisterModuleExports(resolver.get(), kernel_state.get());
RegisterRtlExports(resolver.get(), kernel_state.get());
RegisterThreadingExports(resolver.get(), kernel_state.get());
// TODO(benvanik): alloc heap memory somewhere in user space
// TODO(benvanik): tools for reading/writing to heap 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,
0x80102100);
XESETUINT32BE(mem + 0x80102100, 0x1);
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
// flags cpu# ? ? ? ? ? ?
// 0x00000000, 0x06, 0x00, 0x00, 0x00, 0x00000000, 0x0000, 0x0000
// Games seem to check if bit 26 (0x20) is set, which at least for xbox1
// was whether an HDD was present. Not sure what the other flags are.
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x00000156,
0x80100FED);
XESETUINT32BE(mem + 0x80100FED, 0x00000000); // flags
XESETUINT8BE(mem + 0x80100FEE, 0x06); // cpu count
// Remaining 11b are zeroes?
// XexExecutableModuleHandle (?**)
// Games try to dereference this to get a pointer to some module struct.
// So far it seems like it's just in loader code, and only used to look up
// the XexHeaderBase for use by RtlImageXexHeaderField.
// We fake it so that the address passed to that looks legit.
// 0x80100FFC <- pointer to structure
// 0x80101000 <- our module structure
// 0x80101058 <- pointer to xex header
// 0x80101100 <- xex header base
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x00000193,
0x80100FFC);
XESETUINT32BE(mem + 0x80100FFC, 0x80101000);
XESETUINT32BE(mem + 0x80101058, 0x80101100);
// ExLoadedCommandLine (char*)
// The name of the xex. Not sure this is ever really used on real devices.
// Perhaps it's how swap disc/etc data is sent?
// Always set to "default.xex" (with quotes) for now.
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x000001AE,
0x80102000);
char command_line[] = "\"default.xex\"";
xe_copy_memory(mem + 0x80102000, 1024,
command_line, XECOUNT(command_line) + 1);
}
XboxkrnlModule::~XboxkrnlModule() {
}

View File

@ -0,0 +1,42 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#define XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/kernel_module.h>
namespace xe {
namespace kernel {
namespace xboxkrnl {
class KernelState;
class XboxkrnlModule : public KernelModule {
public:
XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XboxkrnlModule();
private:
auto_ptr<KernelState> kernel_state;
};
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_

View File

@ -2,6 +2,7 @@
{
'sources': [
'kernel_state.cc',
'module.cc',
'xboxkrnl_hal.cc',
'xboxkrnl_memory.cc',
'xboxkrnl_module.cc',

View File

@ -75,6 +75,10 @@ typedef uint32_t X_HANDLE;
#define X_PROCTYPE_SYSTEM 2
// TLS specials.
#define X_TLS_OUT_OF_INDEXES UINT32_MAX // (-1)
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe

View File

@ -9,13 +9,10 @@
#include "kernel/modules/xboxkrnl/xboxkrnl_module.h"
#include "kernel/modules/xboxkrnl/kernel_state.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_hal.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_memory.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_rtl.h"
#include "kernel/modules/xboxkrnl/xboxkrnl_threading.h"
#include <xenia/kernel/xex2.h>
#include "kernel/modules/xboxkrnl/xboxkrnl_table.h"
#include "kernel/shim_utils.h"
#include "kernel/modules/xboxkrnl/xboxkrnl.h"
using namespace xe;
@ -25,76 +22,87 @@ using namespace xe::kernel::xboxkrnl;
namespace {
// void ExGetXConfigSetting_shim(
// xe_ppc_state_t* ppc_state, KernelState* state) {
// // ?
// SHIM_SET_RETURN(0);
// }
void XexCheckExecutablePrivilege_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// BOOL
// DWORD Privilege
uint32_t privilege = SHIM_GET_ARG_32(0);
XELOGD(
XT("XexCheckExecutablePrivilege(%.8X)"),
privilege);
// Privilege is bit position in xe_xex2_system_flags enum - so:
// Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
uint32_t mask = 1 << privilege;
// TODO(benvanik): pull from xex header:
// XEKernelModuleRef module = XEKernelGetExecutableModule(XEGetKernel());
// const XEXHeader* xexhdr = XEKernelModuleGetXEXHeader(module);
// return xexhdr->systemFlags & mask;
if (mask == XEX_SYSTEM_PAL50_INCOMPATIBLE) {
// Only one we've seen.
} else {
XELOGW(XT("XexCheckExecutablePrivilege: %.8X is NOT IMPLEMENTED"),
privilege);
}
SHIM_SET_RETURN(0);
}
XboxkrnlModule::XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver) :
KernelModule(pal, memory, resolver) {
resolver->RegisterTable(
"xboxkrnl.exe", xboxkrnl_export_table, XECOUNT(xboxkrnl_export_table));
void XexGetModuleHandle_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// BOOL
// LPCSZ ModuleName
// LPHMODULE ModuleHandle
// Setup the kernel state instance.
// This is where all kernel objects are kept while running.
kernel_state = auto_ptr<KernelState>(new KernelState(pal, memory, resolver));
uint32_t module_name_ptr = SHIM_GET_ARG_32(0);
const char* module_name = (const char*)SHIM_MEM_ADDR(module_name_ptr);
uint32_t module_handle_ptr = SHIM_GET_ARG_32(1);
// Register all exported functions.
RegisterHalExports(resolver.get(), kernel_state.get());
RegisterMemoryExports(resolver.get(), kernel_state.get());
RegisterRtlExports(resolver.get(), kernel_state.get());
RegisterThreadingExports(resolver.get(), kernel_state.get());
XELOGD(
XT("XexGetModuleHandle(%s, %.8X)"),
module_name, module_handle_ptr);
// TODO(benvanik): alloc heap memory somewhere in user space
// TODO(benvanik): tools for reading/writing to heap memory
XEASSERTALWAYS();
uint8_t* mem = xe_memory_addr(memory, 0);
// TODO(benvanik): get module
// XEKernelModuleRef module = XEKernelGetModuleByName(XEGetKernel(), ModuleName);
// if (!module) {
SHIM_SET_RETURN(0);
// return;
// }
// 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,
0x80102100);
XESETUINT32BE(mem + 0x80102100, 0x1);
// XboxHardwareInfo (XboxHardwareInfo_t, 16b)
// flags cpu# ? ? ? ? ? ?
// 0x00000000, 0x06, 0x00, 0x00, 0x00, 0x00000000, 0x0000, 0x0000
// Games seem to check if bit 26 (0x20) is set, which at least for xbox1
// was whether an HDD was present. Not sure what the other flags are.
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x00000156,
0x80100FED);
XESETUINT32BE(mem + 0x80100FED, 0x00000000); // flags
XESETUINT8BE(mem + 0x80100FEE, 0x06); // cpu count
// Remaining 11b are zeroes?
// XexExecutableModuleHandle (?**)
// Games try to dereference this to get a pointer to some module struct.
// So far it seems like it's just in loader code, and only used to look up
// the XexHeaderBase for use by RtlImageXexHeaderField.
// We fake it so that the address passed to that looks legit.
// 0x80100FFC <- pointer to structure
// 0x80101000 <- our module structure
// 0x80101058 <- pointer to xex header
// 0x80101100 <- xex header base
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x00000193,
0x80100FFC);
XESETUINT32BE(mem + 0x80100FFC, 0x80101000);
XESETUINT32BE(mem + 0x80101058, 0x80101100);
// ExLoadedCommandLine (char*)
// The name of the xex. Not sure this is ever really used on real devices.
// Perhaps it's how swap disc/etc data is sent?
// Always set to "default.xex" (with quotes) for now.
resolver->SetVariableMapping(
"xboxkrnl.exe", 0x000001AE,
0x80102000);
char command_line[] = "\"default.xex\"";
xe_copy_memory(mem + 0x80102000, 1024,
command_line, XECOUNT(command_line) + 1);
// SHIM_SET_MEM_32(module_handle_ptr, module->handle());
// SHIM_SET_RETURN(1);
}
XboxkrnlModule::~XboxkrnlModule() {
}
void xe::kernel::xboxkrnl::RegisterModuleExports(
ExportResolver* export_resolver, KernelState* state) {
#define SHIM_SET_MAPPING(ordinal, shim, impl) \
export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
//SHIM_SET_MAPPING(0x00000010, ExGetXConfigSetting_shim, NULL);
SHIM_SET_MAPPING(0x00000194, XexCheckExecutablePrivilege_shim, NULL);
SHIM_SET_MAPPING(0x00000195, XexGetModuleHandle_shim, NULL);
#undef SET_MAPPING
}

View File

@ -7,36 +7,23 @@
******************************************************************************
*/
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#define XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_IMPL_H_
#define XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_IMPL_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/export.h>
#include <xenia/kernel/kernel_module.h>
#include "kernel/modules/xboxkrnl/kernel_state.h"
namespace xe {
namespace kernel {
namespace xboxkrnl {
class KernelState;
class XboxkrnlModule : public KernelModule {
public:
XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory,
shared_ptr<ExportResolver> resolver);
virtual ~XboxkrnlModule();
private:
auto_ptr<KernelState> kernel_state;
};
void RegisterModuleExports(ExportResolver* export_resolver, KernelState* state);
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_IMPL_H_

View File

@ -49,6 +49,15 @@ void RtlImageXexHeaderField_shim(
return;
}
// TODO(benvanik): pull from xex header
// module = GetExecutableModule() || (user defined one)
// header = module->xex_header()
// for (n = 0; n < header->header_count; n++) {
// if (header->headers[n].key == ImageField) {
// return value? or offset?
// }
// }
uint32_t return_value = 0;
switch (image_field) {
case XEX_HEADER_DEFAULT_HEAP_SIZE:
@ -68,6 +77,107 @@ void RtlImageXexHeaderField_shim(
SHIM_SET_RETURN(return_value);
}
// http://msdn.microsoft.com/en-us/library/ff561778
void RtlCompareMemory_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// SIZE_T
// _In_ const VOID *Source1,
// _In_ const VOID *Source2,
// _In_ SIZE_T Length
uint32_t source1 = SHIM_GET_ARG_32(0);
uint32_t source2 = SHIM_GET_ARG_32(1);
uint32_t length = SHIM_GET_ARG_32(2);
XELOGD(
XT("RtlCompareMemory(%.8X, %.8X, %d)"),
source1, source2, length);
uint8_t* p1 = SHIM_MEM_ADDR(source1);
uint8_t* p2 = SHIM_MEM_ADDR(source2);
// Note that the return value is the number of bytes that match, so it's best
// we just do this ourselves vs. using memcmp.
// On Windows we could use the builtin function.
uint32_t c = 0;
for (uint32_t n = 0; n < length; n++, p1++, p2++) {
if (*p1 == *p2) {
c++;
}
}
SHIM_SET_RETURN(c);
}
// http://msdn.microsoft.com/en-us/library/ff552123
void RtlCompareMemoryUlong_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// SIZE_T
// _In_ PVOID Source,
// _In_ SIZE_T Length,
// _In_ ULONG Pattern
uint32_t source = SHIM_GET_ARG_32(0);
uint32_t length = SHIM_GET_ARG_32(1);
uint32_t pattern = SHIM_GET_ARG_32(2);
XELOGD(
XT("RtlCompareMemoryUlong(%.8X, %d, %.8X)"),
source, length, pattern);
if ((source % 4) || (length % 4)) {
SHIM_SET_RETURN(0);
return;
}
uint8_t* p = SHIM_MEM_ADDR(source);
// Swap pattern.
// TODO(benvanik): ensure byte order of pattern is correct.
// Since we are doing byte-by-byte comparison we may not want to swap.
// GET_ARG swaps, so this is a swap back. Ugly.
const uint32_t pb32 = XESWAP32BE(pattern);
const uint8_t* pb = (uint8_t*)&pb32;
uint32_t c = 0;
for (uint32_t n = 0; n < length; n++, p++) {
if (*p == pb[n % 4]) {
c++;
}
}
SHIM_SET_RETURN(c);
}
// http://msdn.microsoft.com/en-us/library/ff552263
void RtlFillMemoryUlong_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// VOID
// _Out_ PVOID Destination,
// _In_ SIZE_T Length,
// _In_ ULONG Pattern
uint32_t destination = SHIM_GET_ARG_32(0);
uint32_t length = SHIM_GET_ARG_32(1);
uint32_t pattern = SHIM_GET_ARG_32(2);
XELOGD(
XT("RtlFillMemoryUlong(%.8X, %d, %.8X)"),
destination, length, pattern);
// NOTE: length must be % 4, so we can work on uint32s.
uint32_t* p = (uint32_t*)SHIM_MEM_ADDR(destination);
// TODO(benvanik): ensure byte order is correct - we're writing back the
// swapped arg value.
for (uint32_t n = 0; n < length / 4; n++, p++) {
*p = pattern;
}
}
//RtlInitializeCriticalSection
//RtlEnterCriticalSection
@ -82,6 +192,10 @@ void xe::kernel::xboxkrnl::RegisterRtlExports(
export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
SHIM_SET_MAPPING(0x0000011A, RtlCompareMemory_shim, NULL);
SHIM_SET_MAPPING(0x0000011B, RtlCompareMemoryUlong_shim, NULL);
SHIM_SET_MAPPING(0x00000126, RtlFillMemoryUlong_shim, NULL);
SHIM_SET_MAPPING(0x0000012B, RtlImageXexHeaderField_shim, NULL);
#undef SET_MAPPING

View File

@ -21,6 +21,55 @@ using namespace xe::kernel::xboxkrnl;
namespace {
// r13 + 0x100: pointer to thread local state
// Thread local state:
// 0x14C: thread id
// 0x150: if >0 then error states don't get set
// 0x160: last error
// GetCurrentThreadId:
// lwz r11, 0x100(r13)
// lwz r3, 0x14C(r11)
// RtlGetLastError:
// lwz r11, 0x150(r13)
// if (r11 != 0) {
// lwz r11, 0x100(r13)
// stw r3, 0x160(r11)
// }
// RtlSetLastError:
// lwz r11, 0x150(r13)
// if (r11 != 0) {
// lwz r11, 0x100(r13)
// stw r3, 0x160(r11)
// }
// RtlSetLastNTError:
// r3 = RtlNtStatusToDosError(r3)
// lwz r11, 0x150(r13)
// if (r11 != 0) {
// lwz r11, 0x100(r13)
// stw r3, 0x160(r11)
// }
void ExCreateThread() {
// launch native thread
//
}
void ExCreateThread_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
XELOGD(
XT("ExCreateThread()"));
SHIM_SET_RETURN(0);
}
void KeGetCurrentProcessType_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// DWORD
@ -32,6 +81,121 @@ void KeGetCurrentProcessType_shim(
}
// The TLS system used here is a bit hacky, but seems to work.
// Both Win32 and pthreads use unsigned longs as TLS indices, so we can map
// right into the system for these calls. We're just round tripping the IDs and
// hoping for the best.
// http://msdn.microsoft.com/en-us/library/ms686801
void KeTlsAlloc_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// DWORD
XELOGD(
XT("KeTlsAlloc()"));
uint32_t tls_index;
#if XE_PLATFORM(WIN32)
tls_index = TlsAlloc();
#else
pthread_key_t key;
if (pthread_key_create(&key, NULL)) {
tls_index = X_TLS_OUT_OF_INDEXES;
} else {
tls_index = (uint32_t)key;
}
#endif // WIN32
SHIM_SET_RETURN(tls_index);
}
// http://msdn.microsoft.com/en-us/library/ms686804
void KeTlsFree_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// BOOL
// _In_ DWORD dwTlsIndex
uint32_t tls_index = SHIM_GET_ARG_32(0);
XELOGD(
XT("KeTlsFree(%.8X)"),
tls_index);
if (tls_index == X_TLS_OUT_OF_INDEXES) {
SHIM_SET_RETURN(0);
return;
}
int result_code = 0;
#if XE_PLATFORM(WIN32)
result_code = TlsFree(tls_index);
#else
result_code = pthread_key_delete(tls_index) == 0;
#endif // WIN32
SHIM_SET_RETURN(result_code);
}
// http://msdn.microsoft.com/en-us/library/ms686812
void KeTlsGetValue_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// LPVOID
// _In_ DWORD dwTlsIndex
uint32_t tls_index = SHIM_GET_ARG_32(0);
XELOGD(
XT("KeTlsGetValue(%.8X)"),
tls_index);
uint32_t value = 0;
#if XE_PLATFORM(WIN32)
value = (uint32_t)((uint64_t)TlsGetValue(tls_index));
#else
value = (uint32_t)((uint64_t)pthread_getspecific(tls_index));
#endif // WIN32
if (!value) {
XELOGW(XT("KeTlsGetValue should SetLastError if result is NULL"));
// TODO(benvanik): SetLastError
}
SHIM_SET_RETURN(value);
}
// http://msdn.microsoft.com/en-us/library/ms686818
void KeTlsSetValue_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
// BOOL
// _In_ DWORD dwTlsIndex,
// _In_opt_ LPVOID lpTlsValue
uint32_t tls_index = SHIM_GET_ARG_32(0);
uint32_t tls_value = SHIM_GET_ARG_32(1);
XELOGD(
XT("KeTlsSetValue(%.8X, %.8X)"),
tls_index, tls_value);
int result_code = 0;
#if XE_PLATFORM(WIN32)
result_code = TlsSetValue(tls_index, tls_value);
#else
result_code = pthread_setspecific(tls_index, (void*)tls_value) == 0;
#endif // WIN32
SHIM_SET_RETURN(result_code);
}
}
@ -41,7 +205,14 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports(
export_resolver->SetFunctionMapping("xboxkrnl.exe", ordinal, \
state, (xe_kernel_export_shim_fn)shim, (xe_kernel_export_impl_fn)impl)
SHIM_SET_MAPPING(0x0000000D, ExCreateThread_shim, ExCreateThread);
SHIM_SET_MAPPING(0x00000066, KeGetCurrentProcessType_shim, NULL);
SHIM_SET_MAPPING(0x00000152, KeTlsAlloc_shim, NULL);
SHIM_SET_MAPPING(0x00000153, KeTlsFree_shim, NULL);
SHIM_SET_MAPPING(0x00000154, KeTlsGetValue_shim, NULL);
SHIM_SET_MAPPING(0x00000155, KeTlsSetValue_shim, NULL);
#undef SET_MAPPING
}

View File

@ -27,8 +27,6 @@ Runtime::Runtime(xe_pal_ref pal, shared_ptr<cpu::Processor> processor,
kernel_modules_.push_back(
new xboxkrnl::XboxkrnlModule(pal_, memory_, export_resolver_));
kernel_modules_.push_back(
new xbdm::XbdmModule(pal_, memory_, export_resolver_));
kernel_modules_.push_back(
new xam::XamModule(pal_, memory_, export_resolver_));
}