예제 #1
0
파일: fmap.c 프로젝트: tidatida/coreboot
int find_fmap_entry(const char name[], void **pointer)
{
	MAYBE_STATIC const struct fmap *fmap = NULL;
	const struct fmap_area *area;
	void *base = NULL;

	if (!fmap)
		fmap = fmap_find();

	area = find_fmap_area(fmap, name);

	if (!area)
		return -1;

	/* Right now cros_bundle_firmware does not write a valid
	 * base address into the FMAP. Hence, if base is 0, assume
	 * 4GB-8MB as base address.
	 */
	if (fmap->base) {
		base = (void *)(unsigned long)fmap->base;
		printk(BIOS_DEBUG, "FMAP: %s base at %p\n", name, base);
	} else {
#if CONFIG_ARCH_X86
		base = (void *)(0 - CONFIG_ROM_SIZE);
		printk(BIOS_WARNING, "FMAP: No valid base address, using"
				" 0x%p\n", base);
#endif
	}

	*pointer = (void*) ((uintptr_t)base + area->offset);
	printk(BIOS_DEBUG, "FMAP: %s at %p (offset %x)\n",
	       name, *pointer, area->offset);
	return area->size;
}
예제 #2
0
partitioned_file_t *partitioned_file_create(const char *filename,
							struct buffer *flashmap)
{
	assert(filename);
	assert(flashmap);
	assert(flashmap->data);

	if (fmap_find((const uint8_t *)flashmap->data, flashmap->size) != 0) {
		ERROR("Attempted to create a partitioned image out of something that isn't an FMAP\n");
		return NULL;
	}
	struct fmap *bootstrap_fmap = (struct fmap *)flashmap->data;

	const struct fmap_area *fmap_area =
			fmap_find_area(bootstrap_fmap, SECTION_NAME_FMAP);
	if (!fmap_area) {
		ERROR("Provided FMAP missing '%s' region\n", SECTION_NAME_FMAP);
		return NULL;
	}

	if (count_selected_fmap_entries(bootstrap_fmap,
		partitioned_file_fmap_select_children_of, fmap_area)) {
		ERROR("Provided FMAP's '%s' region contains other regions\n",
							SECTION_NAME_FMAP);
		return NULL;
	}

	int fmap_len = fmap_size(bootstrap_fmap);
	if (fmap_len < 0) {
		ERROR("Unable to determine size of provided FMAP\n");
		return NULL;
	}
	assert((size_t)fmap_len <= flashmap->size);
	if ((uint32_t)fmap_len > fmap_area->size) {
		ERROR("Provided FMAP's '%s' region needs to be at least %d bytes\n",
						SECTION_NAME_FMAP, fmap_len);
		return NULL;
	}

	partitioned_file_t *file = partitioned_file_create_flat(filename,
							bootstrap_fmap->size);
	if (!file)
		return NULL;

	struct buffer fmap_region;
	buffer_splice(&fmap_region, &file->buffer, fmap_area->offset, fmap_area->size);
	memcpy(fmap_region.data, bootstrap_fmap, fmap_len);
	if (!partitioned_file_write_region(file, &fmap_region)) {
		partitioned_file_close(file);
		return NULL;
	}
	file->fmap = (struct fmap *)(file->buffer.data + fmap_area->offset);

	return file;
}
예제 #3
0
int ft_show_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
{
	FmapHeader *fmap;
	FmapAreaHeader *ah = 0;
	char ah_name[FMAP_NAMELEN + 1];
	enum bios_component c;
	int retval = 0;
	struct bios_state_s state;

	memset(&state, 0, sizeof(state));

	printf("BIOS:                    %s\n", name);

	/* We've already checked, so we know this will work. */
	fmap = fmap_find(buf, len);
	for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
		/* We know one of these will work, too */
		if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
		    fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
			/* But the file might be truncated */
			fmap_limit_area(ah, len);
			/* The name is not necessarily null-terminated */
			snprintf(ah_name, sizeof(ah_name), "%s", ah->area_name);

			/* Update the state we're passing around */
			state.c = c;
			state.area[c].offset = ah->area_offset;
			state.area[c].buf = buf + ah->area_offset;
			state.area[c].len = ah->area_size;

			Debug("%s() showing FMAP area %d (%s),"
			      " offset=0x%08x len=0x%08x\n",
			      __func__, c, ah_name,
			      ah->area_offset, ah->area_size);

			/* Go look at it. */
			if (fmap_show_fn[c])
				retval += fmap_show_fn[c](ah_name,
							  state.area[c].buf,
							  state.area[c].len,
							  &state);
		}
	}

	return retval;
}
예제 #4
0
partitioned_file_t *partitioned_file_reopen(const char *filename,
				partitioned_file_flat_decider_t flat_override)
{
	assert(filename);

	partitioned_file_t *file = reopen_flat_file(filename);
	if (!file)
		return NULL;

	if (flat_override && flat_override(&file->buffer)) {
		INFO("Opening image as a flat file in response to explicit request\n");
		return file;
	}

	long fmap_region_offset = fmap_find((const uint8_t *)file->buffer.data,
							file->buffer.size);
	if (fmap_region_offset < 0) {
		INFO("Opening image as a flat file because it doesn't contain any FMAP\n");
		return file;
	}
	file->fmap = (struct fmap *)(file->buffer.data + fmap_region_offset);

	if (file->fmap->size > file->buffer.size) {
		int fmap_region_size = fmap_size(file->fmap);
		ERROR("FMAP records image size as %u, but file is only %zu bytes%s\n",
					file->fmap->size, file->buffer.size,
						fmap_region_offset == 0 &&
				(signed)file->buffer.size == fmap_region_size ?
				" (is it really an image, or *just* an FMAP?)" :
					" (did something truncate this file?)");
		partitioned_file_close(file);
		return NULL;
	}

	const struct fmap_area *fmap_fmap_entry =
				fmap_find_area(file->fmap, SECTION_NAME_FMAP);
	if ((long)fmap_fmap_entry->offset != fmap_region_offset) {
		ERROR("FMAP's '%s' section doesn't point back to FMAP start (did something corrupt this file?)\n",
							SECTION_NAME_FMAP);
		partitioned_file_close(file);
		return NULL;
	}

	return file;
}
예제 #5
0
파일: fmap.c 프로젝트: Tydus/flashmap
/* get SHA1 sum of all static regions described by the flashmap and copy into
   *digest (which will be allocated and must be freed by the caller),  */
int fmap_get_csum(const uint8_t *image, unsigned int image_len, uint8_t **digest)
{
	int i;
	struct fmap *fmap;
	int fmap_offset;
	SHA_CTX ctx;

	if ((image == NULL))
		return -1;

	if ((fmap_offset = fmap_find(image, image_len)) < 0)
		return -1;
	fmap = (struct fmap *)(image + fmap_offset);

	SHA_init(&ctx);

	/* Iterate through flash map and calculate the checksum piece-wise. */
	for (i = 0; i < fmap->nareas; i++) {
		/* skip non-static areas */
		if (!(fmap->areas[i].flags & FMAP_AREA_STATIC))
			continue;

		/* sanity check the offset */
		if (fmap->areas[i].size + fmap->areas[i].offset > image_len) {
			fprintf(stderr,
			        "(%s) invalid parameter detected in area %d\n",
			        __func__, i);
			return -1;
		}

		SHA_update(&ctx,
		           image + fmap->areas[i].offset,
		           fmap->areas[i].size);
	}

	SHA_final(&ctx);
	*digest = malloc(SHA_DIGEST_SIZE);
	memcpy(*digest, ctx.buf, SHA_DIGEST_SIZE);

	return SHA_DIGEST_SIZE;
}
예제 #6
0
enum futil_file_type ft_recognize_bios_image(uint8_t *buf, uint32_t len)
{
	FmapHeader *fmap;
	enum bios_component c;

	fmap = fmap_find(buf, len);
	if (!fmap)
		return FILE_TYPE_UNKNOWN;

	for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
		if (!fmap_find_by_name(buf, len, fmap, fmap_name[c], 0))
			break;
	if (c == NUM_BIOS_COMPONENTS)
		return FILE_TYPE_BIOS_IMAGE;

	for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
		if (!fmap_find_by_name(buf, len, fmap, fmap_oldname[c], 0))
			break;
	if (c == NUM_BIOS_COMPONENTS)
		return FILE_TYPE_OLD_BIOS_IMAGE;

	return FILE_TYPE_UNKNOWN;
}
예제 #7
0
static int fmap_find_test(struct fmap *fmap)
{
	uint8_t *buf;
	size_t total_size, offset;

	status = fail;

	/*
	 * Note: In these tests, we'll use fmap_find() and control usage of
	 * lsearch and bsearch by using a power-of-2 total_size. For lsearch,
	 * use total_size - 1. For bsearch, use total_size.
	 */

	total_size = 0x100000;
	buf = calloc(total_size, 1);

	/* test if image length is zero */
	if (fmap_find(buf, 0) >= 0) {
		printf("FAILURE: failed to abort on zero-length image\n");
		goto fmap_find_test_exit;
	}

	/* test if no fmap exists */
	if (fmap_find(buf, total_size - 1) >= 0) {
		printf("FAILURE: lsearch returned false positive\n");
		goto fmap_find_test_exit;
	}
	if (fmap_find(buf, total_size) >= 0) {
		printf("FAILURE: bsearch returned false positive\n");
		goto fmap_find_test_exit;
	}

	/* simple test case: fmap at (total_size / 2) + 1 */
	offset = (total_size / 2) + 1;
	memcpy(&buf[offset], fmap, fmap_size(fmap));

	if ((unsigned)fmap_find(buf, total_size - 1) != offset) {
		printf("FAILURE: lsearch failed to find fmap\n");
		goto fmap_find_test_exit;
	}
	if ((unsigned)fmap_find(buf, total_size) != offset) {
		printf("FAILURE: bsearch failed to find fmap\n");
		goto fmap_find_test_exit;
	}

	/* test bsearch if offset is at 0 */
	offset = 0;
	memset(buf, 0, total_size);
	memcpy(buf, fmap, fmap_size(fmap));
	if ((unsigned)fmap_find(buf, total_size) != offset) {
		printf("FAILURE: bsearch failed to find fmap at offset 0\n");
		goto fmap_find_test_exit;
	}

	/* test overrun detection */
	memset(buf, 0, total_size);
	memcpy(&buf[total_size - fmap_size(fmap) + 1],
	       fmap,
	       fmap_size(fmap) + 1);
	if (fmap_find(buf, total_size - 1) >= 0) {
		printf("FAILURE: lsearch failed to catch overrun\n");
		goto fmap_find_test_exit;
	}
	if (fmap_find(buf, total_size) >= 0) {
		printf("FAILURE: bsearch failed to catch overrun\n");
		goto fmap_find_test_exit;
	}

	status = pass;
fmap_find_test_exit:
	free(buf);
	return status;
}