Permalink
Browse files

Full 6.2 support! and other refactoring

  • Loading branch information...
Reisyukaku committed Dec 9, 2018
2 parents 94aa9fc + ec297fc commit 032e5c244b072ce81cf271cceea2676284f6ddb8
Showing with 2,052 additions and 1,228 deletions.
  1. +6 −6 Makefile
  2. +5 −3 link.ld
  3. +118 −77 src/bootloader.c
  4. +20 −9 src/bootloader.h
  5. +144 −92 src/firmware.c
  6. +0 −13 src/firmware.h
  7. +2 −1 src/hwinit.h
  8. +0 −35 src/hwinit/arm64.h
  9. +1,086 −664 src/hwinit/emc.h
  10. +42 −46 src/hwinit/heap.c
  11. +16 −1 src/hwinit/heap.h
  12. +0 −141 src/hwinit/ini.c
  13. +0 −42 src/hwinit/ini.h
  14. +170 −0 src/hwinit/smmu.c
  15. +82 −0 src/hwinit/smmu.h
  16. +76 −7 src/hwinit/t210.h
  17. +178 −63 src/hwinit/tsec.c
  18. +12 −1 src/hwinit/tsec.h
  19. +50 −0 src/hwinit/tsec_t210.h
  20. +9 −8 src/hwinit/types.h
  21. +13 −0 src/hwinit/util.h
  22. +18 −15 src/package.c
  23. +2 −1 src/package.h
  24. +3 −3 src/start.s
@@ -9,7 +9,7 @@ LD = $(DEVKITARM)/bin/arm-none-eabi-ld
OBJCOPY = $(DEVKITARM)/bin/arm-none-eabi-objcopy

name := ReiNX
ver := 1.6
ver := 2.0

dir_source := src
dir_data := data
@@ -18,7 +18,7 @@ dir_out := out
dir_sysmod := NX_Sysmodules

ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -DVERSION='"$(ver)"' -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -fno-builtin -std=gnu11# -Wall
CFLAGS = $(ARCH) -DVERSION='"$(ver)"' -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -fno-builtin -std=gnu11# -Wall -Werror
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections

objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
@@ -47,16 +47,16 @@ clean:

$(dir_out)/sysmodules: $(dir_sysmod)
@$(MAKE) -C $(dir_sysmod)

$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
@mkdir -p "$(@D)"
@mkdir -p "$(dir_out)/ReiNX/sysmodules"
@mkdir -p "$(dir_out)/ReiNX/sysmodules.dis"
@mkdir -p "$(dir_out)/ReiNX/patches"
@cp $(dir_sysmod)/loader/loader.kip $(dir_out)/ReiNX/sysmodules/
@cp $(dir_sysmod)/sm/sm.kip $(dir_out)/ReiNX/sysmodules/
@cp $(dir_sysmod)/pm/pm.kip $(dir_out)/ReiNX/sysmodules/
@cp $(dir_sysmod)/fs_mitm/fs_mitm.kip $(dir_out)/ReiNX/sysmodules.dis/

