Skip to content

Commit

Permalink
modularise, wip nand_extract (unfinished)
Browse files Browse the repository at this point in the history
  • Loading branch information
InvoxiPlayGames committed Jan 18, 2024
1 parent 7d35711 commit c76807d
Show file tree
Hide file tree
Showing 23 changed files with 1,237 additions and 318 deletions.
10 changes: 3 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Compile (GCC)
run: make CC=gcc
- name: Compile (Clang)
run: make CC=clang
run: make
- name: Upload
uses: actions/upload-artifact@v4
with:
Expand All @@ -23,7 +21,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Compile
- name: Compile (Clang)
run: make
- name: Upload
uses: actions/upload-artifact@v4
Expand All @@ -43,11 +41,9 @@ jobs:
uses: msys2/setup-msys2@v2
with:
msystem: mingw64
install: make mingw-w64-x86_64-gcc mingw-w64-x86_64-clang
install: make mingw-w64-x86_64-gcc
- name: Compile (GCC)
run: make CC=gcc
- name: Compile (Clang)
run: make CC=clang
- name: Upload
uses: actions/upload-artifact@v4
with:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Licensed to you under the GNU General Public License version 2. See LICENSE for

## Features so far

* Decompressing the CE/5BL base kernel.
* Extracting and updating the kernel stages. (CE/SE + CG/SE)

## Usage
Expand Down
9 changes: 9 additions & 0 deletions include/cb-handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdint.h>
#include <stdbool.h>

bool cb_is_decrypted(uint8_t *cb_data);
void cb_print_info(uint8_t *cb_data);
void cb_decrypt(uint8_t *cb_data, uint8_t *cba_or_1bl_key);
void cb_b_decrypt(uint8_t *cb_b_data, uint8_t *cb_a_data, uint8_t *cpu_key);
void cb_calculate_rotsum(uint8_t *cb_data, uint8_t *sha_out);
bool cb_verify_signature(uint8_t *cb_data);
7 changes: 7 additions & 0 deletions include/cd-handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdint.h>
#include <stdbool.h>

bool cd_is_decrypted(uint8_t *cd_data);
void cd_print_info(uint8_t *cd_data);
void cd_decrypt(uint8_t *cd_data, uint8_t *cbb_key, uint8_t *cpu_key);
void cd_calculate_rotsum(uint8_t *cd_data, uint8_t *sha_out);
2 changes: 1 addition & 1 deletion include/cf-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

bool cf_is_decrypted(uint8_t *cf_data);
void cf_print_info(uint8_t *cf_data);
void cf_decrypt(uint8_t *cf_data, uint8_t *cpu_or_1bl_key);
void cf_decrypt(uint8_t *cf_data, uint8_t *onebl_key);
void cf_calculate_rotsum(uint8_t *cf_data, uint8_t *sha_out);
bool cf_verify_signature(uint8_t *cf_data);
3 changes: 3 additions & 0 deletions include/commands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int do_decompress_command(int argc, char **argv);
int do_nand_extract_command(int argc, char **argv);
int do_xboxupd_command(int argc, char **argv);
91 changes: 91 additions & 0 deletions include/nand-ecc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Reference: https://free60.org/System-Software/NAND_File_System/
// these all need checking before i want to rely on using them for anything
#include <stdint.h>

// ECC spare data used on 1st gen NAND controllers
typedef struct _ecc_data_v1 {
// uint16_t block_id : 12;
uint8_t block_id_1;
uint8_t block_id_0 : 4;

uint8_t fs_unused : 4;
uint8_t fs_sequence_0;
uint8_t fs_sequence_1;
uint8_t fs_sequence_2;
uint8_t bad_block;
uint8_t fs_sequence_3;

// uint16_t fs_size;
uint8_t fs_size_1;
uint8_t fs_size_0;

uint8_t fs_page_count;
uint8_t fs_unused_2[2];
uint8_t fs_block_type : 6;

// 14-bit ECC data
uint8_t ecc3 : 2;
uint8_t ecc2;
uint8_t ecc1;
uint8_t ecc0;
} ecc_data_v1;

// ECC spare data used on 2nd gen NAND controllers (16/64MB)
typedef struct _ecc_data_v2_sb {
uint8_t fs_sequence_0;

// uint16_t block_id : 12;
uint8_t block_id_1;
uint8_t block_id_0 : 4;

uint8_t fs_unused : 4;
uint8_t fs_sequence_1;
uint8_t fs_sequence_2;
uint8_t bad_block;
uint8_t fs_sequence_3;

// uint16_t fs_size;
uint8_t fs_size_1;
uint8_t fs_size_0;

uint8_t fs_page_count;
uint8_t fs_unused_2[2];
uint8_t fs_block_type : 6;

// 14-bit ECC data
uint8_t ecc3 : 2;
uint8_t ecc2;
uint8_t ecc1;
uint8_t ecc0;
} ecc_data_v2_sb;

// ECC spare data used on 2nd gen NAND controllers (256/512MB)
typedef struct _ecc_data_v2_bb {
uint8_t bad_block;

// uint16_t block_id : 12;
uint8_t block_id_1;
uint8_t block_id_0 : 4;

uint8_t fs_unused : 4;
uint8_t fs_sequence_2;
uint8_t fs_sequence_1;
uint8_t fs_sequence_0;
uint8_t fs_unused_2;

// uint16_t fs_size;
uint8_t fs_size_1;
uint8_t fs_size_0;

uint8_t fs_page_count;
uint8_t fs_unused_3[2];
uint8_t fs_block_type : 6;

// 14-bit ECC data
uint8_t ecc3 : 2;
uint8_t ecc2;
uint8_t ecc1;
uint8_t ecc0;
} ecc_data_v2_bb;

void calculate_nand_ecc(uint8_t page[0x200], uint8_t spare[0x10], uint8_t ecc[0x4]);
54 changes: 54 additions & 0 deletions include/nand.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "xenon-bootloader.h"

#define NAND_PAGE_SIZE 0x200
#define NAND_META_SIZE 0x10
#define NAND_PAGE_FULL (NAND_PAGE_SIZE + NAND_META_SIZE)

#define NAND_KV_VERSION 0x0712

