void stage_cache_load_stage(int stage_id, struct prog *stage)
{
	struct stage_cache *meta;
	const struct cbmem_entry *e;
	void *c;
	size_t size;
	void *load_addr;

	prog_set_entry(stage, NULL, NULL);

	meta = cbmem_find(CBMEM_ID_STAGEx_META + stage_id);
	if (meta == NULL)
		return;

	e = cbmem_entry_find(CBMEM_ID_STAGEx_CACHE + stage_id);

	if (e == NULL)
		return;

	c = cbmem_entry_start(e);
	size = cbmem_entry_size(e);
	load_addr = (void *)(uintptr_t)meta->load_addr;

	memcpy(load_addr, c, size);

	prog_set_area(stage, load_addr, size);
	prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr, NULL);
}
Beispiel #2
0
int fsp_relocate(struct prog *fsp_relocd, const struct region_device *fsp_src)
{
	void *new_loc;
	void *fih;
	ssize_t fih_offset;
	size_t size = region_device_sz(fsp_src);

	new_loc = cbmem_add(CBMEM_ID_REFCODE, size);

	if (new_loc == NULL) {
		printk(BIOS_ERR, "ERROR: Unable to load FSP into memory.\n");
		return -1;
	}

	if (rdev_readat(fsp_src, new_loc, 0, size) != size) {
		printk(BIOS_ERR, "ERROR: Can't read FSP's region device.\n");
		return -1;
	}

	fih_offset = fsp1_1_relocate((uintptr_t)new_loc, new_loc, size);

	if (fih_offset <= 0) {
		printk(BIOS_ERR, "ERROR: FSP relocation faiulre.\n");
		return -1;
	}

	fih = (void *)((uint8_t *)new_loc + fih_offset);

	prog_set_area(fsp_relocd, new_loc, size);
	prog_set_entry(fsp_relocd, fih, NULL);

	return 0;
}
Beispiel #3
0
void stage_cache_load_stage(int stage_id, struct prog *stage)
{
	struct imd *imd;
	struct stage_cache *meta;
	const struct imd_entry *e;
	void *c;
	size_t size;

	imd = imd_get();
	e = imd_entry_find(imd, CBMEM_ID_STAGEx_META + stage_id);
	if (e == NULL) {
		printk(BIOS_DEBUG, "Error: Can't find %x metadata in imd\n",
				CBMEM_ID_STAGEx_META + stage_id);
		return;
	}

	meta = imd_entry_at(imd, e);

	e = imd_entry_find(imd, CBMEM_ID_STAGEx_CACHE + stage_id);

	if (e == NULL) {
		printk(BIOS_DEBUG, "Error: Can't find stage_cache %x in imd\n",
				CBMEM_ID_STAGEx_CACHE + stage_id);
		return;
	}

	c = imd_entry_at(imd, e);
	size = imd_entry_size(imd, e);

	memcpy((void *)(uintptr_t)meta->load_addr, c, size);

	prog_set_area(stage, (void *)(uintptr_t)meta->load_addr, size);
	prog_set_entry(stage, (void *)(uintptr_t)meta->entry_addr,
			(void *)(uintptr_t)meta->arg);
}
void payload_load(void)
{
	int i;
	const struct prog_loader_ops *ops;
	struct prog *payload = &global_payload;

	for (i = 0; i < ARRAY_SIZE(payload_ops); i++) {
		ops = payload_ops[i];
		if (ops->prepare(payload) < 0) {
			printk(BIOS_DEBUG, "%s: could not locate payload.\n",
				ops->name);
			continue;
		}
		printk(BIOS_DEBUG, "%s: located payload @ %p, %zu bytes.\n",
			ops->name, prog_start(payload), prog_size(payload));
		break;
	}

	if (i == ARRAY_SIZE(payload_ops))
		goto out;

	mirror_payload(payload);

	/* Pass cbtables to payload if architecture desires it. */
	prog_set_entry(payload, selfload(payload),
			cbmem_find(CBMEM_ID_CBTABLE));

out:
	if (prog_entry(payload) == NULL)
		die("Payload not loaded.\n");
}
Beispiel #5
0
int rmodule_stage_load(struct rmod_stage_load *rsl)
{
	struct rmodule rmod_stage;
	size_t region_size;
	char *stage_region;
	int rmodule_offset;
	int load_offset;
	struct cbfs_stage stage;
	void *rmod_loc;
	struct region_device *fh;

	if (rsl->prog == NULL || prog_name(rsl->prog) == NULL)
		return -1;

	fh = prog_rdev(rsl->prog);

	if (rdev_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage))
		return -1;

	rmodule_offset =
		rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE,
		                    stage.memlen, &region_size, &load_offset);

	stage_region = cbmem_add(rsl->cbmem_id, region_size);

	if (stage_region == NULL)
		return -1;

	rmod_loc = &stage_region[rmodule_offset];

	printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n",
	       prog_name(rsl->prog), rmod_loc, stage.memlen);

	if (!cbfs_load_and_decompress(fh, sizeof(stage), stage.len, rmod_loc,
				      stage.memlen, stage.compression))
		return -1;

	if (rmodule_parse(rmod_loc, &rmod_stage))
		return -1;

	if (rmodule_load(&stage_region[load_offset], &rmod_stage))
		return -1;

	prog_set_area(rsl->prog, rmod_stage.location,
			rmodule_memory_size(&rmod_stage));
	prog_set_entry(rsl->prog, rmodule_entry(&rmod_stage), NULL);

	/* Allow caller to pick up parameters, if available. */
	rsl->params = rmodule_parameters(&rmod_stage);

	return 0;
}
Beispiel #6
0
void payload_load(void)
{
	struct prog *payload = &global_payload;

	timestamp_add_now(TS_LOAD_PAYLOAD);

	if (prog_locate(payload))
		goto out;

	mirror_payload(payload);

	/* Pass cbtables to payload if architecture desires it. */
	prog_set_entry(payload, selfload(payload),
			cbmem_find(CBMEM_ID_CBTABLE));

out:
	if (prog_entry(payload) == NULL)
		die("Payload not loaded.\n");
}
Beispiel #7
0
int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage)
{
	struct rmodule rmod_stage;
	size_t region_size;
	char *stage_region;
	int rmodule_offset;
	int load_offset;

	if (stage == NULL || rsl->prog == NULL || rsl->prog->name == NULL)
		return -1;

	rmodule_offset =
		rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE,
		                    stage->memlen, &region_size, &load_offset);

	stage_region = cbmem_add(rsl->cbmem_id, region_size);

	if (stage_region == NULL)
		return -1;

	printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n",
	       rsl->prog->name, &stage_region[rmodule_offset], stage->memlen);

	if (!cbfs_decompress(stage->compression, &stage[1],
	                    &stage_region[rmodule_offset], stage->len))
		return -1;

	if (rmodule_parse(&stage_region[rmodule_offset], &rmod_stage))
		return -1;

	if (rmodule_load(&stage_region[load_offset], &rmod_stage))
		return -1;

	prog_set_area(rsl->prog, rmod_stage.location,
			rmodule_memory_size(&rmod_stage));
	prog_set_entry(rsl->prog, rmodule_entry(&rmod_stage), NULL);

	return 0;
}
Beispiel #8
0
/*
 * Parse the uImage FIT, choose a configuration and extract images.
 */