$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
@mkdir -p "$(@D)"
@mkdir -p "$(dir_out)/ReiNX/patches"
@cp -R $(dir_data)/*.bin $(dir_out)/ReiNX/
@cp -R $(dir_data)/*.rxp $(dir_out)/ReiNX/patches
$(OBJCOPY) -S -O binary $< $@
@@ -2,8 +2,10 @@ ENTRY(_start)

SECTIONS
{
PROVIDE(payload_start = 0x40003000);
. = payload_start;
PROVIDE(__payload_start = 0x40008000);
PROVIDE(__heap_start = 0x90020000);

. = __payload_start;
.text.start :
{
*(.text.start)
@@ -18,7 +20,7 @@ SECTIONS
*(.rodata*);
}
. = ALIGN(0x10);
payload_end = .;
__payload_end = .;
.bss :
{
__bss_start = .;
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2018 Reisyukaku, naehrwert
* Copyright (c) 2018 Reisyukaku
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 elise
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -17,17 +19,17 @@
#include "hwinit.h"
#include "error.h"
#include "bootloader.h"

#include "package.h"
void check_sku() {
if (FUSE(FUSE_SKU) != 0x83)
if (FUSE(0x110) != 0x83)
panic();
}

u32 get_unknown_config() {
u32 res = 0;
u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4));
u32 config = ((deviceInfo & 4u) >> 2) | 2 * ((deviceInfo & 0x100u) >> 8);

if(config == 1)
return 0;
if(config == 2)
@@ -40,7 +42,7 @@ u32 get_unknown_config() {
u32 get_unit_type() {
u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4));
u32 deviceType = deviceInfo & 3 | 4 * ((deviceInfo & 0x200u) >> 9);

if(deviceType == 3)
return 0;
if(deviceType == 4)
@@ -52,76 +54,115 @@ void check_config_fuses() {
u32 config = get_unknown_config();
u32 unitType = get_unit_type();
u32 bromVer = FUSE(FUSE_SOC_SPEEDO_1);

if (config == 3 || unitType == 2 || bromVer < 0x1F)
panic();
}

int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw) {
u8 tmp[0x10];

se_key_acc_ctrl(0x0D, 0x15);
se_key_acc_ctrl(0x0E, 0x15);

// Get TSEC key.
if (tsec_query(tmp, 1, tsec_fw) < 0)
return 0;

se_aes_key_set(0x0D, tmp, 0x10);

// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(0x0F, 0x0E, tmp);
se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[fwVer-1]);
se_aes_unwrap_key(0x0D, 0x0E, tmp);

// Clear SBK
se_aes_key_clear(0x0E);

se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed);

// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
if(fwVer < KB_FIRMWARE_VERSION_620)
se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // Package1 key
se_aes_key_set(0x0C, keyblob + 0x20, 0x10);
se_aes_key_set(0x0D, keyblob + 0x20, 0x10);

se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail);

switch (fwVer) {
//case KB_FIRMWARE_VERSION_100:
case KB_FIRMWARE_VERSION_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break;

case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break;

case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
case KB_FIRMWARE_VERSION_620:
default:
se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break;
int keygen(u8 *keyblob, u32 fwVer, void * pkg1, pk11_offs * offs) {
u8 tmp[0x20];
int sp = fwVer >= KB_FIRMWARE_VERSION_620;
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.key_ver = 1;
tsec_ctxt.fw = pkg1 + offs->tsec_off;
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.pkg11_off = offs->pkg11_off;
tsec_ctxt.secmon_base = offs->secmon_base;
tsec_ctxt.size = sp ? 0x2900 : 0xF00;

se_key_acc_ctrl(0xE, 0x15);
se_key_acc_ctrl(0xD, 0x15);

if (sp) {
print("Going to emulate TSEC\nSize: 0x%x\nLoc: 0x%x\nOff: 0x%x\n", tsec_ctxt.size, tsec_ctxt.fw-tsec_ctxt.pkg1, tsec_ctxt.pkg11_off);

This comment has been minimized.

@Flat

Flat Dec 9, 2018

Typo emulating

u8 *tsec_paged = (u8 *)page_alloc(3);
memcpy(tsec_paged, (void *)tsec_ctxt.fw, tsec_ctxt.size);
print("Copied, emulaing tsec\n");
}

// Package2 key
if(fwVer < KB_FIRMWARE_VERSION_620){
se_key_acc_ctrl(0x08, 0x15);
se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
int retries = 0;
int ret = tsec_query(tmp, fwVer, &tsec_ctxt);
while (ret < 0)
{
print("Failed to keygen, retrying\n");
memset(tmp, 0x00, 0x20);
if (++retries > 3)
return 0;
ret = tsec_query(tmp, fwVer, &tsec_ctxt);
}

if(sp) {
// Set TSEC key.
se_aes_key_set(12, tmp, 0x10);

// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp);

// Set TSEC root key.
se_aes_key_set(13, tmp + 0x10, 0x10);

// Package2 key.
se_aes_key_set(8, tmp + 0x10, 0x10);
se_aes_unwrap_key(8, 8, new_master_keyseed);
se_aes_unwrap_key(8, 8, pre400_master_keyseed);
se_aes_unwrap_key(8, 8, pk21_keyseed);
} else {
se_key_acc_ctrl(13, 0x15);
se_key_acc_ctrl(14, 0x15);

// Set TSEC key.
se_aes_key_set(13, tmp, 0x10);

// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[fwVer]);
se_aes_unwrap_key(13, 14, tmp);

// Clear SBK.
se_aes_key_clear(14);

se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);

// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
se_aes_key_set(12, keyblob + 0x20, 0x10);
se_aes_key_set(13, keyblob + 0x20, 0x10);

se_aes_crypt_block_ecb(12, 0, tmp, pre400_master_keyseed);

switch (fwVer)
{
case KB_FIRMWARE_VERSION_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
se_aes_unwrap_key(13, 15, console_keyseed);
se_aes_unwrap_key(12, 12, pre400_master_keyseed);
break;
case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, pre620_master_keyseed);
se_aes_unwrap_key(12, 12, pre400_master_keyseed);
break;
case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
se_aes_unwrap_key(10, 15, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, pre620_master_keyseed);
se_aes_unwrap_key(12, 12, pre400_master_keyseed);
break;
}

// Package2 key.
se_key_acc_ctrl(8, 0x15);
se_aes_unwrap_key(8, 12, pk21_keyseed);
}

return 1;
}

void mbist_workaround() {
@@ -222,11 +263,11 @@ void setup() {
config_oscillators();
APB_MISC(0x40) = 0;
config_gpios();

if (get_unit_type() == 0) {
// TODO: devunit sub_40018D90
}

clock_enable_cl_dvfs();
clock_enable_i2c(I2C_1);
clock_enable_i2c(I2C_5);
@@ -260,19 +301,19 @@ void setup() {
mc_config_carveout();

sdram_init();

sdram_lp0_save_params(sdram_get_params());

// Check if power off from HOS and shutdown
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_IRQTOP) & MAX77620_IRQ_TOP_RTC_MASK)
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_IRQTOP) & MAX77620_IRQ_TOP_RTC_MASK)
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);

}

void bootloader() {
void bootloader() {
mbist_workaround();
clock_enable_se();

// This makes fuse registers visible
clock_enable_fuse(0x01);

@@ -286,7 +327,7 @@ void bootloader() {

// Setup memory controllers
mc_enable();

// Pre-Firmware setup
setup();
}
}
@@ -15,6 +15,20 @@
*/

