Exemple #1
0
int cbfs_print_entry_info(struct cbfs_image *image, struct cbfs_file *entry,
			  void *arg)
{
	const char *name = CBFS_NAME(entry);
	struct cbfs_payload_segment *payload;
	FILE *fp = (FILE *)arg;

	if (!cbfs_is_valid_entry(image, entry)) {
		ERROR("cbfs_print_entry_info: Invalid entry at 0x%x\n",
		      cbfs_get_entry_addr(image, entry));
		return -1;
	}
	if (!fp)
		fp = stdout;

	fprintf(fp, "%-30s 0x%-8x %-12s %d\n",
		*name ? name : "(empty)",
		cbfs_get_entry_addr(image, entry),
		get_cbfs_entry_type_name(ntohl(entry->type)),
		ntohl(entry->len));

	if (!verbose)
		return 0;

	DEBUG(" cbfs_file=0x%x, offset=0x%x, content_address=0x%x+0x%x\n",
	      cbfs_get_entry_addr(image, entry), ntohl(entry->offset),
	      cbfs_get_entry_addr(image, entry) + ntohl(entry->offset),
	      ntohl(entry->len));

	/* note the components of the subheader may be in host order ... */
	switch (ntohl(entry->type)) {
		case CBFS_COMPONENT_STAGE:
			cbfs_print_stage_info((struct cbfs_stage *)
					      CBFS_SUBHEADER(entry), fp);
			break;

		case CBFS_COMPONENT_PAYLOAD:
			payload  = (struct cbfs_payload_segment *)
					CBFS_SUBHEADER(entry);
			while (payload) {
				/* Stop when PAYLOAD_SEGMENT_ENTRY seen. */
				if (cbfs_print_payload_segment_info(payload,
									fp))
					break;
				payload ++;
			}
			break;
		default:
			break;
	}
	return 0;
}
Exemple #2
0
/* Copy SPD data for on-board memory */
static void copy_spd(struct pei_data *peid)
{
	const int gpio_vector[] = {67, 68, 69, -1};
	int spd_index = get_gpios(gpio_vector);
	struct cbfs_file *spd_file;

	printk(BIOS_DEBUG, "SPD index %d\n", spd_index);
	spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
	if (!spd_file)
		die("SPD data not found.");

	if (ntohl(spd_file->len) <
	    ((spd_index + 1) * sizeof(peid->spd_data[0]))) {
		printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n");
		spd_index = 0;
	}

	if (spd_file->len < sizeof(peid->spd_data[0]))
		die("Missing SPD data.");

	memcpy(peid->spd_data[0],
	       ((char*)CBFS_SUBHEADER(spd_file)) +
	       spd_index * sizeof(peid->spd_data[0]),
	       sizeof(peid->spd_data[0]));
}
Exemple #3
0
void mainboard_romstage_entry(struct romstage_params *rp)
{
	struct cbfs_file *spd_file;
	void *spd_content;
	int dual_channel = 0;

	struct mrc_params mp = {
		.mainboard = {
			.dram_type = DRAM_DDR3L,
			.dram_info_location = DRAM_INFO_SPD_MEM,
			.weaker_odt_settings = 1,
		},
	};

	spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
	if (!spd_file)
		die("SPD data not found.");

	spd_content = get_spd_pointer(CBFS_SUBHEADER(spd_file),
	                              ntohl(spd_file->len) / SPD_SIZE,
	                              &dual_channel);
	mp.mainboard.dram_data[0] = spd_content;
	if (dual_channel)
		mp.mainboard.dram_data[1] = spd_content;

	rp->mrc_params = &mp;
	romstage_common(rp);
}
Exemple #4
0
int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
		      const char *filename)
{
	struct cbfs_file *entry = cbfs_get_entry(image, entry_name);
	struct buffer buffer;
	if (!entry) {
		ERROR("File not found: %s\n", entry_name);
		return -1;
	}
	LOG("Found file %.30s at 0x%x, type %.12s, size %d\n",
	    entry_name, cbfs_get_entry_addr(image, entry),
	    get_cbfs_entry_type_name(ntohl(entry->type)), ntohl(entry->len));

	if (ntohl(entry->type) != CBFS_COMPONENT_RAW) {
		WARN("Only 'raw' files are safe to extract.\n");
	}

	buffer.data = CBFS_SUBHEADER(entry);
	buffer.size = ntohl(entry->len);
	buffer.name = (char *)"(cbfs_export_entry)";
	if (buffer_write_file(&buffer, filename) != 0) {
		ERROR("Failed to write %s into %s.\n",
		      entry_name, filename);
		return -1;
	}
	INFO("Successfully dumped the file to: %s\n", filename);
	return 0;
}
Exemple #5
0
void *cbfs_load_payload(struct cbfs_media *media, const char *name)
{
	int file_len;
	void *file_start;
	struct cbfs_file *file;

	file_start = vboot_get_payload(&file_len);

	if (file_start != NULL)
		return spi_mirror(file_start, file_len);

	file = cbfs_get_file(media, name);

	if (file == NULL)
		return NULL;

	if (ntohl(file->type) != CBFS_TYPE_PAYLOAD)
		return NULL;

	file_len = ntohl(file->len);

	file_start = CBFS_SUBHEADER(file);

	return spi_mirror(file_start, file_len);
}
Exemple #6
0
static void vga_init(device_t dev)
{
	printk(BIOS_INFO, "Starting Graphics Initialization\n");
	struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "mbi.bin");
	void *mbi = NULL;
	unsigned int mbi_len = 0;

	if (file) {
		if (ntohl(file->type) != CBFS_TYPE_MBI) {
			printk(BIOS_INFO,  "CBFS:  MBI binary is of type %x instead of"
			       "type %x\n", file->type, CBFS_TYPE_MBI);
		} else {
			mbi = (void *) CBFS_SUBHEADER(file);
			mbi_len = ntohl(file->len);
		}
	} else {
		printk(BIOS_INFO,  "Could not find MBI.\n");
	}

	if (mbi && mbi_len) {
		/* The GDT or coreboot table is going to live here. But
		 * a long time after we relocated the GNVS, so this is
		 * not troublesome.
		 */
		*(u32 *)0x500 = (u32)mbi;
		*(u32 *)0x504 = (u32)mbi_len;
		outb(0xeb, 0xb2);
	}

	pci_dev_init(dev);
	printk(BIOS_INFO, "Graphics Initialization Complete\n");

	/* Enable TV-Out */
#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
#define PIPE_A_CRT	(1 << 0)
#define PIPE_A_LFP	(1 << 1)
#define PIPE_A_TV	(1 << 3)
#define PIPE_B_CRT	(1 << 8)
#define PIPE_B_TV	(1 << 10)
	printk(BIOS_DEBUG, "Enabling TV-Out\n");
	void runInt10(void);
	X86_AX = 0x5f64;
	X86_BX = 0x0001; // Set Display Device, force execution
	X86_CX = PIPE_A_CRT | PIPE_A_TV;
	// M.x86.R_CX = PIPE_B_TV;
	runInt10();
	switch (X86_AX) {
	case 0x005f:
		printk(BIOS_DEBUG, "... failed.\n");
		break;
	case 0x015f:
		printk(BIOS_DEBUG, "... ok.\n");
		break;
	default:
		printk(BIOS_DEBUG, "... not supported.\n");
		break;
	}
#endif
}
Exemple #7
0
int cbfs_create_empty_entry(struct cbfs_image *image, struct cbfs_file *entry,
		      size_t len, const char *name)
{
	memset(entry, CBFS_CONTENT_DEFAULT_VALUE, sizeof(*entry));
	memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic));
	entry->type = htonl(CBFS_COMPONENT_NULL);
	entry->len = htonl(len);
	entry->checksum = 0;  // TODO Build a checksum algorithm.
	entry->offset = htonl(cbfs_calculate_file_header_size(name));
	memset(CBFS_NAME(entry), 0, ntohl(entry->offset) - sizeof(*entry));
	strcpy(CBFS_NAME(entry), name);
	memset(CBFS_SUBHEADER(entry), CBFS_CONTENT_DEFAULT_VALUE, len);
	return 0;
}
Exemple #8
0
void *cbfs_find_file(const char *name, unsigned int type, unsigned int *len)
{
	struct cbfs_file *file = cbfs_find(name);

	if (file == NULL) {
		printf("CBFS:  Could not find file %s\n",
		       name);
		return NULL;
	}

	if (ntohl(file->type) != type) {
		printf("CBFS:  File %s is of type %x instead of"
		       "type %x\n", name, file->type, type);

		return NULL;
	}
	if (len != NULL) *len = file->len;

	return (void *) CBFS_SUBHEADER(file);
}
Exemple #9
0
int cbfs_remove_entry(struct cbfs_image *image, const char *name)
{
	struct cbfs_file *entry, *next;
	size_t len;
	entry = cbfs_get_entry(image, name);
	if (!entry) {
		ERROR("CBFS file %s not found.\n", name);
		return -1;
	}
	next = cbfs_find_next_entry(image, entry);
	assert(next);
	DEBUG("cbfs_remove_entry: Removed %s @ 0x%x\n",
	      CBFS_NAME(entry), cbfs_get_entry_addr(image, entry));
	entry->type = htonl(CBFS_COMPONENT_DELETED);
	len = (cbfs_get_entry_addr(image, next) -
	       cbfs_get_entry_addr(image, entry));
	entry->offset = htonl(cbfs_calculate_file_header_size(""));
	entry->len = htonl(len - ntohl(entry->offset));
	memset(CBFS_NAME(entry), 0, ntohl(entry->offset) - sizeof(*entry));
	memset(CBFS_SUBHEADER(entry), CBFS_CONTENT_DEFAULT_VALUE,
	       ntohl(entry->len));
	return 0;
}
Exemple #10
0
void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
			    int type, size_t *sz)
{
	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;
	}

	if (sz)
		*sz = ntohl(file->len);

	return (void *)CBFS_SUBHEADER(file);
}
Exemple #11
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;
}
Exemple #12
0
int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
		   const char *name, uint32_t type, uint32_t content_offset)
{
	uint32_t entry_type;
	uint32_t addr, addr_next;
	struct cbfs_file *entry, *next;
	uint32_t header_size, need_size, new_size;

	header_size = cbfs_calculate_file_header_size(name);

	need_size = header_size + buffer->size;
	DEBUG("cbfs_add_entry('%s'@0x%x) => need_size = %u+%zu=%u\n",
	      name, content_offset, header_size, buffer->size, need_size);

	if (IS_TOP_ALIGNED_ADDRESS(content_offset)) {
		// legacy cbfstool takes top-aligned address.
		uint32_t theromsize = image->header->romsize;
		INFO("Converting top-aligned address 0x%x to offset: 0x%x\n",
		     content_offset, content_offset + theromsize);
		content_offset += theromsize;
	}

	// Merge empty entries.
	DEBUG("(trying to merge empty entries...)\n");
	cbfs_walk(image, cbfs_merge_empty_entry, NULL);

	for (entry = cbfs_find_first_entry(image);
	     entry && cbfs_is_valid_entry(image, entry);
	     entry = cbfs_find_next_entry(image, entry)) {

		entry_type = ntohl(entry->type);
		if (entry_type != CBFS_COMPONENT_NULL)
			continue;

		addr = cbfs_get_entry_addr(image, entry);
		next = cbfs_find_next_entry(image, entry);
		addr_next = cbfs_get_entry_addr(image, next);

		DEBUG("cbfs_add_entry: space at 0x%x+0x%x(%d) bytes\n",
		      addr, addr_next - addr, addr_next - addr);

		/* Will the file fit? Don't yet worry if we have space for a new
		 * "empty" entry. We take care of that later.
		 */
		if (addr + need_size > addr_next)
			continue;

		// Can we simply put object here?
		if (!content_offset || content_offset == addr + header_size) {
			DEBUG("Filling new entry data (%zd bytes).\n",
			      buffer->size);
			cbfs_create_empty_entry(image, entry, buffer->size,
						name);
			entry->type = htonl(type);
			memcpy(CBFS_SUBHEADER(entry), buffer->data, buffer->size);
			if (verbose)
				cbfs_print_entry_info(image, entry, stderr);

			// setup new entry
			DEBUG("Setting new empty entry.\n");
			entry = cbfs_find_next_entry(image, entry);
			new_size = (cbfs_get_entry_addr(image, next) -
				    cbfs_get_entry_addr(image, entry));

			/* Entry was added and no space for new "empty" entry */
			if (new_size < cbfs_calculate_file_header_size("")) {
				DEBUG("No need for new \"empty\" entry\n");
				/* No need to increase the size of the just
				 * stored file to extend to next file. Alignment
				 * of next file takes care of this.
				 */
				return 0;
			}
			new_size -= cbfs_calculate_file_header_size("");
			DEBUG("new size: %d\n", new_size);
			cbfs_create_empty_entry(image, entry, new_size, "");
			if (verbose)
				cbfs_print_entry_info(image, entry, stderr);
			return 0;
		}

		// We need to put content here, and the case is really
		// complicated...
		assert(content_offset);
		if (addr_next < content_offset) {
			DEBUG("Not for specified offset yet");
			continue;
		} else if (addr > content_offset) {
			DEBUG("Exceed specified content_offset.");
			break;
		} else if (addr + header_size > content_offset) {
			ERROR("Not enough space for header.\n");
			break;
		} else if (content_offset + buffer->size > addr_next) {
			ERROR("Not enough space for content.\n");
			break;
		}

		// TODO there are more few tricky cases that we may
		// want to fit by altering offset.
		DEBUG("section 0x%x+0x%x for content_offset 0x%x.\n",
		      addr, addr_next - addr, content_offset);

		if (cbfs_add_entry_at(image, entry, buffer->size, name, type,
				      buffer->data, content_offset) == 0) {
			return 0;
		}
		break;
	}

	ERROR("Could not add [%s, %zd bytes (%zd KB)@0x%x]; too big?\n",
	      buffer->name, buffer->size, buffer->size / 1024, content_offset);
	return -1;
}
Exemple #13
0
/* Tries to add an entry with its data (CBFS_SUBHEADER) at given offset. */
static int cbfs_add_entry_at(struct cbfs_image *image,
			     struct cbfs_file *entry,
			     uint32_t size,
			     const char *name,
			     uint32_t type,
			     const void *data,
			     uint32_t content_offset)
{
	struct cbfs_file *next = cbfs_find_next_entry(image, entry);
	uint32_t addr = cbfs_get_entry_addr(image, entry),
		 addr_next = cbfs_get_entry_addr(image, next);
	uint32_t header_size = cbfs_calculate_file_header_size(name),
		 min_entry_size = cbfs_calculate_file_header_size("");
	uint32_t len, target;
	uint32_t align = image->header->align;

	target = content_offset - header_size;
	if (target % align)
		target -= target % align;
	if (target < addr) {
		ERROR("No space to hold cbfs_file header.");
		return -1;
	}

	// Process buffer BEFORE content_offset.
	if (target - addr > min_entry_size) {
		DEBUG("|min|...|header|content|... <create new entry>\n");
		len = target - addr - min_entry_size;
		cbfs_create_empty_entry(image, entry, len, "");
		if (verbose > 1) cbfs_print_entry_info(image, entry, stderr);
		entry = cbfs_find_next_entry(image, entry);
		addr = cbfs_get_entry_addr(image, entry);
	}

	len = size + (content_offset - addr - header_size);
	cbfs_create_empty_entry(image, entry, len, name);
	if (len != size) {
		DEBUG("|..|header|content|... <use offset to create entry>\n");
		DEBUG("before: offset=0x%x, len=0x%x\n",
		      ntohl(entry->offset), ntohl(entry->len));
		// TODO reset expanded name buffer to 0xFF.
		entry->offset = htonl(ntohl(entry->offset) + (len - size));
		entry->len = htonl(size);
		DEBUG("after: offset=0x%x, len=0x%x\n",
		      ntohl(entry->offset), ntohl(entry->len));
	}

	// Ready to fill data into entry.
	assert(ntohl(entry->len) == size);
	entry->type = htonl(type);
	DEBUG("content_offset: 0x%x, entry location: %x\n",
	      content_offset, (int)((char*)CBFS_SUBHEADER(entry) -
				    image->buffer.data));
	assert((char*)CBFS_SUBHEADER(entry) - image->buffer.data ==
	       content_offset);
	memcpy(CBFS_SUBHEADER(entry), data, size);
	if (verbose > 1) cbfs_print_entry_info(image, entry, stderr);

	// Process buffer AFTER entry.
	entry = cbfs_find_next_entry(image, entry);
	addr = cbfs_get_entry_addr(image, entry);
	assert(addr < addr_next);

	if (addr_next - addr < min_entry_size) {
		DEBUG("No space after content to keep CBFS structure.\n");
		return -1;
	}

	len = addr_next - addr - min_entry_size;
	cbfs_create_empty_entry(image, entry, len, "");
	if (verbose > 1) cbfs_print_entry_info(image, entry, stderr);
	return 0;
}