blob: 511ffd02db91ec1d3479b7fd835ef94ea4388124 [file] [log] [blame]
Zheng Baoe35c5022023-10-11 16:08:44 +08001/* 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
16enum {
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
73static const char optstring[] = {AMDFW_OPT_CONFIG, ':',
74 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
75};
76
77static 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
136static 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
212extern amd_fw_entry amd_psp_fw_table[];
213extern amd_bios_entry amd_bios_table[];
214extern amd_fw_entry amd_fw_table[];
215
216static 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
235static 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
254static 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
267static 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
289static 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
303static 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
316void 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
340int 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}