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