void *cbfs_get_contents(struct cbfs_handle *handle, size_t *size, size_t limit) { struct cbfs_media *m = &handle->media; size_t on_media_size = handle->content_size; int algo = CBFS_COMPRESS_NONE; void *ret = NULL; size_t dummy_size; if (!size) size = &dummy_size; struct cbfs_file_attr_compression *comp = cbfs_get_attr(handle, CBFS_FILE_ATTR_TAG_COMPRESSION); if (comp) { algo = ntohl(comp->compression); DEBUG("File '%s' is compressed (alg=%d)\n", name, algo); *size = ntohl(comp->decompressed_size); /* TODO: Implement partial decompression with |limit| */ } if (algo == CBFS_COMPRESS_NONE) { if (limit != 0 && limit < on_media_size) { *size = limit; on_media_size = limit; } else { *size = on_media_size; } } void *data = m->map(m, handle->media_offset + handle->content_offset, on_media_size); if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) return NULL; ret = malloc(*size); if (ret != NULL && !cbfs_decompress(algo, data, ret, *size)) { free(ret); ret = NULL; } m->unmap(m, data); return ret; }
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; }
void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type, size_t *sz) { struct cbfs_media default_media; if (media == CBFS_DEFAULT_MEDIA) { media = &default_media; if (init_default_cbfs_media(media) != 0) { ERROR("Failed to initialize default media.\n"); return NULL; } } struct cbfs_file *file = cbfs_get_file(media, name); if (sz) *sz = 0; if (file == NULL) { ERROR("Could not find file '%s'.\n", name); return NULL; } if (ntohl(file->type) != type) { ERROR("File '%s' is of type %x, but we requested %x.\n", name, ntohl(file->type), type); return NULL; } void *file_content = (void *)CBFS_SUBHEADER(file); struct cbfs_file_attribute *attr = cbfs_file_find_attr(file, CBFS_FILE_ATTR_TAG_COMPRESSION); size_t final_size = ntohl(file->len); int compression_algo = CBFS_COMPRESS_NONE; if (attr) { struct cbfs_file_attr_compression *comp = (struct cbfs_file_attr_compression *)attr; compression_algo = ntohl(comp->compression); DEBUG("File '%s' is compressed (alg=%d)\n", name, compression_algo); final_size = ntohl(comp->decompressed_size); } void *dst = malloc(final_size); if (dst == NULL) goto err; if (!cbfs_decompress(compression_algo, file_content, dst, final_size)) goto err; if (sz) *sz = final_size; media->unmap(media, file); return dst; err: media->unmap(media, file); free(dst); return NULL; }