#pragma once
#include "package.h"

// TODO: Maybe find these with memsearch
static const pk11_offs _pk11_offs[] = {
{ KB_FIRMWARE_VERSION_100, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, 0x8000D000, 1 }, //1.0.0
{ KB_FIRMWARE_VERSION_200, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //2.0.0 - 2.3.0
{ KB_FIRMWARE_VERSION_300, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //3.0.0
{ KB_FIRMWARE_VERSION_301, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //3.0.1 - 3.0.2
{ KB_FIRMWARE_VERSION_400, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0 }, //4.0.0 - 4.1.0
{ KB_FIRMWARE_VERSION_500, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0 }, //5.0.0 - 5.0.2
{ KB_FIRMWARE_VERSION_600, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, 0 }, //6.0.0
{ KB_FIRMWARE_VERSION_620, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, 0 }, //6.2.0
{ NULL } // End.
};

static const u8 keyblob_keyseeds[][0x10] = {
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0
@@ -26,15 +40,12 @@ static const u8 keyblob_keyseeds[][0x10] = {
};

static const u8 cmac_keyseed[0x10] = { 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
static const u8 master_keyseed_retail[0x10] = { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 pre400_master_keyseed[0x10] = { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 console_keyseed[0x10] = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
static const u8 key8_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 master_keyseed_4xx[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 pk21_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 pre620_master_keyseed[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 console_keyseed_4xx[0x10] = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
static const u8 new_master_keyseed[0x10] = { 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };

static const u8 new_master_kek_seeds[][0x10] = {
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */
};

int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw);
void bootloader();
int keygen(u8 *keyblob, u32 fwVer, void * pkg1, pk11_offs * offs);
void bootloader();
Oops, something went wrong.

0 comments on commit 032e5c2

Please sign in to comment.