/ util / amdfwtool / opts.c
opts.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <stdio.h>
  4  #include <stdlib.h>
  5  #include <string.h>
  6  #include <getopt.h>
  7  
  8  #include "amdfwtool.h"
  9  
 10  #define MIN_ROM_KB		256
 11  #define MAX_MAPPED_WINDOW	(16 * MiB)
 12  #define MAX_MAPPED_WINDOW_MASK	(MAX_MAPPED_WINDOW - 1)
 13  
 14  #define DEFAULT_SOFT_FUSE_CHAIN "0x1"
 15  
 16  enum {
 17  	AMDFW_OPT_CONFIG =	'c',
 18  	AMDFW_OPT_DEBUG =	'd',
 19  	AMDFW_OPT_HELP =	'h',
 20  
 21  	AMDFW_OPT_XHCI = 128,
 22  	AMDFW_OPT_IMC,
 23  	AMDFW_OPT_GEC,
 24  	AMDFW_OPT_RECOVERY_AB,
 25  	AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
 26  	AMDFW_OPT_USE_COMBO,
 27  	AMDFW_OPT_COMBO1_CONFIG,
 28  	AMDFW_OPT_MULTILEVEL,
 29  	AMDFW_OPT_NVRAM,
 30  
 31  	AMDFW_OPT_FUSE,
 32  	AMDFW_OPT_UNLOCK,
 33  	AMDFW_OPT_WHITELIST,
 34  	AMDFW_OPT_USE_PSPSECUREOS,
 35  	AMDFW_OPT_LOAD_MP2FW,
 36  	AMDFW_OPT_LOAD_S0I3,
 37  	AMDFW_OPT_SPL_TABLE,
 38  	AMDFW_OPT_VERSTAGE,
 39  	AMDFW_OPT_VERSTAGE_SIG,
 40  	AMDFW_OPT_OUTPUT_MANIFEST,
 41  
 42  	AMDFW_OPT_INSTANCE,
 43  	AMDFW_OPT_APCB,
 44  	AMDFW_OPT_APCB_COMBO1,
 45  	AMDFW_OPT_APOBBASE,
 46  	AMDFW_OPT_BIOSBIN,
 47  	AMDFW_OPT_BIOSBIN_SOURCE,
 48  	AMDFW_OPT_BIOSBIN_DEST,
 49  	AMDFW_OPT_BIOS_UNCOMP_SIZE,
 50  	AMDFW_OPT_BIOSBIN_UNCOMP,
 51  	AMDFW_OPT_UCODE,
 52  	AMDFW_OPT_APOB_NVBASE,
 53  	AMDFW_OPT_APOB_NVSIZE,
 54  
 55  	AMDFW_OPT_OUTPUT,
 56  	AMDFW_OPT_FLASHSIZE,
 57  	AMDFW_OPT_LOCATION,
 58  	AMDFW_OPT_ANYWHERE,
 59  	AMDFW_OPT_SHAREDMEM,
 60  	AMDFW_OPT_SHAREDMEM_SIZE,
 61  	AMDFW_OPT_SIGNED_OUTPUT,
 62  	AMDFW_OPT_SIGNED_ADDR,
 63  	AMDFW_OPT_BODY_LOCATION,
 64  	/* begin after ASCII characters */
 65  	LONGOPT_SPI_READ_MODE	= 256,
 66  	LONGOPT_SPI_SPEED	= 257,
 67  	LONGOPT_SPI_MICRON_FLAG	= 258,
 68  	LONGOPT_BIOS_SIG	= 259,
 69  	LONGOPT_NVRAM_BASE	= 260,
 70  	LONGOPT_NVRAM_SIZE	= 261,
 71  	LONGOPT_RPMC_NVRAM_BASE	= 262,
 72  	LONGOPT_RPMC_NVRAM_SIZE	= 263,
 73  };
 74  
 75  static const char optstring[] = {AMDFW_OPT_CONFIG, ':',
 76  	AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
 77  };
 78  
 79  static struct option long_options[] = {
 80  	{"xhci",             required_argument, 0, AMDFW_OPT_XHCI },
 81  	{"imc",              required_argument, 0, AMDFW_OPT_IMC },
 82  	{"gec",              required_argument, 0, AMDFW_OPT_GEC },
 83  	/* PSP Directory Table items */
 84  	{"recovery-ab",            no_argument, 0, AMDFW_OPT_RECOVERY_AB },
 85  	{"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
 86  	{"use-combo",              no_argument, 0, AMDFW_OPT_USE_COMBO },
 87  	{"combo-config1",    required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
 88  	{"multilevel",             no_argument, 0, AMDFW_OPT_MULTILEVEL },
 89  	{"nvram",            required_argument, 0, AMDFW_OPT_NVRAM },
 90  	{"nvram-base",       required_argument, 0, LONGOPT_NVRAM_BASE },
 91  	{"nvram-size",       required_argument, 0, LONGOPT_NVRAM_SIZE },
 92  	{"rpmc-nvram-base",  required_argument, 0, LONGOPT_RPMC_NVRAM_BASE },
 93  	{"rpmc-nvram-size",  required_argument, 0, LONGOPT_RPMC_NVRAM_SIZE },
 94  	{"soft-fuse",        required_argument, 0, AMDFW_OPT_FUSE },
 95  	{"token-unlock",           no_argument, 0, AMDFW_OPT_UNLOCK },
 96  	{"whitelist",        required_argument, 0, AMDFW_OPT_WHITELIST },
 97  	{"use-pspsecureos",        no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
 98  	{"load-mp2-fw",            no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
 99  	{"load-s0i3",              no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
100  	{"spl-table",        required_argument, 0, AMDFW_OPT_SPL_TABLE },
101  	{"verstage",         required_argument, 0, AMDFW_OPT_VERSTAGE },
102  	{"verstage_sig",     required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
103  	{"output-manifest",  required_argument, 0, AMDFW_OPT_OUTPUT_MANIFEST },
104  	/* BIOS Directory Table items */
105  	{"instance",         required_argument, 0, AMDFW_OPT_INSTANCE },
106  	{"apcb",             required_argument, 0, AMDFW_OPT_APCB },
107  	{"apcb-combo1",      required_argument, 0, AMDFW_OPT_APCB_COMBO1 },
108  	{"apob-base",        required_argument, 0, AMDFW_OPT_APOBBASE },
109  	{"bios-bin",         required_argument, 0, AMDFW_OPT_BIOSBIN },
110  	{"bios-bin-src",     required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
111  	{"bios-bin-dest",    required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
112  	{"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
113  	{"bios-bin-uncomp",        no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
114  	{"bios-sig-size",    required_argument, 0, LONGOPT_BIOS_SIG },
115  	{"ucode",            required_argument, 0, AMDFW_OPT_UCODE },
116  	{"apob-nv-base",     required_argument, 0, AMDFW_OPT_APOB_NVBASE },
117  	{"apob-nv-size",     required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
118  	/* Embedded Firmware Structure items*/
119  	{"spi-read-mode",    required_argument, 0, LONGOPT_SPI_READ_MODE },
120  	{"spi-speed",        required_argument, 0, LONGOPT_SPI_SPEED },
121  	{"spi-micron-flag",  required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
122  	{"body-location",     required_argument, 0, AMDFW_OPT_BODY_LOCATION },
123  	/* other */
124  	{"output",           required_argument, 0, AMDFW_OPT_OUTPUT },
125  	{"flashsize",        required_argument, 0, AMDFW_OPT_FLASHSIZE },
126  	{"location",         required_argument, 0, AMDFW_OPT_LOCATION },
127  	{"anywhere",         no_argument,       0, AMDFW_OPT_ANYWHERE },
128  	{"sharedmem",        required_argument, 0, AMDFW_OPT_SHAREDMEM },
129  	{"sharedmem-size",   required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
130  
131  	{"signed-output",           required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
132  	{"signed-addr",           required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
133  
134  	{"config",           required_argument, 0, AMDFW_OPT_CONFIG },
135  	{"debug",            no_argument,       0, AMDFW_OPT_DEBUG },
136  	{"help",             no_argument,       0, AMDFW_OPT_HELP },
137  	{NULL,               0,                 0,  0  }
138  };
139  
140  static void usage(void)
141  {
142  	printf("amdfwtool: Create AMD Firmware combination\n");
143  	printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
144  	printf("--xhci <FILE>                  Add XHCI blob\n");
145  	printf("--imc <FILE>                   Add IMC blob\n");
146  	printf("--gec <FILE>                   Add GEC blob\n");
147  
148  	printf("\nPSP options:\n");
149  	printf("--use-combo                    Use the COMBO layout\n");
150  	printf("--combo-config1 <config file>  Config for 1st combo entry\n");
151  	printf("--multilevel                   Generate primary and secondary tables\n");
152  	printf("--nvram <FILE>                 Add nvram binary\n");
153  	printf("--soft-fuse                    Set soft fuse\n");
154  	printf("--token-unlock                 Set token unlock\n");
155  	printf("--nvram-base <HEX_VAL>         Base address of nvram\n");
156  	printf("--nvram-size <HEX_VAL>         Size of nvram\n");
157  	printf("--rpmc-nvram-base <HEX_VAL>    Base address of RPMC nvram\n");
158  	printf("--rpmc-nvram-size <HEX_VAL>    Size of RPMC nvram\n");
159  	printf("--whitelist                    Set if there is a whitelist\n");
160  	printf("--use-pspsecureos              Set if psp secure OS is needed\n");
161  	printf("--load-mp2-fw                  Set if load MP2 firmware\n");
162  	printf("--load-s0i3                    Set if load s0i3 firmware\n");
163  	printf("--verstage <FILE>              Add verstage\n");
164  	printf("--verstage_sig                 Add verstage signature\n");
165  	printf("--recovery-ab                  Use the recovery A/B layout\n");
166  	printf("\nBIOS options:\n");
167  	printf("--instance <number>            Sets instance field for the next BIOS\n");
168  	printf("                               firmware\n");
169  	printf("--apcb <FILE>                  Add AGESA PSP customization block\n");
170  	printf("--apcb-combo1 <FILE>           Add APCB for 1st combo\n");
171  	printf("--apob-base <HEX_VAL>          Destination for AGESA PSP output block\n");
172  	printf("--apob-nv-base <HEX_VAL>       Location of S3 resume data\n");
173  	printf("--apob-nv-size <HEX_VAL>       Size of S3 resume data\n");
174  	printf("--ucode <FILE>                 Add microcode patch\n");
175  	printf("--bios-bin <FILE>              Add compressed image; auto source address\n");
176  	printf("--bios-bin-src <HEX_VAL>       Address in flash of source if -V not used\n");
177  	printf("--bios-bin-dest <HEX_VAL>      Destination for uncompressed BIOS\n");
178  	printf("--bios-uncomp-size <HEX>       Uncompressed size of BIOS image\n");
179  	printf("--output <filename>            output filename\n");
180  	printf("--flashsize <HEX_VAL>          ROM size in bytes\n");
181  	printf("                               size must be larger than %dKB\n",
182  		MIN_ROM_KB);
183  	printf("                               and must a multiple of 1024\n");
184  	printf("--location                     Location of Directory\n");
185  	printf("--anywhere                     Use any 64-byte aligned addr for Directory\n");
186  	printf("--sharedmem                    Location of PSP/FW shared memory\n");
187  	printf("--sharedmem-size               Maximum size of the PSP/FW shared memory\n");
188  	printf("                               area\n");
189  	printf("--output-manifest <FILE>       Writes a manifest with the blobs versions\n");
190  	printf("\nEmbedded Firmware Structure options used by the PSP:\n");
191  	printf("--spi-speed <HEX_VAL>          SPI fast speed to place in EFS Table\n");
192  	printf("                               0x0 66.66Mhz\n");
193  	printf("                               0x1 33.33MHz\n");
194  	printf("                               0x2 22.22MHz\n");
195  	printf("                               0x3 16.66MHz\n");
196  	printf("                               0x4 100MHz\n");
197  	printf("                               0x5 800KHz\n");
198  	printf("--spi-read-mode <HEX_VAL>      SPI read mode to place in EFS Table\n");
199  	printf("                               0x0 Normal Read (up to 33M)\n");
200  	printf("                               0x1 Reserved\n");
201  	printf("                               0x2 Dual IO (1-1-2)\n");
202  	printf("                               0x3 Quad IO (1-1-4)\n");
203  	printf("                               0x4 Dual IO (1-2-2)\n");
204  	printf("                               0x5 Quad IO (1-4-4)\n");
205  	printf("                               0x6 Normal Read (up to 66M)\n");
206  	printf("                               0x7 Fast Read\n");
207  	printf("--spi-micron-flag <HEX_VAL>    Micron SPI part support for RV and later SOC\n");
208  	printf("                               0x0 Micron parts are not used\n");
209  	printf("                               0x1 Micron parts are always used\n");
210  	printf("                               0x2 Micron parts optional, this option is only\n");
211  	printf("                                   supported with RN/LCN SOC\n");
212  	printf("\nGeneral options:\n");
213  	printf("-c|--config <config file>      Config file\n");
214  	printf("-d|--debug                     Print debug message\n");
215  	printf("-h|--help                      Show this help\n");
216  }
217  
218  extern amd_fw_entry amd_psp_fw_table[];
219  extern amd_bios_entry amd_bios_table[];
220  extern amd_fw_entry amd_fw_table[];
221  
222  static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
223  					char *dst_str, char *size_str)
224  {
225  	unsigned int i;
226  
227  	for (i = 0; amd_psp_fw_table[i].type != AMD_FW_INVALID; i++) {
228  		if (amd_psp_fw_table[i].type != type)
229  			continue;
230  
231  		if (amd_psp_fw_table[i].subprog == sub) {
232  			if (dst_str)
233  				amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
234  			if (size_str)
235  				amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
236  			return;
237  		}
238  	}
239  }
240  
241  static void register_bios_fw_addr(amd_bios_type type, char *src_str,
242  					char *dst_str, char *size_str)
243  {
244  	uint32_t i;
245  	for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
246  		if (amd_bios_table[i].type != type)
247  			continue;
248  
249  		if (src_str)
250  			amd_bios_table[i].src = strtoull(src_str, NULL, 16);
251  		if (dst_str)
252  			amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
253  		if (size_str)
254  			amd_bios_table[i].size = strtoul(size_str, NULL, 16);
255  
256  		return;
257  	}
258  }
259  
260  static void register_fw_token_unlock(void)
261  {
262  	uint32_t i;
263  
264  	for (i = 0; amd_psp_fw_table[i].type != AMD_FW_INVALID; i++) {
265  		if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
266  			continue;
267  
268  		amd_psp_fw_table[i].other = 1;
269  		return;
270  	}
271  }
272  
273  static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
274  {
275  	unsigned int i;
276  
277  	for (i = 0; amd_fw_table[i].type != AMD_FW_INVALID; i++) {
278  		if (amd_fw_table[i].type == type) {
279  			amd_fw_table[i].filename = filename;
280  			return;
281  		}
282  	}
283  
284  	for (i = 0; amd_psp_fw_table[i].type != AMD_FW_INVALID; i++) {
285  		if (amd_psp_fw_table[i].type != type)
286  			continue;
287  
288  		if (amd_psp_fw_table[i].subprog == sub) {
289  			amd_psp_fw_table[i].filename = filename;
290  			return;
291  		}
292  	}
293  }
294  
295  static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
296  {
297  	uint32_t i;
298  
299  	for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
300  		if (amd_bios_table[i].type == type
301  					&& amd_bios_table[i].inst == ins
302  					&& amd_bios_table[i].subpr == sub) {
303  			amd_bios_table[i].filename = name;
304  			return;
305  		}
306  	}
307  }
308  
309  static void register_fw_fuse(char *str)
310  {
311  	uint32_t i;
312  
313  	for (i = 0; amd_psp_fw_table[i].type != AMD_FW_INVALID; i++) {
314  		if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
315  			continue;
316  
317  		amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
318  		return;
319  	}
320  }
321  
322  void register_apcb_combo(amd_cb_config *cb_config, int combo_index, context *ctx)
323  {
324  	if (ctx->combo_apcb[combo_index].filename != NULL) {
325  		register_bdt_data(AMD_BIOS_APCB,
326  			ctx->combo_apcb[combo_index].sub,
327  			ctx->combo_apcb[combo_index].ins & 0xF,
328  			ctx->combo_apcb[combo_index].filename);
329  		if (cb_config->have_apcb_bk)
330  			register_bdt_data(AMD_BIOS_APCB_BK,
331  				ctx->combo_apcb_bk[combo_index].sub,
332  				ctx->combo_apcb_bk[combo_index].ins & 0xF,
333  				ctx->combo_apcb_bk[combo_index].filename);
334  	} else {
335  		/* Use main APCB if no Combo APCB is provided */
336  		register_bdt_data(AMD_BIOS_APCB, ctx->combo_apcb[0].sub,
337  			ctx->combo_apcb[0].ins & 0xF, ctx->combo_apcb[0].filename);
338  		if (cb_config->have_apcb_bk)
339  			register_bdt_data(AMD_BIOS_APCB_BK,
340  				ctx->combo_apcb_bk[0].sub,
341  				ctx->combo_apcb_bk[0].ins & 0xF,
342  				ctx->combo_apcb_bk[0].filename);
343  	}
344  }
345  
346  int amdfwtool_getopt(int argc, char *argv[], amd_cb_config *cb_config, context *ctx)
347  {
348  	int c;
349  	/* Values cleared after each firmware or parameter, regardless if N/A */
350  	uint8_t sub = 0, instance = 0;
351  	char *tmp;
352  	int retval = 0;
353  	bool any_location = 0;
354  	int fuse_defined = 0;
355  
356  	while (1) {
357  		int optindex = 0;
358  		int bios_tbl_index = -1;
359  
360  		c = getopt_long(argc, argv, optstring, long_options, &optindex);
361  
362  		if (c == -1)
363  			break;
364  
365  		switch (c) {
366  		case AMDFW_OPT_XHCI:
367  			register_fw_filename(AMD_FW_XHCI, sub, optarg);
368  			sub = instance = 0;
369  			break;
370  		case AMDFW_OPT_IMC:
371  			register_fw_filename(AMD_FW_IMC, sub, optarg);
372  			sub = instance = 0;
373  			break;
374  		case AMDFW_OPT_GEC:
375  			register_fw_filename(AMD_FW_GEC, sub, optarg);
376  			sub = instance = 0;
377  			break;
378  		case AMDFW_OPT_RECOVERY_AB:
379  			cb_config->recovery_ab = true;
380  			break;
381  		case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
382  			cb_config->recovery_ab = true;
383  			cb_config->recovery_ab_single_copy = true;
384  			break;
385  		case AMDFW_OPT_USE_COMBO:
386  			cb_config->use_combo = true;
387  			break;
388  		case AMDFW_OPT_COMBO1_CONFIG:
389  			cb_config->use_combo = true;
390  			/* assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx); */
391  			cb_config->combo_config[1] = optarg;
392  			break;
393  		case AMDFW_OPT_MULTILEVEL:
394  			cb_config->multi_level = true;
395  			break;
396  		case AMDFW_OPT_UNLOCK:
397  			register_fw_token_unlock();
398  			cb_config->unlock_secure = true;
399  			sub = instance = 0;
400  			break;
401  		case AMDFW_OPT_USE_PSPSECUREOS:
402  			cb_config->use_secureos = true;
403  			break;
404  		case AMDFW_OPT_INSTANCE:
405  			instance = strtoul(optarg, &tmp, 16);
406  			break;
407  		case AMDFW_OPT_LOAD_MP2FW:
408  			cb_config->load_mp2_fw = true;
409  			break;
410  		case AMDFW_OPT_NVRAM:
411  			register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
412  			sub = instance = 0;
413  			break;
414  		case AMDFW_OPT_FUSE:
415  			register_fw_fuse(optarg);
416  			fuse_defined = 1;
417  			sub = 0;
418  			break;
419  		case AMDFW_OPT_APCB:
420  			if ((instance & 0xF0) == 0) {
421  				register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
422  				ctx->combo_apcb[0].filename = optarg;
423  				ctx->combo_apcb[0].ins = instance;
424  				ctx->combo_apcb[0].sub = sub;
425  			} else {
426  				register_bdt_data(AMD_BIOS_APCB_BK, sub,
427  					instance & 0xF, optarg);
428  				ctx->combo_apcb_bk[0].filename = optarg;
429  				ctx->combo_apcb_bk[0].ins = instance;
430  				ctx->combo_apcb_bk[0].sub = sub;
431  				cb_config->have_apcb_bk = 1;
432  			}
433  			sub = instance = 0;
434  			break;
435  		case AMDFW_OPT_APCB_COMBO1:
436  			/* assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx); */
437  			if ((instance & 0xF0) == 0) {
438  				ctx->combo_apcb[1].filename = optarg;
439  				ctx->combo_apcb[1].ins = instance;
440  				ctx->combo_apcb[1].sub = sub;
441  			} else {
442  				ctx->combo_apcb_bk[1].filename = optarg;
443  				ctx->combo_apcb_bk[1].ins = instance;
444  				ctx->combo_apcb_bk[1].sub = sub;
445  				cb_config->have_apcb_bk = 1;
446  			}
447  			sub = instance = 0;
448  			break;
449  		case AMDFW_OPT_APOBBASE:
450  			/* APOB destination */
451  			register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
452  			sub = instance = 0;
453  			break;
454  		case AMDFW_OPT_APOB_NVBASE:
455  			/* APOB NV source */
456  			register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
457  			sub = instance = 0;
458  			break;
459  		case AMDFW_OPT_APOB_NVSIZE:
460  			/* APOB NV size */
461  			register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
462  			sub = instance = 0;
463  			break;
464  		case AMDFW_OPT_BIOSBIN:
465  			register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
466  			sub = instance = 0;
467  			break;
468  		case AMDFW_OPT_BIOSBIN_SOURCE:
469  			/* BIOS source */
470  			register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
471  			sub = instance = 0;
472  			break;
473  		case AMDFW_OPT_BIOSBIN_DEST:
474  			/* BIOS destination */
475  			register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
476  			sub = instance = 0;
477  			break;
478  		case AMDFW_OPT_BIOS_UNCOMP_SIZE:
479  			/* BIOS destination size */
480  			register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
481  			sub = instance = 0;
482  			break;
483  		case AMDFW_OPT_BIOSBIN_UNCOMP:
484  			bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
485  			if (bios_tbl_index != -1)
486  				amd_bios_table[bios_tbl_index].zlib = 0;
487  			break;
488  		case LONGOPT_BIOS_SIG:
489  			/* BIOS signature size */
490  			register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
491  			sub = instance = 0;
492  			break;
493  		case AMDFW_OPT_UCODE:
494  			register_bdt_data(AMD_BIOS_UCODE, sub,
495  				instance, optarg);
496  			sub = instance = 0;
497  			break;
498  		case AMDFW_OPT_LOAD_S0I3:
499  			cb_config->s0i3 = true;
500  			break;
501  		case AMDFW_OPT_SPL_TABLE:
502  			register_fw_filename(AMD_FW_SPL, sub, optarg);
503  			sub = instance = 0;
504  			cb_config->have_mb_spl = true;
505  			break;
506  		case AMDFW_OPT_WHITELIST:
507  			register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
508  			sub = instance = 0;
509  			cb_config->have_whitelist = true;
510  			break;
511  		case AMDFW_OPT_VERSTAGE:
512  			register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
513  			sub = instance = 0;
514  			break;
515  		case AMDFW_OPT_VERSTAGE_SIG:
516  			register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
517  			sub = instance = 0;
518  			break;
519  		case AMDFW_OPT_OUTPUT_MANIFEST:
520  			cb_config->manifest_file = optarg;
521  			break;
522  		case AMDFW_OPT_SIGNED_OUTPUT:
523  			cb_config->signed_output_file = optarg;
524  			sub = instance = 0;
525  			break;
526  		case AMDFW_OPT_SIGNED_ADDR:
527  			cb_config->signed_start_addr = strtoull(optarg, NULL, 10);
528  			sub = instance = 0;
529  			break;
530  		case LONGOPT_SPI_READ_MODE:
531  			cb_config->efs_spi_readmode = strtoull(optarg, NULL, 16);
532  			sub = instance = 0;
533  			break;
534  		case LONGOPT_SPI_SPEED:
535  			cb_config->efs_spi_speed = strtoull(optarg, NULL, 16);
536  			sub = instance = 0;
537  			break;
538  		case LONGOPT_SPI_MICRON_FLAG:
539  			cb_config->efs_spi_micron_flag = strtoull(optarg, NULL, 16);
540  			sub = instance = 0;
541  			break;
542  		case AMDFW_OPT_OUTPUT:
543  			cb_config->output = optarg;
544  			break;
545  		case AMDFW_OPT_FLASHSIZE:
546  			ctx->rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
547  			if (*tmp != '\0') {
548  				fprintf(stderr, "Error: ROM size specified"
549  					" incorrectly (%s)\n\n", optarg);
550  				retval = 1;
551  			}
552  			break;
553  		case AMDFW_OPT_LOCATION:
554  			cb_config->efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
555  			if (*tmp != '\0') {
556  				fprintf(stderr, "Error: Directory Location specified"
557  					" incorrectly (%s)\n\n", optarg);
558  				retval = 1;
559  			}
560  			if (cb_config->body_location == 0)
561  				cb_config->body_location = cb_config->efs_location;
562  			break;
563  		case AMDFW_OPT_ANYWHERE:
564  			any_location = 1;
565  			break;
566  		case AMDFW_OPT_SHAREDMEM:
567  			/* shared memory destination */
568  			register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
569  			sub = instance = 0;
570  			break;
571  		case AMDFW_OPT_SHAREDMEM_SIZE:
572  			/* shared memory size */
573  			register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
574  			sub = instance = 0;
575  			break;
576  		case LONGOPT_NVRAM_BASE:
577  			/* PSP NV base */
578  			register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
579  			sub = instance = 0;
580  			break;
581  		case LONGOPT_NVRAM_SIZE:
582  			/* PSP NV size */
583  			register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
584  			sub = instance = 0;
585  			break;
586  		case LONGOPT_RPMC_NVRAM_BASE:
587  			/* PSP RPMC NV base */
588  			register_amd_psp_fw_addr(AMD_RPMC_NVRAM, sub, optarg, 0);
589  			sub = instance = 0;
590  			break;
591  		case LONGOPT_RPMC_NVRAM_SIZE:
592  			/* PSP RPMC NV size */
593  			register_amd_psp_fw_addr(AMD_RPMC_NVRAM, sub, 0, optarg);
594  			sub = instance = 0;
595  			break;
596  		case AMDFW_OPT_CONFIG:
597  			cb_config->config = optarg;
598  			break;
599  		case AMDFW_OPT_DEBUG:
600  			cb_config->debug = 1;
601  			break;
602  		case AMDFW_OPT_HELP:
603  			usage();
604  			retval = 1;
605  			break;
606  		case AMDFW_OPT_BODY_LOCATION:
607  			cb_config->body_location = (uint32_t)strtoul(optarg, &tmp, 16);
608  			if (*tmp != '\0') {
609  				fprintf(stderr, "Error: Body Location specified"
610  					" incorrectly (%s)\n\n", optarg);
611  				retval = 1;
612  			}
613  			break;
614  
615  		default:
616  			break;
617  		}
618  	}
619  
620  	if (!fuse_defined)
621  		register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
622  
623  	if (!cb_config->output) {
624  		fprintf(stderr, "Error: Output value is not specified.\n\n");
625  		retval = 1;
626  	}
627  
628  	if (ctx->rom_size % 1024 != 0) {
629  		fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
630  			" 1024 bytes.\n\n", ctx->rom_size);
631  		retval = 1;
632  	}
633  
634  	if (ctx->rom_size < MIN_ROM_KB * 1024) {
635  		fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
636  			ctx->rom_size / 1024, MIN_ROM_KB);
637  		retval = 1;
638  	}
639  
640  	printf("    AMDFWTOOL  Using ROM size of %dKB\n", ctx->rom_size / 1024);
641  
642  	if (ctx->rom_size <= MAX_MAPPED_WINDOW) {
643  		uint32_t rom_base_address;
644  
645  		rom_base_address = 0xFFFFFFFF - ctx->rom_size + 1;
646  		if (cb_config->efs_location & ~MAX_MAPPED_WINDOW_MASK)
647  			cb_config->efs_location = cb_config->efs_location - rom_base_address;
648  		if (cb_config->body_location & ~MAX_MAPPED_WINDOW_MASK)
649  			cb_config->body_location = cb_config->body_location - rom_base_address;
650  	}
651  
652  	/* If the flash size is larger than 16M, we assume the given
653  	   addresses are already relative ones. Otherwise we print error.*/
654  	if (cb_config->efs_location && cb_config->efs_location > ctx->rom_size) {
655  		fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
656  		return 1;
657  	}
658  	if (cb_config->body_location && cb_config->body_location > ctx->rom_size) {
659  		fprintf(stderr, "Error: Body location outside of ROM.\n\n");
660  		return 1;
661  	}
662  
663  	if (!cb_config->efs_location && cb_config->body_location) {
664  		fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
665  		return 1;
666  	}
667  
668  	if (cb_config->body_location != cb_config->efs_location &&
669  			cb_config->body_location <
670  				ALIGN(cb_config->efs_location + sizeof(embedded_firmware),
671  					BLOB_ALIGNMENT)) {
672  		fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
673  		fprintf(stderr, "  Require safe spacing of 256 bytes\n");
674  		return 1;
675  	}
676  
677  	if (any_location) {
678  		if ((cb_config->body_location & 0x3f) || (cb_config->efs_location & 0x3f)) {
679  			fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
680  			fprintf(stderr, "  Valid locations are 64-byte aligned\n");
681  			return 1;
682  		}
683  	} else {
684  		/* efs_location is relative address now. */
685  		switch (cb_config->efs_location) {
686  		case 0:
687  		case 0xFA0000:
688  		case 0xF20000:
689  		case 0xE20000:
690  		case 0xC20000:
691  		case 0x820000:
692  		case 0x020000:
693  			break;
694  		case 0x7A0000:
695  		case 0x720000:
696  		case 0x620000:
697  		case 0x420000:
698  			/* Special cases for 8M. */
699  			if (ctx->rom_size != 0x800000) {
700  				fprintf(stderr, "Error: Invalid Directory location.\n");
701  				fprintf(stderr, "%x is only for 8M image size.", cb_config->efs_location);
702  				return 1;
703  			}
704  			break;
705  		case 0x3A0000:
706  		case 0x320000:
707  		case 0x220000:
708  			/* Special cases for 4M. */
709  			if (ctx->rom_size != 0x400000) {
710  				fprintf(stderr, "Error: Invalid Directory location.\n");
711  				fprintf(stderr, "%x is only for 4M image size.", cb_config->efs_location);
712  				return 1;
713  			}
714  			break;
715  		default:
716  			fprintf(stderr, "Error: Invalid Directory location.\n");
717  			fprintf(stderr, "  Valid locations are 0xFFFA0000, 0xFFF20000,\n");
718  			fprintf(stderr, "  0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
719  			fprintf(stderr, "  0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
720  			fprintf(stderr, "  0x820000, 0x020000\n");
721  			return 1;
722  		}
723  	}
724  
725  	printf("    AMDFWTOOL  Using firmware directory location of address: 0x%08x",
726  			cb_config->efs_location);
727  	if (cb_config->body_location != cb_config->efs_location)
728  		printf(" with a split body at: 0x%08x\n", cb_config->body_location);
729  	else
730  		printf("\n");
731  
732  	if (retval) {
733  		usage();
734  		return retval;
735  	}
736  
737  	return 0;
738  }