cbfstool: add unprocessed flag for file exporting
Add an unprocessed flag (-U) which modifies how files are exported.
In the case of a compressed raw file, extract without decompressing.
In the case of a stage or payload, extract without decompressing or
converting to an ELF.
This can be useful for verifying the integrity of a stage or payload,
since converting to an ELF may not be a deterministic process on
different platforms or coreboot versions.
BUG=b:111577108
TEST=USE=cb_legacy_tianocore emerge-eve edk2 coreboot-utils chromeos-bootimage
     cd /build/eve/firmware
     /build/eve/usr/bin/cbfstool image.bin extract -r RW_LEGACY \
       -n payload -f /tmp/payload_1 -U
     START=$((16#`xxd -s 20 -l 4 -p tianocore.cbfs`))
     SIZE=$((16#`xxd -s 8 -l 4 -p tianocore.cbfs`))
     dd if=tianocore.cbfs skip=$START count=$SIZE bs=1 > /tmp/payload_2
     diff /tmp/payload_1 /tmp/payload_2
     rm /tmp/payload_1 /tmp/payload_2
Change-Id: I351d471d699daedd51adf4a860661877f25607e6
Signed-off-by: Joel Kitching <kitching@chromium.org>
Reviewed-on: https://review.coreboot.org/29616
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						parent
						
							73bbcee932
						
					
				
				
					commit
					21fdd89b0c
				
			@@ -1286,7 +1286,7 @@ out:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
					int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
				
			||||||
		      const char *filename, uint32_t arch)
 | 
							      const char *filename, uint32_t arch, bool do_processing)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cbfs_file *entry = cbfs_get_entry(image, entry_name);
 | 
						struct cbfs_file *entry = cbfs_get_entry(image, entry_name);
 | 
				
			||||||
	struct buffer buffer;
 | 
						struct buffer buffer;
 | 
				
			||||||
@@ -1295,26 +1295,37 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
				
			|||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int compressed_size = ntohl(entry->len);
 | 
				
			||||||
	unsigned int decompressed_size = 0;
 | 
						unsigned int decompressed_size = 0;
 | 
				
			||||||
	unsigned int compression = cbfs_file_get_compression_info(entry,
 | 
						unsigned int compression = cbfs_file_get_compression_info(entry,
 | 
				
			||||||
		&decompressed_size);
 | 
							&decompressed_size);
 | 
				
			||||||
 | 
						unsigned int buffer_size;
 | 
				
			||||||
 | 
						decomp_func_ptr decompress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	decomp_func_ptr decompress = decompression_function(compression);
 | 
						if (do_processing) {
 | 
				
			||||||
	if (!decompress) {
 | 
							decompress = decompression_function(compression);
 | 
				
			||||||
		ERROR("looking up decompression routine failed\n");
 | 
							if (!decompress) {
 | 
				
			||||||
		return -1;
 | 
								ERROR("looking up decompression routine failed\n");
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							buffer_size = decompressed_size;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Force nop decompression */
 | 
				
			||||||
 | 
							decompress = decompression_function(CBFS_COMPRESS_NONE);
 | 
				
			||||||
 | 
							buffer_size = compressed_size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LOG("Found file %.30s at 0x%x, type %.12s, size %d\n",
 | 
						LOG("Found file %.30s at 0x%x, type %.12s, compressed %d, size %d\n",
 | 
				
			||||||
	    entry_name, cbfs_get_entry_addr(image, entry),
 | 
						    entry_name, cbfs_get_entry_addr(image, entry),
 | 
				
			||||||
	    get_cbfs_entry_type_name(ntohl(entry->type)), decompressed_size);
 | 
						    get_cbfs_entry_type_name(ntohl(entry->type)), compressed_size,
 | 
				
			||||||
 | 
						    decompressed_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buffer_init(&buffer, strdup("(cbfs_export_entry)"), NULL, 0);
 | 
						buffer_init(&buffer, strdup("(cbfs_export_entry)"), NULL, 0);
 | 
				
			||||||
 | 
						buffer.data = malloc(buffer_size);
 | 
				
			||||||
 | 
						buffer.size = buffer_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buffer.data = malloc(decompressed_size);
 | 
						if (decompress(CBFS_SUBHEADER(entry), compressed_size,
 | 
				
			||||||
	buffer.size = decompressed_size;
 | 
							       buffer.data, buffer.size, NULL)) {
 | 
				
			||||||
	if (decompress(CBFS_SUBHEADER(entry), ntohl(entry->len),
 | 
					 | 
				
			||||||
		buffer.data, buffer.size, NULL)) {
 | 
					 | 
				
			||||||
		ERROR("decompression failed for %s\n", entry_name);
 | 
							ERROR("decompression failed for %s\n", entry_name);
 | 
				
			||||||
		buffer_delete(&buffer);
 | 
							buffer_delete(&buffer);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
@@ -1326,13 +1337,19 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
				
			|||||||
	 * one has to do a second pass for stages to potentially decompress
 | 
						 * one has to do a second pass for stages to potentially decompress
 | 
				
			||||||
	 * the stage data to make it more meaningful.
 | 
						 * the stage data to make it more meaningful.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (ntohl(entry->type) == CBFS_COMPONENT_STAGE) {
 | 
						if (do_processing) {
 | 
				
			||||||
		if (cbfs_stage_make_elf(&buffer, arch)) {
 | 
							int (*make_elf)(struct buffer *, uint32_t) = NULL;
 | 
				
			||||||
			buffer_delete(&buffer);
 | 
							switch (ntohl(entry->type)) {
 | 
				
			||||||
			return -1;
 | 
							case CBFS_COMPONENT_STAGE:
 | 
				
			||||||
 | 
								make_elf = cbfs_stage_make_elf;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case CBFS_COMPONENT_SELF:
 | 
				
			||||||
 | 
								make_elf = cbfs_payload_make_elf;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (ntohl(entry->type) == CBFS_COMPONENT_SELF) {
 | 
							if (make_elf && make_elf(&buffer, arch)) {
 | 
				
			||||||
		if (cbfs_payload_make_elf(&buffer, arch)) {
 | 
								ERROR("Failed to write %s into %s.\n",
 | 
				
			||||||
 | 
								      entry_name, filename);
 | 
				
			||||||
			buffer_delete(&buffer);
 | 
								buffer_delete(&buffer);
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,10 +95,11 @@ int cbfs_image_delete(struct cbfs_image *image);
 | 
				
			|||||||
/* Returns a pointer to entry by name, or NULL if name is not found. */
 | 
					/* Returns a pointer to entry by name, or NULL if name is not found. */
 | 
				
			||||||
struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name);
 | 
					struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Exports an entry to external file.
 | 
					/* Exports an entry to external file. If do_processing is true, file contents
 | 
				
			||||||
 | 
					 * will be decompressed, and also turned into an ELF if appropriate.
 | 
				
			||||||
 * Returns 0 on success, otherwise (ex, not found) non-zero. */
 | 
					 * Returns 0 on success, otherwise (ex, not found) non-zero. */
 | 
				
			||||||
int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
					int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 | 
				
			||||||
		      const char *filename, uint32_t arch);
 | 
							      const char *filename, uint32_t arch, bool do_processing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Adds an entry to CBFS image by given name and type. If content_offset is
 | 
					/* Adds an entry to CBFS image by given name and type. If content_offset is
 | 
				
			||||||
 * non-zero, try to align "content" (CBFS_SUBHEADER(p)) at content_offset.
 | 
					 * non-zero, try to align "content" (CBFS_SUBHEADER(p)) at content_offset.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,6 +83,7 @@ static struct param {
 | 
				
			|||||||
	bool stage_xip;
 | 
						bool stage_xip;
 | 
				
			||||||
	bool autogen_attr;
 | 
						bool autogen_attr;
 | 
				
			||||||
	bool machine_parseable;
 | 
						bool machine_parseable;
 | 
				
			||||||
 | 
						bool unprocessed;
 | 
				
			||||||
	int fit_empty_entries;
 | 
						int fit_empty_entries;
 | 
				
			||||||
	enum comp_algo compression;
 | 
						enum comp_algo compression;
 | 
				
			||||||
	int precompression;
 | 
						int precompression;
 | 
				
			||||||
@@ -1095,7 +1096,7 @@ static int cbfs_extract(void)
 | 
				
			|||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cbfs_export_entry(&image, param.name, param.filename,
 | 
						return cbfs_export_entry(&image, param.name, param.filename,
 | 
				
			||||||
				param.arch);
 | 
									param.arch, !param.unprocessed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int cbfs_write(void)
 | 
					static int cbfs_write(void)
 | 
				
			||||||
@@ -1314,7 +1315,7 @@ static const struct command commands[] = {
 | 
				
			|||||||
	{"compact", "r:h?", cbfs_compact, true, true},
 | 
						{"compact", "r:h?", cbfs_compact, true, true},
 | 
				
			||||||
	{"copy", "r:R:h?", cbfs_copy, true, true},
 | 
						{"copy", "r:R:h?", cbfs_copy, true, true},
 | 
				
			||||||
	{"create", "M:r:s:B:b:H:o:m:vh?", cbfs_create, true, true},
 | 
						{"create", "M:r:s:B:b:H:o:m:vh?", cbfs_create, true, true},
 | 
				
			||||||
	{"extract", "H:r:m:n:f:vh?", cbfs_extract, true, false},
 | 
						{"extract", "H:r:m:n:f:Uvh?", cbfs_extract, true, false},
 | 
				
			||||||
	{"layout", "wvh?", cbfs_layout, false, false},
 | 
						{"layout", "wvh?", cbfs_layout, false, false},
 | 
				
			||||||
	{"print", "H:r:vkh?", cbfs_print, true, false},
 | 
						{"print", "H:r:vkh?", cbfs_print, true, false},
 | 
				
			||||||
	{"read", "r:f:vh?", cbfs_read, true, false},
 | 
						{"read", "r:f:vh?", cbfs_read, true, false},
 | 
				
			||||||
@@ -1362,6 +1363,7 @@ static struct option long_options[] = {
 | 
				
			|||||||
	{"xip",           no_argument,       0, 'y' },
 | 
						{"xip",           no_argument,       0, 'y' },
 | 
				
			||||||
	{"gen-attribute", no_argument,       0, 'g' },
 | 
						{"gen-attribute", no_argument,       0, 'g' },
 | 
				
			||||||
	{"mach-parseable",no_argument,       0, 'k' },
 | 
						{"mach-parseable",no_argument,       0, 'k' },
 | 
				
			||||||
 | 
						{"unprocessed",   no_argument,       0, 'U' },
 | 
				
			||||||
	{NULL,            0,                 0,  0  }
 | 
						{NULL,            0,                 0,  0  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1428,6 +1430,7 @@ static void usage(char *name)
 | 
				
			|||||||
	     "  -d               Accept short data; fill downward/from top\n"
 | 
						     "  -d               Accept short data; fill downward/from top\n"
 | 
				
			||||||
	     "  -F               Force action\n"
 | 
						     "  -F               Force action\n"
 | 
				
			||||||
	     "  -g               Generate position and alignment arguments\n"
 | 
						     "  -g               Generate position and alignment arguments\n"
 | 
				
			||||||
 | 
						     "  -U               Unprocessed; don't decompress or make ELF\n"
 | 
				
			||||||
	     "  -v               Provide verbose output\n"
 | 
						     "  -v               Provide verbose output\n"
 | 
				
			||||||
	     "  -h               Display this help message\n\n"
 | 
						     "  -h               Display this help message\n\n"
 | 
				
			||||||
	     "COMMANDs:\n"
 | 
						     "COMMANDs:\n"
 | 
				
			||||||
@@ -1473,8 +1476,8 @@ static void usage(char *name)
 | 
				
			|||||||
			"List mutable (or, with -w, readable) image regions\n"
 | 
								"List mutable (or, with -w, readable) image regions\n"
 | 
				
			||||||
	     " print [-r image,regions]                                    "
 | 
						     " print [-r image,regions]                                    "
 | 
				
			||||||
			"Show the contents of the ROM\n"
 | 
								"Show the contents of the ROM\n"
 | 
				
			||||||
	     " extract [-r image,regions] [-m ARCH] -n NAME -f FILE        "
 | 
						     " extract [-r image,regions] [-m ARCH] -n NAME -f FILE [-U]   "
 | 
				
			||||||
			"Extracts a raw payload from ROM\n"
 | 
								"Extracts a file from ROM\n"
 | 
				
			||||||
	     " write [-F] -r image,regions -f file [-u | -d] [-i int]      "
 | 
						     " write [-F] -r image,regions -f file [-u | -d] [-i int]      "
 | 
				
			||||||
			"Write file into same-size [or larger] raw region\n"
 | 
								"Write file into same-size [or larger] raw region\n"
 | 
				
			||||||
	     " read [-r fmap-region] -f file                               "
 | 
						     " read [-r fmap-region] -f file                               "
 | 
				
			||||||
@@ -1770,6 +1773,9 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			case 'k':
 | 
								case 'k':
 | 
				
			||||||
				param.machine_parseable = true;
 | 
									param.machine_parseable = true;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								case 'U':
 | 
				
			||||||
 | 
									param.unprocessed = true;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			case 'h':
 | 
								case 'h':
 | 
				
			||||||
			case '?':
 | 
								case '?':
 | 
				
			||||||
				usage(argv[0]);
 | 
									usage(argv[0]);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user