mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-02-18 14:36:20 +00:00
Exosphere: Fix extremely spooky Security Engine bugs, now makes it to the end of package2loader.
This commit is contained in:
parent
ac7ee45493
commit
366cc5e189
7 changed files with 45 additions and 24 deletions
|
@ -33,7 +33,7 @@ static bool g_has_booted_up = false;
|
||||||
void bootup_misc_mmio(void) {
|
void bootup_misc_mmio(void) {
|
||||||
/* Initialize Fuse registers. */
|
/* Initialize Fuse registers. */
|
||||||
fuse_init();
|
fuse_init();
|
||||||
|
|
||||||
/* Verify Security Engine sanity. */
|
/* Verify Security Engine sanity. */
|
||||||
se_set_in_context_save_mode(false);
|
se_set_in_context_save_mode(false);
|
||||||
/* TODO: se_verify_keys_unreadable(); */
|
/* TODO: se_verify_keys_unreadable(); */
|
||||||
|
@ -82,6 +82,8 @@ void bootup_misc_mmio(void) {
|
||||||
MC_SECURITY_CFG1_0 = 0;
|
MC_SECURITY_CFG1_0 = 0;
|
||||||
MC_SECURITY_CFG3_0 = 3;
|
MC_SECURITY_CFG3_0 = 3;
|
||||||
configure_default_carveouts();
|
configure_default_carveouts();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Mark registers secure world only. */
|
/* Mark registers secure world only. */
|
||||||
/* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */
|
/* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */
|
||||||
|
@ -111,14 +113,15 @@ void bootup_misc_mmio(void) {
|
||||||
MAKE_MC_REG(0x230) = 0xFFFFFFFF;
|
MAKE_MC_REG(0x230) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0x234) = 0xFFFFFFFF;
|
MAKE_MC_REG(0x234) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0xB98) = 0xFFFFFFFF;
|
MAKE_MC_REG(0xB98) = 0xFFFFFFFF;
|
||||||
MAKE_MC_REG(0x038) = 0;
|
MAKE_MC_REG(0x038) = 0xE;
|
||||||
MAKE_MC_REG(0x03C) = 0;
|
MAKE_MC_REG(0x03C) = 0;
|
||||||
MAKE_MC_REG(0x0E0) = 0;
|
MAKE_MC_REG(0x9E0) = 0;
|
||||||
MAKE_MC_REG(0x0E4) = 0;
|
MAKE_MC_REG(0x9E4) = 0;
|
||||||
MAKE_MC_REG(0x0E8) = 0;
|
MAKE_MC_REG(0x9E8) = 0;
|
||||||
MAKE_MC_REG(0x0EC) = 0;
|
MAKE_MC_REG(0x9EC) = 0;
|
||||||
MAKE_MC_REG(0x0F0) = 0;
|
MAKE_MC_REG(0x9F0) = 0;
|
||||||
MAKE_MC_REG(0x0F4) = 0;
|
MAKE_MC_REG(0x9F4) = 0;
|
||||||
|
MAKE_MC_REG(0x01C) = 0;
|
||||||
MAKE_MC_REG(0x020) = 0;
|
MAKE_MC_REG(0x020) = 0;
|
||||||
MAKE_MC_REG(0x014) = 0x30000030;
|
MAKE_MC_REG(0x014) = 0x30000030;
|
||||||
MAKE_MC_REG(0x018) = 0x2800003F;
|
MAKE_MC_REG(0x018) = 0x2800003F;
|
||||||
|
@ -129,7 +132,7 @@ void bootup_misc_mmio(void) {
|
||||||
(void)(MAKE_MC_REG(0x014));
|
(void)(MAKE_MC_REG(0x014));
|
||||||
MAKE_MC_REG(0x010) = 1;
|
MAKE_MC_REG(0x010) = 1;
|
||||||
(void)(MAKE_MC_REG(0x014));
|
(void)(MAKE_MC_REG(0x014));
|
||||||
|
|
||||||
/* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */
|
/* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */
|
||||||
uint32_t reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN);
|
uint32_t reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN);
|
||||||
EVP_CPU_RESET_VECTOR_0 = 0;
|
EVP_CPU_RESET_VECTOR_0 = 0;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
/* TODO: What should this be, for release? */
|
/* TODO: What should this be, for release? */
|
||||||
#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_100
|
#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_100
|
||||||
|
#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1
|
||||||
|
|
||||||
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,10 @@ static void setup_se(void) {
|
||||||
|
|
||||||
/* Perform some sanity initialization. */
|
/* Perform some sanity initialization. */
|
||||||
volatile security_engine_t *p_security_engine = get_security_engine();
|
volatile security_engine_t *p_security_engine = get_security_engine();
|
||||||
|
p_security_engine->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */
|
||||||
|
(void)(SECURITY_ENGINE->FLAGS_REG);
|
||||||
|
__dsb_sy();
|
||||||
|
|
||||||
p_security_engine->_0x4 = 0;
|
p_security_engine->_0x4 = 0;
|
||||||
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
||||||
p_security_engine->RSA_KEY_READ_DISABLE_REG = 0;
|
p_security_engine->RSA_KEY_READ_DISABLE_REG = 0;
|
||||||
|
@ -107,6 +111,7 @@ static void setup_se(void) {
|
||||||
|
|
||||||
/* Generate test vector for our keys. */
|
/* Generate test vector for our keys. */
|
||||||
se_generate_stored_vector();
|
se_generate_stored_vector();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_boot_config(void) {
|
static void setup_boot_config(void) {
|
||||||
|
@ -178,7 +183,8 @@ static void verify_header_signature(package2_header_t *header) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is normally only allowed on dev units, but we'll allow it anywhere. */
|
/* This is normally only allowed on dev units, but we'll allow it anywhere. */
|
||||||
if (bootconfig_is_package2_unsigned() == 0 && se_rsa2048_pss_verify(header->signature, 0x100, modulus, 0x100, header->encrypted_header, 0x100) == 0) {
|
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) {
|
||||||
panic(0xF0000001); /* Invalid PK21 signature. */
|
panic(0xF0000001); /* Invalid PK21 signature. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +197,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
||||||
if (metadata->magic != MAGIC_PK21) {
|
if (metadata->magic != MAGIC_PK21) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Package2 size, version number is stored XORed in header CTR. */
|
/* Package2 size, version number is stored XORed in header CTR. */
|
||||||
/* Nintendo, what the fuck? */
|
/* Nintendo, what the fuck? */
|
||||||
|
@ -246,13 +253,14 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_hash = EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG == 0;
|
||||||
/* Validate section hashes. */
|
/* Validate section hashes. */
|
||||||
if (metadata->section_sizes[section]) {
|
if (metadata->section_sizes[section]) {
|
||||||
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset);
|
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + cur_section_offset);
|
||||||
uint8_t calculated_hash[0x20];
|
uint8_t calculated_hash[0x20];
|
||||||
flush_dcache_range((uint8_t *)section_data, (uint8_t *)section_data + metadata->section_sizes[section]);
|
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]);
|
se_calculate_sha256(calculated_hash, section_data, metadata->section_sizes[section]);
|
||||||
if (memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) {
|
if (check_hash && memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cur_section_offset += metadata->section_sizes[section];
|
cur_section_offset += metadata->section_sizes[section];
|
||||||
|
@ -288,6 +296,7 @@ static uint32_t decrypt_and_validate_header(package2_header_t *header) {
|
||||||
memcpy(metadata.ctr, header->metadata.ctr, sizeof(header->metadata.ctr));
|
memcpy(metadata.ctr, header->metadata.ctr, sizeof(header->metadata.ctr));
|
||||||
/* See if this is the correct key. */
|
/* See if this is the correct key. */
|
||||||
if (validate_package2_metadata(&metadata)) {
|
if (validate_package2_metadata(&metadata)) {
|
||||||
|
se_calculate_sha256(metadata.ctr, &header->metadata, sizeof(package2_meta_t));
|
||||||
header->metadata = metadata;
|
header->metadata = metadata;
|
||||||
return mkey_rev;
|
return mkey_rev;
|
||||||
}
|
}
|
||||||
|
@ -446,7 +455,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
flush_dcache_range((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, (uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(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));
|
memcpy(&header, NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, sizeof(header));
|
||||||
flush_dcache_range((uint8_t *)&header, (uint8_t *)&header + sizeof(header));
|
flush_dcache_range((uint8_t *)&header, (uint8_t *)&header + sizeof(header));
|
||||||
|
|
||||||
/* Perform signature checks. */
|
/* Perform signature checks. */
|
||||||
/* Special exosphere patching enable: All-zeroes signature + decrypted header implies unsigned and decrypted package2. */
|
/* 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) {
|
if (header.signature[0] == 0 && memcmp(header.signature, header.signature + 1, sizeof(header.signature) - 1) == 0 && header.metadata.magic == MAGIC_PK21) {
|
||||||
|
@ -457,7 +466,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
|
|
||||||
/* Decrypt header, get key revision required. */
|
/* Decrypt header, get key revision required. */
|
||||||
uint32_t package2_mkey_rev = decrypt_and_validate_header(&header);
|
uint32_t package2_mkey_rev = decrypt_and_validate_header(&header);
|
||||||
|
|
||||||
/* Copy hash, if necessary. */
|
/* Copy hash, if necessary. */
|
||||||
if (bootconfig_is_recovery_boot()) {
|
if (bootconfig_is_recovery_boot()) {
|
||||||
bootconfig_set_package2_hash_for_recovery(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, get_package2_size(&header.metadata));
|
bootconfig_set_package2_hash_for_recovery(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS, get_package2_size(&header.metadata));
|
||||||
|
@ -477,8 +486,6 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
indentity_unmap_dram();
|
indentity_unmap_dram();
|
||||||
|
|
||||||
/* Synchronize with NX BOOTLOADER. */
|
/* Synchronize with NX BOOTLOADER. */
|
||||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED);
|
|
||||||
|
|
||||||
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
|
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||||
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
|
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X);
|
||||||
setup_4x_mmio();
|
setup_4x_mmio();
|
||||||
|
@ -490,5 +497,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||||
set_version_specific_smcs();
|
set_version_specific_smcs();
|
||||||
|
|
||||||
/* Update SCR_EL3 depending on value in Bootconfig. */
|
/* Update SCR_EL3 depending on value in Bootconfig. */
|
||||||
set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3());
|
set_extabt_serror_taken_to_el3(bootconfig_take_extabt_serror_to_el3());
|
||||||
|
strcpy((void *)MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM), (void *)"PK2LOADED");
|
||||||
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ void ll_init(se_ll_t *ll, void *buffer, size_t size) {
|
||||||
ll->addr_info.address = 0;
|
ll->addr_info.address = 0;
|
||||||
ll->addr_info.size = 0;
|
ll->addr_info.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll));
|
flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,17 +452,20 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||||
|
|
||||||
ll_init(&in_ll, (void *)src, src_size);
|
ll_init(&in_ll, (void *)src, src_size);
|
||||||
ll_init(&out_ll, dst, dst_size);
|
ll_init(&out_ll, dst, dst_size);
|
||||||
|
|
||||||
|
__dsb_sy();
|
||||||
|
|
||||||
/* Set the LLs. */
|
/* Set the LLs. */
|
||||||
SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||||
SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||||
|
|
||||||
/* Set registers for operation. */
|
/* Set registers for operation. */
|
||||||
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
||||||
SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG;
|
SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG;
|
||||||
SECURITY_ENGINE->OPERATION_REG = op;
|
SECURITY_ENGINE->OPERATION_REG = op;
|
||||||
|
|
||||||
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||||
|
|
||||||
se_check_for_error();
|
se_check_for_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,14 +662,14 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||||
SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||||
SECURITY_ENGINE->SHA_CONFIG_REG = 1;
|
SECURITY_ENGINE->SHA_CONFIG_REG = 1;
|
||||||
SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (unsigned int)(src_size << 3);
|
SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (unsigned int)(src_size << 3);
|
||||||
|
SECURITY_ENGINE->_0x208 = 0;
|
||||||
SECURITY_ENGINE->_0x20C = 0;
|
SECURITY_ENGINE->_0x20C = 0;
|
||||||
SECURITY_ENGINE->_0x210 = 0;
|
SECURITY_ENGINE->_0x210 = 0;
|
||||||
SECURITY_ENGINE->SHA_MSG_LEFT_REG = 0;
|
SECURITY_ENGINE->SHA_MSG_LEFT_REG = (unsigned int)(src_size << 3);
|
||||||
SECURITY_ENGINE->_0x218 = (unsigned int)(src_size << 3);
|
SECURITY_ENGINE->_0x218 = 0;
|
||||||
SECURITY_ENGINE->_0x21C = 0;
|
SECURITY_ENGINE->_0x21C = 0;
|
||||||
SECURITY_ENGINE->_0x220 = 0;
|
SECURITY_ENGINE->_0x220 = 0;
|
||||||
SECURITY_ENGINE->_0x224 = 0;
|
|
||||||
|
|
||||||
/* Trigger the operation. */
|
/* Trigger the operation. */
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ typedef struct security_engine {
|
||||||
unsigned char _0x74[0x18C];
|
unsigned char _0x74[0x18C];
|
||||||
unsigned int SHA_CONFIG_REG;
|
unsigned int SHA_CONFIG_REG;
|
||||||
unsigned int SHA_MSG_LENGTH_REG;
|
unsigned int SHA_MSG_LENGTH_REG;
|
||||||
|
unsigned int _0x208;
|
||||||
unsigned int _0x20C;
|
unsigned int _0x20C;
|
||||||
unsigned int _0x210;
|
unsigned int _0x210;
|
||||||
unsigned int SHA_MSG_LEFT_REG;
|
unsigned int SHA_MSG_LEFT_REG;
|
||||||
|
@ -110,7 +111,7 @@ typedef struct security_engine {
|
||||||
unsigned char _0x228[0x5C];
|
unsigned char _0x228[0x5C];
|
||||||
unsigned int AES_KEY_READ_DISABLE_REG;
|
unsigned int AES_KEY_READ_DISABLE_REG;
|
||||||
unsigned int AES_KEYSLOT_FLAGS[0x10];
|
unsigned int AES_KEYSLOT_FLAGS[0x10];
|
||||||
unsigned char _0x2C4[0x3C];
|
unsigned char _0x2C8[0x38];
|
||||||
unsigned int _0x300;
|
unsigned int _0x300;
|
||||||
unsigned int CRYPTO_REG;
|
unsigned int CRYPTO_REG;
|
||||||
unsigned int CRYPTO_CTR_REG[4];
|
unsigned int CRYPTO_CTR_REG[4];
|
||||||
|
|
|
@ -201,7 +201,7 @@ __jump_to_main_cold:
|
||||||
bl get_pk2ldr_stack_address
|
bl get_pk2ldr_stack_address
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
|
|
||||||
mov x0, x19
|
mov x0, x20
|
||||||
bl load_package2
|
bl load_package2
|
||||||
|
|
||||||
mov w0, #3 /* use core3 stack temporarily */
|
mov w0, #3 /* use core3 stack temporarily */
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
|
@ -12,10 +13,13 @@ __attribute__ ((noreturn)) void panic(uint32_t code) {
|
||||||
APBDEV_PMC_SCRATCH200_0 = code;
|
APBDEV_PMC_SCRATCH200_0 = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strcpy((void *)MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM), (void *)"PANIC");
|
||||||
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
|
||||||
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */
|
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */
|
||||||
/* For now, just use NX BOOTLOADER's panic. */
|
/* For now, just use NX BOOTLOADER's panic. */
|
||||||
fuse_disable_programming();
|
fuse_disable_programming();
|
||||||
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
||||||
|
while (1) { }
|
||||||
watchdog_reboot();
|
watchdog_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue