blob: 9fe6b9a4c3687c96cc2f8b21ce9938417c744053 [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
Zheng Baodd4c5422021-10-14 16:14:09 +08004 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +08009 * | PSPDIR ADDR|PSPDIR ADDR(C) | BDT ADDR 0 | BDT ADDR 1 |
10 * +------------+---------------+----------------+------------+
11 * | BDT ADDR 2 | | BDT ADDR 3(C) | |
12 * +------------+---------------+----------------+------------+
13 * (C): Could be a combo header
14 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080015 * EC ROM should be 64K aligned.
16 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080017 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080018 * +------------+---------------+----------------+------------+
19 * | 'PSP$' | Fletcher | Count | Reserved |
20 * +------------+---------------+----------------+------------+
21 * | 0 | size | Base address | Reserved | Pubkey
22 * +------------+---------------+----------------+------------+
23 * | 1 | size | Base address | Reserved | Bootloader
24 * +------------+---------------+----------------+------------+
25 * | 8 | size | Base address | Reserved | Smu Firmware
26 * +------------+---------------+----------------+------------+
27 * | 3 | size | Base address | Reserved | Recovery Firmware
28 * +------------+---------------+----------------+------------+
29 * | |
30 * | |
Zheng Baodd4c5422021-10-14 16:14:09 +080031 * | Other PSP Firmware |
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080032 * | |
33 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080034 * | 40 | size | Base address | Reserved |---+
35 * +------------+---------------+----------------+------------+ |
36 * :or 48(A/B A): size : Base address : Reserved : |
37 * + - - + - - + - - + - - + |
38 * : 4A(A/B B): size : Base address : Reserved : |
39 * +------------+---------------+----------------+------------+ |
40 * (A/B A) & (A/B B): Similar as 40, pointing to PSP level 2 |
41 * for A/B recovery |
42 * |
43 * |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
47 * | |
48 * | |
49 * | PSP Firmware |
50 * | (2nd-level is not required on all families) |
51 * | |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
Zheng Bao4fcc9f22015-11-20 12:29:04 +080054 *
zbaoc3b0b722016-02-19 13:47:31 +080055 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080056 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080057 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080058 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080059 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080061 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080062 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080063 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080064 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080069 * BDT Combo is similar
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080070 */
71
Elyes Haouas7d67a192022-10-14 09:58:29 +020072#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080073#include <fcntl.h>
74#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060075#include <limits.h>
Kangheui Won5b84dfd2021-12-21 15:45:06 +110076#include <openssl/sha.h>
Martin Roth37305e72020-04-07 14:16:39 -060077#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080078#include <stdio.h>
79#include <sys/stat.h>
80#include <sys/types.h>
81#include <unistd.h>
82#include <string.h>
83#include <stdlib.h>
84#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080085#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010086#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080087
88#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080089
Martin Roth60f15512016-11-08 09:55:01 -070090#define AMD_ROMSIG_OFFSET 0x20000
91#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092
Marshall Dawson7c1e1422019-04-11 09:44:43 -060093#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
94#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070095#define TABLE_ALIGNMENT 0x1000U
96#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060097#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060098#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080099
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600100#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
101
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100102/* Defines related to hashing signed binaries */
103enum hash_header_ver {
104 HASH_HDR_V1 = 1,
105};
106/* Signature ID enums are defined by PSP based on the algorithm used. */
107enum signature_id {
108 SIG_ID_RSA2048,
109 SIG_ID_RSA4096 = 2,
110};
111#define HASH_FILE_SUFFIX ".hash"
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -0600112#define EFS_FILE_SUFFIX ".efs"
113#define TMP_FILE_SUFFIX ".tmp"
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100114
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800115/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700116 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
117 * can support an optional "combo" implementation. If the PSP sees the
118 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
119 * tables. Using this, support for multiple product generations may be
120 * built into one image. If the PSP$ cookie is found, the table is a
121 * normal directory table.
122 *
123 * Modern generations supporting the combo directories require the
124 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
125 * regardless of the type of directory used. The --combo-capable
126 * argument enforces this placement.
127 *
128 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800129 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800130
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800131/*
132 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
133 * The checksum field of the passed PDU does not need to be reset to zero.
134 *
135 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
136 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
137 * alternative to cyclical redundancy checks because it provides error-
138 * detection properties similar to cyclical redundancy checks but at the
139 * cost of a simple summation technique. Its characteristics were first
140 * published in IEEE Transactions on Communications in January 1982. One
141 * version has been adopted by ISO for use in the class-4 transport layer
142 * of the network protocol.
143 *
144 * This program expects:
145 * stdin: The input file to compute a checksum for. The input file
146 * not be longer than 256 bytes.
147 * stdout: Copied from the input file with the Fletcher's Checksum
148 * inserted 8 bytes after the beginning of the file.
149 * stderr: Used to print out error messages.
150 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700151static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800152{
153 uint32_t c0;
154 uint32_t c1;
155 uint32_t checksum;
156 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700157 const uint16_t *pptr = data;
158
159 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800160
161 c0 = 0xFFFF;
162 c1 = 0xFFFF;
163
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600164 while (length) {
165 index = length >= 359 ? 359 : length;
166 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800167 do {
168 c0 += *(pptr++);
169 c1 += c0;
170 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600171 c0 = (c0 & 0xFFFF) + (c0 >> 16);
172 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800173 }
174
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700175 /* Sums[0,1] mod 64K + overflow */
176 c0 = (c0 & 0xFFFF) + (c0 >> 16);
177 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800178 checksum = (c1 << 16) | c0;
179
180 return checksum;
181}
182
Martin Roth8806f7f2016-11-08 10:44:18 -0700183static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800184{
Martin Roth0e940622016-11-08 10:37:53 -0700185 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800186 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
187 printf("--xhci <FILE> Add XHCI blob\n");
188 printf("--imc <FILE> Add IMC blob\n");
189 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700190
191 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800192 printf("--combo-capable Place PSP directory pointer at Embedded\n");
193 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700194 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800195 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800196 printf("--multilevel Generate primary and secondary tables\n");
197 printf("--nvram <FILE> Add nvram binary\n");
198 printf("--soft-fuse Set soft fuse\n");
199 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530200 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
201 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800202 printf("--whitelist Set if there is a whitelist\n");
203 printf("--use-pspsecureos Set if psp secure OS is needed\n");
204 printf("--load-mp2-fw Set if load MP2 firmware\n");
205 printf("--load-s0i3 Set if load s0i3 firmware\n");
206 printf("--verstage <FILE> Add verstage\n");
207 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800208 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600209 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800210 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800211 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800212 printf("--apcb <FILE> Add AGESA PSP customization block\n");
213 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
214 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
215 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
216 printf("--ucode <FILE> Add microcode patch\n");
217 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
218 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
219 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
220 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
221 printf("--output <filename> output filename\n");
222 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600223 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700224 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600225 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800226 printf("--location Location of Directory\n");
227 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
228 printf("--sharedmem Location of PSP/FW shared memory\n");
229 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800230 printf(" area\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800231 printf("--soc-name <socname> Specify SOC name. Supported names are\n");
Zheng Bao3d7623f2022-08-17 11:52:30 +0800232 printf(" Carrizo, Stoneyridge, Raven, Picasso, Renoir,\n");
233 printf(" Cezanne, Mendocino, Phoenix, Glinda, or\n");
234 printf(" Lucienne\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500235 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
236 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
237 printf(" 0x0 66.66Mhz\n");
238 printf(" 0x1 33.33MHz\n");
239 printf(" 0x2 22.22MHz\n");
240 printf(" 0x3 16.66MHz\n");
241 printf(" 0x4 100MHz\n");
242 printf(" 0x5 800KHz\n");
243 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
244 printf(" 0x0 Normal Read (up to 33M)\n");
245 printf(" 0x1 Reserved\n");
246 printf(" 0x2 Dual IO (1-1-2)\n");
247 printf(" 0x3 Quad IO (1-1-4)\n");
248 printf(" 0x4 Dual IO (1-2-2)\n");
249 printf(" 0x5 Quad IO (1-4-4)\n");
250 printf(" 0x6 Normal Read (up to 66M)\n");
251 printf(" 0x7 Fast Read\n");
252 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
253 printf(" 0x0 Micron parts are not used\n");
254 printf(" 0x1 Micron parts are always used\n");
255 printf(" 0x2 Micron parts optional, this option is only\n");
256 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800257 printf("\nGeneral options:\n");
258 printf("-c|--config <config file> Config file\n");
259 printf("-d|--debug Print debug message\n");
260 printf("-l|--list List out the firmware files\n");
261 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800262}
263
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800264amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100265 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800266 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800267 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200268 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800269 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200270 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
271 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
272 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800273 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100274 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
275 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200276 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200277 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800278 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
279 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800280 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200281 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800283 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
286 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800287 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
288 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100289 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800290 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
291 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800292 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200293 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800294 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200295 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
296 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800297 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
298 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200299 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
300 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
301 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800302 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800303 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
304 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
305 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
306 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
307 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
308 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
309 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
310 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200311 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
312 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600313 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200314 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200315 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200316 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
317 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
318 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
319 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
320 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600321 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
322 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200323 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
325 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
326 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
327 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
328 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800329 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_BOTH_AB },
330 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200331 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
332 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800333 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
334 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200335 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200336 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200337 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
338 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800339 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
340 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
341 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
342 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
343 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
344 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
345 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
346 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
347 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
348 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
349 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
350 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
351 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
352 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500353 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800354 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800355};
356
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800357amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800358 { .type = AMD_FW_XHCI },
359 { .type = AMD_FW_IMC },
360 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800361 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800362};
363
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800364amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800365 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530366 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600367 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700372 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
377 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
378 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
379 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
380 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
381 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
382 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700383 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
384 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
385 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
386 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
387 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700388 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
389 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
390 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
391 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
392 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
393 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
394 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
395 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
396 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
397 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
398 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600399 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
400 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800401 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600402 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
403 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800405 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200407 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600409 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800411 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
415 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200417 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
419 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800421 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
425 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600427 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800429 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
430 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200431 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
432 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600433 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
434 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800435 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
436 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
437 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
438 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
439 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
440 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200441 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
442 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
443 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
444 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800445 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
446 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
447 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
448 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
449 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
450 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600451 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
452 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
453 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200454 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
455 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
456 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
457 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600458 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600459 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600460 { .type = AMD_BIOS_INVALID },
461};
462
Marshall Dawson2794a862019-03-04 16:53:15 -0700463typedef struct _context {
464 char *rom; /* target buffer, size of flash device */
465 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800466 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700467 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800468 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700469} context;
470
471#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800472#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600473 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
474 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
475 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800476#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600477#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800478 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700479#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800480/* The mode in entry can not be higher than the header's.
481 For example, if table mode is 0, all the entry mode will be 0. */
482#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
483 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700484#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
485#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
486#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800487#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
488 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700489#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800490/* Only set the address mode in entry if the table is mode 2. */
491#define SET_ADDR_MODE(table, mode) \
492 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600493 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800494#define SET_ADDR_MODE_BY_TABLE(table) \
495 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700496
Zheng Bao5164e4b2021-10-30 12:09:07 +0800497void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
498{
499 if (count >= max) {
500 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
501 "(%d)\n", count, max);
502 free(ctx->rom);
503 exit(1);
504 }
505}
506
Marshall Dawson24f73d42019-04-01 10:48:43 -0600507static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700508{
509 void *ptr;
510
Marshall Dawson24f73d42019-04-01 10:48:43 -0600511 /*
512 * Force both onto boundary when multi. Primary table is after
513 * updatable table, so alignment ensures primary can stay intact
514 * if secondary is reprogrammed.
515 */
516 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200517 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600518 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200519 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600520
Marshall Dawson2794a862019-03-04 16:53:15 -0700521 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800522 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800523 ((psp_directory_header *)ptr)->additional_info = 0;
524 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700525 ctx->current += sizeof(psp_directory_header)
526 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
527 return ptr;
528}
529
Zheng Baofdd47ef2021-09-17 13:30:08 +0800530static void *new_ish_dir(context *ctx)
531{
532 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200533 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800534 ptr = BUFF_CURRENT(*ctx);
535 ctx->current += TABLE_ALIGNMENT;
536 return ptr;
537}
538
Marshall Dawson2794a862019-03-04 16:53:15 -0700539static void *new_combo_dir(context *ctx)
540{
541 void *ptr;
542
Elyes Haouas7d67a192022-10-14 09:58:29 +0200543 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700544 ptr = BUFF_CURRENT(*ctx);
545 ctx->current += sizeof(psp_combo_header)
546 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
547 return ptr;
548}
549
Zheng Baobf29a0d2020-12-03 23:00:48 +0800550static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800551{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600552 psp_combo_directory *cdir = directory;
553 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600554 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800555 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600556
557 if (!count)
558 return;
Zheng Baob035f582021-05-27 11:26:12 +0800559 if (ctx == NULL || directory == NULL) {
560 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
561 return;
562 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600563
Zheng Baobf29a0d2020-12-03 23:00:48 +0800564 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200565 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800566
Marshall Dawson24f73d42019-04-01 10:48:43 -0600567 switch (cookie) {
568 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700569 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700570 cdir->header.cookie = cookie;
571 cdir->header.num_entries = count;
572 cdir->header.reserved[0] = 0;
573 cdir->header.reserved[1] = 0;
574 /* checksum everything that comes after the Checksum field */
575 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
576 count * sizeof(psp_combo_entry)
577 + sizeof(cdir->header.num_entries)
578 + sizeof(cdir->header.lookup)
579 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600580 break;
581 case PSP_COOKIE:
582 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800583 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800584 if ((table_size % TABLE_ALIGNMENT) != 0) {
585 fprintf(stderr, "The PSP table size should be 4K aligned\n");
586 exit(1);
587 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700588 dir->header.cookie = cookie;
589 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800590 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
591 dir->header.additional_info_fields.spi_block_size = 1;
592 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700593 /* checksum everything that comes after the Checksum field */
594 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700595 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700596 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800597 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600598 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800599 case BHD_COOKIE:
600 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800601 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800602 if ((table_size % TABLE_ALIGNMENT) != 0) {
603 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
604 exit(1);
605 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600606 bdir->header.cookie = cookie;
607 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800608 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
609 bdir->header.additional_info_fields.spi_block_size = 1;
610 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600611 /* checksum everything that comes after the Checksum field */
612 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
613 count * sizeof(bios_directory_entry)
614 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800615 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600616 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700617 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800618
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800619}
620
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700621static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
622{
623 int fd;
624 struct stat fd_stat;
625 ssize_t bytes;
626
627 fd = open(src_file, O_RDONLY);
628 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800629 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700630 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700631 return -1;
632 }
633
634 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800635 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600636 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700637 return -2;
638 }
639
Zheng Bao6d402ac2020-10-01 16:16:30 +0800640 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800641 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600642 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700643 return -3;
644 }
645
646 bytes = read(fd, dest, (size_t)fd_stat.st_size);
647 close(fd);
648 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800649 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700650 return -4;
651 }
652
653 return bytes;
654}
655
Kangheui Won3c164e12021-12-03 20:25:05 +1100656static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
657{
658 ssize_t bytes;
659 size_t total_bytes = 0;
660
661 do {
662 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
663 if (bytes == 0) {
664 fprintf(stderr, "Reached EOF probably\n");
665 break;
666 }
667
668 if (bytes < 0 && errno == EAGAIN)
669 bytes = 0;
670
671 if (bytes < 0) {
672 fprintf(stderr, "Read failure %s\n", strerror(errno));
673 return bytes;
674 }
675
676 total_bytes += bytes;
677 } while (total_bytes < buf_size);
678
679 if (total_bytes != buf_size) {
680 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
681 total_bytes, buf_size);
682 return -1;
683 }
684 return buf_size;
685}
686
687static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
688{
689 ssize_t bytes;
690 size_t total_bytes = 0;
691
692 do {
693 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
694 if (bytes < 0 && errno == EAGAIN)
695 bytes = 0;
696
697 if (bytes < 0) {
698 fprintf(stderr, "Write failure %s\n", strerror(errno));
699 lseek(fd, SEEK_CUR, -total_bytes);
700 return bytes;
701 }
702
703 total_bytes += bytes;
704 } while (total_bytes < buf_size);
705
706 if (total_bytes != buf_size) {
707 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
708 total_bytes, buf_size);
709 lseek(fd, SEEK_CUR, -total_bytes);
710 return -1;
711 }
712
713 return buf_size;
714}
715
Zheng Baoeb0404e2021-10-14 15:09:09 +0800716enum platform {
717 PLATFORM_UNKNOWN,
Zheng Bao3d7623f2022-08-17 11:52:30 +0800718 PLATFORM_CARRIZO,
Zheng Baoeb0404e2021-10-14 15:09:09 +0800719 PLATFORM_STONEYRIDGE,
720 PLATFORM_RAVEN,
721 PLATFORM_PICASSO,
722 PLATFORM_RENOIR,
723 PLATFORM_CEZANNE,
724 PLATFORM_MENDOCINO,
725 PLATFORM_LUCIENNE,
Martin Roth20646cd2023-01-04 21:27:06 -0700726 PLATFORM_PHOENIX,
Martin Roth13490832022-10-06 17:18:02 -0600727 PLATFORM_GLINDA
Zheng Baoeb0404e2021-10-14 15:09:09 +0800728};
729
730static uint32_t get_psp_id(enum platform soc_id)
731{
732 uint32_t psp_id;
733 switch (soc_id) {
734 case PLATFORM_RAVEN:
735 case PLATFORM_PICASSO:
736 psp_id = 0xBC0A0000;
737 break;
738 case PLATFORM_RENOIR:
739 case PLATFORM_LUCIENNE:
740 psp_id = 0xBC0C0000;
741 break;
742 case PLATFORM_CEZANNE:
743 psp_id = 0xBC0C0140;
744 break;
745 case PLATFORM_MENDOCINO:
746 psp_id = 0xBC0D0900;
747 break;
748 case PLATFORM_STONEYRIDGE:
749 psp_id = 0x10220B00;
750 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800751 case PLATFORM_GLINDA:
752 psp_id = 0xBC0E0200;
753 break;
754 case PLATFORM_PHOENIX:
755 psp_id = 0xBC0D0400;
756 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800757 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800758 default:
759 psp_id = 0;
760 break;
761 }
762 return psp_id;
763}
764
Kangheui Won3c164e12021-12-03 20:25:05 +1100765static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
766{
767 switch (soc_id) {
768 case PLATFORM_MENDOCINO:
Zheng Bao4044e852023-02-02 09:26:20 +0800769 case PLATFORM_PHOENIX:
770 case PLATFORM_GLINDA:
Kangheui Won3c164e12021-12-03 20:25:05 +1100771 /* Fallback to fw_type if fw_id is not populated, which serves the same
772 purpose on older SoCs. */
773 return header->fw_id ? header->fw_id : header->fw_type;
774 default:
775 return header->fw_type;
776 }
777}
778
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100779static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
780{
781 uint8_t hash[SHA384_DIGEST_LENGTH];
782 struct amd_fw_header *header = (struct amd_fw_header *)buf;
783 /* Include only signed part for hash calculation. */
784 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
785 uint8_t *body = (uint8_t *)buf;
786
787 if (len > header->size_total)
788 return -1;
789
790 if (header->sig_id == SIG_ID_RSA4096) {
791 SHA384(body, len, hash);
792 entry->sha_len = SHA384_DIGEST_LENGTH;
793 } else if (header->sig_id == SIG_ID_RSA2048) {
794 SHA256(body, len, hash);
795 entry->sha_len = SHA256_DIGEST_LENGTH;
796 } else {
797 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
798 __func__, header->sig_id);
799 return -1;
800 }
801
802 memcpy(entry->sha, hash, entry->sha_len);
803 entry->fw_id = get_psp_fw_type(soc_id, header);
804 entry->subtype = header->fw_subtype;
805
806 return 0;
807}
808
809static int get_num_binaries(void *buf, size_t buf_size)
810{
811 struct amd_fw_header *header = (struct amd_fw_header *)buf;
812 size_t total_len = 0;
813 int num_binaries = 0;
814
815 while (total_len < buf_size) {
816 num_binaries++;
817 total_len += header->size_total;
818 header = (struct amd_fw_header *)(buf + total_len);
819 }
820
821 if (total_len != buf_size) {
822 fprintf(stderr, "Malformed binary\n");
823 return -1;
824 }
825 return num_binaries;
826}
827
828static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
829{
830 struct amd_fw_header *header = (struct amd_fw_header *)buf;
831 /* Include only signed part for hash calculation. */
832 size_t total_len = 0;
833 int num_binaries = get_num_binaries(buf, buf_size);
834
835 if (num_binaries <= 0)
836 return num_binaries;
837
838 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
839 if (!entry->hash_entries) {
840 fprintf(stderr, "Error allocating memory to add FW hash\n");
841 return -1;
842 }
843 entry->num_hash_entries = num_binaries;
844
845 /* Iterate through each binary */
846 for (int i = 0; i < num_binaries; i++) {
847 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
848 free(entry->hash_entries);
849 return -1;
850 }
851 total_len += header->size_total;
852 header = (struct amd_fw_header *)(buf + total_len);
853 }
854
855 return 0;
856}
857
Marshall Dawson2794a862019-03-04 16:53:15 -0700858static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700859 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700860 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800861{
Richard Spiegel137484d2018-01-17 10:23:19 -0700862 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800863 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700864
Elyes Haouas7d67a192022-10-14 09:58:29 +0200865 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800866
Martin Rothcd15bc82016-11-08 11:34:02 -0700867 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800868 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800869 switch (fw_table[i].type) {
870 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200871 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700872 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800873 break;
874 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700875 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800876 break;
877 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700878 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800879 break;
880 default:
881 /* Error */
882 break;
883 }
884
Marshall Dawson2794a862019-03-04 16:53:15 -0700885 bytes = copy_blob(BUFF_CURRENT(*ctx),
886 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600887 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700888 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700889 exit(1);
890 }
891
Elyes Haouas7d67a192022-10-14 09:58:29 +0200892 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700893 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800894 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800895 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800896}
897
Zheng Bao9e908072020-10-28 11:39:13 +0800898/* For debugging */
899static void dump_psp_firmwares(amd_fw_entry *fw_table)
900{
901 amd_fw_entry *index;
902
903 printf("PSP firmware components:");
904 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
905 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800906 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800907 }
908}
909
910static void dump_bdt_firmwares(amd_bios_entry *fw_table)
911{
912 amd_bios_entry *index;
913
914 printf("BIOS Directory Table (BDT) components:");
915 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
916 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800917 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800918 }
919}
920
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800921static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
922{
923 amd_fw_entry *index;
924
925 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
926 if (index->filename &&
927 index->type != AMD_FW_VERSTAGE_SIG &&
928 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800929 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800930 index->type != AMD_FW_PSP_WHITELIST) {
931 free(index->filename);
932 }
933 }
934}
935
936static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
937{
938 amd_bios_entry *index;
939
940 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
941 if (index->filename &&
942 index->type != AMD_BIOS_APCB &&
943 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200944 index->type != AMD_BIOS_APCB_BK &&
945 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800946 free(index->filename);
947 }
948}
949
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100950static void write_or_fail(int fd, void *ptr, size_t size)
951{
952 ssize_t written;
953
954 written = write_from_buf_to_file(fd, ptr, size);
955 if (written < 0 || (size_t)written != size) {
956 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
957 __func__, size, written);
958 exit(-1);
959 }
960}
961
962static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
963{
964 uint16_t type = entry->fw_id;
965 uint16_t subtype = entry->subtype;
966
967 write_or_fail(fd, &type, sizeof(type));
968 write_or_fail(fd, &subtype, sizeof(subtype));
969 write_or_fail(fd, entry->sha, entry->sha_len);
970}
971
972static void write_psp_firmware_hash(const char *filename,
973 amd_fw_entry *fw_table)
974{
975 struct psp_fw_hash_table hash_header = {0};
976 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
977
978 if (fd < 0) {
979 fprintf(stderr, "Error opening file: %s: %s\n",
980 filename, strerror(errno));
981 exit(-1);
982 }
983
984 hash_header.version = HASH_HDR_V1;
985 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
986 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
987 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
988 hash_header.no_of_entries_256++;
989 } else if (fw_table[i].hash_entries[j].sha_len ==
990 SHA384_DIGEST_LENGTH) {
991 hash_header.no_of_entries_384++;
992 } else if (fw_table[i].hash_entries[j].sha_len) {
993 fprintf(stderr, "%s: Error invalid sha_len %d\n",
994 __func__, fw_table[i].hash_entries[j].sha_len);
995 exit(-1);
996 }
997 }
998 }
999
1000 write_or_fail(fd, &hash_header, sizeof(hash_header));
1001
1002 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
1003 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
1004 will cause the hash verification failure at run-time. */
1005 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1006 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
1007 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
1008 write_one_psp_firmware_hash_entry(fd,
1009 &fw_table[i].hash_entries[j]);
1010 }
1011 }
1012
1013 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1014 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
1015 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
1016 write_one_psp_firmware_hash_entry(fd,
1017 &fw_table[i].hash_entries[j]);
1018 }
1019 }
1020
1021 close(fd);
1022 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1023 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
1024 continue;
1025
1026 free(fw_table[i].hash_entries);
1027 fw_table[i].hash_entries = NULL;
1028 fw_table[i].num_hash_entries = 0;
1029 }
1030}
1031
Kangheui Won3c164e12021-12-03 20:25:05 +11001032/**
1033 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
1034 * @signed_rom: Output file path grouping all the signed PSP binaries.
1035 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
1036 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
1037 * the signed PSP binaries.
1038 * @soc_id: SoC ID of the PSP binaries.
1039 */
1040static void process_signed_psp_firmwares(const char *signed_rom,
1041 amd_fw_entry *fw_table,
1042 uint64_t signed_start_addr,
1043 enum platform soc_id)
1044{
1045 unsigned int i;
1046 int fd;
1047 int signed_rom_fd;
1048 ssize_t bytes, align_bytes;
1049 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001050 char *signed_rom_hash;
1051 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +11001052 struct amd_fw_header header;
1053 struct stat fd_stat;
1054 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
1055 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
1056 uint8_t align_data[BLOB_ALIGNMENT - 1];
1057
1058 memset(align_data, 0xff, sizeof(align_data));
1059 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
1060 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1061 if (signed_rom_fd < 0) {
1062 fprintf(stderr, "Error opening file: %s: %s\n",
1063 signed_rom, strerror(errno));
1064 return;
1065 }
1066
1067 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001068 fw_table[i].num_hash_entries = 0;
1069 fw_table[i].hash_entries = NULL;
1070
Kangheui Won3c164e12021-12-03 20:25:05 +11001071 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
1072 continue;
1073
1074 memset(&header, 0, sizeof(header));
1075
1076 fd = open(fw_table[i].filename, O_RDONLY);
1077 if (fd < 0) {
1078 /* Keep the file along with set of unsigned PSP binaries & continue. */
1079 fprintf(stderr, "Error opening file: %s: %s\n",
1080 fw_table[i].filename, strerror(errno));
1081 continue;
1082 }
1083
1084 if (fstat(fd, &fd_stat)) {
1085 /* Keep the file along with set of unsigned PSP binaries & continue. */
1086 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1087 close(fd);
1088 continue;
1089 }
1090
1091 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1092 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1093 /* Keep the file along with set of unsigned PSP binaries & continue. */
1094 fprintf(stderr, "%s: Error reading header from %s\n",
1095 __func__, fw_table[i].filename);
1096 close(fd);
1097 continue;
1098 }
1099
1100 /* If firmware header looks like invalid, assume it's not signed */
1101 if (!header.fw_type && !header.fw_id) {
1102 fprintf(stderr, "%s: Invalid FWID for %s\n",
1103 __func__, fw_table[i].filename);
1104 close(fd);
1105 continue;
1106 }
1107
Kangheui Won3c164e12021-12-03 20:25:05 +11001108
1109 /* PSP binary is not signed and should not be part of signed PSP binaries
1110 set. */
1111 if (header.sig_opt != 1) {
1112 close(fd);
1113 continue;
1114 }
1115
1116 buf = malloc(fd_stat.st_size);
1117 if (!buf) {
1118 /* Keep the file along with set of unsigned PSP binaries & continue. */
1119 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1120 __func__, (long long)fd_stat.st_size);
1121 close(fd);
1122 continue;
1123 }
1124
1125 lseek(fd, SEEK_SET, 0);
1126 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1127 if (bytes != fd_stat.st_size) {
1128 /* Keep the file along with set of unsigned PSP binaries & continue. */
1129 fprintf(stderr, "%s: failed to read %s\n",
1130 __func__, fw_table[i].filename);
1131 free(buf);
1132 close(fd);
1133 continue;
1134 }
1135
1136 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1137 if (bytes != fd_stat.st_size) {
1138 /* Keep the file along with set of unsigned PSP binaries & continue. */
1139 fprintf(stderr, "%s: failed to write %s\n",
1140 __func__, fw_table[i].filename);
1141 free(buf);
1142 close(fd);
1143 continue;
1144 }
1145
1146 /* Write Blob alignment bytes */
1147 align_bytes = 0;
1148 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1149 align_bytes = BLOB_ALIGNMENT -
1150 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1151 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1152 if (bytes != align_bytes) {
1153 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1154 __func__, fw_table[i].filename);
1155 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1156 free(buf);
1157 close(fd);
1158 continue;
1159 }
1160 }
1161
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001162 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1163 exit(-1);
1164
Kangheui Won3c164e12021-12-03 20:25:05 +11001165 /* File is successfully processed and is part of signed PSP binaries set. */
1166 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1167 fw_table[i].addr_signed = signed_start_addr;
1168 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1169
1170 signed_start_addr += fd_stat.st_size + align_bytes;
1171
1172 free(buf);
1173 close(fd);
1174 }
1175
1176 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001177
1178 /* signed_rom file name + ".hash" + '\0' */
1179 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1180 signed_rom_hash = malloc(signed_rom_hash_strlen);
1181 if (!signed_rom_hash) {
1182 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1183 exit(-1);
1184 }
1185 strcpy(signed_rom_hash, signed_rom);
1186 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1187 write_psp_firmware_hash(signed_rom_hash, fw_table);
1188 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001189}
1190
Zheng Bao990d1542021-09-17 13:24:54 +08001191static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001192 psp_directory_table *pspdir2, ish_directory_table *ish,
1193 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001194{
1195 uint32_t count;
1196 uint32_t current_table_save;
1197
1198 current_table_save = ctx->current_table;
1199 ctx->current_table = (char *)pspdir - ctx->rom;
1200 count = pspdir->header.num_entries;
1201 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1202 pspdir->entries[count].type = (uint8_t)ab;
1203 pspdir->entries[count].subprog = 0;
1204 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001205 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001206 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001207 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1208 ish->update_retry_count = 2;
1209 ish->glitch_retry_count = 0;
1210 ish->psp_id = get_psp_id(soc_id);
1211 ish->checksum = fletcher32(&ish->boot_priority,
1212 sizeof(ish_directory_table) - sizeof(uint32_t));
1213 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001214 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001215 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001216 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001217 pspdir->entries[count].size = TABLE_ALIGNMENT;
1218 } else {
1219 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001220 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001221 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001222 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001223 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001224 sizeof(psp_directory_entry) +
1225 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001226 }
Zheng Bao990d1542021-09-17 13:24:54 +08001227
1228 count++;
1229 pspdir->header.num_entries = count;
1230 ctx->current_table = current_table_save;
1231}
1232
Marshall Dawson2794a862019-03-04 16:53:15 -07001233static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001234 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001235 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001236 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001237 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001238 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001239 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +08001240 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001241{
Richard Spiegel137484d2018-01-17 10:23:19 -07001242 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001243 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001244 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301245 uint32_t size;
1246 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001247 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001248 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001249 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001250
1251 /* This function can create a primary table, a secondary table, or a
1252 * flattened table which contains all applicable types. These if-else
1253 * statements infer what the caller intended. If a 2nd-level cookie
1254 * is passed, clearly a 2nd-level table is intended. However, a
1255 * 1st-level cookie may indicate level 1 or flattened. If the caller
1256 * passes a pointer to a 2nd-level table, then assume not flat.
1257 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001258 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001259 level = PSP_BOTH;
1260 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001261 level = PSP_LVL2;
1262 else if (pspdir2)
1263 level = PSP_LVL1;
1264 else
1265 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001266
Zheng Bao990d1542021-09-17 13:24:54 +08001267 if (recovery_ab) {
1268 if (cookie == PSPL2_COOKIE)
1269 level = PSP_LVL2_AB;
1270 else if (pspdir2)
1271 level = PSP_LVL1_AB;
1272 else
1273 level = PSP_BOTH_AB;
1274 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001275 current_table_save = ctx->current_table;
1276 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001277 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001278
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001279 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001280 if (!(fw_table[i].level & level))
1281 continue;
1282
Zheng Bao5164e4b2021-10-30 12:09:07 +08001283 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1284
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001285 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1286 if (!fw_table[i].other)
1287 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001288 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001289 pspdir->entries[count].type = fw_table[i].type;
1290 pspdir->entries[count].size = 4096; /* TODO: doc? */
1291 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001292 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001293 pspdir->entries[count].subprog = fw_table[i].subprog;
1294 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001295 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001296 count++;
1297 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001298 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001299 pspdir->entries[count].subprog = fw_table[i].subprog;
1300 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001301 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001302 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001303 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001304 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001305 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301306 if (fw_table[i].filename == NULL) {
1307 if (fw_table[i].size == 0)
1308 continue;
1309 size = fw_table[i].size;
1310 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001311 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301312 fprintf(stderr,
1313 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1314 exit(1);
1315 }
1316 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001317 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301318 bytes = copy_blob(BUFF_CURRENT(*ctx),
1319 fw_table[i].filename, BUFF_ROOM(*ctx));
1320 if (bytes <= 0) {
1321 free(ctx->rom);
1322 exit(1);
1323 }
1324
Elyes Haouas7d67a192022-10-14 09:58:29 +02001325 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301326 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001327 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301328 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001329 }
1330
1331 pspdir->entries[count].type = fw_table[i].type;
1332 pspdir->entries[count].subprog = fw_table[i].subprog;
1333 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301334 pspdir->entries[count].size = size;
1335 pspdir->entries[count].addr = addr;
1336
Zheng Bao6fff2492021-11-15 19:53:21 +08001337 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001338 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001339
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001340 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001341 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001342 if (fw_table[i].addr_signed) {
1343 pspdir->entries[count].addr =
1344 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1345 pspdir->entries[count].address_mode =
1346 SET_ADDR_MODE_BY_TABLE(pspdir);
1347 bytes = fw_table[i].file_size;
1348 } else {
1349 bytes = copy_blob(BUFF_CURRENT(*ctx),
1350 fw_table[i].filename, BUFF_ROOM(*ctx));
1351 if (bytes < 0) {
1352 free(ctx->rom);
1353 exit(1);
1354 }
1355 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1356 pspdir->entries[count].address_mode =
1357 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001358 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001359 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001360 }
1361
Marshall Dawson239286c2019-02-23 16:42:46 -07001362 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001363 pspdir->entries[count].subprog = fw_table[i].subprog;
1364 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001365 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001366
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001367 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001368 } else {
1369 /* This APU doesn't have this firmware. */
1370 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001371 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001372
Zheng Bao990d1542021-09-17 13:24:54 +08001373 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001374 if (cb_config->need_ish) { /* Need ISH */
1375 ish_a_dir = new_ish_dir(ctx);
1376 if (pspdir2_b != NULL)
1377 ish_b_dir = new_ish_dir(ctx);
1378 }
Zheng Bao990d1542021-09-17 13:24:54 +08001379 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001380 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
1381 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001382 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001383 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
1384 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001385 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001386 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001387 AMD_FW_RECOVERYAB_B, soc_id);
1388
Zheng Bao990d1542021-09-17 13:24:54 +08001389 count = pspdir->header.num_entries;
1390 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001391 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001392 pspdir->entries[count].type = AMD_FW_L2_PTR;
1393 pspdir->entries[count].subprog = 0;
1394 pspdir->entries[count].rsvd = 0;
1395 pspdir->entries[count].size = sizeof(pspdir2->header)
1396 + pspdir2->header.num_entries
1397 * sizeof(psp_directory_entry);
1398
Zheng Bao6fff2492021-11-15 19:53:21 +08001399 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001400 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001401 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001402 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001403 count++;
1404 }
1405
Zheng Baobf29a0d2020-12-03 23:00:48 +08001406 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001407 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001408}
1409
Zheng Bao990d1542021-09-17 13:24:54 +08001410static void add_psp_firmware_entry(context *ctx,
1411 psp_directory_table *pspdir,
1412 void *table, amd_fw_type type, uint32_t size)
1413{
1414 uint32_t count = pspdir->header.num_entries;
1415 uint32_t index;
1416 uint32_t current_table_save;
1417
1418 current_table_save = ctx->current_table;
1419 ctx->current_table = (char *)pspdir - ctx->rom;
1420
1421 /* If there is an entry of "type", replace it. */
1422 for (index = 0; index < count; index++) {
1423 if (pspdir->entries[index].type == (uint8_t)type)
1424 break;
1425 }
1426
1427 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1428 pspdir->entries[index].type = (uint8_t)type;
1429 pspdir->entries[index].subprog = 0;
1430 pspdir->entries[index].rsvd = 0;
1431 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1432 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1433 pspdir->entries[index].size = size;
1434 if (index == count)
1435 count++;
1436
1437 pspdir->header.num_entries = count;
1438 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1439 count * sizeof(psp_directory_entry)
1440 + sizeof(pspdir->header.num_entries)
1441 + sizeof(pspdir->header.additional_info));
1442
1443 ctx->current_table = current_table_save;
1444}
1445
Zheng Baoba3af5e2021-11-04 18:56:47 +08001446static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001447{
1448 void *ptr;
1449
1450 /*
1451 * Force both onto boundary when multi. Primary table is after
1452 * updatable table, so alignment ensures primary can stay intact
1453 * if secondary is reprogrammed.
1454 */
1455 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001456 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001457 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001458 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001459 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001460 ((bios_directory_hdr *) ptr)->additional_info = 0;
1461 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1462 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001463 ctx->current += sizeof(bios_directory_hdr)
1464 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1465 return ptr;
1466}
1467
1468static int locate_bdt2_bios(bios_directory_table *level2,
1469 uint64_t *source, uint32_t *size)
1470{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001471 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001472
1473 *source = 0;
1474 *size = 0;
1475 if (!level2)
1476 return 0;
1477
1478 for (i = 0 ; i < level2->header.num_entries ; i++) {
1479 if (level2->entries[i].type == AMD_BIOS_BIN) {
1480 *source = level2->entries[i].source;
1481 *size = level2->entries[i].size;
1482 return 1;
1483 }
1484 }
1485 return 0;
1486}
1487
1488static int have_bios_tables(amd_bios_entry *table)
1489{
1490 int i;
1491
1492 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1493 if (table[i].level & BDT_LVL1 && table[i].filename)
1494 return 1;
1495 }
1496 return 0;
1497}
1498
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001499static int find_bios_entry(amd_bios_type type)
1500{
1501 int i;
1502
1503 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1504 if (amd_bios_table[i].type == type)
1505 return i;
1506 }
1507 return -1;
1508}
1509
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001510static void integrate_bios_firmwares(context *ctx,
1511 bios_directory_table *biosdir,
1512 bios_directory_table *biosdir2,
1513 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001514 uint32_t cookie,
1515 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001516{
1517 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001518 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001519 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001520 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001521 uint32_t size;
1522 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001523
1524 /* This function can create a primary table, a secondary table, or a
1525 * flattened table which contains all applicable types. These if-else
1526 * statements infer what the caller intended. If a 2nd-level cookie
1527 * is passed, clearly a 2nd-level table is intended. However, a
1528 * 1st-level cookie may indicate level 1 or flattened. If the caller
1529 * passes a pointer to a 2nd-level table, then assume not flat.
1530 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001531 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001532 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001533 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001534 level = BDT_LVL2;
1535 else if (biosdir2)
1536 level = BDT_LVL1;
1537 else
1538 level = BDT_BOTH;
1539
Elyes Haouas7d67a192022-10-14 09:58:29 +02001540 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001541
1542 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1543 if (!(fw_table[i].level & level))
1544 continue;
1545 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301546 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001547 fw_table[i].type != AMD_BIOS_APOB &&
1548 fw_table[i].type != AMD_BIOS_APOB_NV &&
1549 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001550 fw_table[i].type != AMD_BIOS_BIN &&
1551 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001552 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001553
1554 /* BIOS Directory items may have additional requirements */
1555
Ritul Guru9a321f32022-07-29 11:06:40 +05301556 /* SIG needs a size, else no choice but to skip */
1557 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1558 continue;
1559
Martin Roth48dd9fe2020-07-29 16:32:25 -06001560 /* Check APOB_NV requirements */
1561 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1562 if (!fw_table[i].size && !fw_table[i].src)
1563 continue; /* APOB_NV not used */
1564 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001565 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001566 free(ctx->rom);
1567 exit(1);
1568 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001569 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001570 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001571 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1572 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001573 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001574
1575 /* APOB_DATA needs destination */
1576 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001577 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001578 free(ctx->rom);
1579 exit(1);
1580 }
1581
1582 /* BIOS binary must have destination and uncompressed size. If
1583 * no filename given, then user must provide a source address.
1584 */
1585 if (fw_table[i].type == AMD_BIOS_BIN) {
1586 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001587 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001588 free(ctx->rom);
1589 exit(1);
1590 }
1591 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001592 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001593 free(ctx->rom);
1594 exit(1);
1595 }
1596 }
1597
Martin Roth94554742020-04-14 14:59:36 -06001598 /* PSP_SHARED_MEM needs a destination and size */
1599 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1600 (!fw_table[i].dest || !fw_table[i].size))
1601 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001602 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001603
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001604 biosdir->entries[count].type = fw_table[i].type;
1605 biosdir->entries[count].region_type = fw_table[i].region_type;
1606 biosdir->entries[count].dest = fw_table[i].dest ?
1607 fw_table[i].dest : (uint64_t)-1;
1608 biosdir->entries[count].reset = fw_table[i].reset;
1609 biosdir->entries[count].copy = fw_table[i].copy;
1610 biosdir->entries[count].ro = fw_table[i].ro;
1611 biosdir->entries[count].compressed = fw_table[i].zlib;
1612 biosdir->entries[count].inst = fw_table[i].inst;
1613 biosdir->entries[count].subprog = fw_table[i].subpr;
1614
1615 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301616 case AMD_BIOS_SIG:
1617 /* Reserve size bytes within amdfw.rom */
1618 biosdir->entries[count].size = fw_table[i].size;
1619 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1620 biosdir->entries[count].address_mode =
1621 SET_ADDR_MODE_BY_TABLE(biosdir);
1622 memset(BUFF_CURRENT(*ctx), 0xff,
1623 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001624 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301625 + biosdir->entries[count].size, 0x100U);
1626 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001627 case AMD_BIOS_APOB:
1628 biosdir->entries[count].size = fw_table[i].size;
1629 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001630 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001631 break;
1632 case AMD_BIOS_APOB_NV:
1633 if (fw_table[i].src) {
1634 /* If source is given, use that and its size */
1635 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001636 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001637 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001638 biosdir->entries[count].size = fw_table[i].size;
1639 } else {
1640 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001641 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001642 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001643 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001644 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001645 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001646 fw_table[i].size, ERASE_ALIGNMENT);
1647 memset(BUFF_CURRENT(*ctx), 0xff,
1648 biosdir->entries[count].size);
1649 ctx->current = ctx->current
1650 + biosdir->entries[count].size;
1651 }
1652 break;
1653 case AMD_BIOS_BIN:
1654 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001655 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1656 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001657 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001658 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001659 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001660 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001661 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001662
1663 /* level 2, or level 1 and no copy found in level 2 */
1664 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001665 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001666 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001667 biosdir->entries[count].dest = fw_table[i].dest;
1668 biosdir->entries[count].size = fw_table[i].size;
1669
1670 if (!fw_table[i].filename)
1671 break;
1672
1673 bytes = copy_blob(BUFF_CURRENT(*ctx),
1674 fw_table[i].filename, BUFF_ROOM(*ctx));
1675 if (bytes <= 0) {
1676 free(ctx->rom);
1677 exit(1);
1678 }
1679
Zheng Bao6fff2492021-11-15 19:53:21 +08001680 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001681 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001682 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001683 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001684
Elyes Haouas7d67a192022-10-14 09:58:29 +02001685 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001686 break;
Martin Roth94554742020-04-14 14:59:36 -06001687 case AMD_BIOS_PSP_SHARED_MEM:
1688 biosdir->entries[count].dest = fw_table[i].dest;
1689 biosdir->entries[count].size = fw_table[i].size;
1690 break;
1691
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001692 default: /* everything else is copied from input */
1693 if (fw_table[i].type == AMD_BIOS_APCB ||
1694 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001695 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001696 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001697 bytes = copy_blob(BUFF_CURRENT(*ctx),
1698 fw_table[i].filename, BUFF_ROOM(*ctx));
1699 if (bytes <= 0) {
1700 free(ctx->rom);
1701 exit(1);
1702 }
1703
1704 biosdir->entries[count].size = (uint32_t)bytes;
1705 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001706 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001707
Elyes Haouas7d67a192022-10-14 09:58:29 +02001708 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001709 break;
1710 }
1711
1712 count++;
1713 }
1714
1715 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001716 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001717 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001718 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001719 biosdir->entries[count].size =
1720 + MAX_BIOS_ENTRIES
1721 * sizeof(bios_directory_entry);
1722 biosdir->entries[count].source =
1723 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001724 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001725 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001726 biosdir->entries[count].subprog = 0;
1727 biosdir->entries[count].inst = 0;
1728 biosdir->entries[count].copy = 0;
1729 biosdir->entries[count].compressed = 0;
1730 biosdir->entries[count].dest = -1;
1731 biosdir->entries[count].reset = 0;
1732 biosdir->entries[count].ro = 0;
1733 count++;
1734 }
1735
Zheng Baobf29a0d2020-12-03 23:00:48 +08001736 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001737}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001738
1739enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001740 AMDFW_OPT_CONFIG = 'c',
1741 AMDFW_OPT_DEBUG = 'd',
1742 AMDFW_OPT_HELP = 'h',
1743 AMDFW_OPT_LIST_DEPEND = 'l',
1744
1745 AMDFW_OPT_XHCI = 128,
1746 AMDFW_OPT_IMC,
1747 AMDFW_OPT_GEC,
1748 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001749 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001750 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001751 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001752 AMDFW_OPT_MULTILEVEL,
1753 AMDFW_OPT_NVRAM,
1754
1755 AMDFW_OPT_FUSE,
1756 AMDFW_OPT_UNLOCK,
1757 AMDFW_OPT_WHITELIST,
1758 AMDFW_OPT_USE_PSPSECUREOS,
1759 AMDFW_OPT_LOAD_MP2FW,
1760 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001761 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001762 AMDFW_OPT_VERSTAGE,
1763 AMDFW_OPT_VERSTAGE_SIG,
1764
1765 AMDFW_OPT_INSTANCE,
1766 AMDFW_OPT_APCB,
1767 AMDFW_OPT_APOBBASE,
1768 AMDFW_OPT_BIOSBIN,
1769 AMDFW_OPT_BIOSBIN_SOURCE,
1770 AMDFW_OPT_BIOSBIN_DEST,
1771 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1772 AMDFW_OPT_UCODE,
1773 AMDFW_OPT_APOB_NVBASE,
1774 AMDFW_OPT_APOB_NVSIZE,
1775
1776 AMDFW_OPT_OUTPUT,
1777 AMDFW_OPT_FLASHSIZE,
1778 AMDFW_OPT_LOCATION,
1779 AMDFW_OPT_ANYWHERE,
1780 AMDFW_OPT_SHAREDMEM,
1781 AMDFW_OPT_SHAREDMEM_SIZE,
1782 AMDFW_OPT_SOC_NAME,
Kangheui Won3c164e12021-12-03 20:25:05 +11001783 AMDFW_OPT_SIGNED_OUTPUT,
1784 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001785 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001786 /* begin after ASCII characters */
1787 LONGOPT_SPI_READ_MODE = 256,
1788 LONGOPT_SPI_SPEED = 257,
1789 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301790 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301791 LONGOPT_NVRAM_BASE = 260,
1792 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001793};
1794
Zheng Bao806892a2021-04-27 17:21:54 +08001795static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1796 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1797};
Marc Jones90099b62016-09-20 21:05:45 -06001798
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001799static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001800 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1801 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1802 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001803 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001804 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001805 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001806 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001807 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001808 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1809 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301810 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1811 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001812 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1813 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1814 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1815 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1816 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1817 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001818 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001819 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1820 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001821 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001822 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1823 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1824 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1825 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1826 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1827 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1828 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301829 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001830 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1831 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1832 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001833 /* Embedded Firmware Structure items*/
1834 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1835 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1836 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001837 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001838 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001839 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1840 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1841 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1842 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1843 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1844 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1845 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001846
Kangheui Won3c164e12021-12-03 20:25:05 +11001847 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1848 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1849
Zheng Bao806892a2021-04-27 17:21:54 +08001850 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1851 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1852 {"help", no_argument, 0, AMDFW_OPT_HELP },
1853 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001854 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001855};
1856
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001857void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001858{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001859 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001860
1861 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1862 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1863 continue;
1864
1865 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1866 return;
1867 }
1868}
1869
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001870static void register_fw_token_unlock(void)
1871{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001872 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001873
1874 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1875 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1876 continue;
1877
1878 amd_psp_fw_table[i].other = 1;
1879 return;
1880 }
1881}
1882
Marshall Dawsondbae6322019-03-04 10:31:03 -07001883static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001884{
Martin Roth8806f7f2016-11-08 10:44:18 -07001885 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001886
Martin Rothcd15bc82016-11-08 11:34:02 -07001887 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001888 if (amd_fw_table[i].type == type) {
1889 amd_fw_table[i].filename = filename;
1890 return;
1891 }
1892 }
1893
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001894 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001895 if (amd_psp_fw_table[i].type != type)
1896 continue;
1897
1898 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001899 amd_psp_fw_table[i].filename = filename;
1900 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001901 }
1902 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001903}
1904
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001905static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1906{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001907 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001908
1909 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1910 if (amd_bios_table[i].type == type
1911 && amd_bios_table[i].inst == ins
1912 && amd_bios_table[i].subpr == sub) {
1913 amd_bios_table[i].filename = name;
1914 return;
1915 }
1916 }
1917}
1918
Ritul Gurua2cb3402022-08-29 00:51:08 +05301919static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1920 char *dst_str, char *size_str)
1921{
1922 unsigned int i;
1923
1924 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1925 if (amd_psp_fw_table[i].type != type)
1926 continue;
1927
1928 if (amd_psp_fw_table[i].subprog == sub) {
1929 if (dst_str)
1930 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1931 if (size_str)
1932 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1933 return;
1934 }
1935 }
1936}
1937
1938static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001939 char *dst_str, char *size_str)
1940{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001941 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001942 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1943 if (amd_bios_table[i].type != type)
1944 continue;
1945
1946 if (src_str)
1947 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1948 if (dst_str)
1949 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1950 if (size_str)
1951 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1952
1953 return;
1954 }
1955}
1956
Zheng Baoc3007f32022-04-03 12:53:51 +08001957static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1958 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1959 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001960{
1961 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001962 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001963 return 1;
1964 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001965
1966 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1967 * Leave as 0xffffffff for first gen */
1968 if (cb_config->second_gen) {
1969 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1970 amd_romsig->efs_gen.reserved = 0;
1971 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001972 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1973 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001974 }
1975
1976 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001977 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001978 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001979 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1980 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1981 break;
1982 case PLATFORM_RAVEN:
1983 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001984 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1985 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1986 switch (efs_spi_micron_flag) {
1987 case 0:
1988 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1989 break;
1990 case 1:
1991 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1992 break;
1993 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001994 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001995 return 1;
1996 }
1997 break;
1998 case PLATFORM_RENOIR:
1999 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08002000 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08002001 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002002 case PLATFORM_PHOENIX:
2003 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002004 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
2005 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
2006 switch (efs_spi_micron_flag) {
2007 case 0:
2008 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
2009 break;
2010 case 1:
2011 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
2012 break;
2013 case 2:
2014 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
2015 break;
2016 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002017 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002018 return 1;
2019 }
2020 break;
2021 case PLATFORM_UNKNOWN:
2022 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002023 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002024 return 1;
2025 }
2026 return 0;
2027}
2028
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002029static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
2030{
2031 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
2032 int ret;
2033 int fd;
2034 ssize_t bytes = -1;
2035
2036 /* Create a tmp file and rename it at the end so that make does not get confused
2037 if amdfwtool is killed for some unexpected reasons. */
2038 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
2039 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
2040 if (ret < 0) {
2041 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
2042 strerror(errno), ret);
2043 exit(1);
2044 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
2045 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
2046 exit(1);
2047 }
2048
2049 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
2050 if (fd < 0) {
2051 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
2052 exit(1);
2053 }
2054
2055 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
2056 if (bytes != sizeof(*amd_romsig)) {
2057 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
2058 exit(1);
2059 }
2060 close(fd);
2061
2062 /* Rename the tmp file */
2063 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
2064 if (ret < 0) {
2065 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
2066 exit(1);
2067 }
2068
2069 if (rename(efs_tmp_name, efs_name)) {
2070 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
2071 exit(1);
2072 }
2073
2074 return bytes;
2075}
2076
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002077static int identify_platform(char *soc_name)
2078{
2079 if (!strcasecmp(soc_name, "Stoneyridge"))
2080 return PLATFORM_STONEYRIDGE;
Zheng Bao3d7623f2022-08-17 11:52:30 +08002081 else if (!strcasecmp(soc_name, "Carrizo"))
2082 return PLATFORM_CARRIZO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002083 else if (!strcasecmp(soc_name, "Raven"))
2084 return PLATFORM_RAVEN;
2085 else if (!strcasecmp(soc_name, "Picasso"))
2086 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002087 else if (!strcasecmp(soc_name, "Cezanne"))
2088 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08002089 else if (!strcasecmp(soc_name, "Mendocino"))
2090 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002091 else if (!strcasecmp(soc_name, "Renoir"))
2092 return PLATFORM_RENOIR;
2093 else if (!strcasecmp(soc_name, "Lucienne"))
2094 return PLATFORM_LUCIENNE;
Martin Roth20646cd2023-01-04 21:27:06 -07002095 else if (!strcasecmp(soc_name, "Phoenix"))
2096 return PLATFORM_PHOENIX;
Martin Roth13490832022-10-06 17:18:02 -06002097 else if (!strcasecmp(soc_name, "Glinda"))
2098 return PLATFORM_GLINDA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002099 else
2100 return PLATFORM_UNKNOWN;
2101
2102}
2103
Felix Heldf8e2e472022-03-29 23:28:49 +02002104static bool needs_ish(enum platform platform_type)
2105{
Zheng Baode6f1982022-10-16 20:32:43 +08002106 if (platform_type == PLATFORM_MENDOCINO || platform_type == PLATFORM_PHOENIX || platform_type == PLATFORM_GLINDA)
Felix Heldf8e2e472022-03-29 23:28:49 +02002107 return true;
2108 else
2109 return false;
2110}
2111
Zheng Baoc3007f32022-04-03 12:53:51 +08002112static bool is_second_gen(enum platform platform_type)
2113{
2114 switch (platform_type) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08002115 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08002116 case PLATFORM_STONEYRIDGE:
2117 case PLATFORM_RAVEN:
2118 case PLATFORM_PICASSO:
2119 return false;
2120 case PLATFORM_RENOIR:
2121 case PLATFORM_LUCIENNE:
2122 case PLATFORM_CEZANNE:
Jon Murphy9969f4b2022-08-05 13:56:38 -06002123 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002124 case PLATFORM_PHOENIX:
2125 case PLATFORM_GLINDA:
Zheng Baoc3007f32022-04-03 12:53:51 +08002126 return true;
2127 case PLATFORM_UNKNOWN:
2128 default:
2129 fprintf(stderr, "Error: Invalid SOC name.\n\n");
2130 return false;
2131 }
2132}
2133
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002134int main(int argc, char **argv)
2135{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002136 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002137 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002138 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002139 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002140 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002141 psp_directory_table *pspdir = NULL;
2142 psp_directory_table *pspdir2 = NULL;
2143 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08002144 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002145 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002146 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002147 char *output = NULL, *config = NULL;
2148 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002149 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002150 /* Values cleared after each firmware or parameter, regardless if N/A */
2151 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08002152 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002153 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002154 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002155 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002156 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002157 uint8_t soc_id = PLATFORM_UNKNOWN;
2158 uint8_t efs_spi_readmode = 0xff;
2159 uint8_t efs_spi_speed = 0xff;
2160 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002161 const char *signed_output_file = NULL;
2162 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002163
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002164 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002165 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002166 int list_deps = 0;
2167
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002168 while (1) {
2169 int optindex = 0;
2170
2171 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2172
2173 if (c == -1)
2174 break;
2175
2176 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002177 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002178 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002179 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002180 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002181 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002182 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002183 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002184 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002185 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002186 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002187 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002188 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002189 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002190 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07002191 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002192 case AMDFW_OPT_RECOVERY_AB:
2193 cb_config.recovery_ab = true;
2194 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002195 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2196 cb_config.recovery_ab = true;
2197 cb_config.recovery_ab_single_copy = true;
2198 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002199 case AMDFW_OPT_USE_COMBO:
2200 cb_config.use_combo = true;
2201 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002202 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002203 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002204 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002205 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002206 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002207 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002208 sub = instance = 0;
2209 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002210 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002211 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002212 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002213 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002214 instance = strtoul(optarg, &tmp, 16);
2215 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002216 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002217 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002218 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002219 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002220 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002221 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002222 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002223 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002224 register_fw_fuse(optarg);
2225 fuse_defined = 1;
2226 sub = 0;
2227 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002228 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002229 if ((instance & 0xF0) == 0)
2230 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2231 else
2232 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2233 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002234 sub = instance = 0;
2235 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002236 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002237 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302238 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002239 sub = instance = 0;
2240 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002241 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002242 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302243 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002244 sub = instance = 0;
2245 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002246 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002247 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302248 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002249 sub = instance = 0;
2250 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002251 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002252 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2253 sub = instance = 0;
2254 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002255 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002256 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302257 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002258 sub = instance = 0;
2259 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002260 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002261 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302262 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002263 sub = instance = 0;
2264 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002265 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002266 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302267 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002268 sub = instance = 0;
2269 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302270 case LONGOPT_BIOS_SIG:
2271 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302272 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302273 sub = instance = 0;
2274 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002275 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002276 register_bdt_data(AMD_BIOS_UCODE, sub,
2277 instance, optarg);
2278 sub = instance = 0;
2279 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002280 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002281 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002282 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002283 case AMDFW_OPT_SPL_TABLE:
2284 register_fw_filename(AMD_FW_SPL, sub, optarg);
2285 sub = instance = 0;
2286 cb_config.have_mb_spl = true;
2287 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002288 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002289 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2290 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002291 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002292 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002293 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002294 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2295 sub = instance = 0;
2296 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002297 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002298 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2299 sub = instance = 0;
2300 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002301 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002302 soc_id = identify_platform(optarg);
2303 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002304 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002305 retval = 1;
2306 }
2307 sub = instance = 0;
2308 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002309 case AMDFW_OPT_SIGNED_OUTPUT:
2310 signed_output_file = optarg;
2311 sub = instance = 0;
2312 break;
2313 case AMDFW_OPT_SIGNED_ADDR:
2314 signed_start_addr = strtoull(optarg, NULL, 10);
2315 sub = instance = 0;
2316 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002317 case LONGOPT_SPI_READ_MODE:
2318 efs_spi_readmode = strtoull(optarg, NULL, 16);
2319 sub = instance = 0;
2320 break;
2321 case LONGOPT_SPI_SPEED:
2322 efs_spi_speed = strtoull(optarg, NULL, 16);
2323 sub = instance = 0;
2324 break;
2325 case LONGOPT_SPI_MICRON_FLAG:
2326 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2327 sub = instance = 0;
2328 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002329 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002330 output = optarg;
2331 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002332 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002333 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002334 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002335 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002336 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002337 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002338 }
2339 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002340 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002341 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002342 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002343 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002344 " incorrectly (%s)\n\n", optarg);
2345 retval = 1;
2346 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002347 if (body_location == 0)
2348 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002349 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002350 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002351 any_location = 1;
2352 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002353 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002354 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302355 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002356 sub = instance = 0;
2357 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002358 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002359 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302360 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002361 sub = instance = 0;
2362 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302363 case LONGOPT_NVRAM_BASE:
2364 /* PSP NV base */
2365 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2366 sub = instance = 0;
2367 break;
2368 case LONGOPT_NVRAM_SIZE:
2369 /* PSP NV size */
2370 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2371 sub = instance = 0;
2372 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002373 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002374 config = optarg;
2375 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002376 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002377 debug = 1;
2378 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002379 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002380 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002381 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002382 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002383 list_deps = 1;
2384 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002385 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002386 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002387 if (*tmp != '\0') {
2388 fprintf(stderr, "Error: Body Location specified"
2389 " incorrectly (%s)\n\n", optarg);
2390 retval = 1;
2391 }
2392 break;
2393
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002394 default:
2395 break;
2396 }
2397 }
2398
Zheng Baoc3007f32022-04-03 12:53:51 +08002399 cb_config.second_gen = is_second_gen(soc_id);
2400
Felix Heldf8e2e472022-03-29 23:28:49 +02002401 if (needs_ish(soc_id))
2402 cb_config.need_ish = true;
2403
Felix Held830add62022-03-29 23:28:10 +02002404 if (cb_config.need_ish)
2405 cb_config.recovery_ab = true;
2406
2407 if (cb_config.recovery_ab)
2408 cb_config.multi_level = true;
2409
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002410 if (config) {
2411 config_handle = fopen(config, "r");
2412 if (config_handle == NULL) {
2413 fprintf(stderr, "Can not open file %s for reading: %s\n",
2414 config, strerror(errno));
2415 exit(1);
2416 }
2417 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2418 fprintf(stderr, "Configuration file %s parsing error\n", config);
2419 fclose(config_handle);
2420 exit(1);
2421 }
2422 fclose(config_handle);
2423 }
Zheng Bao9e908072020-10-28 11:39:13 +08002424 /* For debug. */
2425 if (debug) {
2426 dump_psp_firmwares(amd_psp_fw_table);
2427 dump_bdt_firmwares(amd_bios_table);
2428 }
2429
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002430 if (!fuse_defined)
2431 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2432
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002433 if (!output && !list_deps) {
2434 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002435 retval = 1;
2436 }
2437
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002438 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2439 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002440 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002441 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002442 }
2443
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002444 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2445 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002446 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002447 retval = 1;
2448 }
2449
2450 if (retval) {
2451 usage();
2452 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002453 }
2454
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002455 if (list_deps) {
2456 return retval;
2457 }
2458
Marshall Dawson2794a862019-03-04 16:53:15 -07002459 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002460
Marshall Dawson2794a862019-03-04 16:53:15 -07002461 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002462 if (efs_location && (efs_location < rom_base_address)) {
2463 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2464 return 1;
2465 }
2466
Zheng Bao99945dc2023-01-02 10:55:56 +08002467 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002468 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2469 return 1;
2470 }
2471
2472 /*
2473 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2474 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2475 * currently. This condition is to ensure that it is not accidentally split. Revisit
2476 * this condition if such a need arises in the future.
2477 */
Zheng Bao99945dc2023-01-02 10:55:56 +08002478 if (!any_location && body_location != efs_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002479 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2480 return 1;
2481 }
2482
Zheng Bao99945dc2023-01-02 10:55:56 +08002483 if (body_location != efs_location &&
2484 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002485 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2486 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002487 return 1;
2488 }
Zheng Bao4e8fb352022-11-21 21:34:45 +08002489 if (efs_location & 0xFF000000)
2490 efs_location = efs_location - rom_base_address;
2491 if (body_location & 0xFF000000)
2492 body_location = body_location - rom_base_address;
Martin Roth0d3b1182017-10-03 14:16:04 -06002493
Martin Roth37305e72020-04-07 14:16:39 -06002494 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002495 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002496 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002497 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002498 return 1;
2499 }
2500 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002501 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002502 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002503 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002504 case 0xFA0000:
2505 case 0xF20000:
2506 case 0xE20000:
2507 case 0xC20000:
2508 case 0x820000:
2509 case 0x020000:
2510 break;
2511 case 0x7A0000:
2512 case 0x720000:
2513 case 0x620000:
2514 case 0x420000:
2515 /* Special cases for 8M. */
2516 if (ctx.rom_size != 0x800000) {
2517 fprintf(stderr, "Error: Invalid Directory location.\n");
2518 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2519 return 1;
2520 }
2521 break;
2522 case 0x3A0000:
2523 case 0x320000:
2524 case 0x220000:
2525 /* Special cases for 4M. */
2526 if (ctx.rom_size != 0x400000) {
2527 fprintf(stderr, "Error: Invalid Directory location.\n");
2528 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2529 return 1;
2530 }
Martin Roth37305e72020-04-07 14:16:39 -06002531 break;
2532 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002533 fprintf(stderr, "Error: Invalid Directory location.\n");
2534 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2535 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002536 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2537 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002538 return 1;
2539 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002540 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002541 ctx.rom = malloc(ctx.rom_size);
2542 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002543 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002544 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002545 }
2546 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002547
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002548 if (efs_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002549 if (efs_location != body_location) {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002550 romsig_offset = efs_location;
2551 ctx.current = body_location;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002552 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002553 romsig_offset = efs_location;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002554 ctx.current = romsig_offset + sizeof(embedded_firmware);
2555 }
2556 } else {
2557 romsig_offset = AMD_ROMSIG_OFFSET;
2558 ctx.current = romsig_offset + sizeof(embedded_firmware);
2559 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002560
Marshall Dawson2794a862019-03-04 16:53:15 -07002561 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002562 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2563 amd_romsig->imc_entry = 0;
2564 amd_romsig->gec_entry = 0;
2565 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002566
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002567 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08002568 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08002569 efs_spi_speed, efs_spi_micron_flag);
2570 if (retval) {
2571 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2572 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002573 }
2574 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002575 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002576 }
2577
Felix Held21a8e382022-03-29 23:10:45 +02002578 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002579 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002580 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002581 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002582 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002583 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002584 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2585 efs_location);
2586 if (body_location != efs_location)
2587 printf(" with a split body at: 0x%08x\n", body_location);
2588 else
2589 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002590
Marshall Dawson2794a862019-03-04 16:53:15 -07002591 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002592
Elyes Haouas7d67a192022-10-14 09:58:29 +02002593 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002594 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002595
Kangheui Won3c164e12021-12-03 20:25:05 +11002596 /* If the tool is invoked with command-line options to keep the signed PSP
2597 binaries separate, process the signed binaries first. */
2598 if (signed_output_file && signed_start_addr)
2599 process_signed_psp_firmwares(signed_output_file,
2600 amd_psp_fw_table,
2601 signed_start_addr,
2602 soc_id);
2603
Zheng Bao481661e2021-08-20 14:47:46 +08002604 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002605 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002606 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2607 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002608 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002609 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2610 /* Create a copy of PSP Directory 2 in the backup slot B.
2611 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002612 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2613 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002614 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002615 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002616 /*
2617 * Either the platform is using only one slot or B is same as above
2618 * directories for A. Skip creating pspdir2_b here to save flash space.
2619 * Related biosdir2_b will be skipped automatically.
2620 */
Zheng Bao990d1542021-09-17 13:24:54 +08002621 pspdir2_b = NULL; /* More explicitly */
2622 }
Zheng Bao481661e2021-08-20 14:47:46 +08002623 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002624 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002625 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002626 } else {
2627 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002628 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002629 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002630 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002631 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002632
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002633 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08002634 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07002635 else
Felix Heldad68b072021-10-18 14:00:35 +02002636 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002637
Zheng Bao993b43f2021-11-10 12:21:46 +08002638 if (cb_config.use_combo) {
2639 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2640 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2641 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2642 combo_dir->entries[0].id_sel = 0;
2643 combo_dir->entries[0].id = get_psp_id(soc_id);
2644 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002645
Zheng Bao993b43f2021-11-10 12:21:46 +08002646 combo_dir->header.lookup = 1;
2647 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2648 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002649
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002650 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002651 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002652 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002653 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002654 bios_directory_table *biosdir2 = NULL;
2655 bios_directory_table *biosdir2_b = NULL;
2656
2657 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2658
Zheng Baoedd1e362021-11-04 17:47:07 +08002659 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002660 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002661 if (cb_config.recovery_ab) {
2662 if (pspdir2_b != NULL) {
2663 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2664 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002665 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002666 }
2667 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2668 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2669 if (pspdir2_b != NULL)
2670 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2671 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2672 } else {
2673 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2674 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002675 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002676 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002677 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002678 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002679 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002680 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002681 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002682 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08002683 switch (soc_id) {
2684 case PLATFORM_RENOIR:
2685 case PLATFORM_LUCIENNE:
2686 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002687 if (!cb_config.recovery_ab)
2688 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002689 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002690 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002691 case PLATFORM_PHOENIX:
2692 case PLATFORM_GLINDA:
Zheng Bao535ec532021-08-12 16:30:19 +08002693 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +08002694 case PLATFORM_CARRIZO:
Zheng Baobf29a0d2020-12-03 23:00:48 +08002695 case PLATFORM_STONEYRIDGE:
2696 case PLATFORM_RAVEN:
2697 case PLATFORM_PICASSO:
2698 default:
2699 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2700 break;
2701 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002702 }
2703
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002704 /* Free the filename. */
2705 free_psp_firmware_filenames(amd_psp_fw_table);
2706 free_bdt_firmware_filenames(amd_bios_table);
2707
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002708 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002709 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002710 ssize_t bytes;
Zheng Bao4e8fb352022-11-21 21:34:45 +08002711 uint32_t offset = body_location ? body_location : AMD_ROMSIG_OFFSET;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002712
2713 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2714 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002715 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2716 retval = 1;
2717 }
Martin Roth31d95a22016-11-08 11:22:12 -07002718 close(targetfd);
2719 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002720 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002721 retval = 1;
2722 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002723
Zheng Bao99945dc2023-01-02 10:55:56 +08002724 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002725 ssize_t bytes;
2726
2727 bytes = write_efs(output, amd_romsig);
2728 if (bytes != sizeof(*amd_romsig)) {
2729 fprintf(stderr, "Error: Writing EFS\n");
2730 retval = 1;
2731 }
2732 }
2733
Martin Roth31d95a22016-11-08 11:22:12 -07002734 free(rom);
2735 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002736}