├── tests ├── clean.bat ├── decode.ini └── test.bat ├── inc ├── XbBiosTool.rc ├── resource.h ├── tea.h ├── sha1.h ├── str_util.h ├── Mcpx.h ├── rc4.h ├── mem_tracking.h ├── version.h ├── loadini.h ├── file.h ├── rsa.h ├── util.h ├── cli_tbl.h ├── XcodeDecoder.h ├── XcodeInterp.h ├── nt_headers.h ├── XbTool.h ├── bldr.h ├── help_strings.h ├── Bios.h └── lzx.h ├── .gitignore ├── boot_state_diagram_mcpx_rev0.md ├── boot_state_diagram_mcpx_rev1.md ├── boot_state_diagram_fbl.md ├── decode_settings2.ini ├── decode_settings3.ini ├── decode_settings.ini ├── boot_state_diagram_2bl.md ├── src ├── tea.c ├── str_util.c ├── rc4.c ├── rsa.c ├── mem_tracking.c ├── loadini.c ├── file.c ├── Mcpx.c ├── XcodeInterp.cpp ├── util.c ├── cli_tbl.cpp ├── nt_headers.c └── sha1.c ├── vc ├── XboxBiosTools.sln ├── XboxBiosTools.vcxproj.user ├── XboxBiosTools.vcxproj.filters └── XboxBiosTools.vcxproj ├── notes.txt ├── DecodeSettings.md └── README.md /tests/clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | del /q *.bin 2>nul 4 | del /q *.img 2>nul -------------------------------------------------------------------------------- /inc/XbBiosTool.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tommojphillips/XboxBiosTool/HEAD/inc/XbBiosTool.rc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .vs 3 | *.exe 4 | *.pdb 5 | *.bin 6 | *.img 7 | *.zip 8 | *.com 9 | *.obj 10 | *.log 11 | *.asm 12 | xcodes.txt 13 | decode2.ini 14 | objd/ 15 | obj/ 16 | .vscode/ 17 | *.lastcodeanalysissucceeded 18 | XbBiosTool.vcxproj.filters 19 | XbBiosTool.vcxproj.user 20 | /tests/xcodes_no_branching.txt 21 | -------------------------------------------------------------------------------- /inc/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by XbBiosTool.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /inc/tea.h: -------------------------------------------------------------------------------- 1 | // tea.h 2 | // https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm 3 | // 4 | // Author: tommojphillips 5 | // GitHub: https:\\github.com\tommojphillips 6 | #ifndef _TEA_H 7 | #define _TEA_H 8 | 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void tea_encrypt(uint32_t v[2], const uint32_t k[4]); 16 | void tea_decrypt(uint32_t v[2], const uint32_t k[4]); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | #endif // !_TEA_H 22 | -------------------------------------------------------------------------------- /boot_state_diagram_mcpx_rev0.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | graph TD; 3 | 4 | PWR_ON[Power On]-->SB_XCODE_INTERP 5 | SB_XCODE_INTERP[Run Xcode Interpreter]-->SB_DECRYPT_2BL 6 | 7 | SB_DECRYPT_2BL[RC4 Decrypt 2BL]-->SB_LOAD_STORED_HASH 8 | SB_LOAD_STORED_HASH[Load Expected Hash]-->SB_IS_2BL_VALID{Does the hash match?} 9 | SB_IS_2BL_VALID-->|Yes|2BL_ENTRY 10 | SB_IS_2BL_VALID-->|No|SB_SHUTDOWN 11 | 12 | 2BL_ENTRY[Jump to 2BL Entry] 13 | SB_SHUTDOWN[SB Shutdown] 14 | ``` 15 | 16 | - [MCPX V1.1](boot_state_diagram_mcpx_rev1.md) 17 | - [FBL](boot_state_diagram_fbl.md) 18 | - [2BL](boot_state_diagram_2bl.md) 19 | -------------------------------------------------------------------------------- /boot_state_diagram_mcpx_rev1.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | graph TD; 3 | 4 | PWR_ON[Power On]-->SB_XCODE_INTERP 5 | SB_XCODE_INTERP[Run Xcode Interpreter]-->SB_HASH_FBL 6 | SB_HASH_FBL[TEA Hash FBL]-->SB_LOAD_STORED_HASH 7 | SB_LOAD_STORED_HASH[Load Expected Hash]-->SB_DOES_HASH_MATCH{Does the hash match?} 8 | 9 | SB_DOES_HASH_MATCH-->|Yes|FBL_ENTRY 10 | SB_DOES_HASH_MATCH-->|No|SB_SHUTDOWN 11 | 12 | SB_SHUTDOWN[SB Shutdown] 13 | FBL_ENTRY[Jump to FBL Entry] 14 | 15 | ``` 16 | 17 | - [MCPX V1.0](boot_state_diagram_mcpx_rev0.md) 18 | - [FBL](boot_state_diagram_fbl.md) 19 | - [2BL](boot_state_diagram_2bl.md) 20 | -------------------------------------------------------------------------------- /boot_state_diagram_fbl.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | graph TD; 3 | 4 | FBL_ENTRY[FBL Entry]-->DECRYPT_PK 5 | DECRYPT_PK[RC4 Decrypt Public Key]-->HASH_XBOX_ROM 6 | HASH_XBOX_ROM[SHA1 Hash Xbox ROM]-->PK_SIGNATURE 7 | 8 | PK_SIGNATURE[Verify The Xbox ROM Signature]-->IS_SIGNATURE_VALID{Is The Signature Valid?} 9 | IS_SIGNATURE_VALID-->|Yes|BLD_2BL_KEY 10 | IS_SIGNATURE_VALID-->|No|SHUTDOWN 11 | 12 | BLD_2BL_KEY[Build 2BL RC4 Key]-->COPY_2BL 13 | COPY_2BL[Copy 2BL into RAM]-->DECRYPT_2BL 14 | DECRYPT_2BL[RC4 Decrypt 2BL]-->2BL_ENTRY 15 | 16 | SHUTDOWN[FBL Shutdown] 17 | 2BL_ENTRY[Jump to 2BL Entry] 18 | 19 | ``` 20 | 21 | - [MCPX V1.0](boot_state_diagram_mcpx_rev0.md) 22 | - [MCPX V1.1](boot_state_diagram_mcpx_rev1.md) 23 | - [2BL](boot_state_diagram_2bl.md) 24 | -------------------------------------------------------------------------------- /decode_settings2.ini: -------------------------------------------------------------------------------- 1 | ; xcode decoder settings ( .ini ) 2 | ; This file is used to configure the xcode decoder. 3 | ; ------------------------------------------------- 4 | 5 | format_str = 'xc_{op} {addr} {data} {comment}' 6 | jmp_str = '{label}' 7 | no_operand_str = '' 8 | num_str = '0{hex8}h' 9 | comment_prefix = '; ' 10 | 11 | label_on_new_line=true 12 | pad=false 13 | 14 | xc_reserved = 'nop' 15 | xc_nop_80 = 'nop_80' 16 | xc_nop_f5 = 'nop_f5' 17 | xc_accum = 'accum' 18 | xc_mem_write = 'mem_write' 19 | xc_mem_read = 'mem_read' 20 | xc_io_write = 'io_write' 21 | xc_io_read = 'io_read' 22 | xc_pci_write = 'pci_write' 23 | xc_pci_read = 'pci_read' 24 | xc_jne = 'jne' 25 | xc_jmp = 'jmp' 26 | xc_and_or = 'and_or' 27 | xc_result = 'result' 28 | xc_exit = 'exit' 29 | -------------------------------------------------------------------------------- /decode_settings3.ini: -------------------------------------------------------------------------------- 1 | ; decode settings 2 | ; This file is used to configure the xcode decoder. 3 | ; ------------------------------------------------- 4 | 5 | format_str = 'xcode<{op}, {addr}, {data}> {comment}' 6 | jmp_str = '{label}-$-4' 7 | no_operand_str = '0h' 8 | num_str = '0{hex}h' 9 | comment_prefix = '; ' 10 | 11 | label_on_new_line=true 12 | pad=false 13 | 14 | xc_reserved = 'REV' 15 | xc_nop_80 = 'UNUSED1' 16 | xc_nop_f5 = 'UNUSED2' 17 | xc_mem_write = 'POKE' 18 | xc_mem_read = 'PEEK' 19 | xc_io_write = 'OUT_BYTE' 20 | xc_io_read = 'IN_BYTE' 21 | xc_pci_write = 'PCI_CFG_WRITE' 22 | xc_pci_read = 'PCI_CFG_READ' 23 | xc_jne = 'COMPARE_RESULT_JNE' 24 | xc_jmp = 'XJMP' 25 | xc_accum = 'ACCUM' 26 | xc_and_or = 'RMW_RESULT' 27 | xc_result = 'USE_RESULT_AS_DATA' 28 | xc_exit = 'QUIT' -------------------------------------------------------------------------------- /decode_settings.ini: -------------------------------------------------------------------------------- 1 | ; decode_settings.ini: 2 | ; This file is used to configure the xcode decoder. 3 | ; ------------------------------------------------- 4 | 5 | format_str = 'xcode<{op}, {addr}, {data}> {comment}' 6 | jmp_str = '{label}-$-4' 7 | no_operand_str = '0h' 8 | num_str = '0{hex8}h' 9 | comment_prefix = '; ' 10 | 11 | label_on_new_line=true 12 | pad=true 13 | 14 | xc_reserved = 'xc_nop' 15 | xc_nop_80 = 'xc_nop_80' 16 | xc_nop_f5 = 'xc_nop_f4' 17 | xc_mem_write = 'xc_mem_write' 18 | xc_mem_read = 'xc_mem_read' 19 | xc_io_write = 'xc_out_byte' 20 | xc_io_read = 'xc_in_byte' 21 | xc_pci_write = 'xc_pci_write' 22 | xc_pci_read = 'xc_pci_read' 23 | xc_jne = 'xc_jne' 24 | xc_jmp = 'xc_jmp' 25 | xc_accum = 'xc_accum' 26 | xc_and_or = 'xc_and_or' 27 | xc_result = 'xc_result' 28 | xc_exit = 'xc_quit' 29 | -------------------------------------------------------------------------------- /boot_state_diagram_2bl.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | flowchart 3 | 4 | 2BL_ENTRY[2BL Entry]-->2BL_DISABLE_SB 5 | 2BL_DISABLE_SB[Disable SB ROM]-->2BL_HASH_ROM 6 | 7 | 2BL_HASH_ROM[SHA1 Hash Xbox ROM]-->2BL_IS_HASH_CORRECT{Is the hash correct?} 8 | 2BL_IS_HASH_CORRECT-->|Yes|2BL_COPY_KERNEL 9 | 2BL_IS_HASH_CORRECT-->|No|2BL_SHUTDOWN 10 | 11 | 2BL_COPY_KERNEL[Copy Kernel Image into RAM]-->2BL_DECRYPT_KERNEL 12 | 2BL_DECRYPT_KERNEL[RC4 Decrypt Kernel Image]-->2BL_DECOMPRESS_KERNEL 13 | 2BL_DECOMPRESS_KERNEL[LZX Decompress Kernel Image]-->2BL_FIND_KERNEL_ENTRY 14 | 15 | 2BL_FIND_KERNEL_ENTRY[Locate Kernel Entry]-->2BL_IS_KERNEL_ENTRY_FOUND{Kernel Entry Found?} 16 | 2BL_IS_KERNEL_ENTRY_FOUND-->|Yes|KERNEL_ENTRY 17 | 2BL_IS_KERNEL_ENTRY_FOUND-->|No|2BL_SHUTDOWN 18 | 19 | 2BL_SHUTDOWN[2BL Shutdown] 20 | KERNEL_ENTRY[Jump to Kernel Entry] 21 | 22 | ``` 23 | 24 | - [MCPX V1.0](boot_state_diagram_mcpx_rev0.md) 25 | - [MCPX V1.1](boot_state_diagram_mcpx_rev1.md) 26 | - [FBL](boot_state_diagram_fbl.md) 27 | -------------------------------------------------------------------------------- /src/tea.c: -------------------------------------------------------------------------------- 1 | // tea.c 2 | // https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm 3 | // 4 | // Author: tommojphillips 5 | // GitHub: https:\\github.com\tommojphillips 6 | 7 | #include 8 | 9 | #include "tea.h" 10 | 11 | #define TEA_DELTA 0x9E3779B9 12 | #define TEA_DECRYPT_SUM 0xC6EF3720 13 | 14 | void tea_encrypt(uint32_t v[2], const uint32_t k[4]) { 15 | uint32_t sum = 0; 16 | uint32_t h0 = v[0], h1 = v[1]; 17 | uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; 18 | 19 | for (uint32_t i = 0; i < 32; ++i) { 20 | sum += TEA_DELTA; 21 | h0 += ((h1 << 4) + k0) ^ (h1 + sum) ^ ((h1 >> 5) + k1); 22 | h1 += ((h0 << 4) + k2) ^ (h0 + sum) ^ ((h0 >> 5) + k3); 23 | } 24 | 25 | v[0] = h0; 26 | v[1] = h1; 27 | } 28 | 29 | void tea_decrypt(uint32_t v[2], const uint32_t k[4]) { 30 | uint32_t sum = TEA_DECRYPT_SUM; 31 | uint32_t h0 = v[0], h1 = v[1]; 32 | uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; 33 | 34 | for (uint32_t i = 0; i < 32; ++i) { 35 | h1 -= ((h0 << 4) + k2) ^ (h0 + sum) ^ ((h0 >> 5) + k3); 36 | h0 -= ((h1 << 4) + k0) ^ (h1 + sum) ^ ((h1 >> 5) + k1); 37 | sum -= TEA_DELTA; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /inc/sha1.h: -------------------------------------------------------------------------------- 1 | // sha1.h 2 | 3 | // GitHub: https://github.com/XboxDev/xbedump 4 | // 5 | // credit to XboxDev, and the authors of xbedump 6 | // Michael Steil (mist64) 7 | // Franz 8 | 9 | #ifndef SHA1_H 10 | #define SHA1_H 11 | 12 | #include 13 | 14 | #define SHA1_DIGEST_LEN 20 15 | 16 | /* error codes */ 17 | #define SHA_STATUS_SUCCESS 0 18 | #define SHA_STATUS_STATE_NULL 1 19 | #define SHA_STATUS_INPUT_TOO_LONG 2 20 | #define SHA_STATUS_STATE_ERROR 3 21 | 22 | // SHA-1 context 23 | typedef struct _SHA1Context { 24 | uint32_t intermediate_hash[SHA1_DIGEST_LEN / 4U]; // Digest 25 | 26 | uint32_t length_low; // Message length in bits 27 | uint32_t length_high; 28 | 29 | short block_index; // Index into message block array 30 | uint8_t block[64]; // 512-bit message blocks 31 | 32 | int computed; // Is the digest computed? 33 | int corrupted; // Is the message digest corrupted? 34 | } SHA1Context; 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | int SHA1Reset(SHA1Context* context); 41 | int SHA1Input(SHA1Context* context, const uint8_t* message, uint32_t len); 42 | int SHA1Result(SHA1Context* context, uint8_t digest[SHA1_DIGEST_LEN]); 43 | 44 | #ifdef __cplusplus 45 | }; 46 | #endif 47 | 48 | #endif // _SHA1_H_ 49 | -------------------------------------------------------------------------------- /inc/str_util.h: -------------------------------------------------------------------------------- 1 | // str_util.h: implements various utility functions for manipulating strings. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef STR_UTIL_H 23 | #define STR_UTIL_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | // trim left side of string. 30 | void ltrim(char** str); 31 | 32 | // trim right side of string. 33 | void rtrim(char** str); 34 | 35 | // pad right side of string. 36 | void rpad(char* str, const int buffSize, const char pad); 37 | 38 | #ifdef __cplusplus 39 | }; 40 | #endif 41 | 42 | #endif // !STR_UTIL_H 43 | -------------------------------------------------------------------------------- /tests/decode.ini: -------------------------------------------------------------------------------- 1 | ; decode settings 2 | ; This file is used to configure the xcode decoder. 3 | ; Used to define decode format for usage in the x86 assembler. 4 | ;------------------------------------------------------------------------------ 5 | 6 | ; format xcode string. 7 | ; {offset} the offset string 8 | ; {op} the opcode string 9 | ; {addr} the address string 10 | ; {data} the data string 11 | ; {comment} the comment string 12 | format_str=xcode<{op}, {addr}, {data}> {comment} 13 | 14 | ; jump xcodes string 15 | ; {label} the name of the label 16 | ; {offset} the offset of the label 17 | jmp_str={label}-$-4 18 | 19 | ; no operand string. use this for xcodes that dont use addr and/or data. 20 | no_operand_str=0h 21 | 22 | ; number string, the number format. 23 | ; {num} in digits 24 | ; {hex} in hex 25 | num_str=0{hex}h 26 | 27 | ; label on new line 28 | ; true label on new line 29 | ; false label on same line 30 | label_on_new_line=true 31 | 32 | ; comment prefix 33 | comment_prefix='; ' 34 | 35 | ; OPCODES 36 | ; xcode opcode strings 37 | xc_nop_80=UNUSED1 38 | xc_nop_f5=UNUSED2 39 | xc_mem_write=POKE 40 | xc_mem_read=PEEK 41 | xc_io_write=OUT_BYTE 42 | xc_io_read=IN_BYTE 43 | xc_pci_write=PCI_CFG_WRITE 44 | xc_pci_read=PCI_CFG_READ 45 | xc_jne=COMPARE_RESULT_JNE 46 | xc_jmp=XJMP 47 | xc_accum=ACCUM 48 | xc_and_or=RMW_RESULT 49 | xc_result=USE_RESULT_AS_DATA 50 | xc_exit=QUIT -------------------------------------------------------------------------------- /inc/Mcpx.h: -------------------------------------------------------------------------------- 1 | // Mcpx.h: 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef MCPX_ROM_H 23 | #define MCPX_ROM_H 24 | 25 | #include 26 | 27 | #define MCPX_BLOCK_SIZE 512 28 | 29 | typedef enum { 30 | MCPX_REV_UNK, 31 | MCPX_REV_0, 32 | MCPX_REV_1, 33 | } MCPX_REV; 34 | 35 | typedef struct { 36 | uint8_t* data; 37 | uint8_t* sbkey; 38 | MCPX_REV rev; 39 | uint8_t hash[20]; 40 | } MCPX; 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | void mcpx_init(MCPX* mcpx); 47 | void mcpx_free(MCPX* mcpx); 48 | int mcpx_load(MCPX* mcpx, uint8_t* data); 49 | 50 | #ifdef __cplusplus 51 | }; 52 | #endif 53 | 54 | #endif // !MCPX_ROM_H 55 | -------------------------------------------------------------------------------- /inc/rc4.h: -------------------------------------------------------------------------------- 1 | // rc4.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef RC4_H 23 | #define RC4_H 24 | 25 | #include 26 | 27 | typedef struct _RC4_CONTEXT { 28 | uint8_t k; 29 | uint8_t j; 30 | uint8_t t; 31 | uint8_t s[256]; 32 | } RC4_CONTEXT; 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | void rc4_key(RC4_CONTEXT* context, const uint8_t* key, const size_t len); 39 | void rc4(RC4_CONTEXT* context, uint8_t* data, const size_t size); 40 | void rc4_symmetric_enc_dec(uint8_t* data, const size_t size, const uint8_t* key, const size_t key_len); 41 | 42 | #ifdef __cplusplus 43 | }; 44 | #endif 45 | 46 | #endif // _RC4_H 47 | -------------------------------------------------------------------------------- /inc/mem_tracking.h: -------------------------------------------------------------------------------- 1 | // mem_tracking.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. */ 17 | 18 | // Author: tommojphillips 19 | // GitHub: https:\\github.com\tommojphillips 20 | 21 | #ifndef MEM_TRACKING_H 22 | #define MEM_TRACKING_H 23 | #ifdef MEM_TRACKING 24 | 25 | #include 26 | 27 | extern int memtrack_allocations; 28 | extern long memtrack_allocatedBytes; 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | void* memtrack_malloc(size_t size); 35 | void* memtrack_realloc(void* ptr, size_t size); 36 | void* memtrack_calloc(size_t count, size_t size); 37 | void memtrack_free(void* ptr); 38 | int memtrack_report(); 39 | 40 | #ifdef __cplusplus 41 | }; 42 | #endif 43 | 44 | #define malloc(size) memtrack_malloc(size) 45 | #define free(ptr) memtrack_free(ptr) 46 | #define realloc(ptr, size) memtrack_realloc(ptr, size) 47 | #define calloc(count, size) memtrack_calloc(count, size) 48 | 49 | #endif // !MEM_TRACKING 50 | #endif // !MEM_TRACKING_H 51 | -------------------------------------------------------------------------------- /vc/XboxBiosTools.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34728.123 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XboxBiosTools", "XboxBiosTools.vcxproj", "{7845CC9D-7D7E-4C08-BCF9-7033B337BA91}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug_NO_MEM_TRACKING|x86 = Debug_NO_MEM_TRACKING|x86 11 | Debug|x86 = Debug|x86 12 | Release_NO_MEM_TRACKING|x86 = Release_NO_MEM_TRACKING|x86 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Debug_NO_MEM_TRACKING|x86.ActiveCfg = Debug_NO_MEM_TRACKING|Win32 17 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Debug_NO_MEM_TRACKING|x86.Build.0 = Debug_NO_MEM_TRACKING|Win32 18 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Debug|x86.ActiveCfg = Debug|Win32 19 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Debug|x86.Build.0 = Debug|Win32 20 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Release_NO_MEM_TRACKING|x86.ActiveCfg = Release_NO_MEM_TRACKING|Win32 21 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Release_NO_MEM_TRACKING|x86.Build.0 = Release_NO_MEM_TRACKING|Win32 22 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Release|x86.ActiveCfg = Release|Win32 23 | {7845CC9D-7D7E-4C08-BCF9-7033B337BA91}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D4771D08-046A-4CCE-A096-CF90E5AC47A6} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /inc/version.h: -------------------------------------------------------------------------------- 1 | // version.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XB_BIOS_TOOL_VERSION_H 23 | #define XB_BIOS_TOOL_VERSION_H 24 | 25 | #define STRIFY(x) #x 26 | #define STR(x) STRIFY(x) 27 | 28 | #define XB_BIOS_TOOL_VER_MAJOR 0 29 | #define XB_BIOS_TOOL_VER_MINOR 2 30 | #define XB_BIOS_TOOL_VER_PATCH 0 31 | #define XB_BIOS_TOOL_VER_BUILD 0 32 | 33 | #define XB_BIOS_TOOL_AUTHOR_STR "tommojphillips" 34 | 35 | #define XB_BIOS_TOOL_VER \ 36 | XB_BIOS_TOOL_VER_MAJOR, \ 37 | XB_BIOS_TOOL_VER_MINOR, \ 38 | XB_BIOS_TOOL_VER_PATCH, \ 39 | XB_BIOS_TOOL_VER_BUILD 40 | 41 | #define XB_BIOS_TOOL_VER_STR \ 42 | STR(XB_BIOS_TOOL_VER_MAJOR) "." \ 43 | STR(XB_BIOS_TOOL_VER_MINOR) "." \ 44 | STR(XB_BIOS_TOOL_VER_PATCH) "." \ 45 | STR(XB_BIOS_TOOL_VER_BUILD) 46 | 47 | #define XB_BIOS_TOOL_NAME_STR "Xbox Bios Tools v" \ 48 | XB_BIOS_TOOL_VER_STR " Copyright (c) 2024 " \ 49 | XB_BIOS_TOOL_AUTHOR_STR 50 | 51 | #endif // !XB_BIOS_TOOL_VERSION_H 52 | -------------------------------------------------------------------------------- /src/str_util.c: -------------------------------------------------------------------------------- 1 | // str_util.c: implements various utility functions for manipulating strings. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | 25 | // user incl 26 | #include "str_util.h" 27 | 28 | void ltrim(char** str) 29 | { 30 | if (str == NULL || *str == NULL) 31 | return; 32 | 33 | while ((*str)[0] == ' ' || (*str)[0] == '\t' || (*str)[0] == '\n') { 34 | (*str)++; 35 | } 36 | } 37 | 38 | void rtrim(char** str) 39 | { 40 | if (str == NULL || *str == NULL) 41 | return; 42 | 43 | int len = strlen(*str); 44 | if (len == 0) 45 | return; 46 | 47 | char* end = *str + len - 1; 48 | while (end > *str && (end[0] == ' ' || end[0] == '\t' || end[0] == '\n')) { 49 | end--; 50 | } 51 | *(end + 1) = '\0'; 52 | } 53 | 54 | void rpad(char* str, const int buffSize, const char pad) 55 | { 56 | if (str == NULL) 57 | return; 58 | 59 | int slen = strlen(str); 60 | memset(str + slen, pad, buffSize - slen - 1); 61 | str[buffSize - 1] = '\0'; 62 | } 63 | -------------------------------------------------------------------------------- /vc/XboxBiosTools.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -extr bios\og_1_0\3944.bin -mcpx mcpx\mcpx_1.0.bin -krnl krnl.bin 5 | WindowsLocalDebugger 6 | $(SolutionDir)..\tests 7 | $(TargetPath) 8 | 9 | 10 | -extr bios\og_1_0\3944.bin -mcpx mcpx\mcpx_1.0.bin -krnl krnl.bin 11 | WindowsLocalDebugger 12 | $(SolutionDir)..\tests 13 | $(TargetPath) 14 | 15 | 16 | -extr bios\og_1_0\3944.bin -mcpx mcpx\mcpx_1.0.bin -krnl krnl.bin 17 | WindowsLocalDebugger 18 | $(SolutionDir)..\tests 19 | 20 | 21 | -extr bios\og_1_0\3944.bin -mcpx mcpx\mcpx_1.0.bin -krnl krnl.bin 22 | WindowsLocalDebugger 23 | $(SolutionDir)..\tests 24 | 25 | -------------------------------------------------------------------------------- /inc/loadini.h: -------------------------------------------------------------------------------- 1 | // loadini.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef LOAD_INI_H 23 | #define LOAD_INI_H 24 | 25 | #include 26 | #include 27 | 28 | typedef enum { 29 | LOADINI_SETTING_TYPE_STR, 30 | LOADINI_SETTING_TYPE_BOOL 31 | } LOADINI_SETTING_TYPE; 32 | 33 | enum { 34 | LOADINI_ERROR_SUCCESS = 0, 35 | LOADINI_ERROR_INVALID_DATA = 1, 36 | LOADINI_ERROR_INVALID_KEY = 2 37 | }; 38 | 39 | typedef struct { 40 | const char* key; 41 | const LOADINI_SETTING_TYPE type; 42 | } LOADINI_SETTING; 43 | 44 | typedef struct { 45 | const LOADINI_SETTING* s; 46 | void* var; 47 | } LOADINI_SETTING_MAP; 48 | 49 | typedef struct { 50 | const LOADINI_SETTING* s; 51 | const uint32_t size; 52 | const uint32_t count; 53 | } LOADINI_RETURN_MAP; 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif 58 | 59 | // load ini file 60 | // stream: file stream 61 | // settings_map: map of settings 62 | // map_size: size of the map 63 | // returns LOADINI_ERROR_CODE 64 | int loadini(FILE* stream, const LOADINI_SETTING_MAP* settings_map, uint32_t map_size); 65 | 66 | #ifdef __cplusplus 67 | }; 68 | #endif 69 | 70 | #endif // !LOAD_INI_H 71 | -------------------------------------------------------------------------------- /src/rc4.c: -------------------------------------------------------------------------------- 1 | // rc4.c : defines functions for symmetric encryption and decryption using the rc4 algorithm 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #include 23 | #include "rc4.h" 24 | 25 | void swap_byte(uint8_t* a, uint8_t* b); 26 | 27 | void rc4_key(RC4_CONTEXT* context, const uint8_t* key, const size_t len) { 28 | int i = 0; 29 | uint8_t j = 0; 30 | uint8_t k[256] = { 0 }; 31 | 32 | context->k = 0; 33 | context->j = 0; 34 | context->t = 0; 35 | 36 | for (i = 0; i < 256; ++i) { 37 | context->s[i] = (uint8_t)i; 38 | k[i] = key[i % len]; 39 | } 40 | 41 | for (i = 0; i < 256; ++i) { 42 | j = j + context->s[i] + k[i]; 43 | swap_byte(&context->s[i], &context->s[j]); 44 | } 45 | } 46 | 47 | void rc4(RC4_CONTEXT* c, uint8_t* data, const size_t size) { 48 | for (size_t i = 0; i < size; ++i) { 49 | c->k = c->k + 1; 50 | c->j = c->j + c->s[c->k]; 51 | swap_byte(&c->s[c->k], &c->s[c->j]); 52 | c->t = c->s[c->k] + c->s[c->j]; 53 | if (data != NULL) 54 | data[i] ^= c->s[c->t]; 55 | } 56 | } 57 | 58 | void rc4_symmetric_enc_dec(uint8_t* data, const size_t size, const uint8_t* key, const size_t key_len) { 59 | RC4_CONTEXT context = { 0 }; 60 | rc4_key(&context, key, key_len); 61 | rc4(&context, data, size); 62 | } 63 | 64 | inline void swap_byte(uint8_t* a, uint8_t* b) { 65 | uint8_t tmp = *a; 66 | *a = *b; 67 | *b = tmp; 68 | } 69 | -------------------------------------------------------------------------------- /inc/file.h: -------------------------------------------------------------------------------- 1 | // file.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. */ 17 | 18 | // Author: tommojphillips 19 | // GitHub: https:\\github.com\tommojphillips 20 | 21 | #ifndef XB_FILE_H 22 | #define XB_FILE_H 23 | 24 | // std incl 25 | #include 26 | #include 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | // read a file. allocates memory for the buffer. 33 | // filename: the absolute path to the file. 34 | // bytesRead: if not NULL, will store the number of bytes read. 35 | // expectedSize: if not -1, will check the file size against this value and return NULL if they don't match. 36 | // returns the buffer if successful, NULL otherwise. 37 | uint8_t* readFile(const char* filename, uint32_t* bytesRead, const uint32_t expectedSize); 38 | 39 | // write to a file. 40 | // filename: the absolute path to the file. 41 | // ptr: the buffer to write from. 42 | // bytesToWrite: the number of bytes to write to the file. 43 | // returns 0 if successful, 1 otherwise. 44 | int writeFile(const char* filename, void* ptr, const uint32_t bytesToWrite); 45 | 46 | // write to a file. 47 | int writeFileF(const char* filename, const char* tag, void* ptr, const uint32_t bytesToWrite); 48 | 49 | // check if file exists. 50 | bool fileExists(const char* filename); 51 | 52 | // deletes a file. 53 | // filename: the absolute path to the file. 54 | // returns 0 if successful, 1 otherwise. 55 | int deleteFile(const char* filename); 56 | 57 | // gets the size of a file. 58 | // file: the file to get the size of. 59 | // fileSize: if not NULL, will store the file size. 60 | // returns 0 if successful, 1 otherwise. 61 | int getFileSize(FILE* file, uint32_t* fileSize); 62 | 63 | #ifdef __cplusplus 64 | }; 65 | #endif 66 | 67 | #endif -------------------------------------------------------------------------------- /src/rsa.c: -------------------------------------------------------------------------------- 1 | // rsa.c: 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | 27 | // user incl 28 | #include "rsa.h" 29 | 30 | int rsa_verifyPublicKey(uint8_t* data, uint32_t size, uint32_t offset, PUBLIC_KEY** pubkey) 31 | { 32 | // verify the public key header. 33 | 34 | static const char RSA1_MAGIC[4] = { 'R', 'S', 'A', '1' }; 35 | RSA_HEADER* rsa_header; 36 | uint32_t pubkey_size; 37 | 38 | if (sizeof(RSA_HEADER) > size || offset + sizeof(RSA_HEADER) > size) // header over run 39 | return RSA_ERROR_INVALID_DATA; 40 | 41 | rsa_header = (RSA_HEADER*)(data + offset); 42 | pubkey_size = RSA_PUBKEY_SIZE(rsa_header); 43 | 44 | if (pubkey_size > size || offset + pubkey_size > size) // mod over run 45 | return RSA_ERROR; 46 | 47 | if (rsa_header->mod_size == 0 || rsa_header->bits == 0 || rsa_header->max_bytes == 0 || rsa_header->exponent == 0) 48 | return RSA_ERROR; 49 | 50 | if (rsa_header->bits % 8) 51 | return RSA_ERROR; 52 | 53 | if (RSA_MOD_SIZE(rsa_header) > rsa_header->mod_size) 54 | return RSA_ERROR; 55 | 56 | if (memcmp(rsa_header->magic, &RSA1_MAGIC, 4) != 0) // no match 57 | return RSA_ERROR; 58 | 59 | if (pubkey != NULL) 60 | *pubkey = (PUBLIC_KEY*)(rsa_header); 61 | 62 | return RSA_ERROR_SUCCESS; 63 | } 64 | int rsa_findPublicKey(uint8_t* data, uint32_t size, PUBLIC_KEY** pubkey, uint32_t* offset) 65 | { 66 | size_t i; 67 | int result = 0; 68 | if (data == NULL || pubkey == NULL) 69 | return RSA_ERROR_INVALID_DATA; 70 | 71 | for (i = 0; i < size - sizeof(RSA_HEADER); ++i) { 72 | result = rsa_verifyPublicKey(data, size, i, pubkey); 73 | if (result != RSA_ERROR) 74 | break; 75 | } 76 | 77 | if (offset != NULL) 78 | *offset = i; 79 | 80 | return result; 81 | } 82 | -------------------------------------------------------------------------------- /inc/rsa.h: -------------------------------------------------------------------------------- 1 | // rsa.h: 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef RSA_H 23 | #define RSA_H 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #define RSA_ERROR_SUCCESS 0 32 | #define RSA_ERROR 1 33 | #define RSA_ERROR_INVALID_DATA 2 34 | 35 | #define RSA_MOD_SIZE(rsa_header) ((rsa_header)->bits / 8U) 36 | #define RSA_MOD_BUFFER_SIZE(rsa_header) ((rsa_header)->mod_size) 37 | #define RSA_PUBKEY_SIZE(rsa_header) (sizeof(RSA_HEADER) + RSA_MOD_SIZE((RSA_HEADER*)rsa_header)) 38 | #define RSA_PUBKEY_BUFFER_SIZE(rsa_header) (sizeof(RSA_HEADER) + RSA_MOD_BUFFER_SIZE(rsa_header)) 39 | 40 | // The rsa header structure 41 | typedef struct _RSA_HEADER { 42 | char magic[4]; // (RSA1/RSA2) rsa magic 43 | uint32_t mod_size; // modulus buffer size in bytes 44 | uint32_t bits; // modulus size in bits 45 | uint32_t max_bytes; // max bytes to be encrypted 46 | uint32_t exponent; // public exponent 47 | } RSA_HEADER; 48 | 49 | // The public key structure 50 | typedef struct _PUBLIC_KEY { 51 | RSA_HEADER header; // rsa header structure 52 | uint8_t* modulus; // pointer to the modulus. 53 | } PUBLIC_KEY; 54 | 55 | // verify rsa1 public key at offset 56 | // data: input buffer 57 | // size: size of the buffer 58 | // offset: the offset to verify the pub key at. 59 | // pubkey: output pub key (points to the public key in data) 60 | int rsa_verifyPublicKey(uint8_t* data, uint32_t size, uint32_t offset, PUBLIC_KEY** pubkey); 61 | 62 | // find a rsa1 public key in the buffer. 63 | // data: input buffer 64 | // size: size of the buffer 65 | // pubkey: output pub key (points to the public key in data) 66 | // offset: output offset where the pub key was found. 67 | int rsa_findPublicKey(uint8_t* data, uint32_t size, PUBLIC_KEY** pubkey, uint32_t* offset); 68 | 69 | #ifdef __cplusplus 70 | }; 71 | #endif 72 | 73 | #endif // !RSA_H 74 | -------------------------------------------------------------------------------- /inc/util.h: -------------------------------------------------------------------------------- 1 | // util.h: implements various utility functions for manipulating strings, printing to console, changing console foreground color, size checking, etc. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef UTIL_H 23 | #define UTIL_H 24 | 25 | #include 26 | 27 | // pointer-of-struct bounds check 28 | #define IN_BOUNDS(struc, buff, size) ((uint8_t*)struc >= (uint8_t*)buff && (uint8_t*)struc + sizeof(*struc) < (uint8_t*)buff + size) 29 | 30 | // pointer-of-block bounds check 31 | #define IN_BOUNDS_BLOCK(block, blockSize, buff, buffSize) ((uint8_t*)block >= (uint8_t*)buff && (uint8_t*)block + blockSize < (uint8_t*)buff + buffSize) 32 | 33 | // console colors 34 | #define CONSOLE_COLOR_ERR 0 35 | #define CONSOLE_COLOR_OK 1 36 | #define CONSOLE_COLOR_MSG 3 37 | #define CONSOLE_COLOR_BLACK 30 38 | #define CONSOLE_COLOR_RED 31 39 | #define CONSOLE_COLOR_RED 31 40 | #define CONSOLE_COLOR_GREEN 32 41 | #define CONSOLE_COLOR_YELLOW 33 42 | #define CONSOLE_COLOR_BLUE 34 43 | #define CONSOLE_COLOR_MAGENTA 35 44 | #define CONSOLE_COLOR_CYAN 36 45 | #define CONSOLE_COLOR_WHITE 37 46 | 47 | #define ERROR_SUCCESS 0 48 | #define ERROR_FAILED 1 49 | #define ERROR_BUFFER_OVERFLOW 4 50 | #define ERROR_OUT_OF_MEMORY 5 51 | #define ERROR_INVALID_DATA 6 52 | 53 | #ifdef __cplusplus 54 | extern "C" { 55 | #endif 56 | 57 | // set console color 58 | void util_setConsoleColor(const int col); 59 | void util_setForegroundColor(const int col); 60 | 61 | // get timestamp string. 62 | void util_getTimestampStr(const size_t timestamp, char* timestamp_str); 63 | 64 | // std print to console with color 65 | void uprintc(const int col, const char* format, ...); 66 | 67 | // print to buffer. format. {1} = arg1, {2} = arg2, etc. 68 | void uprintf(char* data, const size_t size, const char* format, ...); 69 | 70 | // print a byte array as hex; single line. 71 | // data: buffer 72 | // size: buffer size 73 | // new_line: output new line 74 | void uprinth(const uint8_t* data, const size_t size); 75 | 76 | // print byte array as ascii; single line. 77 | // data: buffer 78 | // size: buffer size 79 | // new_line: output new line 80 | void uprinta(const uint8_t* data, const size_t size, const int new_line); 81 | 82 | // print byte array as hex; multi line 83 | // data: buffer 84 | // size: buffer size 85 | // per_line: num of hex digits per line. eg 16. -> xx xx xx xx ... x16 86 | void uprinthl(const uint8_t* data, const size_t size, uint32_t per_line, const char* prefix, const int ascii); 87 | 88 | #ifdef __cplusplus 89 | }; 90 | #endif 91 | 92 | #endif //UTIL_H 93 | -------------------------------------------------------------------------------- /src/mem_tracking.c: -------------------------------------------------------------------------------- 1 | // mem_tracking.c 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. */ 17 | 18 | // Author: tommojphillips 19 | // GitHub: https:\\github.com\tommojphillips 20 | 21 | #include 22 | #include 23 | 24 | //#define MEM_TRACKING_PRINT 25 | 26 | long memtrack_allocatedBytes = 0; 27 | int memtrack_allocations = 0; 28 | 29 | void* memtrack_malloc(size_t size) 30 | { 31 | void* ptr = malloc(size); 32 | if (ptr == NULL) { 33 | #ifdef MEM_TRACKING_PRINT 34 | printf("Error: could not allocate %d bytes\n", size); 35 | #endif 36 | return NULL; 37 | } 38 | 39 | memtrack_allocations++; 40 | memtrack_allocatedBytes += size; 41 | 42 | #ifdef MEM_TRACKING_PRINT 43 | printf("allocated %d bytes\n", size); 44 | #endif 45 | return ptr; 46 | } 47 | 48 | void memtrack_free(void* ptr) 49 | { 50 | #ifdef MEM_TRACKING_PRINT 51 | if (ptr == NULL) { 52 | printf("Error: attempting to free NULL pointer\n"); 53 | return; 54 | } 55 | #endif 56 | 57 | size_t size = _msize(ptr); 58 | free(ptr); 59 | 60 | memtrack_allocations--; 61 | memtrack_allocatedBytes -= size; 62 | 63 | if (memtrack_allocations < 0) { 64 | printf("Error neg allocations.\n"); 65 | } 66 | 67 | if (memtrack_allocatedBytes < 0) { 68 | printf("Error neg allocated bytes.\n"); 69 | } 70 | 71 | #ifdef MEM_TRACKING_PRINT 72 | printf("freed %d bytes\n", size); 73 | #endif 74 | } 75 | 76 | void* memtrack_realloc(void* ptr, size_t size) 77 | { 78 | size_t oldSize = _msize(ptr); 79 | void* newPtr = realloc(ptr, size); 80 | 81 | if (newPtr == NULL) { 82 | #ifdef MEM_TRACKING_PRINT 83 | printf("Error: could not reallocate %d bytes\n", size); 84 | #endif 85 | return NULL; 86 | } 87 | 88 | memtrack_allocatedBytes -= oldSize; 89 | memtrack_allocatedBytes += size; 90 | 91 | #ifdef MEM_TRACKING_PRINT 92 | printf("reallocated %u -> %u ( %d bytes )\n", oldSize, size, (size - oldSize)); 93 | #endif 94 | 95 | return newPtr; 96 | } 97 | 98 | void* memtrack_calloc(size_t count, size_t size) 99 | { 100 | if (count == 0 || size == 0) 101 | return NULL; 102 | 103 | void* ptr = calloc(count, size); 104 | if (ptr == NULL) { 105 | #ifdef MEM_TRACKING_PRINT 106 | printf("Error: could not allocate %d bytes\n", size); 107 | #endif 108 | return NULL; 109 | } 110 | 111 | memtrack_allocations++; 112 | memtrack_allocatedBytes += size; 113 | 114 | #ifdef MEM_TRACKING_PRINT 115 | printf("allocated %d bytes.\n", size); 116 | #endif 117 | 118 | return ptr; 119 | } 120 | 121 | int memtrack_report() 122 | { 123 | if (memtrack_allocatedBytes != 0 || memtrack_allocations != 0) { 124 | printf("\nLEAK DETECTED: %ld bytes in %d allocations\n", memtrack_allocatedBytes, memtrack_allocations); 125 | return 1; 126 | } 127 | 128 | #ifdef MEM_TRACKING_PRINT 129 | printf("\nno leaks detected\n"); 130 | #endif 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /src/loadini.c: -------------------------------------------------------------------------------- 1 | // loadini.c: implements the loadini functions for loading settings from a settings file. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // user incl 29 | #include "loadini.h" 30 | #include "str_util.h" 31 | 32 | #ifdef MEM_TRACKING 33 | #include "mem_tracking.h" 34 | #endif 35 | 36 | #define LOADINI_MAX_LINE_SIZE 128 37 | #define LOADINI_DELIM "=" 38 | 39 | static void set_setting_value(char** setting, const char* value, uint32_t len); 40 | 41 | int loadini(FILE* stream, const LOADINI_SETTING_MAP* settings_map, uint32_t map_size) { 42 | uint32_t i = 0; 43 | uint32_t len = 0; 44 | 45 | char buf[LOADINI_MAX_LINE_SIZE] = { 0 }; 46 | char* line_ptr = NULL; 47 | char* key = NULL; 48 | char* value = NULL; 49 | 50 | // parse next line 51 | while (fgets(buf, LOADINI_MAX_LINE_SIZE, stream) != NULL) { 52 | 53 | line_ptr = buf; 54 | ltrim(&line_ptr); 55 | 56 | if (line_ptr[0] == ';') // comment 57 | continue; 58 | 59 | // line-format: key=value 60 | 61 | // get the key. 62 | key = strtok(line_ptr, LOADINI_DELIM); 63 | if (key == NULL) 64 | continue; 65 | ltrim(&key); 66 | rtrim(&key); 67 | 68 | // get the value 69 | value = strtok(NULL, LOADINI_DELIM); 70 | if (value == NULL) 71 | continue; 72 | len = strlen(value); 73 | ltrim(&value); 74 | rtrim(&value); 75 | 76 | // quotes 77 | if (value[0] == '\"' || value[0] == '\'') { 78 | value++; 79 | len = strlen(value); 80 | if (value[len - 1] == '\"' || value[len - 1] == '\'') { 81 | value[len - 1] = '\0'; 82 | len--; 83 | } 84 | } 85 | 86 | // cmp key and set values. 87 | for (i = 0; i < map_size / sizeof(LOADINI_SETTING_MAP); i++) { 88 | if (strcmp(key, settings_map[i].s->key) != 0) 89 | continue; 90 | 91 | switch (settings_map[i].s->type) { 92 | case LOADINI_SETTING_TYPE_STR: 93 | set_setting_value((char**)settings_map[i].var, value, len); 94 | break; 95 | 96 | case LOADINI_SETTING_TYPE_BOOL: 97 | if (strcmp(value, "true") == 0) { 98 | *(bool*)settings_map[i].var = true; 99 | } 100 | else if (strcmp(value, "false") == 0) { 101 | *(bool*)settings_map[i].var = false; 102 | } 103 | break; 104 | } 105 | break; 106 | } 107 | 108 | if (i == map_size / sizeof(LOADINI_SETTING_MAP)) { 109 | return LOADINI_ERROR_INVALID_KEY; 110 | } 111 | } 112 | 113 | return LOADINI_ERROR_SUCCESS; 114 | } 115 | 116 | static void set_setting_value(char** setting, const char* value, uint32_t len) { 117 | if (setting == NULL || *setting != NULL) 118 | return; 119 | *setting = (char*)malloc(len + 1); 120 | if (*setting != NULL) { 121 | strcpy(*setting, value); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /inc/cli_tbl.h: -------------------------------------------------------------------------------- 1 | // cli_tbl.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // How to use: 23 | // define a command table (CMD_TBL) and parameter table (PARAM_TBL) in your source file. 24 | // define enums, CLI_COMMAND and CLI_SWITCH, for the command and switch types in your source file. 25 | // first element in the enum should represent no command or switch. 26 | // call parseCli() passing in the command line arguments, and tables. 27 | // set the command and parameter values based on the command line arguments. 28 | // update the switch flags based and cmd ptr based on the command line arguments. 29 | 30 | #ifndef CLI_TBL_H 31 | #define CLI_TBL_H 32 | 33 | #ifndef CLI_SWITCH_MAX_LEN 34 | #define CLI_SWITCH_MAX_LEN 20 35 | #endif 36 | 37 | #define CLI_SWITCH_MAX_COUNT 64 38 | 39 | #ifndef CLI_SWITCH_MAX_COUNT 40 | #define CLI_SWITCH_MAX_COUNT 32 41 | #endif 42 | 43 | #define CLI_SWITCH_BITS (sizeof(int) * 8) 44 | #define CLI_SWITCH_SIZE ((CLI_SWITCH_MAX_COUNT + CLI_SWITCH_BITS - 1) / CLI_SWITCH_BITS) 45 | 46 | typedef unsigned char CLI_SWITCH; 47 | typedef unsigned char CLI_COMMAND; 48 | 49 | const CLI_SWITCH SW_NONE = (CLI_SWITCH)0; 50 | const CLI_SWITCH SW_HELP = (CLI_SWITCH)1; 51 | const CLI_COMMAND CMD_NONE = (CLI_COMMAND)0; 52 | const CLI_COMMAND CMD_HELP = (CLI_COMMAND)1; 53 | 54 | #define CLI_COMMAND_START_INDEX 2 55 | #define CLI_SWITCH_START_INDEX 2 56 | 57 | enum CLI_CMD_ERROR : int { 58 | CLI_SUCCESS = 0, 59 | 60 | CLI_ERROR_NO_CMD, 61 | CLI_ERROR_INVALID_CMD, 62 | CLI_ERROR_UNKNOWN_CMD, 63 | 64 | CLI_ERROR_MISSING_SW, 65 | CLI_ERROR_INVALID_SW, 66 | CLI_ERROR_UNKNOWN_SW, 67 | 68 | CLI_ERROR_MISSING_ARG, 69 | CLI_ERROR_INVALID_ARG, 70 | }; 71 | 72 | typedef struct { 73 | const char* sw; 74 | CLI_COMMAND type; 75 | CLI_SWITCH requiredSwitches[7]; 76 | CLI_SWITCH inferredSwitches[4]; 77 | } CMD_TBL; 78 | typedef struct { 79 | enum PARAM_TYPE : char { NONE, STR, INT, BOOL, FLAG }; 80 | const char* sw; 81 | void* var; 82 | CLI_SWITCH swType; 83 | PARAM_TYPE cmdType; 84 | } PARAM_TBL; 85 | 86 | // parse the command line arguments 87 | // argc: the number of arguments 88 | // argv: the arguments 89 | // cmd: the selected/current command 90 | // cmd_tbl: the command table 91 | // cmd_tbl_size: the size of the command table 92 | // param_tbl: the parameter table 93 | // param_tbl_size: the size of the parameter table 94 | // returns: CLI_CMD_ERROR. 95 | int parseCli(int argc, char* argv[], 96 | const CMD_TBL*& cmd, 97 | const CMD_TBL* cmd_tbl, 98 | const int cmd_tbl_size, 99 | const PARAM_TBL* param_tbl, 100 | const int param_tbl_size); 101 | 102 | void setFlag(const CLI_SWITCH sw); 103 | void clearFlag(const CLI_SWITCH sw); 104 | bool isFlagSet(const CLI_SWITCH sw); 105 | bool isFlagClear(const CLI_SWITCH sw); 106 | 107 | // check if any of the flags are set in the switch array 108 | // sw: the SET switches. eg (1 << 19) | (1 << 20) 109 | // flags: the flags array 110 | // returns: true if any of the flags are set. 111 | bool isFlagSetAny(const int sw); 112 | 113 | #endif // XB_CLI_TBL_H 114 | -------------------------------------------------------------------------------- /inc/XcodeDecoder.h: -------------------------------------------------------------------------------- 1 | // XcodeDecoder.h: defines functions for decoding XCODE instructions 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XCODE_DECODER_H 23 | #define XCODE_DECODER_H 24 | 25 | #include 26 | 27 | // user incl 28 | #include "XcodeInterp.h" 29 | 30 | extern const LOADINI_RETURN_MAP decode_settings_map; 31 | 32 | typedef enum : uint8_t { 33 | DECODE_FIELD_OFFSET, 34 | DECODE_FIELD_OPCODE, 35 | DECODE_FIELD_ADDRESS, 36 | DECODE_FIELD_DATA, 37 | DECODE_FIELD_COMMENT 38 | } DECODE_FIELD; 39 | typedef struct { 40 | const char* field; 41 | const char* value; 42 | } DECODE_SETTING_MAP; 43 | typedef struct { 44 | DECODE_FIELD type; 45 | uint32_t seq; 46 | char* str; 47 | } DECODE_STR_SETTING_MAP; 48 | 49 | // DECODE SETTINGS 50 | typedef struct { 51 | char* format_str; 52 | char* prefix_str; 53 | char* jmp_str; 54 | char* no_operand_str; 55 | char* num_str; 56 | char* num_str_format; 57 | char* comment_prefix; 58 | DECODE_STR_SETTING_MAP format_map[5]; 59 | bool label_on_new_line; 60 | bool pad; 61 | bool opcode_use_result; 62 | 63 | uint32_t opcodeMaxLen; 64 | uint32_t labelMaxLen; 65 | FIELD_MAP opcodes[XC_OPCODE_COUNT]; 66 | } DECODE_SETTINGS; 67 | 68 | #define JMP_XCODE_NOT_BRANCHABLE 0 69 | #define JMP_XCODE_BRANCHABLE 1 70 | 71 | typedef struct _JMP_XCODE { 72 | int branchable; 73 | uint32_t xcodeOffset; 74 | XCODE* xcode; 75 | } JMP_XCODE; 76 | 77 | // DECODE_CONTEXT 78 | typedef struct { 79 | DECODE_SETTINGS settings; 80 | JMP_XCODE* jmps; 81 | LABEL* labels; 82 | XCODE* xcode; 83 | FILE* stream; 84 | uint32_t labelCount; 85 | uint32_t xcodeCount; 86 | uint32_t jmpCount; 87 | uint32_t xcodeSize; 88 | uint32_t xcodeBase; 89 | bool branch; 90 | char str_decode[128]; 91 | } DECODE_CONTEXT; 92 | 93 | void initDecodeSettings(DECODE_SETTINGS* settings); 94 | DECODE_SETTINGS* createDecodeSettings(); 95 | void destroyDecodeSettings(DECODE_SETTINGS* settings); 96 | 97 | void initDecodeContext(DECODE_CONTEXT* context); 98 | DECODE_CONTEXT* createDecodeContext(); 99 | void destroyDecodeContext(DECODE_CONTEXT* context); 100 | 101 | class XcodeDecoder 102 | { 103 | public: 104 | XcodeDecoder() { 105 | context = NULL; 106 | }; 107 | ~XcodeDecoder() { 108 | destroyDecodeContext(context); 109 | }; 110 | 111 | DECODE_CONTEXT* context; 112 | XcodeInterp interp; 113 | 114 | // load the decoder. 115 | // data: the xcode data. xcodes should start at data[base]. 116 | // size: the size of the xcode data. 117 | // ini: the ini file. [OPTIONAL]. if not provided, default settings are used. NULL if not needed. 118 | int load(uint8_t* data, uint32_t size, uint32_t base, const char* ini); 119 | int decodeXcodes(); 120 | int decode(); 121 | 122 | private: 123 | int loadSettings(const char* ini, DECODE_SETTINGS* settings) const; 124 | int getCommentStr(char* str); 125 | }; 126 | 127 | #endif // !XCODE_DECODER_H 128 | -------------------------------------------------------------------------------- /src/file.c: -------------------------------------------------------------------------------- 1 | // File.c: File handling functions 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "file.h" 27 | 28 | #ifdef MEM_TRACKING 29 | #include "mem_tracking.h" 30 | #endif 31 | 32 | uint8_t* readFile(const char* filename, uint32_t* bytesRead, const uint32_t expectedSize) { 33 | FILE* file = NULL; 34 | uint32_t size = 0; 35 | 36 | if (filename == NULL) 37 | return NULL; 38 | 39 | fopen_s(&file, filename, "rb"); 40 | if (file == NULL) { 41 | printf("Error: could not open file: %s\n", filename); 42 | return NULL; 43 | } 44 | 45 | getFileSize(file, &size); 46 | 47 | if (expectedSize != 0 && size != expectedSize) { 48 | printf("Error: invalid file size. Expected %u bytes. Got %u bytes\n", expectedSize, size); 49 | fclose(file); 50 | return NULL; 51 | } 52 | 53 | uint8_t* data = (uint8_t*)malloc(size); 54 | if (data != NULL) { 55 | fread(data, 1, size, file); 56 | if (bytesRead != NULL) { 57 | *bytesRead = size; 58 | } 59 | } 60 | fclose(file); 61 | 62 | return data; 63 | } 64 | 65 | int writeFile(const char* filename, void* ptr, const uint32_t bytesToWrite) { 66 | FILE* file = NULL; 67 | uint32_t bytesWritten = 0; 68 | 69 | if (filename == NULL) 70 | return 1; 71 | 72 | fopen_s(&file, filename, "wb"); 73 | if (file == NULL) { 74 | printf("Error: Could not open file: %s\n", filename); 75 | return 1; 76 | } 77 | 78 | bytesWritten = fwrite(ptr, 1, bytesToWrite, file); 79 | fclose(file); 80 | 81 | return 0; 82 | } 83 | int writeFileF(const char* filename, const char* tag, void* ptr, const uint32_t bytesToWrite) { 84 | static const char SUCCESS_OUT[] = "Writing %s to %s ( %.2f %s )\n"; 85 | static const char FAIL_OUT[] = "Error: Failed to write %s\n"; 86 | static const char* units[] = { "bytes", "kb", "mb", "gb" }; 87 | 88 | int result; 89 | float bytesF; 90 | const char* sizeSuffix; 91 | 92 | bytesF = (float)bytesToWrite; 93 | result = 0; 94 | while (bytesF > 1024.0f && result < (sizeof(units) / sizeof(char*)) - 1) { 95 | bytesF /= 1024.0f; 96 | result++; 97 | } 98 | sizeSuffix = units[result]; 99 | 100 | result = writeFile(filename, ptr, bytesToWrite); 101 | if (result == 0) { 102 | printf(SUCCESS_OUT, tag, filename, bytesF, sizeSuffix); 103 | } 104 | else { 105 | printf(FAIL_OUT, filename); 106 | } 107 | 108 | return result; 109 | } 110 | 111 | int getFileSize(FILE* file, uint32_t* fileSize) { 112 | if (file == NULL) 113 | return 1; 114 | 115 | fseek(file, 0, SEEK_END); 116 | *fileSize = ftell(file); 117 | fseek(file, 0, SEEK_SET); 118 | return 0; 119 | } 120 | bool fileExists(const char* filename) { 121 | FILE* file = NULL; 122 | 123 | if (filename == NULL) 124 | return false; 125 | 126 | fopen_s(&file, filename, "rb"); 127 | if (file == NULL) 128 | return false; 129 | fclose(file); 130 | return true; 131 | } 132 | 133 | int deleteFile(const char* filename) { 134 | if (filename == NULL) 135 | return 1; 136 | 137 | if (!fileExists(filename)) 138 | return 0; 139 | 140 | if (remove(filename) != 0) 141 | return 1; 142 | 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /inc/XcodeInterp.h: -------------------------------------------------------------------------------- 1 | // XcodeInterp.h: Implements an xcode interpreter. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XCODE_INTERP_H 23 | #define XCODE_INTERP_H 24 | 25 | #include 26 | 27 | // user incl 28 | #include "bldr.h" 29 | #include "loadini.h" 30 | 31 | #define SMB_BASE 0xC000 32 | #define SMB_CMD_REGISTER (SMB_BASE + 0x08) 33 | #define SMB_VAL_REGISTER (SMB_BASE + 0x06) 34 | 35 | #define NV2A_BASE 0x0F000000 36 | #define NV2A_BASE_KERNEL 0x0FD00000 37 | #define MCPX_1_0_IO_BAR 0x80000810 38 | #define MCPX_1_1_IO_BAR 0x80000884 39 | #define MCPX_IO_BAR_VAL 0x8001 40 | #define MCPX_LEG_24 0x80000860 41 | #define NV_CLK_REG 0x680500 42 | 43 | #define MEMTEST_PATTERN1 0xAAAAAAAA 44 | #define MEMTEST_PATTERN2 0x5A5A5A5A 45 | #define MEMTEST_PATTERN3 0x55555555 46 | 47 | #define XC_RESERVED 0X01 48 | #define XC_MEM_READ 0X02 49 | #define XC_MEM_WRITE 0X03 50 | #define XC_PCI_WRITE 0X04 51 | #define XC_PCI_READ 0X05 52 | #define XC_AND_OR 0X06 53 | #define XC_USE_RESULT 0X07 54 | #define XC_JNE 0X08 55 | #define XC_JMP 0X09 56 | #define XC_ACCUM 0X10 57 | #define XC_IO_WRITE 0X11 58 | #define XC_IO_READ 0X12 59 | #define XC_NOP_80 0X80 60 | #define XC_EXIT 0XEE 61 | #define XC_NOP_F5 0XF5 62 | 63 | #define XC_OPCODE_COUNT 15 64 | 65 | #define XC_INTERP_ERROR_SUCCESS 0 66 | #define XC_INTERP_ERROR_FAILED 1 67 | #define XC_INTERP_ERROR_BUFFER_OVERFLOW 4 68 | #define XC_INTERP_ERROR_OUT_OF_MEMORY 5 69 | #define XC_INTERP_ERROR_INVALID_DATA 6 70 | 71 | typedef uint8_t OPCODE; 72 | 73 | typedef struct _LABEL { 74 | uint32_t offset; // the offset of the label 75 | uint32_t references; // how many times the label is jumped to ( xcodes that use this label ) 76 | bool defined; // if we have come across this label definition. ( the xcode that this label points to ) 77 | char name[20]; 78 | } LABEL; 79 | 80 | typedef struct _FIELD_MAP { 81 | const char* str; 82 | uint8_t field; 83 | } FIELD_MAP; 84 | 85 | // Xcode interpreter 86 | 87 | extern const FIELD_MAP xcode_opcode_map[]; 88 | 89 | class XcodeInterp { 90 | public: 91 | XcodeInterp() { 92 | size = 0; 93 | reset(); 94 | data = NULL; 95 | }; 96 | ~XcodeInterp() { 97 | unload(); 98 | }; 99 | 100 | enum INTERP_STATUS : int { DATA_OK = 0, EXIT_OP_FOUND, DATA_ERROR }; 101 | 102 | int load(uint8_t* data, uint32_t size); 103 | void reset(); 104 | void unload(); 105 | int interpretNext(XCODE*& xcode); 106 | 107 | uint8_t* data; // XCODE data 108 | uint32_t size; // size of the XCODE data 109 | XCODE* ptr; // current position in the XCODE data 110 | uint32_t offset; // offset from the start of the data to the end of the current XCODE (offset to the next XCODE) 111 | INTERP_STATUS status; // status of the xcode interpreter 112 | }; 113 | 114 | int encodeX86AsMemWrites(uint8_t* data, uint32_t size, uint32_t base, uint8_t*& buffer, uint32_t* xcodeSize); 115 | int getOpcodeStr(const FIELD_MAP* opcodes, uint8_t opcode, const char*& str); 116 | 117 | #endif // !XCODE_INTERP_H -------------------------------------------------------------------------------- /inc/nt_headers.h: -------------------------------------------------------------------------------- 1 | // nt_headers.h: 2 | 3 | // Author: tommojphillips 4 | // GitHub: https:\\github.com\tommojphillips 5 | 6 | #ifndef XB_BIOS_TOOL_NT_IMAGE_H 7 | #define XB_BIOS_TOOL_NT_IMAGE_H 8 | 9 | #include 10 | 11 | #ifndef __cplusplus 12 | #include 13 | #endif 14 | 15 | #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ 16 | #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 17 | 18 | typedef struct { 19 | uint16_t e_magic; 20 | uint16_t e_cblp; 21 | uint16_t e_cp; 22 | uint16_t e_crlc; 23 | uint16_t e_cparhdr; 24 | uint16_t e_minalloc; 25 | uint16_t e_maxalloc; 26 | uint16_t e_ss; 27 | uint16_t e_sp; 28 | uint16_t e_csum; 29 | uint16_t e_ip; 30 | uint16_t e_cs; 31 | uint16_t e_lfarlc; 32 | uint16_t e_ovno; 33 | uint16_t e_res[4]; 34 | uint16_t e_oemid; 35 | uint16_t e_oeminfo; 36 | uint16_t e_res2[10]; 37 | uint32_t e_lfanew; 38 | } IMAGE_DOS_HEADER; 39 | typedef struct { 40 | uint16_t machine; 41 | uint16_t numSections; 42 | uint32_t datetimeStamp; 43 | uint32_t symbolTablePtr; 44 | uint32_t numSymbols; 45 | uint16_t sizeOfOptionalHeader; 46 | uint16_t characteristics; 47 | } COFF_FILE_HEADER; 48 | typedef struct { 49 | uint32_t address; 50 | uint32_t size; 51 | } IMAGE_DATA_DIRECTORY; 52 | typedef struct { 53 | uint16_t magic; 54 | uint8_t majorLinkerVersion; 55 | uint8_t minorLinkerVersion; 56 | uint32_t codeSize; 57 | uint32_t initializedDataSize; 58 | uint32_t uninitializedDataSize; 59 | uint32_t addressOfEntryPoint; 60 | uint32_t baseOfCode; 61 | uint32_t baseOfData; 62 | } IMAGE_OPTIONAL_HEADER_STD_FIELDS; 63 | typedef struct { 64 | IMAGE_OPTIONAL_HEADER_STD_FIELDS std; 65 | uint32_t imageBase; 66 | uint32_t sectionAlignment; 67 | uint32_t fileAlignment; 68 | uint16_t majorOperatingSystemVersion; 69 | uint16_t minorOperatingSystemVersion; 70 | uint16_t majorImageVersion; 71 | uint16_t minorImageVersion; 72 | uint16_t majorSubsystemVersion; 73 | uint16_t minorSubsystemVersion; 74 | uint32_t win32VersionValue; 75 | uint32_t imageSize; 76 | uint32_t headersSize; 77 | uint32_t checksum; 78 | uint16_t subsystem; 79 | uint16_t characteristics; 80 | uint32_t stackReserveSize; 81 | uint32_t stackCommitSize; 82 | uint32_t heapReserveSize; 83 | uint32_t heapCommitSize; 84 | uint32_t loaderFlags; 85 | uint32_t numRvaAndSizes; 86 | IMAGE_DATA_DIRECTORY* dataDirectory; 87 | } IMAGE_OPTIONAL_HEADER; 88 | typedef struct { 89 | uint32_t signature; 90 | COFF_FILE_HEADER file_header; 91 | IMAGE_OPTIONAL_HEADER optional_header; 92 | } IMAGE_NT_HEADER; 93 | typedef struct { 94 | uint8_t name[8]; 95 | uint32_t virtualSize; 96 | uint32_t virtualAddress; 97 | uint32_t rawDataSize; 98 | uint32_t pointerToRawData; 99 | uint32_t pointerToRelocations; 100 | uint32_t pointerToLineNumbers; 101 | uint16_t numRelocations; 102 | uint16_t numLineNumbers; 103 | uint32_t characteristics; 104 | } IMAGE_SECTION_HEADER; 105 | typedef struct { 106 | uint32_t uninitializedDataSize; 107 | uint32_t initializedDataSize; 108 | uint32_t rawDataPtr; 109 | uint32_t virtualAddr; 110 | } DATA_SECTION_HEADER; 111 | 112 | #ifdef __cplusplus 113 | extern "C" { 114 | #endif 115 | 116 | void print_krnl_data_section_header(IMAGE_DOS_HEADER* dos_header); 117 | 118 | void print_image_dos_header(IMAGE_DOS_HEADER* dos_header); 119 | void print_image_file_header(COFF_FILE_HEADER* file_header, bool basic); 120 | void print_image_optional_header(IMAGE_OPTIONAL_HEADER* optional_header, bool basic); 121 | void print_nt_headers(IMAGE_NT_HEADER* nt_header, bool basic); 122 | 123 | int dump_nt_headers(uint8_t* data, uint32_t size, bool basic); 124 | 125 | IMAGE_DOS_HEADER* verify_dos_header(uint8_t* data, uint32_t size); 126 | IMAGE_NT_HEADER* verify_nt_headers(uint8_t* data, uint32_t size); 127 | 128 | #ifdef __cplusplus 129 | }; 130 | #endif 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /inc/XbTool.h: -------------------------------------------------------------------------------- 1 | // XbTool.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XB_BIOS_TOOL_H 23 | #define XB_BIOS_TOOL_H 24 | 25 | #include 26 | 27 | // user incl 28 | #include "Bios.h" 29 | #include "Mcpx.h" 30 | #include "cli_tbl.h" 31 | 32 | enum XB_CLI_COMMAND : CLI_COMMAND { 33 | CMD_INFO = CLI_COMMAND_START_INDEX, 34 | CMD_LIST_BIOS, 35 | CMD_SPLIT_BIOS, 36 | CMD_COMBINE_BIOS, 37 | CMD_EXTRACT_BIOS, 38 | CMD_BUILD_BIOS, 39 | CMD_SIMULATE_XCODE, 40 | CMD_DECODE_XCODE, 41 | CMD_ENCODE_X86, 42 | CMD_DUMP_PE_IMG, 43 | CMD_REPLICATE_BIOS, 44 | CMD_COMPRESS_FILE, 45 | CMD_DECOMPRESS_FILE, 46 | }; 47 | enum XB_CLI_SWITCH : CLI_SWITCH { 48 | SW_ROMSIZE = CLI_SWITCH_START_INDEX, 49 | SW_KEY_KRNL_FILE, 50 | SW_KEY_BLDR_FILE, 51 | SW_OUT_FILE, 52 | SW_IN_FILE, 53 | SW_BLDR_FILE, 54 | SW_PRELDR_FILE, 55 | SW_KRNL_FILE, 56 | SW_INITTBL_FILE, 57 | SW_KRNL_DATA_FILE, 58 | SW_ENC_BLDR, 59 | SW_ENC_KRNL, 60 | SW_BINSIZE, 61 | SW_LS_NV2A_TBL, 62 | SW_LS_DATA_TBL, 63 | SW_DUMP_KRNL, 64 | SW_KEYS, 65 | SW_NO_MAX_SIZE, 66 | SW_MCPX_FILE, 67 | SW_PUB_KEY_FILE, 68 | SW_CERT_KEY_FILE, 69 | SW_EEPROM_KEY_FILE, 70 | SW_BLD_BFM, 71 | SW_DMP, 72 | SW_SIM_SIZE, 73 | SW_BANK1_FILE, 74 | SW_BANK2_FILE, 75 | SW_BANK3_FILE, 76 | SW_BANK4_FILE, 77 | SW_INI_FILE, 78 | SW_BASE, 79 | SW_HACK_INITTBL, 80 | SW_HACK_SIGNATURE, 81 | SW_UPDATE_BOOT_PARAMS, 82 | SW_HELP_ENCRYPTION, 83 | SW_BRANCH, 84 | SW_HELP_ALL, 85 | SW_WORKING_DIRECTORY, 86 | SW_OFFSET, 87 | SW_XCODES 88 | }; 89 | 90 | typedef struct { 91 | uint32_t romsize; 92 | uint32_t binsize; 93 | uint32_t simSize; 94 | uint32_t base; 95 | uint32_t offset; 96 | uint8_t* bldr_key; 97 | uint8_t* kernel_key; 98 | MCPX mcpx; 99 | const char* in_file; 100 | const char* out_file; 101 | const char* bank_files[4]; 102 | const char* init_tbl_file; 103 | const char* preldr_file; 104 | const char* bldr_file; 105 | const char* kernel_file; 106 | const char* kernel_data_file; 107 | const char* mcpx_file; 108 | const char* bldr_key_file; 109 | const char* kernel_key_file; 110 | const char* public_key_file; 111 | const char* cert_key_file; 112 | const char* eeprom_key_file; 113 | const char* settings_file; 114 | const char* working_directory_path; 115 | const char* xcodes_file; 116 | } XbToolParameters; 117 | 118 | /* Command functions */ 119 | 120 | int info(); 121 | int help(); 122 | int helpAll(); 123 | int helpEncryption(); 124 | int listBios(); 125 | int extractBios(); 126 | int buildBios(); 127 | int splitBios(); 128 | int combineBios(); 129 | int replicateBios(); 130 | int simulateXcodes(); 131 | int decodeXcodes(); 132 | int encodeX86(); 133 | int dumpCoffPeImg(); 134 | int compressFile(); 135 | int decompressFile(); 136 | 137 | void init_parameters(XbToolParameters* params); 138 | void free_parameters(XbToolParameters* params); 139 | int inject_xcodes(uint8_t* data, uint32_t size, uint8_t* xcodes, uint32_t xcodesSize); 140 | uint8_t* load_init_tbl_file(uint32_t* size, uint32_t* base); 141 | 142 | /* BIOS print functions */ 143 | void printBldrInfo(Bios* bios); 144 | void printPreldrInfo(Bios* bios); 145 | void printInitTblInfo(Bios* bios); 146 | void printNv2aInfo(Bios* bios); 147 | void printDataTblInfo(Bios* bios); 148 | void printKeyInfo(Bios* bios); 149 | 150 | int main(int argc, char** argv); 151 | 152 | #endif // !XB_BIOS_TOOL_H 153 | -------------------------------------------------------------------------------- /src/Mcpx.c: -------------------------------------------------------------------------------- 1 | // Mcpx.cpp : Implements the MCPX_ROM class for handling MCPX ROMs. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | 26 | // user incl 27 | #include "Mcpx.h" 28 | #include "sha1.h" 29 | 30 | #ifdef MEM_TRACKING 31 | #include "mem_tracking.h" 32 | #endif 33 | 34 | // SHA1 hashes of accepted mcpx roms. 35 | // Used to verify the integrity of the mcpx rom 36 | 37 | // MCPX V1.0 38 | const uint8_t MCPX_V1_0_SHA1_HASH[SHA1_DIGEST_LEN] = { 39 | 0x5d, 0x27, 0x06, 0x75, 40 | 0xb5, 0x4e, 0xb8, 0x07, 41 | 0x1b, 0x48, 0x0e, 0x42, 42 | 0xd2, 0x2a, 0x30, 0x15, 43 | 0xac, 0x21, 0x1c, 0xef 44 | }; 45 | 46 | // MCPX V1.1 47 | const uint8_t MCPX_V1_1_SHA1_HASH[SHA1_DIGEST_LEN] = { 48 | 0x6c, 0x87, 0x5f, 0x17, 49 | 0xf7, 0x73, 0xaa, 0xec, 50 | 0x51, 0xeb, 0x43, 0x40, 51 | 0x68, 0xbb, 0x6c, 0x65, 52 | 0x7c, 0x43, 0x43, 0xc0 53 | }; 54 | 55 | // MOUSE rev 1 v0.9.0 56 | const uint8_t MOUSE_REV1_SHA1_HASH[SHA1_DIGEST_LEN] = { 57 | 0x15, 0x13, 0xab, 0xcb, 58 | 0x6b, 0x97, 0x9f, 0x79, 59 | 0x53, 0x6f, 0xcf, 0x0e, 60 | 0xd9, 0x67, 0xf3, 0x77, 61 | 0x55, 0xe0, 0x7f, 0x9b 62 | }; 63 | 64 | // MOUSE rev 0 v0.9.0 65 | const uint8_t MOUSE_REV0_SHA1_HASH[SHA1_DIGEST_LEN] = { 66 | 0xb9, 0xe8, 0x8e, 0x37, 67 | 0x50, 0x40, 0xbf, 0xaf, 68 | 0x90, 0x28, 0x15, 0xbe, 69 | 0x99, 0x16, 0x8c, 0x8b, 70 | 0x05, 0x14, 0x71, 0x37 71 | }; 72 | 73 | void mcpx_init(MCPX* mcpx) { 74 | mcpx->rev = MCPX_REV_UNK; 75 | mcpx->data = NULL; 76 | mcpx->sbkey = NULL; 77 | memset(mcpx->hash, 0, SHA1_DIGEST_LEN); 78 | } 79 | void mcpx_free(MCPX* mcpx) { 80 | if (mcpx->data != NULL) { 81 | free(mcpx->data); 82 | mcpx->data = NULL; 83 | } 84 | mcpx->sbkey = NULL; 85 | mcpx->rev = MCPX_REV_UNK; 86 | } 87 | 88 | int mcpx_load(MCPX* mcpx, uint8_t* data) { 89 | 90 | mcpx->data = data; 91 | 92 | // hash the mcpx 93 | SHA1Context context; 94 | SHA1Reset(&context); 95 | SHA1Input(&context, mcpx->data, MCPX_BLOCK_SIZE); 96 | SHA1Result(&context, mcpx->hash); 97 | 98 | // compare precomputed hashes 99 | 100 | if (memcmp(mcpx->hash, MCPX_V1_0_SHA1_HASH, SHA1_DIGEST_LEN) == 0) { 101 | // mcpx v1.0 102 | mcpx->rev = MCPX_REV_0; 103 | mcpx->sbkey = (mcpx->data + 0x1A5); 104 | } 105 | else if (memcmp(mcpx->hash, MCPX_V1_1_SHA1_HASH, SHA1_DIGEST_LEN) == 0) { 106 | // mcpx v1.1 107 | mcpx->rev = MCPX_REV_1; 108 | mcpx->sbkey = (mcpx->data + 0x19C); 109 | return 0; 110 | } 111 | else if (memcmp(mcpx->hash, MOUSE_REV0_SHA1_HASH, SHA1_DIGEST_LEN) == 0) { 112 | // mouse rev.0 v0.8.0 113 | mcpx->rev = MCPX_REV_0; 114 | mcpx->sbkey = (mcpx->data + 0x19C); 115 | } 116 | else if (memcmp(mcpx->hash, MOUSE_REV1_SHA1_HASH, SHA1_DIGEST_LEN) == 0) { 117 | // mouse rev.1 v0.8.0 118 | mcpx->rev = MCPX_REV_1; 119 | mcpx->sbkey = (mcpx->data + 0x19C); 120 | } 121 | else if (memcmp(mcpx->hash, MOUSE_REV0_SHA1_HASH, SHA1_DIGEST_LEN) == 0) { 122 | // mouse rev.0 v0.9.0 123 | mcpx->rev = MCPX_REV_0; 124 | mcpx->sbkey = (mcpx->data + 0x19C); 125 | } 126 | else { 127 | // mcpx hash doesnt match; unknown mcpx dump; 128 | /*printf("const uint8_t mcpx_hash[] {"); 129 | for (uint32_t i = 0; i < SHA1_DIGEST_LEN; i++) { 130 | if (i % 4 == 0) { 131 | printf("\n\t"); 132 | } 133 | printf("0x%02x, ", mcpx->hash[i]); 134 | } 135 | printf("\n};\n");*/ 136 | return 1; 137 | } 138 | 139 | return 0; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/XcodeInterp.cpp: -------------------------------------------------------------------------------- 1 | // XcodeInterp.cpp: defines functions for interpreting XCODE instructions 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | 27 | // user incl 28 | #include "XcodeInterp.h" 29 | #include "str_util.h" 30 | 31 | #ifdef MEM_TRACKING 32 | #include "mem_tracking.h" 33 | #endif 34 | 35 | const FIELD_MAP xcode_opcode_map[] = { 36 | { "xc_reserved", XC_RESERVED }, 37 | { "xc_mem_read", XC_MEM_READ }, 38 | { "xc_mem_write", XC_MEM_WRITE }, 39 | { "xc_pci_write", XC_PCI_WRITE }, 40 | { "xc_pci_read", XC_PCI_READ }, 41 | { "xc_and_or", XC_AND_OR }, 42 | { "xc_result", XC_USE_RESULT }, 43 | { "xc_jne", XC_JNE }, 44 | { "xc_jmp", XC_JMP }, 45 | { "xc_accum", XC_ACCUM }, 46 | { "xc_io_write", XC_IO_WRITE }, 47 | { "xc_io_read", XC_IO_READ }, 48 | { "xc_nop_f5", XC_NOP_F5 }, 49 | { "xc_exit", XC_EXIT }, 50 | { "xc_nop_80", XC_NOP_80 } 51 | }; 52 | 53 | int XcodeInterp::load(uint8_t* in_data, uint32_t in_size) { 54 | if (data != NULL) { 55 | return 1; 56 | } 57 | 58 | data = (uint8_t*)malloc(in_size); 59 | if (data == NULL) { 60 | return XC_INTERP_ERROR_OUT_OF_MEMORY; 61 | } 62 | 63 | memcpy(data, in_data, in_size); 64 | size = in_size; 65 | 66 | reset(); 67 | 68 | return 0; 69 | } 70 | void XcodeInterp::reset() { 71 | offset = 0; 72 | status = DATA_OK; 73 | ptr = (XCODE*)data; 74 | } 75 | void XcodeInterp::unload() { 76 | if (data != NULL) { 77 | free(data); 78 | data = NULL; 79 | } 80 | } 81 | int XcodeInterp::interpretNext(XCODE*& xcode) { 82 | if (data == NULL) { 83 | status = INTERP_STATUS::DATA_ERROR; 84 | return XC_INTERP_ERROR_INVALID_DATA; 85 | } 86 | 87 | // last xcode was an exit. dont interpret anymore xcodes after this 88 | if (status == INTERP_STATUS::EXIT_OP_FOUND) 89 | return 1; 90 | 91 | // check if offset is within bounds 92 | if (offset + sizeof(XCODE) > size) { 93 | status = INTERP_STATUS::DATA_ERROR; 94 | return 1; 95 | } 96 | 97 | ptr = (XCODE*)(data + offset); 98 | xcode = ptr; 99 | 100 | if (xcode->opcode == XC_EXIT) { 101 | status = INTERP_STATUS::EXIT_OP_FOUND; 102 | } 103 | else { 104 | status = INTERP_STATUS::DATA_OK; 105 | } 106 | 107 | offset += sizeof(XCODE); 108 | 109 | return 0; 110 | } 111 | 112 | int encodeX86AsMemWrites(uint8_t* data, uint32_t size, uint32_t base, uint8_t*& buffer, uint32_t* xcodeSize) { 113 | const uint32_t allocSize = sizeof(XCODE) * 10; 114 | 115 | buffer = (uint8_t*)malloc(allocSize); 116 | if (buffer == NULL) 117 | return XC_INTERP_ERROR_OUT_OF_MEMORY; 118 | 119 | uint32_t nSize = allocSize; 120 | uint32_t offset = 0; 121 | XCODE xcode = { XC_MEM_WRITE, 0, 0 }; 122 | uint32_t xc_d; 123 | 124 | for (uint32_t i = 0; i < size; i+=4) { 125 | if (i + 4 > size) { 126 | xc_d = 0; 127 | memcpy(&xc_d, data + i, size - i); 128 | } 129 | else { 130 | xc_d = *(uint32_t*)(data + i); 131 | } 132 | 133 | xcode.addr = base + i; 134 | xcode.data = xc_d; 135 | 136 | if (offset + sizeof(XCODE) > nSize) { 137 | uint8_t* new_buffer = (uint8_t*)realloc(buffer, nSize + allocSize); 138 | if (new_buffer == NULL) { 139 | return XC_INTERP_ERROR_OUT_OF_MEMORY; 140 | } 141 | buffer = new_buffer; 142 | nSize += allocSize; 143 | } 144 | 145 | memcpy(buffer + offset, &xcode, sizeof(XCODE)); 146 | offset += sizeof(XCODE); 147 | } 148 | 149 | if (xcodeSize != NULL) { 150 | *xcodeSize = offset; 151 | } 152 | 153 | return 0; 154 | } 155 | int getOpcodeStr(const FIELD_MAP* opcodes, uint8_t opcode, const char*& str) { 156 | for (uint32_t i = 0; i < XC_OPCODE_COUNT; ++i) { 157 | if (opcodes[i].field == opcode) { 158 | str = opcodes[i].str; 159 | return 0; 160 | } 161 | } 162 | return 1; 163 | } 164 | -------------------------------------------------------------------------------- /inc/bldr.h: -------------------------------------------------------------------------------- 1 | // bldr.h: Implements Original Xbox Bootloader structures and constants. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XB_BLDR_H 23 | #define XB_BLDR_H 24 | 25 | #include 26 | 27 | #define XB_KEY_SIZE 16 28 | 29 | typedef struct { 30 | uint8_t countA; 31 | uint8_t countB; 32 | } DRV_SLW_COUNTS; 33 | 34 | typedef struct { 35 | uint16_t max_m_clk; 36 | DRV_SLW_COUNTS slowest; 37 | DRV_SLW_COUNTS slow; 38 | DRV_SLW_COUNTS standard; 39 | DRV_SLW_COUNTS fast; 40 | DRV_SLW_COUNTS fastest; 41 | } DRV_SLW_CAL_PARAMS; 42 | 43 | typedef struct { 44 | uint8_t adr_drv_fall; 45 | uint8_t adr_drv_rise; 46 | uint8_t adr_slw_fall; 47 | uint8_t adr_slw_rise; 48 | uint8_t clk_drv_fall; 49 | uint8_t clk_drv_rise; 50 | uint8_t clk_slw_fall; 51 | uint8_t clk_slw_rise; 52 | uint8_t dat_drv_fall; 53 | uint8_t dat_drv_rise; 54 | uint8_t dat_slw_fall; 55 | uint8_t dat_slw_rise; 56 | uint8_t dqs_drv_fall; 57 | uint8_t dqs_drv_rise; 58 | uint8_t dqs_slw_fall; 59 | uint8_t dqs_slw_rise; 60 | uint8_t dat_inb_delay; 61 | uint8_t clk_ic_delay; 62 | uint8_t dqs_inb_delay; 63 | } DRV_SLW_PAD_PARAMS; 64 | 65 | // init table structure. 66 | typedef struct { 67 | uint32_t ptr1; 68 | uint32_t ptr2; 69 | uint32_t header; 70 | uint32_t val1; 71 | uint32_t val2; 72 | uint32_t val3; 73 | uint32_t val4; 74 | uint32_t val5; 75 | uint32_t val6; 76 | uint32_t val7; 77 | uint32_t val8; 78 | uint32_t val9; 79 | uint32_t val10; 80 | uint32_t vals[14]; 81 | uint16_t revision; 82 | uint16_t val11; 83 | uint32_t val12; 84 | uint32_t val13; 85 | uint16_t init_tbl_identifier; 86 | uint16_t kernel_ver; 87 | uint32_t data_tbl_offset; 88 | } INIT_TBL; 89 | 90 | // rom table structure. 91 | typedef struct { 92 | DRV_SLW_CAL_PARAMS cal; 93 | DRV_SLW_PAD_PARAMS samsung[5]; 94 | DRV_SLW_PAD_PARAMS micron[5]; 95 | } ROM_DATA_TBL; 96 | 97 | // xcode structure. 98 | #pragma pack(push, 1) 99 | typedef struct _XCODE { 100 | uint8_t opcode; 101 | uint32_t addr; 102 | uint32_t data; 103 | } XCODE; 104 | #pragma pack(pop) 105 | 106 | // loader parameters structure. 107 | typedef struct { 108 | uint32_t bldr_entry_point; 109 | char command_line[64]; 110 | } BOOT_LDR_PARAM; 111 | 112 | // boot params structure. 113 | typedef struct { 114 | uint32_t uncompressed_kernel_data_size; 115 | uint32_t init_tbl_size; 116 | uint32_t signature; 117 | uint32_t compressed_kernel_size; 118 | uint8_t digest[20]; 119 | } BOOT_PARAMS; 120 | 121 | // 2BL keys structure 122 | typedef struct { 123 | uint8_t eeprom_key[XB_KEY_SIZE]; 124 | uint8_t cert_key[XB_KEY_SIZE]; 125 | uint8_t kernel_key[XB_KEY_SIZE]; 126 | } BLDR_KEYS; 127 | 128 | // 2BL entry structure 129 | typedef struct { 130 | uint32_t keys_ptr; 131 | uint32_t bfm_entry_point; 132 | } BLDR_ENTRY; 133 | 134 | // Preldr parameters structure 135 | #pragma pack(push, 1) 136 | typedef struct { 137 | uint8_t jmp_opcode; 138 | uint32_t jmp_offset; 139 | uint8_t pad[3]; 140 | uint32_t func_block_ptr; 141 | } PRELDR_PARAMS; 142 | #pragma pack(pop) 143 | 144 | // Preldr pointer block structure 145 | typedef struct { 146 | uint32_t public_key_ptr; 147 | uint32_t func_block_ptr; 148 | } PRELDR_PTR_BLOCK; 149 | 150 | // Preldr function block structure 151 | typedef struct { 152 | uint32_t sha_init_func_ptr; 153 | uint32_t sha_update_func_ptr; 154 | uint32_t sha_result_func_ptr; 155 | uint32_t verify_digest_func_ptr; 156 | } PRELDR_FUNC_BLOCK; 157 | 158 | // Preldr entry structure 159 | typedef struct { 160 | uint32_t bldr_entry_offset; 161 | uint32_t bfm_entry_point; 162 | } PRELDR_ENTRY; 163 | 164 | #endif // !XB_BLDR_H 165 | -------------------------------------------------------------------------------- /vc/XboxBiosTools.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files 103 | 104 | 105 | Header Files 106 | 107 | 108 | Header Files 109 | 110 | 111 | Header Files 112 | 113 | 114 | Header Files 115 | 116 | 117 | Header Files 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | Header Files 130 | 131 | 132 | Header Files 133 | 134 | 135 | Header Files 136 | 137 | 138 | 139 | 140 | Resource Files 141 | 142 | 143 | -------------------------------------------------------------------------------- /inc/help_strings.h: -------------------------------------------------------------------------------- 1 | // help_strings.h 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XB_HELP_STR_H 23 | #define XB_HELP_STR_H 24 | 25 | // All lines are limited to 80 characters. 26 | 27 | const char HELP_USAGE_STR[] = "Usage: xbios [switches]"; 28 | const char HELP_STR_LIST[] = "Dump BIOS infomation. params, sizes, signatures, keys, tables, etc."; 29 | 30 | const char HELP_STR_BUILD[] = "Build a BIOS from a preldr, 2BL, kernel, section data, init table.\n" \ 31 | "* The romsize dictates the amount of space available for the BIOS image.\n" \ 32 | "* The BIOS image is replicated upto the binsize"; 33 | 34 | const char HELP_STR_SPLIT[] = "Split a BIOS into banks. Eg: bios.bin 1mb -> bios.bin 4x 256kb.\n" \ 35 | "* Use -romsize to split the BIOS into 256kb or 512kb banks"; 36 | 37 | const char HELP_STR_COMBINE[] = "Combine BIOSes into a single BIOS. Eg: bios.bin x4 256kb -> bios.bin 1mb.\n" \ 38 | "* Provide atleast 2 BIOSes to combine."; 39 | 40 | const char HELP_STR_X86_ENCODE[] = "Encode x86 instructions as mem write xcodes. (visor)\n" \ 41 | "* input file must be a binary file containing x86 instructions."; 42 | 43 | const char HELP_STR_XCODE_DECODE[] = "Decode xcodes from a BIOS or init tbl.\n" \ 44 | "* Supports retail opcodes\n" \ 45 | "* Supports custom decode format via config file"; 46 | 47 | const char HELP_STR_EXTR_ALL[] = "Extract the preldr, 2BL, kernel, section data, init table."; 48 | const char HELP_STR_XCODE_SIM[] = "Simulate mem-write xcodes and parse x86 instructions. (visor sim)"; 49 | const char HELP_STR_DUMP_NT_IMG[] = "Dump COFF/PE image infomation. headers, sections etc."; 50 | const char HELP_STR_INFO[] = "Display licence, version and author information."; 51 | const char HELP_STR_REPLICATE[] = "Replicate a BIOS image upto a specified size."; 52 | const char HELP_STR_COMPRESS_FILE[] = "Compress a file using the lzx algorithm."; 53 | const char HELP_STR_DECOMPRESS_FILE[] = "Decompress a file using the lzx algorithm."; 54 | const char HELP_STR_DISASM[] = "Disasm x86 instructions from a file."; 55 | 56 | const char HELP_STR_VALID_ROM_SIZES[] = "valid opts: 256, 512, 1024."; 57 | 58 | const char HELP_STR_MCPX_ROM[] = "-mcpx \t\t- path to the mcpx file. Should be 512 bytes\n" \ 59 | "\t\t\t- Used for en/decrypting the 2BL.\n" \ 60 | "\t\t\t- Use mcpx 1.0 for BIOS versions <= 4627\n\t\t\t- Use mcpx 1.1 for BIOS versions >= 4817."; 61 | 62 | const char HELP_STR_RC4_KEY[] = " " \ 63 | "\t- path to the %s key file. Should be 16 bytes"; 64 | 65 | const char HELP_STR_RC4_ENC[] = "\t\t- dont encrypt/decrypt the %s"; 66 | 67 | const char HELP_STR_PARAM_EEPROM_KEY[] = "-eepromkey eeprom key file"; 68 | const char HELP_STR_PARAM_BLDR[] = "-bldr - 2BL file"; 69 | const char HELP_STR_PARAM_PRELDR[] = "-preldr - FBL file"; 70 | const char HELP_STR_PARAM_KRNL[] = "-krnl - kernel file"; 71 | const char HELP_STR_PARAM_KRNL_DATA[] = "-krnldata - kernel data section file"; 72 | const char HELP_STR_PARAM_INITTBL[] = "-inittbl - init table file"; 73 | const char HELP_STR_PARAM_CERT_KEY[] = "-certkey - cert key file"; 74 | const char HELP_STR_PARAM_PUB_KEY[] = "-pubkey - public key file"; 75 | const char HELP_STR_PARAM_LS_NV2A_TBL[] = "-nv2a - list NV2A table"; 76 | const char HELP_STR_PARAM_LS_DATA_TBL[] = "-datatbl - list ROM data table"; 77 | const char HELP_STR_PARAM_LS_DUMP_KRNL[] = "-img - list kernel image header info"; 78 | const char HELP_STR_PARAM_LS_KEYS[] = "-keys - list rc4 keys"; 79 | const char HELP_STR_PARAM_EXTRACT_KEYS[] = "-keys - extract rc4 keys"; 80 | const char HELP_STR_PARAM_BFM[] = "-bfm - build a boot from media BIOS"; 81 | const char HELP_STR_PARAM_DECODE_INI[] = "-ini - set the decode settings file"; 82 | const char HELP_STR_PARAM_IN_FILE[] = "-in - input file"; 83 | const char HELP_STR_PARAM_OUT_FILE[] = "-out - output file"; 84 | const char HELP_STR_PARAM_IN_BIOS_FILE[] = "-in - BIOS file"; 85 | const char HELP_STR_PARAM_OUT_BIOS_FILE[] = "-out - BIOS output file; defaults to bios.bin"; 86 | const char HELP_STR_PARAM_SIM_SIZE[] = "-simsize - size of the sim space in bytes. default is 32 bytes"; 87 | const char HELP_STR_PARAM_ROMSIZE[] = "-romsize - rom size in kb"; 88 | const char HELP_STR_PARAM_BINSIZE[] = "-binsize - bin size in kb"; 89 | const char HELP_STR_PARAM_BASE[] = "-base - base offset in bytes"; 90 | const char HELP_STR_PARAM_HACK_INITTBL[] = "-hackinittbl - hack init tbl (size = 0)"; 91 | const char HELP_STR_PARAM_HACK_SIGNATURE[] ="-hacksignature - hack boot signature (signature = 0)"; 92 | const char HELP_STR_PARAM_WDIR[] = "-dir - working directory"; 93 | const char HELP_STR_PARAM_UPDATE_BOOT_PARAMS[] = "-nobootparams - dont update 2BL boot params"; 94 | const char HELP_STR_PARAM_RESTORE_BOOT_PARAMS[] = "-nobootparams - dont restore 2BL boot params (FBL BIOSes only)"; 95 | const char HELP_STR_PARAM_BRANCH[] = "-branch - take unbranchable jumps"; 96 | 97 | #endif // XB_BIOS_TOOL_COMMANDS_H -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | // util.cpp: utility functions. printing to console, changing console color, etc. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | // user incl 32 | #include "util.h" 33 | 34 | void util_setConsoleColor(const int col) 35 | { 36 | static int console_util_color = 0; 37 | 38 | if (col != 0) { 39 | console_util_color = 0; 40 | printf("\033[0m"); 41 | } 42 | 43 | if (col < 0) { 44 | return; 45 | } 46 | 47 | console_util_color = col; 48 | printf("\x1B[%dm", col); 49 | } 50 | void util_setForegroundColor(const int col) 51 | { 52 | int con_col = col; 53 | 54 | if (col >= 0 && col < CONSOLE_COLOR_BLACK) { 55 | con_col += 31; 56 | } 57 | 58 | util_setConsoleColor(con_col); 59 | } 60 | void util_getTimestampStr(size_t timestamp, char* timestamp_str) 61 | { 62 | if (timestamp_str == NULL) 63 | return; 64 | 65 | time_t rawtime = (time_t)timestamp; 66 | struct tm* ptm; 67 | ptm = gmtime(&rawtime); 68 | char* time_str = asctime(ptm); 69 | 70 | if (time_str == NULL) 71 | { 72 | strcpy(timestamp_str, "0"); 73 | } 74 | else 75 | { 76 | time_str[strlen(time_str) - 1] = '\0'; 77 | strcpy(timestamp_str, time_str); 78 | } 79 | } 80 | 81 | void uprintf(char* data, const size_t size, const char* format, ...) 82 | { 83 | // find {1}, {2}, etc and replace with the corresponding argument 84 | 85 | const char START_TOKEN = '{'; 86 | const char END_TOKEN = '}'; 87 | const char* formatPtr = format; 88 | char* bufferPtr = data; 89 | const char* startToken = NULL; 90 | const char* endToken = NULL; 91 | size_t argLen = 0; 92 | 93 | if (data == NULL || format == NULL || size < 1 || strlen(format) < 1) 94 | return; 95 | 96 | while (1) { 97 | if (*formatPtr == '\0') // check if we are done 98 | break; 99 | 100 | // check for token 101 | if (*formatPtr == START_TOKEN) { 102 | startToken = formatPtr; 103 | while (*formatPtr != END_TOKEN) { 104 | if (*formatPtr == '\0') 105 | break; 106 | formatPtr++; 107 | } 108 | 109 | if (*formatPtr != END_TOKEN) 110 | break; 111 | 112 | // replace token with argument 113 | 114 | endToken = formatPtr; 115 | 116 | // get the number between the tokens 117 | int num = 0; 118 | int tokenLen = (endToken - startToken + 1) - 2; // -2 to remove the '{' and '}' 119 | char tokenStr[10] = { 0 }; 120 | 121 | if (tokenLen + 1 > sizeof(tokenStr)) { 122 | break; 123 | } 124 | strncpy(tokenStr, startToken + 1, tokenLen); 125 | tokenStr[tokenLen] = '\0'; 126 | 127 | num = atoi(tokenStr); 128 | if (num < 1) { 129 | break; 130 | } 131 | 132 | // get the argument based on the number 133 | 134 | char* arg = NULL; 135 | va_list ap; 136 | 137 | va_start(ap, format); 138 | for (int i = 0; i < num; ++i) { 139 | arg = va_arg(ap, char*); 140 | if (arg == NULL) { 141 | break; 142 | } 143 | argLen = strlen(arg); 144 | } 145 | va_end(ap); 146 | 147 | if (argLen > 0) { 148 | if (bufferPtr + argLen >= data + size) { 149 | break; 150 | } 151 | memcpy(bufferPtr, arg, argLen); 152 | bufferPtr += argLen; 153 | } 154 | } 155 | else { 156 | // go find next '{' 157 | startToken = formatPtr; 158 | while (*formatPtr != '\0') { 159 | if (*formatPtr == START_TOKEN) { 160 | break; 161 | } 162 | formatPtr++; 163 | } 164 | 165 | // copy up to '{' 166 | argLen = formatPtr - startToken; 167 | if (argLen > 0) { 168 | if (bufferPtr + argLen >= data + size) 169 | { 170 | break; 171 | } 172 | memcpy(bufferPtr, startToken, argLen); 173 | bufferPtr += argLen; 174 | } 175 | 176 | if (*formatPtr == '\0') // check if we are done 177 | break; 178 | 179 | if (*formatPtr != START_TOKEN) 180 | formatPtr += argLen; 181 | } 182 | 183 | if (*formatPtr != START_TOKEN) 184 | formatPtr++; 185 | } 186 | 187 | bufferPtr[0] = '\0'; 188 | } 189 | void uprintc(const int col, const char* format, ...) 190 | { 191 | util_setForegroundColor(col); 192 | va_list args; 193 | va_start(args, format); 194 | vfprintf(stdout, format, args); 195 | va_end(args); 196 | util_setConsoleColor(0); 197 | } 198 | 199 | void uprinth(const uint8_t* data, const size_t size) 200 | { 201 | // print hex str 202 | if (data == NULL || size == 0) 203 | return; 204 | 205 | for (uint32_t i = 0; i < size; i++) { 206 | printf("%02X ", data[i]); 207 | } 208 | 209 | printf("\n"); 210 | } 211 | void uprinta(const uint8_t* data, const size_t size, const int new_line) 212 | { 213 | // print ascii str 214 | if (data == NULL || size == 0) 215 | return; 216 | 217 | for (uint32_t k = 0; k < size; ++k) { 218 | if ((data[k] >= 0x30 && data[k] < 0x39) || 219 | (data[k] >= 50 && data[k] < 132)) { 220 | printf("%c", data[k]); 221 | } 222 | else { 223 | printf("."); 224 | } 225 | } 226 | 227 | if (new_line) 228 | printf("\n"); 229 | } 230 | 231 | void uprinthl(const uint8_t* data, const size_t size, uint32_t per_line, const char* prefix, const int ascii) 232 | { 233 | #define HEX_STR_LEN(x) ((x)*3) 234 | #define MAX_BYTES_PER_LINE 32 235 | #define DEFAULT_BYTES_PER_LINE 8 236 | 237 | char line[((MAX_BYTES_PER_LINE * 3) + 1) + MAX_BYTES_PER_LINE] = { 0 }; 238 | 239 | if (per_line == 0 || per_line > MAX_BYTES_PER_LINE - 1) 240 | per_line = DEFAULT_BYTES_PER_LINE; 241 | 242 | uint32_t j = 0; 243 | for (uint32_t i = 0; i < size; i += per_line) { 244 | if (prefix != NULL) { 245 | printf(prefix); 246 | } 247 | for (j = 0; j < per_line; ++j) { 248 | if (i + j >= size) { 249 | sprintf(line + HEX_STR_LEN(j), "%*c", HEX_STR_LEN(per_line - j), ' '); 250 | break; 251 | } 252 | sprintf(line + HEX_STR_LEN(j), "%02X ", data[i + j]); 253 | } 254 | printf("%s", line); 255 | 256 | if (ascii) 257 | uprinta(data + i, j, 1); 258 | else 259 | printf("\n"); 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/cli_tbl.cpp: -------------------------------------------------------------------------------- 1 | // cli_tbl.cpp: Implements functions for parsing command line arguments based on a command and parameter table. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | 27 | // user incl 28 | #include "cli_tbl.h" 29 | 30 | static int cli_flags[CLI_SWITCH_SIZE] = { 0 }; 31 | 32 | void setParamValue(const PARAM_TBL* param, char* arg); 33 | 34 | int getCmd(const CMD_TBL* cmds, const int cmd_size, const char* arg, const CMD_TBL** cmd) 35 | { 36 | for (int i = 0; i < (int)(cmd_size / sizeof(CMD_TBL)); i++) 37 | { 38 | if (strcmp(arg, cmds[i].sw) == 0) 39 | { 40 | *cmd = &cmds[i]; 41 | return 0; 42 | } 43 | } 44 | return 1; 45 | } 46 | 47 | int parseCli(int argc, char* argv[], const CMD_TBL*& cmd, const CMD_TBL* cmds, const int cmd_size, const PARAM_TBL* params, const int param_size) 48 | { 49 | int i; 50 | int j; 51 | int k; 52 | int startIndex; 53 | bool swNeedValue; 54 | char arg[CLI_SWITCH_MAX_LEN] = {}; 55 | 56 | if (CLI_SWITCH_MAX_COUNT - 1 < param_size / sizeof(PARAM_TBL)) 57 | return CLI_ERROR_INVALID_SW; 58 | if (argc == 1) 59 | return CLI_ERROR_NO_CMD; 60 | if (strlen(argv[1]) < 2) 61 | return CLI_ERROR_INVALID_CMD; 62 | 63 | if (argv[1][0] != '-' && argv[1][0] != '/') 64 | strncpy_s(arg, argv[1], CLI_SWITCH_MAX_LEN-1); 65 | else 66 | strncpy_s(arg, argv[1] + 1, CLI_SWITCH_MAX_LEN-1); 67 | 68 | if(getCmd(cmds, cmd_size, arg, &cmd) == 0) 69 | startIndex = 2; 70 | else 71 | startIndex = 1; 72 | 73 | if (cmd == NULL || cmd->type == 0) 74 | { 75 | printf("Error: Unknown command. %s\n", arg); 76 | return CLI_ERROR_UNKNOWN_CMD; 77 | } 78 | 79 | for (i = startIndex; i < argc; i++) 80 | { 81 | 82 | // check for inferred switches 83 | if (argv[i][0] != '-' && argv[i][0] != '/') 84 | { 85 | for (j = 0; j < sizeof(cmd->inferredSwitches) / sizeof(CLI_SWITCH); j++) 86 | { 87 | if (isFlagClear(cmd->inferredSwitches[j])) 88 | { 89 | for (k = 0; k < (int)(param_size / sizeof(PARAM_TBL)); k++) 90 | { 91 | if (params[k].swType == cmd->inferredSwitches[j]) 92 | { 93 | setFlag(params[k].swType); 94 | setParamValue(¶ms[k], argv[i]); 95 | goto NextArg; 96 | } 97 | } 98 | } 99 | } 100 | 101 | // convert to ' -?' for help; user did the reverse '-? ' 102 | if (cmd->type == CMD_HELP) 103 | { 104 | getCmd(cmds, cmd_size, argv[i], &cmd); 105 | setFlag(SW_HELP); 106 | continue; 107 | } 108 | 109 | printf("Error: No corresponding switch defined for argument, '%s'.\n\nUsage: - \n", argv[i]); 110 | return CLI_ERROR_INVALID_ARG; 111 | 112 | NextArg: 113 | continue; 114 | } 115 | 116 | /*if (strlen(argv[i]) > CLI_SWITCH_MAX_LEN - 1) 117 | { 118 | printf("Error: Invalid switch: %s\n", arg); 119 | return CLI_ERROR_INVALID_SW; 120 | }*/ 121 | 122 | arg[0] = '\0'; 123 | strcat_s(arg, argv[i] + 1); 124 | 125 | // check for explicit switches 126 | for (j = 0; j < (int)(param_size / sizeof(PARAM_TBL)); j++) 127 | { 128 | if (strcmp(arg, params[j].sw) != 0) 129 | continue; 130 | 131 | setFlag(params[j].swType); 132 | 133 | if (isFlagClear(SW_HELP)) 134 | { 135 | swNeedValue = (params[j].cmdType != PARAM_TBL::BOOL) && (params[j].cmdType != PARAM_TBL::FLAG); 136 | if (swNeedValue && i + 1 >= argc) 137 | { 138 | printf("Error: '-%s' switch is missing an argument\n\nUsage: -%s \n", arg, arg); 139 | return CLI_ERROR_MISSING_ARG; 140 | } 141 | 142 | if (swNeedValue && (argv[i + 1][0] == '-' || argv[i + 1][0] == '/')) 143 | { 144 | printf("Error: '-%s' switch has an invaild argument, '%s'\n\nUsage: -%s \n", arg, argv[i + 1], arg); 145 | return CLI_ERROR_INVALID_ARG; 146 | } 147 | 148 | setParamValue(¶ms[j], argv[i + 1]); 149 | 150 | if (swNeedValue) 151 | i++; 152 | } 153 | break; 154 | } 155 | 156 | // convert to ' -?' for help; user did the reverse '-? ' 157 | if (cmd->type == CMD_HELP) 158 | { 159 | getCmd(cmds, cmd_size, arg, &cmd); 160 | setFlag(SW_HELP); 161 | i++; 162 | continue; 163 | } 164 | 165 | if (isFlagClear(SW_HELP) && j >= (int)(param_size / sizeof(PARAM_TBL))) 166 | { 167 | printf("Error: Unknown switch, '-%s'\n", arg); 168 | return CLI_ERROR_UNKNOWN_SW; 169 | } 170 | } 171 | 172 | // skip required switches check for help switch ' -?' 173 | if (isFlagSet(SW_HELP)) 174 | return 0; 175 | 176 | // check for required switches 177 | 178 | bool missing = false; 179 | for (i = 0; i < (int)(param_size / sizeof(PARAM_TBL)); i++) 180 | { 181 | for (j = 0; j < sizeof(cmd->requiredSwitches) / sizeof(cmd->requiredSwitches[0]); j++) 182 | { 183 | if (cmd->requiredSwitches[j] == 0) 184 | break; 185 | 186 | if (params[i].swType != cmd->requiredSwitches[j]) 187 | continue; 188 | 189 | if (isFlagClear(params[i].swType)) 190 | { 191 | strcpy_s(arg, params[i].sw); 192 | 193 | printf("Error: Missing switch, '-%s'\n", params[i].sw); 194 | missing = true; 195 | } 196 | } 197 | } 198 | 199 | if (missing) 200 | return CLI_ERROR_MISSING_SW; 201 | 202 | return 0; 203 | } 204 | 205 | void setParamValue(const PARAM_TBL* param, char* arg) { 206 | if (param->var == NULL) 207 | return; 208 | 209 | switch (param->cmdType) 210 | { 211 | case PARAM_TBL::STR: 212 | *(char**)param->var = arg; 213 | break; 214 | 215 | case PARAM_TBL::INT: 216 | if (strlen(arg) > 2 && arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) // hex 217 | *(int*)param->var = strtol(arg, NULL, 16); 218 | else // decimal 219 | *(int*)param->var = atoi(arg); 220 | break; 221 | 222 | case PARAM_TBL::BOOL: 223 | *(bool*)param->var = !(*(bool*)param->var); 224 | break; 225 | 226 | case PARAM_TBL::FLAG: 227 | *(int*)param->var |= param->swType; 228 | break; 229 | } 230 | } 231 | void setFlag(const CLI_SWITCH sw) 232 | { 233 | cli_flags[sw / CLI_SWITCH_BITS] |= (1 << (sw % CLI_SWITCH_BITS)); 234 | } 235 | void clearFlag(const CLI_SWITCH sw) 236 | { 237 | cli_flags[sw / CLI_SWITCH_BITS] &= ~(1 << (sw % CLI_SWITCH_BITS)); 238 | } 239 | bool isFlagSet(const CLI_SWITCH sw) 240 | { 241 | return (cli_flags[sw / CLI_SWITCH_BITS] & (1 << (sw % CLI_SWITCH_BITS))) != 0; 242 | } 243 | bool isFlagClear(const CLI_SWITCH sw) 244 | { 245 | return (cli_flags[sw / CLI_SWITCH_BITS] & (1 << (sw % CLI_SWITCH_BITS))) == 0; 246 | } 247 | 248 | bool isFlagSetAny(const int sw) 249 | { 250 | // check if any of the flags are set in the switch array. 251 | // sw: the SET switches. eg (1 << 19) | (1 << 20) 252 | // flags: the flags array 253 | // returns: true if any of the flags are set. 254 | 255 | // start with the highest switch 256 | // remove current switch from the switch array 257 | // loop until zero. 258 | 259 | int k = sw; 260 | int j; 261 | int i; 262 | 263 | rep: 264 | j = 0; 265 | i = k; 266 | while (i > 0) 267 | { 268 | i >>= 1; 269 | j++; 270 | } 271 | if (isFlagSet((CLI_SWITCH)(j-1))) 272 | return true; 273 | else 274 | k &= ~(1 << (j-1)); 275 | 276 | if (k != 0) 277 | goto rep; 278 | 279 | return false; 280 | } 281 | -------------------------------------------------------------------------------- /inc/Bios.h: -------------------------------------------------------------------------------- 1 | // Bios.h: handling An Xbox BIOS. 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef XB_BIOS_H 23 | #define XB_BIOS_H 24 | 25 | #include 26 | 27 | // user incl 28 | #include "Mcpx.h" 29 | #include "bldr.h" 30 | #include "rsa.h" 31 | #include "sha1.h" 32 | 33 | #define MIN_BIOS_SIZE 0x40000 // Min bios file/rom size in bytes 34 | #define MAX_BIOS_SIZE 0x100000 // Max bios file/rom size in bytes 35 | #define KD_DELAY_FLAG 0x80000000 // Kernel Delay Flag 36 | 37 | #define ROM_DIGEST_SIZE 0x100 // rom digest size in bytes 38 | 39 | #define PRELDR_BLOCK_SIZE 0x2A00 // preldr block size in bytes 40 | #define PRELDR_PARAMS_SIZE 0x80 // preldr params size in bytes 41 | #define PRELDR_SIZE (PRELDR_BLOCK_SIZE - ROM_DIGEST_SIZE - PRELDR_PARAMS_SIZE) // preldr size in bytes 42 | #define PRELDR_NONCE_SIZE 0x10 // preldr nonce size in bytes 43 | #define PRELDR_REAL_BASE (0xFFFFFFFF - MCPX_BLOCK_SIZE - PRELDR_BLOCK_SIZE + 1) // preldr rom base address ; FFFF.D400 44 | #define PRELDR_REAL_END (PRELDR_REAL_BASE + PRELDR_SIZE) // preldr rom end address ; FFFF.FC80 45 | 46 | #define BLDR_BLOCK_SIZE 0x6000 // 2BL block size in bytes 47 | #define BLDR_RELOC 0x00400000 // 2BL relocation base address 48 | #define BLDR_BASE 0x00090000 // 2BL boot base address 49 | #define BLDR_REAL_BASE (0xFFFFFFFF - MCPX_BLOCK_SIZE - BLDR_BLOCK_SIZE + 1) // 2BL rom base address 50 | 51 | #define BOOT_SIGNATURE 2018801994U // J y T x 52 | 53 | // BIOS load status codes 54 | #define BIOS_LOAD_STATUS_SUCCESS 0 // success; the bios is loaded. 55 | #define BIOS_LOAD_STATUS_INVALID_BLDR 1 // success; but the bldr is invalid. 56 | #define BIOS_LOAD_STATUS_FAILED 2 // ERROR 57 | 58 | // Preldr status codes 59 | #define PRELDR_STATUS_BLDR_DECRYPTED 0 // found and was used to load and decrypt the 2bl. 60 | #define PRELDR_STATUS_FOUND 1 // found but was not used to load the 2bl. 61 | #define PRELDR_STATUS_NOT_FOUND 2 // not found. old bios (mcpx v1.0) or not a valid bios. 62 | #define PRELDR_STATUS_ERROR 3 // ERROR 63 | 64 | #define PRELDR_TEA_ATTACK_ENTRY_POINT 0x007fd588 65 | 66 | // xbox public key structure 67 | typedef struct _XB_PUBLIC_KEY { 68 | RSA_HEADER header; // rsa header structure 69 | uint8_t modulus[264]; // pointer to the modulus. 70 | } XB_PUBLIC_KEY; 71 | 72 | // Preldr structure 73 | typedef struct { 74 | uint8_t* data; 75 | PRELDR_PARAMS* params; 76 | PRELDR_PTR_BLOCK* ptr_block; 77 | PRELDR_FUNC_BLOCK* func_block; 78 | XB_PUBLIC_KEY* public_key; 79 | uint8_t bldr_key[SHA1_DIGEST_LEN]; 80 | uint32_t jmp_offset; 81 | int status; 82 | } PRELDR; 83 | 84 | // 2BL structure 85 | typedef struct { 86 | uint8_t* data; 87 | BLDR_ENTRY* entry; 88 | uint8_t* bfm_key; 89 | BLDR_KEYS* keys; 90 | BOOT_PARAMS* boot_params; 91 | BOOT_LDR_PARAM* ldr_params; 92 | bool encryption_state; 93 | } BLDR; 94 | 95 | // Kernel structure 96 | typedef struct { 97 | uint8_t* compressed_kernel_ptr; 98 | uint8_t* uncompressed_data_ptr; 99 | uint8_t* img; 100 | uint32_t img_size; 101 | bool encryption_state; 102 | } KERNEL; 103 | 104 | // Bios load parameters 105 | typedef struct BIOS_LOAD_PARAMS { 106 | uint32_t romsize; 107 | uint8_t* bldr_key; 108 | uint8_t* kernel_key; 109 | MCPX* mcpx; 110 | bool enc_bldr; 111 | bool enc_kernel; 112 | bool restore_boot_params; 113 | } BIOS_LOAD_PARAMS; 114 | 115 | // Bios build parmeters 116 | typedef struct BIOS_BUILD_PARAMS { 117 | uint8_t* init_tbl; 118 | uint8_t* preldr; 119 | uint8_t* bldr; 120 | uint8_t* compressed_kernel; 121 | uint8_t* kernel_data; 122 | uint8_t* eeprom_key; 123 | uint8_t* cert_key; 124 | uint32_t preldr_size; 125 | uint32_t bldrSize; 126 | uint32_t init_tbl_size; 127 | uint32_t kernel_size; 128 | uint32_t kernel_data_size; 129 | bool bfm; 130 | bool hackinittbl; 131 | bool hacksignature; 132 | bool nobootparams; 133 | bool zero_kernel_key; 134 | } BIOS_BUILD_PARAMS; 135 | 136 | // Bios 137 | class Bios { 138 | public: 139 | uint8_t* data; 140 | uint32_t size; 141 | BLDR bldr; 142 | PRELDR preldr; 143 | KERNEL kernel; 144 | INIT_TBL* init_tbl; 145 | uint8_t* rom_digest; 146 | int available_space; 147 | int bios_status; 148 | 149 | BIOS_LOAD_PARAMS params; 150 | 151 | Bios() { 152 | resetValues(); 153 | }; 154 | ~Bios() { 155 | unload(); 156 | }; 157 | 158 | // unload the bios. reset values and free memory. 159 | void unload(); 160 | 161 | // load bios from memory. 162 | int load(uint8_t* buff, const uint32_t binsize, const BIOS_LOAD_PARAMS* bios_params); 163 | 164 | // build bios. 165 | int build(BIOS_BUILD_PARAMS* build_params, uint32_t binsize, BIOS_LOAD_PARAMS* bios_params); 166 | 167 | // initialize bios and calculate offsets and pointers. 168 | int init(uint8_t* buff, const uint32_t binsize, const BIOS_LOAD_PARAMS* bios_params); 169 | 170 | // calculate initial offsets for the bios. based on params. 171 | // sets up bldr and preldr structs, initTbl and dataTbl pointers. 172 | // Should be invoked when the bios is loaded. 173 | void getOffsets(); 174 | 175 | // calculate offsets and pointers. base on bios data. 176 | // sets up 2bl, krnl and uncompressed_kernel_data pointers. 177 | // Should be invoked when the 2bl is valid. (not encrypted). 178 | void getOffsets2(); 179 | 180 | // validate the 2BL boot param sizes and romsize. 181 | int validateBldrBootParams(); 182 | 183 | // preldr create the bldr key 184 | void preldrCreateKey(uint8_t* sbkey, uint8_t* key); 185 | 186 | // preldr symmetric encryption and decryption for the 2BL. 187 | void preldrSymmetricEncDecBldr(const uint8_t* key, const uint32_t len); 188 | 189 | // validate the preldr and decrypt the 2bl. 190 | // sets up the preldr struct and decrypts the 2bl. 191 | void preldrValidateAndDecryptBldr(); 192 | 193 | // symmetric encryption and decryption for the 2BL. 194 | void symmetricEncDecBldr(const uint8_t* key, const uint32_t len); 195 | 196 | // symmetric encryption and decryption for the kernel. 197 | void symmetricEncDecKernel(); 198 | 199 | // decompress the kernel image from the bios. 200 | // stores results in decompressedKrnl pointer and decompressedKrnlSize. 201 | // returns 0 if successful, 202 | int decompressKrnl(); 203 | 204 | // preldr decrypt preldr public key. 205 | int preldrDecryptPublicKey(); 206 | 207 | private: 208 | // reset bios; reset values. 209 | void resetValues(); 210 | }; 211 | 212 | void bios_init_preldr(PRELDR* preldr); 213 | void bios_init_bldr(BLDR* bldr); 214 | void bios_init_kernel(KERNEL* kernel); 215 | void bios_init_params(BIOS_LOAD_PARAMS* params); 216 | void bios_init_build_params(BIOS_BUILD_PARAMS* params); 217 | void bios_free_build_params(BIOS_BUILD_PARAMS* params); 218 | int bios_check_size(const uint32_t size); 219 | int bios_replicate_data(uint32_t from, uint32_t to, uint8_t* buffer, uint32_t buffersize); 220 | 221 | #endif // !XB_BIOS_H 222 | -------------------------------------------------------------------------------- /src/nt_headers.c: -------------------------------------------------------------------------------- 1 | // nt_headers.c 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | // std incl 23 | #include 24 | #include 25 | #include 26 | 27 | // user incl 28 | #include "nt_headers.h" 29 | #include "util.h" 30 | 31 | void print_image_dos_header(IMAGE_DOS_HEADER* dos_header) 32 | { 33 | char magic[3] = { 0 }; 34 | memcpy(magic, &dos_header->e_magic, 2); 35 | 36 | printf("Magic:\t\t%s ( %02X )\n" \ 37 | "cblp:\t\t0x%02x\n" \ 38 | "cp:\t\t0x%02x\n" \ 39 | "crlc:\t\t0x%02x\n" \ 40 | "cparhdr:\t0x%02x\n" \ 41 | "alloc:\t\t0x%02x - 0x%02x\n" \ 42 | "\nss:\t\t0x%02x\n" \ 43 | "sp:\t\t0x%02x\n" \ 44 | "ip:\t\t0x%02x\n" \ 45 | "cs:\t\t0x%02x\n" \ 46 | 47 | "\nchecksum:\t0x%02x\n" \ 48 | "lfarlc:\t\t0x%02x\n" \ 49 | "ovno:\t\t0x%02x\n" \ 50 | 51 | "oem id:\t\t0x%02x\n" \ 52 | "oem info:\t0x%02x\n" \ 53 | 54 | "nt header ptr:\t0x%02x\n", \ 55 | &magic, dos_header->e_magic, dos_header->e_cblp, dos_header->e_cp, dos_header->e_crlc, dos_header->e_cparhdr, 56 | dos_header->e_minalloc, dos_header->e_maxalloc, dos_header->e_ss, dos_header->e_sp, 57 | dos_header->e_ip, dos_header->e_cs, dos_header->e_csum, dos_header->e_lfarlc, dos_header->e_ovno, dos_header->e_oemid, 58 | dos_header->e_oeminfo, dos_header->e_lfanew); 59 | 60 | printf("reserved 1:\t"); 61 | for (int i = 0; i < 4; i++) 62 | { 63 | printf("0x%x ", dos_header->e_res[i]); 64 | } 65 | printf("\n"); 66 | 67 | printf("reserved 2:\t"); 68 | for (int i = 0; i < 10; i++) 69 | { 70 | printf("0x%x ", dos_header->e_res2[i]); 71 | } 72 | printf("\n"); 73 | } 74 | void print_krnl_data_section_header(IMAGE_DOS_HEADER* dos_header) 75 | { 76 | DATA_SECTION_HEADER* data_section = (DATA_SECTION_HEADER*)&dos_header->e_res2; 77 | printf("\nData Section Header:\n" \ 78 | "uninitialized data:\t%d\n" \ 79 | "initialized data:\t%d\n" \ 80 | "data ptr:\t\t0x%04X\n" \ 81 | "virtual address:\t0x%04X\n", 82 | data_section->uninitializedDataSize, data_section->initializedDataSize, data_section->rawDataPtr, data_section->virtualAddr); 83 | } 84 | void print_image_file_header(COFF_FILE_HEADER* file_header, bool basic) 85 | { 86 | char datetime[28] = { 0 }; 87 | const char* machine_str = { 0 }; 88 | 89 | switch (file_header->machine) 90 | { 91 | case 0x014C: machine_str = "X86 "; break; 92 | default: machine_str = "unk"; break; 93 | } 94 | 95 | util_getTimestampStr(file_header->datetimeStamp, datetime); 96 | 97 | printf("\nFile Header:\nMachine:\t%s ( %X )\nTimestamp:\t%s UTC\n", machine_str, file_header->machine, datetime); 98 | 99 | if (basic) 100 | return; 101 | 102 | printf("Num sections:\t%d\nHeader size: %X\n", file_header->numSections, file_header->sizeOfOptionalHeader); 103 | 104 | if (file_header->symbolTablePtr != 0) 105 | { 106 | printf("Symbol table ptr:\t0x%08X\n" \ 107 | "Num symbols:\t0x%08X\n", file_header->symbolTablePtr, file_header->numSymbols); 108 | } 109 | } 110 | void print_image_optional_header(IMAGE_OPTIONAL_HEADER* optional_header, bool basic) 111 | { 112 | const char* magic_str = NULL; 113 | const char* subsys_str = NULL; 114 | 115 | switch (optional_header->std.magic) 116 | { 117 | case 0x010B: magic_str = "PE32"; break; 118 | case 0x020B: magic_str = "PE32+"; break; 119 | default: magic_str = "unk"; break; 120 | } 121 | 122 | switch (optional_header->subsystem) 123 | { 124 | case 0xE: subsys_str = "xbox"; break; 125 | case 0x3: subsys_str = "windows console"; break; 126 | default: subsys_str = "unk"; break; 127 | } 128 | 129 | printf("\nOptional Header:\nMagic:\t\t%s ( %X )\n" \ 130 | "Headers size:\t%d\nCode size:\t%d\nData size:\t%d\nImage size:\t%d\n" \ 131 | "\nEntry point:\t0x%X ( 0x%X ) main\nCode base:\t0x%X\nData base:\t0x%X\nImage base:\t0x%X\n", 132 | magic_str, optional_header->std.magic, optional_header->headersSize, optional_header->std.codeSize, 133 | optional_header->std.initializedDataSize + optional_header->std.uninitializedDataSize, 134 | optional_header->imageSize, optional_header->std.addressOfEntryPoint, optional_header->imageBase + optional_header->std.addressOfEntryPoint, optional_header->std.baseOfCode, 135 | optional_header->std.baseOfData, optional_header->imageBase); 136 | 137 | if (basic) 138 | return; 139 | 140 | printf("Sect alignment:\t0x%x\nFile alignment:\t0x%x\n" \ 141 | "\nImage version:\t%d.%d\nOperating sys:\t%d.%d\nSubsystem:\t%s ( %X )\n" \ 142 | "\nStack reserve:\t0x%X\nStack commit:\t0x%X\nHeap reserve:\t0x%X\nHeap commit:\t0x%X\n", 143 | optional_header->sectionAlignment, optional_header->fileAlignment, optional_header->majorImageVersion, 144 | optional_header->minorImageVersion, optional_header->majorOperatingSystemVersion, optional_header->minorOperatingSystemVersion, subsys_str, optional_header->subsystem, optional_header->stackReserveSize, 145 | optional_header->stackCommitSize, optional_header->heapReserveSize, optional_header->heapCommitSize); 146 | } 147 | void print_nt_headers(IMAGE_NT_HEADER* nt_header, bool basic) 148 | { 149 | print_image_file_header(&nt_header->file_header, basic); 150 | print_image_optional_header(&nt_header->optional_header, basic); 151 | } 152 | 153 | int dump_nt_headers(uint8_t* data, uint32_t size, bool basic) 154 | { 155 | IMAGE_NT_HEADER* nt = verify_nt_headers(data, size); 156 | if (nt == NULL) { 157 | IMAGE_DOS_HEADER* dos = verify_dos_header(data, size); 158 | if (dos == NULL) { 159 | return 1; 160 | } 161 | print_image_dos_header(dos); 162 | return 1; 163 | } 164 | 165 | printf("PE signature found\n"); 166 | 167 | print_nt_headers(nt, basic); 168 | 169 | return 0; 170 | } 171 | 172 | IMAGE_DOS_HEADER* verify_dos_header(uint8_t* data, uint32_t size) 173 | { 174 | if (data == NULL) 175 | { 176 | printf("Error: Invalid data\n"); 177 | return NULL; 178 | } 179 | 180 | IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)data; 181 | if (IN_BOUNDS(dosHeader, data, size) == false) 182 | { 183 | printf("Error: DOS header out of bounds\n"); 184 | return NULL; 185 | } 186 | 187 | if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) 188 | { 189 | printf("Error: Invalid DOS signature\n"); 190 | return NULL; 191 | } 192 | 193 | return dosHeader; 194 | } 195 | IMAGE_NT_HEADER* verify_nt_headers(uint8_t* data, uint32_t size) 196 | { 197 | IMAGE_DOS_HEADER* dos = NULL; 198 | IMAGE_NT_HEADER* nt = NULL; 199 | 200 | if (data == NULL) 201 | { 202 | printf("Error: Invalid data\n"); 203 | return NULL; 204 | } 205 | 206 | dos = verify_dos_header(data, size); 207 | if (dos == NULL) 208 | { 209 | return NULL; 210 | } 211 | 212 | nt = (IMAGE_NT_HEADER*)(data + dos->e_lfanew); 213 | if (IN_BOUNDS(nt, data, size) == false) 214 | { 215 | printf("Error: NT headers out of bounds\n"); 216 | return NULL; 217 | } 218 | 219 | if (nt->signature != IMAGE_NT_SIGNATURE) 220 | { 221 | printf("Error: Invalid PE signature\n"); 222 | return NULL; 223 | } 224 | 225 | return nt; 226 | } 227 | -------------------------------------------------------------------------------- /inc/lzx.h: -------------------------------------------------------------------------------- 1 | // lzx.h: lzx common definitions 2 | 3 | /* Copyright(C) 2024 tommojphillips 4 | * 5 | * This program is free software : you can redistribute it and /or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program.If not, see < https://www.gnu.org/licenses/>. 17 | */ 18 | 19 | // Author: tommojphillips 20 | // GitHub: https:\\github.com\tommojphillips 21 | 22 | #ifndef LZX_H 23 | #define LZX_H 24 | 25 | // std incl 26 | #include 27 | #include 28 | #include 29 | 30 | #define LZX_WINDOW_SIZE (128*1024) 31 | #define LZX_CHUNK_SIZE (32*1024) 32 | #define LZX_MAX_GROWTH 6144 33 | #define LZX_OUTPUT_SIZE (LZX_CHUNK_SIZE+LZX_MAX_GROWTH) 34 | #define LZX_NUM_REPEATED_OFFSETS 3 35 | #define LZX_MAIN_TREE_ELEMENTS(x) (256 + (x << 3)) 36 | #define LZX_MIN_MATCH 2 37 | #define LZX_MAX_MATCH (LZX_MIN_MATCH + 255) 38 | #define LZX_NUM_PRIMARY_LEN 7 39 | #define LZX_NUM_SECONDARY_LEN ((LZX_MAX_MATCH - LZX_MIN_MATCH + 1) - LZX_NUM_PRIMARY_LEN) 40 | #define LZX_ALIGNED_TABLE_BITS 7 41 | #define LZX_ALIGNED_NUM_ELEMENTS 8 42 | #define LZX_MAX_MAIN_TREE_ELEMENTS 700 43 | #define MAIN_TREE_TABLE_BITS 10 44 | #define SECONDARY_LEN_TREE_TABLE_BITS 8 45 | 46 | // error codes 47 | #define LZX_ERROR_SUCCESS 0 48 | #define LZX_ERROR_FAILED 1 49 | #define LZX_ERROR_BUFFER_OVERFLOW 4 50 | #define LZX_ERROR_OUT_OF_MEMORY 5 51 | #define LZX_ERROR_INVALID_DATA 6 52 | 53 | // block type 54 | #define LZX_BLOCK_TYPE_INVALID 0 55 | #define LZX_BLOCK_TYPE_VERBATIM 1 56 | #define LZX_BLOCK_TYPE_ALIGNED 2 57 | #define LZX_BLOCK_TYPE_UNCOMPRESSED 3 58 | 59 | typedef struct _LZX_BLOCK { 60 | uint16_t compressed_size; 61 | uint16_t uncompressed_size; 62 | } LZX_BLOCK; 63 | 64 | typedef struct { 65 | uint8_t* mem_window; 66 | uint32_t window_size; 67 | uint32_t window_mask; 68 | uint32_t last_matchpos_offset[LZX_NUM_REPEATED_OFFSETS]; 69 | short main_tree_table[1 << MAIN_TREE_TABLE_BITS]; 70 | short secondary_len_tree_table[1 << SECONDARY_LEN_TREE_TABLE_BITS]; 71 | uint8_t main_tree_len[LZX_MAX_MAIN_TREE_ELEMENTS]; 72 | uint8_t secondary_len_tree_len[LZX_NUM_SECONDARY_LEN]; 73 | uint8_t pad1[2]; 74 | uint8_t num_position_slots; 75 | char aligned_table[1 << LZX_ALIGNED_TABLE_BITS]; 76 | uint8_t aligned_len[LZX_ALIGNED_NUM_ELEMENTS]; 77 | short main_tree_left_right[LZX_MAX_MAIN_TREE_ELEMENTS * 4]; 78 | short secondary_len_tree_left_right[LZX_NUM_SECONDARY_LEN * 4]; 79 | const uint8_t* input_curpos; 80 | const uint8_t* end_input_pos; 81 | uint8_t* output_buffer; 82 | uint8_t* input_buffer; 83 | long position_at_start; 84 | uint8_t main_tree_prev_len[LZX_MAX_MAIN_TREE_ELEMENTS]; 85 | uint8_t secondary_len_tree_prev_len[LZX_NUM_SECONDARY_LEN]; 86 | char bitcount; 87 | bool first_time_this_group; 88 | bool error_condition; 89 | uint32_t bitbuf; 90 | long pos; 91 | uint32_t current_file_size; 92 | uint32_t instr_pos; 93 | uint32_t num_cfdata_frames; 94 | long original_block_size; 95 | long block_size; 96 | int block_type; 97 | int decoder_state; 98 | } LZX_DECODER_CONTEXT; 99 | 100 | typedef struct { 101 | uint32_t link; 102 | uint32_t path; 103 | uint32_t repeated_offset[LZX_NUM_REPEATED_OFFSETS]; 104 | uint32_t numbits; 105 | } DECISION_NODE; 106 | 107 | typedef struct { 108 | uint8_t* mem_window; 109 | uint32_t window_size; 110 | uint32_t* tree_root; 111 | uint32_t* left; 112 | uint32_t* right; 113 | uint32_t bitbuf; 114 | char bitcount; 115 | char depth; 116 | bool output_overflow; 117 | uint32_t literals; 118 | uint32_t distances; 119 | uint32_t* dist_data; 120 | uint8_t* lit_data; 121 | uint8_t* item_type; 122 | uint32_t repeated_offset_at_literal_zero[LZX_NUM_REPEATED_OFFSETS]; 123 | uint32_t last_matchpos_offset[LZX_NUM_REPEATED_OFFSETS]; 124 | uint32_t matchpos_table[LZX_MAX_MATCH + 1]; 125 | uint32_t bufpos; 126 | uint8_t slot_table[1024]; 127 | uint8_t* output_buffer_start; 128 | uint8_t* output_buffer_curpos; 129 | uint8_t* output_buffer_end; 130 | uint32_t input_running_total; 131 | uint32_t bufpos_last_output_block; 132 | uint32_t num_position_slots; 133 | uint32_t file_size_for_translation; 134 | uint8_t num_block_splits; 135 | uint8_t first_block; 136 | bool need_to_recalc_stats; 137 | bool first_time_this_group; 138 | uint8_t ones[256]; 139 | uint32_t encoder_second_partition_size; 140 | uint32_t earliest_window_data_remaining; 141 | uint32_t bufpos_at_last_block; 142 | uint8_t* input_ptr; 143 | long input_left; 144 | uint32_t instr_pos; 145 | uint16_t* tree_freq; 146 | uint16_t* tree_sortptr; 147 | uint8_t* len; 148 | short tree_heap[LZX_MAX_MAIN_TREE_ELEMENTS + 2]; 149 | uint16_t tree_leftright[2 * (2 * LZX_MAX_MAIN_TREE_ELEMENTS - 1)]; 150 | uint16_t tree_len_cnt[17]; 151 | short tree_heapsize; 152 | int tree_n; 153 | uint32_t next_tree_create; 154 | uint32_t last_literals; 155 | uint32_t last_distances; 156 | DECISION_NODE* decision_node; 157 | uint8_t main_tree_len[LZX_MAX_MAIN_TREE_ELEMENTS + 1]; 158 | uint8_t secondary_tree_len[LZX_NUM_SECONDARY_LEN + 1]; 159 | uint16_t main_tree_freq[LZX_MAX_MAIN_TREE_ELEMENTS * 2]; 160 | uint16_t main_tree_code[LZX_MAX_MAIN_TREE_ELEMENTS]; 161 | uint8_t main_tree_prev_len[LZX_MAX_MAIN_TREE_ELEMENTS + 1]; 162 | uint16_t secondary_tree_freq[LZX_NUM_SECONDARY_LEN * 2]; 163 | uint16_t secondary_tree_code[LZX_NUM_SECONDARY_LEN]; 164 | uint8_t secondary_tree_prev_len[LZX_NUM_SECONDARY_LEN + 1]; 165 | uint16_t aligned_tree_freq[LZX_ALIGNED_NUM_ELEMENTS * 2]; 166 | uint16_t aligned_tree_code[LZX_ALIGNED_NUM_ELEMENTS]; 167 | uint8_t aligned_tree_len[LZX_ALIGNED_NUM_ELEMENTS]; 168 | uint8_t aligned_tree_prev_len[LZX_ALIGNED_NUM_ELEMENTS]; 169 | uint8_t* real_mem_window; 170 | uint32_t* real_left; 171 | uint32_t* real_right; 172 | uint32_t cfdata_frames; 173 | uint8_t* input_buffer; 174 | uint8_t* output_buffer; 175 | uint32_t output_buffer_size; 176 | uint32_t output_buffer_block_count; 177 | } ENCODER_CONTEXT; 178 | 179 | #ifdef __cplusplus 180 | extern "C" { 181 | #endif 182 | 183 | /* Create lzx decoder */ 184 | LZX_DECODER_CONTEXT* lzx_create_decompression(); 185 | 186 | /* Destroy lzx decoder */ 187 | void lzx_destroy_decompression(LZX_DECODER_CONTEXT* context); 188 | 189 | /* Decompress block */ 190 | int lzx_decompress_block(LZX_DECODER_CONTEXT* context, const uint8_t* src, uint32_t src_size, uint8_t* dest, uint32_t* bytes_decompressed); 191 | 192 | /* Decompress next block */ 193 | int lzx_decompress_next_block(LZX_DECODER_CONTEXT* context, const uint8_t** src, uint32_t* src_size, uint8_t** dest, uint32_t* bytes_decompressed); 194 | 195 | /* Decompress the input buffer block by block into the output buffer 196 | src: Input buffer 197 | src_size: Input buffer size 198 | dest: Address of the output buffer. pre-allocate or null buffer. 199 | dest_size: Output buffer size; returns the output buffer size. if output buffer is pre-allocated, this should be the size of the pre-allocated buffer. 200 | decompressed_size: Returns the decompressed size. 201 | returns 0 on SUCCESS, otherwise LZX_ERROR */ 202 | int lzx_decompress(const uint8_t* src, const uint32_t src_size, uint8_t** dest, uint32_t* dest_size, uint32_t* decompressed_size); 203 | 204 | /* Create lzx encoder */ 205 | ENCODER_CONTEXT* lzx_create_compression(uint8_t* dest); 206 | 207 | /* Destroy lzx encoder */ 208 | void lzx_destroy_compression(ENCODER_CONTEXT* context); 209 | 210 | /* Compress block */ 211 | int lzx_compress_block(ENCODER_CONTEXT* context, const uint8_t* src, uint32_t bytes_read); 212 | 213 | /* Compress next block */ 214 | int lzx_compress_next_block(ENCODER_CONTEXT* context, const uint8_t** src, uint32_t bytes_read, uint32_t* bytes_remaining); 215 | 216 | /* Flush lzx encoder */ 217 | void lzx_flush_compression(ENCODER_CONTEXT* context); 218 | 219 | /* Compress the input buffer block by block into the output buffer 220 | src: Input buffer 221 | src_size: Input buffer size 222 | dest: Address of the output buffer. pre-allocate or null buffer 223 | compressed_size: Returns the compressed size 224 | returns 0 on SUCCESS, otherwise LZX_ERROR */ 225 | int lzx_compress(const uint8_t* src, const uint32_t src_size, uint8_t** dest, uint32_t* compressed_size); 226 | 227 | #ifdef __cplusplus 228 | }; 229 | #endif 230 | 231 | #endif // LZX_H 232 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | xbios.exe 25.07.2024 - tommojphillips 2 | 3 | -------------------------------------------------------------------------------------------------------------------------------- 4 | /? 5 | # Display help 6 | 7 | /ls 8 | # Dump bios info to console. boot params, sizes, signatures, keys, nv2a tbl, etc. 9 | -in - The bios file (req) 10 | -romsize - The rom size in Kb. valid opts: 256, 512, 1024 11 | -nv2a - List nv2a table 12 | -datatbl - List rom data table 13 | -dump-krnl - dump kernel (nt) image info to console 14 | -keys - List Rc4 keys (eeprom, cert, bfm, kernel ) + sb key from mcpx, preldr key (if apl) 15 | -bootable - Check if BIOS is bootable. Checks if and how BIOS gets to 2BL. (visor hack or mcpx validation) 16 | Use '-d' to dump 2BL if found. 17 | /xcode-sim 18 | # Simulate mem-write xcodes and parse x86 instructions. (visor sim) 19 | -in - The input file (req) 20 | -out - The output file 21 | -simsize - The size of the simulated memory in bytes. 22 | -d - write sim memory to a file for analysis in a disassembler. 23 | 24 | /xcode-decode 25 | # Decode xcodes from a bios file or extracted init tbl. currently only supports retail opcodes. 26 | -in - The input file (req) 27 | -d - Write decoded xcodes to a .txt. Use -out to set output file. 28 | -ini - The decode settings file; use to set/change format of decode output. 29 | 30 | /extr 31 | # Extract the 2bl, compressed krnl, uncompressed krnl data, init table 32 | -in - The bios file (req) 33 | -keys - Extract RC4 keys from the BIOS. (eeprom, cert, bfm, kernel ) + sb key from mcpx, preldr key (if apl) 34 | 35 | -bldr - 2bl file path; use to specify output file 36 | -krnl - Compressed kernel file path; use to specify output file 37 | -krnldata - kernel section data file path; use to specify output file 38 | -inittbl - init table file path; use to specify output file 39 | -preldr - preldr file path; use to specify output file 40 | 41 | /bld 42 | # Build a bios from a 2bl, compressed krnl, uncompressed krnl data, init table 43 | -bldr - The boot loader file (req). 44 | -krnl - The kernel file (req). 45 | -krnldata - The kernel data section file (req). 46 | -inittbl - The init table file (req). 47 | -preldr - The preldr file. only use for testing. 48 | -out - The output file. 49 | -romsize - The rom size in Kb. valid opts: 256, 512, 1024. 50 | -binsize - The bin size in Kb. valid opts: 256, 512, 1024. 51 | -certkey - Path to the cert key file. 52 | -eepromkey - Path to the eeprom key file. 53 | -bfm - build a boot-from-media bios. 54 | -enc-krnl - If provided, encrypts the kernel with the kernel key in the 2bl (if found). 55 | -hackinittbl - hack the inittbl size (inittblsize=0) 56 | -hacksignature - hack 2BL boot signature (signature=0xFFFFFFFF) 57 | -nobootparams - don't modify/update the boot params. 58 | 59 | 60 | /split 61 | # Split a bios into banks. Eg: bios.bin 1Mb -> bios.bin 4x 256Kb 62 | -bios - The bios file (req) 63 | -romsize - The rom size in Kb. valid opts: 256, 512, 1024 64 | 65 | /combine 66 | # Combine banks into a single bios. Eg: bios.bin x4 256Kb -> bios.bin 1Mb 67 | * bank arguments are inferred. eg -> -combine bank1.bin bank2.bin 68 | * banks are combined in the order they are specified. 69 | -bank[1-4] - The bank file 70 | -out - The output file 71 | 72 | /x86-encode 73 | # Encode x86 instructions as xcodes. (visor) 74 | * input file must be a binary file containing x86 instructions. 75 | -in - The input file (req) 76 | -out - The output file 77 | 78 | /dump-img 79 | # Dump pe image info to console. PE header etc. 80 | -in - The image file (req) 81 | 82 | /replicate 83 | # replicate a bios 84 | -in - The bios file (req) 85 | -binsize - The output file size. 86 | -romsize - The rom size; BIOS is replicated from romsize upto binsize. 87 | -out - The output file 88 | 89 | /compress 90 | # Compress lzx a file 91 | -in - The input file (req) 92 | -out - The output file (req) 93 | 94 | /decompress 95 | # Decompress lzx a file 96 | -in - The input file (req) 97 | -out - The output file (req) 98 | 99 | /get16 100 | # Get Preldr 16; get first 16 bytes of the 2bl in a bios with a preldr 101 | -in - The input file 102 | 103 | /disasm 104 | # disasemable x86 code 105 | -in - The input file. (req) 106 | -base - The base offset to start disasm. 107 | 108 | -------------------------------------------------------------------------------------------------------------------------------- 109 | Switches: 110 | 111 | -key-bldr 112 | # Path to the 16 byte rc4_key.bin file. 113 | * If key is provided, 2bl is assumed to be encrypted. 114 | * Required for en / decrypting the 2bl. 115 | 116 | -mcpx 117 | # Path to the MCPX ROM file. 118 | * Can be used for decrypting the 2bl instead of the '-key-bldr' switch. 119 | 120 | -key-krnl 121 | # Path to the 16 byte rc4_key.bin file. 122 | * If key is provided, the kernel is assumed to be encrypted. 123 | * This should not be required unless it's a custom bios, as keys are located in the 2bl. 124 | 125 | -enc-bldr 126 | # If flag is provided, the 2bl is assumed to be unencrypted. (in most cases.) 127 | 128 | -enc-krnl 129 | # If flag is provided, the kernel is assumed to be unencrypted. (in most cases.) 130 | 131 | -romsize 132 | # The size of the rom within the bios file size. 133 | * Usually 256KB. if debug or custom bios, this could be 512KB or 1MB. 134 | * A bios is replicate upto the binsize ( binsize / romsize = num_of_replications ) 135 | 136 | -binsize 137 | # The size of the bios file (total size. of the bios file.) 138 | * Cannot be less then romsize. 139 | 140 | -------------------------------------------------------------------------------------------------------------------------------- 141 | Original bios kernel version / build timestamp 142 | 143 | # 3944: Fri Sep 21 11:43:41 2001 UTC 144 | 145 | # 4034: Thu Oct 25 22:26:49 2001 UTC 146 | # 4132: Thu Oct 25 22:26:49 2001 UTC 147 | 148 | # 4627: Tue Jun 04 12:12:32 2002 UTC 149 | # 4627 (debug) Tue Jun 04 14:02:18 2002 UTC 150 | 151 | # 4817: Thu Jul 11 12:09:09 2002 UTC 152 | # 5101: Thu Oct 03 11:18:14 2002 UTC 153 | 154 | # 5530: Tue Apr 29 11:45:37 2003 UTC 155 | # 5713: Tue Aug 12 11:43:10 2003 UTC 156 | # 5838: Tue Dec 09 12:44:11 2003 UTC 157 | 158 | # x2.5035: Sun Jun 05 15:20:55 2005 UTC 159 | 160 | -------------------------------------------------------------------------------------------------------------------------------- 161 | init table version 162 | 163 | < 0x40: Old DVT 3 Boxes with NV2A A02 old metal 7 (NVCLK 155, CPU 665) 164 | = 0x40: New DVT 3 Boxes with NV2A A02 new metal 7 (Faster) 165 | = 0x46: DVT4/5 166 | > 0x46: DVT6 167 | 168 | -------------------------------------------------------------------------------------------------------------------------------- 169 | X86 to Xcodes 170 | 171 | Machine code: (8 bytes) 172 | 0000: B8 ED 0B F0 173 | 0004: FF FF E0 90 174 | 175 | Xcodes: ---> Assembly: 176 | 0000: mem_write 0x00, 0xf00bedb8 mov eax, 0xfff00bed 177 | 0009: mem_write 0x04, 0x90e0ffff jmp eax 178 | nop 179 | 180 | Byte code: (18 bytes) 181 | 0000: 03 00 00 00 182 | 0004: 00 B8 ED 0B 183 | 0008: F0 03 04 00 184 | 000C: 00 00 FF FF 185 | 0010: E0 90 186 | 187 | 8 bytes -> 18 bytes. 188 | That is a factor of 2.25x increase in code size. 189 | -------------------------------------------------------------------------------------------------------------------------------- 190 | /get16 -try it yourself. 191 | Brute forcing the first 16 bytes of the 2BL from BIOSes with a preldr. 192 | # the first 16 bytes of the 2BL is zeroed during the build process to prevent rc4 attacks 193 | # the original (unencrypted) 16 bytes consists of the 2bl loader params which holds a pointer to the 2bl entry point (4 bytes) and some zero space. 194 | # we know what the original versions of these bytes are. calculated from offsets within the preldr. it's just 2bl entry offset + 2bl base. 195 | 196 | -------------------------------------------------------------------------------------------------------------------------------- 197 | CALULATED BYTES: -> BC 01 09 00 00 00 00 00 00 00 00 00 00 00 00 00 198 | -------------------------------------------------------------------------------------------------------------------------------- 199 | 200 | pseudo code: 201 | # 2 loops: 202 | # 1: loop 0 - num_guessing 203 | # 2: loop 0 - 255 204 | # 205 | # get test_byte; 206 | # copy test_byte to test_index. 207 | # decrypt 2bl. 208 | # compare test_byte to known_byte at test_index. 209 | # if match; save test_byte. increment test_index; 210 | # revert 2bl state to encrypted. 211 | # do it until we are at num_guessing 212 | 213 | There's only 4080 combinations at worst 214 | -------------------------------------------------------------------------------------------------------------------------------- 215 | output: 216 | 217 | 90 218 | 90 13 219 | 90 13 6F 220 | 90 13 6F 1D 221 | 90 13 6F 1D 1B 222 | 90 13 6F 1D 1B E9 223 | 90 13 6F 1D 1B E9 91 224 | 90 13 6F 1D 1B E9 91 D9 225 | 90 13 6F 1D 1B E9 91 D9 15 226 | 90 13 6F 1D 1B E9 91 D9 15 FD 227 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 228 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 0A 229 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 0A 82 230 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 0A 82 60 231 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 0A 82 60 78 232 | 90 13 6F 1D 1B E9 91 D9 15 FD E9 0A 82 60 78 6B 233 | 234 | -------------------------------------------------------------------------------------------------------------------------------- 235 | -------------------------------------------------------------------------------- /src/sha1.c: -------------------------------------------------------------------------------- 1 | // sha1.cpp: defines functions for SHA-1 hashing 2 | 3 | // GitHub: https://github.com/XboxDev/xbedump 4 | // License: ?? 5 | // 6 | // credit to XboxDev, and the authors of xbedump 7 | // Michael Steil (mist64) 8 | // Franz 9 | 10 | /* sha1.cpp: defines functions for SHA-1 hashing 11 | * 12 | * Description: 13 | * This file implements the Secure Hashing Algorithm 1 as 14 | * defined in FIPS PUB 180-1 published April 17, 1995. 15 | * 16 | * The SHA-1, produces a 160-bit message digest for a given 17 | * data stream. It should take about 2**n steps to find a 18 | * message with the same digest as a given message and 19 | * 2**(n/2) to find any two messages with the same digest, 20 | * when n is the digest size in bits. Therefore, this 21 | * algorithm can serve as a means of providing a 22 | * "fingerprint" for a message. 23 | * 24 | * Portability Issues: 25 | * SHA-1 is defined in terms of 32-bit "words". This code 26 | * uses (included via "sha1.h" to define 32 and 8 27 | * bit unsigned integer types. If your C compiler does not 28 | * support 32 bit unsigned integers, this code is not 29 | * appropriate. 30 | * 31 | * Caveats: 32 | * SHA-1 is designed to work with messages less than 2^64 bits 33 | * long. Although SHA-1 allows a message digest to be generated 34 | * for messages of any number of bits less than 2^64, this 35 | * implementation only works with messages with a length that is 36 | * a multiple of the size of an 8-bit character. 37 | */ 38 | 39 | #include "sha1.h" 40 | 41 | #define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits)))) 42 | 43 | void SHA1PadMessage(SHA1Context*); 44 | void SHA1ProcessMessageBlock(SHA1Context*); 45 | 46 | /* 47 | * SHA1Reset 48 | * 49 | * Description: 50 | * This function will initialize the SHA1Context in preparation 51 | * for computing a new SHA1 message digest. 52 | * 53 | * Parameters: 54 | * context: [in/out] 55 | * The context to reset. 56 | * 57 | * Returns: 58 | * sha Error Code. 59 | */ 60 | int SHA1Reset(SHA1Context* context) 61 | { 62 | if (!context) 63 | { 64 | return SHA_STATUS_STATE_NULL; 65 | } 66 | 67 | context->length_low = 0; 68 | context->length_high = 0; 69 | context->block_index = 0; 70 | 71 | context->intermediate_hash[0] = 0x67452301; 72 | context->intermediate_hash[1] = 0xEFCDAB89; 73 | context->intermediate_hash[2] = 0x98BADCFE; 74 | context->intermediate_hash[3] = 0x10325476; 75 | context->intermediate_hash[4] = 0xC3D2E1F0; 76 | 77 | context->computed = 0; 78 | context->corrupted = 0; 79 | 80 | return SHA_STATUS_SUCCESS; 81 | } 82 | 83 | /* 84 | * SHA1Result 85 | * 86 | * Description: 87 | * This function will return the 160-bit message digest into the 88 | * Message_Digest array provided by the caller. 89 | * NOTE: The first octet of hash is stored in the 0th element, 90 | * the last octet of hash in the 19th element. 91 | * 92 | * Parameters: 93 | * context: [in/out] 94 | * The context to use to calculate the SHA-1 hash. 95 | * Message_Digest: [out] 96 | * Where the digest is returned. 97 | * 98 | * Returns: 99 | * sha Error Code. 100 | */ 101 | int SHA1Result(SHA1Context* context, uint8_t digest[SHA1_DIGEST_LEN]) 102 | { 103 | int i; 104 | 105 | if (!context || !digest) { 106 | return SHA_STATUS_STATE_NULL; 107 | } 108 | 109 | if (context->corrupted) { 110 | return context->corrupted; 111 | } 112 | 113 | if (!context->computed) { 114 | SHA1PadMessage(context); 115 | for(i=0; i<64; ++i) { 116 | context->block[i] = 0; 117 | } 118 | 119 | context->length_low = 0; 120 | context->length_high = 0; 121 | context->computed = 1; 122 | 123 | } 124 | 125 | for(i = 0; i < SHA1_DIGEST_LEN; ++i) { 126 | digest[i] = (uint8_t)(context->intermediate_hash[i >> 2] >> 8 * (3 - (i & 0x03))); 127 | } 128 | 129 | return SHA_STATUS_SUCCESS; 130 | } 131 | 132 | /* SHA1Input 133 | * 134 | * Description: 135 | * This function accepts an array of octets as the next portion 136 | * of the message. 137 | * 138 | * Parameters: 139 | * context: [in/out] 140 | * The SHA context to update 141 | * message_array: [in] 142 | * An array of characters representing the next portion of 143 | * the message. 144 | * length: [in] 145 | * The length of the message in message_array 146 | * 147 | * Returns: 148 | * sha Error Code. 149 | */ 150 | int SHA1Input(SHA1Context* context, const uint8_t *message, uint32_t len) 151 | { 152 | if (!len) return SHA_STATUS_SUCCESS; 153 | 154 | if (!context || !message) return SHA_STATUS_STATE_NULL; 155 | 156 | if (context->computed) { 157 | context->corrupted = SHA_STATUS_STATE_ERROR; 158 | return SHA_STATUS_STATE_ERROR; 159 | } 160 | 161 | if (context->corrupted) return context->corrupted; 162 | 163 | while(len-- && !context->corrupted) { 164 | if (context->block_index >= 64) { 165 | context->corrupted = SHA_STATUS_INPUT_TOO_LONG; 166 | return SHA_STATUS_INPUT_TOO_LONG; 167 | } 168 | 169 | context->block[context->block_index] = (*message & 0xFF); 170 | 171 | context->block_index++; 172 | 173 | context->length_low += 8; 174 | 175 | if (context->length_low == 0) { 176 | context->length_high++; 177 | 178 | if (context->length_high == 0) { // Message is too long 179 | context->corrupted = SHA_STATUS_INPUT_TOO_LONG; 180 | } 181 | } 182 | 183 | if (context->block_index == 64) { // Process the message block 184 | SHA1ProcessMessageBlock(context); 185 | } 186 | 187 | message++; 188 | } 189 | 190 | return SHA_STATUS_SUCCESS; 191 | } 192 | 193 | /* SHA1ProcessMessageBlock 194 | * 195 | * Description: 196 | * This function will process the next 512 bits of the message 197 | * stored in the block array. 198 | */ 199 | void SHA1ProcessMessageBlock(SHA1Context *context) 200 | { 201 | // Constants defined in SHA-1 202 | const uint32_t K[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; 203 | 204 | int t; // Loop counter 205 | uint32_t temp; // Temporary word value 206 | uint32_t W[80]; // Word sequence 207 | uint32_t A, B, C, D, E; // Word buffers 208 | 209 | for(t = 0; t < 16; t++) { 210 | W[t] = context->block[t * 4] << 24; 211 | W[t] |= context->block[t * 4 + 1] << 16; 212 | W[t] |= context->block[t * 4 + 2] << 8; 213 | W[t] |= context->block[t * 4 + 3]; 214 | } 215 | 216 | for(t = 16; t < 80; t++) { 217 | W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 218 | } 219 | 220 | A = context->intermediate_hash[0]; 221 | B = context->intermediate_hash[1]; 222 | C = context->intermediate_hash[2]; 223 | D = context->intermediate_hash[3]; 224 | E = context->intermediate_hash[4]; 225 | 226 | for(t = 0; t < 20; t++) { 227 | temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 228 | E = D; 229 | D = C; 230 | C = SHA1CircularShift(30,B); 231 | 232 | B = A; 233 | A = temp; 234 | } 235 | 236 | for(t = 20; t < 40; t++) { 237 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 238 | E = D; 239 | D = C; 240 | C = SHA1CircularShift(30,B); 241 | B = A; 242 | A = temp; 243 | } 244 | 245 | for(t = 40; t < 60; t++) { 246 | temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 247 | E = D; 248 | D = C; 249 | C = SHA1CircularShift(30,B); 250 | B = A; 251 | A = temp; 252 | } 253 | 254 | for(t = 60; t < 80; t++) { 255 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 256 | E = D; 257 | D = C; 258 | C = SHA1CircularShift(30,B); 259 | B = A; 260 | A = temp; 261 | } 262 | 263 | context->intermediate_hash[0] += A; 264 | context->intermediate_hash[1] += B; 265 | context->intermediate_hash[2] += C; 266 | context->intermediate_hash[3] += D; 267 | context->intermediate_hash[4] += E; 268 | 269 | context->block_index = 0; 270 | } 271 | 272 | /* SHA1PadMessage 273 | * 274 | * Description: 275 | * According to the standard, the message must be padded to an even 276 | * 512 bits. The first padding bit must be a '1'. The last 64 277 | * bits represent the length of the original message. All bits in 278 | * between should be 0. This function will pad the message 279 | * according to those rules by filling the Message_Block array 280 | * accordingly. It will also call the ProcessMessageBlock function 281 | * provided appropriately. When it returns, it can be assumed that 282 | * the message digest has been computed. 283 | * 284 | * Parameters: 285 | * context: [in/out] 286 | * The context to pad 287 | * ProcessMessageBlock: [in] 288 | * The appropriate SHA*ProcessMessageBlock function 289 | */ 290 | void SHA1PadMessage(SHA1Context *context) 291 | { 292 | /*Check to see if the current message block is too small to hold 293 | the initial padding bits and length. If so, we will pad the 294 | block, process it, and then continue padding into a second block.*/ 295 | 296 | if (context->block_index > 55) { 297 | context->block[context->block_index++] = 0x80; 298 | while(context->block_index < 64) { 299 | context->block[context->block_index++] = 0; 300 | } 301 | 302 | SHA1ProcessMessageBlock(context); 303 | 304 | while(context->block_index < 56) { 305 | context->block[context->block_index++] = 0; 306 | } 307 | } 308 | else { 309 | context->block[context->block_index++] = 0x80; 310 | while(context->block_index < 56) { 311 | 312 | context->block[context->block_index++] = 0; 313 | } 314 | } 315 | 316 | context->block[56] = (context->length_high >> 24); 317 | context->block[57] = (uint8_t)(context->length_high >> 16); 318 | context->block[58] = (uint8_t)(context->length_high >> 8); 319 | context->block[59] = (uint8_t)(context->length_high); 320 | 321 | context->block[60] = context->length_low >> 24; 322 | context->block[61] = (uint8_t)(context->length_low >> 16); 323 | context->block[62] = (uint8_t)(context->length_low >> 8); 324 | context->block[63] = (uint8_t)(context->length_low); 325 | 326 | SHA1ProcessMessageBlock(context); 327 | } 328 | -------------------------------------------------------------------------------- /tests/test.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM test script for xbios.exe 3 | 4 | cls 5 | 6 | setlocal enabledelayedexpansion 7 | 8 | if "%~1" == "-?" goto :help 9 | if "%~1" == "/?" goto :help 10 | 11 | :setup 12 | 13 | title xbios testing 14 | 15 | REM ensure we got (cmpsrc.exe) on the PATH. 16 | where "cmpsrc.exe" 2>nul || ( 17 | echo tommojphillips' "cmpsrc.exe" not found. 18 | echo https://github.com/tommojphillips/CompareSrc/releases/ 19 | exit /b 1 20 | ) 21 | 22 | REM ensure we we in the correct directory 23 | if NOT "%CD%\" == "%~dp0" ( 24 | echo Change directory to %~dp0 25 | exit /b 1 26 | ) 27 | 28 | set "error_flag=0" 29 | 30 | set "exe=..\bin\xbios.exe" 31 | 32 | set "MCPX_ROM_1_0=-mcpx mcpx\mcpx_1.0.bin" 33 | set "MCPX_ROM_1_1=-mcpx mcpx\mcpx_1.1.bin" 34 | 35 | if not exist "mcpx" mkdir mcpx 36 | if not exist "bios" mkdir bios 37 | 38 | if not exist "bios\preldr" mkdir bios\preldr 39 | if not exist "bios\custom" mkdir bios\custom 40 | if not exist "bios\custom_512kb_noenc" mkdir bios\custom_512kb_noenc 41 | 42 | if not exist "bios\og_1_0" mkdir bios\og_1_0 43 | if not exist "bios\og_1_1" mkdir bios\og_1_1 44 | if not exist "bios\512kb" mkdir bios\512kb 45 | if not exist "bios\img" mkdir bios\img 46 | if not exist "logs\" mkdir logs 47 | 48 | set "x3_preldr=bios\preldr\x3preldr.bin" 49 | 50 | if not exist "decode.ini" echo. > decode.ini 51 | 52 | :cleanup_test_files 53 | echo Cleaning up test files... 54 | del /q logs\*.log 2>nul || ( 55 | echo Failed to clear logs directory 56 | exit /b 1 57 | ) 58 | del /q *.bin 2>nul || ( 59 | echo Failed to clear root directory 60 | exit /b 1 61 | ) 62 | del /q *.img 2>nul || ( 63 | echo Failed to clear root directory 64 | exit /b 1 65 | ) 66 | echo Cleaned up. 67 | if "%~1" == "-c" exit /b 0 68 | 69 | :check_files 70 | if not exist "mcpx\mcpx_1.0.bin" ( 71 | echo mcpx\mcpx_1.0.bin not found 72 | exit /b 1 73 | ) 74 | if not exist "mcpx\mcpx_1.1.bin" ( 75 | echo mcpx\mcpx_1.1.bin not found 76 | exit /b 1 77 | ) 78 | 79 | if not exist "!exe!" ( 80 | echo '!exe!' not found 81 | exit /b 1 82 | ) 83 | 84 | if not exist "!x3_preldr!" ( 85 | echo bone stock x3 preldr not found. Used to verify preldr was extracted correctly. ^( for BIOSes ^>= 4817 ^) 86 | exit /b 1 87 | ) 88 | 89 | :run_tests 90 | set jobs_passed=0 91 | set jobs_total=0 92 | set "cur_job=" 93 | 94 | set "test_group=%~1" 95 | 96 | if "!test_group!" == "-1.0" ( 97 | echo Running tests for 1.0 bios... 98 | goto :mcpx_1_0_bios_tests 99 | ) else if "!test_group!" == "-1.1" ( 100 | echo Running tests for 1.1 bios... 101 | goto :mcpx_1_1_bios_tests 102 | ) else if "!test_group!" == "-512" ( 103 | echo Running tests for 512kb bios... 104 | goto :mcpx_1_0_512kb_bios_tests 105 | ) else if "!test_group!" == "-custom" ( 106 | echo Running custom bios tests... 107 | goto :custom_bios_tests 108 | ) else if "!test_group!" == "-img" ( 109 | echo Running tests for xb img files... 110 | goto :img_tests 111 | ) else if NOT "!test_group!" == "" ( 112 | echo Error: unknown test option '!test_group!' 113 | exit /b 1 114 | ) 115 | goto :execute_tests 116 | 117 | :execute_tests 118 | REM test help 119 | call :do_test "-?" 0 120 | 121 | REM test garbage input 122 | call :do_test "-ls noexist.bin" 1 123 | call :do_test "-ls !exe!" 1 124 | call :do_test "-nocommand blah" 1 125 | call :do_test "-ls very_very_very_very_very_very_ver_very_very_very_very_long_file_name.bin" 1 126 | call :do_test "-ls_very_very_very_verry_veryy_very_very_very_very_long_command.bin bios.bin" 1 127 | 128 | REM ensure we got help for ALL commands 129 | call :do_test "-? -help-all" 0 130 | 131 | REM run original tests for bios less than 4817 132 | :mcpx_1_0_bios_tests 133 | call :run_og_test "bios\og_1_0" "%MCPX_ROM_1_0%" 134 | 135 | for %%f in (bios\og_1_0\*.bin) do ( 136 | set "arg=%%f" 137 | set arg_name=%%~nf 138 | 139 | call :do_test "-split !arg!" 0 "!arg_name!" 140 | 141 | REM note this test expects bios to be 1MB 142 | call :do_test "-combine !arg_name!_bank1.bin !arg_name!_bank2.bin !arg_name!_bank3.bin !arg_name!_bank4.bin" 0 "!arg_name!" 143 | 144 | call :cmp_file "!arg_name!_bank1.bin" "!arg_name!_bank2.bin" 145 | call :cmp_file "!arg_name!_bank1.bin" "!arg_name!_bank3.bin" 146 | call :cmp_file "!arg_name!_bank1.bin" "!arg_name!_bank4.bin" 147 | ) 148 | if "!test_group!" == "-1.0" goto :exit 149 | 150 | REM run original tests for bios greater than or equal to 4817 151 | :mcpx_1_1_bios_tests 152 | call :run_og_test "bios\og_1_1" "%MCPX_ROM_1_1%" 153 | 154 | for %%f in (bios\og_1_1\*.bin) do ( 155 | set "arg=%%f" 156 | set arg_name=%%~nf 157 | 158 | REM test extracting preldr. cmp preldr. 159 | call :do_test "-extr !arg! %MCPX_ROM_1_1% -preldr preldr.bin" 0 160 | 161 | REM compare preldr with REAL preldr. ensure we extracting it exactly as intended. 162 | call :cmp_file "preldr.bin" "!x3_preldr!" 163 | ) 164 | if "!test_group!" == "-1.1" goto :exit 165 | 166 | REM run original tests for 512kb bios (less than 4817) 167 | :mcpx_1_0_512kb_bios_tests 168 | call :run_og_test "bios\512kb" "%MCPX_ROM_1_0%" "-binsize 512 -romsize 512" 169 | 170 | for %%f in (bios\512kb\*.bin) do ( 171 | set "arg=%%f" 172 | set arg_name=%%~nf 173 | 174 | call :do_test "-split !arg! -romsize 512" 0 "!arg_name!" 175 | call :do_test "-combine !arg_name!_bank1.bin !arg_name!_bank2.bin" 0 "!arg_name!" 176 | 177 | call :cmp_file "!arg_name!_bank1.bin" "!arg_name!_bank2.bin" 178 | ) 179 | if "!test_group!" == "-512" goto :exit 180 | 181 | :custom_bios_tests 182 | 183 | REM custom bios decoding and visor simulation 184 | for %%f in (bios\custom\*.bin) do ( 185 | set "arg=%%f" 186 | set arg_name=%%~nf 187 | 188 | call :run_decode_xcode_tests 189 | 190 | call :do_test "-xcode-sim !arg!" 0 "!arg_name!" 191 | call :do_test "-xcode-sim !arg! -d -out mem_sim.bin" 0 "!arg_name!" 192 | ) 193 | 194 | REM custom bios that need 512kb and w/ no bldr (2bl) encryption (x2) 195 | call :run_og_test "bios\custom_512kb_noenc" "" "-romsize 512 -enc-bldr -enc-krnl" 196 | 197 | if "!test_group!" == "-custom" goto :exit 198 | 199 | :img_tests 200 | REM test xb img files 201 | for %%f in (bios\img\*.img) do ( 202 | set "arg=%%f" 203 | set arg_name=%%~nf 204 | 205 | call :do_test "-dump-img !arg!" 0 "!arg_name!" 206 | ) 207 | if "!test_group!" == "-img" goto :exit 208 | 209 | :exit 210 | :error 211 | if !jobs_total! equ 0 ( 212 | echo No tests were found to run. 213 | ) 214 | if !error_flag! neq 0 ( 215 | echo Test !jobs_total! failed. expected: '!expected_error!' got: '!last_error!' 216 | REM ask user to if they want to see the log 217 | :ask_log 218 | set "view_log=n" 219 | set /p "view_log=Rerun? (y/n): " 220 | if /i "!view_log!" == "y" ( 221 | cls 222 | echo !cur_job! 223 | !cur_job! 224 | echo. 225 | goto :ask_log 226 | ) 227 | exit /b 1 228 | ) else ( 229 | echo. 230 | echo !jobs_passed!/!jobs_total! tests passed. 231 | ) 232 | 233 | endlocal 234 | exit /b !last_error! 235 | 236 | :do_test 237 | if NOT !error_flag! == 0 exit /b 0 238 | 239 | set "cur_job=!exe! %~1" 240 | set "expected_error=%~2" 241 | set "job_name=%~3" 242 | 243 | if "%~1" == "" exit /b 0 244 | 245 | REM get cmd from cur_job 246 | for /f "tokens=1 delims= " %%a in ("!cur_job!") do set "cmd=%%a" 247 | set "cmd=!cmd:~1!" 248 | 249 | if "%expected_error%" == "" set "expected_error=0" 250 | 251 | set /a jobs_total+=1 252 | 253 | echo. 254 | echo Test !jobs_total! '!cur_job!' 255 | 256 | !cur_job! > nul 2> nul 257 | set last_error=!errorlevel! 258 | if !errorlevel! neq !expected_error! ( 259 | set error_flag=!last_error! 260 | exit /b 0 261 | ) 262 | 263 | set /a jobs_passed+=1 264 | echo Pass. 265 | 266 | exit /b 0 267 | 268 | :cmp_file 269 | REM check files match using cmpsrc.exe 270 | if NOT !error_flag! == 0 exit /b 0 271 | 272 | set /a jobs_total+=1 273 | set expected_error=0 274 | set "cur_job=cmpsrc -f %~1 %~2 -c" 275 | 276 | echo. 277 | echo Test !jobs_total! '!cur_job!' 278 | 279 | !cur_job! 280 | 281 | set last_error=!errorlevel! 282 | if !errorlevel! neq !expected_error! ( 283 | set error_flag=!last_error! 284 | echo. 285 | exit /b 0 286 | ) 287 | 288 | set /a jobs_passed+=1 289 | echo Pass. 290 | 291 | exit /b 0 292 | 293 | :help 294 | echo Usage: %~nx0 [-h] [-c] [-1.0] [-1.1] [-512] 295 | echo. 296 | echo -h: Display this help message 297 | echo -c: Clean up the test directory 298 | echo -1.0: Run tests for mcpx 1.0 299 | echo -1.1: Run tests for mcpx 1.1 300 | echo -512: Run tests for 512kb bios 301 | echo -custom: Run tests for custom bios 302 | exit /b 0 303 | 304 | :run_og_test 305 | set "bios_dir=%~1" 306 | set "mcpx_rom=%~2" 307 | set "extra_args=%~3" 308 | 309 | for %%f in (!bios_dir!\*.bin) do ( 310 | set "arg=%%f" 311 | set arg_name=%%~nf 312 | REM test all original bios are decryptable using specified mcpx rom 313 | 314 | call :do_test "-ls !arg! !mcpx_rom! !extra_args!" 0 "!arg_name!" 315 | call :do_test "-ls !arg! -nv2a" 0 "!arg_name!" 316 | call :do_test "-ls !arg! -datatbl" 0 "!arg_name!" 317 | call :do_test "-ls !arg! -img !mcpx_rom! !extra_args!" 0 "!arg_name!" 318 | 319 | call :run_decode_xcode_tests 320 | 321 | REM test extracting bios 322 | call :do_test "-extr !arg! !mcpx_rom! !extra_args! -krnl krnl.bin" 0 323 | 324 | REM decompress extracted krnl. 325 | call :do_test "-decompress krnl.bin -out krnl_decompressed.img" 0 "!arg_name!" 326 | 327 | REM cmp decompressed files 328 | call :cmp_file "krnl_decompressed.img" "krnl.img" 329 | 330 | REM compress decompressed extracted krnl. 331 | call :do_test "-compress krnl_decompressed.img -out krnl_compressed.bin" 0 "!arg_name!" 332 | 333 | REM cmp compressed files. 334 | call :cmp_file "krnl.bin" "krnl_compressed.bin" 335 | 336 | REM build that extracted bios ; replicate to 1mb ; encrypt kernel; encrypting with mcpx 1.0 337 | call :do_test "-bld -bldr bldr.bin -inittbl inittbl.bin -krnl krnl.bin -krnldata krnl_data.bin %MCPX_ROM_1_0% -enc-krnl !extra_args! -binsize 1024 -out bios.bin" 0 338 | 339 | REM test built bios; running -ls calls most things in the program. 340 | call :do_test "-ls bios.bin %MCPX_ROM_1_0% !extra_args!" 0 341 | 342 | REM compare decompressed kernel with an already decompressed kernel image to ensure we havent fucked anything up. 343 | call :cmp_file "krnl.img" "bios\img\!arg_name!_krnl.img" 344 | ) 345 | exit /b 0 346 | 347 | :run_decode_xcode_tests 348 | call :do_test "-xcode-decode !arg!" 0 "!arg_name!" 349 | call :do_test "-xcode-decode -ini ..\decode_settings.ini !arg!" 0 "!arg_name!" 350 | call :do_test "-xcode-decode -ini ..\decode_settings2.ini !arg!" 0 "!arg_name!" 351 | call :do_test "-xcode-decode -ini ..\decode_settings3.ini !arg!" 0 "!arg_name!" 352 | exit /b 0 -------------------------------------------------------------------------------- /DecodeSettings.md: -------------------------------------------------------------------------------- 1 | ### Table of Contents 2 | 3 | - [Decode Command](./README.md#xcode-decode-command) 4 | - [Example Settings (decode_settings.ini)](./decode_settings.ini) 5 | - [Example Output](#example-output) 6 | 7 | ### Xcode Decode settings 8 | 9 | Specify the xcode format 10 | 11 | | `format_str=` | Desc | 12 | | ------------ | ------------------- | 13 | | `{offset}` | The offset | 14 | | `{op}` | The opcode string | 15 | | `{addr}` | The address string | 16 | | `{data}` | The data string | 17 | | `{comment}` | The xcode comment | 18 | 19 | ``` 20 | format_str={offset}: {op} {addr} {data} {comment} 21 | ``` 22 | 23 | `> 0080: xc_mem_write, 0x0, 0xF4 ; ` 24 | 25 | ``` 26 | format_str=xcode<{op}, {addr}, {data}> {comment} 27 | ``` 28 | 29 | `> xcode ; ` 30 | 31 | --- 32 | 33 | Specify the address format in a jump instruction. 34 | 35 | | `jmp_str=` | Desc | 36 | | --------- | ------------- | 37 | | `{label}` | The label | 38 | 39 | ``` 40 | jmp_str={label} 41 | ``` 42 | 43 | `xcode` 44 | 45 | ``` 46 | jmp_str={label}-$-4 47 | ``` 48 | 49 | `xcode` 50 | 51 | --- 52 | 53 | Specify the number format. 54 | 55 | | `num_str=`| Desc | 56 | | --------- | ------- | 57 | | `{hex}` | hex | 58 | | `{hex8}` | hex8 | 59 | | `{HEX}` | HEX | 60 | | `{HEX8}` | HEX8 | 61 | 62 | `xcode` 63 | 64 | `xcode` 65 | 66 | `xcode` 67 | 68 | `xcode` 69 | 70 | --- 71 | 72 | Specify if a label is on the same line as the xcode. 73 | 74 | | `label_on_new_line=` | Desc | 75 | | --------| ----------------- | 76 | | `true` | Label on new line | 77 | | `false` | Label in front | 78 | 79 | ``` 80 | label1: xcode 81 | ``` 82 | 83 | ``` 84 | label1: 85 | xcode 86 | ``` 87 | 88 | --- 89 | 90 | Specify if the xcode ouput is aligned/padded. 91 | 92 | | `pad=` | Desc | 93 | | --------| ------------------- | 94 | | `true` | Align decode ouput. | 95 | | `false` | Dont align. | 96 | 97 | ``` 98 | xcode 99 | xcode 100 | xcode 101 | ``` 102 | 103 | ``` 104 | xcode 105 | xcode 106 | xcode 107 | ``` 108 | 109 | --- 110 | 111 | See: [decode_settings.ini](./decode_settings.ini) 112 | 113 | ### Example Output 114 |
Example output: 115 | 116 | ```ini 117 | xcode count: 228 118 | xcode size: 2052 bytes 119 | xcode base: 0x80 120 | 0080: xc_pci_write 80000884 00008001 ; set io bar (C03) MCPX v1.1 121 | 0089: xc_pci_write 80000810 00008001 ; set io bar (B02) MCPX v1.0 122 | 0092: xc_pci_write 80000804 00000003 ; enable io space 123 | 009b: xc_io_write 00008049 00000008 ; disable the tco timer 124 | 00a4: xc_io_write 000080d9 00000000 ; KBDRSTIN# in gpio mode 125 | 00ad: xc_io_write 00008026 00000001 ; disable PWRBTN# 126 | 00b6: xc_pci_write 8000f04c 00000001 ; enable internal graphics 127 | 00bf: xc_pci_write 8000f018 00010100 ; setup secondary bus 1 128 | 00c8: xc_pci_write 80000084 07ffffff ; set memory size 128 Mb 129 | 130 | 00d1: xc_pci_write 8000f020 0ff00f00 131 | 00da: xc_pci_write 8000f024 f7f0f000 132 | 00e3: xc_pci_write 80010010 0f000000 ; set nv reg base 133 | 00ec: xc_pci_write 80010014 f0000000 134 | 00f5: xc_pci_write 80010004 00000007 135 | 00fe: xc_pci_write 8000f004 00000007 136 | 0107: xc_mem_write 0f0010b0 07633461 ; ctrim_A2 137 | 0110: xc_mem_write 0f0010cc 66660000 138 | 0119: xc_mem_read 0f101000 139 | 0122: xc_and_or 000c0000 00000000 140 | 012b: xc_jne 00000000 lb_00: 141 | 0134: xc_mem_read 0f101000 142 | 013d: xc_and_or e1f3ffff 80000000 143 | 0146: xc_result 00000003 0f101000 144 | 014f: xc_mem_write 0f0010b8 eeee0000 ; set ctrim2 ( micron ) 145 | 0158: xc_jmp lb_01: 146 | lb_00: 0161: xc_jne 000c0000 lb_02: 147 | 016a: xc_mem_read 0f101000 148 | 0173: xc_and_or e1f3ffff 860c0000 149 | 017c: xc_result 00000003 0f101000 150 | 0185: xc_mem_write 0f0010b8 ffff0000 ; set ctrim2 ( samsung ) 151 | 018e: xc_jmp lb_01: 152 | lb_02: 0197: xc_mem_read 0f101000 153 | 01a0: xc_and_or e1f3ffff 820c0000 154 | 01a9: xc_result 00000003 0f101000 155 | 01b2: xc_mem_write 0f0010b8 11110000 156 | lb_01: 01bb: xc_mem_write 0f0010d4 00000009 ; ctrim continue 157 | 01c4: xc_mem_write 0f0010b4 00000000 ; ctrim common 158 | 01cd: xc_mem_write 0f0010bc 00005866 159 | 01d6: xc_mem_write 0f0010c4 0351c858 160 | 01df: xc_mem_write 0f0010c8 30007d67 161 | 01e8: xc_mem_write 0f0010d8 00000000 162 | 01f1: xc_mem_write 0f0010dc a0423635 163 | 01fa: xc_mem_write 0f0010e8 0c6558c6 164 | 0203: xc_mem_write 0f100200 03070103 ; set extbank bit (00000F00) 165 | 020c: xc_mem_write 0f100410 11000016 166 | 0215: xc_mem_write 0f100330 84848888 167 | 021e: xc_mem_write 0f10032c ffffcfff 168 | 0227: xc_mem_write 0f100328 00000001 169 | 0230: xc_mem_write 0f100338 000000df 170 | 0239: xc_pci_write 80000904 00000001 171 | 0242: xc_pci_write 80000914 0000c001 172 | 024b: xc_pci_write 80000918 0000c201 173 | 0254: xc_io_write 0000c200 00000070 174 | 025d: xc_io_write 0000c004 0000008a ; CX871 slave address 175 | 0266: xc_io_write 0000c008 000000ba ; CX871 0xBA = 0x3F 176 | 026f: xc_io_write 0000c006 0000003f ; smbus set val 177 | 0278: xc_io_write 0000c002 0000000a ; smbus kickoff 178 | lb_05: 0281: xc_io_read 0000c000 ; smbus read status 179 | 028a: xc_jne 00000010 lb_03: ; spin until smbus is ready 180 | 0293: xc_jmp lb_04: 181 | lb_03: 029c: xc_and_or 00000008 00000000 182 | 02a5: xc_jne 00000000 lb_05: 183 | 02ae: xc_jmp lb_06: 184 | lb_04: 02b7: xc_io_write 0000c000 00000010 ; smbus clear status 185 | 186 | 02c0: xc_io_write 0000c008 0000006c ; CX871 0x6C = 0x46 187 | 02c9: xc_io_write 0000c006 00000046 ; smbus set val 188 | 02d2: xc_io_write 0000c002 0000000a ; smbus kickoff 189 | lb_07: 02db: xc_io_read 0000c000 ; smbus read status 190 | 02e4: xc_jne 00000010 lb_07: ; spin until smbus is ready 191 | 02ed: xc_io_write 0000c000 00000010 ; smbus clear status 192 | 193 | 02f6: xc_io_write 0000c008 000000b8 ; CX871 0xB8 = 0x00 194 | 02ff: xc_io_write 0000c006 00000000 ; smbus set val 195 | 0308: xc_io_write 0000c002 0000000a ; smbus kickoff 196 | lb_08: 0311: xc_io_read 0000c000 ; smbus read status 197 | 031a: xc_jne 00000010 lb_08: ; spin until smbus is ready 198 | 0323: xc_io_write 0000c000 00000010 ; smbus clear status 199 | 200 | 032c: xc_io_write 0000c008 000000ce ; CX871 0xCE = 0x19 201 | 0335: xc_io_write 0000c006 00000019 ; smbus set val 202 | 033e: xc_io_write 0000c002 0000000a ; smbus kickoff 203 | lb_09: 0347: xc_io_read 0000c000 ; smbus read status 204 | 0350: xc_jne 00000010 lb_09: ; spin until smbus is ready 205 | 0359: xc_io_write 0000c000 00000010 ; smbus clear status 206 | 207 | 0362: xc_io_write 0000c008 000000c6 ; CX871 0xC6 = 0x9C 208 | 036b: xc_io_write 0000c006 0000009c ; smbus set val 209 | 0374: xc_io_write 0000c002 0000000a ; smbus kickoff 210 | lb_10: 037d: xc_io_read 0000c000 ; smbus read status 211 | 0386: xc_jne 00000010 lb_10: ; spin until smbus is ready 212 | 038f: xc_io_write 0000c000 00000010 ; smbus clear status 213 | 214 | 0398: xc_io_write 0000c008 00000032 ; CX871 0x32 = 0x08 215 | 03a1: xc_io_write 0000c006 00000008 ; smbus set val 216 | 03aa: xc_io_write 0000c002 0000000a ; smbus kickoff 217 | lb_11: 03b3: xc_io_read 0000c000 ; smbus read status 218 | 03bc: xc_jne 00000010 lb_11: ; spin until smbus is ready 219 | 03c5: xc_io_write 0000c000 00000010 ; smbus clear status 220 | 221 | 03ce: xc_io_write 0000c008 000000c4 ; CX871 0xC4 = 0x01 222 | 03d7: xc_io_write 0000c006 00000001 ; smbus set val 223 | 03e0: xc_io_write 0000c002 0000000a ; smbus kickoff 224 | lb_12: 03e9: xc_io_read 0000c000 ; smbus read status 225 | 03f2: xc_jne 00000010 lb_12: ; spin until smbus is ready 226 | 03fb: xc_io_write 0000c000 00000010 ; smbus clear status 227 | 228 | 0404: xc_jmp lb_13: 229 | lb_06: 040d: xc_io_write 0000c000 000000ff 230 | 0416: xc_io_write 0000c000 00000010 ; smbus clear status 231 | 232 | 041f: xc_io_write 0000c004 000000d4 ; focus slave address 233 | 0428: xc_io_write 0000c008 0000000c ; smbus set cmd 234 | 0431: xc_io_write 0000c006 00000000 ; smbus set val 235 | 043a: xc_io_write 0000c002 0000000a ; smbus kickoff 236 | lb_16: 0443: xc_io_read 0000c000 ; smbus read status 237 | 044c: xc_jne 00000010 lb_14: ; spin until smbus is ready 238 | 0455: xc_jmp lb_15: 239 | lb_14: 045e: xc_and_or 00000008 00000000 240 | 0467: xc_jne 00000000 lb_16: 241 | 0470: xc_jmp lb_17: 242 | lb_15: 0479: xc_io_write 0000c000 00000010 ; smbus clear status 243 | 244 | 0482: xc_io_write 0000c008 0000000d ; smbus set cmd 245 | 048b: xc_io_write 0000c006 00000020 ; smbus set val 246 | 0494: xc_io_write 0000c002 0000000a ; smbus kickoff 247 | lb_18: 049d: xc_io_read 0000c000 ; smbus read status 248 | 04a6: xc_jne 00000010 lb_18: ; spin until smbus is ready 249 | 04af: xc_io_write 0000c000 00000010 ; smbus clear status 250 | 251 | 04b8: xc_jmp lb_13: 252 | lb_17: 04c1: xc_io_write 0000c000 000000ff 253 | 04ca: xc_io_write 0000c000 00000010 ; smbus clear status 254 | 255 | 04d3: xc_io_write 0000c004 000000e0 256 | 04dc: xc_io_write 0000c008 00000000 ; smbus set cmd 257 | 04e5: xc_io_write 0000c006 00000000 ; smbus set val 258 | 04ee: xc_io_write 0000c002 0000000a ; smbus kickoff 259 | lb_19: 04f7: xc_io_read 0000c000 ; smbus read status 260 | 0500: xc_jne 00000010 lb_19: ; spin until smbus is ready 261 | 0509: xc_io_write 0000c000 00000010 ; smbus clear status 262 | 263 | 0512: xc_io_write 0000c008 000000b8 ; CX871 0xB8 = 0x00 264 | 051b: xc_io_write 0000c006 00000000 ; smbus set val 265 | 0524: xc_io_write 0000c002 0000000a ; smbus kickoff 266 | lb_20: 052d: xc_io_read 0000c000 ; smbus read status 267 | 0536: xc_jne 00000010 lb_20: ; spin until smbus is ready 268 | 053f: xc_io_write 0000c000 00000010 ; smbus clear status 269 | 270 | lb_13: 0548: xc_io_write 0000c004 00000020 ; smc slave write address 271 | 0551: xc_io_write 0000c008 00000001 ; smbus read revision register 272 | 055a: xc_io_write 0000c006 00000000 ; smbus set val 273 | 0563: xc_io_write 0000c002 0000000a ; smbus kickoff 274 | lb_21: 056c: xc_io_read 0000c000 ; smbus read status 275 | 0575: xc_jne 00000010 lb_21: ; spin until smbus is ready 276 | 057e: xc_io_write 0000c000 00000010 ; smbus clear status 277 | 278 | 0587: xc_io_write 0000c004 00000021 ; smc slave read address 279 | 0590: xc_io_write 0000c008 00000001 ; smbus read revision register 280 | 0599: xc_io_write 0000c002 0000000a ; smbus kickoff 281 | lb_22: 05a2: xc_io_read 0000c000 ; smbus read status 282 | 05ab: xc_jne 00000010 lb_22: ; spin until smbus is ready 283 | 05b4: xc_io_write 0000c000 00000010 ; smbus clear status 284 | 285 | 05bd: xc_io_read 0000c006 286 | 05c6: xc_mem_write 0f680500 00011c01 ; set nv clk 233MHz (@ 16.667MHz) 287 | 05cf: xc_mem_write 0f68050c 000a0400 ; pll_select 288 | 05d8: xc_mem_write 0f001220 00000000 289 | 05e1: xc_mem_write 0f001228 00000000 290 | 05ea: xc_mem_write 0f001264 00000000 291 | 05f3: xc_mem_write 0f001210 00000010 292 | 05fc: xc_mem_read 0f101000 293 | 0605: xc_and_or 06000000 00000000 294 | 060e: xc_jne 00000000 lb_23: 295 | 0617: xc_mem_write 0f001214 48480848 296 | 0620: xc_mem_write 0f00122c 88888888 297 | 0629: xc_jmp lb_24: 298 | lb_23: 0632: xc_jne 06000000 lb_25: 299 | 063b: xc_mem_write 0f001214 09090909 ; configure pad for samsung 300 | 0644: xc_mem_write 0f00122c aaaaaaaa 301 | 064d: xc_jmp lb_24: 302 | lb_25: 0656: xc_mem_write 0f001214 09090909 ; configure pad for samsung 303 | 065f: xc_mem_write 0f00122c aaaaaaaa 304 | lb_24: 0668: xc_mem_write 0f001230 ffffffff ; memory pad configuration 305 | 0671: xc_mem_write 0f001234 aaaaaaaa 306 | 067a: xc_mem_write 0f001238 aaaaaaaa 307 | 0683: xc_mem_write 0f00123c 8b8b8b8b 308 | 068c: xc_mem_write 0f001240 ffffffff 309 | 0695: xc_mem_write 0f001244 8b8b8b8b 310 | 069e: xc_mem_write 0f001248 8b8b8b8b 311 | 06a7: xc_mem_write 0f1002d4 00000001 312 | 06b0: xc_mem_write 0f1002c4 00100042 313 | 06b9: xc_mem_write 0f1002cc 00100042 314 | 06c2: xc_mem_write 0f1002c0 00000011 315 | 06cb: xc_mem_write 0f1002c8 00000011 316 | 06d4: xc_mem_write 0f1002c0 00000032 317 | 06dd: xc_mem_write 0f1002c8 00000032 318 | 06e6: xc_mem_write 0f1002c0 00000132 319 | 06ef: xc_mem_write 0f1002c8 00000132 320 | 06f8: xc_mem_write 0f1002d0 00000001 321 | 0701: xc_mem_write 0f1002d0 00000001 322 | 070a: xc_mem_write 0f100210 80000000 323 | 0713: xc_mem_write 0f00124c aa8baa8b 324 | 071c: xc_mem_write 0f001250 0000aa8b 325 | 0725: xc_mem_write 0f100228 081205ff 326 | 072e: xc_mem_write 0f001218 00010000 327 | 0737: xc_pci_read 80000860 328 | 0740: xc_and_or ffffffff 00000400 329 | 0749: xc_result 00000004 80000860 ; don't gen INIT# on powercycle 330 | 0752: xc_pci_write 8000084c 0000fdde 331 | 075b: xc_pci_write 8000089c 871cc707 332 | 0764: xc_pci_read 800008b4 333 | 076d: xc_and_or fffff0ff 00000f00 334 | 0776: xc_result 00000004 800008b4 335 | 077f: xc_pci_write 80000340 f0f0c0c0 336 | 0788: xc_pci_write 80000344 00c00000 337 | 0791: xc_pci_write 8000035c 04070000 338 | 079a: xc_pci_write 8000036c 00230801 339 | 07a3: xc_pci_write 8000036c 01230801 340 | ; took unbranchable jmp!! 341 | 07ac: xc_jmp lb_26: ; 15ns delay by performing jmps 342 | ; took unbranchable jmp!! 343 | lb_26: 07b5: xc_jmp lb_27: 344 | lb_27: 07be: xc_mem_write 0f100200 03070103 ; set extbank bit (00000F00) 345 | 07c7: xc_mem_write 0f100204 11448000 346 | 07d0: xc_pci_write 8000103c 00000000 ; clear scratch pad (mem type) 347 | 07d9: xc_io_write 0000c000 00000010 ; smbus clear status 348 | 349 | 07e2: xc_io_write 0000c004 00000020 ; report memory type 350 | 07eb: xc_io_write 0000c008 00000013 ; smbus set cmd 351 | 07f4: xc_io_write 0000c006 0000000f ; smbus set val 352 | 07fd: xc_io_write 0000c002 0000000a ; smbus kickoff 353 | lb_28: 0806: xc_io_read 0000c000 ; smbus read status 354 | 080f: xc_jne 00000010 lb_28: ; spin until smbus is ready 355 | 0818: xc_io_write 0000c000 00000010 ; smbus clear status 356 | 357 | 0821: xc_io_write 0000c008 00000012 ; smbus set cmd 358 | 082a: xc_io_write 0000c006 000000f0 ; smbus set val 359 | 0833: xc_io_write 0000c002 0000000a ; smbus kickoff 360 | lb_29: 083c: xc_io_read 0000c000 ; smbus read status 361 | 0845: xc_jne 00000010 lb_29: ; spin until smbus is ready 362 | 084e: xc_io_write 0000c000 00000010 ; smbus clear status 363 | 364 | 0857: xc_pci_write 8000f020 fdf0fd00 ; reload nv reg base 365 | 0860: xc_pci_write 80010010 fd000000 366 | 0869: xc_mem_write 00000000 fc1000b8 ; visor attack prep 367 | 0872: xc_mem_write 00000004 90e0ffff 368 | 087b: xc_exit 00000806 ; quit xcodes 369 | ``` 370 | 371 |
372 | -------------------------------------------------------------------------------- /vc/XboxBiosTools.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug_NO_MEM_TRACKING 6 | Win32 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release_NO_MEM_TRACKING 14 | Win32 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {7845cc9d-7d7e-4c08-bcf9-7033b337ba91} 25 | XbBiosTool 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | x86 35 | true 36 | 37 | 38 | Application 39 | true 40 | v143 41 | Unicode 42 | x86 43 | false 44 | 45 | 46 | Application 47 | false 48 | v143 49 | true 50 | Unicode 51 | x86 52 | 53 | 54 | Application 55 | false 56 | v143 57 | true 58 | Unicode 59 | x86 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | $(SolutionDir)..\bin\ 104 | objd\ 105 | xbios 106 | false 107 | false 108 | 109 | 110 | $(SolutionDir)..\bin\ 111 | objd\ 112 | xbios 113 | false 114 | false 115 | 116 | 117 | $(SolutionDir)..\bin\ 118 | obj\ 119 | xbios 120 | false 121 | 122 | 123 | $(SolutionDir)..\bin\ 124 | obj\ 125 | xbios 126 | false 127 | 128 | 129 | 130 | Level4 131 | true 132 | MEM_TRACKING;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | 134 | 135 | $(SolutionDir)..\inc;%(AdditionalIncludeDirectories) 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | ProgramDatabase 145 | 146 | 147 | 148 | 149 | 150 | 151 | Console 152 | true 153 | %(AdditionalDependencies) 154 | 155 | 156 | 157 | 158 | true 159 | 160 | 161 | 162 | 163 | 164 | 165 | Level4 166 | true 167 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 168 | 169 | 170 | $(SolutionDir)..\inc;%(AdditionalIncludeDirectories) 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | ProgramDatabase 180 | 181 | 182 | 183 | 184 | 185 | 186 | Console 187 | true 188 | %(AdditionalDependencies) 189 | 190 | 191 | 192 | 193 | true 194 | 195 | 196 | 197 | 198 | 199 | 200 | Level3 201 | true 202 | false 203 | true 204 | MEM_TRACKING;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 205 | true 206 | $(SolutionDir)..\inc;%(AdditionalIncludeDirectories) 207 | NoListing 208 | MaxSpeed 209 | AnySuitable 210 | Size 211 | false 212 | true 213 | false 214 | false 215 | 216 | 217 | Console 218 | true 219 | true 220 | true 221 | %(AdditionalDependencies) 222 | 223 | 224 | false 225 | NotSet 226 | false 227 | Default 228 | 229 | 230 | 231 | 232 | Level3 233 | true 234 | false 235 | true 236 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 237 | true 238 | $(SolutionDir)..\inc;%(AdditionalIncludeDirectories) 239 | NoListing 240 | MaxSpeed 241 | AnySuitable 242 | Size 243 | false 244 | true 245 | false 246 | false 247 | 248 | 249 | Console 250 | true 251 | true 252 | true 253 | %(AdditionalDependencies) 254 | 255 | 256 | false 257 | NotSet 258 | false 259 | Default 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Xbox Bios Tools 3 | 4 | A command-line tool for extracting and decrypting components of An Original Xbox BIOS. 5 | 6 | ## Table of Contents 7 | 8 | - [Commands](#commands) 9 | - [Encryption / Decryption](#encryption-decryption) 10 | - [What MCPX ROM do i use?](#what-mcpx-rom-do-i-use) 11 | - [Examples](#example-commands) 12 | - [Building](#building) 13 | - [Credits / Resources](#credits-resources) 14 | 15 | ## Commands 16 | | Command | Desc | 17 | | ---------------------------------------- | ------------------------------------------ | 18 | | [`/?`](#help-command) | Displays help message | 19 | | [`/ls`](#list-bios-command) | Display BIOS infomation | 20 | | [`/extr`](#extract-bios-command) | Extract components from a BIOS | 21 | | [`/bld`](#build-bios-command) | Build a BIOS | 22 | | [`/split`](#split-bios-command) | Split a BIOS into banks | 23 | | [`/combine`](#combine-bios-command) | Combine multiple banks into a single BIOS | 24 | | [`/replicate`](#replicate-bios-command) | replicate a single BIOS | 25 | | [`/xcode-sim`](#xcode-visor-sim-command) | Simulate xcodes and Decode x86 | 26 | | [`/xcode-decode`](#xcode-decode-command) | Decode Xcodes from a BIOS or init table | 27 | | [`/x86-encode`](#x86-encode-command) | Encode x86 as xcodes | 28 | | [`/compress`](#compress-file-command) | Compress a file using lzx | 29 | | [`/decompress`](#decompress-file-command)| Decompress a file using lzx | 30 | 31 | ## Switches 32 | | Switch | Description | 33 | | ----------------- | ----------------------------------------------------------------- | 34 | | `/enc-bldr` | Assume the 2BL is unencrypted (Decryption will be skipped) | 35 | | `/enc-krnl` | Assume the kernel is unencrypted (Decryption will be skipped) | 36 | | `/key-bldr `| 16-byte 2BL RC4 file | 37 | | `/key-krnl `| 16-byte kernel RC4 file | 38 | | `/mcpx ` | MCPX ROM file. Used for en/decrypting the 2BL | 39 | | `/romsize ` | How much space is available for the BIOS in kb, (256, 512, 1024) | 40 | | `/binsize ` | Total space of the file or flash in kb (256, 512, 1024) | 41 | 42 | ## Notes / Comments 43 | - Supports all Original Xbox BIOSes. 44 | - There is *no guarantee* that this program will work correctly with modified BIOSes. 45 | 46 | ## Encryption / Decryption 47 | The 2BL needs to be decrypted to calculate the offsets to the kernel image. 48 | You need to provide the `RC4 2BL key` in the form of a *MCPX rom* or a *16-byte file*. 49 | 50 | If the 2BL isn't encrypted, you can ignore these switches. 51 | 52 | - Use `/key-bldr ` to specify the key from a file. (*16-byte file*) 53 | - Use `/mcpx ` to specify the key from the MCPX ROM file. (*512-byte file*) 54 | 55 | If the 2BL has been decrypted, you will see a message like `decrypting 2BL` 56 | 57 | --- 58 | The Kernel needs to be decrypted before decompressing it. The `RC4 Kernel Key` 59 | can be found in the decrypted 2BL or you can provide it. 60 | 61 | If the Kernel isn't encrypted, Use `/enc-krnl` to specify do not want the kernel decrypted. 62 | 63 | - Use `/key-krnl ` to specify a kernel key from a file. (*16-byte file*) 64 | - Use `/enc-krnl` if you do not want the kernel decrypted. 65 | 66 | If the kernel has been decrypted, you will see a message like `decrypting kernel` 67 | 68 | --- 69 | 70 | ## What MCPX ROM do i use? 71 | It depends on the BIOS version. The different revisions of the MCPX have 72 | different keys and different hashing algorithms. 73 | 74 | | `Rev. 0 ` | MD5 Hash | 75 | | ---------------- |----------------------------------- | 76 | | MCPX v1.0 | `d49c52a4102f6df7bcf8d0617ac475ed` | 77 | | M.O.U.S.E rev. 0 v0.9.0 | `da9e9f527c5cb716f7a2143e976f6091` | 78 | 79 | | `Rev. 1` | MD5 Hash | 80 | | ---------------- | ---------------------------- | 81 | | MCPX v1.1 | `2870d58a459c745d7cc4c6122ceb3dcb` | 82 | | M.O.U.S.E rev. 1 v0.9.0 | `06b227adbefc4dd55fb127c33590b735` | 83 | 84 | - Use MCPX `Rev. 0` for BIOSes `< 4817` 85 | - Use MCPX `Rev. 1` for BIOSes `4817+` 86 | 87 | Typically, if the BIOS contains a Preldr (FBL), Use a `Rev. 1 MCPX` . 88 | This is only true if the FBL TEA Attack hasn't been applied. in that instance 89 | it's likely that the BIOS is not encrypted at all, and the startup format maybe different. 90 | 91 | ``` 92 | xbios.exe / /mcpx 93 | ``` 94 | 95 | --- 96 | 97 | ## Help command 98 | Display command/switch list: 99 | ``` 100 | xbios.exe /? 101 | ``` 102 | 103 | Display help about a specific command: 104 | ``` 105 | xbios.exe /? 106 | ``` 107 | 108 | Display help about Encryption: 109 | ``` 110 | xbios.exe /? /help-enc 111 | ``` 112 | 113 | ## List BIOS command 114 | Display infomation about the BIOS. 115 | 116 | The list command has some flags to display specific infomation. 117 | 118 | | Switch | Desc | 119 | | ------------- | ------------------------------------------------ | 120 | | `/in ` | BIOS file (req) | 121 | | `/datatbl` | Display ROM drive / slew calibration table data | 122 | | `/nv2a` | Display init table magic values | 123 | | `/img` | Display kernel image header info | 124 | | `/keys` | Display rc4, rsa keys | 125 | 126 | ``` 127 | xbios.exe /ls 128 | ``` 129 | 130 | ## Extract BIOS command 131 | Extract components from a BIOS file 132 | - `Bldr (2BL)` 133 | - `Preldr (FBL)` 134 | - `Init table (magic numbers, xcodes)` 135 | - `Compressed & Decompressed kernel image (.bin) (.img)` 136 | - `Uncompressed kernel section data` 137 | - `RC4, RSA keys` 138 | 139 | | Switch | Desc | 140 | | ------------------- | --------------------- | 141 | | `/in ` | BIOS file (req) | 142 | | `/keys` | Extract keys | 143 | | `/nobootparams` | Dont restore 2BL boot params (FBL BIOSes) | 144 | | `/dir ` | Set output directory | 145 | 146 | | Output file | Desc | 147 | | ------------------- | --------------------- | 148 | | `/bldr ` | Output 2BL file | 149 | | `/inittbl ` | Output init table file | 150 | | `/krnl ` | Output compressed kernel file | 151 | | `/krnldata ` | Output uncompressed data section file | 152 | | `/preldr ` | Output preldr file | 153 | | `/eepromkey ` | Output eeprom key file | 154 | | `/certkey ` | Output cert key file | 155 | 156 | ``` 157 | xbios.exe /extr 158 | ``` 159 | 160 | ## Build BIOS command 161 | Build a BIOS from a 2BL, compressed kernel, uncompressed data section, init table. 162 | 163 | | Switch | Desc | 164 | | ------------------- | ------------------------------------------------------- | 165 | | `/out ` | Output BIOS file; defaults to bios.bin | 166 | | `/xcodes ` | Inject xcodes file | 167 | | `/romsize ` | romsize in kb (256, 512, 1024) | 168 | | `/binsize ` | binsize in kb (256, 512, 1024) | 169 | | `/enc-krnl` | Locate the kernel key in 2BL and use it for encryption | 170 | | `/bfm` | Patch BIOS to boot from media ( bfm ) | 171 | | `/hackinittbl` | Hack initbl size (size = 0) | 172 | | `/hacksignature` | Hack 2BL boot signature (signature = 0xFFFFFFFF) | 173 | | `/nobootparams` | Dont update boot params | 174 | 175 | | Input file | Desc | 176 | | ------------------- | ------------------------------------------------------- | 177 | | `/bldr ` | Input 2BL file (req) | 178 | | `/inittbl ` | Input Init table file (req) | 179 | | `/krnl ` | Input Compressed kernel file (req) | 180 | | `/krnldata ` | Input Uncompressed data section file (req) | 181 | | `/preldr ` | Input Preldr (FBL) file | 182 | 183 | The switch, `-enc-krnl` works different with this command. Provide the flag 184 | *if you want the kernel encrypted* with the kernel key located in the 2BL. 185 | 186 | The switch, `-xcodes` injects the xcodes at the end of the xcode table. 187 | If no space is available, (no zero space) the exit xcode is replaced with 188 | a jump to free space where the xcodes will be injected. 189 | 190 | ``` 191 | xbios.exe /bld /bldr /inittbl /krnl /krnldata 192 | ``` 193 | 194 | ## Split BIOS command 195 | Split a BIOS into banks. 196 | 197 | | Switch | Desc | 198 | | ------------- | ----------------------------------------------- | 199 | | `/in ` | BIOS file (req) | 200 | | `/romsize` | Bank size (256, 512, 1024) ; defaults to 256kb | 201 | 202 | ``` 203 | xbios.exe /split /romsize 204 | ``` 205 | 206 | ## Combine BIOS command 207 | Combine multiple banks into a single BIOS file. 208 | Provide atleast 2 banks to combine. 209 | 210 | The `-bank[1-4]` switches are inferred with this command. 211 | - The first file provided without a switch (`/`) is bank[1] 212 | - The second file provided without a switch (`/`) is bank[2] 213 | - etc 214 | 215 | | Switch | Desc | 216 | | ------------- | ----------------------------------------------- | 217 | | `-bank[1-4] ` | Bank file | 218 | | `/out ` | BIOS file; defaults to bios.bin | 219 | 220 | ``` 221 | xbios.exe /combine 222 | ``` 223 | 224 | ## Replicate BIOS command 225 | Replicate a single BIOS file. 226 | 227 | | Switch | Desc | 228 | | ------------- | ---------------------------------- | 229 | | `/in ` | BIOS file (req) | 230 | | `/out ` | BIOS file; defaults to bios.bin | 231 | | `/binsize` | BIOS size (req) (256, 512, 1024) | 232 | 233 | ## X86 encode command 234 | Encode x86 *machine code* as xcode *byte code* that writes to RAM. 235 | 236 | | Switch | Desc | 237 | | ------------- | ------------------------------------------ | 238 | | `/in ` | Input file | 239 | | `/out ` | Output file; defaults to xcodes.bin | 240 | 241 | - Start address of mem-write is 0. Each write is increment by 4 bytes. 242 | - Code size increases by a factor of x2.25. 243 | 244 | ``` 245 | xbios.exe /x86-encode /out 246 | ``` 247 | 248 |
x2.25 Example 249 | 250 | ``` 251 | Machine code: ---> Byte code: 252 | 0000: B8 ED 0B F0 mov eax, 0xfff00bed 0000: 03 00 00 00 xc_mem_write 0x00, 0xf00bedb8 253 | 0004: FF FF E0 jmp eax 0004: 00 F0 0B ED 254 | 0007: 90 nop 0008: B8 255 | 0009: 03 00 00 00 xc_mem_write 0x04, 0x90e0ffff 256 | 000D: 04 90 E0 FF 257 | 0011: FF 258 | ``` 259 | 260 |
261 | 262 | ## Xcode sim command 263 | Simulate mem-write xcodes and disassemble x86 machine code. (visor sim) 264 | 265 | | Switch | Desc | Default | 266 | | ---------------- | --------------------------------------------------- | ------- | 267 | | `/in ` | Input file (req) | 268 | | `/base ` | Base address of xcodes | `0x80` | 269 | | `/offset ` | Address of start offset | `0x00` | 270 | | `/simsize `| Size of the sim space in bytes | `0x20` | 271 | | `/d` | Write to a file; Use `-out` to specify output file | `false` | 272 | 273 | If simulating a file other than a BIOS or extracted init table, 274 | The `base` of the xcodes might be different. Use `-base ` to specify. 275 | 276 | `-offset` is used to change what mem-writes are recorded starting from some 277 | `offset` extending to `offset + simsize`. Only mem-writes in this range are recorded. 278 | 279 | ``` 280 | xbios.exe /xcode-sim 281 | ``` 282 | 283 |
Example 1 output 284 | 285 | ``` 286 | Xcodes: 287 | 1a9f: xc_mem_write 0x00, 0x7FC900BE 288 | 1aa8: xc_mem_write 0x04, 0x0000BFFF 289 | 1ab1: xc_mem_write 0x08, 0x00B90009 290 | 1aba: xc_mem_write 0x0c, 0xFC000018 291 | 1ac3: xc_mem_write 0x10, 0x1D8BA5F3 292 | 1acc: xc_mem_write 0x14, 0x00090000 293 | 1ad5: xc_mem_write 0x18, 0x0000E3FF 294 | 1ade: xc_mem_write 0x1c, 0x00000000 295 | 296 | Assembly: 297 | mov esi, 0xff7fc900 298 | mov edi, 0x90000 299 | mov ecx, 0x1800 300 | cld 301 | rep movsd 302 | mov ebx, [0x90000] 303 | jmp ebx 304 | 305 | Mem dump: ( 26 bytes ) 306 | 0000: BE 00 C9 7F FF BF 00 00 307 | 0008: 09 00 B9 00 18 00 00 FC 308 | 0010: F3 A5 8B 1D 00 00 09 00 309 | 0018: FF E3 310 | ``` 311 | 312 |
313 | 314 |
Example 2 output 315 | 316 | ``` 317 | Xcodes: 318 | 0869: xc_mem_write 0x00, 0xFC1000EA 319 | 0872: xc_mem_write 0x04, 0x000008FF 320 | 321 | Assembly: 322 | jmp 0xfffc1000:0x08 323 | 324 | Mem dump: ( 7 bytes ) 325 | 0000: EA 00 10 FC FF 08 00 326 | 327 | ``` 328 | 329 |
330 | 331 | 332 | ## Xcode decode command 333 | Decode Xcodes from a BIOS file, extracted init table. 334 | 335 | | Switch | Desc | Default | 336 | | -------------- | --------------------------------------------------- | ------- | 337 | | `/in ` | Input file (req) | | 338 | | `/base ` | Base address for xcodes | `0x80` | 339 | | `/ini ` | Decode settings file | `default` | 340 | | `/branch` | Take unbranchable jumps | `false` | 341 | | `/d` | Write to a file; Use `-out` to specify output file. | `false` | 342 | 343 | If decoding a file other than a BIOS or extracted init table, 344 | The `base` of the xcodes might be different. Use `/base ` to specify. 345 | 346 | See: [Xcode Decode Settings](./DecodeSettings.md) for more infomation. 347 | 348 | ``` 349 | xbios.exe /xcode-decode 350 | ``` 351 | 352 | ## Compress file command 353 | Compress a file using lzx 354 | 355 | | Switch | Desc | 356 | | -------------- | ------------------- | 357 | | `/in ` | Input file (req) | 358 | | `/out ` | Output file (req) | 359 | 360 | ``` 361 | xbios.exe /compress /out 362 | ``` 363 | 364 | ## Decompress file command 365 | Decompress a file using lzx 366 | 367 | | Switch | Desc | 368 | | -------------- | ------------------- | 369 | | `/in ` | Input file (req) | 370 | | `/out ` | Output file (req) | 371 | 372 | ``` 373 | xbios.exe /decompress /out 374 | ``` 375 | 376 | ## Example Commands 377 | 378 | Extract BIOS + Keys 379 | ``` 380 | xbios.exe /extr /keys /mcpx 381 | ``` 382 | 383 | List BIOS infomation 384 | ``` 385 | xbios.exe /ls /mcpx 386 | ``` 387 | 388 | List BIOS Keys 389 | ``` 390 | xbios.exe /ls /keys /mcpx 391 | ``` 392 | 393 | Replicate BIOS (256 kb) to 512 kb 394 | ``` 395 | xbios.exe /replicate /binsize 512 396 | ``` 397 | 398 | ## Building 399 | 400 | The project is built in Visual Studio 2022 401 | 402 | 1. Clone the repo 403 | 404 | ``` 405 | git clone https://github.com/tommojphillips/XboxBiosTool.git 406 | ``` 407 | 408 | 2. Open vc\XboxBiosTools.sln in visual studio and build and run 409 | 410 | ## Credits / Resources 411 | 412 | - [Xbox Dev Wiki](https://xboxdevwiki.net/Main_Page) 413 | - [Deconstructing the Xbox Boot Rom](https://web.archive.org/web/20201108132438/https://mborgerson.com/deconstructing-the-xbox-boot-rom/) by [mborgerson](https://github.com/mborgerson) 414 | - [xbedump](https://github.com/XboxDev/xbedump) by [XboxDev](https://github.com/XboxDev) - sha1.c implementation 415 | - [XBOverclock](https://github.com/WulfyStylez/XBOverclock) by [WulfyStylez](https://github.com/WulfyStylez) - GPU clock calculations 416 | --------------------------------------------------------------------------------