Support Mariko, patched Erista
This commit is contained in:
parent
044c8b32f0
commit
a0eaa5e4ed
8 changed files with 406 additions and 183 deletions
|
@ -23,6 +23,19 @@
|
|||
#define PKG1_OFFSET 0x100000
|
||||
#define KEYBLOB_OFFSET 0x180000
|
||||
|
||||
typedef struct _bl_hdr_t210b01_t
|
||||
{
|
||||
u8 aes_mac[0x10];
|
||||
u8 rsa_sig[0x100];
|
||||
u8 salt[0x20];
|
||||
u8 sha256[0x20];
|
||||
u32 version;
|
||||
u32 size;
|
||||
u32 load_addr;
|
||||
u32 entrypoint;
|
||||
u8 rsvd[0x10];
|
||||
} bl_hdr_t210b01_t;
|
||||
|
||||
typedef struct _pkg1_id_t
|
||||
{
|
||||
const char *id;
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
|
||||
// Sha256 hash of the null string.
|
||||
static u8 null_hash[0x20] = {
|
||||
static const u8 null_hash[0x20] __attribute__((aligned(4))) = {
|
||||
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
|
||||
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55};
|
||||
|
||||
static const u8 keyblob_key_source[][0x10] = {
|
||||
static const u8 keyblob_key_source[][0x10] __attribute__((aligned(4))) = {
|
||||
{0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, //1.0.0
|
||||
{0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, //3.0.0
|
||||
{0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, //3.0.1
|
||||
|
@ -28,7 +28,7 @@ static const u8 keyblob_key_source[][0x10] = {
|
|||
{0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0} //6.0.0
|
||||
};
|
||||
|
||||
static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_620 + 1][0x10] = {
|
||||
static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_620 + 1][0x10] __attribute__((aligned(4))) = {
|
||||
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, //6.2.0
|
||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, //7.0.0
|
||||
{0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, //8.1.0
|
||||
|
@ -36,7 +36,7 @@ static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION
|
|||
{0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A}, //9.1.0
|
||||
};
|
||||
|
||||
static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
|
||||
static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] __attribute__((aligned(4))) = {
|
||||
{0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */
|
||||
{0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD}, /* Master key 00 encrypted with Master key 01. */
|
||||
{0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */
|
||||
|
@ -52,29 +52,29 @@ static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
|
|||
|
||||
//======================================Keys======================================//
|
||||
// from Package1 -> Secure_Monitor
|
||||
static const u8 aes_kek_generation_source[0x10] = {
|
||||
static const u8 aes_kek_generation_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9};
|
||||
static const u8 aes_kek_seed_01[0x10] = {
|
||||
static const u8 aes_kek_seed_01[0x10] __attribute__((aligned(4))) = {
|
||||
0xA2, 0xAB, 0xBF, 0x9C, 0x92, 0x2F, 0xBB, 0xE3, 0x78, 0x79, 0x9B, 0xC0, 0xCC, 0xEA, 0xA5, 0x74};
|
||||
static const u8 aes_kek_seed_03[0x10] = {
|
||||
static const u8 aes_kek_seed_03[0x10] __attribute__((aligned(4))) = {
|
||||
0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB};
|
||||
static const u8 package2_key_source[0x10] = {
|
||||
static const u8 package2_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7};
|
||||
static const u8 titlekek_source[0x10] = {
|
||||
static const u8 titlekek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B};
|
||||
static const u8 retail_specific_aes_key_source[0x10] = {
|
||||
static const u8 retail_specific_aes_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95};
|
||||
|
||||
// from Package1ldr (or Secure_Monitor on 6.2.0+)
|
||||
static const u8 keyblob_mac_key_source[0x10] = {
|
||||
static const u8 keyblob_mac_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5};
|
||||
static const u8 master_key_source[0x10] = {
|
||||
static const u8 master_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C};
|
||||
static const u8 per_console_key_source[0x10] = {
|
||||
static const u8 per_console_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78};
|
||||
static const u8 device_master_key_source_kek_source[0x10] = {
|
||||
static const u8 device_master_key_source_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28};
|
||||
static const u8 mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600 + 1][0x10] = {
|
||||
static const u8 mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600 + 1][0x10] __attribute__((aligned(4))) = {
|
||||
{0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56}, // 6.0.0.
|
||||
{0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE}, // 6.2.0.
|
||||
{0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A}, // 7.0.0.
|
||||
|
@ -83,7 +83,7 @@ static const u8 mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_
|
|||
{0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}, // 9.1.0.
|
||||
};
|
||||
|
||||
static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
|
||||
static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = {
|
||||
{0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.0.0 Device Master Key Source Source. */
|
||||
{0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.0.0 Device Master Key Source Source. */
|
||||
{0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.0.0 Device Master Key Source Source. */
|
||||
|
@ -95,18 +95,18 @@ static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FI
|
|||
};
|
||||
|
||||
// from ES
|
||||
static const u8 eticket_rsa_kek_source[0x10] = {
|
||||
static const u8 eticket_rsa_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0XDB, 0XA4, 0X51, 0X12, 0X4C, 0XA0, 0XA9, 0X83, 0X68, 0X14, 0XF5, 0XED, 0X95, 0XE3, 0X12, 0X5B};
|
||||
static const u8 eticket_rsa_kekek_source[0x10] = {
|
||||
static const u8 eticket_rsa_kekek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0X46, 0X6E, 0X57, 0XB7, 0X4A, 0X44, 0X7F, 0X02, 0XF3, 0X21, 0XCD, 0XE5, 0X8F, 0X2F, 0X55, 0X35};
|
||||
|
||||
// from SSL
|
||||
static const u8 ssl_rsa_kek_source_x[0x10] = {
|
||||
static const u8 ssl_rsa_kek_source_x[0x10] __attribute__((aligned(4))) = {
|
||||
0X7F, 0X5B, 0XB0, 0X84, 0X7B, 0X25, 0XAA, 0X67, 0XFA, 0XC8, 0X4B, 0XE2, 0X3D, 0X7B, 0X69, 0X03};
|
||||
static const u8 ssl_rsa_kek_source_y[0x10] = {
|
||||
static const u8 ssl_rsa_kek_source_y[0x10] __attribute__((aligned(4))) = {
|
||||
0X9A, 0X38, 0X3B, 0XF4, 0X31, 0XD0, 0XBD, 0X81, 0X32, 0X53, 0X4B, 0XA9, 0X64, 0X39, 0X7D, 0XE3};
|
||||
|
||||
static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
|
||||
static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = {
|
||||
{0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.0.0 Device Master Kek Source. */
|
||||
{0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.0.0 Device Master Kek Source. */
|
||||
{0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.0.0 Device Master Kek Source. */
|
||||
|
@ -118,13 +118,13 @@ static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_
|
|||
};
|
||||
|
||||
// from SPL
|
||||
static const u8 aes_key_generation_source[0x10] = {
|
||||
static const u8 aes_key_generation_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8};
|
||||
|
||||
// from FS
|
||||
static const u8 bis_kek_source[0x10] = {
|
||||
static const u8 bis_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
|
||||
static const u8 bis_key_source[3][0x20] = {
|
||||
static const u8 bis_key_source[3][0x20] __attribute__((aligned(4))) = {
|
||||
{0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48,
|
||||
0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06},
|
||||
{0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F,
|
||||
|
@ -132,32 +132,32 @@ static const u8 bis_key_source[3][0x20] = {
|
|||
{0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C,
|
||||
0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4}
|
||||
};
|
||||
static const u8 header_kek_source[0x10] = {
|
||||
static const u8 header_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0x1F, 0x12, 0x91, 0x3A, 0x4A, 0xCB, 0xF0, 0x0D, 0x4C, 0xDE, 0x3A, 0xF6, 0xD5, 0x23, 0x88, 0x2A};
|
||||
static const u8 header_key_source[0x20] = {
|
||||
static const u8 header_key_source[0x20] __attribute__((aligned(4))) = {
|
||||
0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0,
|
||||
0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2};
|
||||
static const u8 key_area_key_sources[3][0x10] = {
|
||||
static const u8 key_area_key_sources[3][0x10] __attribute__((aligned(4))) = {
|
||||
{0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D}, // application
|
||||
{0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82}, // ocean
|
||||
{0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A}, // system
|
||||
};
|
||||
static const u8 save_mac_kek_source[0x10] = {
|
||||
static const u8 save_mac_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0XD8, 0X9C, 0X23, 0X6E, 0XC9, 0X12, 0X4E, 0X43, 0XC8, 0X2B, 0X03, 0X87, 0X43, 0XF9, 0XCF, 0X1B};
|
||||
static const u8 save_mac_key_source[0x10] = {
|
||||
static const u8 save_mac_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0XE4, 0XCD, 0X3D, 0X4A, 0XD5, 0X0F, 0X74, 0X28, 0X45, 0XA4, 0X87, 0XE5, 0XA0, 0X63, 0XEA, 0X1F};
|
||||
static const u8 save_mac_sd_card_kek_source[0x10] = {
|
||||
static const u8 save_mac_sd_card_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0X04, 0X89, 0XEF, 0X5D, 0X32, 0X6E, 0X1A, 0X59, 0XC4, 0XB7, 0XAB, 0X8C, 0X36, 0X7A, 0XAB, 0X17};
|
||||
static const u8 save_mac_sd_card_key_source[0x10] = {
|
||||
static const u8 save_mac_sd_card_key_source[0x10] __attribute__((aligned(4))) = {
|
||||
0X6F, 0X64, 0X59, 0X47, 0XC5, 0X61, 0X46, 0XF9, 0XFF, 0XA0, 0X45, 0XD5, 0X95, 0X33, 0X29, 0X18};
|
||||
static const u8 sd_card_custom_storage_key_source[0x20] = {
|
||||
static const u8 sd_card_custom_storage_key_source[0x20] __attribute__((aligned(4))) = {
|
||||
0X37, 0X0C, 0X34, 0X5E, 0X12, 0XE4, 0XCE, 0XFE, 0X21, 0XB5, 0X8E, 0X64, 0XDB, 0X52, 0XAF, 0X35,
|
||||
0X4F, 0X2C, 0XA5, 0XA3, 0XFC, 0X99, 0X9A, 0X47, 0XC0, 0X3E, 0XE0, 0X04, 0X48, 0X5B, 0X2F, 0XD0};
|
||||
static const u8 sd_card_kek_source[0x10] = {
|
||||
static const u8 sd_card_kek_source[0x10] __attribute__((aligned(4))) = {
|
||||
0X88, 0X35, 0X8D, 0X9C, 0X62, 0X9B, 0XA1, 0XA0, 0X01, 0X47, 0XDB, 0XE0, 0X62, 0X1B, 0X54, 0X32};
|
||||
static const u8 sd_card_nca_key_source[0x20] = {
|
||||
static const u8 sd_card_nca_key_source[0x20] __attribute__((aligned(4))) = {
|
||||
0X58, 0X41, 0XA2, 0X84, 0X93, 0X5B, 0X56, 0X27, 0X8B, 0X8E, 0X1F, 0XC5, 0X18, 0XE9, 0X9F, 0X2B,
|
||||
0X67, 0XC7, 0X93, 0XF0, 0XF2, 0X4F, 0XDE, 0XD0, 0X75, 0X49, 0X5D, 0XCA, 0X00, 0X6D, 0X99, 0XC2};
|
||||
static const u8 sd_card_save_key_source[0x20] = {
|
||||
static const u8 sd_card_save_key_source[0x20] __attribute__((aligned(4))) = {
|
||||
0X24, 0X49, 0XB7, 0X22, 0X72, 0X67, 0X03, 0XA8, 0X19, 0X65, 0XE6, 0XE3, 0XEA, 0X58, 0X2F, 0XDD,
|
||||
0X9A, 0X95, 0X15, 0X17, 0XB1, 0X6E, 0X8F, 0X7F, 0X1F, 0X68, 0X26, 0X31, 0X52, 0XEA, 0X29, 0X6A};
|
||||
|
|
|
@ -74,7 +74,7 @@ static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x
|
|||
static void _save_key(const char *name, const void *data, u32 len, char *outbuf);
|
||||
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf);
|
||||
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
|
||||
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *master_key);
|
||||
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *new_device_key, const void *master_key);
|
||||
// titlekey functions
|
||||
static bool _test_key_pair(const void *E, const void *D, const void *N);
|
||||
|
||||
|
@ -112,9 +112,12 @@ static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) {
|
|||
EPRINTF("Unable to read pkg1.");
|
||||
return NULL;
|
||||
}
|
||||
*pkg1_id = pkg1_identify(pkg1);
|
||||
|
||||
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
|
||||
*pkg1_id = pkg1_identify(pkg1 + pk1_offset);
|
||||
if (!*pkg1_id) {
|
||||
EPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release.");
|
||||
gfx_hexdump(0, pkg1, 0x20);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -169,7 +172,7 @@ static bool _handle_sept(void *tsec_fw, u32 tsec_size, u32 kb, void *out_key) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
se_aes_key_read(se_key_acc_ctrl_get(12) == 0x6A ? 13 : 12, out_key, AES_128_KEY_SIZE);
|
||||
se_aes_key_get(se_key_acc_ctrl_get(12) == 0x6A ? 13 : 12, out_key, AES_128_KEY_SIZE);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -225,8 +228,15 @@ static bool _derive_tsec_keys(tsec_ctxt_t *tsec_ctxt, u32 kb, key_derivation_ctx
|
|||
return true;
|
||||
}
|
||||
|
||||
static void _derive_master_keys_post_620_erista(u32 pkg1_kb, key_derivation_ctx_t *keys) {
|
||||
u8 temp_key[AES_128_KEY_SIZE];
|
||||
static void _derive_master_key_mariko(u32 kb, key_derivation_ctx_t *keys) {
|
||||
// Relies on the SBK being properly set in slot 14
|
||||
se_aes_crypt_block_ecb(14, 0, keys->device_key_4x, device_master_key_source_kek_source);
|
||||
// Relies on the Mariko KEK being properly set in slot 12
|
||||
se_aes_unwrap_key(8, 12, &mariko_master_kek_sources[kb - KB_FIRMWARE_VERSION_600]);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->master_key[kb], master_key_source);
|
||||
}
|
||||
|
||||
static void _derive_master_keys_post_620(u32 pkg1_kb, key_derivation_ctx_t *keys) {
|
||||
// on firmware 6.2.0 only, the tsec_root_key is available
|
||||
if (pkg1_kb == KB_FIRMWARE_VERSION_620 && _key_exists(keys->tsec_keys + AES_128_KEY_SIZE)) {
|
||||
se_aes_key_set(8, keys->tsec_keys + AES_128_KEY_SIZE, AES_128_KEY_SIZE); // mkek6 = unwrap(mkeks6, tsecroot)
|
||||
|
@ -244,15 +254,15 @@ static void _derive_master_keys_post_620_erista(u32 pkg1_kb, key_derivation_ctx_
|
|||
se_aes_crypt_block_ecb(8, 0, keys->master_key[i - 1], master_key_vectors[i]);
|
||||
}
|
||||
se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE);
|
||||
se_aes_crypt_block_ecb(8, 0, temp_key, master_key_vectors[0]);
|
||||
if (!_key_exists(temp_key)) {
|
||||
se_aes_crypt_block_ecb(8, 0, keys->temp_key, master_key_vectors[0]);
|
||||
if (!_key_exists(keys->temp_key)) {
|
||||
break;
|
||||
}
|
||||
memcpy(keys->master_key[kb - 1], keys->master_key[kb], AES_128_KEY_SIZE);
|
||||
memset(keys->master_key[kb], 0, AES_128_KEY_SIZE);
|
||||
}
|
||||
if (_key_exists(temp_key)) {
|
||||
EPRINTFARGS("Unable to derive master key. kb = %d.\n Put current sept files on SD and retry.", pkg1_kb);
|
||||
if (_key_exists(keys->temp_key)) {
|
||||
EPRINTFARGS("Unable to derive master key. kb = %d.\n Check sept files on SD and retry.", pkg1_kb);
|
||||
memset(keys->master_key, 0, sizeof(keys->master_key));
|
||||
}
|
||||
}
|
||||
|
@ -261,11 +271,20 @@ static void _derive_master_keys_post_620_erista(u32 pkg1_kb, key_derivation_ctx_
|
|||
static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) {
|
||||
u8 *keyblob_block = (u8 *)calloc(KB_FIRMWARE_VERSION_600 + 1, NX_EMMC_BLOCKSIZE);
|
||||
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
|
||||
u8 keyblob_mac[AES_128_KEY_SIZE] = {0};
|
||||
u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0};
|
||||
|
||||
keys->sbk[0] = FUSE(FUSE_PRIVATE_KEY0);
|
||||
keys->sbk[1] = FUSE(FUSE_PRIVATE_KEY1);
|
||||
keys->sbk[2] = FUSE(FUSE_PRIVATE_KEY2);
|
||||
keys->sbk[3] = FUSE(FUSE_PRIVATE_KEY3);
|
||||
|
||||
if (keys->sbk[0] == 0xFFFFFFFF) {
|
||||
u8 *aes_keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE);
|
||||
memcpy(keys->sbk, aes_keys + 14 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
|
||||
free(aes_keys);
|
||||
}
|
||||
|
||||
se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2);
|
||||
se_aes_key_set(9, keys->sbk, sizeof(keys->sbk));
|
||||
|
||||
|
@ -315,23 +334,21 @@ static void _derive_bis_keys(key_derivation_ctx_t *keys) {
|
|||
if (key_generation)
|
||||
key_generation--;
|
||||
|
||||
if (_key_exists(keys->device_key)) {
|
||||
if (key_generation) {
|
||||
_get_device_key(8, keys->temp_key, key_generation, keys->device_key_4x, keys->master_key[0]);
|
||||
} else
|
||||
memcpy(keys->temp_key, keys->device_key, AES_128_KEY_SIZE);
|
||||
se_aes_key_set(8, keys->temp_key, AES_128_KEY_SIZE);
|
||||
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_source[0] + 0x10);
|
||||
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
|
||||
_generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_source[1] + 0x10);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_source[2] + 0x00);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_source[2] + 0x10);
|
||||
memcpy(keys->bis_key[3], keys->bis_key[2], 0x20);
|
||||
if (!(_key_exists(keys->device_key) || (key_generation && _key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x)))) {
|
||||
return;
|
||||
}
|
||||
_get_device_key(8, keys->temp_key, key_generation, keys->device_key, keys->device_key_4x, keys->master_key[0]);
|
||||
se_aes_key_set(8, keys->temp_key, AES_128_KEY_SIZE);
|
||||
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_source[0] + 0x10);
|
||||
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
|
||||
_generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_source[1] + 0x10);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_source[2] + 0x00);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_source[2] + 0x10);
|
||||
memcpy(keys->bis_key[3], keys->bis_key[2], 0x20);
|
||||
}
|
||||
|
||||
static void _derive_misc_keys(key_derivation_ctx_t *keys, u32 *derivable_key_count) {
|
||||
|
@ -365,13 +382,13 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, u32 *derivable_key_cou
|
|||
if (_key_exists(keys->master_key[0])) {
|
||||
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
|
||||
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
|
||||
_generate_kek(7, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL);
|
||||
se_aes_crypt_block_ecb(7, 0, keys->eticket_rsa_kek, eticket_rsa_kek_source);
|
||||
_generate_kek(8, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->eticket_rsa_kek, eticket_rsa_kek_source);
|
||||
|
||||
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
|
||||
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
|
||||
_generate_kek(7, ssl_rsa_kek_source_x, keys->master_key[0], keys->temp_key, NULL);
|
||||
se_aes_crypt_block_ecb(7, 0, keys->ssl_rsa_kek, ssl_rsa_kek_source_y);
|
||||
_generate_kek(8, ssl_rsa_kek_source_x, keys->master_key[0], keys->temp_key, NULL);
|
||||
se_aes_crypt_block_ecb(8, 0, keys->ssl_rsa_kek, ssl_rsa_kek_source_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,8 +428,8 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title
|
|||
return false;
|
||||
}
|
||||
|
||||
char ticket_bin_path[0x40] = "/ticket.bin";
|
||||
char ticket_list_bin_path[0x40] = "/ticket_list.bin";
|
||||
char ticket_bin_path[32] = "/ticket.bin";
|
||||
char ticket_list_bin_path[32] = "/ticket_list.bin";
|
||||
save_data_file_ctx_t ticket_file;
|
||||
|
||||
if (!save_open_file(save_ctx, &ticket_file, ticket_list_bin_path, OPEN_MODE_READ)) {
|
||||
|
@ -503,7 +520,7 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title
|
|||
}
|
||||
|
||||
void dump_keys() {
|
||||
key_derivation_ctx_t keys;
|
||||
key_derivation_ctx_t __attribute__((aligned(4))) keys = {0};
|
||||
|
||||
sd_mount();
|
||||
|
||||
|
@ -544,9 +561,10 @@ void dump_keys() {
|
|||
|
||||
// Master key derivation
|
||||
if (h_cfg.t210b01) {
|
||||
// todo: derive mariko master keys
|
||||
_derive_master_key_mariko(pkg1_id->kb, &keys);
|
||||
_derive_master_keys_post_620(pkg1_id->kb, &keys);
|
||||
} else {
|
||||
_derive_master_keys_post_620_erista(pkg1_id->kb, &keys);
|
||||
_derive_master_keys_post_620(pkg1_id->kb, &keys);
|
||||
_derive_master_keys_from_keyblobs(&keys);
|
||||
}
|
||||
|
||||
|
@ -625,7 +643,7 @@ void dump_keys() {
|
|||
goto get_titlekeys;
|
||||
}
|
||||
|
||||
u8 read_buf[0x20] = {0};
|
||||
u8 read_buf[0x20] __attribute__((aligned(4))) = {0};
|
||||
for (u32 i = 0x8000; i < f_size(&fp); i += 0x4000) {
|
||||
if (f_lseek(&fp, i) || f_read(&fp, read_buf, 0x20, &read_bytes) || read_bytes != 0x20)
|
||||
break;
|
||||
|
@ -669,8 +687,8 @@ get_titlekeys:
|
|||
keypair_generation--;
|
||||
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
|
||||
keys.temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
|
||||
u8 temp_device_key[AES_128_KEY_SIZE] = {0};
|
||||
_get_device_key(7, temp_device_key, keypair_generation, keys.device_key_4x, keys.master_key[0]);
|
||||
u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0};
|
||||
_get_device_key(7, temp_device_key, keypair_generation, keys.device_key, keys.device_key_4x, keys.master_key[0]);
|
||||
_generate_kek(7, eticket_rsa_kekek_source, temp_device_key, keys.temp_key, NULL);
|
||||
se_aes_crypt_block_ecb(7, 0, keys.eticket_rsa_kek_personalized, eticket_rsa_kek_source);
|
||||
memcpy(keys.temp_key, keys.eticket_rsa_kek_personalized, sizeof(keys.temp_key));
|
||||
|
@ -724,16 +742,16 @@ key_output: ;
|
|||
SAVE_KEY(aes_kek_generation_source);
|
||||
SAVE_KEY(aes_key_generation_source);
|
||||
SAVE_KEY(bis_kek_source);
|
||||
SAVE_KEY_FAMILY(keys.bis_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(bis_key, keys.bis_key, 0);
|
||||
SAVE_KEY_FAMILY(bis_key_source, 0);
|
||||
SAVE_KEY(keys.device_key);
|
||||
SAVE_KEY(keys.device_key_4x);
|
||||
SAVE_KEY(keys.eticket_rsa_kek);
|
||||
SAVE_KEY(keys.eticket_rsa_kek_personalized);
|
||||
SAVE_KEY_VAR(device_key, keys.device_key);
|
||||
SAVE_KEY_VAR(device_key_4x, keys.device_key_4x);
|
||||
SAVE_KEY_VAR(eticket_rsa_kek, keys.eticket_rsa_kek);
|
||||
SAVE_KEY_VAR(eticket_rsa_kek_personalized, keys.eticket_rsa_kek_personalized);
|
||||
SAVE_KEY(eticket_rsa_kek_source);
|
||||
SAVE_KEY(eticket_rsa_kekek_source);
|
||||
SAVE_KEY(header_kek_source);
|
||||
SAVE_KEY(keys.header_key);
|
||||
SAVE_KEY_VAR(header_key, keys.header_key);
|
||||
SAVE_KEY(header_key_source);
|
||||
SAVE_KEY_FAMILY_VAR(key_area_key_application, keys.key_area_key[0], 0);
|
||||
SAVE_KEY_VAR(key_area_key_application_source, key_area_key_sources[0]);
|
||||
|
@ -741,17 +759,17 @@ key_output: ;
|
|||
SAVE_KEY_VAR(key_area_key_ocean_source, key_area_key_sources[1]);
|
||||
SAVE_KEY_FAMILY_VAR(key_area_key_system, keys.key_area_key[2], 0);
|
||||
SAVE_KEY_VAR(key_area_key_system_source, key_area_key_sources[2]);
|
||||
SAVE_KEY_FAMILY(keys.keyblob, 0);
|
||||
SAVE_KEY_FAMILY(keys.keyblob_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(keyblob, keys.keyblob, 0);
|
||||
SAVE_KEY_FAMILY_VAR(keyblob_key, keys.keyblob_key, 0);
|
||||
SAVE_KEY_FAMILY(keyblob_key_source, 0);
|
||||
SAVE_KEY_FAMILY(keys.keyblob_mac_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(keyblob_mac_key, keys.keyblob_mac_key, 0);
|
||||
SAVE_KEY(keyblob_mac_key_source);
|
||||
SAVE_KEY_FAMILY(keys.master_kek, 0);
|
||||
SAVE_KEY_FAMILY_VAR(master_kek, keys.master_kek, 0);
|
||||
SAVE_KEY_FAMILY_VAR(master_kek_source, master_kek_sources, KB_FIRMWARE_VERSION_620);
|
||||
SAVE_KEY_FAMILY(keys.master_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(master_key, keys.master_key, 0);
|
||||
SAVE_KEY(master_key_source);
|
||||
SAVE_KEY_FAMILY(keys.package1_key, 0);
|
||||
SAVE_KEY_FAMILY(keys.package2_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(package1_key, keys.package1_key, 0);
|
||||
SAVE_KEY_FAMILY_VAR(package2_key, keys.package2_key, 0);
|
||||
SAVE_KEY(package2_key_source);
|
||||
SAVE_KEY(per_console_key_source);
|
||||
SAVE_KEY(retail_specific_aes_key_source);
|
||||
|
@ -762,7 +780,7 @@ key_output: ;
|
|||
keys.temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
|
||||
SAVE_KEY_VAR(rsa_private_kek_generation_source, keys.temp_key);
|
||||
SAVE_KEY(save_mac_kek_source);
|
||||
SAVE_KEY(keys.save_mac_key);
|
||||
SAVE_KEY_VAR(save_mac_key, keys.save_mac_key);
|
||||
SAVE_KEY(save_mac_key_source);
|
||||
SAVE_KEY(save_mac_sd_card_kek_source);
|
||||
SAVE_KEY(save_mac_sd_card_key_source);
|
||||
|
@ -770,12 +788,12 @@ key_output: ;
|
|||
SAVE_KEY(sd_card_kek_source);
|
||||
SAVE_KEY(sd_card_nca_key_source);
|
||||
SAVE_KEY(sd_card_save_key_source);
|
||||
SAVE_KEY(keys.sd_seed);
|
||||
SAVE_KEY_VAR(sd_seed, keys.sd_seed);
|
||||
SAVE_KEY_VAR(secure_boot_key, keys.sbk);
|
||||
SAVE_KEY(keys.ssl_rsa_kek);
|
||||
SAVE_KEY_VAR(ssl_rsa_kek, keys.ssl_rsa_kek);
|
||||
SAVE_KEY(ssl_rsa_kek_source_x);
|
||||
SAVE_KEY(ssl_rsa_kek_source_y);
|
||||
SAVE_KEY_FAMILY(keys.titlekek, 0);
|
||||
SAVE_KEY_FAMILY_VAR(titlekek, keys.titlekek, 0);
|
||||
SAVE_KEY(titlekek_source);
|
||||
_save_key("tsec_key", keys.tsec_keys, AES_128_KEY_SIZE, text_buffer);
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
|
@ -861,13 +879,15 @@ static void _generate_kek(u32 ks, const void *key_source, void *master_key, cons
|
|||
se_aes_unwrap_key(ks, ks, key_seed);
|
||||
}
|
||||
|
||||
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *master_key) {
|
||||
if (revision < KB_FIRMWARE_VERSION_400)
|
||||
static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *new_device_key, const void *master_key) {
|
||||
if (revision < KB_FIRMWARE_VERSION_400) {
|
||||
memcpy(out_device_key, device_key, AES_128_KEY_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
revision -= KB_FIRMWARE_VERSION_400;
|
||||
u8 temp_key[AES_128_KEY_SIZE] = {0};
|
||||
se_aes_key_set(ks, device_key, AES_128_KEY_SIZE);
|
||||
u32 temp_key[AES_128_KEY_SIZE / 4] = {0};
|
||||
se_aes_key_set(ks, new_device_key, AES_128_KEY_SIZE);
|
||||
se_aes_crypt_ecb(ks, 0, temp_key, AES_128_KEY_SIZE, device_master_key_source_sources[revision], AES_128_KEY_SIZE);
|
||||
se_aes_key_set(ks, master_key, AES_128_KEY_SIZE);
|
||||
se_aes_unwrap_key(ks, ks, device_master_kek_sources[revision]);
|
||||
|
@ -875,7 +895,9 @@ static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const vo
|
|||
}
|
||||
|
||||
static bool _test_key_pair(const void *public_exponent, const void *private_exponent, const void *modulus) {
|
||||
u8 plaintext[RSA_2048_KEY_SIZE] = {0}, ciphertext[RSA_2048_KEY_SIZE] = {0}, work[RSA_2048_KEY_SIZE] = {0};
|
||||
u8 plaintext[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0},
|
||||
ciphertext[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0},
|
||||
work[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0};
|
||||
|
||||
// 0xCAFEBABE
|
||||
plaintext[0xfc] = 0xca; plaintext[0xfd] = 0xfe; plaintext[0xfe] = 0xba; plaintext[0xff] = 0xbe;
|
||||
|
|
|
@ -297,27 +297,30 @@ void _get_key_generations(char *sysnand_label, char *emunand_label)
|
|||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
u8 *bct = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct);
|
||||
sdmmc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
sprintf(sysnand_label + 36, "% 3d", bct[0x130] - 1);
|
||||
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset);
|
||||
sprintf(sysnand_label + 36, "% 3d", pkg1_id->kb);
|
||||
ment_top[0].caption = sysnand_label;
|
||||
if (h_cfg.emummc_force_disable)
|
||||
{
|
||||
free(bct);
|
||||
free(pkg1);
|
||||
return;
|
||||
}
|
||||
|
||||
emummc_storage_init_mmc(&storage, &sdmmc);
|
||||
memset(bct, 0, NX_EMMC_BLOCKSIZE);
|
||||
memset(pkg1, 0, PKG1_MAX_SIZE);
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
emummc_storage_read(&storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct);
|
||||
emummc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
emummc_storage_end(&storage);
|
||||
|
||||
sprintf(emunand_label + 36, "% 3d", bct[0x130] - 1);
|
||||
free(bct);
|
||||
pkg1_id = pkg1_identify(pkg1 + pk1_offset);
|
||||
sprintf(emunand_label + 36, "% 3d", pkg1_id->kb);
|
||||
free(pkg1);
|
||||
ment_top[1].caption = emunand_label;
|
||||
}
|
||||
|
||||
|
@ -393,6 +396,19 @@ void ipl_main()
|
|||
ment_top[1].handler = NULL;
|
||||
}
|
||||
|
||||
// Grey out reboot to RCM option if on Mariko or patched console.
|
||||
if (h_cfg.t210b01 || h_cfg.rcm_patched)
|
||||
{
|
||||
ment_top[6].type = MENT_CAPTION;
|
||||
ment_top[6].color = 0xFF555555;
|
||||
ment_top[6].handler = NULL;
|
||||
}
|
||||
|
||||
if (h_cfg.rcm_patched)
|
||||
{
|
||||
ment_top[5].handler = reboot_full;
|
||||
}
|
||||
|
||||
// Update key generations listed in menu.
|
||||
_get_key_generations((char *)ment_top[0].caption, (char *)ment_top[1].caption);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue