Shuffle some code around.

This commit is contained in:
Dr. Chat 2015-06-29 00:48:24 -05:00
parent e44ac54eed
commit fe87c08424
5 changed files with 162 additions and 37 deletions

View File

@ -21,6 +21,8 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xmodule.h"
#include "third_party/crypto/rijndael-alg-fst.h"
namespace xe {
namespace cpu {
@ -45,6 +47,74 @@ XexModule::XexModule(Processor* processor, KernelState* kernel_state)
XexModule::~XexModule() { xe_xex2_dealloc(xex_); }
bool XexModule::GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
void** out_ptr) {
assert_not_null(header);
assert_not_null(out_ptr);
for (uint32_t i = 0; i < header->header_count; i++) {
const xex2_opt_header& opt_header = header->headers[i];
if (opt_header.key == key) {
// Match!
switch (key & 0xFF) {
case 0x00: {
// We just return the value of the optional header.
*out_ptr = (void*)((uint64_t)opt_header.value);
} break;
case 0x01: {
// Pointer to the value on the optional header.
*out_ptr = (void*)&opt_header.value;
} break;
default: {
// Pointer to the header.
*out_ptr = (void*)((uint8_t*)header + opt_header.offset);
} break;
}
return true;
}
}
return false;
}
bool XexModule::ApplyPatch(XexModule* module) {
auto header = reinterpret_cast<const xex2_header*>(module->xex_header());
if (!(header->module_flags &
(XEX_MODULE_MODULE_PATCH | XEX_MODULE_PATCH_DELTA |
XEX_MODULE_PATCH_FULL))) {
// This isn't a XEX2 patch.
return false;
}
// Grab the delta descriptor and get to work.
xex2_opt_delta_patch_descriptor* patch_header = nullptr;
GetOptHeader(header, XEX_HEADER_DELTA_PATCH_DESCRIPTOR,
(void**)&patch_header);
assert_not_null(patch_header);
// TODO!
return true;
}
bool XexModule::Load(const std::string& name, const std::string& path,
const void* xex_addr, size_t xex_length) {
// TODO: Move loading code here
xex_ = xe_xex2_load(memory(), xex_addr, xex_length, {0});
if (!xex_) {
return false;
}
// Make a copy of the xex header.
auto src_header = reinterpret_cast<const xex2_header*>(xex_addr);
xex_header_ = (xex2_header*)new char[src_header->header_size];
std::memcpy(xex_header_, src_header, src_header->header_size);
return Load(name, path, xex_);
}
bool XexModule::Load(const std::string& name, const std::string& path,
xe_xex2_ref xex) {
xex_ = xex;

View File

@ -14,6 +14,7 @@
#include "xenia/cpu/module.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/util/xex2_info.h"
namespace xe {
@ -32,7 +33,17 @@ class XexModule : public xe::cpu::Module {
virtual ~XexModule();
xe_xex2_ref xex() const { return xex_; }
const xex2_header* xex_header() const { return xex_header_; }
// Gets an optional header. Returns NULL if not found.
// Special case: if key & 0xFF == 0x00, this function will return the value,
// not a pointer!
static bool GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
void** out_ptr);
bool ApplyPatch(XexModule* module);
bool Load(const std::string& name, const std::string& path,
const void* xex_addr, size_t xex_length);
bool Load(const std::string& name, const std::string& path, xe_xex2_ref xex);
const std::string& name() const override { return name_; }
@ -50,6 +61,7 @@ class XexModule : public xe::cpu::Module {
std::string name_;
std::string path_;
xe_xex2_ref xex_;
xex2_header* xex_header_;
uint32_t base_address_;
uint32_t low_address_;

View File

@ -26,8 +26,6 @@ XUserModule::XUserModule(KernelState* kernel_state, const char* path)
XUserModule::~XUserModule() { xe_xex2_dealloc(xex_); }
xe_xex2_ref XUserModule::xex() { return xex_; }
const xe_xex2_header_t* XUserModule::xex_header() {
return xe_xex2_get_header(xex_);
}
@ -82,39 +80,31 @@ X_STATUS XUserModule::LoadFromFile(std::string path) {
X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
Processor* processor = kernel_state()->processor();
// Load the XEX into memory and decrypt.
xe_xex2_options_t xex_options = {0};
xex_ = xe_xex2_load(memory(), addr, length, xex_options);
if (!xex_) {
// Prepare the module for execution.
// Runtime takes ownership.
auto xex_module = std::make_unique<XexModule>(processor, kernel_state());
if (!xex_module->Load(name_, path_, addr, length)) {
return X_STATUS_UNSUCCESSFUL;
}
xex_ = xex_module->xex();
processor_module_ = xex_module.get();
if (!processor->AddModule(std::move(xex_module))) {
return X_STATUS_UNSUCCESSFUL;
}
// Copy the xex2 header into guest memory
const xex2_header* header = reinterpret_cast<const xex2_header*>(addr);
uint32_t header_size = xex2_get_header_size(header);
// Copy the xex2 header into guest memory.
const xex2_header* header = this->xex_module()->xex_header();
guest_xex_header_ = memory()->SystemHeapAlloc(header->header_size);
xex_header_ = memory()->SystemHeapAlloc(header_size);
uint8_t* xex_header_ptr = memory()->TranslateVirtual(xex_header_);
std::memcpy(xex_header_ptr, header, header_size);
uint8_t* xex_header_ptr = memory()->TranslateVirtual(guest_xex_header_);
std::memcpy(xex_header_ptr, header, header->header_size);
// Setup the loader data entry
auto ldr_data =
memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(hmodule_ptr_);
ldr_data->dll_base = 0; // GetProcAddress will read this.
ldr_data->xex_header_base = xex_header_;
// Prepare the module for execution.
// Runtime takes ownership.
auto xex_module = std::make_unique<XexModule>(processor, kernel_state());
if (!xex_module->Load(name_, path_, xex_)) {
return X_STATUS_UNSUCCESSFUL;
}
processor_module_ = xex_module.get();
if (!processor->AddModule(std::move(xex_module))) {
return X_STATUS_UNSUCCESSFUL;
}
ldr_data->xex_header_base = guest_xex_header_;
OnLoad();
@ -146,7 +136,7 @@ X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data,
X_STATUS XUserModule::GetOptHeader(xe_xex2_header_keys key,
uint32_t* out_header_guest_ptr) {
auto header = memory()->TranslateVirtual<xex2_header*>(xex_header_);
auto header = xex_module()->xex_header();
if (!header) {
return X_STATUS_UNSUCCESSFUL;
}

View File

@ -18,6 +18,10 @@
#include "xenia/xbox.h"
namespace xe {
namespace cpu {
class XexModule;
} // namespace cpu
namespace kernel {
class XUserModule : public XModule {
@ -25,8 +29,10 @@ class XUserModule : public XModule {
XUserModule(KernelState* kernel_state, const char* path);
~XUserModule() override;
xe_xex2_ref xex();
const xe_xex2_header_t* xex_header();
const xe::cpu::XexModule* xex_module() const {
return reinterpret_cast<xe::cpu::XexModule*>(processor_module_);
}
X_STATUS LoadFromFile(std::string path);
X_STATUS LoadFromMemory(const void* addr, const size_t length);
@ -48,7 +54,7 @@ class XUserModule : public XModule {
private:
xe_xex2_ref xex_;
uint32_t xex_header_;
uint32_t guest_xex_header_;
};
} // namespace kernel

View File

@ -470,9 +470,8 @@ typedef struct {
} xe_xex2_header_t;
namespace xe {
namespace kernel {
union xex2_version {
uint32_t value;
xe::be<uint32_t> value;
struct {
uint32_t major : 4;
uint32_t minor : 4;
@ -481,6 +480,22 @@ union xex2_version {
};
};
struct xex2_opt_delta_patch_descriptor {
xe::be<uint32_t> size; // 0x0
xex2_version target_version; // 0x4
xex2_version source_version; // 0x8
char digest_source[0x14]; // 0xC
char image_key_source[0x10]; // 0x20
xe::be<uint32_t> size_of_target_headers; // 0x30
xe::be<uint32_t> delta_headers_source_offset; // 0x34
xe::be<uint32_t> delta_headers_source_size; // 0x38
xe::be<uint32_t> delta_headers_target_offset; // 0x3C
xe::be<uint32_t> delta_image_source_offset; // 0x40
xe::be<uint32_t> delta_image_source_size; // 0x44
xe::be<uint32_t> delta_image_target_offset; // 0x48
};
static_assert_size(xex2_opt_delta_patch_descriptor, 0x4C);
struct xex2_opt_execution_info {
xe::be<uint32_t> media_id; // 0x0
xe::be<xex2_version> version; // 0x4
@ -492,32 +507,64 @@ struct xex2_opt_execution_info {
uint8_t disc_count; // 0x13
xe::be<uint32_t> savegame_id; // 0x14
};
static_assert_size(xex2_opt_execution_info, 0x18);
struct xex2_opt_import_libraries {
xe::be<uint32_t> section_size; // 0x0
xe::be<uint32_t> string_table_size; // 0x4
xe::be<uint32_t> library_count; // 0x8
char string_table[1]; // 0xC string_table_size bytes
};
struct xex2_import_library {
xe::be<uint32_t> size; // 0x0
char next_import_digest[0x14]; // 0x4
xe::be<uint32_t> id; // 0x18
xex2_version version; // 0x1C
xex2_version version_min; // 0x20
xe::be<uint16_t> name_index; // 0x24
xe::be<uint16_t> count; // 0x26
xe::be<uint32_t> import_table[1]; // 0x28
};
struct xex2_opt_header {
xe::be<uint32_t> key; // 0x0
union {
xe::be<uint32_t> value; // 0x4
xe::be<uint32_t> offset; // 0x8
xe::be<uint32_t> offset; // 0x4
};
};
struct xex2_header {
xe::be<uint32_t> magic; // 0x0 'XEX2'
xe::be<xe_xex2_module_flags> module_flags; // 0x4
xe::be<uint32_t> exe_offset; // 0x8
xe::be<uint32_t> header_size; // 0x8
xe::be<uint32_t> reserved; // 0xC
xe::be<uint32_t> certificate_offset; // 0x10
xe::be<uint32_t> security_offset; // 0x10
xe::be<uint32_t> header_count; // 0x14
xex2_opt_header headers[1]; // 0x18
};
struct xex2_loader_info {
xe::be<uint32_t> header_size;
xe::be<uint32_t> image_size;
struct xex2_security_info {
xe::be<uint32_t> header_size; // 0x0
xe::be<uint32_t> image_size; // 0x4
char rsa_signature[0x100]; // 0x8
xe::be<uint32_t> unk_108; // 0x108 unk length
xe::be<uint32_t> image_flags; // 0x10C
xe::be<uint32_t> load_address; // 0x110
char section_digest[0x14]; // 0x114
xe::be<uint32_t> import_table_count; // 0x128
char import_table_digest[0x14]; // 0x12C
char xgd2_media_id[0x10]; // 0x140
char aes_key[0x10]; // 0x150
xe::be<uint32_t> export_table; // 0x160
char header_digest[0x14]; // 0x164
xe::be<uint32_t> region; // 0x178
xe::be<uint32_t> allowed_media_types; // 0x17C
};
} // namespace kernel
static_assert_size(xex2_security_info, 0x180);
} // namespace xe
#endif // XENIA_KERNEL_XEX2_INFO_H_