From 0b6f7b5d7a1665727b3c587d20e367a82204367f Mon Sep 17 00:00:00 2001 From: ergo720 <45463469+ergo720@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:51:53 +0200 Subject: [PATCH] Added command line option to load xbox key data --- src/hw/cpu.cpp | 37 ++++++++-- src/main.cpp | 181 ++++++++++++++++++++++++++++--------------------- src/nxbx.hpp | 3 +- 3 files changed, 140 insertions(+), 81 deletions(-) diff --git a/src/hw/cpu.cpp b/src/hw/cpu.cpp index fcc6b4b..8c31383 100644 --- a/src/hw/cpu.cpp +++ b/src/hw/cpu.cpp @@ -65,7 +65,7 @@ cpu::init(const init_info_t &init_info) m_ramsize = init_info.m_console_type == console_t::xbox ? RAM_SIZE64 : RAM_SIZE128; // Load the nboxkrnl exe file - std::ifstream ifs(init_info.m_kernel.c_str(), std::ios_base::in | std::ios_base::binary); + std::ifstream ifs(init_info.m_kernel_path.c_str(), std::ios_base::in | std::ios_base::binary); if (!ifs.is_open()) { logger_en(error, "Could not open kernel file"); return false; @@ -90,7 +90,6 @@ cpu::init(const init_info_t &init_info) return false; } ifs.read(krnl_buff.get(), length); - ifs.close(); // Sanity checks on the kernel exe file PIMAGE_DOS_HEADER dosHeader = reinterpret_cast(krnl_buff.get()); @@ -193,8 +192,38 @@ cpu::init(const init_info_t &init_info) regs->ebp = 0x80400000; regs->eip = peHeader->OptionalHeader.ImageBase + peHeader->OptionalHeader.AddressOfEntryPoint; - // Pass eeprom and certificate keys on the stack (we use dummy all-zero keys) - mem_fill_block_virt(m_lc86cpu, 0x80400000, 16 * 2, 0); + // Pass eeprom and certificate keys on the stack + char keys[32] = { 0 }; + const auto open_keys = [&]() { + if (!init_info.m_keys_path.empty()) { + if (std::filesystem::path(init_info.m_keys_path).filename().compare("keys.bin") == 0) { + std::ifstream ifs(init_info.m_keys_path.c_str(), std::ios_base::in | std::ios_base::binary); + if (!ifs.is_open()) { + logger_en(info, "Could not open keys.bin file"); + return; + } + + ifs.seekg(0, ifs.end); + uint64_t length = ifs.tellg(); + ifs.seekg(0, ifs.beg); + if (length != 32) { + logger_en(info, "Unexpected size of keys.bin file, should be 32 bytes (it was %" PRIu64 ")", length); + return; + } + + ifs.read(keys, 32); + if (!ifs.good()) { + logger_en(info, "Failed to read keys.bin file"); + return; + } + return; + } + logger_en(info, "Could not find keys.bin file"); + } + }; + + open_keys(); + mem_write_block_virt(m_lc86cpu, 0x80400000, 32, keys); return true; } diff --git a/src/main.cpp b/src/main.cpp index 96f0eda..ee0c49d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,13 +13,15 @@ static void print_help() { static const char *help = - "usage: [options] \n\ -options: \n\ --k Path to nboxkrnl (xbox kernel) to run\n\ --s Specify assembly syntax (default is AT&T)\n\ --c Specify the console type to emulate (default is xbox)\n\ --d Start with debugger\n\ --h Print this message"; + "usage: nxbx [options]\n\ +options:\n\ +-i Path to the XBE (xbox executable) or XISO (xbox disk image) to run\n\ +-keys Path of xbox keys.bin file\n\ +-k Path to nboxkrnl (xbox kernel) to run\n\ +-s Specify assembly syntax (default is AT&T)\n\ +-c Specify the console type to emulate (default is xbox)\n\ +-d Start with debugger\n\ +-h Print this message"; logger("%s", help); } @@ -28,13 +30,28 @@ int main(int argc, char **argv) { init_info_t init_info; + init_info.m_keys_path = ""; init_info.m_syntax = disas_syntax::att; init_info.m_console_type = console_t::xbox; init_info.m_use_dbg = 0; char option = ' '; + const auto print_unk_opt = [](std::string_view arg_str) { + logger("Unknown option %s", arg_str.data()); + print_help(); + return 0; + }; + + const auto check_missing_arg = [argc, argv](int &idx, const char *opt) { + if (++idx == argc || argv[idx][0] == '-') { + logger("Missing argument for option \"%s\"", opt); + return true; + } + return false; + }; + /* parameter parsing */ - if (argc < 2) { + if (argc < 3) { print_help(); return 0; } @@ -43,91 +60,103 @@ main(int argc, char **argv) try { option = ' '; std::string arg_str(argv[idx]); - if (arg_str.size() == 2 && arg_str.front() == '-') { - switch (option = arg_str.at(1)) - { - case 'k': - if (++idx == argc || argv[idx][0] == '-') { - logger("Missing argument for option \"%c\"", option); - return 0; - } - init_info.m_kernel = argv[idx]; - break; + if (arg_str.front() == '-') { + if (arg_str.size() == 2) { - case 's': - if (++idx == argc || argv[idx][0] == '-') { - logger("Missing argument for option \"s\""); - return 0; - } - switch (init_info.m_syntax = static_cast(std::stoul(std::string(argv[idx]), nullptr, 0))) + // Process single-letter options + switch (option = arg_str.at(1)) { - case disas_syntax::att: - case disas_syntax::masm: - case disas_syntax::intel: + case 'i': + if (check_missing_arg(idx, "i")) { + return 0; + } + if (!nxbx::validate_input_file(init_info, argv[idx])) { + return 1; + } + init_info.m_input_path = argv[idx]; break; - default: - logger("Unknown syntax specified by option \"%c\"", option); - return 0; - } - break; + case 'k': + if (check_missing_arg(idx, "k")) { + return 0; + } + init_info.m_kernel_path = argv[idx]; + break; - case 'c': { - if (++idx == argc || argv[idx][0] == '-') { - logger("Missing argument for option \"%c\"", option); - return 0; - } - std::string console = argv[idx]; - if (console == nxbx::console_to_string(console_t::xbox)) { - init_info.m_console_type = console_t::xbox; - } - else if (console == nxbx::console_to_string(console_t::chihiro)) { - init_info.m_console_type = console_t::chihiro; - } - else if (console == nxbx::console_to_string(console_t::devkit)) { - init_info.m_console_type = console_t::devkit; - } - else { - switch (init_info.m_console_type = static_cast(std::stoul(console, nullptr, 0))) + case 's': + if (check_missing_arg(idx, "s")) { + return 0; + } + switch (init_info.m_syntax = static_cast(std::stoul(std::string(argv[idx]), nullptr, 0))) { - case console_t::xbox: - case console_t::chihiro: - case console_t::devkit: + case disas_syntax::att: + case disas_syntax::masm: + case disas_syntax::intel: break; default: - logger("Unknown console type specified by option \"%c\"", option); + logger("Unknown syntax specified by option \"%c\"", option); return 0; } - } - } - break; + break; - case 'd': - init_info.m_use_dbg = 1; + case 'c': { + if (check_missing_arg(idx, "c")) { + return 0; + } + std::string console = argv[idx]; + if (console == nxbx::console_to_string(console_t::xbox)) { + init_info.m_console_type = console_t::xbox; + } + else if (console == nxbx::console_to_string(console_t::chihiro)) { + init_info.m_console_type = console_t::chihiro; + } + else if (console == nxbx::console_to_string(console_t::devkit)) { + init_info.m_console_type = console_t::devkit; + } + else { + switch (init_info.m_console_type = static_cast(std::stoul(console, nullptr, 0))) + { + case console_t::xbox: + case console_t::chihiro: + case console_t::devkit: + break; + + default: + logger("Unknown console type specified by option \"%c\"", option); + return 0; + } + } + } break; - case 'h': - print_help(); - return 0; + case 'd': + init_info.m_use_dbg = 1; + break; + + case 'h': + print_help(); + return 0; - default: - logger("Unknown option %s", arg_str.c_str()); - print_help(); - return 0; + default: + return print_unk_opt(arg_str); + } } - } - else if ((idx + 1) == argc) { - if (!nxbx::validate_input_file(init_info, arg_str)) { - return 1; + else { + // Process multi-letter options + if (arg_str.compare("-keys") == 0) { + if (check_missing_arg(idx, arg_str.c_str())) { + return 0; + } + init_info.m_keys_path = argv[idx]; + } + else { + return print_unk_opt(arg_str); + } } - init_info.m_input_path = std::move(arg_str); - break; } else { - logger("Unknown option %s", arg_str.c_str()); - print_help(); - return 0; + return print_unk_opt(arg_str); } } /* handle possible exceptions thrown by std::stoul */ @@ -149,7 +178,7 @@ main(int argc, char **argv) } init_info.m_nxbx_path = nxbx::get_path(); - if (init_info.m_kernel.empty()) { + if (init_info.m_kernel_path.empty()) { // Attempt to find nboxkrnl in the current directory of nxbx std::filesystem::path curr_dir = init_info.m_nxbx_path; curr_dir = curr_dir.remove_filename(); @@ -160,7 +189,7 @@ main(int argc, char **argv) logger("Unable to find \"nboxkrnl.exe\" in the current working directory"); return 1; } - init_info.m_kernel = curr_dir.string(); + init_info.m_kernel_path = curr_dir.string(); } if (nxbx::init_settings(init_info) == false) { diff --git a/src/nxbx.hpp b/src/nxbx.hpp index cf750f5..e15b93f 100644 --- a/src/nxbx.hpp +++ b/src/nxbx.hpp @@ -33,9 +33,10 @@ enum class input_t : uint32_t { }; struct init_info_t { - std::string m_kernel; + std::string m_kernel_path; std::string m_nxbx_path; std::string m_input_path; + std::string m_keys_path; disas_syntax m_syntax; uint32_t m_use_dbg; console_t m_console_type;