Ejemplo n.º 1
0
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");
	}
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
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();
    }
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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();
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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();
	}
}