[CPU] Move XEX2 code into XexModule class, autodetect XEX key
Code is mainly just copy/pasted from kernel/util/xex2.cc, I've tried fixing it up to work better in a class, but there's probably some things I missed. Also includes some minor improvements to the XEX loader, like being able to try both XEX keys (retail/devkit) automatically, and some fixes to how the base address is determined. (Previously there was code that would get base address from optional header, code that'd get it from xex_security_info, code that'd use a stored base address value... Now everything reads it from a single stored value instead, which is set either from the xex_security_info, or if it exists from the optional header instead. Maybe this can help improve compatibility with any weird XEX's that don't have a base address optional header?) Compressed XEX loader also has some extra checks to make sure the compressed data hash matches what's expected. Might increase loading times by a fraction, but could save reports from people unknowingly using corrupt XEXs. (still no checks for non-compressed data though, maybe need to compare data with xex_security_info->ImageHash?)
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/cpu/module.h"
|
||||
#include "xenia/kernel/util/xex2.h"
|
||||
#include "xenia/kernel/util/xex2_info.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -30,40 +29,73 @@ class Runtime;
|
||||
|
||||
class XexModule : public xe::cpu::Module {
|
||||
public:
|
||||
struct ImportLibraryFn {
|
||||
public:
|
||||
uint32_t Ordinal;
|
||||
uint32_t ValueAddress;
|
||||
uint32_t ThunkAddress;
|
||||
};
|
||||
struct ImportLibrary {
|
||||
public:
|
||||
std::string Name;
|
||||
uint32_t ID;
|
||||
xe_xex2_version_t Version;
|
||||
xe_xex2_version_t MinVersion;
|
||||
std::vector<ImportLibraryFn> Imports;
|
||||
};
|
||||
|
||||
XexModule(Processor* processor, kernel::KernelState* kernel_state);
|
||||
virtual ~XexModule();
|
||||
|
||||
xe_xex2_ref xex() const { return xex_; }
|
||||
bool loaded() const { return loaded_; }
|
||||
const xex2_header* xex_header() const {
|
||||
return reinterpret_cast<const xex2_header*>(xex_header_mem_.data());
|
||||
}
|
||||
const xex2_security_info* xex_security_info() const {
|
||||
return GetSecurityInfo(xex_header());
|
||||
return reinterpret_cast<const xex2_security_info*>(
|
||||
uintptr_t(xex_header()) + xex_header()->security_offset);
|
||||
}
|
||||
|
||||
const std::vector<ImportLibrary>* import_libraries() const {
|
||||
return &import_libs_;
|
||||
}
|
||||
|
||||
const xex2_opt_execution_info* opt_execution_info() const {
|
||||
xex2_opt_execution_info* retval = nullptr;
|
||||
GetOptHeader(XEX_HEADER_EXECUTION_INFO, &retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
const xex2_opt_file_format_info* opt_file_format_info() const {
|
||||
xex2_opt_file_format_info* retval = nullptr;
|
||||
GetOptHeader(XEX_HEADER_FILE_FORMAT_INFO, &retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
const uint32_t base_address() const { return base_address_; }
|
||||
|
||||
// Gets an optional header. Returns NULL if not found.
|
||||
// Special case: if key & 0xFF == 0x00, this function will return the value,
|
||||
// not a pointer! This assumes out_ptr points to uint32_t.
|
||||
static bool GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
|
||||
static bool GetOptHeader(const xex2_header* header, xex2_header_keys key,
|
||||
void** out_ptr);
|
||||
bool GetOptHeader(xe_xex2_header_keys key, void** out_ptr) const;
|
||||
bool GetOptHeader(xex2_header_keys key, void** out_ptr) const;
|
||||
|
||||
// Ultra-cool templated version
|
||||
// Special case: if key & 0xFF == 0x00, this function will return the value,
|
||||
// not a pointer! This assumes out_ptr points to uint32_t.
|
||||
template <typename T>
|
||||
static bool GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
|
||||
static bool GetOptHeader(const xex2_header* header, xex2_header_keys key,
|
||||
T* out_ptr) {
|
||||
return GetOptHeader(header, key, reinterpret_cast<void**>(out_ptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool GetOptHeader(xe_xex2_header_keys key, T* out_ptr) const {
|
||||
bool GetOptHeader(xex2_header_keys key, T* out_ptr) const {
|
||||
return GetOptHeader(key, reinterpret_cast<void**>(out_ptr));
|
||||
}
|
||||
|
||||
static const xex2_security_info* GetSecurityInfo(const xex2_header* header);
|
||||
const PESection* GetPESection(const char* name);
|
||||
|
||||
uint32_t GetProcAddress(uint16_t ordinal) const;
|
||||
uint32_t GetProcAddress(const char* name) const;
|
||||
@@ -71,7 +103,6 @@ class XexModule : public xe::cpu::Module {
|
||||
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);
|
||||
bool Unload();
|
||||
|
||||
const std::string& name() const override { return name_; }
|
||||
@@ -81,10 +112,31 @@ class XexModule : public xe::cpu::Module {
|
||||
|
||||
bool ContainsAddress(uint32_t address) override;
|
||||
|
||||
static void DecryptBuffer(const uint8_t* session_key,
|
||||
const uint8_t* input_buffer,
|
||||
const size_t input_size, uint8_t* output_buffer,
|
||||
const size_t output_size);
|
||||
|
||||
uint8_t* HostData() {
|
||||
if (base_address_)
|
||||
return memory()->TranslateVirtual(base_address_);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Function> CreateFunction(uint32_t address) override;
|
||||
|
||||
private:
|
||||
void DecryptSessionKey(bool useDevkit = false);
|
||||
|
||||
int ReadImage(const void* xex_addr, size_t xex_length);
|
||||
int ReadImageUncompressed(const void* xex_addr, size_t xex_length);
|
||||
int ReadImageBasicCompressed(const void* xex_addr, size_t xex_length);
|
||||
int ReadImageCompressed(const void* xex_addr, size_t xex_length);
|
||||
|
||||
int ReadPEHeaders();
|
||||
|
||||
bool SetupLibraryImports(const char* name,
|
||||
const xex2_import_library* library);
|
||||
bool FindSaveRest();
|
||||
@@ -93,13 +145,23 @@ class XexModule : public xe::cpu::Module {
|
||||
kernel::KernelState* kernel_state_ = nullptr;
|
||||
std::string name_;
|
||||
std::string path_;
|
||||
xe_xex2_ref xex_ = nullptr;
|
||||
std::vector<uint8_t> xex_header_mem_; // Holds the xex header
|
||||
bool loaded_ = false; // Loaded into memory?
|
||||
|
||||
// various optional headers
|
||||
std::vector<ImportLibrary>
|
||||
import_libs_; // pre-loaded import libraries for ease of use
|
||||
|
||||
std::vector<PESection> pe_sections_;
|
||||
|
||||
uint8_t session_key_[0x10];
|
||||
|
||||
bool loaded_ = false; // Loaded into memory?
|
||||
|
||||
uint32_t base_address_ = 0;
|
||||
uint32_t low_address_ = 0;
|
||||
uint32_t high_address_ = 0;
|
||||
|
||||
bool is_dev_kit_ = false;
|
||||
};
|
||||
|
||||
} // namespace cpu
|
||||
|
||||
Reference in New Issue
Block a user