From 23378443e8adf9ef4886a6d5b426032bef027085 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 30 Jan 2013 14:26:28 -0800 Subject: [PATCH] Kernel function work. --- TODO.md | 2 - src/kernel/modules/modules.h | 3 +- src/kernel/modules/sources.gypi | 1 - src/kernel/modules/xam/sources.gypi | 2 + src/kernel/modules/xam/xam_info.cc | 47 +++++ .../{xbdm/xbdm_table.h => xam/xam_info.h} | 22 +-- src/kernel/modules/xam/xam_module.cc | 8 + src/kernel/modules/xam/xam_module.h | 5 + .../{xbdm/xbdm_module.cc => xam/xam_state.cc} | 25 ++- .../{xbdm/xbdm_module.h => xam/xam_state.h} | 24 ++- src/kernel/modules/xbdm/sources.gypi | 6 - src/kernel/modules/xboxkrnl/module.cc | 102 +++++++++++ src/kernel/modules/xboxkrnl/module.h | 42 +++++ src/kernel/modules/xboxkrnl/sources.gypi | 1 + src/kernel/modules/xboxkrnl/xboxkrnl.h | 4 + .../modules/xboxkrnl/xboxkrnl_module.cc | 144 ++++++++------- src/kernel/modules/xboxkrnl/xboxkrnl_module.h | 25 +-- src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc | 114 ++++++++++++ .../modules/xboxkrnl/xboxkrnl_threading.cc | 171 ++++++++++++++++++ src/kernel/runtime.cc | 2 - 20 files changed, 616 insertions(+), 134 deletions(-) create mode 100644 src/kernel/modules/xam/xam_info.cc rename src/kernel/modules/{xbdm/xbdm_table.h => xam/xam_info.h} (63%) rename src/kernel/modules/{xbdm/xbdm_module.cc => xam/xam_state.cc} (57%) rename src/kernel/modules/{xbdm/xbdm_module.h => xam/xam_state.h} (62%) delete mode 100644 src/kernel/modules/xbdm/sources.gypi create mode 100644 src/kernel/modules/xboxkrnl/module.cc create mode 100644 src/kernel/modules/xboxkrnl/module.h diff --git a/TODO.md b/TODO.md index 6da3e3464..ad2aa05ce 100644 --- a/TODO.md +++ b/TODO.md @@ -9,8 +9,6 @@ Ordered: ``` RtlInitializeCriticalSection/RtlInitializeCriticalSectionAndSpinCount RtlEnterCriticalSection/RtlLeaveCriticalSection -XexCheckExecutablePrivilege -XGetAVPack ExGetXConfigSetting KeTlsAlloc KeTlsSetValue diff --git a/src/kernel/modules/modules.h b/src/kernel/modules/modules.h index b8a40da66..77316eac8 100644 --- a/src/kernel/modules/modules.h +++ b/src/kernel/modules/modules.h @@ -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_ diff --git a/src/kernel/modules/sources.gypi b/src/kernel/modules/sources.gypi index bbcfda6ae..86759bfec 100644 --- a/src/kernel/modules/sources.gypi +++ b/src/kernel/modules/sources.gypi @@ -2,7 +2,6 @@ { 'includes': [ 'xam/sources.gypi', - 'xbdm/sources.gypi', 'xboxkrnl/sources.gypi', ], } diff --git a/src/kernel/modules/xam/sources.gypi b/src/kernel/modules/xam/sources.gypi index 5e9fb53e5..78fbc6320 100644 --- a/src/kernel/modules/xam/sources.gypi +++ b/src/kernel/modules/xam/sources.gypi @@ -1,6 +1,8 @@ # Copyright 2013 Ben Vanik. All Rights Reserved. { 'sources': [ + 'xam_info.cc', 'xam_module.cc', + 'xam_state.cc', ], } diff --git a/src/kernel/modules/xam/xam_info.cc b/src/kernel/modules/xam/xam_info.cc new file mode 100644 index 000000000..bd5f2f175 --- /dev/null +++ b/src/kernel/modules/xam/xam_info.cc @@ -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 +} diff --git a/src/kernel/modules/xbdm/xbdm_table.h b/src/kernel/modules/xam/xam_info.h similarity index 63% rename from src/kernel/modules/xbdm/xbdm_table.h rename to src/kernel/modules/xam/xam_info.h index e1fd6227b..11693d97c 100644 --- a/src/kernel/modules/xbdm/xbdm_table.h +++ b/src/kernel/modules/xam/xam_info.h @@ -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 +#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_ diff --git a/src/kernel/modules/xam/xam_module.cc b/src/kernel/modules/xam/xam_module.cc index 721c76992..bd2cb9f11 100644 --- a/src/kernel/modules/xam/xam_module.cc +++ b/src/kernel/modules/xam/xam_module.cc @@ -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(new XamState(pal, memory, resolver)); + + // Register all exported functions. + RegisterInfoExports(resolver.get(), xam_state.get()); } XamModule::~XamModule() { diff --git a/src/kernel/modules/xam/xam_module.h b/src/kernel/modules/xam/xam_module.h index 8900315d5..d629f2ddb 100644 --- a/src/kernel/modules/xam/xam_module.h +++ b/src/kernel/modules/xam/xam_module.h @@ -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 resolver); virtual ~XamModule(); + +private: + auto_ptr xam_state; }; diff --git a/src/kernel/modules/xbdm/xbdm_module.cc b/src/kernel/modules/xam/xam_state.cc similarity index 57% rename from src/kernel/modules/xbdm/xbdm_module.cc rename to src/kernel/modules/xam/xam_state.cc index 14534c137..4d08bd389 100644 --- a/src/kernel/modules/xbdm/xbdm_module.cc +++ b/src/kernel/modules/xam/xam_state.cc @@ -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 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 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); } diff --git a/src/kernel/modules/xbdm/xbdm_module.h b/src/kernel/modules/xam/xam_state.h similarity index 62% rename from src/kernel/modules/xbdm/xbdm_module.h rename to src/kernel/modules/xam/xam_state.h index a17ed2a5a..23112f4cb 100644 --- a/src/kernel/modules/xbdm/xbdm_module.h +++ b/src/kernel/modules/xam/xam_state.h @@ -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 #include @@ -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 resolver); - virtual ~XbdmModule(); + XamState(xe_pal_ref pal, xe_memory_ref memory, + shared_ptr export_resolver); + ~XamState(); + + xe_pal_ref pal; + xe_memory_ref memory; + +private: + shared_ptr 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_ diff --git a/src/kernel/modules/xbdm/sources.gypi b/src/kernel/modules/xbdm/sources.gypi deleted file mode 100644 index 66f53e060..000000000 --- a/src/kernel/modules/xbdm/sources.gypi +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'xbdm_module.cc', - ], -} diff --git a/src/kernel/modules/xboxkrnl/module.cc b/src/kernel/modules/xboxkrnl/module.cc new file mode 100644 index 000000000..07599f944 --- /dev/null +++ b/src/kernel/modules/xboxkrnl/module.cc @@ -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 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(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() { +} diff --git a/src/kernel/modules/xboxkrnl/module.h b/src/kernel/modules/xboxkrnl/module.h new file mode 100644 index 000000000..acb0f207c --- /dev/null +++ b/src/kernel/modules/xboxkrnl/module.h @@ -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 +#include + +#include +#include + + +namespace xe { +namespace kernel { +namespace xboxkrnl { + +class KernelState; + + +class XboxkrnlModule : public KernelModule { +public: + XboxkrnlModule(xe_pal_ref pal, xe_memory_ref memory, + shared_ptr resolver); + virtual ~XboxkrnlModule(); + +private: + auto_ptr kernel_state; +}; + + +} // namespace xboxkrnl +} // namespace kernel +} // namespace xe + +#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_ diff --git a/src/kernel/modules/xboxkrnl/sources.gypi b/src/kernel/modules/xboxkrnl/sources.gypi index 7bdac658b..dde3ff855 100644 --- a/src/kernel/modules/xboxkrnl/sources.gypi +++ b/src/kernel/modules/xboxkrnl/sources.gypi @@ -2,6 +2,7 @@ { 'sources': [ 'kernel_state.cc', + 'module.cc', 'xboxkrnl_hal.cc', 'xboxkrnl_memory.cc', 'xboxkrnl_module.cc', diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl.h b/src/kernel/modules/xboxkrnl/xboxkrnl.h index 8fe2ef0b3..c6c3fd91e 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl.h +++ b/src/kernel/modules/xboxkrnl/xboxkrnl.h @@ -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 diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc b/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc index 2a4700d08..e10511fbc 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_module.cc @@ -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 -#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 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(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 } diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_module.h b/src/kernel/modules/xboxkrnl/xboxkrnl_module.h index acb0f207c..70c6f2bcb 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_module.h +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_module.h @@ -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 -#include - -#include -#include +#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 resolver); - virtual ~XboxkrnlModule(); - -private: - auto_ptr 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_ diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc b/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc index b57dba21a..b0bb3387b 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc @@ -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 diff --git a/src/kernel/modules/xboxkrnl/xboxkrnl_threading.cc b/src/kernel/modules/xboxkrnl/xboxkrnl_threading.cc index 35678a26d..287e791cb 100644 --- a/src/kernel/modules/xboxkrnl/xboxkrnl_threading.cc +++ b/src/kernel/modules/xboxkrnl/xboxkrnl_threading.cc @@ -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 } diff --git a/src/kernel/runtime.cc b/src/kernel/runtime.cc index 819ef1a77..be3a180fa 100644 --- a/src/kernel/runtime.cc +++ b/src/kernel/runtime.cc @@ -27,8 +27,6 @@ Runtime::Runtime(xe_pal_ref pal, shared_ptr 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_)); }