Compare commits

...

15 Commits
0.8.1 ... 0.8.2

Author SHA1 Message Date
Michael Scire
84c776fa6b Bump version to 0.8.2 2018-12-07 17:30:07 -08:00
Michael Scire
a21b5d453a ams: turn on debugmode by default. 2018-12-07 17:23:20 -08:00
Michael Scire
0ef3368893 fusee: retry tsec key generation on failure. 2018-12-07 14:54:06 -08:00
Michael Scire
4827fd71b4 fusee: Fix race condition involving volatile reads 2018-12-07 14:27:46 -08:00
hexkyz
00aa283a54 fusee: Fix KFUSE clock. 2018-12-07 22:18:01 +00:00
hexkyz
ef373d954f fusee: Fix KFUSE clock. 2018-12-07 22:17:06 +00:00
Michael Scire
d452d6f89d exo: Correct seal key source 2018-12-06 09:29:09 -08:00
Michael Scire
a51d355707 exo: there's no reason to not always init uart to be safe, actually 2018-12-04 16:01:26 -08:00
Michael Scire
a79f4cf6f6 exosphere: fix sleep mode when debugmode is enabled 2018-12-04 15:59:30 -08:00
Michael Scire
903789cf6e fusee: fix error printing pre-SD card init (closes #289). 2018-12-04 04:01:22 -08:00
Michael Scire
49ba3a86e2 fusee: move BCT.ini/secondary into atmosphere/ 2018-12-04 03:55:01 -08:00
Michael Scire
021d84ff04 fusee: remove duplicate hook 2018-12-01 21:39:29 -08:00
Michael Scire
8ecf68cb65 fusee: Add support for 1.0.0-7. 2018-12-01 21:38:28 -08:00
Michael Scire
bbed78149c fs.mitm: Hog less CPU time if SD card not inserted 2018-12-01 19:07:25 -08:00
Michael Scire
3fa973f430 fatal/set_mitm: Support 1.0.0 kernel. 2018-12-01 19:07:05 -08:00
18 changed files with 146 additions and 61 deletions

View File

@@ -42,8 +42,8 @@ dist: all
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin
cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini
cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini
cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp

View File

@@ -1,11 +1,12 @@
BCT0
[stage1]
stage2_path = fusee-secondary.bin
stage2_path = atmosphere/fusee-secondary.bin
stage2_addr = 0xF0000000
stage2_entrypoint = 0xF0000000
[exosphere]
debugmode = 0
; Note: Disabling debugmode will cause parts of ams.tma to not work, in the future.
debugmode = 1
debugmode_user = 0
[stratosphere]

View File

@@ -19,6 +19,6 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
#define ATMOSPHERE_RELEASE_VERSION_MINOR 8
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#define ATMOSPHERE_RELEASE_VERSION_MICRO 2
#endif

View File

@@ -1,4 +1,13 @@
# Changelog
## 0.8.2
+ A number of bugs were fixed causing users to sometimes see `Key Derivation Failed!`.
+ KFUSE clock enable timings have been adjusted to allow time to stabilize before TSEC is granted access.
+ A race condition was fixed that could cause wrong key data to be used on 6.2.0
+ The TSEC firmware is now retried on failure, fixing a failure affecting ~1/50 boots on 6.2.0.
+ A bug was fixed causing some modules to not work on firmware 1.0.0.
+ A bug was fixed causing sleep mode to not work with debugmode enabled.
+ As a result, debugmode is now enabled in the default BCT.ini.
+ General system stability improvements to enhance the user's experience.
## 0.8.1
+ A bug was fixed causing users to see `Failed to enable SMMU!` if fusee had previously rebooted.
+ This message will still occur sporadically if fusee is not launched from coldboot, but it can never happen twice in a row.

View File

@@ -31,6 +31,7 @@
#include "configitem.h"
#include "timers.h"
#include "misc.h"
#include "uart.h"
#include "bpmp.h"
#include "sysreg.h"
#include "interrupt.h"
@@ -213,6 +214,11 @@ void bootup_misc_mmio(void) {
}
if (!g_has_booted_up) {
/* N doesn't do this, but we should for compatibility. */
uart_select(UART_A);
clkrst_reboot(CARDEVICE_UARTA);
uart_init(UART_A, 115200);
intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed);
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler);

