mb/dell: Add Latitude E5520 (Sandy Bridge)
[coreboot.git] / util / amdfwtool / opts.c
blob62bbc97ae56b480775480fd7106a40e2f2b90bca
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <getopt.h>
8 #include "amdfwtool.h"
10 #define MIN_ROM_KB 256
11 #define MAX_MAPPED_WINDOW (16 * MiB)
12 #define MAX_MAPPED_WINDOW_MASK (MAX_MAPPED_WINDOW - 1)
14 #define DEFAULT_SOFT_FUSE_CHAIN "0x1"
16 enum {
17 AMDFW_OPT_CONFIG = 'c',
18 AMDFW_OPT_DEBUG = 'd',
19 AMDFW_OPT_HELP = 'h',
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,
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,
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,
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,
75 static const char optstring[] = {AMDFW_OPT_CONFIG, ':',
76 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
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 },
131 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
132 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
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 }
140 static void usage(void)
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");
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");
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[];
222 static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
223 char *dst_str, char *size_str)
225 unsigned int i;
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;
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;
241 static void register_bios_fw_addr(amd_bios_type type, char *src_str,
242 char *dst_str, char *size_str)
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;
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);
256 return;
260 static void register_fw_token_unlock(void)
262 uint32_t i;
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;
268 amd_psp_fw_table[i].other = 1;
269 return;
273 static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
275 unsigned int i;
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;
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;
288 if (amd_psp_fw_table[i].subprog == sub) {
289 amd_psp_fw_table[i].filename = filename;
290 return;
295 static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
297 uint32_t i;
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;
309 static void register_fw_fuse(char *str)
311 uint32_t i;
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;
317 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
318 return;
322 void register_apcb_combo(amd_cb_config *cb_config, int combo_index, context *ctx)
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);
346 int amdfwtool_getopt(int argc, char *argv[], amd_cb_config *cb_config, context *ctx)
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;
356 while (1) {
357 int optindex = 0;
358 int bios_tbl_index = -1;
360 c = getopt_long(argc, argv, optstring, long_options, &optindex);
362 if (c == -1)
363 break;
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;
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;
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;
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;
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;
613 break;
615 default:
616 break;
620 if (!fuse_defined)
621 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
623 if (!cb_config->output) {
624 fprintf(stderr, "Error: Output value is not specified.\n\n");
625 retval = 1;
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;
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;
640 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx->rom_size / 1024);
642 if (ctx->rom_size <= MAX_MAPPED_WINDOW) {
643 uint32_t rom_base_address;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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");
732 if (retval) {
733 usage();
734 return retval;
737 return 0;