int program_flash_dword(const uint64_t *dword) { int rv; dbgprintx32("program_flash_dword ", PARTITION_FLASHMODE_START, "\r\n"); rv = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, PARTITION_FLASHMODE_START, *dword); return rv; }
void dump_partitions(void) { dbgprintx32("FLASH_BOUNDARY 0x", FLASH_BOUNDARY , "\r\n"); dbgprintx32("PARTITION_BOOT_START 0x", PARTITION_BOOT_START , "\r\n"); dbgprintx32("PARTITION_BOOT_END 0x", PARTITION_BOOT_END , "\r\n"); dbgprintx32("PARTITION_TFTF_START 0x", PARTITION_TFTF_START , "\r\n"); dbgprintx32("PARTITION_TFTF_END 0x", PARTITION_TFTF_END , "\r\n"); dbgprintx32("PARTITION_MAIN_START 0x", PARTITION_MAIN_START , "\r\n"); dbgprintx32("PARTITION_MAIN_END 0x", PARTITION_MAIN_END , "\r\n"); dbgprintx32("PARTITION_FLASHMODE_START 0x", PARTITION_FLASHMODE_START, "\r\n"); dbgprintx32("PARTITION_FLASHMODE_END 0x", PARTITION_FLASHMODE_END , "\r\n"); }
static int find_public_key(tftf_signature *signature, const unsigned char **key) { uint32_t *ps, *pk; int i, k; uint32_t size = (sizeof(public_keys[0]) - sizeof(public_keys[0].key)) / sizeof(uint32_t); ps = (uint32_t *)&(signature->type); for (k = 0; k < number_of_public_keys; k++) { if (chip_is_key_revoked(k)) { dbgprintx32("Key ", k, " revoked\n"); continue; } pk = (uint32_t *)&public_keys[k]; for (i = 0; i < size; i++) { if (ps[i] != pk[i]) { break; } } if (i >= size) { dbgprint("Found pub. key for this sig.\n"); *key = public_keys[k].key; return 0; } } dbgprint("Failed to find pub. key for this sig.\n"); return -1; }
static int gbboot_get_firmware_size(uint32_t cportid, gb_operation_header *op_header) { int rc; uint8_t *payload = (uint8_t *)op_header + sizeof(*op_header); uint32_t size; spi_ops.init(); stage_to_load = *payload - 1; rc = locate_ffff_element_on_storage(&spi_ops, stage_to_load, &size); dbgprintx32("image size: ", size, "\n"); #if _SPECIAL_TEST == SPECIAL_GEAR_CHANGE_TEST switch_gear_change(GEAR_HS_G2, TERMINATION_ON, HS_MODE_A, 1, POWERMODE_FAST); #endif return greybus_op_response(cportid, op_header, (rc == 0) ? GB_OP_SUCCESS : GB_OP_UNKNOWN_ERROR, (unsigned char*)&size, sizeof(size)); }
int spi_write_calc_total_len(void *data) { tftf_header *tf_header = (tftf_header *)data; tftf_section_descriptor *section = tf_header->sections; uint32_t num_sections = 0; total_section_length = 0; while (section->section_type != TFTF_SECTION_END) { total_section_length += section->section_length; num_sections++; section++; } #ifdef CONFIG_DEBUG_SPI_FLASH dbgprintx32("spi flash tftf num_sections ", num_sections, "\r\n"); dbgprintx32("spi flash tftf total_section_length ", total_section_length, "\r\n"); #endif return total_section_length; }
static int gbboot_ready_to_boot(uint32_t cportid, gb_operation_header *op_header) { uint8_t *payload = (uint8_t *)op_header + sizeof(*op_header); dbgprintx32("ready-to-boot, status: ", *payload, "\n"); image_download_finished = true; return greybus_op_response(cportid, op_header, (*payload != 0) ? GB_OP_SUCCESS : GB_OP_UNKNOWN_ERROR, NULL, 0); }
int spi_write_to_flash_data(const data_write_ops *ops, void *src, uint32_t len) { int result = 0; #ifdef CONFIG_DEBUG_SPI_FLASH dbgprintx32("spi_write_to_flash_data dst ", dst, "\r\n"); #endif ops->write(dst, src, len); result = ops->verify(dst, src, len); dst += len; return result; }
/** * @brief Wrapper to set the bootloader-specific "errno" value * * Note: The first error is sticky (subsequent settings are ignored) * * @param errno A BRE_xxx error code to save */ void set_last_error(uint32_t err) { if (br_errno == BRE_OK) { uint32_t err_group = err & BRE_GROUP_MASK; /* Save the error */ br_errno = err; /* Print out the error */ dbgprintx32((err_group == BRE_EFUSE_BASE)? "e-Fuse err: ": (err_group == BRE_TFTF_BASE)? "TFTF err: ": (err_group == BRE_FFFF_BASE)? "FFFF err: " : (err_group == BRE_CRYPTO_BASE)? "Crypto err: " : "error: ", err, "\n"); } }
static int gbboot_get_firmware_size(uint32_t cportid, gb_operation_header *op_header) { int rc; uint8_t *payload = (uint8_t *)op_header + sizeof(*op_header); uint32_t size; spi_ops.init(); stage_to_load = *payload - 1; rc = locate_ffff_element_on_storage(&spi_ops, stage_to_load, &size); dbgprintx32("image size: ", size, "\n"); return greybus_op_response(cportid, op_header, (rc == 0) ? GB_OP_SUCCESS : GB_OP_UNKNOWN_ERROR, (unsigned char*)&size, sizeof(size)); }
static int gbboot_ready_to_boot(uint32_t cportid, gb_operation_header *op_header) { uint8_t *payload = (uint8_t *)op_header + sizeof(*op_header); dbgprintx32("ready-to-boot, status: ", *payload, "\n"); image_download_finished = true; #if _SPECIAL_TEST == SPECIAL_GEAR_CHANGE_TEST switch_gear_change(GEAR_HS_G3, TERMINATION_ON, HS_MODE_A, 2, POWERMODE_FAST); #endif return greybus_op_response(cportid, op_header, (*payload != 0) ? GB_OP_SUCCESS : GB_OP_UNKNOWN_ERROR, NULL, 0); }
/** * @brief Stage 2 loader "C" entry point. Started from Stage 1 * bootloader. Primary function is to load, validate, and start * executing a stage 3 image. Also will (when fully implemented) * perform startup negotiations with AP, cryptographic initialzations * and tests, module authentication, flash update, and other housekeeping. * Image load and validation are essntially identical to the crresponding * functions in stage 1, although different keys are used for signature * validation. * * @param none * * @returns Nothing. Will launch/restart image if successful, halt if not. */ void bootrom_main(void) { int rc; /* TA-20 R/W data in bufRAM */ uint32_t boot_status = INIT_STATUS_OPERATING; bool boot_from_spi = true; bool fallback_boot_unipro = false; uint32_t is_secure_image; secondstage_cfgdata *cfgdata; chip_init(); dbginit(); /* Ensure that we start each boot with an assumption of success */ init_last_error(); crypto_init(); dbgprint("\nHello world from s2fw\n"); if (!get_2ndstage_cfgdata(&cfgdata)) { dbgprint("found valid config data\n"); if (cfgdata->use_fake_ims) { /** * We don't really need to handle all the efuses as boot ROM * does. But we do want to update the EPUID according to the * fake IMS. And the rest of the efuse handling do no harm * anyway. */ if (efuse_init() != 0) { halt_and_catch_fire(boot_status); } } } uint8_t ims[TSB_ISAA_NUM_IMS_BYTES]; tsb_get_ims(ims, TSB_ISAA_NUM_IMS_BYTES); key_generation(ims); chip_unipro_init(); boot_control(&boot_from_spi); /* Advertise our boot status */ chip_advertise_boot_status(boot_status); /* Advertise our initialization type */ rc = chip_advertise_boot_type(); if (rc) { halt_and_catch_fire(boot_status); } if (boot_from_spi) { dbgprint("Boot from SPIROM\n"); spi_ops.init(); /** * Call locate_ffff_element_on_storage to locate next stage FW. * Do not care about the image length here so pass NULL. */ if (locate_ffff_element_on_storage(&spi_ops, FFFF_ELEMENT_STAGE_3_FW, NULL) == 0) { boot_status = INIT_STATUS_SPI_BOOT_STARTED; chip_advertise_boot_status(boot_status); if (!load_tftf_image(&spi_ops, &is_secure_image)) { spi_ops.finish(true, is_secure_image); if (is_secure_image) { boot_status = INIT_STATUS_TRUSTED_SPI_FLASH_BOOT_FINISHED; dbgprintx32("SPI Trusted: (", merge_errno_with_boot_status(boot_status), ")\n"); } else { boot_status = INIT_STATUS_UNTRUSTED_SPI_FLASH_BOOT_FINISHED; dbgprintx32("SPI Untrusted: (", merge_errno_with_boot_status(boot_status), ")\n"); /* * Disable IMS, CMS access before starting untrusted image. * NB. JTAG continues to be not enabled at this point */ efuse_rig_for_untrusted(); } /* Log that we're starting the boot-from-SPIROM */ chip_advertise_boot_status(merge_errno_with_boot_status(boot_status)); /* TA-16 jump to SPI code (BOOTRET_o = 0 && SPIBOOT_N = 0) */ jump_to_image(); } } spi_ops.finish(false, false); /* Fallback to UniPro boot */ boot_from_spi = false; fallback_boot_unipro = true; chip_clear_image_loading_ram(); } else { /* (Not boot-from-spi, */ fallback_boot_unipro = false; } if (greybus_init()) { set_last_error(BRE_BOU_GBCTRL_CPORT); halt_and_catch_fire(boot_status); } /* Boot-Over-UniPro... * We get here if directed to do so by the bootselector, or as a fallback * for a failed SPIROM boot. */ if (!boot_from_spi) { /* Boot over Unipro */ if (fallback_boot_unipro) { boot_status = merge_errno_with_boot_status( INIT_STATUS_FALLLBACK_UNIPRO_BOOT_STARTED); dbgprintx32("Spi boot failed (", boot_status, "), "); } else { boot_status = INIT_STATUS_UNIPRO_BOOT_STARTED; } chip_advertise_boot_status(boot_status); dbgprintx32("Boot over UniPro (", merge_errno_with_boot_status(boot_status), ")\n"); advertise_ready(); #if RUN_SPI_TEST spi_gb_init(); dbgprint("Running in loop to perform as SPI over Greybus\n"); while (1) { if (greybus_loop()) { dbgprint("ERROR in greuybus loop\n"); halt_and_catch_fire(boot_status); } } #endif dbgprint("Ready-poked; download-ready\n"); if (greybus_ops.init() != 0) { halt_and_catch_fire(boot_status); } if (!load_tftf_image(&greybus_ops, &is_secure_image)) { if (greybus_ops.finish(true, is_secure_image) != 0) { halt_and_catch_fire(boot_status); } if (is_secure_image) { boot_status = fallback_boot_unipro ? INIT_STATUS_FALLLBACK_TRUSTED_UNIPRO_BOOT_FINISHED : INIT_STATUS_TRUSTED_UNIPRO_BOOT_FINISHED; dbgprintx32("UP Trusted: (", merge_errno_with_boot_status(boot_status), ")\n"); } else { boot_status = fallback_boot_unipro ? INIT_STATUS_FALLLBACK_UNTRUSTED_UNIPRO_BOOT_FINISHED : INIT_STATUS_UNTRUSTED_UNIPRO_BOOT_FINISHED; dbgprintx32("UP Trusted: (", merge_errno_with_boot_status(boot_status), ")\n"); /* * Disable IMS, CMS access before starting * untrusted image * NB. JTAG continues to be not enabled at this point */ efuse_rig_for_untrusted(); } /* Log that we're starting the boot-from-UniPro */ chip_advertise_boot_status(boot_status); /* TA-17 jump to Workram code (BOOTRET_o = 0 && SPIM_BOOT_N = 1) */ jump_to_image(); } if (greybus_ops.finish(false, is_secure_image) != 0) { halt_and_catch_fire(boot_status); } } /* If we reach here, we didn't find an image to boot - stop while we're * ahead... */ halt_and_catch_fire(boot_status); }
static int es2_fixup_mphy(void) { uint32_t debug_0720 = tsb_get_debug_reg(0x0720); uint32_t urc; const struct tsb_mphy_fixup *fu; /* * Apply the "register 2" map fixups. */ unipro_attr_local_write(TSB_MPHY_MAP, TSB_MPHY_MAP_TSB_REGISTER_2, 0, &urc); if (urc) { dbgprint((char*)__func__); dbgprintx32(": failed to switch to register 2 map:", urc, "\r\n"); return urc; } fu = tsb_register_2_map_mphy_fixups; do { unipro_attr_local_write(fu->attrid, fu->value, fu->select_index, &urc); if (urc) { dbgprint((char*)__func__); dbgprintx32(": failed to switch to register 2 map:", urc, "\r\n"); return urc; } } while (!tsb_mphy_fixup_is_last(fu++)); /* * Switch to "normal" map. */ unipro_attr_local_write(TSB_MPHY_MAP, TSB_MPHY_MAP_NORMAL, 0, &urc); if (urc) { dbgprint((char*)__func__); dbgprintx32(": failed to switch to normal map: ", urc, "\r\n"); return urc; } /* * Apply the "register 1" map fixups. */ unipro_attr_local_write(TSB_MPHY_MAP, TSB_MPHY_MAP_TSB_REGISTER_1, 0, &urc); if (urc) { dbgprint((char*)__func__); dbgprintx32(": failed to switch to register 1 map: ", urc, "\r\n"); return urc; } fu = tsb_register_1_map_mphy_fixups; do { if (tsb_mphy_r1_fixup_is_magic(fu)) { /* * The magic R1 fixups come from the mysterious and solemn * debug register 0x0720. * */ unipro_attr_local_write(0x8002, (debug_0720 >> 1) & 0x1f, 0, &urc); } else { unipro_attr_local_write(fu->attrid, fu->value, fu->select_index, &urc); } if (urc) { dbgprint((char*)__func__); dbgprintx32(": failed to switch to register 1 map: ", urc, "\r\n"); return urc; } } while (!tsb_mphy_fixup_is_last(fu++));