View File

@@ -72,6 +72,15 @@ bool configitem_should_profile_battery(void) {
return g_battery_profile;
}
bool configitem_is_debugmode_priv(void) {
uint64_t debugmode = 0;
if (configitem_get(true, CONFIGITEM_ISDEBUGMODE, &debugmode) != 0) {
generic_panic();
}
return debugmode != 0;
}
uint64_t configitem_get_hardware_type(void) {
uint64_t hardware_type;
if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) {

View File

@@ -50,6 +50,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue);
bool configitem_is_recovery_boot(void);
bool configitem_is_retail(void);
bool configitem_should_profile_battery(void);
bool configitem_is_debugmode_priv(void);
void configitem_set_debugmode_override(bool user, bool priv);

View File

@@ -35,6 +35,7 @@
#include "smc_api.h"
#include "timers.h"
#include "misc.h"
#include "uart.h"
#include "exocfg.h"
#define u8 uint8_t
@@ -241,7 +242,7 @@ void save_se_and_power_down_cpu(void) {
save_se_state();
if (!configitem_is_retail()) {
/* TODO: uart_log("OYASUMI"); */
uart_send(UART_A, "OYASUMI", 8);
}
finalize_powerdown();

View File

@@ -33,7 +33,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = {
{0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D},
{0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE},
{0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9},
{0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9}
{0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE6, 0xD8, 0x9A, 0xCF, 0xE5, 0x3F, 0xB3, 0x4B}
};
bool usecase_is_invalid(unsigned int usecase) {

View File

@@ -30,6 +30,7 @@
#include "car.h"
#include "i2c.h"
#include "misc.h"
#include "uart.h"
#include "interrupt.h"
#include "pmc.h"
@@ -55,8 +56,16 @@ void __attribute__((noreturn)) warmboot_main(void) {
/* On warmboot (not cpu_on) only */
if (VIRT_MC_SECURITY_CFG3 == 0) {
/* N only does this on dev units, but we will do it unconditionally. */
{
uart_select(UART_A);
clkrst_reboot(CARDEVICE_UARTA);
uart_init(UART_A, 115200);
}
if (!configitem_is_retail()) {
/* TODO: uart_log("OHAYO"); */
uart_send(UART_A, "OHAYO", 6);
uart_wait_idle(UART_A, UART_VENDOR_STATE_TX_IDLE);
}
/* Sanity check the Security Engine. */

View File

@@ -15,6 +15,7 @@
*/
#include "car.h"
#include "timers.h"
#include "utils.h"
static inline uint32_t get_clk_source_reg(CarDevice dev) {
@@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) {
void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev);
clkrst_enable(dev);
if (dev == CARDEVICE_KFUSE) {
/* Workaround for KFUSE clock. */
clk_enable(dev);
udelay(100);
rst_disable(dev);
udelay(200);
} else {
clkrst_enable(dev);
}
}
void clkrst_enable_fuse_regs(bool enable) {

View File

@@ -40,12 +40,12 @@ static char g_bct0_buffer[BCTO_MAX_SIZE];
#define DEFAULT_BCT0_FOR_DEBUG \
"BCT0\n"\
"[stage1]\n"\
"stage2_path = fusee-secondary.bin\n"\
"stage2_path = atmosphere/fusee-secondary.bin\n"\
"stage2_addr = 0xF0000000\n"\
"stage2_entrypoint = 0xF0000000\n"
static const char *load_config(void) {
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) {
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "atmosphere/BCT.ini")) {
print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n");
memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG));
@@ -108,7 +108,7 @@ static void setup_env(void) {
/* Set up the exception handlers. */
setup_exception_handlers();
/* Mount the SD card. */
mount_sd();
}
@@ -133,6 +133,9 @@ int main(void) {
uint32_t stage2_version = 0;
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
/* Override the global logging level. */
log_set_log_level(log_level);
/* Initialize the display, console, etc. */
setup_env();
@@ -144,9 +147,6 @@ int main(void) {
fatal_error("Failed to parse BCT.ini!\n");
}
/* Override the global logging level. */
log_set_log_level(log_level);
/* Say hello. */
print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
@@ -159,7 +159,7 @@ int main(void) {
strcpy(g_chainloader_arg_data, stage2_path);
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
memcpy(&stage2_args->version, &stage2_version, 4);
stage2_args->log_level = log_level;
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
stage2_args->display_initialized = false;
strcpy(stage2_args->bct0, bct0);
g_chainloader_argc = 2;

View File

@@ -15,6 +15,7 @@
*/
#include "car.h"
#include "timers.h"
#include "utils.h"
static inline uint32_t get_clk_source_reg(CarDevice dev) {
@@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) {
void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev);
clkrst_enable(dev);
if (dev == CARDEVICE_KFUSE) {
/* Workaround for KFUSE clock. */
clk_enable(dev);
udelay(100);
rst_disable(dev);
udelay(200);
} else {
clkrst_enable(dev);
}
}
void clkrst_enable_fuse_regs(bool enable) {

View File

@@ -442,6 +442,11 @@ static const kernel_hook_t g_kernel_hooks_600[] = {
/* Kernel Infos. */
static const kernel_info_t g_kernel_infos[] = {
{ /* 1.0.0-7. */
.hash = {0x64, 0x44, 0x07, 0x2F, 0x56, 0x44, 0x73, 0xDD, 0xD5, 0x46, 0x1B, 0x8C, 0xDC, 0xEF, 0x54, 0x98, 0x16, 0xDA, 0x81, 0xDE, 0x5B, 0x1C, 0x9D, 0xD7, 0x5A, 0x13, 0x91, 0xD9, 0x53, 0xAB, 0x8D, 0x8D},
.free_code_space_offset = 0x4797C,
KERNEL_HOOKS(100)
},
{ /* 1.0.0. */
.hash = {0xB8, 0xC5, 0x0C, 0x68, 0x25, 0xA9, 0xB9, 0x5B, 0xD2, 0x4D, 0x2C, 0x7C, 0x81, 0x7F, 0xE6, 0x96, 0xF2, 0x42, 0x4E, 0x1D, 0x78, 0xDF, 0x3B, 0xCA, 0x3D, 0x6B, 0x68, 0x12, 0xDD, 0xA9, 0xCB, 0x9C},
.free_code_space_offset = 0x4797C,

View File

@@ -20,6 +20,8 @@
#include "timers.h"
#include "tsec.h"
#define TSEC_KEYGEN_MAX_RETRIES 25
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
@@ -168,14 +170,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
/* Copy package1 into IRAM. */
memcpy((void *)0x40010000, package1, package1_size);
/* Load the TSEC firmware from IRAM. */
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
}
/* Disable the aperture since it has precedence over the SMMU. */
mc_disable_ahb_redirect();
/* Setup TSEC's address space. */
uint32_t *pdir = smmu_setup_tsec_as(1);
@@ -189,21 +183,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
volatile uint32_t *iram_pages = smmu_alloc_page(48);
volatile uint32_t *expv_page = smmu_alloc_page(1);
/* Copy CAR, MC and FUSE. */
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
/* Copy IRAM. */
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
car_page[0x1F4/4] = 2;
/* TSEC wants the aperture fully open. */
mc_page[0x65C/4] = 0;
mc_page[0x660/4] = 0x80000000;
/* Map all necessary pages. */
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
@@ -217,19 +196,69 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
/* Enable the SMMU. */
smmu_enable();
/* Run the TSEC firmware. */
tsec_run_fw();
/* Extract the keys from SE. */
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
uint32_t key_buf[0x20/4] = {0};
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
uint32_t old_key_data = *key_data;
uint32_t buf_counter = 0;
while (!(tsec->FALCON_CPUCTL & 0x10)) {
if (*key_data != old_key_data) {
old_key_data = *key_data;
key_buf[buf_counter] = *key_data;
buf_counter++;
unsigned int retries = 0;
while (true) {
if (retries++ > TSEC_KEYGEN_MAX_RETRIES) {
fatal_error("[SMMU] TSEC key generation race was lost too many times!");
}
/* Load the TSEC firmware from IRAM. */
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
}
/* Disable the aperture since it has precedence over the SMMU. */
mc_disable_ahb_redirect();
/* Clear all pages. */
memset((void *)car_page, 0, SMMU_PAGE_SIZE);
memset((void *)fuse_page, 0, SMMU_PAGE_SIZE);
memset((void *)pmc_page, 0, SMMU_PAGE_SIZE);
memset((void *)flow_page, 0, SMMU_PAGE_SIZE);
memset((void *)se_page, 0, SMMU_PAGE_SIZE);
memset((void *)mc_page, 0, SMMU_PAGE_SIZE);
memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE);
memset((void *)expv_page, 0, SMMU_PAGE_SIZE);
/* Copy CAR, MC and FUSE. */
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
/* Copy IRAM. */
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
car_page[0x1F4/4] = 2;
/* TSEC wants the aperture fully open. */
mc_page[0x65C/4] = 0;
mc_page[0x660/4] = 0x80000000;
/* Run the TSEC firmware. */
tsec_run_fw();
/* Extract the keys from SE. */
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
uint32_t old_key_data = *key_data;
uint32_t buf_counter = 0;
while (!(tsec->FALCON_CPUCTL & 0x10)) {
const uint32_t new_key_data = *key_data;
if (new_key_data != old_key_data) {
old_key_data = new_key_data;
key_buf[buf_counter] = new_key_data;
buf_counter++;
}
}
/* Enable back the aperture. */
mc_enable_ahb_redirect();
if (buf_counter == 8) {
break;
}
}
@@ -248,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
/* Clear TSEC's address space. */
smmu_clear_tsec_as(1);
/* Enable back the aperture. */
mc_enable_ahb_redirect();
/* Return the decrypted package1 from emulated IRAM. */
memcpy(package1_dec, (void *)iram_pages, package1_size);

View File

@@ -4,13 +4,13 @@
"title_id_range_min": "0x0100000000000034",
"title_id_range_max": "0x0100000000000034",
"main_thread_stack_size": "0x00010000",
"main_thread_priority": 37,
"main_thread_priority": 15,
"default_cpu_id": 3,
"process_category": 0,
"is_retail": true,
"pool_partition": 2,
"is_64_bit": true,
"address_space_type": 3,
"address_space_type": 1,
"filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF"
},
@@ -88,7 +88,7 @@
}
}, {
"type": "min_kernel_version",
"value": "0x0060"
"value": "0x0030"
}, {
"type": "handle_table_size",
"value": 128

View File

@@ -69,7 +69,7 @@ void Utils::InitializeSdThreadFunc(void *args) {
/* Mount SD. */
while (R_FAILED(fsMountSdcard(&g_sd_filesystem))) {
svcSleepThread(1000ULL);
svcSleepThread(1000000ULL);
}
/* Back up CAL0, if it's not backed up already. */

View File

@@ -10,7 +10,7 @@
"is_retail": true,
"pool_partition": 2,
"is_64_bit": true,
"address_space_type": 3,
"address_space_type": 1,
"filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF"
},
@@ -99,7 +99,7 @@
},
{
"type": "min_kernel_version",
"value": "0x0060"
"value": "0x0030"
}
]
}