void fit_payload(struct prog *payload)
{
	struct device_tree *dt = NULL;
	struct region kernel = {0}, fdt = {0}, initrd = {0};
	void *data;

	data = rdev_mmap_full(prog_rdev(payload));

	if (data == NULL)
		return;

	printk(BIOS_INFO, "FIT: Examine payload %s\n", payload->name);

	struct fit_config_node *config = fit_load(data);

	if (!config || !config->kernel_node) {
		printk(BIOS_ERR, "ERROR: Could not load FIT\n");
		rdev_munmap(prog_rdev(payload), data);
		return;
	}

	if (config->fdt_node) {
		dt = fdt_unflatten(config->fdt_node->data);
		if (!dt) {
			printk(BIOS_ERR,
			       "ERROR: Failed to unflatten the FDT.\n");
			rdev_munmap(prog_rdev(payload), data);
			return;
		}

		dt_apply_fixups(dt);

		/* Insert coreboot specific information */
		add_cb_fdt_data(dt);

		/* Update device_tree */
#if defined(CONFIG_LINUX_COMMAND_LINE)
		fit_update_chosen(dt, (char *)CONFIG_LINUX_COMMAND_LINE);
#endif
		fit_update_memory(dt);
	}

	/* Collect infos for fit_payload_arch */
	kernel.size = config->kernel_node->size;
	fdt.size = dt ? dt_flat_size(dt) : 0;
	initrd.size = config->ramdisk_node ? config->ramdisk_node->size : 0;

	/* Invoke arch specific payload placement and fixups */
	if (!fit_payload_arch(payload, config, &kernel, &fdt, &initrd)) {
		printk(BIOS_ERR, "ERROR: Failed to find free memory region\n");
		bootmem_dump_ranges();
		rdev_munmap(prog_rdev(payload), data);
		return;
	}

	/* Load the images to given position */
	if (config->fdt_node) {
		/* Update device_tree */
		if (config->ramdisk_node)
			fit_add_ramdisk(dt, (void *)initrd.offset, initrd.size);

		pack_fdt(&fdt, dt);
	}

	if (config->ramdisk_node &&
	    extract(&initrd, config->ramdisk_node)) {
		printk(BIOS_ERR, "ERROR: Failed to extract initrd\n");
		prog_set_entry(payload, NULL, NULL);
		rdev_munmap(prog_rdev(payload), data);
		return;
	}

	timestamp_add_now(TS_KERNEL_DECOMPRESSION);

	if (extract(&kernel, config->kernel_node)) {
		printk(BIOS_ERR, "ERROR: Failed to extract kernel\n");
		prog_set_entry(payload, NULL, NULL);
		rdev_munmap(prog_rdev(payload), data);
		return;
	}

	timestamp_add_now(TS_START_KERNEL);

	rdev_munmap(prog_rdev(payload), data);
}