diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index dd2cfd870..afa1f7e20 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -138,9 +138,9 @@ void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash) { } bool bootconfig_is_recovery_boot(void) { - return (g_boot_reason.is_recovery_boot != 0); + return ((g_boot_reason.bootloader_attribute & 0x01) != 0); } uint64_t bootconfig_get_boot_reason(void) { - return ((uint64_t)g_boot_reason.boot_reason_high << 24) | (g_boot_reason.boot_reason_low & 0xFFFFFF); + return ((uint64_t)g_boot_reason.boot_reason_state << 24) | (g_boot_reason.boot_reason_value & 0xFFFFFF); } diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index 823323a03..e2e410ade 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -34,11 +34,12 @@ static inline bootconfig_t *get_loaded_bootconfig(void) { } typedef struct { - uint64_t _0x00; - uint32_t _0x08; - uint32_t is_recovery_boot; - uint32_t boot_reason_low; - uint32_t boot_reason_high; + uint32_t bootloader_version; + uint32_t bootloader_start_block; + uint32_t bootloader_start_page; + uint32_t bootloader_attribute; + uint32_t boot_reason_value; + uint32_t boot_reason_state; } boot_reason_t; void bootconfig_load_and_verify(const bootconfig_t *bootconfig); diff --git a/exosphere/src/sysctr0.h b/exosphere/src/sysctr0.h index 9c887c48c..c29a956ea 100644 --- a/exosphere/src/sysctr0.h +++ b/exosphere/src/sysctr0.h @@ -9,9 +9,25 @@ #define SYSCTR0_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSCTR0)) - #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) - +#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) +#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) +#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) +#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) +#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) +#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) +#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) +#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) +#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) +#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) +#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) +#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) +#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) +#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) +#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) +#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) +#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) #endif diff --git a/fusee/fusee-primary/src/btn.c b/fusee/fusee-primary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-primary/src/btn.c +++ b/fusee/fusee-primary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; uint32_t val = 0; - if (i2c_query(4, 0x3C, 0x15, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) { if (val & 0x4) res |= BTN_POWER; diff --git a/fusee/fusee-primary/src/car.h b/fusee/fusee-primary/src/car.h index 6ec42e744..572595c90 100644 --- a/fusee/fusee-primary/src/car.h +++ b/fusee/fusee-primary/src/car.h @@ -224,16 +224,16 @@ typedef struct { uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t _0x350[2]; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ @@ -456,6 +456,7 @@ typedef struct { uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-primary/src/di.c +++ b/fusee/fusee-primary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ uint8_t val = 0xD0; - i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1); /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-primary/src/fs_utils.c b/fusee/fusee-primary/src/fs_utils.c index 1c8529f07..9146ad0c2 100644 --- a/fusee/fusee-primary/src/fs_utils.c +++ b/fusee/fusee-primary/src/fs_utils.c @@ -47,6 +47,12 @@ void unmount_sd(void) sdmmc_device_finish(&g_sd_device); g_sd_mounted = false; } + + /* Disable AHB redirection if necessary. */ + if (g_ahb_redirect_enabled) { + mc_disable_ahb_redirect(); + g_ahb_redirect_enabled = false; + } } uint32_t get_file_size(const char *filename) diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index 903b750bd..929136d38 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -203,33 +203,33 @@ void nx_hwinit() clkrst_reboot(CARDEVICE_UNK); /* Initialize I2C1 and I2C5. */ - i2c_init(0); - i2c_init(4); + i2c_init(I2C_1); + i2c_init(I2C_5); uint8_t val = 0x40; - i2c_send(4, 0x3C, MAX77620_REG_CNFGBBC, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1); val = 0x78; - i2c_send(4, 0x3C, MAX77620_REG_ONOFFCNFG1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); val = 0x38; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1); val = 0x3A; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG1, &val, 1); val = 0x38; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG2, &val, 1); val = 0xF; - i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO4, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO4, &val, 1); val = 0xC7; - i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO8, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO8, &val, 1); val = 0x4F; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD0, &val, 1); val = 0x29; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1); val = 0x1B; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD3, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1); val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */ - i2c_send(4, 0x3C, MAX77620_REG_SD0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1); /* Configure and lock PMC scratch registers. */ config_pmc_scratch(); diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); val |= 4; - i2c_send(4, 0x3C, 0x41, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); } /* Queries the value of TI charger bit over I2C. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); return (val & 0x80) != 0; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val &= 0x7F; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Sets TI charger bit over I2C. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val |= 0x80; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Get registers pointer based on I2C ID. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + typedef struct { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-primary/src/max77620.h b/fusee/fusee-primary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-primary/src/max77620.h +++ b/fusee/fusee-primary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _MFD_MAX77620_H_ #define _MFD_MAX77620_H_ +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-primary/src/max7762x.c +++ b/fusee/fusee-primary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; if (reg->type == REGULATOR_SD) { - if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1)) return (val & reg->status_mask) ? 0 : 1; } - if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) return (val & 8) ? 0 : 1; return 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) { return 1; } @@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; uint8_t val = 0; - if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); - if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { udelay(1000); return 1; @@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable) uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; uint8_t val = 0; - if (i2c_query(4, 0x3C, addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { if (enable) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else val &= ~reg->enable_mask; - if (i2c_send(4, 0x3C, addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { udelay(1000); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { uint8_t val = 0; - if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1)) { max77620_regulator_config_fps(i); max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } uint8_t val = 4; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); } void max77620_low_battery_monitor_config() { uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); - i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); } diff --git a/fusee/fusee-primary/src/sdram.c b/fusee/fusee-primary/src/sdram.c index eb941f235..135833eea 100644 --- a/fusee/fusee-primary/src/sdram.c +++ b/fusee/fusee-primary/src/sdram.c @@ -542,9 +542,9 @@ void sdram_init() const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); uint8_t val = 5; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */ - i2c_send(4, 0x3C, MAX77620_REG_SD1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD1, &val, 1); pmc->vddp_sel = params->pmc_vddp_sel; udelay(params->pmc_vddp_sel_wait); diff --git a/fusee/fusee-primary/src/sysctr0.h b/fusee/fusee-primary/src/sysctr0.h index 477063bb0..d861f739b 100644 --- a/fusee/fusee-primary/src/sysctr0.h +++ b/fusee/fusee-primary/src/sysctr0.h @@ -3,9 +3,26 @@ #include -#define SYSCTR0_BASE 0x7000F000 +#define SYSCTR0_BASE 0x700F0000 #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) +#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) +#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) +#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) #define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) +#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) +#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) +#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) +#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) +#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) +#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) +#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) +#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) +#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) +#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) +#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) +#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) +#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) #endif diff --git a/fusee/fusee-secondary/src/btn.c b/fusee/fusee-secondary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-secondary/src/btn.c +++ b/fusee/fusee-secondary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; uint32_t val = 0; - if (i2c_query(4, 0x3C, 0x15, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) { if (val & 0x4) res |= BTN_POWER; diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 6ec42e744..572595c90 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -224,16 +224,16 @@ typedef struct { uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t _0x350[2]; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ @@ -456,6 +456,7 @@ typedef struct { uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index bceaf7d73..12eebeb8b 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -12,22 +12,22 @@ void _cluster_enable_power() { uint8_t val = 0; - i2c_query(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); val &= 0xDF; - i2c_send(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO5, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); /* Enable power. */ val = 0x20; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL3, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); val = 0x8D; - i2c_send(4, 0x1B, MAX77620_REG_CNFG1_32K, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); val = 0xB7; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); val = 0xB7; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL2, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); } int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) @@ -77,12 +77,12 @@ void cluster_boot_cpu0(uint32_t entry) udelay(2); car->pllx_base = 0x80404E02; car->pllx_base = 0x404E02; - car->pllx_misc = ((car->pllx_base & 0xFFFBFFFF) | 0x40000); + car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000); car->pllx_base = 0x40404E02; } while (!(car->pllx_base & 0x8000000)) { - /* Spinlock. */ + /* Wait. */ } /* Configure MSELECT source and enable clock. */ @@ -111,13 +111,13 @@ void cluster_boot_cpu0(uint32_t entry) /* Request and wait for RAM repair. */ FLOW_CTLR_RAM_REPAIR_0 = 1; while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){ - /* Spinlock. */ + /* Wait. */ } MAKE_EXCP_VEC_REG(0x100) = 0; /* Set reset vector. */ - SB_AA64_RESET_LOW_0 = entry | 1; + SB_AA64_RESET_LOW_0 = (entry | 1); SB_AA64_RESET_HIGH_0 = 0; /* Non-secure reset vector write disable. */ diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-secondary/src/di.c +++ b/fusee/fusee-secondary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ uint8_t val = 0xD0; - i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1); /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); val |= 4; - i2c_send(4, 0x3C, 0x41, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); } /* Queries the value of TI charger bit over I2C. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); return (val & 0x80) != 0; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val &= 0x7F; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Sets TI charger bit over I2C. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val |= 0x80; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Get registers pointer based on I2C ID. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + typedef struct { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-secondary/src/max77620.h b/fusee/fusee-secondary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-secondary/src/max77620.h +++ b/fusee/fusee-secondary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _MFD_MAX77620_H_ #define _MFD_MAX77620_H_ +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-secondary/src/max7762x.c +++ b/fusee/fusee-secondary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; if (reg->type == REGULATOR_SD) { - if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1)) return (val & reg->status_mask) ? 0 : 1; } - if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) return (val & 8) ? 0 : 1; return 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) { return 1; } @@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; uint8_t val = 0; - if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); - if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { udelay(1000); return 1; @@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable) uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; uint8_t val = 0; - if (i2c_query(4, 0x3C, addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { if (enable) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else val &= ~reg->enable_mask; - if (i2c_send(4, 0x3C, addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { udelay(1000); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { uint8_t val = 0; - if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1)) { max77620_regulator_config_fps(i); max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } uint8_t val = 4; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); } void max77620_low_battery_monitor_config() { uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); - i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 17a9b5f0c..8a44b2f8c 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -7,10 +7,13 @@ #include "fs_utils.h" #include "nxboot.h" #include "nxfs.h" +#include "bct.h" #include "di.h" #include "mc.h" #include "se.h" #include "pmc.h" +#include "i2c.h" +#include "max77620.h" #include "cluster.h" #include "flow.h" #include "timers.h" @@ -78,13 +81,98 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) { *(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg; } +static void nxboot_set_bootreason() { + boot_reason_t boot_reason = {0}; + FILE *boot0; + nvboot_config_table *bct; + nv_bootloader_info *bootloader_info; + + /* Allocate memory for the BCT. */ + bct = malloc(sizeof(nvboot_config_table)); + if (bct == NULL) { + fatal_error("[NXBOOT]: Out of memory!\n"); + } + + /* Open boot0. */ + boot0 = fopen("boot0:/", "rb"); + if (boot0 == NULL) { + fatal_error("[NXBOOT]: Failed to open boot0!\n"); + } + + /* Read the BCT. */ + if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) { + fatal_error("[NXBOOT]: Failed to read the BCT!\n"); + } + + /* Close boot0. */ + fclose(boot0); + + /* Populate bootloader parameters. */ + bootloader_info = &bct->bootloader[0]; + boot_reason.bootloader_version = bootloader_info->version; + boot_reason.bootloader_start_block = bootloader_info->start_blk; + boot_reason.bootloader_start_page = bootloader_info->start_page; + boot_reason.bootloader_attribute = bootloader_info->attribute; + + uint8_t power_key_intr = 0; + uint8_t rtc_intr = 0; + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFIRQ, &power_key_intr, 1); + i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1); + + /* Set PMIC value. */ + boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr); + + /* TODO: Find out what these mean. */ + if (power_key_intr & 0x80) + boot_reason.boot_reason_state = 0x01; + else if (power_key_intr & 0x08) + boot_reason.boot_reason_state = 0x02; + else if (rtc_intr & 0x02) + boot_reason.boot_reason_state = 0x03; + else if (rtc_intr & 0x04) + boot_reason.boot_reason_state = 0x04; + + /* Set in memory. */ + memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON, &boot_reason, sizeof(boot_reason)); + + /* Clean up. */ + free(bct); +} + +static void nxboot_move_bootconfig() { + FILE *bcfile; + void *bootconfig; + + /* Allocate memory for reading BootConfig. */ + bootconfig = memalign(0x1000, 0x4000); + if (bootconfig == NULL) { + fatal_error("[NXBOOT]: Out of memory!\n"); + } + + /* Get BootConfig from the Package2 partition. */ + bcfile = fopen("bcpkg21:/", "rb"); + if (bcfile == NULL) { + fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n"); + } + if (fread(bootconfig, 0x4000, 1, bcfile) < 1) { + fatal_error("[NXBOOT]: Failed to read BootConfig!\n"); + } + fclose(bcfile); + + /* Copy the first 0x3000 bytes into IRAM. */ + memset((void *)0x4003D000, 0, 0x3000); + memcpy((void *)0x4003D000, bootconfig, 0x3000); + + /* Clean up. */ + free(bootconfig); +} + /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { volatile tegra_pmc_t *pmc = pmc_get_regs(); volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); - /* void *bootconfig; */ package2_header_t *package2; size_t package2_size; void *tsec_fw; @@ -101,7 +189,7 @@ void nxboot_main(void) { void *exosphere_memaddr; /* Allocate memory for reading Package2. */ - package2 = memalign(4096, PACKAGE2_SIZE_MAX); + package2 = memalign(0x1000, PACKAGE2_SIZE_MAX); if (package2 == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -115,10 +203,12 @@ void nxboot_main(void) { } } else { pk2file = fopen("bcpkg21:/", "rb"); - if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { - printf("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + if (pk2file == NULL) { + fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + } + if (fseek(pk2file, 0x4000, SEEK_SET) != 0) { + fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); fclose(pk2file); - generic_panic(); } } @@ -127,7 +217,7 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Failed to read Package2!\n"); } package2_size = package2_meta_get_size(&package2->metadata); - if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) { + if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) { fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); } if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { @@ -138,7 +228,7 @@ void nxboot_main(void) { /* Read and parse boot0. */ printf("[NXBOOT]: Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); - if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) { + if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); @@ -146,13 +236,15 @@ void nxboot_main(void) { /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if (tsec_fw_size != 0 && tsec_fw_size != 0xF00) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) { fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } - + + /* Allocate memory for the TSEC firmware. */ tsec_fw = memalign(0x100, tsec_fw_size); + if (tsec_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -165,10 +257,6 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } } - - /* TODO: Validate that we're capable of booting. */ - - /* TODO: Initialize Boot Reason. */ /* Find the system's target firmware. */ uint32_t target_firmware = nxboot_get_target_firmware(package1loader); @@ -180,6 +268,12 @@ void nxboot_main(void) { /* Setup boot configuration for Exosphère. */ nxboot_configure_exosphere(target_firmware); + /* Initialize Boot Reason on older firmware versions. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + printf("[NXBOOT]: Initializing Boot Reason...\n"); + nxboot_set_bootreason(); + } + /* Derive keydata. */ if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { fatal_error("[NXBOOT]: Key derivation failed!\n"); @@ -192,7 +286,9 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } + /* Allocate memory for the warmboot firmware. */ warmboot_fw = malloc(warmboot_fw_size); + if (warmboot_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -236,32 +332,45 @@ void nxboot_main(void) { /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); - printf(u8"Reading Exosphère...\n"); + printf(u8"[NXBOOT]: Reading Exosphère...\n"); /* Select the right address for Exosphère. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { - exosphere_memaddr = (void *)0x40020000; + exosphere_memaddr = (void *)0x4002D000; } else { - exosphere_memaddr = (void *)0x40018000; /* 5.x has its secmon's crt0 around this region. */ + exosphere_memaddr = (void *)0x4002B000; } /* Copy Exosphère to a good location or read it directly to it. */ if (loader_ctx->exosphere_path[0] != '\0') { size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); if (exosphere_size == 0) { - fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } else if (exosphere_size > 0x10000) { /* The maximum is actually a bit less than that. */ - fatal_error(u8"Exosphère from %s is too big!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Exosphère from %s is too big!\n", loader_ctx->exosphere_path); } if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) { - fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } + /* Move BootConfig. */ + printf("[NXBOOT]: Moving BootConfig...\n"); + nxboot_move_bootconfig(); + + /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) { + const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; + if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) + pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/ + else if (!strcmp(package1loader_header->build_timestamp, "20170710161758")) + pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */ + } + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -272,9 +381,6 @@ void nxboot_main(void) { } free(package2); - /* Unmount everything. */ - nxfs_unmount_all(); - /* Clear used keyslots. */ clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); @@ -287,9 +393,6 @@ void nxboot_main(void) { set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); } - /* TODO: Handle bootconfig. */ - memset((void *)0x4003D000, 0, 0x3000); - /* Finalize the GPU UCODE carveout. */ mc_config_carveout_finalize(); @@ -320,6 +423,9 @@ void nxboot_main(void) { /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path); + /* Unmount everything. */ + nxfs_unmount_all(); + /* Turn off the backlight. */ display_backlight(false); @@ -327,7 +433,7 @@ void nxboot_main(void) { display_end(); /* Boot CPU0. */ - cluster_boot_cpu0((uint64_t)(uintptr_t)exosphere_memaddr); + cluster_boot_cpu0((uint32_t)exosphere_memaddr); /* Wait for Exosphère to wake up. */ while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 32710d7eb..5f24266d3 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -5,22 +5,26 @@ #define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000)) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) #define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 - #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2 #define NX_BOOTLOADER_STATE_FINISHED 3 - #define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2 #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3 #define NX_BOOTLOADER_STATE_FINISHED_4X 4 -/* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) - -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) +typedef struct { + uint32_t bootloader_version; + uint32_t bootloader_start_block; + uint32_t bootloader_start_page; + uint32_t bootloader_attribute; + uint32_t boot_reason_value; + uint32_t boot_reason_state; +} boot_reason_t; void nxboot_main(void); diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index fcb05d0f9..81c775a30 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -48,6 +48,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) { devpart->crypto_work_buffer_num_sectors = 0; } + /* Enable AHB redirection if necessary. */ if (!g_ahb_redirect_enabled) { mc_enable_ahb_redirect(); g_ahb_redirect_enabled = true; @@ -78,6 +79,12 @@ static int mmc_partition_initialize(device_partition_t *devpart) { static void mmc_partition_finalize(device_partition_t *devpart) { free(devpart->crypto_work_buffer); + + /* Disable AHB redirection if necessary. */ + if (g_ahb_redirect_enabled) { + mc_disable_ahb_redirect(); + g_ahb_redirect_enabled = false; + } } static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index c317d3797..dd0591b9a 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -1,5 +1,4 @@ #include -#include "utils.h" #include "timers.h" #include "splash_screen.h" #include "fs_utils.h" @@ -7,7 +6,7 @@ void display_splash_screen_bmp(const char *custom_splash_path) { uint8_t *splash_screen = g_default_splash_screen; - if (custom_splash_path != NULL && custom_splash_path[0] != '\x00') { + if ((custom_splash_path != NULL) && (custom_splash_path[0] != '\x00')) { if (!read_from_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) { fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path); } @@ -16,5 +15,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) { /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ /* Display the splash screen for three seconds. */ - wait(3000000); + /* udelay(3000000); */ } diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index a0d1b5db0..4a1835085 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -19,6 +19,11 @@ static ini1_header_t *g_stratosphere_ini1 = NULL; +static bool g_stratosphere_loader_enabled = true; +static bool g_stratosphere_sm_enabled = true; +static bool g_stratosphere_pm_enabled = true; +static bool g_stratosphere_boot_enabled = false; + extern const uint8_t boot_100_kip[], boot_200_kip[]; extern const uint8_t loader_kip[], pm_kip[], sm_kip[]; extern const uint32_t boot_100_kip_size, boot_200_kip_size; @@ -27,8 +32,9 @@ extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size; /* GCC doesn't consider the size as const... we have to write it ourselves. */ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { - /* const uint8_t *boot_kip = NULL; */ + const uint8_t *boot_kip = NULL; uint32_t boot_kip_size = 0; + uint32_t num_processes = 0; uint8_t *data; if (g_stratosphere_ini1 != NULL) { @@ -36,14 +42,36 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { } if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) { - /* boot_kip = boot_100_kip; */ + boot_kip = boot_100_kip; boot_kip_size = boot_100_kip_size; } else { - /* boot_kip = boot_200_kip; */ + boot_kip = boot_200_kip; boot_kip_size = boot_200_kip_size; } - size_t size = sizeof(ini1_header_t) + loader_kip_size + pm_kip_size + sm_kip_size + boot_kip_size; + size_t size = sizeof(ini1_header_t); + + /* Calculate our processes' sizes. */ + if (g_stratosphere_loader_enabled) { + size += loader_kip_size; + num_processes++; + } + + if (g_stratosphere_pm_enabled) { + size += pm_kip_size; + num_processes++; + } + + if (g_stratosphere_sm_enabled) { + size += sm_kip_size; + num_processes++; + } + + if (g_stratosphere_boot_enabled) { + size += boot_kip_size; + num_processes++; + } + g_stratosphere_ini1 = (ini1_header_t *)malloc(size); if (g_stratosphere_ini1 == NULL) { @@ -52,26 +80,31 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { g_stratosphere_ini1->magic = MAGIC_INI1; g_stratosphere_ini1->size = size; - g_stratosphere_ini1->num_processes = 3; /*TODO: Change to 4 when boot is supported. */ + g_stratosphere_ini1->num_processes = num_processes; g_stratosphere_ini1->_0xC = 0; data = g_stratosphere_ini1->kip_data; /* Copy our processes. */ - memcpy(data, loader_kip, loader_kip_size); - data += loader_kip_size; + if (g_stratosphere_loader_enabled) { + memcpy(data, loader_kip, loader_kip_size); + data += loader_kip_size; + } - memcpy(data, pm_kip, pm_kip_size); - data += pm_kip_size; + if (g_stratosphere_pm_enabled) { + memcpy(data, pm_kip, pm_kip_size); + data += pm_kip_size; + } - memcpy(data, sm_kip, sm_kip_size); - data += sm_kip_size; + if (g_stratosphere_sm_enabled) { + memcpy(data, sm_kip, sm_kip_size); + data += sm_kip_size; + } - /* TODO: Uncomment when boot is supported. */ - /* - memcpy(data, boot_kip, boot_kip_size); - data += boot_kip_size; - */ + if (g_stratosphere_boot_enabled) { + memcpy(data, boot_kip, boot_kip_size); + data += boot_kip_size; + } return g_stratosphere_ini1; }