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); }
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; }
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 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 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, ®ion_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; }
static int cbfs_locate_payload(struct prog *payload) { void *buffer; size_t size; const int type = CBFS_TYPE_PAYLOAD; buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name, type, &size); if (buffer == NULL) return -1; prog_set_area(payload, buffer, size); return 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, ®ion_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; }