1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * ROMSIG At ROMBASE + 0x20000:
6 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
9 * | PSPDIR ADDR|PSPDIR ADDR |<-- Field 0x14 could be either
10 * +------------+---------------+ 2nd PSP directory or PSP COMBO directory
11 * EC ROM should be 64K aligned.
13 * PSP directory (Where "PSPDIR ADDR" points)
14 * +------------+---------------+----------------+------------+
15 * | 'PSP$' | Fletcher | Count | Reserved |
16 * +------------+---------------+----------------+------------+
17 * | 0 | size | Base address | Reserved | Pubkey
18 * +------------+---------------+----------------+------------+
19 * | 1 | size | Base address | Reserved | Bootloader
20 * +------------+---------------+----------------+------------+
21 * | 8 | size | Base address | Reserved | Smu Firmware
22 * +------------+---------------+----------------+------------+
23 * | 3 | size | Base address | Reserved | Recovery Firmware
24 * +------------+---------------+----------------+------------+
27 * | Other PSP Firmware |
30 * +------------+---------------+----------------+------------+
33 * +------------+---------------+----------------+------------+
34 * | 'PSP2' | Fletcher | Count |Look up mode|
35 * +------------+---------------+----------------+------------+
37 * +------------+---------------+----------------+------------+
38 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
39 * +------------+---------------+----------------+------------+
40 * | ID-Sel | PSP ID | PSPDIR ADDR | | 3rd PSP directory
41 * +------------+---------------+----------------+------------+
45 * +------------+---------------+----------------+------------+
54 #include <sys/types.h>
60 #define AMD_ROMSIG_OFFSET 0x20000
61 #define MIN_ROM_KB 256
63 #define ALIGN(val, by) (((val) + (by) - 1) & ~((by) - 1))
64 #define _MAX(A, B) (((A) > (B)) ? (A) : (B))
65 #define ERASE_ALIGNMENT 0x1000U
66 #define TABLE_ALIGNMENT 0x1000U
67 #define BLOB_ALIGNMENT 0x100U
68 #define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
69 #define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
71 #define DEFAULT_SOFT_FUSE_CHAIN "0x1"
73 #define EMBEDDED_FW_SIGNATURE 0x55aa55aa
74 #define PSP_COOKIE 0x50535024 /* 'PSP$' */
75 #define PSPL2_COOKIE 0x324c5024 /* '2LP$' */
76 #define PSP2_COOKIE 0x50535032 /* 'PSP2' */
77 #define BDT1_COOKIE 0x44484224 /* 'DHB$ */
78 #define BDT2_COOKIE 0x324c4224 /* '2LB$ */
81 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
82 * can support an optional "combo" implementation. If the PSP sees the
83 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
84 * tables. Using this, support for multiple product generations may be
85 * built into one image. If the PSP$ cookie is found, the table is a
86 * normal directory table.
88 * Modern generations supporting the combo directories require the
89 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
90 * regardless of the type of directory used. The --combo-capable
91 * argument enforces this placement.
93 * TODO: Future work may require fully implementing the PSP_COMBO feature.
97 #if defined(__GLIBC__)
98 typedef unsigned long long int uint64_t;
99 typedef unsigned int uint32_t;
100 typedef unsigned char uint8_t;
101 typedef unsigned short uint16_t;
105 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
106 * The checksum field of the passed PDU does not need to be reset to zero.
108 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
109 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
110 * alternative to cyclical redundancy checks because it provides error-
111 * detection properties similar to cyclical redundancy checks but at the
112 * cost of a simple summation technique. Its characteristics were first
113 * published in IEEE Transactions on Communications in January 1982. One
114 * version has been adopted by ISO for use in the class-4 transport layer
115 * of the network protocol.
117 * This program expects:
118 * stdin: The input file to compute a checksum for. The input file
119 * not be longer than 256 bytes.
120 * stdout: Copied from the input file with the Fletcher's Checksum
121 * inserted 8 bytes after the beginning of the file.
122 * stderr: Used to print out error messages.
124 static uint32_t fletcher32(const void *data
, int length
)
130 const uint16_t *pptr
= data
;
138 index
= length
>= 359 ? 359 : length
;
144 c0
= (c0
& 0xFFFF) + (c0
>> 16);
145 c1
= (c1
& 0xFFFF) + (c1
>> 16);
148 /* Sums[0,1] mod 64K + overflow */
149 c0
= (c0
& 0xFFFF) + (c0
>> 16);
150 c1
= (c1
& 0xFFFF) + (c1
>> 16);
151 checksum
= (c1
<< 16) | c0
;
156 static void usage(void)
158 printf("amdfwtool: Create AMD Firmware combination\n");
159 printf("Usage: amdfwtool [options] -f <size> -o <filename>\n");
160 printf("-x | --xhci <FILE> Add XHCI blob\n");
161 printf("-i | --imc <FILE> Add IMC blob\n");
162 printf("-g | --gec <FILE> Add GEC blob\n");
164 printf("\nPSP options:\n");
165 printf("-A | --combo-capable Place PSP directory pointer at Embedded Firmware\n");
166 printf(" offset able to support combo directory\n");
167 printf("-M | --multilevel Generate primary and secondary tables\n");
168 printf("-p | --pubkey <FILE> Add pubkey\n");
169 printf("-b | --bootloader <FILE> Add bootloader\n");
170 printf("-S | --subprogram <number> Sets subprogram field for the next firmware\n");
171 printf("-s | --smufirmware <FILE> Add smufirmware\n");
172 printf("-r | --recovery <FILE> Add recovery\n");
173 printf("-k | --rtmpubkey <FILE> Add rtmpubkey\n");
174 printf("-c | --secureos <FILE> Add secureos\n");
175 printf("-n | --nvram <FILE> Add nvram\n");
176 printf("-d | --securedebug <FILE> Add securedebug\n");
177 printf("-t | --trustlets <FILE> Add trustlets\n");
178 printf("-u | --trustletkey <FILE> Add trustletkey\n");
179 printf("-w | --smufirmware2 <FILE> Add smufirmware2\n");
180 printf("-m | --smuscs <FILE> Add smuscs\n");
181 printf("-T | --soft-fuse <HEX_VAL> Override default soft fuse values\n");
182 printf("-z | --abl-image <FILE> Add AGESA Binary\n");
183 printf("-J | --sec-gasket <FILE> Add security gasket\n");
184 printf("-B | --mp2-fw <FILE> Add MP2 firmware\n");
185 printf("-N | --secdebug <FILE> Add secure unlock image\n");
186 printf("-U | --token-unlock Reserve space for debug token\n");
187 printf("-K | --drv-entry-pts <FILE> Add PSP driver entry points\n");
188 printf("-L | --ikek <FILE> Add Wrapped iKEK\n");
189 printf("-Y | --s0i3drv <FILE> Add s0i3 driver\n");
190 printf("-Z | --verstage <FILE> Add verstage\n");
191 printf("\nBIOS options:\n");
192 printf("-I | --instance <number> Sets instance field for the next BIOS firmware\n");
193 printf("-a | --apcb <FILE> Add AGESA PSP customization block\n");
194 printf("-Q | --apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
195 printf("-F | --apob-nv-base <HEX_VAL> Location of S3 resume data\n");
196 printf("-H | --apob-nv-size <HEX_VAL> Size of S3 resume data\n");
197 printf("-y | --pmu-inst <FILE> Add PMU firmware instruction portion\n");
198 printf("-G | --pmu-data <FILE> Add PMU firmware data portion\n");
199 printf("-O | --ucode <FILE> Add microcode patch\n");
200 printf("-X | --mp2-config <FILE> Add MP2 configuration\n");
201 printf("-V | --bios-bin <FILE> Add compressed image; auto source address\n");
202 printf("-e | --bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
203 printf("-v | --bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
204 printf("-j | --bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
205 printf("\n-o | --output <filename> output filename\n");
206 printf("-f | --flashsize <HEX_VAL> ROM size in bytes\n");
207 printf(" size must be larger than %dKB\n",
209 printf(" and must a multiple of 1024\n");
210 printf("-l | --location Location of Directory\n");
211 printf("-q | --anywhere Use any 64-byte aligned addr for Directory\n");
212 printf("-R | --sharedmem Location of PSP/FW shared memory\n");
213 printf("-P | --sharedmem-size Maximum size of the PSP/FW shared memory area\n");
214 printf("-C | --soc-name <socname> Specify SOC name. Supported names are\n");
215 printf(" Stoneyridge, Raven, Picasso, Renoir or Lucienne");
216 printf("-h | --help show this help\n");
217 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
218 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
219 printf(" 0x0 66.66Mhz\n");
220 printf(" 0x1 33.33MHz\n");
221 printf(" 0x2 22.22MHz\n");
222 printf(" 0x3 16.66MHz\n");
223 printf(" 0x4 100MHz\n");
224 printf(" 0x5 800KHz\n");
225 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
226 printf(" 0x0 Normal Read (up to 33M)\n");
227 printf(" 0x1 Reserved\n");
228 printf(" 0x2 Dual IO (1-1-2)\n");
229 printf(" 0x3 Quad IO (1-1-4)\n");
230 printf(" 0x4 Dual IO (1-2-2)\n");
231 printf(" 0x5 Quad IO (1-4-4)\n");
232 printf(" 0x6 Normal Read (up to 66M)\n");
233 printf(" 0x7 Fast Read\n");
234 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
235 printf(" 0x0 Micron parts are not used\n");
236 printf(" 0x1 Micron parts are always used\n");
237 printf(" 0x2 Micron parts optional, this option is only\n");
238 printf(" supported with RN/LCN SOC\n");
241 typedef enum _amd_bios_type
{
242 AMD_BIOS_APCB
= 0x60,
243 AMD_BIOS_APOB
= 0x61,
245 AMD_BIOS_APOB_NV
= 0x63,
246 AMD_BIOS_PMUI
= 0x64,
247 AMD_BIOS_PMUD
= 0x65,
248 AMD_BIOS_UCODE
= 0x66,
249 AMD_BIOS_APCB_BK
= 0x68,
250 AMD_BIOS_MP2_CFG
= 0x6a,
251 AMD_BIOS_PSP_SHARED_MEM
= 0x6b,
252 AMD_BIOS_L2_PTR
= 0x70,
258 #define BDT_BOTH (BDT_LVL1 | BDT_LVL2)
259 typedef struct _amd_bios_entry
{
275 typedef enum _amd_fw_type
{
276 AMD_FW_PSP_PUBKEY
= 0,
277 AMD_FW_PSP_BOOTLOADER
= 1,
278 AMD_FW_PSP_SMU_FIRMWARE
= 8,
279 AMD_FW_PSP_RECOVERY
= 3,
280 AMD_FW_PSP_RTM_PUBKEY
= 5,
281 AMD_FW_PSP_SECURED_OS
= 2,
282 AMD_FW_PSP_NVRAM
= 4,
283 AMD_FW_PSP_SECURED_DEBUG
= 9,
284 AMD_FW_PSP_TRUSTLETS
= 12,
285 AMD_FW_PSP_TRUSTLETKEY
= 13,
286 AMD_FW_PSP_SMU_FIRMWARE2
= 18,
287 AMD_PSP_FUSE_CHAIN
= 11,
288 AMD_FW_PSP_SMUSCS
= 95,
289 AMD_DEBUG_UNLOCK
= 0x13,
290 AMD_WRAPPED_IKEK
= 0x21,
291 AMD_TOKEN_UNLOCK
= 0x22,
292 AMD_SEC_GASKET
= 0x24,
294 AMD_DRIVER_ENTRIES
= 0x28,
295 AMD_S0I3_DRIVER
= 0x2d,
304 AMD_FW_PSP_WHITELIST
= 0x3a,
305 AMD_FW_L2_PTR
= 0x40,
306 AMD_FW_PSP_VERSTAGE
= 0x52,
307 AMD_FW_VERSTAGE_SIG
= 0x53,
316 #define PSP_BOTH (PSP_LVL1 | PSP_LVL2)
317 typedef struct _amd_fw_entry
{
325 static amd_fw_entry amd_psp_fw_table
[] = {
326 { .type
= AMD_FW_PSP_PUBKEY
, .level
= PSP_BOTH
},
327 { .type
= AMD_FW_PSP_BOOTLOADER
, .level
= PSP_BOTH
},
328 { .type
= AMD_FW_PSP_SMU_FIRMWARE
, .subprog
= 0, .level
= PSP_BOTH
},
329 { .type
= AMD_FW_PSP_RECOVERY
, .level
= PSP_LVL1
},
330 { .type
= AMD_FW_PSP_RTM_PUBKEY
, .level
= PSP_BOTH
},
331 { .type
= AMD_FW_PSP_SECURED_OS
, .level
= PSP_LVL2
},
332 { .type
= AMD_FW_PSP_NVRAM
, .level
= PSP_LVL2
},
333 { .type
= AMD_FW_PSP_SMU_FIRMWARE
, .subprog
= 2, .level
= PSP_BOTH
},
334 { .type
= AMD_FW_PSP_SECURED_DEBUG
, .level
= PSP_LVL2
},
335 { .type
= AMD_FW_PSP_TRUSTLETS
, .level
= PSP_LVL2
},
336 { .type
= AMD_FW_PSP_TRUSTLETKEY
, .level
= PSP_LVL2
},
337 { .type
= AMD_FW_PSP_SMU_FIRMWARE2
, .subprog
= 2, .level
= PSP_BOTH
},
338 { .type
= AMD_FW_PSP_SMU_FIRMWARE
, .subprog
= 1, .level
= PSP_BOTH
},
339 { .type
= AMD_FW_PSP_SMU_FIRMWARE2
, .subprog
= 1, .level
= PSP_BOTH
},
340 { .type
= AMD_FW_PSP_SMU_FIRMWARE2
, .level
= PSP_BOTH
},
341 { .type
= AMD_FW_PSP_SMUSCS
, .level
= PSP_BOTH
},
342 { .type
= AMD_PSP_FUSE_CHAIN
, .level
= PSP_LVL2
},
343 { .type
= AMD_DEBUG_UNLOCK
, .level
= PSP_LVL2
},
344 { .type
= AMD_WRAPPED_IKEK
, .level
= PSP_BOTH
},
345 { .type
= AMD_TOKEN_UNLOCK
, .level
= PSP_BOTH
},
346 { .type
= AMD_SEC_GASKET
, .subprog
= 2, .level
= PSP_BOTH
},
347 { .type
= AMD_SEC_GASKET
, .subprog
= 1, .level
= PSP_BOTH
},
348 { .type
= AMD_MP2_FW
, .subprog
= 2, .level
= PSP_LVL2
},
349 { .type
= AMD_MP2_FW
, .subprog
= 1, .level
= PSP_LVL2
},
350 { .type
= AMD_DRIVER_ENTRIES
, .level
= PSP_LVL2
},
351 { .type
= AMD_S0I3_DRIVER
, .level
= PSP_LVL2
},
352 { .type
= AMD_ABL0
, .level
= PSP_BOTH
},
353 { .type
= AMD_ABL1
, .level
= PSP_BOTH
},
354 { .type
= AMD_ABL2
, .level
= PSP_BOTH
},
355 { .type
= AMD_ABL3
, .level
= PSP_BOTH
},
356 { .type
= AMD_ABL4
, .level
= PSP_BOTH
},
357 { .type
= AMD_ABL5
, .level
= PSP_BOTH
},
358 { .type
= AMD_ABL6
, .level
= PSP_BOTH
},
359 { .type
= AMD_ABL7
, .level
= PSP_BOTH
},
360 { .type
= AMD_FW_PSP_SMU_FIRMWARE
, .subprog
= 1, .level
= PSP_BOTH
},
361 { .type
= AMD_FW_PSP_SMU_FIRMWARE2
, .subprog
= 1, .level
= PSP_BOTH
},
362 { .type
= AMD_FW_PSP_WHITELIST
, .level
= PSP_LVL2
},
363 { .type
= AMD_FW_PSP_VERSTAGE
, .level
= PSP_BOTH
},
364 { .type
= AMD_FW_VERSTAGE_SIG
, .level
= PSP_BOTH
},
365 { .type
= AMD_FW_INVALID
},
368 static amd_fw_entry amd_fw_table
[] = {
369 { .type
= AMD_FW_XHCI
},
370 { .type
= AMD_FW_IMC
},
371 { .type
= AMD_FW_GEC
},
372 { .type
= AMD_FW_INVALID
},
375 static amd_bios_entry amd_bios_table
[] = {
376 { .type
= AMD_BIOS_APCB
, .inst
= 0, .level
= BDT_BOTH
},
377 { .type
= AMD_BIOS_APCB
, .inst
= 1, .level
= BDT_BOTH
},
378 { .type
= AMD_BIOS_APCB
, .inst
= 2, .level
= BDT_BOTH
},
379 { .type
= AMD_BIOS_APCB
, .inst
= 3, .level
= BDT_BOTH
},
380 { .type
= AMD_BIOS_APCB
, .inst
= 4, .level
= BDT_BOTH
},
381 { .type
= AMD_BIOS_APCB
, .inst
= 5, .level
= BDT_BOTH
},
382 { .type
= AMD_BIOS_APCB
, .inst
= 6, .level
= BDT_BOTH
},
383 { .type
= AMD_BIOS_APCB
, .inst
= 7, .level
= BDT_BOTH
},
384 { .type
= AMD_BIOS_APCB
, .inst
= 8, .level
= BDT_BOTH
},
385 { .type
= AMD_BIOS_APCB
, .inst
= 9, .level
= BDT_BOTH
},
386 { .type
= AMD_BIOS_APCB
, .inst
= 10, .level
= BDT_BOTH
},
387 { .type
= AMD_BIOS_APCB
, .inst
= 11, .level
= BDT_BOTH
},
388 { .type
= AMD_BIOS_APCB
, .inst
= 12, .level
= BDT_BOTH
},
389 { .type
= AMD_BIOS_APCB
, .inst
= 13, .level
= BDT_BOTH
},
390 { .type
= AMD_BIOS_APCB
, .inst
= 14, .level
= BDT_BOTH
},
391 { .type
= AMD_BIOS_APCB
, .inst
= 15, .level
= BDT_BOTH
},
392 { .type
= AMD_BIOS_APCB_BK
, .inst
= 0, .level
= BDT_BOTH
},
393 { .type
= AMD_BIOS_APCB_BK
, .inst
= 1, .level
= BDT_BOTH
},
394 { .type
= AMD_BIOS_APCB_BK
, .inst
= 2, .level
= BDT_BOTH
},
395 { .type
= AMD_BIOS_APCB_BK
, .inst
= 3, .level
= BDT_BOTH
},
396 { .type
= AMD_BIOS_APCB_BK
, .inst
= 4, .level
= BDT_BOTH
},
397 { .type
= AMD_BIOS_APCB_BK
, .inst
= 5, .level
= BDT_BOTH
},
398 { .type
= AMD_BIOS_APCB_BK
, .inst
= 6, .level
= BDT_BOTH
},
399 { .type
= AMD_BIOS_APCB_BK
, .inst
= 7, .level
= BDT_BOTH
},
400 { .type
= AMD_BIOS_APCB_BK
, .inst
= 8, .level
= BDT_BOTH
},
401 { .type
= AMD_BIOS_APCB_BK
, .inst
= 9, .level
= BDT_BOTH
},
402 { .type
= AMD_BIOS_APCB_BK
, .inst
= 10, .level
= BDT_BOTH
},
403 { .type
= AMD_BIOS_APCB_BK
, .inst
= 11, .level
= BDT_BOTH
},
404 { .type
= AMD_BIOS_APCB_BK
, .inst
= 12, .level
= BDT_BOTH
},
405 { .type
= AMD_BIOS_APCB_BK
, .inst
= 13, .level
= BDT_BOTH
},
406 { .type
= AMD_BIOS_APCB_BK
, .inst
= 14, .level
= BDT_BOTH
},
407 { .type
= AMD_BIOS_APCB_BK
, .inst
= 15, .level
= BDT_BOTH
},
408 { .type
= AMD_BIOS_APOB
, .level
= BDT_BOTH
},
409 { .type
= AMD_BIOS_BIN
,
410 .reset
= 1, .copy
= 1, .zlib
= 1, .level
= BDT_BOTH
},
411 { .type
= AMD_BIOS_APOB_NV
, .level
= BDT_LVL2
},
412 { .type
= AMD_BIOS_PMUI
, .inst
= 1, .subpr
= 0, .level
= BDT_BOTH
},
413 { .type
= AMD_BIOS_PMUD
, .inst
= 1, .subpr
= 0, .level
= BDT_BOTH
},
414 { .type
= AMD_BIOS_PMUI
, .inst
= 4, .subpr
= 0, .level
= BDT_BOTH
},
415 { .type
= AMD_BIOS_PMUD
, .inst
= 4, .subpr
= 0, .level
= BDT_BOTH
},
416 { .type
= AMD_BIOS_PMUI
, .inst
= 1, .subpr
= 1, .level
= BDT_BOTH
},
417 { .type
= AMD_BIOS_PMUD
, .inst
= 1, .subpr
= 1, .level
= BDT_BOTH
},
418 { .type
= AMD_BIOS_PMUI
, .inst
= 4, .subpr
= 1, .level
= BDT_BOTH
},
419 { .type
= AMD_BIOS_PMUD
, .inst
= 4, .subpr
= 1, .level
= BDT_BOTH
},
420 { .type
= AMD_BIOS_UCODE
, .inst
= 0, .level
= BDT_LVL2
},
421 { .type
= AMD_BIOS_UCODE
, .inst
= 1, .level
= BDT_LVL2
},
422 { .type
= AMD_BIOS_UCODE
, .inst
= 2, .level
= BDT_LVL2
},
423 { .type
= AMD_BIOS_MP2_CFG
, .level
= BDT_LVL2
},
424 { .type
= AMD_BIOS_PSP_SHARED_MEM
, .inst
= 0, .level
= BDT_BOTH
},
425 { .type
= AMD_BIOS_INVALID
},
428 typedef struct _embedded_firmware
{
429 uint32_t signature
; /* 0x55aa55aa */
435 uint32_t bios0_entry
; /* todo: add way to select correct entry */
436 uint32_t bios1_entry
;
437 uint32_t bios2_entry
;
438 uint32_t second_gen_efs
;
439 uint32_t bios3_entry
;
440 uint32_t reserved_2Ch
;
441 uint32_t promontory_fw_ptr
;
442 uint32_t lp_promontory_fw_ptr
;
443 uint32_t reserved_38h
;
444 uint32_t reserved_3Ch
;
445 uint8_t spi_readmode_f15_mod_60_6f
;
446 uint8_t fast_speed_new_f15_mod_60_6f
;
447 uint8_t reserved_42h
;
448 uint8_t spi_readmode_f17_mod_00_2f
;
449 uint8_t spi_fastspeed_f17_mod_00_2f
;
450 uint8_t qpr_dummy_cycle_f17_mod_00_2f
;
451 uint8_t reserved_46h
;
452 uint8_t spi_readmode_f17_mod_30_3f
;
453 uint8_t spi_fastspeed_f17_mod_30_3f
;
454 uint8_t micron_detect_f17_mod_30_3f
;
455 uint8_t reserved_4Ah
;
456 uint8_t reserved_4Bh
;
457 uint32_t reserved_4Ch
;
458 } __attribute__((packed
, aligned(16))) embedded_firmware
;
460 typedef struct _psp_directory_header
{
463 uint32_t num_entries
;
465 } __attribute__((packed
, aligned(16))) psp_directory_header
;
467 typedef struct _psp_directory_entry
{
472 uint64_t addr
; /* or a value in some cases */
473 } __attribute__((packed
)) psp_directory_entry
;
475 typedef struct _psp_directory_table
{
476 psp_directory_header header
;
477 psp_directory_entry entries
[];
478 } __attribute__((packed
)) psp_directory_table
;
480 #define MAX_PSP_ENTRIES 0x1f
482 typedef struct _psp_combo_header
{
485 uint32_t num_entries
;
487 uint64_t reserved
[2];
488 } __attribute__((packed
, aligned(16))) psp_combo_header
;
490 typedef struct _psp_combo_entry
{
494 } __attribute__((packed
)) psp_combo_entry
;
496 typedef struct _psp_combo_directory
{
497 psp_combo_header header
;
498 psp_combo_entry entries
[];
499 } __attribute__((packed
)) psp_combo_directory
;
501 #define MAX_COMBO_ENTRIES 1
503 typedef struct _bios_directory_hdr
{
506 uint32_t num_entries
;
508 } __attribute__((packed
, aligned(16))) bios_directory_hdr
;
510 typedef struct _bios_directory_entry
{
518 uint8_t subprog
; /* b[7:3] reserved */
522 } __attribute__((packed
)) bios_directory_entry
;
524 typedef struct _bios_directory_table
{
525 bios_directory_hdr header
;
526 bios_directory_entry entries
[];
527 } bios_directory_table
;
529 #define MAX_BIOS_ENTRIES 0x2f
531 typedef struct _context
{
532 char *rom
; /* target buffer, size of flash device */
533 uint32_t rom_size
; /* size of flash device */
534 uint32_t current
; /* pointer within flash & proxy buffer */
537 #define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
538 #define RUN_OFFSET(ctx, offset) (RUN_BASE(ctx) + (offset))
539 #define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
540 #define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
541 #define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
542 #define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
543 #define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
545 static void *new_psp_dir(context
*ctx
, int multi
)
550 * Force both onto boundary when multi. Primary table is after
551 * updatable table, so alignment ensures primary can stay intact
552 * if secondary is reprogrammed.
555 ctx
->current
= ALIGN(ctx
->current
, TABLE_ERASE_ALIGNMENT
);
557 ctx
->current
= ALIGN(ctx
->current
, TABLE_ALIGNMENT
);
559 ptr
= BUFF_CURRENT(*ctx
);
560 ctx
->current
+= sizeof(psp_directory_header
)
561 + MAX_PSP_ENTRIES
* sizeof(psp_directory_entry
);
566 static void *new_combo_dir(context
*ctx
)
570 ctx
->current
= ALIGN(ctx
->current
, TABLE_ALIGNMENT
);
571 ptr
= BUFF_CURRENT(*ctx
);
572 ctx
->current
+= sizeof(psp_combo_header
)
573 + MAX_COMBO_ENTRIES
* sizeof(psp_combo_entry
);
578 static void fill_dir_header(void *directory
, uint32_t count
, uint32_t cookie
)
580 psp_combo_directory
*cdir
= directory
;
581 psp_directory_table
*dir
= directory
;
582 bios_directory_table
*bdir
= directory
;
589 /* caller is responsible for lookup mode */
590 cdir
->header
.cookie
= cookie
;
591 cdir
->header
.num_entries
= count
;
592 cdir
->header
.reserved
[0] = 0;
593 cdir
->header
.reserved
[1] = 0;
594 /* checksum everything that comes after the Checksum field */
595 cdir
->header
.checksum
= fletcher32(&cdir
->header
.num_entries
,
596 count
* sizeof(psp_combo_entry
)
597 + sizeof(cdir
->header
.num_entries
)
598 + sizeof(cdir
->header
.lookup
)
599 + 2 * sizeof(cdir
->header
.reserved
[0]));
603 dir
->header
.cookie
= cookie
;
604 dir
->header
.num_entries
= count
;
605 dir
->header
.reserved
= 0;
606 /* checksum everything that comes after the Checksum field */
607 dir
->header
.checksum
= fletcher32(&dir
->header
.num_entries
,
608 count
* sizeof(psp_directory_entry
)
609 + sizeof(dir
->header
.num_entries
)
610 + sizeof(dir
->header
.reserved
));
614 bdir
->header
.cookie
= cookie
;
615 bdir
->header
.num_entries
= count
;
616 bdir
->header
.reserved
= 0;
617 /* checksum everything that comes after the Checksum field */
618 bdir
->header
.checksum
= fletcher32(&bdir
->header
.num_entries
,
619 count
* sizeof(bios_directory_entry
)
620 + sizeof(bdir
->header
.num_entries
)
621 + sizeof(bdir
->header
.reserved
));
626 static ssize_t
copy_blob(void *dest
, const char *src_file
, size_t room
)
632 fd
= open(src_file
, O_RDONLY
);
634 printf("Error opening file: %s: %s\n",
635 src_file
, strerror(errno
));
639 if (fstat(fd
, &fd_stat
)) {
640 printf("fstat error: %s\n", strerror(errno
));
645 if ((size_t)fd_stat
.st_size
> room
) {
646 printf("Error: %s will not fit. Exiting.\n", src_file
);
651 bytes
= read(fd
, dest
, (size_t)fd_stat
.st_size
);
653 if (bytes
!= (ssize_t
)fd_stat
.st_size
) {
654 printf("Error while reading %s\n", src_file
);
661 static void integrate_firmwares(context
*ctx
,
662 embedded_firmware
*romsig
,
663 amd_fw_entry
*fw_table
)
668 ctx
->current
+= sizeof(embedded_firmware
);
669 ctx
->current
= ALIGN(ctx
->current
, BLOB_ALIGNMENT
);
671 for (i
= 0; fw_table
[i
].type
!= AMD_FW_INVALID
; i
++) {
672 if (fw_table
[i
].filename
!= NULL
) {
673 switch (fw_table
[i
].type
) {
675 ctx
->current
= ALIGN(ctx
->current
, 0x10000U
);
676 romsig
->imc_entry
= RUN_CURRENT(*ctx
);
679 romsig
->gec_entry
= RUN_CURRENT(*ctx
);
682 romsig
->xhci_entry
= RUN_CURRENT(*ctx
);
689 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
690 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
696 ctx
->current
= ALIGN(ctx
->current
+ bytes
,
702 static void integrate_psp_firmwares(context
*ctx
,
703 psp_directory_table
*pspdir
,
704 psp_directory_table
*pspdir2
,
705 amd_fw_entry
*fw_table
,
709 unsigned int i
, count
;
712 /* This function can create a primary table, a secondary table, or a
713 * flattened table which contains all applicable types. These if-else
714 * statements infer what the caller intended. If a 2nd-level cookie
715 * is passed, clearly a 2nd-level table is intended. However, a
716 * 1st-level cookie may indicate level 1 or flattened. If the caller
717 * passes a pointer to a 2nd-level table, then assume not flat.
719 if (cookie
== PSPL2_COOKIE
)
726 ctx
->current
= ALIGN(ctx
->current
, BLOB_ALIGNMENT
);
728 for (i
= 0, count
= 0; fw_table
[i
].type
!= AMD_FW_INVALID
; i
++) {
729 if (!(fw_table
[i
].level
& level
))
732 if (fw_table
[i
].type
== AMD_TOKEN_UNLOCK
) {
733 if (!fw_table
[i
].other
)
735 ctx
->current
= ALIGN(ctx
->current
, ERASE_ALIGNMENT
);
736 pspdir
->entries
[count
].type
= fw_table
[i
].type
;
737 pspdir
->entries
[count
].size
= 4096; /* TODO: doc? */
738 pspdir
->entries
[count
].addr
= RUN_CURRENT(*ctx
);
739 pspdir
->entries
[count
].subprog
= fw_table
[i
].subprog
;
740 pspdir
->entries
[count
].rsvd
= 0;
741 ctx
->current
= ALIGN(ctx
->current
+ 4096, 0x100U
);
743 } else if (fw_table
[i
].type
== AMD_PSP_FUSE_CHAIN
) {
744 pspdir
->entries
[count
].type
= fw_table
[i
].type
;
745 pspdir
->entries
[count
].subprog
= fw_table
[i
].subprog
;
746 pspdir
->entries
[count
].rsvd
= 0;
747 pspdir
->entries
[count
].size
= 0xFFFFFFFF;
748 pspdir
->entries
[count
].addr
= fw_table
[i
].other
;
750 } else if (fw_table
[i
].type
== AMD_FW_PSP_NVRAM
) {
751 if (fw_table
[i
].filename
== NULL
)
753 /* TODO: Add a way to reserve for NVRAM without
754 * requiring a filename. This isn't a feature used
755 * by coreboot systems, so priority is very low.
757 ctx
->current
= ALIGN(ctx
->current
, ERASE_ALIGNMENT
);
758 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
759 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
765 pspdir
->entries
[count
].type
= fw_table
[i
].type
;
766 pspdir
->entries
[count
].subprog
= fw_table
[i
].subprog
;
767 pspdir
->entries
[count
].rsvd
= 0;
768 pspdir
->entries
[count
].size
= ALIGN(bytes
,
770 pspdir
->entries
[count
].addr
= RUN_CURRENT(*ctx
);
772 ctx
->current
= ALIGN(ctx
->current
+ bytes
,
773 BLOB_ERASE_ALIGNMENT
);
775 } else if (fw_table
[i
].filename
!= NULL
) {
776 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
777 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
783 pspdir
->entries
[count
].type
= fw_table
[i
].type
;
784 pspdir
->entries
[count
].subprog
= fw_table
[i
].subprog
;
785 pspdir
->entries
[count
].rsvd
= 0;
786 pspdir
->entries
[count
].size
= (uint32_t)bytes
;
787 pspdir
->entries
[count
].addr
= RUN_CURRENT(*ctx
);
789 ctx
->current
= ALIGN(ctx
->current
+ bytes
,
793 /* This APU doesn't have this firmware. */
798 pspdir
->entries
[count
].type
= AMD_FW_L2_PTR
;
799 pspdir
->entries
[count
].subprog
= 0;
800 pspdir
->entries
[count
].rsvd
= 0;
801 pspdir
->entries
[count
].size
= sizeof(pspdir2
->header
)
802 + pspdir2
->header
.num_entries
803 * sizeof(psp_directory_entry
);
805 pspdir
->entries
[count
].addr
= BUFF_TO_RUN(*ctx
, pspdir2
);
809 if (count
> MAX_PSP_ENTRIES
) {
810 printf("Error: PSP entries exceed max allowed items\n");
815 fill_dir_header(pspdir
, count
, cookie
);
818 static void *new_bios_dir(context
*ctx
, int multi
)
823 * Force both onto boundary when multi. Primary table is after
824 * updatable table, so alignment ensures primary can stay intact
825 * if secondary is reprogrammed.
828 ctx
->current
= ALIGN(ctx
->current
, TABLE_ERASE_ALIGNMENT
);
830 ctx
->current
= ALIGN(ctx
->current
, TABLE_ALIGNMENT
);
831 ptr
= BUFF_CURRENT(*ctx
);
832 ctx
->current
+= sizeof(bios_directory_hdr
)
833 + MAX_BIOS_ENTRIES
* sizeof(bios_directory_entry
);
837 static int locate_bdt2_bios(bios_directory_table
*level2
,
838 uint64_t *source
, uint32_t *size
)
847 for (i
= 0 ; i
< level2
->header
.num_entries
; i
++) {
848 if (level2
->entries
[i
].type
== AMD_BIOS_BIN
) {
849 *source
= level2
->entries
[i
].source
;
850 *size
= level2
->entries
[i
].size
;
857 static int have_bios_tables(amd_bios_entry
*table
)
861 for (i
= 0 ; table
[i
].type
!= AMD_BIOS_INVALID
; i
++) {
862 if (table
[i
].level
& BDT_LVL1
&& table
[i
].filename
)
868 static int find_bios_entry(amd_bios_type type
)
872 for (i
= 0; amd_bios_table
[i
].type
!= AMD_BIOS_INVALID
; i
++) {
873 if (amd_bios_table
[i
].type
== type
)
879 static void integrate_bios_firmwares(context
*ctx
,
880 bios_directory_table
*biosdir
,
881 bios_directory_table
*biosdir2
,
882 amd_bios_entry
*fw_table
,
886 unsigned int i
, count
;
892 /* This function can create a primary table, a secondary table, or a
893 * flattened table which contains all applicable types. These if-else
894 * statements infer what the caller intended. If a 2nd-level cookie
895 * is passed, clearly a 2nd-level table is intended. However, a
896 * 1st-level cookie may indicate level 1 or flattened. If the caller
897 * passes a pointer to a 2nd-level table, then assume not flat.
899 if (cookie
== BDT2_COOKIE
)
906 ctx
->current
= ALIGN(ctx
->current
, BLOB_ALIGNMENT
);
908 for (i
= 0, count
= 0; fw_table
[i
].type
!= AMD_BIOS_INVALID
; i
++) {
909 if (!(fw_table
[i
].level
& level
))
911 if (fw_table
[i
].filename
== NULL
&& (
912 fw_table
[i
].type
!= AMD_BIOS_APOB
&&
913 fw_table
[i
].type
!= AMD_BIOS_APOB_NV
&&
914 fw_table
[i
].type
!= AMD_BIOS_L2_PTR
&&
915 fw_table
[i
].type
!= AMD_BIOS_BIN
&&
916 fw_table
[i
].type
!= AMD_BIOS_PSP_SHARED_MEM
))
919 /* BIOS Directory items may have additional requirements */
921 /* Check APOB_NV requirements */
922 if (fw_table
[i
].type
== AMD_BIOS_APOB_NV
) {
923 if (!fw_table
[i
].size
&& !fw_table
[i
].src
)
924 continue; /* APOB_NV not used */
925 if (fw_table
[i
].src
&& !fw_table
[i
].size
) {
926 printf("Error: APOB NV address provided, but no size\n");
930 /* If the APOB isn't used, APOB_NV isn't used either */
931 apob_idx
= find_bios_entry(AMD_BIOS_APOB
);
932 if (apob_idx
< 0 || !fw_table
[apob_idx
].dest
)
933 continue; /* APOV NV not supported */
936 /* APOB_DATA needs destination */
937 if (fw_table
[i
].type
== AMD_BIOS_APOB
&& !fw_table
[i
].dest
) {
938 printf("Error: APOB destination not provided\n");
943 /* BIOS binary must have destination and uncompressed size. If
944 * no filename given, then user must provide a source address.
946 if (fw_table
[i
].type
== AMD_BIOS_BIN
) {
947 if (!fw_table
[i
].dest
|| !fw_table
[i
].size
) {
948 printf("Error: BIOS binary destination and uncompressed size are required\n");
952 if (!fw_table
[i
].filename
&& !fw_table
[i
].src
) {
953 printf("Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
959 /* PSP_SHARED_MEM needs a destination and size */
960 if (fw_table
[i
].type
== AMD_BIOS_PSP_SHARED_MEM
&&
961 (!fw_table
[i
].dest
|| !fw_table
[i
].size
))
964 biosdir
->entries
[count
].type
= fw_table
[i
].type
;
965 biosdir
->entries
[count
].region_type
= fw_table
[i
].region_type
;
966 biosdir
->entries
[count
].dest
= fw_table
[i
].dest
?
967 fw_table
[i
].dest
: (uint64_t)-1;
968 biosdir
->entries
[count
].reset
= fw_table
[i
].reset
;
969 biosdir
->entries
[count
].copy
= fw_table
[i
].copy
;
970 biosdir
->entries
[count
].ro
= fw_table
[i
].ro
;
971 biosdir
->entries
[count
].compressed
= fw_table
[i
].zlib
;
972 biosdir
->entries
[count
].inst
= fw_table
[i
].inst
;
973 biosdir
->entries
[count
].subprog
= fw_table
[i
].subpr
;
975 switch (fw_table
[i
].type
) {
977 biosdir
->entries
[count
].size
= fw_table
[i
].size
;
978 biosdir
->entries
[count
].source
= fw_table
[i
].src
;
980 case AMD_BIOS_APOB_NV
:
981 if (fw_table
[i
].src
) {
982 /* If source is given, use that and its size */
983 biosdir
->entries
[count
].source
= fw_table
[i
].src
;
984 biosdir
->entries
[count
].size
= fw_table
[i
].size
;
986 /* Else reserve size bytes within amdfw.rom */
987 ctx
->current
= ALIGN(ctx
->current
, ERASE_ALIGNMENT
);
988 biosdir
->entries
[count
].source
= RUN_CURRENT(*ctx
);
989 biosdir
->entries
[count
].size
= ALIGN(
990 fw_table
[i
].size
, ERASE_ALIGNMENT
);
991 memset(BUFF_CURRENT(*ctx
), 0xff,
992 biosdir
->entries
[count
].size
);
993 ctx
->current
= ctx
->current
994 + biosdir
->entries
[count
].size
;
998 /* Don't make a 2nd copy, point to the same one */
999 if (level
== BDT_LVL1
&& locate_bdt2_bios(biosdir2
, &source
, &size
)) {
1000 biosdir
->entries
[count
].source
= source
;
1001 biosdir
->entries
[count
].size
= size
;
1005 /* level 2, or level 1 and no copy found in level 2 */
1006 biosdir
->entries
[count
].source
= fw_table
[i
].src
;
1007 biosdir
->entries
[count
].dest
= fw_table
[i
].dest
;
1008 biosdir
->entries
[count
].size
= fw_table
[i
].size
;
1010 if (!fw_table
[i
].filename
)
1013 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
1014 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
1020 biosdir
->entries
[count
].source
= RUN_CURRENT(*ctx
);
1022 ctx
->current
= ALIGN(ctx
->current
+ bytes
, 0x100U
);
1024 case AMD_BIOS_PSP_SHARED_MEM
:
1025 biosdir
->entries
[count
].dest
= fw_table
[i
].dest
;
1026 biosdir
->entries
[count
].size
= fw_table
[i
].size
;
1029 default: /* everything else is copied from input */
1030 if (fw_table
[i
].type
== AMD_BIOS_APCB
||
1031 fw_table
[i
].type
== AMD_BIOS_APCB_BK
)
1032 ctx
->current
= ALIGN(
1033 ctx
->current
, ERASE_ALIGNMENT
);
1035 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
1036 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
1042 biosdir
->entries
[count
].size
= (uint32_t)bytes
;
1043 biosdir
->entries
[count
].source
= RUN_CURRENT(*ctx
);
1045 ctx
->current
= ALIGN(ctx
->current
+ bytes
, 0x100U
);
1053 biosdir
->entries
[count
].type
= AMD_BIOS_L2_PTR
;
1054 biosdir
->entries
[count
].size
=
1056 * sizeof(bios_directory_entry
);
1057 biosdir
->entries
[count
].source
=
1058 BUFF_TO_RUN(*ctx
, biosdir2
);
1059 biosdir
->entries
[count
].subprog
= 0;
1060 biosdir
->entries
[count
].inst
= 0;
1061 biosdir
->entries
[count
].copy
= 0;
1062 biosdir
->entries
[count
].compressed
= 0;
1063 biosdir
->entries
[count
].dest
= -1;
1064 biosdir
->entries
[count
].reset
= 0;
1065 biosdir
->entries
[count
].ro
= 0;
1069 if (count
> MAX_BIOS_ENTRIES
) {
1070 printf("Error: BIOS entries (%d) exceeds max allowed items "
1071 "(%d)\n", count
, MAX_BIOS_ENTRIES
);
1076 fill_dir_header(biosdir
, count
, cookie
);
1080 /* begin after ASCII characters */
1081 LONGOPT_SPI_READ_MODE
= 256,
1082 LONGOPT_SPI_SPEED
= 257,
1083 LONGOPT_SPI_MICRON_FLAG
= 258,
1087 static const char *optstring
= "x:i:g:AMS:p:b:s:r:k:c:n:d:t:u:w:m:T:z:J:B:K:L:Y:N:UW:I:a:Q:V:e:v:j:y:G:O:X:F:H:o:f:l:hZ:qR:P:C:E:";
1089 static struct option long_options
[] = {
1090 {"xhci", required_argument
, 0, 'x' },
1091 {"imc", required_argument
, 0, 'i' },
1092 {"gec", required_argument
, 0, 'g' },
1093 /* PSP Directory Table items */
1094 {"combo-capable", no_argument
, 0, 'A' },
1095 {"multilevel", no_argument
, 0, 'M' },
1096 {"subprogram", required_argument
, 0, 'S' },
1097 {"pubkey", required_argument
, 0, 'p' },
1098 {"bootloader", required_argument
, 0, 'b' },
1099 {"smufirmware", required_argument
, 0, 's' },
1100 {"recovery", required_argument
, 0, 'r' },
1101 {"rtmpubkey", required_argument
, 0, 'k' },
1102 {"secureos", required_argument
, 0, 'c' },
1103 {"nvram", required_argument
, 0, 'n' },
1104 {"securedebug", required_argument
, 0, 'd' },
1105 {"trustlets", required_argument
, 0, 't' },
1106 {"trustletkey", required_argument
, 0, 'u' },
1107 {"smufirmware2", required_argument
, 0, 'w' },
1108 {"smuscs", required_argument
, 0, 'm' },
1109 {"soft-fuse", required_argument
, 0, 'T' },
1110 {"abl-image", required_argument
, 0, 'z' },
1111 {"sec-gasket", required_argument
, 0, 'J' },
1112 {"mp2-fw", required_argument
, 0, 'B' },
1113 {"drv-entry-pts", required_argument
, 0, 'K' },
1114 {"ikek", required_argument
, 0, 'L' },
1115 {"s0i3drv", required_argument
, 0, 'Y' },
1116 {"secdebug", required_argument
, 0, 'N' },
1117 {"token-unlock", no_argument
, 0, 'U' },
1118 {"whitelist", required_argument
, 0, 'W' },
1119 {"verstage", required_argument
, 0, 'Z' },
1120 {"verstage_sig", required_argument
, 0, 'E' },
1121 /* BIOS Directory Table items */
1122 {"instance", required_argument
, 0, 'I' },
1123 {"apcb", required_argument
, 0, 'a' },
1124 {"apob-base", required_argument
, 0, 'Q' },
1125 {"bios-bin", required_argument
, 0, 'V' },
1126 {"bios-bin-src", required_argument
, 0, 'e' },
1127 {"bios-bin-dest", required_argument
, 0, 'v' },
1128 {"bios-uncomp-size", required_argument
, 0, 'j' },
1129 {"pmu-inst", required_argument
, 0, 'y' },
1130 {"pmu-data", required_argument
, 0, 'G' },
1131 {"ucode", required_argument
, 0, 'O' },
1132 {"mp2-config", required_argument
, 0, 'X' },
1133 {"apob-nv-base", required_argument
, 0, 'F' },
1134 {"apob-nv-size", required_argument
, 0, 'H' },
1135 /* Embedded Firmware Structure items*/
1136 {"spi-read-mode", required_argument
, 0, LONGOPT_SPI_READ_MODE
},
1137 {"spi-speed", required_argument
, 0, LONGOPT_SPI_SPEED
},
1138 {"spi-micron-flag", required_argument
, 0, LONGOPT_SPI_MICRON_FLAG
},
1140 {"output", required_argument
, 0, 'o' },
1141 {"flashsize", required_argument
, 0, 'f' },
1142 {"location", required_argument
, 0, 'l' },
1143 {"anywhere", no_argument
, 0, 'q' },
1144 {"sharedmem", required_argument
, 0, 'R' },
1145 {"sharedmem-size", required_argument
, 0, 'P' },
1146 {"soc-name", required_argument
, 0, 'C' },
1147 {"help", no_argument
, 0, 'h' },
1151 static void register_fw_fuse(char *str
)
1155 for (i
= 0; i
< sizeof(amd_psp_fw_table
) / sizeof(amd_fw_entry
); i
++) {
1156 if (amd_psp_fw_table
[i
].type
!= AMD_PSP_FUSE_CHAIN
)
1159 amd_psp_fw_table
[i
].other
= strtoull(str
, NULL
, 16);
1164 static void register_fw_token_unlock(void)
1168 for (i
= 0; i
< sizeof(amd_psp_fw_table
) / sizeof(amd_fw_entry
); i
++) {
1169 if (amd_psp_fw_table
[i
].type
!= AMD_TOKEN_UNLOCK
)
1172 amd_psp_fw_table
[i
].other
= 1;
1177 static void register_fw_filename(amd_fw_type type
, uint8_t sub
, char filename
[])
1181 for (i
= 0; i
< sizeof(amd_fw_table
) / sizeof(amd_fw_entry
); i
++) {
1182 if (amd_fw_table
[i
].type
== type
) {
1183 amd_fw_table
[i
].filename
= filename
;
1188 for (i
= 0; i
< sizeof(amd_psp_fw_table
) / sizeof(amd_fw_entry
); i
++) {
1189 if (amd_psp_fw_table
[i
].type
!= type
)
1192 if (amd_psp_fw_table
[i
].subprog
== sub
) {
1193 amd_psp_fw_table
[i
].filename
= filename
;
1199 static void register_bdt_data(amd_bios_type type
, int sub
, int ins
, char name
[])
1203 for (i
= 0; i
< sizeof(amd_bios_table
) / sizeof(amd_bios_entry
); i
++) {
1204 if (amd_bios_table
[i
].type
== type
1205 && amd_bios_table
[i
].inst
== ins
1206 && amd_bios_table
[i
].subpr
== sub
) {
1207 amd_bios_table
[i
].filename
= name
;
1213 static void register_fw_addr(amd_bios_type type
, char *src_str
,
1214 char *dst_str
, char *size_str
)
1217 for (i
= 0; i
< sizeof(amd_bios_table
) / sizeof(amd_bios_entry
); i
++) {
1218 if (amd_bios_table
[i
].type
!= type
)
1222 amd_bios_table
[i
].src
= strtoull(src_str
, NULL
, 16);
1224 amd_bios_table
[i
].dest
= strtoull(dst_str
, NULL
, 16);
1226 amd_bios_table
[i
].size
= strtoul(size_str
, NULL
, 16);
1234 PLATFORM_STONEYRIDGE
,
1241 static int set_efs_table(uint8_t soc_id
, embedded_firmware
*amd_romsig
,
1242 uint8_t efs_spi_readmode
, uint8_t efs_spi_speed
,
1243 uint8_t efs_spi_micron_flag
)
1245 if ((efs_spi_readmode
== 0xFF) || (efs_spi_speed
== 0xFF)) {
1246 printf("Error: EFS read mode and SPI speed must be set\n");
1250 case PLATFORM_STONEYRIDGE
:
1251 amd_romsig
->second_gen_efs
= 0;
1252 amd_romsig
->spi_readmode_f15_mod_60_6f
= efs_spi_readmode
;
1253 amd_romsig
->fast_speed_new_f15_mod_60_6f
= efs_spi_speed
;
1255 case PLATFORM_RAVEN
:
1256 case PLATFORM_PICASSO
:
1257 amd_romsig
->second_gen_efs
= 0;
1258 amd_romsig
->spi_readmode_f17_mod_00_2f
= efs_spi_readmode
;
1259 amd_romsig
->spi_fastspeed_f17_mod_00_2f
= efs_spi_speed
;
1260 switch (efs_spi_micron_flag
) {
1262 amd_romsig
->qpr_dummy_cycle_f17_mod_00_2f
= 0xff;
1265 amd_romsig
->qpr_dummy_cycle_f17_mod_00_2f
= 0xa;
1268 printf("Error: EFS Micron flag must be correctly set.\n\n");
1272 case PLATFORM_RENOIR
:
1273 case PLATFORM_LUCIENNE
:
1274 amd_romsig
->second_gen_efs
= 1;
1275 amd_romsig
->spi_readmode_f17_mod_30_3f
= efs_spi_readmode
;
1276 amd_romsig
->spi_fastspeed_f17_mod_30_3f
= efs_spi_speed
;
1277 switch (efs_spi_micron_flag
) {
1279 amd_romsig
->micron_detect_f17_mod_30_3f
= 0xff;
1282 amd_romsig
->micron_detect_f17_mod_30_3f
= 0xaa;
1285 amd_romsig
->micron_detect_f17_mod_30_3f
= 0x55;
1288 printf("Error: EFS Micron flag must be correctly set.\n\n");
1292 case PLATFORM_UNKNOWN
:
1294 printf("Error: Invalid SOC name.\n\n");
1300 static int identify_platform(char *soc_name
)
1302 if (!strcasecmp(soc_name
, "Stoneyridge"))
1303 return PLATFORM_STONEYRIDGE
;
1304 else if (!strcasecmp(soc_name
, "Raven"))
1305 return PLATFORM_RAVEN
;
1306 else if (!strcasecmp(soc_name
, "Picasso"))
1307 return PLATFORM_PICASSO
;
1308 else if (!strcasecmp(soc_name
, "Renoir"))
1309 return PLATFORM_RENOIR
;
1310 else if (!strcasecmp(soc_name
, "Lucienne"))
1311 return PLATFORM_LUCIENNE
;
1313 return PLATFORM_UNKNOWN
;
1317 int main(int argc
, char **argv
)
1323 embedded_firmware
*amd_romsig
;
1324 psp_directory_table
*pspdir
;
1326 int fuse_defined
= 0;
1328 char *output
= NULL
;
1329 context ctx
= { 0 };
1330 /* Values cleared after each firmware or parameter, regardless if N/A */
1331 uint8_t sub
= 0, instance
= 0;
1333 uint32_t dir_location
= 0;
1334 bool any_location
= 0;
1335 uint32_t romsig_offset
;
1336 uint32_t rom_base_address
;
1337 uint8_t soc_id
= PLATFORM_UNKNOWN
;
1338 uint8_t efs_spi_readmode
= 0xff;
1339 uint8_t efs_spi_speed
= 0xff;
1340 uint8_t efs_spi_micron_flag
= 0xff;
1347 c
= getopt_long(argc
, argv
, optstring
, long_options
, &optindex
);
1354 register_fw_filename(AMD_FW_XHCI
, sub
, optarg
);
1358 register_fw_filename(AMD_FW_IMC
, sub
, optarg
);
1362 register_fw_filename(AMD_FW_GEC
, sub
, optarg
);
1372 register_fw_token_unlock();
1376 sub
= (uint8_t)strtoul(optarg
, &tmp
, 16);
1379 instance
= strtoul(optarg
, &tmp
, 16);
1382 register_fw_filename(AMD_FW_PSP_PUBKEY
, sub
, optarg
);
1386 register_fw_filename(AMD_FW_PSP_BOOTLOADER
,
1391 register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE
,
1396 register_fw_filename(AMD_FW_PSP_RECOVERY
, sub
, optarg
);
1400 register_fw_filename(AMD_FW_PSP_RTM_PUBKEY
,
1405 register_fw_filename(AMD_FW_PSP_SECURED_OS
,
1410 register_fw_filename(AMD_FW_PSP_NVRAM
, sub
, optarg
);
1414 register_fw_filename(AMD_FW_PSP_SECURED_DEBUG
,
1419 register_fw_filename(AMD_FW_PSP_TRUSTLETS
, sub
, optarg
);
1423 register_fw_filename(AMD_FW_PSP_TRUSTLETKEY
,
1428 register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE2
,
1433 register_fw_filename(AMD_FW_PSP_SMUSCS
, sub
, optarg
);
1437 register_fw_fuse(optarg
);
1442 register_bdt_data(AMD_BIOS_APCB
, sub
, instance
, optarg
);
1443 register_bdt_data(AMD_BIOS_APCB_BK
, sub
,
1448 /* APOB destination */
1449 register_fw_addr(AMD_BIOS_APOB
, 0, optarg
, 0);
1453 /* APOB NV source */
1454 register_fw_addr(AMD_BIOS_APOB_NV
, optarg
, 0, 0);
1459 register_fw_addr(AMD_BIOS_APOB_NV
, 0, 0, optarg
);
1463 register_bdt_data(AMD_BIOS_BIN
, sub
, instance
, optarg
);
1468 register_fw_addr(AMD_BIOS_BIN
, optarg
, 0, 0);
1472 /* BIOS destination */
1473 register_fw_addr(AMD_BIOS_BIN
, 0, optarg
, 0);
1477 /* BIOS destination size */
1478 register_fw_addr(AMD_BIOS_BIN
, 0, 0, optarg
);
1482 register_bdt_data(AMD_BIOS_PMUI
, sub
, instance
, optarg
);
1486 register_bdt_data(AMD_BIOS_PMUD
, sub
, instance
, optarg
);
1490 register_bdt_data(AMD_BIOS_UCODE
, sub
,
1495 register_fw_filename(AMD_SEC_GASKET
, sub
, optarg
);
1499 register_fw_filename(AMD_MP2_FW
, sub
, optarg
);
1503 register_fw_filename(AMD_ABL0
+ abl_image
++,
1508 register_bdt_data(AMD_BIOS_MP2_CFG
, sub
,
1513 register_fw_filename(AMD_DRIVER_ENTRIES
, sub
, optarg
);
1517 register_fw_filename(AMD_WRAPPED_IKEK
, sub
, optarg
);
1521 register_fw_filename(AMD_S0I3_DRIVER
, sub
, optarg
);
1525 register_fw_filename(AMD_DEBUG_UNLOCK
, sub
, optarg
);
1529 register_fw_filename(AMD_FW_PSP_WHITELIST
, sub
, optarg
);
1533 register_fw_filename(AMD_FW_PSP_VERSTAGE
, sub
, optarg
);
1537 register_fw_filename(AMD_FW_VERSTAGE_SIG
, sub
, optarg
);
1541 soc_id
= identify_platform(optarg
);
1542 if (soc_id
== PLATFORM_UNKNOWN
) {
1543 printf("Error: Invalid SOC name specified\n\n");
1548 case LONGOPT_SPI_READ_MODE
:
1549 efs_spi_readmode
= strtoull(optarg
, NULL
, 16);
1552 case LONGOPT_SPI_SPEED
:
1553 efs_spi_speed
= strtoull(optarg
, NULL
, 16);
1556 case LONGOPT_SPI_MICRON_FLAG
:
1557 efs_spi_micron_flag
= strtoull(optarg
, NULL
, 16);
1564 ctx
.rom_size
= (uint32_t)strtoul(optarg
, &tmp
, 16);
1566 printf("Error: ROM size specified"
1567 " incorrectly (%s)\n\n", optarg
);
1572 dir_location
= (uint32_t)strtoul(optarg
, &tmp
, 16);
1574 printf("Error: Directory Location specified"
1575 " incorrectly (%s)\n\n", optarg
);
1583 /* shared memory destination */
1584 register_fw_addr(AMD_BIOS_PSP_SHARED_MEM
, 0, optarg
, 0);
1588 /* shared memory size */
1589 register_fw_addr(AMD_BIOS_PSP_SHARED_MEM
, NULL
, NULL
, optarg
);
1602 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN
);
1605 printf("Error: Output value is not specified.\n\n");
1609 if (ctx
.rom_size
% 1024 != 0) {
1610 printf("Error: ROM Size (%d bytes) should be a multiple of"
1611 " 1024 bytes.\n\n", ctx
.rom_size
);
1615 if (ctx
.rom_size
< MIN_ROM_KB
* 1024) {
1616 printf("Error: ROM Size (%dKB) must be at least %dKB.\n\n",
1617 ctx
.rom_size
/ 1024, MIN_ROM_KB
);
1626 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx
.rom_size
/ 1024);
1628 rom_base_address
= 0xFFFFFFFF - ctx
.rom_size
+ 1;
1629 if (dir_location
&& (dir_location
< rom_base_address
)) {
1630 printf("Error: Directory location outside of ROM.\n\n");
1635 if (dir_location
& 0x3f) {
1636 printf("Error: Invalid Directory location.\n");
1637 printf(" Valid locations are 64-byte aligned\n");
1641 switch (dir_location
) {
1642 case 0: /* Fall through */
1643 case 0xFFFA0000: /* Fall through */
1644 case 0xFFF20000: /* Fall through */
1645 case 0xFFE20000: /* Fall through */
1646 case 0xFFC20000: /* Fall through */
1647 case 0xFF820000: /* Fall through */
1648 case 0xFF020000: /* Fall through */
1651 printf("Error: Invalid Directory location.\n");
1652 printf(" Valid locations are 0xFFFA0000, 0xFFF20000,\n");
1653 printf(" 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
1658 ctx
.rom
= malloc(ctx
.rom_size
);
1660 printf("Error: Failed to allocate memory\n");
1663 memset(ctx
.rom
, 0xFF, ctx
.rom_size
);
1666 romsig_offset
= ctx
.current
= dir_location
- rom_base_address
;
1668 romsig_offset
= ctx
.current
= AMD_ROMSIG_OFFSET
;
1669 printf(" AMDFWTOOL Using firmware directory location of 0x%08x\n",
1672 amd_romsig
= BUFF_OFFSET(ctx
, romsig_offset
);
1673 amd_romsig
->signature
= EMBEDDED_FW_SIGNATURE
;
1674 amd_romsig
->imc_entry
= 0;
1675 amd_romsig
->gec_entry
= 0;
1676 amd_romsig
->xhci_entry
= 0;
1678 if (soc_id
!= PLATFORM_UNKNOWN
) {
1679 retval
= set_efs_table(soc_id
, amd_romsig
, efs_spi_readmode
,
1680 efs_spi_speed
, efs_spi_micron_flag
);
1682 printf("ERROR: Failed to initialize EFS table!\n");
1686 printf("WARNING: No SOC name specified.\n");
1689 integrate_firmwares(&ctx
, amd_romsig
, amd_fw_table
);
1691 ctx
.current
= ALIGN(ctx
.current
, 0x10000U
); /* TODO: is it necessary? */
1694 /* Do 2nd PSP directory followed by 1st */
1695 psp_directory_table
*pspdir2
= new_psp_dir(&ctx
, multi
);
1696 integrate_psp_firmwares(&ctx
, pspdir2
, 0,
1697 amd_psp_fw_table
, PSPL2_COOKIE
);
1699 pspdir
= new_psp_dir(&ctx
, multi
);
1700 integrate_psp_firmwares(&ctx
, pspdir
, pspdir2
,
1701 amd_psp_fw_table
, PSP_COOKIE
);
1703 /* flat: PSP 1 cookie and no pointer to 2nd table */
1704 pspdir
= new_psp_dir(&ctx
, multi
);
1705 integrate_psp_firmwares(&ctx
, pspdir
, 0,
1706 amd_psp_fw_table
, PSP_COOKIE
);
1710 amd_romsig
->comboable
= BUFF_TO_RUN(ctx
, pspdir
);
1712 amd_romsig
->psp_entry
= BUFF_TO_RUN(ctx
, pspdir
);
1715 psp_combo_directory
*combo_dir
= new_combo_dir(&ctx
);
1716 amd_romsig
->comboable
= BUFF_TO_RUN(ctx
, combo_dir
);
1717 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
1718 combo_dir
->entries
[0].id_sel
= 0;
1719 /* TODO: PSP ID. Documentation is needed. */
1720 combo_dir
->entries
[0].id
= 0x10220B00;
1721 combo_dir
->entries
[0].lvl2_addr
= BUFF_TO_RUN(ctx
, pspdir
);
1723 combo_dir
->header
.lookup
= 1;
1724 fill_dir_header(combo_dir
, 1, PSP2_COOKIE
);
1727 if (have_bios_tables(amd_bios_table
)) {
1728 bios_directory_table
*biosdir
;
1730 /* Do 2nd level BIOS directory followed by 1st */
1731 bios_directory_table
*biosdir2
=
1732 new_bios_dir(&ctx
, multi
);
1733 integrate_bios_firmwares(&ctx
, biosdir2
, 0,
1734 amd_bios_table
, BDT2_COOKIE
);
1736 biosdir
= new_bios_dir(&ctx
, multi
);
1737 integrate_bios_firmwares(&ctx
, biosdir
, biosdir2
,
1738 amd_bios_table
, BDT1_COOKIE
);
1740 /* flat: BDT1 cookie and no pointer to 2nd table */
1741 biosdir
= new_bios_dir(&ctx
, multi
);
1742 integrate_bios_firmwares(&ctx
, biosdir
, 0,
1743 amd_bios_table
, BDT1_COOKIE
);
1745 amd_romsig
->bios1_entry
= BUFF_TO_RUN(ctx
, biosdir
);
1748 targetfd
= open(output
, O_RDWR
| O_CREAT
| O_TRUNC
, 0666);
1749 if (targetfd
>= 0) {
1751 bytes
= write(targetfd
, amd_romsig
, ctx
.current
- romsig_offset
);
1752 if (bytes
!= ctx
.current
- romsig_offset
) {
1753 fprintf(stderr
, "Error: Writing to file %s failed\n", output
);
1758 printf("Error: could not open file: %s\n", output
);