2018-09-07 16:00:13 +01:00
/*
2020-01-24 02:10:40 -08:00
* Copyright ( c ) 2018 - 2020 Atmosphère - NX
2018-09-07 16:00:13 +01:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2019-06-18 22:22:40 -07:00
2018-02-22 18:32:47 -05:00
# include <string.h>
2018-02-21 10:57:51 -08:00
# include "utils.h"
2018-02-25 03:34:15 +01:00
# include "memory_map.h"
2018-03-02 11:28:05 -08:00
# include "bootup.h"
2018-02-25 20:00:50 +01:00
# include "cpu_context.h"
2018-02-21 10:57:51 -08:00
# include "package2.h"
# include "configitem.h"
# include "se.h"
2018-02-27 20:28:34 -08:00
# include "interrupt.h"
2018-02-21 10:57:51 -08:00
# include "masterkey.h"
2018-02-27 22:29:47 +01:00
# include "arm.h"
2018-03-01 03:24:45 -08:00
# include "pmc.h"
2018-02-21 10:57:51 -08:00
# include "randomcache.h"
# include "timers.h"
2018-03-03 19:31:22 +01:00
# include "bootconfig.h"
2018-06-01 22:20:04 -06:00
# include "sysctr0.h"
2018-03-25 15:05:08 -06:00
# include "exocfg.h"
# include "smc_api.h"
2018-02-21 10:57:51 -08:00
2018-03-01 19:11:09 +01:00
extern void * __start_cold_addr ;
extern size_t __bin_size ;
2018-09-08 23:51:52 -07:00
static const uint8_t new_device_key_sources [ MASTERKEY_NUM_NEW_DEVICE_KEYS ] [ 0x10 ] = {
2018-11-25 17:11:21 -08:00
{ 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. */
2019-01-30 22:37:26 -08:00
{ 0x8E , 0x09 , 0x1F , 0x7A , 0xBB , 0xCA , 0x6A , 0xFB , 0xB8 , 0x9B , 0xD5 , 0xC1 , 0x25 , 0x9C , 0xA9 , 0x17 } , /* 6.2.0 New Device Key Source. */
{ 0x8F , 0x77 , 0x5A , 0x96 , 0xB0 , 0x94 , 0xFD , 0x8D , 0x28 , 0xE4 , 0x19 , 0xC8 , 0x16 , 0x1C , 0xDB , 0x3D } , /* 7.0.0 New Device Key Source. */
2019-09-12 01:18:58 -07:00
{ 0x67 , 0x62 , 0xD4 , 0x8E , 0x55 , 0xCF , 0xFF , 0x41 , 0x31 , 0x15 , 0x3B , 0x24 , 0x0C , 0x7C , 0x07 , 0xAE } , /* 8.1.0 New Device Key Source. */
{ 0x4A , 0xC3 , 0x4E , 0x14 , 0x8B , 0x96 , 0x4A , 0xD5 , 0xD4 , 0x99 , 0x73 , 0xC4 , 0x45 , 0xAB , 0x8B , 0x49 } , /* 9.0.0 New Device Key Source. */
2019-12-07 13:44:08 -08:00
{ 0x14 , 0xB8 , 0x74 , 0x12 , 0xCB , 0xBD , 0x0B , 0x8F , 0x20 , 0xFB , 0x30 , 0xDA , 0x27 , 0xE4 , 0x58 , 0x94 } , /* 9.1.0 New Device Key Source. */
2018-09-08 23:51:52 -07:00
} ;
static const uint8_t new_device_keygen_sources [ MASTERKEY_NUM_NEW_DEVICE_KEYS ] [ 0x10 ] = {
2018-11-25 17:11:21 -08:00
{ 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. */
2019-01-30 22:37:26 -08:00
{ 0x81 , 0x3C , 0x6C , 0xBF , 0x5D , 0x21 , 0xDE , 0x77 , 0x20 , 0xD9 , 0x6C , 0xE3 , 0x22 , 0x06 , 0xAE , 0xBB } , /* 6.2.0 New Device Keygen Source. */
{ 0x86 , 0x61 , 0xB0 , 0x16 , 0xFA , 0x7A , 0x9A , 0xEA , 0xF6 , 0xF5 , 0xBE , 0x1A , 0x13 , 0x5B , 0x6D , 0x9E } , /* 7.0.0 New Device Keygen Source. */
2019-09-12 01:18:58 -07:00
{ 0xA6 , 0x81 , 0x71 , 0xE7 , 0xB5 , 0x23 , 0x74 , 0xB0 , 0x39 , 0x8C , 0xB7 , 0xFF , 0xA0 , 0x62 , 0x9F , 0x8D } , /* 8.1.0 New Device Keygen Source. */
2019-12-07 13:44:08 -08:00
{ 0x03 , 0xE7 , 0xEB , 0x43 , 0x1B , 0xCF , 0x5F , 0xB5 , 0xED , 0xDC , 0x97 , 0xAE , 0x21 , 0x8D , 0x19 , 0xED } , /* 9.0.0 New Device Keygen Source. */
{ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } , /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
2018-09-08 23:51:52 -07:00
} ;
static const uint8_t new_device_keygen_sources_dev [ MASTERKEY_NUM_NEW_DEVICE_KEYS ] [ 0x10 ] = {
2018-11-25 17:11:21 -08:00
{ 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. */
2019-01-30 22:37:26 -08:00
{ 0x20 , 0xAB , 0xF2 , 0x0F , 0x05 , 0xE3 , 0xDE , 0x2E , 0xA1 , 0xFB , 0x37 , 0x5E , 0x8B , 0x22 , 0x1A , 0x38 } , /* 6.2.0 New Device Keygen Source. */
2019-06-18 22:22:40 -07:00
{ 0x60 , 0xAE , 0x56 , 0x68 , 0x11 , 0xE2 , 0x0C , 0x99 , 0xDE , 0x05 , 0xAE , 0x68 , 0x78 , 0x85 , 0x04 , 0xAE } , /* 7.0.0 New Device Keygen Source. */
2019-09-12 01:18:58 -07:00
{ 0x94 , 0xD6 , 0xA8 , 0xC0 , 0x95 , 0xAF , 0xD0 , 0xA6 , 0x27 , 0x53 , 0x5E , 0xE5 , 0x8E , 0x70 , 0x1F , 0x87 } , /* 8.1.0 New Device Keygen Source. */
2019-12-07 13:44:08 -08:00
{ 0x61 , 0x6A , 0x88 , 0x21 , 0xA3 , 0x52 , 0xB0 , 0x19 , 0x16 , 0x25 , 0xA4 , 0xE3 , 0x4C , 0x54 , 0x02 , 0x0F } , /* 9.0.0 New Device Keygen Source. */
{ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } , /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
2018-09-08 23:51:52 -07:00
} ;
2018-03-25 15:05:08 -06:00
static void derive_new_device_keys ( unsigned int keygen_keyslot ) {
uint8_t work_buffer [ 0x10 ] ;
2018-09-08 23:51:52 -07:00
bool is_retail = configitem_is_retail ( ) ;
2018-03-25 15:05:08 -06:00
for ( unsigned int revision = 0 ; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS ; revision + + ) {
2019-06-18 22:22:40 -07:00
const unsigned int relative_revision = revision + MASTERKEY_REVISION_400_410 ;
2018-03-25 15:05:08 -06:00
se_aes_ecb_decrypt_block ( keygen_keyslot , work_buffer , 0x10 , new_device_key_sources [ revision ] , 0x10 ) ;
2018-09-08 23:51:52 -07:00
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 ) ;
2019-06-18 22:22:40 -07:00
if ( relative_revision > mkey_get_revision ( ) ) {
break ;
} else if ( relative_revision = = mkey_get_revision ( ) ) {
/* On 7.0.0, sept will have derived this key for us already. */
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) < ATMOSPHERE_TARGET_FIRMWARE_7_0_0 ) {
2019-06-18 22:22:40 -07:00
decrypt_data_into_keyslot ( KEYSLOT_SWITCH_DEVICEKEY , KEYSLOT_SWITCH_TEMPKEY , work_buffer , 0x10 ) ;
}
2018-03-25 15:05:08 -06:00
} else {
2019-06-18 22:22:40 -07:00
se_aes_ecb_decrypt_block ( KEYSLOT_SWITCH_TEMPKEY , work_buffer , 0x10 , work_buffer , 0x10 ) ;
set_old_devkey ( relative_revision , work_buffer ) ;
2018-03-25 15:05:08 -06:00
}
}
set_aes_keyslot_flags ( KEYSLOT_SWITCH_DEVICEKEY , 0xFF ) ;
clear_aes_keyslot ( keygen_keyslot ) ;
}
2018-02-21 10:57:51 -08:00
/* Hardware init, sets up the RNG and SESSION keyslots, derives new DEVICE key. */
2018-02-25 03:34:15 +01:00
static void setup_se ( void ) {
2018-02-21 10:57:51 -08:00
uint8_t work_buffer [ 0x10 ] ;
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Sanity check the Security Engine. */
se_verify_flags_cleared ( ) ;
2018-02-28 19:06:41 +01:00
2018-03-03 19:31:22 +01:00
/* Initialize interrupts. */
2018-02-27 19:58:56 -08:00
intr_initialize_gic_nonsecure ( ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Perform some sanity initialization. */
2018-09-15 21:08:58 +01:00
volatile tegra_se_t * se = se_get_regs ( ) ;
2019-12-31 17:59:15 +00:00
se - > SE_SE_SECURITY & = 0xFFFEFFFF ; /* Clear bit 16. */
( void ) ( se - > SE_STATUS ) ;
2018-05-21 04:30:32 -06:00
__dsb_sy ( ) ;
2019-06-18 22:22:40 -07:00
/* NOTE: On 8.1.0+, Nintendo does not make keyslots 0-5 unreadable. */
2019-12-31 17:59:15 +00:00
se - > SE_TZRAM_SECURITY = 0 ;
se - > SE_CRYPTO_SECURITY_PERKEY = 0 ;
se - > SE_RSA_SECURITY_PERKEY = 0 ;
se - > SE_SE_SECURITY & = 0xFFFFFFFB ;
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Currently unknown what each flag does. */
for ( unsigned int i = 0 ; i < KEYSLOT_AES_MAX ; i + + ) {
set_aes_keyslot_flags ( i , 0x15 ) ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
for ( unsigned int i = 4 ; i < KEYSLOT_AES_MAX ; i + + ) {
set_aes_keyslot_flags ( i , 0x40 ) ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
for ( unsigned int i = 0 ; i < KEYSLOT_RSA_MAX ; i + + ) {
set_rsa_keyslot_flags ( i , 0x41 ) ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Detect Master Key revision. */
mkey_detect_revision ( ) ;
2018-05-11 14:07:37 +02:00
2018-03-25 15:05:08 -06:00
/* Derive new device keys. */
2020-05-06 22:29:07 -07:00
{
const uint32_t target_fw = exosphere_get_target_firmware ( ) ;
if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ) {
2018-03-25 15:05:08 -06:00
derive_new_device_keys ( KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY ) ;
2020-05-06 22:29:07 -07:00
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
derive_new_device_keys ( KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY ) ;
} else {
/* No new keys to derive */
}
2018-02-21 10:57:51 -08:00
}
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
se_initialize_rng ( KEYSLOT_SWITCH_DEVICEKEY ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Generate random data, transform with device key to get RNG key. */
se_generate_random ( KEYSLOT_SWITCH_DEVICEKEY , work_buffer , 0x10 ) ;
decrypt_data_into_keyslot ( KEYSLOT_SWITCH_RNGKEY , KEYSLOT_SWITCH_DEVICEKEY , work_buffer , 0x10 ) ;
set_aes_keyslot_flags ( KEYSLOT_SWITCH_RNGKEY , 0xFF ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Repeat for Session key. */
se_generate_random ( KEYSLOT_SWITCH_DEVICEKEY , work_buffer , 0x10 ) ;
decrypt_data_into_keyslot ( KEYSLOT_SWITCH_SESSIONKEY , KEYSLOT_SWITCH_DEVICEKEY , work_buffer , 0x10 ) ;
set_aes_keyslot_flags ( KEYSLOT_SWITCH_SESSIONKEY , 0xFF ) ;
2018-02-25 03:34:15 +01:00
2018-03-02 12:59:12 -08:00
/* Generate test vector for our keys. */
2019-06-18 22:22:40 -07:00
se_generate_stored_vector ( ) ;
2018-02-21 10:57:51 -08:00
}
2018-02-25 03:34:15 +01:00
static void setup_boot_config ( void ) {
2018-02-21 10:57:51 -08:00
/* Load boot config only if dev unit. */
if ( configitem_is_retail ( ) ) {
bootconfig_clear ( ) ;
} else {
2018-09-08 23:51:52 -07:00
void * bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER ;
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_6_0_0 ) {
2018-09-08 23:51:52 -07:00
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 ) ;
2018-02-21 10:57:51 -08:00
}
}
2018-02-25 03:34:15 +01:00
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 ) {
2018-02-21 11:52:39 -08:00
/* Derive package2 key. */
2018-09-08 23:51:52 -07:00
static const uint8_t package2_key_source [ 0x10 ] = { 0xFB , 0x8B , 0x6A , 0x9C , 0x79 , 0x00 , 0xC8 , 0x49 , 0xEF , 0xD2 , 0x4D , 0x85 , 0x4D , 0x30 , 0xA0 , 0xC7 } ;
2018-02-21 11:52:39 -08:00
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 ) ;
decrypt_data_into_keyslot ( KEYSLOT_SWITCH_PACKAGE2KEY , keyslot , package2_key_source , 0x10 ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* Perform Encryption. */
se_aes_ctr_crypt ( KEYSLOT_SWITCH_PACKAGE2KEY , dst , dst_size , src , src_size , ctr , ctr_size ) ;
}
2018-02-25 03:34:15 +01:00
static void verify_header_signature ( package2_header_t * header ) {
2018-02-21 11:52:39 -08:00
const uint8_t * modulus ;
if ( configitem_is_retail ( ) ) {
2018-02-27 20:28:34 -08:00
static const uint8_t package2_modulus_retail [ 0x100 ] = {
2018-02-21 11:52:39 -08:00
0x8D , 0x13 , 0xA7 , 0x77 , 0x6A , 0xE5 , 0xDC , 0xC0 , 0x3B , 0x25 , 0xD0 , 0x58 , 0xE4 , 0x20 , 0x69 , 0x59 ,
0x55 , 0x4B , 0xAB , 0x70 , 0x40 , 0x08 , 0x28 , 0x07 , 0xA8 , 0xA7 , 0xFD , 0x0F , 0x31 , 0x2E , 0x11 , 0xFE ,
0x47 , 0xA0 , 0xF9 , 0x9D , 0xDF , 0x80 , 0xDB , 0x86 , 0x5A , 0x27 , 0x89 , 0xCD , 0x97 , 0x6C , 0x85 , 0xC5 ,
0x6C , 0x39 , 0x7F , 0x41 , 0xF2 , 0xFF , 0x24 , 0x20 , 0xC3 , 0x95 , 0xA6 , 0xF7 , 0x9D , 0x4A , 0x45 , 0x74 ,
0x8B , 0x5D , 0x28 , 0x8A , 0xC6 , 0x99 , 0x35 , 0x68 , 0x85 , 0xA5 , 0x64 , 0x32 , 0x80 , 0x9F , 0xD3 , 0x48 ,
0x39 , 0xA2 , 0x1D , 0x24 , 0x67 , 0x69 , 0xDF , 0x75 , 0xAC , 0x12 , 0xB5 , 0xBD , 0xC3 , 0x29 , 0x90 , 0xBE ,
0x37 , 0xE4 , 0xA0 , 0x80 , 0x9A , 0xBE , 0x36 , 0xBF , 0x1F , 0x2C , 0xAB , 0x2B , 0xAD , 0xF5 , 0x97 , 0x32 ,
0x9A , 0x42 , 0x9D , 0x09 , 0x8B , 0x08 , 0xF0 , 0x63 , 0x47 , 0xA3 , 0xE9 , 0x1B , 0x36 , 0xD8 , 0x2D , 0x8A ,
0xD7 , 0xE1 , 0x54 , 0x11 , 0x95 , 0xE4 , 0x45 , 0x88 , 0x69 , 0x8A , 0x2B , 0x35 , 0xCE , 0xD0 , 0xA5 , 0x0B ,
0xD5 , 0x5D , 0xAC , 0xDB , 0xAF , 0x11 , 0x4D , 0xCA , 0xB8 , 0x1E , 0xE7 , 0x01 , 0x9E , 0xF4 , 0x46 , 0xA3 ,
0x8A , 0x94 , 0x6D , 0x76 , 0xBD , 0x8A , 0xC8 , 0x3B , 0xD2 , 0x31 , 0x58 , 0x0C , 0x79 , 0xA8 , 0x26 , 0xE9 ,
0xD1 , 0x79 , 0x9C , 0xCB , 0xD4 , 0x2B , 0x6A , 0x4F , 0xC6 , 0xCC , 0xCF , 0x90 , 0xA7 , 0xB9 , 0x98 , 0x47 ,
0xFD , 0xFA , 0x4C , 0x6C , 0x6F , 0x81 , 0x87 , 0x3B , 0xCA , 0xB8 , 0x50 , 0xF6 , 0x3E , 0x39 , 0x5D , 0x4D ,
0x97 , 0x3F , 0x0F , 0x35 , 0x39 , 0x53 , 0xFB , 0xFA , 0xCD , 0xAB , 0xA8 , 0x7A , 0x62 , 0x9A , 0x3F , 0xF2 ,
0x09 , 0x27 , 0x96 , 0x3F , 0x07 , 0x9A , 0x91 , 0xF7 , 0x16 , 0xBF , 0xC6 , 0x3A , 0x82 , 0x5A , 0x4B , 0xCF ,
0x49 , 0x50 , 0x95 , 0x8C , 0x55 , 0x80 , 0x7E , 0x39 , 0xB1 , 0x48 , 0x05 , 0x1E , 0x21 , 0xC7 , 0x24 , 0x4F
} ;
modulus = package2_modulus_retail ;
} else {
2018-02-27 20:28:34 -08:00
static const uint8_t package2_modulus_dev [ 0x100 ] = {
2018-02-21 11:52:39 -08:00
0xB3 , 0x65 , 0x54 , 0xFB , 0x0A , 0xB0 , 0x1E , 0x85 , 0xA7 , 0xF6 , 0xCF , 0x91 , 0x8E , 0xBA , 0x96 , 0x99 ,
0x0D , 0x8B , 0x91 , 0x69 , 0x2A , 0xEE , 0x01 , 0x20 , 0x4F , 0x34 , 0x5C , 0x2C , 0x4F , 0x4E , 0x37 , 0xC7 ,
0xF1 , 0x0B , 0xD4 , 0xCD , 0xA1 , 0x7F , 0x93 , 0xF1 , 0x33 , 0x59 , 0xCE , 0xB1 , 0xE9 , 0xDD , 0x26 , 0xE6 ,
0xF3 , 0xBB , 0x77 , 0x87 , 0x46 , 0x7A , 0xD6 , 0x4E , 0x47 , 0x4A , 0xD1 , 0x41 , 0xB7 , 0x79 , 0x4A , 0x38 ,
0x06 , 0x6E , 0xCF , 0x61 , 0x8F , 0xCD , 0xC1 , 0x40 , 0x0B , 0xFA , 0x26 , 0xDC , 0xC0 , 0x34 , 0x51 , 0x83 ,
0xD9 , 0x3B , 0x11 , 0x54 , 0x3B , 0x96 , 0x27 , 0x32 , 0x9A , 0x95 , 0xBE , 0x1E , 0x68 , 0x11 , 0x50 , 0xA0 ,
0x6B , 0x10 , 0xA8 , 0x83 , 0x8B , 0xF5 , 0xFC , 0xBC , 0x90 , 0x84 , 0x7A , 0x5A , 0x5C , 0x43 , 0x52 , 0xE6 ,
0xC8 , 0x26 , 0xE9 , 0xFE , 0x06 , 0xA0 , 0x8B , 0x53 , 0x0F , 0xAF , 0x1E , 0xC4 , 0x1C , 0x0B , 0xCF , 0x50 ,
0x1A , 0xA4 , 0xF3 , 0x5C , 0xFB , 0xF0 , 0x97 , 0xE4 , 0xDE , 0x32 , 0x0A , 0x9F , 0xE3 , 0x5A , 0xAA , 0xB7 ,
0x44 , 0x7F , 0x5C , 0x33 , 0x60 , 0xB9 , 0x0F , 0x22 , 0x2D , 0x33 , 0x2A , 0xE9 , 0x69 , 0x79 , 0x31 , 0x42 ,
0x8F , 0xE4 , 0x3A , 0x13 , 0x8B , 0xE7 , 0x26 , 0xBD , 0x08 , 0x87 , 0x6C , 0xA6 , 0xF2 , 0x73 , 0xF6 , 0x8E ,
0xA7 , 0xF2 , 0xFE , 0xFB , 0x6C , 0x28 , 0x66 , 0x0D , 0xBD , 0xD7 , 0xEB , 0x42 , 0xA8 , 0x78 , 0xE6 , 0xB8 ,
0x6B , 0xAE , 0xC7 , 0xA9 , 0xE2 , 0x40 , 0x6E , 0x89 , 0x20 , 0x82 , 0x25 , 0x8E , 0x3C , 0x6A , 0x60 , 0xD7 ,
0xF3 , 0x56 , 0x8E , 0xEC , 0x8D , 0x51 , 0x8A , 0x63 , 0x3C , 0x04 , 0x78 , 0x23 , 0x0E , 0x90 , 0x0C , 0xB4 ,
0xE7 , 0x86 , 0x3B , 0x4F , 0x8E , 0x13 , 0x09 , 0x47 , 0x32 , 0x0E , 0x04 , 0xB8 , 0x4D , 0x5B , 0xB0 , 0x46 ,
0x71 , 0xB0 , 0x5C , 0xF4 , 0xAD , 0x63 , 0x4F , 0xC5 , 0xE2 , 0xAC , 0x1E , 0xC4 , 0x33 , 0x96 , 0x09 , 0x7B
} ;
modulus = package2_modulus_dev ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* This is normally only allowed on dev units, but we'll allow it anywhere. */
2018-05-21 04:30:32 -06:00
bool is_unsigned = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG | | bootconfig_is_package2_unsigned ( ) ;
if ( ! is_unsigned & & se_rsa2048_pss_verify ( header - > signature , 0x100 , modulus , 0x100 , header - > encrypted_header , 0x100 ) = = 0 ) {
2018-03-01 03:24:45 -08:00
panic ( 0xF0000001 ) ; /* Invalid PK21 signature. */
2018-02-21 11:52:39 -08:00
}
}
2018-03-25 15:05:08 -06:00
static uint32_t get_package2_size ( package2_meta_t * metadata ) {
return metadata - > ctr_dwords [ 0 ] ^ metadata - > ctr_dwords [ 2 ] ^ metadata - > ctr_dwords [ 3 ] ;
}
2018-02-25 03:34:15 +01:00
static bool validate_package2_metadata ( package2_meta_t * metadata ) {
2018-02-21 11:52:39 -08:00
if ( metadata - > magic ! = MAGIC_PK21 ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 11:52:39 -08:00
}
2019-06-18 22:22:40 -07:00
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Package2 size, version number is stored XORed in header CTR. */
/* Nintendo, what the fuck? */
uint32_t package_size = metadata - > ctr_dwords [ 0 ] ^ metadata - > ctr_dwords [ 2 ] ^ metadata - > ctr_dwords [ 3 ] ;
uint8_t header_version = ( uint8_t ) ( ( metadata - > ctr_dwords [ 1 ] ^ ( metadata - > ctr_dwords [ 1 ] > > 16 ) ^ ( metadata - > ctr_dwords [ 1 ] > > 24 ) ) & 0xFF ) ;
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Ensure package isn't too big or too small. */
2018-05-17 16:14:20 +02:00
if ( package_size < = sizeof ( package2_header_t ) | | package_size > PACKAGE2_SIZE_MAX ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Validate that we're working with a header we know how to handle. */
if ( header_version > MASTERKEY_REVISION_MAX ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Require aligned entrypoint. */
if ( metadata - > entrypoint & 3 ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Validate section size sanity. */
if ( metadata - > section_sizes [ 0 ] + metadata - > section_sizes [ 1 ] + metadata - > section_sizes [ 2 ] + sizeof ( package2_header_t ) ! = package_size ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
bool entrypoint_found = false ;
2018-02-21 13:38:55 -08:00
/* Header has space for 4 sections, but only 3 are validated/potentially loaded on hardware. */
2018-03-01 03:24:45 -08:00
size_t cur_section_offset = 0 ;
2018-02-21 13:38:55 -08:00
for ( unsigned int section = 0 ; section < PACKAGE2_SECTION_MAX ; section + + ) {
/* Validate section size alignment. */
if ( metadata - > section_sizes [ section ] & 3 ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Validate section does not overflow. */
if ( check_32bit_additive_overflow ( metadata - > section_offsets [ section ] , metadata - > section_sizes [ section ] ) ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Check for entrypoint presence. */
uint32_t section_end = metadata - > section_offsets [ section ] + metadata - > section_sizes [ section ] ;
if ( metadata - > section_offsets [ section ] < = metadata - > entrypoint & & metadata - > entrypoint < section_end ) {
2018-02-22 22:58:39 -05:00
entrypoint_found = true ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Ensure no overlap with later sections. */
2019-04-20 03:41:03 -07:00
if ( metadata - > section_sizes [ section ] ! = 0 ) {
for ( unsigned int later_section = section + 1 ; later_section < PACKAGE2_SECTION_MAX ; later_section + + ) {
if ( metadata - > section_sizes [ later_section ] = = 0 ) {
continue ;
}
uint32_t later_section_end = metadata - > section_offsets [ later_section ] + metadata - > section_sizes [ later_section ] ;
if ( overlaps ( metadata - > section_offsets [ section ] , section_end , metadata - > section_offsets [ later_section ] , later_section_end ) ) {
return false ;
}
2018-02-21 13:38:55 -08:00
}
}
2018-02-22 22:58:39 -05:00
2018-05-21 04:30:32 -06:00
bool check_hash = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG = = 0 ;
2018-02-21 13:38:55 -08:00
/* Validate section hashes. */
2018-03-01 03:24:45 -08:00
if ( metadata - > section_sizes [ section ] ) {
void * section_data = ( void * ) ( ( uint8_t * ) NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof ( package2_header_t ) + cur_section_offset ) ;
uint8_t calculated_hash [ 0x20 ] ;
flush_dcache_range ( ( uint8_t * ) section_data , ( uint8_t * ) section_data + metadata - > section_sizes [ section ] ) ;
se_calculate_sha256 ( calculated_hash , section_data , metadata - > section_sizes [ section ] ) ;
2018-05-21 04:30:32 -06:00
if ( check_hash & & memcmp ( calculated_hash , metadata - > section_hashes [ section ] , sizeof ( metadata - > section_hashes [ section ] ) ) ! = 0 ) {
2018-03-01 03:24:45 -08:00
return false ;
}
cur_section_offset + = metadata - > section_sizes [ section ] ;
2018-02-21 13:38:55 -08:00
}
2018-03-01 03:24:45 -08:00
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Ensure that entrypoint is present in one of our sections. */
if ( ! entrypoint_found ) {
2018-02-22 22:58:39 -05:00
return false ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-02-21 13:38:55 -08:00
/* Perform version checks. */
/* We will be compatible with all package2s released before current, but not newer ones. */
2020-04-13 23:30:54 -07:00
if ( metadata - > version_max > = PACKAGE2_MINVER_THEORETICAL & & metadata - > version_min < PACKAGE2_MAXVER_1000_CURRENT ) {
2018-03-01 03:24:45 -08:00
return true ;
2018-02-21 13:38:55 -08:00
}
2018-02-22 22:58:39 -05:00
2018-03-01 03:24:45 -08:00
return false ;
2018-02-21 11:52:39 -08:00
}
/* Decrypts package2 header, and returns the master key revision required. */
2018-02-25 03:34:15 +01:00
static uint32_t decrypt_and_validate_header ( package2_header_t * header ) {
2018-02-21 11:52:39 -08:00
package2_meta_t metadata ;
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
if ( bootconfig_is_package2_plaintext ( ) = = 0 ) {
uint32_t mkey_rev ;
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* Try to decrypt for all possible master keys. */
2018-03-01 03:24:45 -08:00
for ( mkey_rev = 0 ; mkey_rev < = mkey_get_revision ( ) ; mkey_rev + + ) {
2018-02-21 11:52:39 -08:00
package2_crypt_ctr ( mkey_rev , & metadata , sizeof ( package2_meta_t ) , & header - > metadata , sizeof ( package2_meta_t ) , header - > metadata . ctr , sizeof ( header - > metadata . ctr ) ) ;
/* Copy the ctr (which stores information) into the decrypted metadata. */
memcpy ( metadata . ctr , header - > metadata . ctr , sizeof ( header - > metadata . ctr ) ) ;
/* See if this is the correct key. */
if ( validate_package2_metadata ( & metadata ) ) {
2018-02-22 23:31:13 -05:00
header - > metadata = metadata ;
2018-03-01 03:28:34 -08:00
return mkey_rev ;
2018-02-21 11:52:39 -08:00
}
}
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* Ensure we successfully decrypted the header. */
2019-04-20 03:41:03 -07:00
if ( mkey_rev > mkey_get_revision ( ) ) {
2018-03-01 03:24:45 -08:00
panic ( 0xFAF00003 ) ;
}
2018-04-11 21:56:30 -06:00
} else if ( ! validate_package2_metadata ( & header - > metadata ) ) {
panic ( 0xFAF0003 ) ;
2018-02-21 11:52:39 -08:00
}
return 0 ;
}
2018-02-25 03:34:15 +01:00
static void load_package2_sections ( package2_meta_t * metadata , uint32_t master_key_rev ) {
2018-02-21 13:38:55 -08:00
/* By default, copy data directly from where NX_BOOTLOADER puts it. */
void * load_buf = NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ;
2018-02-25 03:34:15 +01:00
2018-02-21 13:38:55 -08:00
/* Check whether any of our sections overlap this region. If they do, we must relocate and copy from elsewhere. */
2018-02-22 22:58:39 -05:00
bool needs_relocation = false ;
2018-02-21 13:38:55 -08:00
for ( unsigned int section = 0 ; section < PACKAGE2_SECTION_MAX ; section + + ) {
uint64_t section_start = DRAM_BASE_PHYSICAL + ( uint64_t ) metadata - > section_offsets [ section ] ;
uint64_t section_end = section_start + ( uint64_t ) metadata - > section_sizes [ section ] ;
if ( overlaps ( section_start , section_end , ( uint64_t ) ( NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ) , ( uint64_t ) ( NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ) + PACKAGE2_SIZE_MAX ) ) {
2018-02-22 22:58:39 -05:00
needs_relocation = true ;
2018-02-21 13:38:55 -08:00
}
}
if ( needs_relocation ) {
2018-02-21 13:48:36 -08:00
/* This code should *always* succeed in finding a carveout within seven loops, */
2018-02-21 13:38:55 -08:00
/* due to the section size limit, and section number limit. */
2018-02-21 13:48:36 -08:00
/* However, Nintendo tries panics after 8 loops if a safe section is not found. */
/* This should never be the case, mathematically. */
2018-02-21 13:38:55 -08:00
/* We will replicate this behavior. */
2018-02-22 22:58:39 -05:00
bool found_safe_carveout = false ;
2018-02-21 13:38:55 -08:00
uint64_t potential_base_start = DRAM_BASE_PHYSICAL ;
uint64_t potential_base_end = potential_base_start + PACKAGE2_SIZE_MAX ;
for ( unsigned int i = 0 ; i < 8 ; i + + ) {
int is_safe = 1 ;
for ( unsigned int section = 0 ; section < PACKAGE2_SECTION_MAX ; section + + ) {
uint64_t section_start = DRAM_BASE_PHYSICAL + ( uint64_t ) metadata - > section_offsets [ section ] ;
uint64_t section_end = section_start + ( uint64_t ) metadata - > section_sizes [ section ] ;
if ( overlaps ( section_start , section_end , potential_base_start , potential_base_end ) ) {
is_safe = 0 ;
}
}
found_safe_carveout | = is_safe ;
if ( found_safe_carveout ) {
break ;
}
potential_base_start + = PACKAGE2_SIZE_MAX ;
potential_base_end + = PACKAGE2_SIZE_MAX ;
}
if ( ! found_safe_carveout ) {
2018-02-24 06:20:45 -08:00
generic_panic ( ) ;
2018-02-21 13:38:55 -08:00
}
/* Relocate to new carveout. */
memcpy ( ( void * ) potential_base_start , load_buf , PACKAGE2_SIZE_MAX ) ;
memset ( load_buf , 0 , PACKAGE2_SIZE_MAX ) ;
load_buf = ( void * ) potential_base_start ;
}
2018-05-11 14:07:37 +02:00
2018-03-01 03:24:45 -08:00
size_t cur_section_offset = 0 ;
2018-02-21 13:38:55 -08:00
/* Copy each section to its appropriate location, decrypting if necessary. */
2018-02-26 22:09:35 +01:00
for ( unsigned int section = 0 ; section < PACKAGE2_SECTION_MAX ; section + + ) {
2018-02-21 13:38:55 -08:00
if ( metadata - > section_sizes [ section ] = = 0 ) {
continue ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 13:38:55 -08:00
void * dst_start = ( void * ) ( DRAM_BASE_PHYSICAL + ( uint64_t ) metadata - > section_offsets [ section ] ) ;
2018-03-01 03:24:45 -08:00
void * src_start = load_buf + sizeof ( package2_header_t ) + cur_section_offset ;
2018-02-21 13:38:55 -08:00
size_t size = ( size_t ) metadata - > section_sizes [ section ] ;
2018-02-26 22:09:35 +01:00
2018-03-08 11:17:46 +01:00
if ( bootconfig_is_package2_plaintext ( ) & & size ! = 0 ) {
2018-02-21 13:38:55 -08:00
memcpy ( dst_start , src_start , size ) ;
2018-03-08 11:17:46 +01:00
} else if ( size ! = 0 ) {
2018-02-22 15:19:29 -08:00
package2_crypt_ctr ( master_key_rev , dst_start , size , src_start , size , metadata - > section_ctrs [ section ] , 0x10 ) ;
2018-02-21 13:38:55 -08:00
}
2018-03-01 03:24:45 -08:00
cur_section_offset + = size ;
2018-02-21 13:38:55 -08:00
}
2018-02-25 03:34:15 +01:00
2018-02-21 13:38:55 -08:00
/* Clear the encrypted package2 from memory. */
memset ( load_buf , 0 , PACKAGE2_SIZE_MAX ) ;
}
2018-08-16 18:45:38 -07:00
static void copy_warmboot_bin_to_dram ( ) {
2018-09-08 23:51:52 -07:00
uint8_t * warmboot_src ;
2020-05-06 22:29:07 -07:00
{
const uint32_t target_fw = exosphere_get_target_firmware ( ) ;
if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_7_0_0 ) {
2019-01-30 22:37:26 -08:00
warmboot_src = ( uint8_t * ) 0x4003E000 ;
2020-05-18 08:57:20 -07:00
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_6_0_0 ) {
2020-05-06 22:29:07 -07:00
warmboot_src = ( uint8_t * ) 0x4003D800 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
warmboot_src = ( uint8_t * ) 0x4003B000 ;
} else {
return ;
}
2018-09-08 23:51:52 -07:00
}
2020-05-06 22:29:07 -07:00
2018-08-16 18:45:38 -07:00
uint8_t * warmboot_dst = ( uint8_t * ) 0x8000D000 ;
const size_t warmboot_size = 0x2000 ;
2019-06-18 22:22:40 -07:00
2018-08-16 18:45:38 -07:00
/* Flush cache, to ensure warmboot is where we need it to be. */
flush_dcache_range ( warmboot_src , warmboot_src + warmboot_size ) ;
__dsb_sy ( ) ;
2019-06-18 22:22:40 -07:00
2018-08-16 18:45:38 -07:00
/* Copy warmboot. */
for ( size_t i = 0 ; i < warmboot_size ; i + = sizeof ( uint32_t ) ) {
write32le ( warmboot_dst , i , read32le ( warmboot_src , i ) ) ;
}
2019-06-18 22:22:40 -07:00
2018-08-16 18:45:38 -07:00
/* Flush cache, to ensure warmboot is where we need it to be. */
flush_dcache_range ( warmboot_dst , warmboot_dst + warmboot_size ) ;
__dsb_sy ( ) ;
}
2018-03-01 19:11:09 +01:00
static void sync_with_nx_bootloader ( int state ) {
2019-01-30 23:13:27 -08:00
while ( MAILBOX_NX_BOOTLOADER_SETUP_STATE ( exosphere_get_target_firmware ( ) ) < state ) {
2018-03-01 21:15:19 -08:00
wait ( 100 ) ;
2018-03-01 19:11:09 +01:00
}
}
2018-08-16 18:45:38 -07:00
static void identity_unmap_dram ( void ) {
2018-03-02 07:33:47 +01:00
uintptr_t * mmu_l1_tbl = ( uintptr_t * ) ( TZRAM_GET_SEGMENT_ADDRESS ( TZRAM_SEGEMENT_ID_SECMON_EVT ) + 0x800 - 64 ) ;
mmu_unmap_range ( 1 , mmu_l1_tbl , IDENTITY_GET_MAPPING_ADDRESS ( IDENTITY_MAPPING_DRAM ) , IDENTITY_GET_MAPPING_SIZE ( IDENTITY_MAPPING_DRAM ) ) ;
tlb_invalidate_all_inner_shareable ( ) ;
}
2018-02-25 03:34:15 +01:00
uintptr_t get_pk2ldr_stack_address ( void ) {
2018-02-26 22:09:35 +01:00
return TZRAM_GET_SEGMENT_ADDRESS ( TZRAM_SEGMENT_ID_PK2LDR ) + 0x2000 ;
2018-02-25 03:34:15 +01:00
}
/* This function is called during coldboot init, and validates a package2. */
2018-02-21 10:57:51 -08:00
/* This package2 is read into memory by a concurrent BPMP bootloader. */
2018-03-02 02:19:35 +01:00
void load_package2 ( coldboot_crt0_reloc_list_t * reloc_list ) {
2018-03-25 15:05:08 -06:00
/* Load Exosphere-specific config. */
exosphere_load_config ( ) ;
2018-11-30 03:10:27 -08:00
configitem_set_debugmode_override ( exosphere_should_override_debugmode_user ( ) ! = 0 , exosphere_should_override_debugmode_priv ( ) ! = 0 ) ;
2019-05-10 03:50:25 -07:00
if ( exosphere_should_disable_usermode_exception_handlers ( ) ! = 0 ) {
configitem_disable_usermode_exception_handlers ( ) ;
}
2019-12-07 15:35:34 -08:00
if ( exosphere_should_enable_usermode_pmu_access ( ) ) {
configitem_enable_usermode_pmu_access ( ) ;
}
2018-05-11 14:07:37 +02:00
2018-02-21 10:57:51 -08:00
/* Setup the Security Engine. */
setup_se ( ) ;
2019-06-18 22:22:40 -07:00
2018-06-01 22:20:04 -06:00
/* Perform initial PMC register writes, if relevant. */
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
2019-06-18 22:22:40 -07:00
MAKE_REG32 ( PMC_BASE + 0x054 ) = 0x8000D000 ;
MAKE_REG32 ( PMC_BASE + 0x0A0 ) & = 0xFFF3FFFF ;
MAKE_REG32 ( PMC_BASE + 0x818 ) & = 0xFFFFFFFE ;
2018-09-08 23:51:52 -07:00
MAKE_REG32 ( PMC_BASE + 0x334 ) | = 0x10 ;
2020-05-06 22:29:07 -07:00
const uint32_t target_fw = exosphere_get_target_firmware ( ) ;
if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_10_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x105 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_9_1_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x18C ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_9_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x16B ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_8_1_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x14A ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_7_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x129 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_6_2_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x0A8 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_6_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x087 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_5_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x006 ;
} else if ( target_fw > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
MAKE_REG32 ( PMC_BASE + 0x360 ) = 0x105 ;
2018-09-08 23:51:52 -07:00
}
2018-06-01 22:20:04 -06:00
}
2018-02-26 22:09:35 +01:00
2018-03-01 21:15:19 -08:00
wait ( 1000 ) ;
2018-03-02 11:28:05 -08:00
bootup_misc_mmio ( ) ;
2018-02-26 22:09:35 +01:00
2018-03-02 14:16:54 -08:00
setup_current_core_state ( ) ;
2018-03-01 19:11:09 +01:00
2018-03-08 01:48:57 -08:00
/* Save boot reason to global. */
2019-01-30 23:13:27 -08:00
bootconfig_load_boot_reason ( ( volatile boot_reason_t * ) ( MAILBOX_NX_BOOTLOADER_BOOT_REASON ( exosphere_get_target_firmware ( ) ) ) ) ;
2018-05-11 14:07:37 +02:00
2018-02-21 10:57:51 -08:00
/* Initialize cache'd random bytes for kernel. */
randomcache_init ( ) ;
2018-05-11 14:07:37 +02:00
2018-03-01 19:11:09 +01:00
/* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */
2018-09-15 21:08:58 +01:00
/* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */
2019-06-18 22:22:40 -07:00
2018-02-21 10:57:51 -08:00
/* Let NX Bootloader know that we're running. */
2019-01-30 23:13:27 -08:00
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE ( exosphere_get_target_firmware ( ) ) = 1 ;
2018-02-25 03:34:15 +01:00
2018-03-01 03:24:45 -08:00
/* Wait for 1 second, to allow time for NX_BOOTLOADER to draw to the screen. This is useful for debugging. */
2018-06-01 00:46:05 -06:00
/* wait(1000000); */
2018-03-01 03:24:45 -08:00
2018-03-01 19:11:09 +01:00
/* Synchronize with NX BOOTLOADER. */
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG ) ;
2018-03-01 03:24:45 -08:00
2018-02-21 10:57:51 -08:00
/* Load Boot Config into global. */
setup_boot_config ( ) ;
2019-06-18 22:22:40 -07:00
2018-06-01 22:20:04 -06:00
/* Set sysctr0 registers based on bootconfig. */
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
2018-06-01 22:20:04 -06:00
uint64_t sysctr0_val = bootconfig_get_value_for_sysctr0 ( ) ;
MAKE_SYSCTR0_REG ( 0x8 ) = ( uint32_t ) ( ( sysctr0_val > > 0 ) & 0xFFFFFFFFULL ) ;
MAKE_SYSCTR0_REG ( 0xC ) = ( uint32_t ) ( ( sysctr0_val > > 32 ) & 0xFFFFFFFFULL ) ;
MAKE_SYSCTR0_REG ( 0x0 ) = 3 ;
}
2018-02-25 03:34:15 +01:00
2018-02-21 10:57:51 -08:00
/* Synchronize with NX BOOTLOADER. */
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
2018-03-02 11:28:05 -08:00
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X ) ;
2018-08-16 18:45:38 -07:00
copy_warmboot_bin_to_dram ( ) ;
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_6_0_0 ) {
2018-09-08 23:51:52 -07:00
setup_dram_magic_numbers ( ) ;
}
2018-03-02 11:28:05 -08:00
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X ) ;
} else {
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_LOADED_PACKAGE2 ) ;
}
2018-03-01 19:11:09 +01:00
2018-03-03 19:31:22 +01:00
/* Make PMC (2.x+), MC (4.x+) registers secure-only */
secure_additional_devices ( ) ;
2019-06-18 22:22:40 -07:00
2018-03-02 07:33:47 +01:00
/* Remove the identity mapping for iRAM-C+D & TZRAM */
2018-05-11 14:07:37 +02:00
/* For our crt0 to work, this doesn't actually unmap TZRAM */
2018-03-02 07:33:47 +01:00
identity_unmap_iram_cd_tzram ( ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* Load header from NX_BOOTLOADER-initialized DRAM. */
package2_header_t header ;
flush_dcache_range ( ( uint8_t * ) NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS , ( uint8_t * ) NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof ( header ) ) ;
memcpy ( & header , NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS , sizeof ( header ) ) ;
flush_dcache_range ( ( uint8_t * ) & header , ( uint8_t * ) & header + sizeof ( header ) ) ;
2019-06-18 22:22:40 -07:00
2018-02-21 11:52:39 -08:00
/* Perform signature checks. */
2018-04-11 21:56:30 -06:00
/* Special exosphere patching enable: All-zeroes signature + decrypted header implies unsigned and decrypted package2. */
if ( header . signature [ 0 ] = = 0 & & memcmp ( header . signature , header . signature + 1 , sizeof ( header . signature ) - 1 ) = = 0 & & header . metadata . magic = = MAGIC_PK21 ) {
bootconfig_set_package2_plaintext_and_unsigned ( ) ;
}
2018-05-11 14:07:37 +02:00
2018-02-21 11:52:39 -08:00
verify_header_signature ( & header ) ;
2018-02-25 03:34:15 +01:00
2018-02-21 11:52:39 -08:00
/* Decrypt header, get key revision required. */
uint32_t package2_mkey_rev = decrypt_and_validate_header ( & header ) ;
2019-06-18 22:22:40 -07:00
2018-03-25 15:05:08 -06:00
/* Copy hash, if necessary. */
if ( bootconfig_is_recovery_boot ( ) ) {
bootconfig_set_package2_hash_for_recovery ( NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS , get_package2_size ( & header . metadata ) ) ;
}
2018-02-21 13:38:55 -08:00
/* Load Package2 Sections. */
2018-02-23 02:11:15 -05:00
load_package2_sections ( & header . metadata , package2_mkey_rev ) ;
2019-06-18 22:22:40 -07:00
2018-02-21 13:38:55 -08:00
/* Clean up cache. */
flush_dcache_all ( ) ;
2018-03-01 19:11:09 +01:00
invalidate_icache_all ( ) ; /* non-broadcasting */
2018-02-25 03:34:15 +01:00
2018-02-21 13:38:55 -08:00
/* Set CORE0 entrypoint for Package2. */
2018-02-26 17:11:49 +00:00
set_core_entrypoint_and_argument ( 0 , DRAM_BASE_PHYSICAL + header . metadata . entrypoint , 0 ) ;
2018-02-25 03:34:15 +01:00
2018-03-02 07:33:47 +01:00
/* Remove the DRAM identity mapping. */
2018-08-16 18:45:38 -07:00
if ( 0 ) {
identity_unmap_dram ( ) ;
2019-06-18 22:22:40 -07:00
}
2018-03-01 21:15:19 -08:00
2018-02-21 11:52:39 -08:00
/* Synchronize with NX BOOTLOADER. */
2020-05-06 22:29:07 -07:00
if ( exosphere_get_target_firmware ( ) > = ATMOSPHERE_TARGET_FIRMWARE_4_0_0 ) {
2018-03-02 11:28:05 -08:00
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_FINISHED_4X ) ;
2018-03-25 15:05:08 -06:00
setup_4x_mmio ( ) ;
2018-03-02 11:28:05 -08:00
} else {
sync_with_nx_bootloader ( NX_BOOTLOADER_STATE_FINISHED ) ;
}
2018-05-11 14:07:37 +02:00
2018-03-25 15:05:08 -06:00
/* Prepare the SMC API with version-dependent SMCs. */
set_version_specific_smcs ( ) ;
2018-03-02 11:28:05 -08:00
2018-03-02 15:04:16 -08:00
/* Update SCR_EL3 depending on value in Bootconfig. */
2018-05-21 20:14:06 -06:00
set_extabt_serror_taken_to_el3 ( bootconfig_take_extabt_serror_to_el3 ( ) ) ;
2018-02-25 03:34:15 +01:00
}