Add option to read ROM layout from IFD

Add an option --ifd to read the ROM layout from an Intel Firmware
Descriptor (IFD). Works the same as the -l option, if given, -i
specifies the images to update.

v2: o Rebased on libflashrom, use libflashrom interface.
    o Use functions from ich_descriptors.c.

v3: o Move ich_descriptors.o to LIB_OBJS, thus build it independent
      of arch and programmers.
    o Bail out if we aren't compiled for little endian.
    o Update flashrom.8.tmpl.

v4: o Incorporated David's comments.
    o Removed single-character `-d` option.

v5: Changed region names to match the output of `ifdtool --layout ...`

Change-Id: Ifafff2bf6d5c5e62283416b3269723f81fdc0fa3
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/17953
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/cli_classic.c b/cli_classic.c
index 7e3dfd5..0a09cfd 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -42,7 +42,7 @@
 	       "-z|"
 #endif
 	       "-p <programmername>[:<parameters>] [-c <chipname>]\n"
-	       "[-E|(-r|-w|-v) <file>] [-l <layoutfile> [-i <imagename>]...] [-n] [-N] [-f]]\n"
+	       "[-E|(-r|-w|-v) <file>] [(-l <layoutfile>|--ifd) [-i <imagename>]...] [-n] [-N] [-f]]\n"
 	       "[-V[V[V]]] [-o <logfile>]\n\n", name);
 
 	printf(" -h | --help                        print this help text\n"
@@ -57,6 +57,7 @@
 	       " -n | --noverify                    don't auto-verify\n"
 	       " -N | --noverify-all                verify included regions only (cf. -i)\n"
 	       " -l | --layout <layoutfile>         read ROM layout from <layoutfile>\n"
+	       "      --ifd                         read layout from an Intel Firmware Descriptor\n"
 	       " -i | --image <name>                only flash image <name> from flash layout\n"
 	       " -o | --output <logfile>            log output to <logfile>\n"
 	       " -L | --list-supported              print supported devices\n"
@@ -99,12 +100,13 @@
 	struct flashctx *fill_flash;
 	const char *name;
 	int namelen, opt, i, j;
-	int startchip = -1, chipcount = 0, option_index = 0, force = 0;
+	int startchip = -1, chipcount = 0, option_index = 0, force = 0, ifd = 0;
 #if CONFIG_PRINT_WIKI == 1
 	int list_supported_wiki = 0;
 #endif
 	int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
 	int dont_verify_it = 0, dont_verify_all = 0, list_supported = 0, operation_specified = 0;
+	struct flashrom_layout *layout = NULL;
 	enum programmer prog = PROGRAMMER_INVALID;
 	int ret = 0;
 
@@ -120,6 +122,7 @@
 		{"verbose",		0, NULL, 'V'},
 		{"force",		0, NULL, 'f'},
 		{"layout",		1, NULL, 'l'},
+		{"ifd",			0, NULL, 0x0100},
 		{"image",		1, NULL, 'i'},
 		{"list-supported",	0, NULL, 'L'},
 		{"list-supported-wiki",	0, NULL, 'z'},
@@ -220,8 +223,19 @@
 					"more than once. Aborting.\n");
 				cli_classic_abort_usage();
 			}
+			if (ifd) {
+				fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
+				cli_classic_abort_usage();
+			}
 			layoutfile = strdup(optarg);
 			break;
+		case 0x0100:
+			if (layoutfile) {
+				fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
+				cli_classic_abort_usage();
+			}
+			ifd = 1;
+			break;
 		case 'i':
 			tempstr = strdup(optarg);
 			if (register_include_arg(tempstr)) {
@@ -376,7 +390,7 @@
 		ret = 1;
 		goto out;
 	}
-	if (process_include_args()) {
+	if (!ifd && process_include_args(get_global_layout())) {
 		ret = 1;
 		goto out;
 	}
@@ -529,9 +543,15 @@
 		goto out_shutdown;
 	}
 
-	if (layoutfile)
-		flashrom_layout_set(fill_flash, get_global_layout());
+	if (layoutfile) {
+		layout = get_global_layout();
+	} else if (ifd && (flashrom_layout_read_from_ifd(&layout, fill_flash, NULL, 0) ||
+			   process_include_args(layout))) {
+		ret = 1;
+		goto out_shutdown;
+	}
 
+	flashrom_layout_set(fill_flash, layout);
 	flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, !!force);
 	flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE_BOARDMISMATCH, !!force_boardmismatch);
 	flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !dont_verify_it);
@@ -551,6 +571,8 @@
 	else if (verify_it)
 		ret = do_verify(fill_flash, filename);
 
+	flashrom_layout_release(layout);
+
 out_shutdown:
 	programmer_shutdown();
 out: