void fsp_temp_ram_exit(void) { struct fsp_header hdr; uint32_t status; temp_ram_exit_fn temp_ram_exit; struct cbfsf file_desc; struct region_device file_data; const char *name = CONFIG_FSP_M_CBFS; if (cbfs_boot_locate(&file_desc, name, NULL)) { printk(BIOS_CRIT, "Could not locate %s in CBFS\n", name); die("FSPM not available for CAR Exit!\n"); } cbfs_file_data(&file_data, &file_desc); if (fsp_validate_component(&hdr, &file_data) != CB_SUCCESS) die("Invalid FSPM header!\n"); temp_ram_exit = (void *)(hdr.image_base + hdr.temp_ram_exit_entry); printk(BIOS_DEBUG, "Calling TempRamExit: 0x%p\n", temp_ram_exit); status = temp_ram_exit(NULL); if (status != FSP_SUCCESS) { printk(BIOS_CRIT, "TempRamExit returned 0x%08x\n", status); die("TempRamExit returned an error!\n"); } }
void fsps_load(bool s3wake) { struct fsp_header *hdr = &fsps_hdr; struct cbfsf file_desc; struct region_device rdev; const char *name = CONFIG_FSP_S_CBFS; void *dest; size_t size; struct prog fsps = PROG_INIT(PROG_REFCODE, name); static int load_done; if (load_done) return; if (s3wake && !IS_ENABLED(CONFIG_NO_STAGE_CACHE)) { printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n"); stage_cache_load_stage(STAGE_REFCODE, &fsps); if (fsp_validate_component(hdr, prog_rdev(&fsps)) != CB_SUCCESS) die("On resume fsps header is invalid\n"); load_done = 1; return; } if (cbfs_boot_locate(&file_desc, name, NULL)) { printk(BIOS_ERR, "Could not locate %s in CBFS\n", name); die("FSPS not available!\n"); } cbfs_file_data(&rdev, &file_desc); /* Load and relocate into CBMEM. */ size = region_device_sz(&rdev); dest = cbmem_add(CBMEM_ID_REFCODE, size); if (dest == NULL) die("Could not add FSPS to CBMEM!\n"); if (rdev_readat(&rdev, dest, 0, size) < 0) die("Failed to read FSPS!\n"); if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) die("Unable to relocate FSPS!\n"); /* Create new region device in memory after relocation. */ rdev_chain(&rdev, &addrspace_32bit.rdev, (uintptr_t)dest, size); if (fsp_validate_component(hdr, &rdev) != CB_SUCCESS) die("Invalid FSPS header!\n"); prog_set_area(&fsps, dest, size); stage_cache_add(STAGE_REFCODE, &fsps); /* Signal that FSP component has been loaded. */ prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL); load_done = 1; }
int prog_locate(struct prog *prog) { struct cbfsf file; cbfs_prepare_program_locate(); if (cbfs_boot_locate(&file, prog_name(prog), NULL)) return -1; cbfs_file_data(prog_rdev(prog), &file); return 0; }
static void vboot_prepare(void) { int run_verification; run_verification = verification_should_run(); if (run_verification) { verstage_main(); car_set_var(vboot_executed, 1); } else if (verstage_should_load()) { struct cbfsf file; struct prog verstage = PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage"); printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n"); /* load verstage from RO */ if (cbfs_boot_locate(&file, prog_name(&verstage), NULL)) die("failed to load verstage"); cbfs_file_data(prog_rdev(&verstage), &file); if (cbfs_prog_stage_load(&verstage)) die("failed to load verstage"); /* verify and select a slot */ prog_run(&verstage); /* This is not actually possible to hit this condition at * runtime, but this provides a hint to the compiler for dead * code elimination below. */ if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) return; car_set_var(vboot_executed, 1); } /* * Fill in vboot cbmem objects before moving to ramstage so all * downstream users have access to vboot results. This path only * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because * cbmem comes online prior to vboot verification taking place. For * other platforms the vboot cbmem objects are initialized when * cbmem comes online. */ if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) { vb2_store_selected_region(); vboot_fill_handoff(); } }
int tegra210_run_mtc(void) { ssize_t nread; struct region_device fh; struct cbfsf mtc_file; void *const mtc = (void *)(uintptr_t)CONFIG_MTC_ADDRESS; void *dvfs_table; size_t (*mtc_fw)(void **dvfs_table) = (void *)mtc; if (cbfs_boot_locate(&mtc_file, "tegra_mtc.bin", NULL)) { printk(BIOS_ERR, "MTC file not found: tegra_mtc.bin\n"); return -1; } cbfs_file_data(&fh, &mtc_file); /* Read MTC file into predefined region. */ nread = rdev_readat(&fh, mtc, 0, region_device_sz(&fh)); if (nread != region_device_sz(&fh)) { printk(BIOS_ERR, "MTC bytes read (%zu) != file length(%zu)!\n", nread, region_device_sz(&fh)); return -1; } printk(BIOS_INFO, "MTC: %zu bytes loaded @ %p\n", nread, mtc); mtc_table_size = (*mtc_fw)(&dvfs_table); if ((mtc_table_size == 0) || (mtc_table_size > MTC_TABLE_MAX_SIZE)) { printk(BIOS_ERR, "MTC Training table size is invalid.!\n"); return -1; } printk(BIOS_INFO, "MTC: Done. Entries size 0x%zx located at %p\n", mtc_table_size, dvfs_table); void *cbmem_tab = cbmem_add(CBMEM_ID_MTC, mtc_table_size); if (cbmem_tab == NULL) { printk(BIOS_ERR, "MTC table allocation in cbmem failed!\n"); return -1; } memcpy(cbmem_tab, dvfs_table, mtc_table_size); printk(BIOS_INFO, "MTC: Copied 0x%zx bytes from %p to %p\n", mtc_table_size, dvfs_table, cbmem_tab); return 0; }
void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size) { struct cbfsf fh; size_t fsize; if (cbfs_boot_locate(&fh, name, &type)) return NULL; fsize = region_device_sz(&fh.data); if (size != NULL) *size = fsize; return rdev_mmap(&fh.data, 0, fsize); }
static int fsp_find_and_relocate(struct prog *fsp) { struct region_device fsp_rdev; uint32_t type = CBFS_TYPE_FSP; if (cbfs_boot_locate(&fsp_rdev, prog_name(fsp), &type)) { printk(BIOS_ERR, "ERROR: Couldn't find fsp.bin in CBFS.\n"); return -1; } if (fsp_relocate(fsp, &fsp_rdev)) { printk(BIOS_ERR, "ERROR: FSP relocation failed.\n"); return -1; } return 0; }
enum fsp_status fsp_silicon_init(void) { struct fsp_header *hdr = &fsps_hdr; struct cbfsf file_desc; struct region_device rdev; const char *name = CONFIG_FSP_S_CBFS; void *dest; size_t size; if (cbfs_boot_locate(&file_desc, name, NULL)) { printk(BIOS_ERR, "Could not locate %s in CBFS\n", name); return FSP_NOT_FOUND; } cbfs_file_data(&rdev, &file_desc); /* Load and relocate into CBMEM. */ size = region_device_sz(&rdev); dest = cbmem_add(CBMEM_ID_REFCODE, size); if (dest == NULL) { printk(BIOS_ERR, "Could not add FSPS to CBMEM.\n"); return FSP_NOT_FOUND; } if (rdev_readat(&rdev, dest, 0, size) < 0) return FSP_NOT_FOUND; if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) { printk(BIOS_ERR, "Unable to relocate FSPS.\n"); return FSP_NOT_FOUND; } /* Create new region device in memory after relocation. */ rdev_chain(&rdev, &addrspace_32bit.rdev, (uintptr_t)dest, size); if (fsp_validate_component(hdr, &rdev) != CB_SUCCESS) return FSP_NOT_FOUND; /* Signal that FSP component has been loaded. */ prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL); return do_silicon_init(hdr); }
void fsp_memory_init(bool s3wake) { struct fsp_header hdr; enum cb_err status; struct cbfsf file_desc; struct region_device file_data; const char *name = CONFIG_FSP_M_CBFS; struct memranges memmap; struct range_entry freeranges[2]; if (CONFIG(ELOG_BOOT_COUNT) && !s3wake) boot_count_increment(); if (cbfs_boot_locate(&file_desc, name, NULL)) { printk(BIOS_CRIT, "Could not locate %s in CBFS\n", name); die("FSPM not available!\n"); } cbfs_file_data(&file_data, &file_desc); /* Build up memory map of romstage address space including CAR. */ memranges_init_empty(&memmap, &freeranges[0], ARRAY_SIZE(freeranges)); memranges_insert(&memmap, (uintptr_t)_car_region_start, _car_relocatable_data_end - _car_region_start, 0); memranges_insert(&memmap, (uintptr_t)_program, REGION_SIZE(program), 0); if (!CONFIG(FSP_M_XIP)) status = load_fspm_mem(&hdr, &file_data, &memmap); else status = load_fspm_xip(&hdr, &file_data); if (status != CB_SUCCESS) die("Loading FSPM failed!\n"); /* Signal that FSP component has been loaded. */ prog_segment_loaded(hdr.image_base, hdr.image_size, SEG_FINAL); do_fsp_memory_init(&hdr, s3wake, &memmap); }
int ccplex_load_mts(void) { ssize_t nread; struct stopwatch sw; struct cbfsf mts_file; struct region_device fh; /* * MTS location is hard coded to this magic address. The hardware will * take the MTS from this location and place it in the final resting * place in the carveout region. */ void * const mts = (void *)(uintptr_t)MTS_LOAD_ADDRESS; stopwatch_init(&sw); if (cbfs_boot_locate(&mts_file, MTS_FILE_NAME, NULL)) { printk(BIOS_DEBUG, "MTS file not found: %s\n", MTS_FILE_NAME); return -1; } cbfs_file_data(&fh, &mts_file); /* Read MTS file into the carveout region. */ nread = rdev_readat(&fh, mts, 0, region_device_sz(&fh)); if (nread != region_device_sz(&fh)) { printk(BIOS_DEBUG, "MTS bytes read (%zu) != file length(%u)!\n", nread, region_device_sz(&fh)); return -1; } printk(BIOS_DEBUG, "MTS: %zu bytes loaded @ %p in %ld usecs.\n", nread, mts, stopwatch_duration_usecs(&sw)); return ccplex_start(); }
uint32_t vboot_init_crtm(void) { struct prog bootblock = PROG_INIT(PROG_BOOTBLOCK, "bootblock"); struct prog verstage = PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage"); struct prog romstage = PROG_INIT(PROG_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage"); char tcpa_metadata[TCPA_PCR_HASH_NAME]; /* Initialize TCPE PRERAM log. */ tcpa_preram_log_clear(); /* measure bootblock from RO */ struct cbfsf bootblock_data; struct region_device bootblock_fmap; if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) { if (tpm_measure_region(&bootblock_fmap, TPM_CRTM_PCR, "FMAP: BOOTBLOCK")) return VB2_ERROR_UNKNOWN; } else { if (cbfs_boot_locate(&bootblock_data, prog_name(&bootblock), NULL) == 0) { cbfs_file_data(prog_rdev(&bootblock), &bootblock_data); if (create_tcpa_metadata(prog_rdev(&bootblock), prog_name(&bootblock), tcpa_metadata) < 0) return VB2_ERROR_UNKNOWN; if (tpm_measure_region(prog_rdev(&bootblock), TPM_CRTM_PCR, tcpa_metadata)) return VB2_ERROR_UNKNOWN; } else { printk(BIOS_INFO, "VBOOT: Couldn't measure bootblock into CRTM!\n"); return VB2_ERROR_UNKNOWN; } } if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) { struct cbfsf romstage_data; /* measure romstage from RO */ if (cbfs_boot_locate(&romstage_data, prog_name(&romstage), NULL) == 0) { cbfs_file_data(prog_rdev(&romstage), &romstage_data); if (create_tcpa_metadata(prog_rdev(&romstage), prog_name(&romstage), tcpa_metadata) < 0) return VB2_ERROR_UNKNOWN; if (tpm_measure_region(prog_rdev(&romstage), TPM_CRTM_PCR, tcpa_metadata)) return VB2_ERROR_UNKNOWN; } else { printk(BIOS_INFO, "VBOOT: Couldn't measure %s into CRTM!\n", CONFIG_CBFS_PREFIX "/romstage"); return VB2_ERROR_UNKNOWN; } } if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) { struct cbfsf verstage_data; /* measure verstage from RO */ if (cbfs_boot_locate(&verstage_data, prog_name(&verstage), NULL) == 0) { cbfs_file_data(prog_rdev(&verstage), &verstage_data); if (create_tcpa_metadata(prog_rdev(&verstage), prog_name(&verstage), tcpa_metadata) < 0) return VB2_ERROR_UNKNOWN; if (tpm_measure_region(prog_rdev(&verstage), TPM_CRTM_PCR, tcpa_metadata)) return VB2_ERROR_UNKNOWN; } else { printk(BIOS_INFO, "VBOOT: Couldn't measure %s into CRTM!\n", CONFIG_CBFS_PREFIX "/verstage"); return VB2_ERROR_UNKNOWN; } } return VB2_SUCCESS; }
static void vboot_prepare(void) { if (verification_should_run()) { /* Note: this path is not used for VBOOT_RETURN_FROM_VERSTAGE */ verstage_main(); car_set_var(vboot_executed, 1); vb2_save_recovery_reason_vbnv(); /* * Avoid double memory retrain when the EC is running RW code * and a recovery request came in through an EC host event. The * double retrain happens because the EC won't be rebooted * until kernel verification notices the EC isn't running RO * code which is after memory training. Therefore, reboot the * EC after we've saved the potential recovery request so it's * not lost. Lastly, only perform this sequence on x86 * platforms since those are the ones that currently do a * costly memory training in recovery mode. */ if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) && IS_ENABLED(CONFIG_ARCH_X86)) google_chromeec_early_init(); } else if (verstage_should_load()) { struct cbfsf file; struct prog verstage = PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage"); printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n"); /* load verstage from RO */ if (cbfs_boot_locate(&file, prog_name(&verstage), NULL)) die("failed to load verstage"); cbfs_file_data(prog_rdev(&verstage), &file); if (cbfs_prog_stage_load(&verstage)) die("failed to load verstage"); /* verify and select a slot */ prog_run(&verstage); /* This is not actually possible to hit this condition at * runtime, but this provides a hint to the compiler for dead * code elimination below. */ if (!IS_ENABLED(CONFIG_VBOOT_RETURN_FROM_VERSTAGE)) return; car_set_var(vboot_executed, 1); } /* * Fill in vboot cbmem objects before moving to ramstage so all * downstream users have access to vboot results. This path only * applies to platforms employing VBOOT_STARTS_IN_ROMSTAGE because * cbmem comes online prior to vboot verification taking place. For * other platforms the vboot cbmem objects are initialized when * cbmem comes online. */ if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) { vb2_store_selected_region(); vboot_fill_handoff(); } }