typedef struct _xenon_nand_header {
bootloader_header header; // entrypoint leads to CB
char copyright[0x40];
Expand All @@ -15,3 +23,49 @@ typedef struct _xenon_nand_header {
uint32_t smc_boot_size;
uint32_t smc_boot_offset;
} xenon_nand_header;

typedef enum _nand_type {
NAND_TYPE_SMALLBLOCK, // Small 16MB/64MB NANDs on pre-Jasper
NAND_TYPE_SMALLBLOCK_V2, // Small 16MB/64MB NANDs on Jasper and later
NAND_TYPE_BIGBLOCK, // Large 256MB/512MB NANDs on Jasper
NAND_TYPE_UNECC, // NAND image lacks ECC data, and isn't Corona
NAND_TYPE_CORONA, // NAND image is Corona. lolhynix

NAND_TYPE_UNKNOWN = -1
} nand_type;

typedef enum _storage_size {
STORAGE_SIZE_16MB,
STORAGE_SIZE_64MB,
STORAGE_SIZE_256MB,
STORAGE_SIZE_512MB,
STORAGE_SIZE_4GB
} storage_size;

typedef enum _console_type {
CONSOLE_XENON,
CONSOLE_ELPIS, // runs 7xxx series bootloaders
CONSOLE_FALCON,
CONSOLE_JASPER,
CONSOLE_TRINITY,
CONSOLE_CORONA_16MB,
CONSOLE_CORONA_4GB,
CONSOLE_WINCHESTER,

CONSOLE_UNKNOWN = -1
} console_type;

typedef struct _nand_file {
FILE *fp;
int type;
int size;
int console;
bool close_file;
} nand_file;

nand_file *open_nand_file(FILE *fp, bool create);
nand_file *open_nand_file_name(char *name, bool create);

void read_nand_data(nand_file *file, uint32_t offset, uint8_t *data, size_t len);

void close_nand_file(nand_file *file);
15 changes: 15 additions & 0 deletions include/utility.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>

#ifndef SHOULD_BE_BE
#define BE16(i) ((((i) & 0xFF) << 8 | ((i) >> 8) & 0xFF) & 0xFFFF)
Expand All @@ -10,4 +12,17 @@
#define BE64(i) i
#endif

#ifdef SHOULD_BE_BE
#define LE16(i) ((((i) & 0xFF) << 8 | ((i) >> 8) & 0xFF) & 0xFFFF)
#define LE(i) (((i) & 0xff) << 24 | ((i) & 0xff00) << 8 | ((i) & 0xff0000) >> 8 | ((i) >> 24) & 0xff)
#define LE64(i) (BE((i) & 0xFFFFFFFF) << 32 | BE(((i) >> 32) & 0xFFFFFFFF))
#else
#define LE16(i) i
#define LE(i) i
#define LE64(i) i
#endif

void hexdump(uint8_t *data, uint32_t size);
bool parse_hex_str(char *str, uint8_t *out_buf, size_t buf_size);
void dump_to_file(char *filename, uint8_t *buf, size_t size);
size_t get_file_size(FILE *fp);
39 changes: 31 additions & 8 deletions include/xenon-bootloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define XENON_BOOTLOADER_H_

#include <stdint.h>
#include <stdbool.h>
#include "excrypt.h"

typedef enum _xenon_bl_type {
Expand Down Expand Up @@ -37,8 +38,8 @@ typedef struct _onebl_globals {
typedef struct _bootloader_header {
uint16_t magic;
uint16_t version;
uint16_t pairing;
uint16_t flags;
uint16_t pairing; // 0x8000 = devkit?
uint16_t flags; // 0x0001 = mfg, 0x0800 = cba?
uint32_t entrypoint;
uint32_t size;
} bootloader_header;
Expand All @@ -62,17 +63,22 @@ typedef struct _bootloader_cb_header {
uint8_t key[0x10];
uint64_t padding_or_args[4];
EXCRYPT_SIG signature;
uint8_t globals[0x25C]; // find out whats in here...
uint8_t globals[0x128]; // find out whats in here...
EXCRYPT_RSAPUB_2048 devkit_pubkey;
uint8_t sc_key[0x10];
char sc_salt[10];
char sd_salt[10];
uint8_t cd_cbb_hash[0x14]; // CB_A has CB_B hash, CB_B has CD hash
uint8_t more_globals[0x10]; // and here as well...
uint8_t more_globals[0x10]; // more_globals[1] has LDV
} bootloader_cb_header;

typedef struct _bootloader_cd_header {
bootloader_header header;
uint8_t key[0x10];
uint8_t idk_yet[0x220]; // possibly unused?
EXCRYPT_SIG signature; // only valid on devkits
uint8_t idk_yet[0x120]; // unused?
char cf_salt[10];
uint16_t unused;
uint16_t unused2;
uint8_t ce_hash[0x14];
} bootloader_cd_header;

Expand All @@ -87,9 +93,9 @@ typedef struct _bootloader_ce_header {
typedef struct _bootloader_cf_header {
bootloader_header header;
uint16_t base_ver;
uint16_t base_flags; // unsure
uint16_t base_flags; // unsure, 0x8000 for devkit
uint16_t target_ver;
uint16_t target_flags; // unsure
uint16_t target_flags; // unsure, 0x8000 for devkit
uint32_t unknown; // think this is unused
uint32_t cg_size;
uint8_t key[0x10];
Expand Down Expand Up @@ -126,6 +132,17 @@ typedef struct _bootloader_update_inner {
uint8_t part2_sha[0x14];
} bootloader_update_inner;

typedef struct _bootloader_update_tab_entry {
uint16_t cpu_pvr;
uint16_t xenos_id;
uint16_t unk1; // differentiates elpis and corona - possibly PCI bridge revision ID?
uint16_t unk2; // also differentiates elpis/corona but also new GPU revs?
uint16_t from_cb; // seems to be used exclusively on Xenon
uint16_t from_cd; // never used, just an assumption?
uint16_t to_cb; // the CB (and CB_B in v2) version to update to
uint16_t to_cd; // the CD version to update to (matches CB in v2)
} bootloader_update_tab_entry;

typedef struct _bootloader_compression_header {
uint32_t window_size;
uint32_t block_size;
Expand All @@ -145,4 +162,10 @@ typedef struct _bootloader_delta_block {
uint16_t compressed_size;
} bootloader_delta_block;

int get_bootloader_type(bootloader_header *bl);
bool is_bootloader_devkit(bootloader_header *bl);
void xke_sc_calculate_rotsum(uint8_t *bl_data, uint8_t *sha_out);
bool xke_sc_verify_signature(uint8_t *bl_data, char *salt, uint8_t *pubkey);
void xke_sc_decrypt(uint8_t *bl_data, uint8_t *dec_key);

#endif
Loading

0 comments on commit c76807d

Please sign in to comment.