-
-
Save SciresM/d1a1e00e95dae2d23f5a224b15fae769 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c | |
index a1fd252..e81ff1a 100644 | |
--- a/exosphere/src/bootup.c | |
+++ b/exosphere/src/bootup.c | |
@@ -30,6 +30,23 @@ | |
static bool g_has_booted_up = false; | |
+ | |
+void setup_dram_magic_numbers(void) { | |
+ /* TODO: Why does these DRAM write occur? */ | |
+ unsigned int target_fw = exosphere_get_target_firmware(); | |
+ if (EXOSPHERE_TARGET_FIRMWARE_400 <= target_fw) { | |
+ (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; | |
+ flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); | |
+ if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { | |
+ (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; | |
+ (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; | |
+ (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; | |
+ flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); | |
+ } | |
+ } | |
+ __dsb_sy(); | |
+} | |
+ | |
void bootup_misc_mmio(void) { | |
/* Initialize Fuse registers. */ | |
fuse_init(); | |
@@ -50,10 +67,8 @@ void bootup_misc_mmio(void) { | |
se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); | |
se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); | |
- /* TODO: Why does this DRAM write occur? */ | |
- if (!g_has_booted_up && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { | |
- /* 4.x writes this magic number into DRAM. Why? */ | |
- (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; | |
+ if (!g_has_booted_up && EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware() && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { | |
+ setup_dram_magic_numbers(); | |
} | |
/* Todo: What? */ | |
@@ -201,6 +216,9 @@ void bootup_misc_mmio(void) { | |
} | |
void setup_4x_mmio(void) { | |
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ configure_gpu_ucode_carveout(); | |
+ } | |
/* TODO: What are these MC reg writes? */ | |
MAKE_MC_REG(0x65C) = 0xFFFFF000; | |
MAKE_MC_REG(0x660) = 0; | |
diff --git a/exosphere/src/bootup.h b/exosphere/src/bootup.h | |
index 2f5f0d1..ccbed95 100644 | |
--- a/exosphere/src/bootup.h | |
+++ b/exosphere/src/bootup.h | |
@@ -86,6 +86,8 @@ void bootup_misc_mmio(void); | |
void setup_4x_mmio(void); | |
+void setup_dram_magic_numbers(void); | |
+ | |
void setup_current_core_state(void); | |
void identity_unmap_iram_cd_tzram(void); | |
diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h | |
index f02aa24..45413a9 100644 | |
--- a/exosphere/src/exocfg.h | |
+++ b/exosphere/src/exocfg.h | |
@@ -16,9 +16,10 @@ | |
#define EXOSPHERE_TARGET_FIRMWARE_300 3 | |
#define EXOSPHERE_TARGET_FIRMWARE_400 4 | |
#define EXOSPHERE_TARGET_FIRMWARE_500 5 | |
+#define EXOSPHERE_TARGET_FIRMWARE_600 6 | |
/* TODO: What should this be, for release? */ | |
-#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_500 | |
+#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_600 | |
#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 | |
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) | |
diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c | |
index 1dc0f9c..f0ee55e 100644 | |
--- a/exosphere/src/lp0.c | |
+++ b/exosphere/src/lp0.c | |
@@ -228,12 +228,13 @@ void save_se_and_power_down_cpu(void) { | |
/* TODO: uart_log("OYASUMI"); */ | |
} | |
- __dsb_sy(); | |
- | |
finalize_powerdown(); | |
} | |
uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argument) { | |
+ /* TODO: 6.0.0 introduces heavy deja vu mitigations. */ | |
+ /* Exosphere may want to implement these. */ | |
+ | |
/* Ensure SMC call is to enter deep sleep. */ | |
if ((power_state & 0x17FFF) != 0x1001B) { | |
return 0xFFFFFFFD; | |
diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c | |
index 4b83da8..6926c99 100644 | |
--- a/exosphere/src/masterkey.c | |
+++ b/exosphere/src/masterkey.c | |
@@ -23,6 +23,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = | |
{0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ | |
{0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ | |
{0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ | |
+ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ | |
}; | |
/* Retail unit keys. */ | |
@@ -33,6 +34,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = | |
{0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ | |
{0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ | |
{0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ | |
+ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ | |
}; | |
bool check_mkey_revision(unsigned int revision, bool is_retail) { | |
@@ -105,7 +107,7 @@ unsigned int mkey_get_keyslot(unsigned int revision) { | |
void set_old_devkey(unsigned int revision, const uint8_t *key) { | |
- if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_500_CURRENT <= revision) { | |
+ if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) { | |
generic_panic(); | |
} | |
@@ -122,7 +124,7 @@ unsigned int devkey_get_keyslot(unsigned int revision) { | |
} | |
if (revision >= 1) { | |
- if (revision == MASTERKEY_REVISION_500_CURRENT) { | |
+ if (revision == MASTERKEY_REVISION_600_CURRENT) { | |
return KEYSLOT_SWITCH_DEVICEKEY; | |
} else { | |
/* Load into a temp keyslot. */ | |
diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h | |
index 5a6a523..9a43454 100644 | |
--- a/exosphere/src/masterkey.h | |
+++ b/exosphere/src/masterkey.h | |
@@ -3,14 +3,15 @@ | |
/* This is glue code to enable master key support across versions. */ | |
-/* TODO: Update to 0x6 on release of new master key. */ | |
-#define MASTERKEY_REVISION_MAX 0x5 | |
+/* TODO: Update to 0x7 on release of new master key. */ | |
+#define MASTERKEY_REVISION_MAX 0x6 | |
#define MASTERKEY_REVISION_100_230 0x00 | |
#define MASTERKEY_REVISION_300 0x01 | |
#define MASTERKEY_REVISION_301_302 0x02 | |
#define MASTERKEY_REVISION_400_410 0x03 | |
-#define MASTERKEY_REVISION_500_CURRENT 0x04 | |
+#define MASTERKEY_REVISION_500_510 0x04 | |
+#define MASTERKEY_REVISION_600_CURRENT 0x05 | |
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) | |
diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c | |
index 4a4aed9..080e6d7 100644 | |
--- a/exosphere/src/mc.c | |
+++ b/exosphere/src/mc.c | |
@@ -22,40 +22,48 @@ volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { | |
return NULL; | |
} | |
-void configure_default_carveouts(void) { | |
- /* Configure Carveout 1 (UNUSED) */ | |
- volatile security_carveout_t *carveout = get_carveout_by_id(1); | |
- carveout->paddr_low = 0; | |
+void configure_gpu_ucode_carveout(void) { | |
+ /* Starting in 6.0.0, Carveout 2 is configured later on. */ | |
+ /* This is a helper function to make this easier... */ | |
+ volatile security_carveout_t *carveout = get_carveout_by_id(2); | |
+ carveout->paddr_low = 0x80020000; | |
carveout->paddr_high = 0; | |
- carveout->size_big_pages = 0; | |
+ carveout->size_big_pages = 2; /* 0x40000 */ | |
carveout->flags_0 = 0; | |
carveout->flags_1 = 0; | |
- carveout->flags_2 = 0; | |
+ carveout->flags_2 = 0x3000000; | |
carveout->flags_3 = 0; | |
- carveout->flags_4 = 0; | |
+ carveout->flags_4 = 0x300; | |
carveout->flags_5 = 0; | |
carveout->flags_6 = 0; | |
carveout->flags_7 = 0; | |
carveout->flags_8 = 0; | |
carveout->flags_9 = 0; | |
- carveout->allowed_clients = 0x04000006; | |
+ carveout->allowed_clients = 0x440167E; | |
+} | |
- /* Configure Carveout 2 (GPU UCODE) */ | |
- carveout = get_carveout_by_id(2); | |
- carveout->paddr_low = 0x80020000; | |
+void configure_default_carveouts(void) { | |
+ /* Configure Carveout 1 (UNUSED) */ | |
+ volatile security_carveout_t *carveout = get_carveout_by_id(1); | |
+ carveout->paddr_low = 0; | |
carveout->paddr_high = 0; | |
- carveout->size_big_pages = 2; /* 0x40000 */ | |
+ carveout->size_big_pages = 0; | |
carveout->flags_0 = 0; | |
carveout->flags_1 = 0; | |
- carveout->flags_2 = 0x3000000; | |
+ carveout->flags_2 = 0; | |
carveout->flags_3 = 0; | |
- carveout->flags_4 = 0x300; | |
+ carveout->flags_4 = 0; | |
carveout->flags_5 = 0; | |
carveout->flags_6 = 0; | |
carveout->flags_7 = 0; | |
carveout->flags_8 = 0; | |
carveout->flags_9 = 0; | |
- carveout->allowed_clients = 0x440167E; | |
+ carveout->allowed_clients = 0x04000006; | |
+ | |
+ /* Configure Carveout 2 (GPU UCODE) */ | |
+ if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ configure_gpu_ucode_carveout(); | |
+ } | |
/* Configure Carveout 3 (UNUSED GPU) */ | |
carveout = get_carveout_by_id(3); | |
diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h | |
index de51417..3e735e3 100644 | |
--- a/exosphere/src/mc.h | |
+++ b/exosphere/src/mc.h | |
@@ -50,6 +50,7 @@ typedef struct { | |
volatile security_carveout_t *get_carveout_by_id(unsigned int carveout); | |
void configure_default_carveouts(void); | |
+void configure_gpu_ucode_carveout(void); | |
void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size); | |
diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c | |
index 26db125..78d953c 100644 | |
--- a/exosphere/src/package2.c | |
+++ b/exosphere/src/package2.c | |
@@ -22,20 +22,31 @@ | |
extern void *__start_cold_addr; | |
extern size_t __bin_size; | |
+ | |
+static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { | |
+ {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ | |
+ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ | |
+ {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4} /* 6.x New Device Key Source. */ | |
+}; | |
+ | |
+static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { | |
+ {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ | |
+ {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ | |
+ {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF} /* 6.x New Device Keygen Source. */ | |
+}; | |
+ | |
+static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { | |
+ {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ | |
+ {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ | |
+ {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5} /* 6.x New Device Keygen Source. */ | |
+}; | |
+ | |
static void derive_new_device_keys(unsigned int keygen_keyslot) { | |
uint8_t work_buffer[0x10]; | |
- static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { | |
- {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ | |
- {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C} /* 5.x New Device Key Source. */ | |
- }; | |
- | |
- static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { | |
- {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ | |
- {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E} /* 5.x New Device Keygen Source. */ | |
- }; | |
+ bool is_retail = configitem_is_retail(); | |
for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) { | |
se_aes_ecb_decrypt_block(keygen_keyslot, work_buffer, 0x10, new_device_key_sources[revision], 0x10); | |
- decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), new_device_keygen_sources[revision], 0x10); | |
+ decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), is_retail ? new_device_keygen_sources[revision] : new_device_keygen_sources_dev[revision], 0x10); | |
if (revision < MASTERKEY_NUM_NEW_DEVICE_KEYS - 1) { | |
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10); | |
set_old_devkey(revision + MASTERKEY_REVISION_400_410, work_buffer); | |
@@ -94,6 +105,7 @@ static void setup_se(void) { | |
derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY); | |
break; | |
case EXOSPHERE_TARGET_FIRMWARE_500: | |
+ case EXOSPHERE_TARGET_FIRMWARE_600: | |
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); | |
break; | |
} | |
@@ -120,14 +132,18 @@ static void setup_boot_config(void) { | |
if (configitem_is_retail()) { | |
bootconfig_clear(); | |
} else { | |
- flush_dcache_range((uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER, (uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER + sizeof(bootconfig_t)); | |
- bootconfig_load_and_verify((bootconfig_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER); | |
+ void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER; | |
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X; | |
+ } | |
+ flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t)); | |
+ bootconfig_load_and_verify((bootconfig_t *)bootconfig_ptr); | |
} | |
} | |
static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { | |
/* Derive package2 key. */ | |
- const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; | |
+ static const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; | |
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size); | |
flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size); | |
unsigned int keyslot = mkey_get_keyslot(master_key_rev); | |
@@ -383,7 +399,22 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke | |
} | |
static void copy_warmboot_bin_to_dram() { | |
- uint8_t *warmboot_src = (uint8_t *)0x4003B000; | |
+ uint8_t *warmboot_src; | |
+ switch (exosphere_get_target_firmware()) { | |
+ case EXOSPHERE_TARGET_FIRMWARE_100: | |
+ case EXOSPHERE_TARGET_FIRMWARE_200: | |
+ case EXOSPHERE_TARGET_FIRMWARE_300: | |
+ default: | |
+ generic_panic(); | |
+ break; | |
+ case EXOSPHERE_TARGET_FIRMWARE_400: | |
+ case EXOSPHERE_TARGET_FIRMWARE_500: | |
+ warmboot_src = (uint8_t *)0x4003B000; | |
+ break; | |
+ case EXOSPHERE_TARGET_FIRMWARE_600: | |
+ warmboot_src = (uint8_t *)0x4003D800; | |
+ break; | |
+ } | |
uint8_t *warmboot_dst = (uint8_t *)0x8000D000; | |
const size_t warmboot_size = 0x2000; | |
@@ -432,8 +463,18 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { | |
MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; | |
MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; | |
MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; | |
- MAKE_REG32(PMC_BASE + 0x334) |= 0x10; | |
- MAKE_REG32(PMC_BASE + 0x360) = 6; | |
+ MAKE_REG32(PMC_BASE + 0x334) |= 0x10; | |
+ switch (exosphere_get_target_firmware()) { | |
+ case EXOSPHERE_TARGET_FIRMWARE_400: | |
+ MAKE_REG32(PMC_BASE + 0x360) = 5; | |
+ break; | |
+ case EXOSPHERE_TARGET_FIRMWARE_500: | |
+ MAKE_REG32(PMC_BASE + 0x360) = 6; | |
+ break; | |
+ case EXOSPHERE_TARGET_FIRMWARE_600: | |
+ MAKE_REG32(PMC_BASE + 0x360) = 0x87; | |
+ break; | |
+ } | |
} | |
wait(1000); | |
@@ -449,7 +490,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { | |
randomcache_init(); | |
/* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */ | |
- memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); | |
+ //memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); | |
/* Let NX Bootloader know that we're running. */ | |
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1; | |
@@ -474,6 +515,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { | |
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { | |
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); | |
copy_warmboot_bin_to_dram(); | |
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ setup_dram_magic_numbers(); | |
+ } | |
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); | |
} else { | |
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2); | |
diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h | |
index 156ab52..94ddd46 100644 | |
--- a/exosphere/src/package2.h | |
+++ b/exosphere/src/package2.h | |
@@ -34,6 +34,7 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { | |
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL) | |
#define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull)) | |
+#define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull)) | |
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) | |
diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c | |
index a0f9607..6d33fd0 100644 | |
--- a/exosphere/src/smc_api.c | |
+++ b/exosphere/src/smc_api.c | |
@@ -142,6 +142,7 @@ void set_version_specific_smcs(void) { | |
/* Do nothing. */ | |
break; | |
case EXOSPHERE_TARGET_FIRMWARE_500: | |
+ case EXOSPHERE_TARGET_FIRMWARE_600: | |
/* No more LoadSecureExpModKey. */ | |
g_smc_user_table[0xE].handler = NULL; | |
g_smc_user_table[0xC].id = 0xC300D60C; | |
diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c | |
index 4f88365..ee440bb 100644 | |
--- a/exosphere/src/smc_user.c | |
+++ b/exosphere/src/smc_user.c | |
@@ -24,6 +24,20 @@ static uint8_t g_imported_exponents[4][0x100]; | |
static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6}; | |
+static bool is_user_keyslot_valid(unsigned int keyslot) { | |
+ switch (exosphere_get_target_firmware()) { | |
+ case EXOSPHERE_TARGET_FIRMWARE_100: | |
+ case EXOSPHERE_TARGET_FIRMWARE_200: | |
+ case EXOSPHERE_TARGET_FIRMWARE_300: | |
+ case EXOSPHERE_TARGET_FIRMWARE_400: | |
+ case EXOSPHERE_TARGET_FIRMWARE_500: | |
+ return keyslot <= 3; | |
+ case EXOSPHERE_TARGET_FIRMWARE_600: | |
+ default: | |
+ return keyslot <= 5; | |
+ } | |
+} | |
+ | |
void set_exp_mod_done(bool done) { | |
g_exp_mod_done = done; | |
} | |
@@ -136,7 +150,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { | |
/* 5.0.0+ Bounds checking. */ | |
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { | |
if (is_personalized) { | |
- if (master_key_rev > MASTERKEY_REVISION_500_CURRENT || ((1 << (master_key_rev + 1)) & 0x33) == 0) { | |
+ if (master_key_rev > MASTERKEY_REVISION_600_CURRENT || ((1 << (master_key_rev + 1)) & 0x73) == 0) { | |
return 2; | |
} | |
if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) { | |
@@ -222,7 +236,7 @@ uint32_t user_load_aes_key(smc_args_t *args) { | |
uint64_t wrapped_key[2]; | |
uint32_t keyslot = (uint32_t)args->X[1]; | |
- if (keyslot > 3) { | |
+ if (!is_user_keyslot_valid(keyslot)) { | |
return 2; | |
} | |
@@ -262,6 +276,10 @@ uint32_t crypt_aes_done_handler(void) { | |
uint32_t user_crypt_aes(smc_args_t *args) { | |
uint32_t keyslot = args->X[1] & 3; | |
uint32_t mode = (args->X[1] >> 4) & 3; | |
+ | |
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ keyslot = args->X[1] & 7; | |
+ } | |
uint64_t iv_ctr[2]; | |
iv_ctr[0] = args->X[2]; | |
@@ -271,7 +289,7 @@ uint32_t user_crypt_aes(smc_args_t *args) { | |
uint32_t out_ll_paddr = (uint32_t)(args->X[5]); | |
size_t size = args->X[6]; | |
- if (size & 0xF) { | |
+ if (!is_user_keyslot_valid(keyslot) || size & 0xF) { | |
return 2; | |
} | |
@@ -390,7 +408,7 @@ uint32_t user_compute_cmac(smc_args_t *args) { | |
upage_ref_t page_ref; | |
/* Validate keyslot and size. */ | |
- if (keyslot > 3 || args->X[3] > 0x400) { | |
+ if (!is_user_keyslot_valid(keyslot) || args->X[3] > 0x400) { | |
return 2; | |
} | |
@@ -626,7 +644,16 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { | |
void *user_wrapped_key = (void *)args->X[1]; | |
void *user_modulus = (void *)args->X[2]; | |
- unsigned int master_key_rev = (unsigned int)args->X[7]; | |
+ unsigned int option = (unsigned int)args->X[7]; | |
+ unsigned int master_key_rev; | |
+ unsigned int titlekey_type; | |
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { | |
+ master_key_rev = option & 0x3F; | |
+ titlekey_type = (option >> 6) & 1; | |
+ } else { | |
+ master_key_rev = option; | |
+ titlekey_type = 0; | |
+ } | |
if(master_key_rev > 0) { | |
master_key_rev -= 1; | |
@@ -657,6 +684,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { | |
tkey_set_expected_label_hash(&args->X[3]); | |
tkey_set_master_key_rev(master_key_rev); | |
+ tkey_set_type(titlekey_type); | |
/* Hardcode RSA keyslot 0. */ | |
set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[0], 0x100); | |
@@ -670,7 +698,7 @@ uint32_t user_load_titlekey(smc_args_t *args) { | |
uint64_t sealed_titlekey[2]; | |
uint32_t keyslot = (uint32_t)args->X[1]; | |
- if (keyslot > 3) { | |
+ if (!is_user_keyslot_valid(keyslot)) { | |
return 2; | |
} | |
@@ -705,6 +733,7 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) { | |
} | |
tkey_set_master_key_rev(master_key_rev); | |
+ tkey_set_type(0); | |
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10); | |
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10); | |
diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c | |
index 4c46ed2..7e2d4ea 100644 | |
--- a/exosphere/src/titlekey.c | |
+++ b/exosphere/src/titlekey.c | |
@@ -3,6 +3,7 @@ | |
#include "utils.h" | |
#include "arm.h" | |
+#include "exocfg.h" | |
#include "titlekey.h" | |
#include "masterkey.h" | |
@@ -10,6 +11,7 @@ | |
static uint64_t g_tkey_expected_label_hash[4]; | |
static unsigned int g_tkey_master_key_rev = MASTERKEY_REVISION_MAX; | |
+static unsigned int g_tkey_type = 0; | |
/* Set the expected db prefix. */ | |
void tkey_set_expected_label_hash(uint64_t *label_hash) { | |
@@ -25,6 +27,17 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) { | |
g_tkey_master_key_rev = master_key_rev; | |
} | |
+static void tkey_validate_type(unsigned int type) { | |
+ if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600)) { | |
+ generic_panic(); | |
+ } | |
+} | |
+ | |
+void tkey_set_type(unsigned int type) { | |
+ tkey_validate_type(type); | |
+ g_tkey_type = type; | |
+} | |
+ | |
/* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */ | |
void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed, size_t seed_size) { | |
uint8_t cur_hash[0x20]; | |
@@ -136,18 +149,19 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si | |
return wrapped_titlekey_size; | |
} | |
+static const uint8_t titlekek_sources[TITLEKEY_TYPE_MAX+1][0x10] = { | |
+ {0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B}, | |
+ {0x3B, 0x78, 0xF2, 0x61, 0x0F, 0x9D, 0x5A, 0xE2, 0x7B, 0x4E, 0x45, 0xAF, 0xCB, 0x0B, 0x67, 0x4D} | |
+}; | |
+ | |
void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) { | |
if (g_tkey_master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) { | |
generic_panic(); | |
} | |
- | |
- const uint8_t titlekek_source[0x10] = { | |
- 0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B | |
- }; | |
- | |
+ | |
/* Generate the appropriate titlekek into keyslot 9. */ | |
unsigned int master_keyslot = mkey_get_keyslot(g_tkey_master_key_rev); | |
- decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_source, 0x10); | |
+ decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_tkey_type], 0x10); | |
/* Unwrap the titlekey using the titlekek. */ | |
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10); | |
diff --git a/exosphere/src/titlekey.h b/exosphere/src/titlekey.h | |
index a74949b..6d19a2d 100644 | |
--- a/exosphere/src/titlekey.h | |
+++ b/exosphere/src/titlekey.h | |
@@ -3,8 +3,11 @@ | |
#include <stdint.h> | |
+#define TITLEKEY_TYPE_MAX 0x1 | |
+ | |
void tkey_set_expected_label_hash(uint64_t *label_hash); | |
void tkey_set_master_key_rev(unsigned int master_key_rev); | |
+void tkey_set_type(unsigned int type); | |
size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_size); | |
diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c | |
index 2f60fbf..09d3938 100644 | |
--- a/exosphere/src/utils.c | |
+++ b/exosphere/src/utils.c | |
@@ -14,14 +14,15 @@ __attribute__ ((noreturn)) void panic(uint32_t code) { | |
APBDEV_PMC_SCRATCH200_0 = code; | |
} | |
- /* Uncomment for Debugging. | |
+ /* // Uncomment for Debugging. | |
uint64_t temp_reg; | |
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM)) = APBDEV_PMC_SCRATCH200_0; | |
SAVE_SYSREG64(ESR_EL3, 0x10); | |
SAVE_SYSREG64(ELR_EL3, 0x18); | |
SAVE_SYSREG64(FAR_EL3, 0x20); | |
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; | |
- MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; */ | |
+ MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; | |
+ */ | |
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */ | |
/* For now, just use NX BOOTLOADER's panic. */ | |
@@ -32,7 +33,7 @@ __attribute__ ((noreturn)) void panic(uint32_t code) { | |
} | |
__attribute__ ((noreturn)) void generic_panic(void) { | |
- /* Uncomment for Debugging. | |
+ /* //Uncomment for Debugging. | |
uint64_t temp_reg; | |
do { __asm__ __volatile__ ("mov %0, LR" : "=r"(temp_reg) :: "memory"); } while (false); | |
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x28) = (uint32_t)((temp_reg >> 0) & 0xFFFFFFFFULL); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment