Kernel function work.
This commit is contained in:
parent
42009cda88
commit
23378443e8
2
TODO.md
2
TODO.md
|
@ -9,8 +9,6 @@ Ordered:
|
|||
```
|
||||
RtlInitializeCriticalSection/RtlInitializeCriticalSectionAndSpinCount
|
||||
RtlEnterCriticalSection/RtlLeaveCriticalSection
|
||||
XexCheckExecutablePrivilege
|
||||
XGetAVPack
|
||||
ExGetXConfigSetting
|
||||
KeTlsAlloc
|
||||
KeTlsSetValue
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
{
|
||||
'includes': [
|
||||
'xam/sources.gypi',
|
||||
'xbdm/sources.gypi',
|
||||
'xboxkrnl/sources.gypi',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'xam_info.cc',
|
||||
'xam_module.cc',
|
||||
'xam_state.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
|
||||
}
|
|
@ -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_
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -1,6 +0,0 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'xbdm_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<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() {
|
||||
}
|
|
@ -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_
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
'sources': [
|
||||
'kernel_state.cc',
|
||||
'module.cc',
|
||||
'xboxkrnl_hal.cc',
|
||||
'xboxkrnl_memory.cc',
|
||||
'xboxkrnl_module.cc',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue