Ejemplo n.º 1
0
bool partitioned_file_read_region(struct buffer *dest,
			const partitioned_file_t *file, const char *region)
{
	assert(dest);
	assert(file);
	assert(file->buffer.data);
	assert(region);

	if (file->fmap) {
		const struct fmap_area *area = fmap_find_area(file->fmap,
									region);
		if (!area) {
			ERROR("Image is missing '%s' region\n", region);
			return false;
		}
		if (area->offset + area->size > file->buffer.size) {
			ERROR("Region '%s' runs off the end of the image file\n",
									region);
			return false;
		}
		buffer_splice(dest, &file->buffer, area->offset, area->size);
	} else {
		if (strcmp(region, SECTION_NAME_PRIMARY_CBFS) != 0) {
			ERROR("This is a legacy image that contains only a CBFS\n");
			return false;
		}
		buffer_clone(dest, &file->buffer);
	}

	return true;
}
Ejemplo n.º 2
0
VbError_t VbExEcGetExpectedRW(enum VbSelectFirmware_t select,
			      const uint8_t **image, int *image_size)
{
	const char *name;

	switch (select) {
	case VB_SELECT_FIRMWARE_A:
		name = "EC_MAIN_A";
		break;
	case VB_SELECT_FIRMWARE_B:
		name = "EC_MAIN_B";
		break;
	default:
		printf("Unrecognized EC firmware requested.\n");
		return VBERROR_UNKNOWN;
	}

	FmapArea area;
	if (fmap_find_area(name, &area)) {
		printf("Didn't find section %s in the fmap.\n", name);
		return VBERROR_UNKNOWN;
	}

	uint32_t size;
	*image = index_subsection(&area, 0, &size);
	*image_size = size;
	if (!*image)
		return VBERROR_UNKNOWN;

	printf("EC-RW firmware address, size are %p, %d.\n",
		*image, *image_size);

	return VBERROR_SUCCESS;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
struct cbfs_media *cbfs_ro_media(void)
{
	FmapArea area;
	struct cbfs_media *media;

	/* The FMAP entries for the RO CBFS are either COREBOOT or BOOT_STUB. */
	if (fmap_find_area("COREBOOT", &area) &&
	    fmap_find_area("BOOT_STUB", &area))
		return NULL;

	media = xmalloc(sizeof(*media));

	libpayload_init_default_cbfs_media(media);

	media->context = xmalloc(sizeof(area));

	memcpy(media->context, &area, sizeof(area));

	return media;
}
Ejemplo n.º 5
0
bool partitioned_file_region_contains_nested(const partitioned_file_t *file,
							const char *region)
{
	assert(file);
	assert(region);

	if (!file->fmap)
		return false;
	const struct fmap_area *area = fmap_find_area(file->fmap, region);
	return area && partitioned_file_fmap_count(file,
			partitioned_file_fmap_select_children_of, area);
}
Ejemplo n.º 6
0
int gbb_copy_in_bmp_block(void)
{
	FmapArea area;
	if (fmap_find_area("GBB", &area)) {
		printf("Couldn't find the GBB.\n");
		return 1;
	}

	GoogleBinaryBlockHeader *header =
		(GoogleBinaryBlockHeader *)cparams.gbb_data;

	if (!gbb_copy_in(area.offset, header->bmpfv_offset,
			 header->bmpfv_size))
		return 1;

	return 0;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
static int gbb_init(void)
{
	if (gbb_initialized)
		return 0;

	FmapArea area;
	if (fmap_find_area("GBB", &area)) {
		printf("Couldn't find the GBB.\n");
		return 1;
	}

	if (area.size > CONFIG_GBB_COPY_SIZE) {
		printf("Not enough room for a copy of the GBB.\n");
		return 1;
	}

	cparams.gbb_size = area.size;
	cparams.gbb_data = &_gbb_copy_start;
	memset(cparams.gbb_data, 0, cparams.gbb_size);

	uint32_t offset = area.offset;

	GoogleBinaryBlockHeader *header =
		gbb_copy_in(offset, 0, sizeof(GoogleBinaryBlockHeader));
	if (!header)
		return 1;
	printf("The GBB signature is at %p and is: ", header->signature);
	for (int i = 0; i < GBB_SIGNATURE_SIZE; i++)
		printf(" %02x", header->signature[i]);
	printf("\n");

	if (!gbb_copy_in(offset, header->hwid_offset, header->hwid_size))
		return 1;

	if (!gbb_copy_in(offset, header->rootkey_offset, header->rootkey_size))
		return 1;

	if (!gbb_copy_in(offset, header->recovery_key_offset,
			 header->recovery_key_size))
		return 1;

	gbb_initialized = 1;
	return 0;
}
Ejemplo n.º 9
0
int gbb_clear_flags(void)
{
	/* If WP is enabled, cannot write to RO-GBB. */
	if (flash_is_wp_enabled() != 0)
		return 1;

	if (gbb_init() != 0)
		return 1;

	FmapArea area;
	if (fmap_find_area("GBB", &area)) {
		printf("Couldn't find the GBB.\n");
		return 1;
	}

	GoogleBinaryBlockHeader *header = cparams.gbb_data;
	header->flags = 0;
	gbb_copy_out(area.offset, 0, sizeof(*header));
	return 0;
}
Ejemplo n.º 10
0
VbError_t VbExEcGetExpectedRWHash(enum VbSelectFirmware_t select,
				  const uint8_t **hash, int *hash_size)
{
	const char *name;

	switch (select) {
	case VB_SELECT_FIRMWARE_A:
		name = "FW_MAIN_A";
		break;
	case VB_SELECT_FIRMWARE_B:
		name = "FW_MAIN_B";
		break;
	default:
		printf("Unrecognized EC hash requested.\n");
		return VBERROR_UNKNOWN;
	}

	FmapArea area;
	if (fmap_find_area(name, &area)) {
		printf("Didn't find section %s in the fmap.\n", name);
		return VBERROR_UNKNOWN;
	}

	uint32_t size;
	*hash = index_subsection(&area, 1, &size);
	*hash_size = size;
	if (!*hash)
		return VBERROR_UNKNOWN;

	printf("EC-RW hash address, size are %p, %d.\n",
		*hash, *hash_size);

	printf("Hash = ");
	for (int i = 0; i < *hash_size; i++)
		printf("%02x", (*hash)[i]);
	printf("\n");

	return VBERROR_SUCCESS;
}
Ejemplo n.º 11
0
/* this test re-allocates the fmap, so it gets a double-pointer */
static int fmap_append_area_test(struct fmap **fmap)
{
	int total_size;
	uint16_t nareas_orig;
	/* test_area will be used by fmap_csum_test and find_area_test */
	struct fmap_area test_area = {
		.offset = 0x400,
		.size = 0x10000,
		.name = "test_area_1",
		.flags = FMAP_AREA_STATIC,
	};

	status = fail;

	if ((fmap_append_area(NULL, 0, 0, test_area.name, 0) >= 0) ||
	    (fmap_append_area(fmap, 0, 0, NULL, 0) >= 0)) {
		printf("FAILURE: failed to abort on NULL pointer input\n");
		goto fmap_append_area_test_exit;
	}

	nareas_orig = (*fmap)->nareas;
	(*fmap)->nareas = ~(0);
	if (fmap_append_area(fmap, 0, 0, (const uint8_t *)"foo", 0) >= 0) {
		printf("FAILURE: failed to abort with too many areas\n");
		goto fmap_append_area_test_exit;
	}
	(*fmap)->nareas = nareas_orig;

	total_size = sizeof(**fmap) + sizeof(test_area);
	if (fmap_append_area(fmap,
			     test_area.offset,
			     test_area.size,
			     test_area.name,
			     test_area.flags
			     ) != total_size) {
		printf("failed to append area\n");
		goto fmap_append_area_test_exit;
	}

	if ((*fmap)->nareas != 1) {
		printf("FAILURE: failed to increment number of areas\n");
		goto fmap_append_area_test_exit;
	}

	status = pass;
fmap_append_area_test_exit:
	return status;
}

static int fmap_find_area_test(struct fmap *fmap)
{
	status = fail;
	char area_name[] = "test_area_1";

	if (fmap_find_area(NULL, area_name) ||
	    fmap_find_area(fmap, NULL)) {
		printf("FAILURE: failed to abort on NULL pointer input\n");
		goto fmap_find_area_test_exit;
	}

	if (fmap_find_area(fmap, area_name) == NULL) {
		printf("FAILURE: failed to find \"%s\"\n", area_name);
		goto fmap_find_area_test_exit;
	}

	status = pass;
fmap_find_area_test_exit:
	return status;
}
Ejemplo n.º 12
0
int main(void)
{
	NetbootParam *param;

	// Initialize some consoles.
	serial_console_init();
	cbmem_console_init();
	video_console_init();
	input_init();

	printf("\n\nStarting netboot on " CONFIG_BOARD "...\n");

	timestamp_init();

	if (run_init_funcs())
		halt();

	// Make sure graphics are available if they aren't already.
	enable_graphics();

	dc_usb_initialize();

	srand(timer_raw_value());

	printf("Looking for network device... ");
	while (!net_get_device())
		usb_poll();
	printf("done.\n");

	printf("Waiting for link... ");
	int ready = 0;
	while (!ready) {
		if (net_ready(&ready))
			halt();
	}
	mdelay(200);	// some dongles need more time than they think
	printf("done.\n");

	// Start up the network stack.
	uip_init();

	// Plug in the MAC address.
	const uip_eth_addr *mac_addr = net_get_mac();
	if (!mac_addr)
		halt();
	printf("MAC: ");
	print_mac_addr(mac_addr);
	printf("\n");
	uip_setethaddr(*mac_addr);

	// Find out who we are.
	uip_ipaddr_t my_ip, next_ip, server_ip;
	const char *dhcp_bootfile;
	while (dhcp_request(&next_ip, &server_ip, &dhcp_bootfile))
		printf("Dhcp failed, retrying.\n");

	printf("My ip is ");
	uip_gethostaddr(&my_ip);
	print_ip_addr(&my_ip);
	printf("\nThe DHCP server ip is ");
	print_ip_addr(&server_ip);
	printf("\n");

	// Retrieve settings from the shared data area.
	FmapArea shared_data;
	if (fmap_find_area("SHARED_DATA", &shared_data)) {
		printf("Couldn't find the shared data area.\n");
		halt();
	}
	void *data = flash_read(shared_data.offset, shared_data.size);
	netboot_params_init(data, shared_data.size);

	// Get TFTP server IP and file name from params with DHCP as fallback
	uip_ipaddr_t *tftp_ip = NULL;
	param = netboot_params_val(NetbootParamIdTftpServerIp);
	if (param->data && param->size >= sizeof(uip_ipaddr_t)) {
		tftp_ip = (uip_ipaddr_t *)param->data;
		printf("TFTP server IP set from firmware parameters: ");
	} else {
		tftp_ip = &next_ip;
		printf("TFTP server IP supplied by DHCP server: ");
	}
	print_ip_addr(tftp_ip);
	printf("\n");

	const char *bootfile = NULL;
	param = netboot_params_val(NetbootParamIdBootfile);
	if (param->data && param->size > 0 && strnlen((const char *)param->data,
			param->size) < param->size) {
		bootfile = (const char *)param->data;
		printf("Bootfile set from firmware parameters: %s\n", bootfile);
	} else {
		bootfile = dhcp_bootfile;
		printf("Bootfile supplied by DHCP server: %s\n", bootfile);
	}

	// Download the bootfile.
	uint32_t size;
	if (tftp_read(payload, tftp_ip, bootfile, &size, MaxPayloadSize)) {
		printf("Tftp failed.\n");
		if (dhcp_release(server_ip))
			printf("Dhcp release failed.\n");
		halt();
	}
	printf("The bootfile was %d bytes long.\n", size);

	// Use command line from params when present (added to the default).
	param = netboot_params_val(NetbootParamIdKernelArgs);
	if (param->data && param->size > 0 && *(char *)param->data != '\0') {
		cmd_line[sizeof(def_cmd_line) - 1] = ' ';
		strncpy(&cmd_line[sizeof(def_cmd_line)], param->data,
			sizeof(cmd_line) - sizeof(def_cmd_line));
		printf("Command line set from firmware parameters.\n");
	// Otherwise, try to fetch it dynamically as a TFTP file.
	} else if (!(tftp_read(cmd_line, tftp_ip, "cmdline." CONFIG_BOARD,
			       &size, sizeof(cmd_line) - 1))) {
		while (cmd_line[size - 1] <= ' ')  // strip trailing whitespace
			if (!--size) break;	   // and control chars (\n, \r)
		cmd_line[size] = '\0';
		while (size--)			   // replace inline control
			if (cmd_line[size] < ' ')  // chars with spaces
				cmd_line[size] = ' ';
		printf("Command line loaded dynamically from TFTP server.\n");
	// If the file doesn't exist, finally fall back to built-in default.
	} else {
		printf("No command line from TFTP, falling back to default.\n");
	}
	cmd_line[sizeof(cmd_line) - 1] = '\0';

	// We're done on the network, so release our IP.
	if (dhcp_release(server_ip)) {
		printf("Dhcp release failed.\n");
		halt();
	}

	// Add tftp server IP into command line.
	static const char def_tftp_cmdline[] = " tftpserverip=xxx.xxx.xxx.xxx";
	const int tftp_cmdline_def_size = sizeof(def_tftp_cmdline) - 1;
	int cmd_line_size = strlen(cmd_line);
	if (cmd_line_size + tftp_cmdline_def_size >= sizeof(cmd_line)) {
		printf("Out of space adding TFTP server IP to the command line.\n");
		return 1;
	}
	sprintf(&cmd_line[cmd_line_size], " tftpserverip=%d.%d.%d.%d",
		uip_ipaddr1(tftp_ip), uip_ipaddr2(tftp_ip),
		uip_ipaddr3(tftp_ip), uip_ipaddr4(tftp_ip));
	printf("The command line is: %s\n", cmd_line);

	// Boot.
	boot(payload, cmd_line, NULL, NULL);

	// We should never get here.
	printf("Got to the end!\n");
	halt();
	return 0;
}