vboot2: load decompressed stage directly to load address
this change allows vboot_load_stage to load a decompressed stage directly to the load address without using the cbfs cache. BUG=None TEST=Booted Nyan Blaze. BRANCH=None Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Change-Id: I76530276ff9a87b44f98a33f2c34bd5b2de6888f Reviewed-on: https://chromium-review.googlesource.com/219028 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
parent
24a9ebfda3
commit
0ad6f7fee9
3 changed files with 37 additions and 39 deletions
|
|
@ -57,6 +57,7 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
|
|||
uint16_t device, void * dest);
|
||||
void *cbfs_load_payload(struct cbfs_media *media, const char *name);
|
||||
void *cbfs_load_stage(struct cbfs_media *media, const char *name);
|
||||
void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset);
|
||||
|
||||
/* Simple buffer for streaming media. */
|
||||
struct cbfs_simple_buffer {
|
||||
|
|
|
|||
|
|
@ -169,10 +169,50 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
|
|||
|
||||
#else
|
||||
|
||||
void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset)
|
||||
{
|
||||
struct cbfs_stage stage;
|
||||
|
||||
DEBUG("reading stage header: offset=0x%x len=%d type=%d offset=0x%x\n",
|
||||
offset, file.len, file.type, file.offset);
|
||||
if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage)) {
|
||||
ERROR("ERROR: failed to read stage header\n");
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
LOG("loading stage @ 0x%llx (%d bytes), entry @ 0x%llx\n",
|
||||
stage.load, stage.memlen, stage.entry);
|
||||
|
||||
/* Stages rely the below clearing so that the bss is initialized. */
|
||||
memset((void *)(uintptr_t)stage.load, 0, stage.memlen);
|
||||
|
||||
if (stage.compression == CBFS_COMPRESS_NONE) {
|
||||
if (cbfs_read(media, (void *)(uintptr_t)stage.load,
|
||||
offset + sizeof(stage), stage.len) != stage.len) {
|
||||
ERROR("ERROR: Reading stage failed.\n");
|
||||
return (void *)-1;
|
||||
}
|
||||
} else {
|
||||
void *data = media->map(media, offset + sizeof(stage),
|
||||
stage.len);
|
||||
if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
|
||||
ERROR("ERROR: Mapping stage failed.\n");
|
||||
return (void *)-1;
|
||||
}
|
||||
if (cbfs_decompress(stage.compression, data,
|
||||
(void *)(uintptr_t)stage.load, stage.len))
|
||||
return (void *)-1;
|
||||
media->unmap(media, data);
|
||||
}
|
||||
|
||||
DEBUG("stage loaded\n");
|
||||
|
||||
return (void *)(uintptr_t)stage.entry;
|
||||
}
|
||||
|
||||
void *cbfs_load_stage(struct cbfs_media *media, const char *name)
|
||||
{
|
||||
struct cbfs_media default_media;
|
||||
struct cbfs_stage stage;
|
||||
struct cbfs_file file;
|
||||
ssize_t offset;
|
||||
|
||||
|
|
@ -182,39 +222,7 @@ void *cbfs_load_stage(struct cbfs_media *media, const char *name)
|
|||
if (offset < 0 || file.type != CBFS_TYPE_STAGE)
|
||||
return (void *)-1;
|
||||
|
||||
DEBUG("reading stage header: offset=0x%x len=%d type=%d offset=0x%x\n",
|
||||
offset, file.len, file.type, file.offset);
|
||||
if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage))
|
||||
return (void *)-1;
|
||||
|
||||
LOG("loading stage %s @ 0x%llx (%d bytes), entry @ 0x%llx\n",
|
||||
name,
|
||||
stage.load, stage.memlen,
|
||||
stage.entry);
|
||||
|
||||
/* Stages rely the below clearing so that the bss is initialized. */
|
||||
memset((void *)(uintptr_t)stage.load, 0, stage.memlen);
|
||||
|
||||
if (stage.compression == CBFS_COMPRESS_NONE) {
|
||||
if (cbfs_read(media, (void *)(uintptr_t)stage.load,
|
||||
offset + sizeof(stage), stage.len) != stage.len)
|
||||
return (void *)-1;
|
||||
} else {
|
||||
void *data = media->map(media, offset + sizeof(stage),
|
||||
stage.len);
|
||||
if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
|
||||
ERROR("ERROR: Mapping %s failed.\n", name);
|
||||
return (void *)-1;
|
||||
}
|
||||
if (cbfs_decompress(stage.compression, data,
|
||||
(void *)(uintptr_t)stage.load, stage.len))
|
||||
return (void *)-1;
|
||||
media->unmap(media, data);
|
||||
}
|
||||
|
||||
DEBUG("stage %s loaded\n", name);
|
||||
|
||||
return (void *)(uintptr_t)stage.entry;
|
||||
return cbfs_load_stage_by_offset(media, offset);
|
||||
}
|
||||
#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
|
||||
|
||||
|
|
|
|||
|
|
@ -222,9 +222,10 @@ void *vboot_load_stage(int stage_index,
|
|||
struct vboot_region *fw_main,
|
||||
struct vboot_components *fw_info)
|
||||
{
|
||||
struct cbfs_stage *stage;
|
||||
struct cbfs_media default_media, *media = &default_media;
|
||||
uintptr_t fc_addr;
|
||||
uint32_t fc_size;
|
||||
void *entry;
|
||||
|
||||
if (stage_index >= fw_info->num_components) {
|
||||
printk(BIOS_INFO, "invalid stage index\n");
|
||||
|
|
@ -239,27 +240,15 @@ void *vboot_load_stage(int stage_index,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Loading to cbfs cache. This stage data must be retained until it's
|
||||
* decompressed. */
|
||||
stage = vboot_get_region(fc_addr, fc_size, NULL);
|
||||
init_default_cbfs_media(media);
|
||||
|
||||
if (stage == NULL) {
|
||||
printk(BIOS_INFO, "failed to load a stage\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Stages rely the below clearing so that the bss is initialized. */
|
||||
memset((void *) (uintptr_t)stage->load, 0, stage->memlen);
|
||||
|
||||
if (cbfs_decompress(stage->compression,
|
||||
(unsigned char *)stage + sizeof(*stage),
|
||||
(void *) (uintptr_t) stage->load,
|
||||
stage->len)) {
|
||||
printk(BIOS_INFO, "failed to decompress a stage\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)(uintptr_t)stage->entry;
|
||||
/* we're making cbfs access offset outside of the region managed by
|
||||
* cbfs. this works because cbfs_load_stage_by_offset does not check
|
||||
* the offset. */
|
||||
entry = cbfs_load_stage_by_offset(media, fc_addr);
|
||||
if (entry == (void *)-1)
|
||||
entry = NULL;
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct vb2_working_data * const vboot_get_working_data(void)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue