blob: abc0a9eb9d429e3d7458bdca72e7c099317d26ab [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/*
4 * ROMSIG At ROMBASE + 0x20000:
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 * +------------+---------------+----------------+------------+
zbaoc3b0b722016-02-19 13:47:31 +08009 * | PSPDIR ADDR|PSPDIR ADDR |<-- Field 0x14 could be either
10 * +------------+---------------+ 2nd PSP directory or PSP COMBO directory
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080011 * EC ROM should be 64K aligned.
12 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080013 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080014 * +------------+---------------+----------------+------------+
15 * | 'PSP$' | Fletcher | Count | Reserved |
16 * +------------+---------------+----------------+------------+
17 * | 0 | size | Base address | Reserved | Pubkey
18 * +------------+---------------+----------------+------------+
19 * | 1 | size | Base address | Reserved | Bootloader
20 * +------------+---------------+----------------+------------+
21 * | 8 | size | Base address | Reserved | Smu Firmware
22 * +------------+---------------+----------------+------------+
23 * | 3 | size | Base address | Reserved | Recovery Firmware
24 * +------------+---------------+----------------+------------+
25 * | |
26 * | |
27 * | Other PSP Firmware |
28 * | |
29 * | |
30 * +------------+---------------+----------------+------------+
Zheng Bao4fcc9f22015-11-20 12:29:04 +080031 *
zbaoc3b0b722016-02-19 13:47:31 +080032 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080033 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080034 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080035 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080036 * | R e s e r v e d |
37 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080038 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080039 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080040 * | ID-Sel | PSP ID | PSPDIR ADDR | | 3rd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080041 * +------------+---------------+----------------+------------+
42 * | |
43 * | Other PSP |
44 * | |
45 * +------------+---------------+----------------+------------+
46 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080047 */
48
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080049#include <fcntl.h>
50#include <errno.h>
Martin Roth37305e72020-04-07 14:16:39 -060051#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080052#include <stdio.h>
53#include <sys/stat.h>
54#include <sys/types.h>
55#include <unistd.h>
56#include <string.h>
57#include <stdlib.h>
58#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080059#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010060#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080061
62#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080063
Martin Roth60f15512016-11-08 09:55:01 -070064#define AMD_ROMSIG_OFFSET 0x20000
65#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080066
Martin Rothcd15bc82016-11-08 11:34:02 -070067#define ALIGN(val, by) (((val) + (by) - 1) & ~((by) - 1))
Marshall Dawson7c1e1422019-04-11 09:44:43 -060068#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
69#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070070#define TABLE_ALIGNMENT 0x1000U
71#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060072#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060073#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080074
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060075#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
76
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080077/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -070078 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
79 * can support an optional "combo" implementation. If the PSP sees the
80 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
81 * tables. Using this, support for multiple product generations may be
82 * built into one image. If the PSP$ cookie is found, the table is a
83 * normal directory table.
84 *
85 * Modern generations supporting the combo directories require the
86 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
87 * regardless of the type of directory used. The --combo-capable
88 * argument enforces this placement.
89 *
90 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +080091 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080093/*
94 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
95 * The checksum field of the passed PDU does not need to be reset to zero.
96 *
97 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
98 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
99 * alternative to cyclical redundancy checks because it provides error-
100 * detection properties similar to cyclical redundancy checks but at the
101 * cost of a simple summation technique. Its characteristics were first
102 * published in IEEE Transactions on Communications in January 1982. One
103 * version has been adopted by ISO for use in the class-4 transport layer
104 * of the network protocol.
105 *
106 * This program expects:
107 * stdin: The input file to compute a checksum for. The input file
108 * not be longer than 256 bytes.
109 * stdout: Copied from the input file with the Fletcher's Checksum
110 * inserted 8 bytes after the beginning of the file.
111 * stderr: Used to print out error messages.
112 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700113static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800114{
115 uint32_t c0;
116 uint32_t c1;
117 uint32_t checksum;
118 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700119 const uint16_t *pptr = data;
120
121 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800122
123 c0 = 0xFFFF;
124 c1 = 0xFFFF;
125
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600126 while (length) {
127 index = length >= 359 ? 359 : length;
128 length -= index;
129 do {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800130 c0 += *(pptr++);
131 c1 += c0;
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600132 } while (--index);
133 c0 = (c0 & 0xFFFF) + (c0 >> 16);
134 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800135 }
136
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700137 /* Sums[0,1] mod 64K + overflow */
138 c0 = (c0 & 0xFFFF) + (c0 >> 16);
139 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800140 checksum = (c1 << 16) | c0;
141
142 return checksum;
143}
144
Martin Roth8806f7f2016-11-08 10:44:18 -0700145static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800146{
Martin Roth0e940622016-11-08 10:37:53 -0700147 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800148 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
149 printf("--xhci <FILE> Add XHCI blob\n");
150 printf("--imc <FILE> Add IMC blob\n");
151 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700152
153 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800154 printf("--combo-capable Place PSP directory pointer at Embedded\n");
155 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700156 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800157 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800158 printf("--multilevel Generate primary and secondary tables\n");
159 printf("--nvram <FILE> Add nvram binary\n");
160 printf("--soft-fuse Set soft fuse\n");
161 printf("--token-unlock Set token unlock\n");
162 printf("--whitelist Set if there is a whitelist\n");
163 printf("--use-pspsecureos Set if psp secure OS is needed\n");
164 printf("--load-mp2-fw Set if load MP2 firmware\n");
165 printf("--load-s0i3 Set if load s0i3 firmware\n");
166 printf("--verstage <FILE> Add verstage\n");
167 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800168 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600169 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800170 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800171 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800172 printf("--apcb <FILE> Add AGESA PSP customization block\n");
173 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
174 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
175 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
176 printf("--ucode <FILE> Add microcode patch\n");
177 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
178 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
179 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
180 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
181 printf("--output <filename> output filename\n");
182 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600183 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700184 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600185 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800186 printf("--location Location of Directory\n");
187 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
188 printf("--sharedmem Location of PSP/FW shared memory\n");
189 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800190 printf(" area\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800191 printf("--soc-name <socname> Specify SOC name. Supported names are\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800192 printf(" Stoneyridge, Raven, Picasso, Renoir, Cezanne\n");
193 printf(" or Lucienne\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500194 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
195 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
196 printf(" 0x0 66.66Mhz\n");
197 printf(" 0x1 33.33MHz\n");
198 printf(" 0x2 22.22MHz\n");
199 printf(" 0x3 16.66MHz\n");
200 printf(" 0x4 100MHz\n");
201 printf(" 0x5 800KHz\n");
202 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
203 printf(" 0x0 Normal Read (up to 33M)\n");
204 printf(" 0x1 Reserved\n");
205 printf(" 0x2 Dual IO (1-1-2)\n");
206 printf(" 0x3 Quad IO (1-1-4)\n");
207 printf(" 0x4 Dual IO (1-2-2)\n");
208 printf(" 0x5 Quad IO (1-4-4)\n");
209 printf(" 0x6 Normal Read (up to 66M)\n");
210 printf(" 0x7 Fast Read\n");
211 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
212 printf(" 0x0 Micron parts are not used\n");
213 printf(" 0x1 Micron parts are always used\n");
214 printf(" 0x2 Micron parts optional, this option is only\n");
215 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800216 printf("\nGeneral options:\n");
217 printf("-c|--config <config file> Config file\n");
218 printf("-d|--debug Print debug message\n");
219 printf("-l|--list List out the firmware files\n");
220 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800221}
222
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800223amd_fw_entry amd_psp_fw_table[] = {
Zheng Baofb9b7842022-02-24 15:15:50 +0800224 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB },
225 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800226 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Marshall Dawson24f73d42019-04-01 10:48:43 -0600227 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
228 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
Zheng Bao990d1542021-09-17 13:24:54 +0800229 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
230 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
231 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
232 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB },
233 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
234 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
235 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
236 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
237 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
238 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
239 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH },
240 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
241 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
242 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Baofb9b7842022-02-24 15:15:50 +0800243 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800244 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
245 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
246 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
247 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
248 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
249 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
250 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
251 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
252 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
253 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
254 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
255 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
256 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
257 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
258 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
259 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
260 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
261 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
262 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
Felix Held5f18bb72022-03-24 02:04:51 +0100263 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
264 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
265 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800266 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
267 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian0ab04d22022-05-03 18:16:34 -0600268 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800269 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
270 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
271 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
272 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
273 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
274 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
275 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
276 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
277 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
278 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600279 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 },
Zheng Bao990d1542021-09-17 13:24:54 +0800280 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_BOTH_AB },
281 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_BOTH_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800282 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800283};
284
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800285amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800286 { .type = AMD_FW_XHCI },
287 { .type = AMD_FW_IMC },
288 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800289 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800290};
291
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800292amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800293 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600294 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
295 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
296 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
297 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
298 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700299 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
300 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
301 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
302 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
303 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
304 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
305 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
306 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
307 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
308 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
309 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700310 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
311 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
312 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
313 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
314 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700315 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
316 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
317 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
318 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
319 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
320 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
321 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
322 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
323 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
324 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
325 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600326 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
327 { .type = AMD_BIOS_BIN,
328 .reset = 1, .copy = 1, .zlib = 1, .level = BDT_BOTH },
329 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
330 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
331 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800332 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
333 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600334 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
335 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
336 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
337 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800338 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
339 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600340 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
341 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
342 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
343 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
344 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
345 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600346 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600347 { .type = AMD_BIOS_INVALID },
348};
349
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600350
Martin Roth94554742020-04-14 14:59:36 -0600351#define MAX_BIOS_ENTRIES 0x2f
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600352
Marshall Dawson2794a862019-03-04 16:53:15 -0700353typedef struct _context {
354 char *rom; /* target buffer, size of flash device */
355 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800356 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700357 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800358 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700359} context;
360
361#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800362#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600363 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
364 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
365 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800366#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600367#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800368 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700369#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800370/* The mode in entry can not be higher than the header's.
371 For example, if table mode is 0, all the entry mode will be 0. */
372#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
373 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700374#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
375#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
376#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800377#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
378 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700379#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800380/* Only set the address mode in entry if the table is mode 2. */
381#define SET_ADDR_MODE(table, mode) \
382 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600383 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800384#define SET_ADDR_MODE_BY_TABLE(table) \
385 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700386
Zheng Bao5164e4b2021-10-30 12:09:07 +0800387void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
388{
389 if (count >= max) {
390 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
391 "(%d)\n", count, max);
392 free(ctx->rom);
393 exit(1);
394 }
395}
396
Marshall Dawson24f73d42019-04-01 10:48:43 -0600397static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700398{
399 void *ptr;
400
Marshall Dawson24f73d42019-04-01 10:48:43 -0600401 /*
402 * Force both onto boundary when multi. Primary table is after
403 * updatable table, so alignment ensures primary can stay intact
404 * if secondary is reprogrammed.
405 */
406 if (multi)
407 ctx->current = ALIGN(ctx->current, TABLE_ERASE_ALIGNMENT);
408 else
409 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
410
Marshall Dawson2794a862019-03-04 16:53:15 -0700411 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800412 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800413 ((psp_directory_header *)ptr)->additional_info = 0;
414 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700415 ctx->current += sizeof(psp_directory_header)
416 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
417 return ptr;
418}
419
Zheng Baofdd47ef2021-09-17 13:30:08 +0800420static void *new_ish_dir(context *ctx)
421{
422 void *ptr;
423 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
424 ptr = BUFF_CURRENT(*ctx);
425 ctx->current += TABLE_ALIGNMENT;
426 return ptr;
427}
428
Marshall Dawson2794a862019-03-04 16:53:15 -0700429static void *new_combo_dir(context *ctx)
430{
431 void *ptr;
432
433 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
434 ptr = BUFF_CURRENT(*ctx);
435 ctx->current += sizeof(psp_combo_header)
436 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
437 return ptr;
438}
439
Zheng Baobf29a0d2020-12-03 23:00:48 +0800440static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800441{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600442 psp_combo_directory *cdir = directory;
443 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600444 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800445 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600446
447 if (!count)
448 return;
Zheng Baob035f582021-05-27 11:26:12 +0800449 if (ctx == NULL || directory == NULL) {
450 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
451 return;
452 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600453
Zheng Baobf29a0d2020-12-03 23:00:48 +0800454 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baob035f582021-05-27 11:26:12 +0800455 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800456
Marshall Dawson24f73d42019-04-01 10:48:43 -0600457 switch (cookie) {
458 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700459 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700460 cdir->header.cookie = cookie;
461 cdir->header.num_entries = count;
462 cdir->header.reserved[0] = 0;
463 cdir->header.reserved[1] = 0;
464 /* checksum everything that comes after the Checksum field */
465 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
466 count * sizeof(psp_combo_entry)
467 + sizeof(cdir->header.num_entries)
468 + sizeof(cdir->header.lookup)
469 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600470 break;
471 case PSP_COOKIE:
472 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800473 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800474 if ((table_size % TABLE_ALIGNMENT) != 0) {
475 fprintf(stderr, "The PSP table size should be 4K aligned\n");
476 exit(1);
477 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700478 dir->header.cookie = cookie;
479 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800480 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
481 dir->header.additional_info_fields.spi_block_size = 1;
482 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700483 /* checksum everything that comes after the Checksum field */
484 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700485 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700486 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800487 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600488 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800489 case BHD_COOKIE:
490 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800491 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800492 if ((table_size % TABLE_ALIGNMENT) != 0) {
493 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
494 exit(1);
495 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600496 bdir->header.cookie = cookie;
497 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800498 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
499 bdir->header.additional_info_fields.spi_block_size = 1;
500 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600501 /* checksum everything that comes after the Checksum field */
502 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
503 count * sizeof(bios_directory_entry)
504 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800505 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600506 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700507 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800508
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800509}
510
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700511static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
512{
513 int fd;
514 struct stat fd_stat;
515 ssize_t bytes;
516
517 fd = open(src_file, O_RDONLY);
518 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800519 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700520 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700521 return -1;
522 }
523
524 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800525 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600526 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700527 return -2;
528 }
529
Zheng Bao6d402ac2020-10-01 16:16:30 +0800530 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800531 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600532 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700533 return -3;
534 }
535
536 bytes = read(fd, dest, (size_t)fd_stat.st_size);
537 close(fd);
538 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800539 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700540 return -4;
541 }
542
543 return bytes;
544}
545
Zheng Baoeb0404e2021-10-14 15:09:09 +0800546enum platform {
547 PLATFORM_UNKNOWN,
548 PLATFORM_STONEYRIDGE,
549 PLATFORM_RAVEN,
550 PLATFORM_PICASSO,
551 PLATFORM_RENOIR,
552 PLATFORM_CEZANNE,
553 PLATFORM_MENDOCINO,
554 PLATFORM_LUCIENNE,
Felix Heldb18a4c72022-03-29 02:34:11 +0200555 PLATFORM_SABRINA,
Zheng Baoeb0404e2021-10-14 15:09:09 +0800556};
557
558static uint32_t get_psp_id(enum platform soc_id)
559{
560 uint32_t psp_id;
561 switch (soc_id) {
562 case PLATFORM_RAVEN:
563 case PLATFORM_PICASSO:
564 psp_id = 0xBC0A0000;
565 break;
566 case PLATFORM_RENOIR:
567 case PLATFORM_LUCIENNE:
568 psp_id = 0xBC0C0000;
569 break;
570 case PLATFORM_CEZANNE:
571 psp_id = 0xBC0C0140;
572 break;
573 case PLATFORM_MENDOCINO:
Felix Heldb18a4c72022-03-29 02:34:11 +0200574 case PLATFORM_SABRINA:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800575 psp_id = 0xBC0D0900;
576 break;
577 case PLATFORM_STONEYRIDGE:
578 psp_id = 0x10220B00;
579 break;
580 default:
581 psp_id = 0;
582 break;
583 }
584 return psp_id;
585}
586
Marshall Dawson2794a862019-03-04 16:53:15 -0700587static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700588 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700589 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800590{
Richard Spiegel137484d2018-01-17 10:23:19 -0700591 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800592 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700593
594 ctx->current += sizeof(embedded_firmware);
595 ctx->current = ALIGN(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800596
Martin Rothcd15bc82016-11-08 11:34:02 -0700597 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800598 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800599 switch (fw_table[i].type) {
600 case AMD_FW_IMC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700601 ctx->current = ALIGN(ctx->current, 0x10000U);
602 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800603 break;
604 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700605 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800606 break;
607 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700608 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800609 break;
610 default:
611 /* Error */
612 break;
613 }
614
Marshall Dawson2794a862019-03-04 16:53:15 -0700615 bytes = copy_blob(BUFF_CURRENT(*ctx),
616 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600617 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700618 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700619 exit(1);
620 }
621
Marshall Dawson2794a862019-03-04 16:53:15 -0700622 ctx->current = ALIGN(ctx->current + bytes,
623 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800624 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800625 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800626}
627
Zheng Bao9e908072020-10-28 11:39:13 +0800628/* For debugging */
629static void dump_psp_firmwares(amd_fw_entry *fw_table)
630{
631 amd_fw_entry *index;
632
633 printf("PSP firmware components:");
634 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
635 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800636 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800637 }
638}
639
640static void dump_bdt_firmwares(amd_bios_entry *fw_table)
641{
642 amd_bios_entry *index;
643
644 printf("BIOS Directory Table (BDT) components:");
645 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
646 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800647 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800648 }
649}
650
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800651static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
652{
653 amd_fw_entry *index;
654
655 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
656 if (index->filename &&
657 index->type != AMD_FW_VERSTAGE_SIG &&
658 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800659 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800660 index->type != AMD_FW_PSP_WHITELIST) {
661 free(index->filename);
662 }
663 }
664}
665
666static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
667{
668 amd_bios_entry *index;
669
670 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
671 if (index->filename &&
672 index->type != AMD_BIOS_APCB &&
673 index->type != AMD_BIOS_BIN &&
674 index->type != AMD_BIOS_APCB_BK)
675 free(index->filename);
676 }
677}
678
Zheng Bao990d1542021-09-17 13:24:54 +0800679static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800680 psp_directory_table *pspdir2, ish_directory_table *ish,
681 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800682{
683 uint32_t count;
684 uint32_t current_table_save;
685
686 current_table_save = ctx->current_table;
687 ctx->current_table = (char *)pspdir - ctx->rom;
688 count = pspdir->header.num_entries;
689 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
690 pspdir->entries[count].type = (uint8_t)ab;
691 pspdir->entries[count].subprog = 0;
692 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800693 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600694 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800695 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
696 ish->update_retry_count = 2;
697 ish->glitch_retry_count = 0;
698 ish->psp_id = get_psp_id(soc_id);
699 ish->checksum = fletcher32(&ish->boot_priority,
700 sizeof(ish_directory_table) - sizeof(uint32_t));
701 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600702 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800703 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600704 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800705 pspdir->entries[count].size = TABLE_ALIGNMENT;
706 } else {
707 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600708 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800709 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600710 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800711 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800712 sizeof(psp_directory_entry) +
713 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800714 }
Zheng Bao990d1542021-09-17 13:24:54 +0800715
716 count++;
717 pspdir->header.num_entries = count;
718 ctx->current_table = current_table_save;
719}
720
Marshall Dawson2794a862019-03-04 16:53:15 -0700721static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700722 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600723 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800724 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600725 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800726 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800727 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +0800728 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800729{
Richard Spiegel137484d2018-01-17 10:23:19 -0700730 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700731 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600732 int level;
Zheng Bao6fff2492021-11-15 19:53:21 +0800733 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800734 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800735 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600736
737 /* This function can create a primary table, a secondary table, or a
738 * flattened table which contains all applicable types. These if-else
739 * statements infer what the caller intended. If a 2nd-level cookie
740 * is passed, clearly a 2nd-level table is intended. However, a
741 * 1st-level cookie may indicate level 1 or flattened. If the caller
742 * passes a pointer to a 2nd-level table, then assume not flat.
743 */
Zheng Baoba3af5e2021-11-04 18:56:47 +0800744 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800745 level = PSP_BOTH;
746 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600747 level = PSP_LVL2;
748 else if (pspdir2)
749 level = PSP_LVL1;
750 else
751 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -0700752
Zheng Bao990d1542021-09-17 13:24:54 +0800753 if (recovery_ab) {
754 if (cookie == PSPL2_COOKIE)
755 level = PSP_LVL2_AB;
756 else if (pspdir2)
757 level = PSP_LVL1_AB;
758 else
759 level = PSP_BOTH_AB;
760 }
Zheng Bao6fff2492021-11-15 19:53:21 +0800761 current_table_save = ctx->current_table;
762 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800763 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800764
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700765 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -0600766 if (!(fw_table[i].level & level))
767 continue;
768
Zheng Bao5164e4b2021-10-30 12:09:07 +0800769 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
770
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600771 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
772 if (!fw_table[i].other)
773 continue;
774 ctx->current = ALIGN(ctx->current, ERASE_ALIGNMENT);
775 pspdir->entries[count].type = fw_table[i].type;
776 pspdir->entries[count].size = 4096; /* TODO: doc? */
777 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800778 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600779 pspdir->entries[count].subprog = fw_table[i].subprog;
780 pspdir->entries[count].rsvd = 0;
781 ctx->current = ALIGN(ctx->current + 4096, 0x100U);
782 count++;
783 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -0700784 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -0700785 pspdir->entries[count].subprog = fw_table[i].subprog;
786 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -0700787 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600788 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +0800789 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700790 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -0600791 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
792 if (fw_table[i].filename == NULL)
793 continue;
794 /* TODO: Add a way to reserve for NVRAM without
795 * requiring a filename. This isn't a feature used
796 * by coreboot systems, so priority is very low.
797 */
798 ctx->current = ALIGN(ctx->current, ERASE_ALIGNMENT);
799 bytes = copy_blob(BUFF_CURRENT(*ctx),
800 fw_table[i].filename, BUFF_ROOM(*ctx));
801 if (bytes <= 0) {
802 free(ctx->rom);
803 exit(1);
804 }
805
806 pspdir->entries[count].type = fw_table[i].type;
807 pspdir->entries[count].subprog = fw_table[i].subprog;
808 pspdir->entries[count].rsvd = 0;
809 pspdir->entries[count].size = ALIGN(bytes,
810 ERASE_ALIGNMENT);
Zheng Bao6fff2492021-11-15 19:53:21 +0800811 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600812 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +0800813 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600814 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -0600815
816 ctx->current = ALIGN(ctx->current + bytes,
817 BLOB_ERASE_ALIGNMENT);
818 count++;
zbaoc3a08a92016-03-02 14:47:27 +0800819 } else if (fw_table[i].filename != NULL) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700820 bytes = copy_blob(BUFF_CURRENT(*ctx),
821 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600822 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700823 free(ctx->rom);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700824 exit(1);
825 }
826
Marshall Dawson239286c2019-02-23 16:42:46 -0700827 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -0700828 pspdir->entries[count].subprog = fw_table[i].subprog;
829 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700830 pspdir->entries[count].size = (uint32_t)bytes;
Marshall Dawson2794a862019-03-04 16:53:15 -0700831 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800832 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800833
Marshall Dawson2794a862019-03-04 16:53:15 -0700834 ctx->current = ALIGN(ctx->current + bytes,
835 BLOB_ALIGNMENT);
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700836 count++;
zbaoc3a08a92016-03-02 14:47:27 +0800837 } else {
838 /* This APU doesn't have this firmware. */
839 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800840 }
Marshall Dawson2794a862019-03-04 16:53:15 -0700841
Zheng Bao990d1542021-09-17 13:24:54 +0800842 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +0800843 if (cb_config->need_ish) { /* Need ISH */
844 ish_a_dir = new_ish_dir(ctx);
845 if (pspdir2_b != NULL)
846 ish_b_dir = new_ish_dir(ctx);
847 }
Zheng Bao990d1542021-09-17 13:24:54 +0800848 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800849 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
850 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +0800851 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +0800852 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
853 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -0600854 else
855 integrate_psp_ab(ctx, pspdir, pspdir2, ish_b_dir,
856 AMD_FW_RECOVERYAB_B, soc_id);
857
Zheng Bao990d1542021-09-17 13:24:54 +0800858 count = pspdir->header.num_entries;
859 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +0800860 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600861 pspdir->entries[count].type = AMD_FW_L2_PTR;
862 pspdir->entries[count].subprog = 0;
863 pspdir->entries[count].rsvd = 0;
864 pspdir->entries[count].size = sizeof(pspdir2->header)
865 + pspdir2->header.num_entries
866 * sizeof(psp_directory_entry);
867
Zheng Bao6fff2492021-11-15 19:53:21 +0800868 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600869 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +0800870 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600871 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600872 count++;
873 }
874
Zheng Baobf29a0d2020-12-03 23:00:48 +0800875 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800876 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800877}
878
Zheng Bao990d1542021-09-17 13:24:54 +0800879static void add_psp_firmware_entry(context *ctx,
880 psp_directory_table *pspdir,
881 void *table, amd_fw_type type, uint32_t size)
882{
883 uint32_t count = pspdir->header.num_entries;
884 uint32_t index;
885 uint32_t current_table_save;
886
887 current_table_save = ctx->current_table;
888 ctx->current_table = (char *)pspdir - ctx->rom;
889
890 /* If there is an entry of "type", replace it. */
891 for (index = 0; index < count; index++) {
892 if (pspdir->entries[index].type == (uint8_t)type)
893 break;
894 }
895
896 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
897 pspdir->entries[index].type = (uint8_t)type;
898 pspdir->entries[index].subprog = 0;
899 pspdir->entries[index].rsvd = 0;
900 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
901 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
902 pspdir->entries[index].size = size;
903 if (index == count)
904 count++;
905
906 pspdir->header.num_entries = count;
907 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
908 count * sizeof(psp_directory_entry)
909 + sizeof(pspdir->header.num_entries)
910 + sizeof(pspdir->header.additional_info));
911
912 ctx->current_table = current_table_save;
913}
914
Zheng Baoba3af5e2021-11-04 18:56:47 +0800915static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600916{
917 void *ptr;
918
919 /*
920 * Force both onto boundary when multi. Primary table is after
921 * updatable table, so alignment ensures primary can stay intact
922 * if secondary is reprogrammed.
923 */
924 if (multi)
925 ctx->current = ALIGN(ctx->current, TABLE_ERASE_ALIGNMENT);
926 else
927 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
928 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800929 ((bios_directory_hdr *) ptr)->additional_info = 0;
930 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
931 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600932 ctx->current += sizeof(bios_directory_hdr)
933 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
934 return ptr;
935}
936
937static int locate_bdt2_bios(bios_directory_table *level2,
938 uint64_t *source, uint32_t *size)
939{
Zheng Bao6d402ac2020-10-01 16:16:30 +0800940 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600941
942 *source = 0;
943 *size = 0;
944 if (!level2)
945 return 0;
946
947 for (i = 0 ; i < level2->header.num_entries ; i++) {
948 if (level2->entries[i].type == AMD_BIOS_BIN) {
949 *source = level2->entries[i].source;
950 *size = level2->entries[i].size;
951 return 1;
952 }
953 }
954 return 0;
955}
956
957static int have_bios_tables(amd_bios_entry *table)
958{
959 int i;
960
961 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
962 if (table[i].level & BDT_LVL1 && table[i].filename)
963 return 1;
964 }
965 return 0;
966}
967
Marshall Dawsonc4a8c482020-01-21 17:17:59 -0700968static int find_bios_entry(amd_bios_type type)
969{
970 int i;
971
972 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
973 if (amd_bios_table[i].type == type)
974 return i;
975 }
976 return -1;
977}
978
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600979static void integrate_bios_firmwares(context *ctx,
980 bios_directory_table *biosdir,
981 bios_directory_table *biosdir2,
982 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800983 uint32_t cookie,
984 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600985{
986 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -0600987 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600988 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -0700989 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -0600990 uint32_t size;
991 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600992
993 /* This function can create a primary table, a secondary table, or a
994 * flattened table which contains all applicable types. These if-else
995 * statements infer what the caller intended. If a 2nd-level cookie
996 * is passed, clearly a 2nd-level table is intended. However, a
997 * 1st-level cookie may indicate level 1 or flattened. If the caller
998 * passes a pointer to a 2nd-level table, then assume not flat.
999 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001000 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001001 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001002 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001003 level = BDT_LVL2;
1004 else if (biosdir2)
1005 level = BDT_LVL1;
1006 else
1007 level = BDT_BOTH;
1008
Zheng Baobf29a0d2020-12-03 23:00:48 +08001009 ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001010
1011 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1012 if (!(fw_table[i].level & level))
1013 continue;
1014 if (fw_table[i].filename == NULL && (
1015 fw_table[i].type != AMD_BIOS_APOB &&
1016 fw_table[i].type != AMD_BIOS_APOB_NV &&
1017 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001018 fw_table[i].type != AMD_BIOS_BIN &&
1019 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001020 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001021
1022 /* BIOS Directory items may have additional requirements */
1023
Martin Roth48dd9fe2020-07-29 16:32:25 -06001024 /* Check APOB_NV requirements */
1025 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1026 if (!fw_table[i].size && !fw_table[i].src)
1027 continue; /* APOB_NV not used */
1028 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001029 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001030 free(ctx->rom);
1031 exit(1);
1032 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001033 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001034 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001035 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1036 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001037 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001038
1039 /* APOB_DATA needs destination */
1040 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001041 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001042 free(ctx->rom);
1043 exit(1);
1044 }
1045
1046 /* BIOS binary must have destination and uncompressed size. If
1047 * no filename given, then user must provide a source address.
1048 */
1049 if (fw_table[i].type == AMD_BIOS_BIN) {
1050 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001051 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001052 free(ctx->rom);
1053 exit(1);
1054 }
1055 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001056 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001057 free(ctx->rom);
1058 exit(1);
1059 }
1060 }
1061
Martin Roth94554742020-04-14 14:59:36 -06001062 /* PSP_SHARED_MEM needs a destination and size */
1063 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1064 (!fw_table[i].dest || !fw_table[i].size))
1065 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001066 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001067
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001068 biosdir->entries[count].type = fw_table[i].type;
1069 biosdir->entries[count].region_type = fw_table[i].region_type;
1070 biosdir->entries[count].dest = fw_table[i].dest ?
1071 fw_table[i].dest : (uint64_t)-1;
1072 biosdir->entries[count].reset = fw_table[i].reset;
1073 biosdir->entries[count].copy = fw_table[i].copy;
1074 biosdir->entries[count].ro = fw_table[i].ro;
1075 biosdir->entries[count].compressed = fw_table[i].zlib;
1076 biosdir->entries[count].inst = fw_table[i].inst;
1077 biosdir->entries[count].subprog = fw_table[i].subpr;
1078
1079 switch (fw_table[i].type) {
1080 case AMD_BIOS_APOB:
1081 biosdir->entries[count].size = fw_table[i].size;
1082 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001083 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001084 break;
1085 case AMD_BIOS_APOB_NV:
1086 if (fw_table[i].src) {
1087 /* If source is given, use that and its size */
1088 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001089 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001090 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001091 biosdir->entries[count].size = fw_table[i].size;
1092 } else {
1093 /* Else reserve size bytes within amdfw.rom */
1094 ctx->current = ALIGN(ctx->current, ERASE_ALIGNMENT);
1095 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001096 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001097 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001098 biosdir->entries[count].size = ALIGN(
1099 fw_table[i].size, ERASE_ALIGNMENT);
1100 memset(BUFF_CURRENT(*ctx), 0xff,
1101 biosdir->entries[count].size);
1102 ctx->current = ctx->current
1103 + biosdir->entries[count].size;
1104 }
1105 break;
1106 case AMD_BIOS_BIN:
1107 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001108 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1109 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001110 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001111 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001112 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001113 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001114 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001115
1116 /* level 2, or level 1 and no copy found in level 2 */
1117 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001118 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001119 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001120 biosdir->entries[count].dest = fw_table[i].dest;
1121 biosdir->entries[count].size = fw_table[i].size;
1122
1123 if (!fw_table[i].filename)
1124 break;
1125
1126 bytes = copy_blob(BUFF_CURRENT(*ctx),
1127 fw_table[i].filename, BUFF_ROOM(*ctx));
1128 if (bytes <= 0) {
1129 free(ctx->rom);
1130 exit(1);
1131 }
1132
Zheng Bao6fff2492021-11-15 19:53:21 +08001133 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001134 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001135 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001136 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001137
1138 ctx->current = ALIGN(ctx->current + bytes, 0x100U);
1139 break;
Martin Roth94554742020-04-14 14:59:36 -06001140 case AMD_BIOS_PSP_SHARED_MEM:
1141 biosdir->entries[count].dest = fw_table[i].dest;
1142 biosdir->entries[count].size = fw_table[i].size;
1143 break;
1144
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001145 default: /* everything else is copied from input */
1146 if (fw_table[i].type == AMD_BIOS_APCB ||
1147 fw_table[i].type == AMD_BIOS_APCB_BK)
1148 ctx->current = ALIGN(
1149 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001150 bytes = copy_blob(BUFF_CURRENT(*ctx),
1151 fw_table[i].filename, BUFF_ROOM(*ctx));
1152 if (bytes <= 0) {
1153 free(ctx->rom);
1154 exit(1);
1155 }
1156
1157 biosdir->entries[count].size = (uint32_t)bytes;
1158 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001159 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001160
1161 ctx->current = ALIGN(ctx->current + bytes, 0x100U);
1162 break;
1163 }
1164
1165 count++;
1166 }
1167
1168 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001169 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001170 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001171 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001172 biosdir->entries[count].size =
1173 + MAX_BIOS_ENTRIES
1174 * sizeof(bios_directory_entry);
1175 biosdir->entries[count].source =
1176 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001177 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001178 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001179 biosdir->entries[count].subprog = 0;
1180 biosdir->entries[count].inst = 0;
1181 biosdir->entries[count].copy = 0;
1182 biosdir->entries[count].compressed = 0;
1183 biosdir->entries[count].dest = -1;
1184 biosdir->entries[count].reset = 0;
1185 biosdir->entries[count].ro = 0;
1186 count++;
1187 }
1188
Zheng Baobf29a0d2020-12-03 23:00:48 +08001189 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001190}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001191
1192enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001193 AMDFW_OPT_CONFIG = 'c',
1194 AMDFW_OPT_DEBUG = 'd',
1195 AMDFW_OPT_HELP = 'h',
1196 AMDFW_OPT_LIST_DEPEND = 'l',
1197
1198 AMDFW_OPT_XHCI = 128,
1199 AMDFW_OPT_IMC,
1200 AMDFW_OPT_GEC,
1201 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001202 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001203 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001204 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001205 AMDFW_OPT_MULTILEVEL,
1206 AMDFW_OPT_NVRAM,
1207
1208 AMDFW_OPT_FUSE,
1209 AMDFW_OPT_UNLOCK,
1210 AMDFW_OPT_WHITELIST,
1211 AMDFW_OPT_USE_PSPSECUREOS,
1212 AMDFW_OPT_LOAD_MP2FW,
1213 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001214 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001215 AMDFW_OPT_VERSTAGE,
1216 AMDFW_OPT_VERSTAGE_SIG,
1217
1218 AMDFW_OPT_INSTANCE,
1219 AMDFW_OPT_APCB,
1220 AMDFW_OPT_APOBBASE,
1221 AMDFW_OPT_BIOSBIN,
1222 AMDFW_OPT_BIOSBIN_SOURCE,
1223 AMDFW_OPT_BIOSBIN_DEST,
1224 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1225 AMDFW_OPT_UCODE,
1226 AMDFW_OPT_APOB_NVBASE,
1227 AMDFW_OPT_APOB_NVSIZE,
1228
1229 AMDFW_OPT_OUTPUT,
1230 AMDFW_OPT_FLASHSIZE,
1231 AMDFW_OPT_LOCATION,
1232 AMDFW_OPT_ANYWHERE,
1233 AMDFW_OPT_SHAREDMEM,
1234 AMDFW_OPT_SHAREDMEM_SIZE,
1235 AMDFW_OPT_SOC_NAME,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001236 /* begin after ASCII characters */
1237 LONGOPT_SPI_READ_MODE = 256,
1238 LONGOPT_SPI_SPEED = 257,
1239 LONGOPT_SPI_MICRON_FLAG = 258,
1240};
1241
Zheng Bao806892a2021-04-27 17:21:54 +08001242static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1243 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1244};
Marc Jones90099b62016-09-20 21:05:45 -06001245
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001246static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001247 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1248 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1249 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001250 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001251 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001252 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001253 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001254 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001255 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1256 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
1257 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1258 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1259 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1260 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1261 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1262 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001263 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001264 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1265 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001266 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001267 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1268 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1269 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1270 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1271 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1272 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1273 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
1274 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1275 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1276 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001277 /* Embedded Firmware Structure items*/
1278 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1279 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1280 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001281 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001282 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1283 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1284 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1285 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1286 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1287 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1288 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001289
Zheng Bao806892a2021-04-27 17:21:54 +08001290 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1291 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1292 {"help", no_argument, 0, AMDFW_OPT_HELP },
1293 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001294 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001295};
1296
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001297void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001298{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001299 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001300
1301 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1302 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1303 continue;
1304
1305 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1306 return;
1307 }
1308}
1309
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001310static void register_fw_token_unlock(void)
1311{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001312 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001313
1314 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1315 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1316 continue;
1317
1318 amd_psp_fw_table[i].other = 1;
1319 return;
1320 }
1321}
1322
Marshall Dawsondbae6322019-03-04 10:31:03 -07001323static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001324{
Martin Roth8806f7f2016-11-08 10:44:18 -07001325 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001326
Martin Rothcd15bc82016-11-08 11:34:02 -07001327 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001328 if (amd_fw_table[i].type == type) {
1329 amd_fw_table[i].filename = filename;
1330 return;
1331 }
1332 }
1333
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001334 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001335 if (amd_psp_fw_table[i].type != type)
1336 continue;
1337
1338 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001339 amd_psp_fw_table[i].filename = filename;
1340 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001341 }
1342 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001343}
1344
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001345static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1346{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001347 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001348
1349 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1350 if (amd_bios_table[i].type == type
1351 && amd_bios_table[i].inst == ins
1352 && amd_bios_table[i].subpr == sub) {
1353 amd_bios_table[i].filename = name;
1354 return;
1355 }
1356 }
1357}
1358
Martin Rothec933132019-07-13 20:03:34 -06001359static void register_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001360 char *dst_str, char *size_str)
1361{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001362 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001363 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1364 if (amd_bios_table[i].type != type)
1365 continue;
1366
1367 if (src_str)
1368 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1369 if (dst_str)
1370 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1371 if (size_str)
1372 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1373
1374 return;
1375 }
1376}
1377
Zheng Baoc3007f32022-04-03 12:53:51 +08001378static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1379 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1380 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001381{
1382 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001383 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001384 return 1;
1385 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001386
1387 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1388 * Leave as 0xffffffff for first gen */
1389 if (cb_config->second_gen) {
1390 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1391 amd_romsig->efs_gen.reserved = 0;
1392 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001393 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1394 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001395 }
1396
1397 switch (soc_id) {
1398 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001399 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1400 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1401 break;
1402 case PLATFORM_RAVEN:
1403 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001404 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1405 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1406 switch (efs_spi_micron_flag) {
1407 case 0:
1408 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1409 break;
1410 case 1:
1411 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1412 break;
1413 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001414 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001415 return 1;
1416 }
1417 break;
1418 case PLATFORM_RENOIR:
1419 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001420 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001421 case PLATFORM_MENDOCINO:
Felix Heldb18a4c72022-03-29 02:34:11 +02001422 case PLATFORM_SABRINA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001423 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1424 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1425 switch (efs_spi_micron_flag) {
1426 case 0:
1427 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1428 break;
1429 case 1:
1430 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1431 break;
1432 case 2:
1433 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1434 break;
1435 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001436 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001437 return 1;
1438 }
1439 break;
1440 case PLATFORM_UNKNOWN:
1441 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001442 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001443 return 1;
1444 }
1445 return 0;
1446}
1447
1448static int identify_platform(char *soc_name)
1449{
1450 if (!strcasecmp(soc_name, "Stoneyridge"))
1451 return PLATFORM_STONEYRIDGE;
1452 else if (!strcasecmp(soc_name, "Raven"))
1453 return PLATFORM_RAVEN;
1454 else if (!strcasecmp(soc_name, "Picasso"))
1455 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08001456 else if (!strcasecmp(soc_name, "Cezanne"))
1457 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08001458 else if (!strcasecmp(soc_name, "Mendocino"))
1459 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001460 else if (!strcasecmp(soc_name, "Renoir"))
1461 return PLATFORM_RENOIR;
1462 else if (!strcasecmp(soc_name, "Lucienne"))
1463 return PLATFORM_LUCIENNE;
Felix Heldb18a4c72022-03-29 02:34:11 +02001464 else if (!strcasecmp(soc_name, "Sabrina"))
1465 return PLATFORM_SABRINA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001466 else
1467 return PLATFORM_UNKNOWN;
1468
1469}
1470
Felix Heldf8e2e472022-03-29 23:28:49 +02001471static bool needs_ish(enum platform platform_type)
1472{
1473 if (platform_type == PLATFORM_SABRINA)
1474 return true;
1475 else
1476 return false;
1477}
1478
Zheng Baoc3007f32022-04-03 12:53:51 +08001479static bool is_second_gen(enum platform platform_type)
1480{
1481 switch (platform_type) {
1482 case PLATFORM_STONEYRIDGE:
1483 case PLATFORM_RAVEN:
1484 case PLATFORM_PICASSO:
1485 return false;
1486 case PLATFORM_RENOIR:
1487 case PLATFORM_LUCIENNE:
1488 case PLATFORM_CEZANNE:
1489 case PLATFORM_SABRINA:
1490 return true;
1491 case PLATFORM_UNKNOWN:
1492 default:
1493 fprintf(stderr, "Error: Invalid SOC name.\n\n");
1494 return false;
1495 }
1496}
1497
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001498int main(int argc, char **argv)
1499{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001500 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001501 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001502 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07001503 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07001504 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001505 psp_directory_table *pspdir = NULL;
1506 psp_directory_table *pspdir2 = NULL;
1507 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08001508 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001509 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001510 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001511 char *output = NULL, *config = NULL;
1512 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001513 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001514 /* Values cleared after each firmware or parameter, regardless if N/A */
1515 uint8_t sub = 0, instance = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001516 uint32_t dir_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001517 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001518 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07001519 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001520 uint8_t soc_id = PLATFORM_UNKNOWN;
1521 uint8_t efs_spi_readmode = 0xff;
1522 uint8_t efs_spi_speed = 0xff;
1523 uint8_t efs_spi_micron_flag = 0xff;
1524
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001525 amd_cb_config cb_config;
Zheng Bao9e908072020-10-28 11:39:13 +08001526 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001527 int list_deps = 0;
1528
Zheng Baoba3af5e2021-11-04 18:56:47 +08001529 cb_config.have_whitelist = false;
1530 cb_config.unlock_secure = false;
1531 cb_config.use_secureos = false;
1532 cb_config.load_mp2_fw = false;
1533 cb_config.s0i3 = false;
1534 cb_config.multi_level = false;
Zheng Bao990d1542021-09-17 13:24:54 +08001535 cb_config.recovery_ab = false;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001536 cb_config.need_ish = false;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001537 cb_config.recovery_ab_single_copy = false;
Zheng Bao993b43f2021-11-10 12:21:46 +08001538 cb_config.use_combo = false;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001539
1540 while (1) {
1541 int optindex = 0;
1542
1543 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1544
1545 if (c == -1)
1546 break;
1547
1548 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001549 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001550 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001551 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001552 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001553 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001554 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001555 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001556 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001557 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001558 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001559 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001560 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001561 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001562 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07001563 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001564 case AMDFW_OPT_RECOVERY_AB:
1565 cb_config.recovery_ab = true;
1566 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001567 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1568 cb_config.recovery_ab = true;
1569 cb_config.recovery_ab_single_copy = true;
1570 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001571 case AMDFW_OPT_USE_COMBO:
1572 cb_config.use_combo = true;
1573 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001574 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001575 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001576 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001577 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001578 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001579 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001580 sub = instance = 0;
1581 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001582 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001583 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001584 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001585 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001586 instance = strtoul(optarg, &tmp, 16);
1587 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001588 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001589 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001590 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001591 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001592 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001593 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001594 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001595 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001596 register_fw_fuse(optarg);
1597 fuse_defined = 1;
1598 sub = 0;
1599 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001600 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08001601 if ((instance & 0xF0) == 0)
1602 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
1603 else
1604 register_bdt_data(AMD_BIOS_APCB_BK, sub,
1605 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001606 sub = instance = 0;
1607 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001608 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001609 /* APOB destination */
1610 register_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
1611 sub = instance = 0;
1612 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001613 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001614 /* APOB NV source */
1615 register_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
1616 sub = instance = 0;
1617 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001618 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001619 /* APOB NV size */
1620 register_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
1621 sub = instance = 0;
1622 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001623 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001624 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
1625 sub = instance = 0;
1626 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001627 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001628 /* BIOS source */
1629 register_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
1630 sub = instance = 0;
1631 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001632 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001633 /* BIOS destination */
1634 register_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
1635 sub = instance = 0;
1636 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001637 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001638 /* BIOS destination size */
1639 register_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
1640 sub = instance = 0;
1641 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001642 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001643 register_bdt_data(AMD_BIOS_UCODE, sub,
1644 instance, optarg);
1645 sub = instance = 0;
1646 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001647 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001648 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001649 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001650 case AMDFW_OPT_SPL_TABLE:
1651 register_fw_filename(AMD_FW_SPL, sub, optarg);
1652 sub = instance = 0;
1653 cb_config.have_mb_spl = true;
1654 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001655 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001656 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
1657 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08001658 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001659 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001660 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06001661 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
1662 sub = instance = 0;
1663 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001664 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06001665 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
1666 sub = instance = 0;
1667 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001668 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001669 soc_id = identify_platform(optarg);
1670 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001671 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001672 retval = 1;
1673 }
1674 sub = instance = 0;
1675 break;
1676 case LONGOPT_SPI_READ_MODE:
1677 efs_spi_readmode = strtoull(optarg, NULL, 16);
1678 sub = instance = 0;
1679 break;
1680 case LONGOPT_SPI_SPEED:
1681 efs_spi_speed = strtoull(optarg, NULL, 16);
1682 sub = instance = 0;
1683 break;
1684 case LONGOPT_SPI_MICRON_FLAG:
1685 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
1686 sub = instance = 0;
1687 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001688 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001689 output = optarg;
1690 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001691 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07001692 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07001693 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08001694 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07001695 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07001696 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07001697 }
1698 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001699 case AMDFW_OPT_LOCATION:
Martin Roth0d3b1182017-10-03 14:16:04 -06001700 dir_location = (uint32_t)strtoul(optarg, &tmp, 16);
1701 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08001702 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06001703 " incorrectly (%s)\n\n", optarg);
1704 retval = 1;
1705 }
1706 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001707 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06001708 any_location = 1;
1709 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001710 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06001711 /* shared memory destination */
1712 register_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
1713 sub = instance = 0;
1714 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001715 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06001716 /* shared memory size */
1717 register_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
1718 sub = instance = 0;
1719 break;
Martin Roth0d3b1182017-10-03 14:16:04 -06001720
Zheng Bao806892a2021-04-27 17:21:54 +08001721 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001722 config = optarg;
1723 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001724 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08001725 debug = 1;
1726 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001727 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001728 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07001729 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08001730 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001731 list_deps = 1;
1732 break;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001733 default:
1734 break;
1735 }
1736 }
1737
Zheng Baoc3007f32022-04-03 12:53:51 +08001738 cb_config.second_gen = is_second_gen(soc_id);
1739
Felix Heldf8e2e472022-03-29 23:28:49 +02001740 if (needs_ish(soc_id))
1741 cb_config.need_ish = true;
1742
Felix Held830add62022-03-29 23:28:10 +02001743 if (cb_config.need_ish)
1744 cb_config.recovery_ab = true;
1745
1746 if (cb_config.recovery_ab)
1747 cb_config.multi_level = true;
1748
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001749 if (config) {
1750 config_handle = fopen(config, "r");
1751 if (config_handle == NULL) {
1752 fprintf(stderr, "Can not open file %s for reading: %s\n",
1753 config, strerror(errno));
1754 exit(1);
1755 }
1756 if (process_config(config_handle, &cb_config, list_deps) == 0) {
1757 fprintf(stderr, "Configuration file %s parsing error\n", config);
1758 fclose(config_handle);
1759 exit(1);
1760 }
1761 fclose(config_handle);
1762 }
Zheng Bao9e908072020-10-28 11:39:13 +08001763 /* For debug. */
1764 if (debug) {
1765 dump_psp_firmwares(amd_psp_fw_table);
1766 dump_bdt_firmwares(amd_bios_table);
1767 }
1768
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001769 if (!fuse_defined)
1770 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
1771
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001772 if (!output && !list_deps) {
1773 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07001774 retval = 1;
1775 }
1776
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001777 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
1778 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07001779 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07001780 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07001781 }
1782
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001783 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
1784 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07001785 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07001786 retval = 1;
1787 }
1788
1789 if (retval) {
1790 usage();
1791 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07001792 }
1793
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001794 if (list_deps) {
1795 return retval;
1796 }
1797
Marshall Dawson2794a862019-03-04 16:53:15 -07001798 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07001799
Marshall Dawson2794a862019-03-04 16:53:15 -07001800 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Martin Roth0d3b1182017-10-03 14:16:04 -06001801 if (dir_location && (dir_location < rom_base_address)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001802 fprintf(stderr, "Error: Directory location outside of ROM.\n\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06001803 return 1;
1804 }
1805
Martin Roth37305e72020-04-07 14:16:39 -06001806 if (any_location) {
1807 if (dir_location & 0x3f) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001808 fprintf(stderr, "Error: Invalid Directory location.\n");
1809 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06001810 return 1;
1811 }
1812 } else {
1813 switch (dir_location) {
1814 case 0: /* Fall through */
1815 case 0xFFFA0000: /* Fall through */
1816 case 0xFFF20000: /* Fall through */
1817 case 0xFFE20000: /* Fall through */
1818 case 0xFFC20000: /* Fall through */
1819 case 0xFF820000: /* Fall through */
1820 case 0xFF020000: /* Fall through */
1821 break;
1822 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001823 fprintf(stderr, "Error: Invalid Directory location.\n");
1824 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
1825 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06001826 return 1;
1827 }
Martin Roth0d3b1182017-10-03 14:16:04 -06001828 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001829 ctx.rom = malloc(ctx.rom_size);
1830 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001831 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07001832 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07001833 }
1834 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07001835
Martin Roth0d3b1182017-10-03 14:16:04 -06001836 if (dir_location)
Marshall Dawson2794a862019-03-04 16:53:15 -07001837 romsig_offset = ctx.current = dir_location - rom_base_address;
Martin Roth0d3b1182017-10-03 14:16:04 -06001838 else
Marshall Dawson2794a862019-03-04 16:53:15 -07001839 romsig_offset = ctx.current = AMD_ROMSIG_OFFSET;
Martin Roth0d3b1182017-10-03 14:16:04 -06001840
Marshall Dawson2794a862019-03-04 16:53:15 -07001841 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07001842 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
1843 amd_romsig->imc_entry = 0;
1844 amd_romsig->gec_entry = 0;
1845 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001846
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001847 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08001848 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08001849 efs_spi_speed, efs_spi_micron_flag);
1850 if (retval) {
1851 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
1852 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001853 }
1854 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08001855 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001856 }
1857
Felix Held21a8e382022-03-29 23:10:45 +02001858 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001859 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08001860 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001861 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001862 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06001863 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001864 printf(" AMDFWTOOL Using firmware directory location of %s address: 0x%08x\n",
Robert Zieba29bc79f2022-03-14 15:59:12 -06001865 ctx.address_mode == AMD_ADDR_PHYSICAL ? "absolute" : "relative",
Zheng Bao6fff2492021-11-15 19:53:21 +08001866 RUN_CURRENT(ctx));
Zheng Baoda83d2c2021-06-04 19:03:10 +08001867
Marshall Dawson2794a862019-03-04 16:53:15 -07001868 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001869
Patrick Georgi900a2542020-02-17 16:52:40 +01001870 ctx.current = ALIGN(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08001871 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07001872
Zheng Bao481661e2021-08-20 14:47:46 +08001873 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001874 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08001875 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
1876 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001877 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001878 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
1879 /* Create a copy of PSP Directory 2 in the backup slot B.
1880 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08001881 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
1882 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001883 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08001884 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001885 /*
1886 * Either the platform is using only one slot or B is same as above
1887 * directories for A. Skip creating pspdir2_b here to save flash space.
1888 * Related biosdir2_b will be skipped automatically.
1889 */
Zheng Bao990d1542021-09-17 13:24:54 +08001890 pspdir2_b = NULL; /* More explicitly */
1891 }
Zheng Bao481661e2021-08-20 14:47:46 +08001892 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08001893 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001894 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001895 } else {
1896 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08001897 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08001898 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001899 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001900 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001901
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001902 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08001903 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07001904 else
Felix Heldad68b072021-10-18 14:00:35 +02001905 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001906
Zheng Bao993b43f2021-11-10 12:21:46 +08001907 if (cb_config.use_combo) {
1908 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
1909 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
1910 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
1911 combo_dir->entries[0].id_sel = 0;
1912 combo_dir->entries[0].id = get_psp_id(soc_id);
1913 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08001914
Zheng Bao993b43f2021-11-10 12:21:46 +08001915 combo_dir->header.lookup = 1;
1916 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
1917 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08001918
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001919 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08001920 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08001921 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001922 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08001923 bios_directory_table *biosdir2 = NULL;
1924 bios_directory_table *biosdir2_b = NULL;
1925
1926 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
1927
Zheng Baoedd1e362021-11-04 17:47:07 +08001928 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08001929 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08001930 if (cb_config.recovery_ab) {
1931 if (pspdir2_b != NULL) {
1932 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
1933 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08001934 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08001935 }
1936 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
1937 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
1938 if (pspdir2_b != NULL)
1939 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
1940 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
1941 } else {
1942 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
1943 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08001944 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08001945 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001946 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08001947 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08001948 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08001949 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08001950 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001951 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08001952 switch (soc_id) {
1953 case PLATFORM_RENOIR:
1954 case PLATFORM_LUCIENNE:
1955 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08001956 if (!cb_config.recovery_ab)
1957 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08001958 break;
Zheng Bao535ec532021-08-12 16:30:19 +08001959 case PLATFORM_MENDOCINO:
Felix Heldb18a4c72022-03-29 02:34:11 +02001960 case PLATFORM_SABRINA:
Zheng Bao535ec532021-08-12 16:30:19 +08001961 break;
Zheng Baobf29a0d2020-12-03 23:00:48 +08001962 case PLATFORM_STONEYRIDGE:
1963 case PLATFORM_RAVEN:
1964 case PLATFORM_PICASSO:
1965 default:
1966 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
1967 break;
1968 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001969 }
1970
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001971 /* Free the filename. */
1972 free_psp_firmware_filenames(amd_psp_fw_table);
1973 free_bdt_firmware_filenames(amd_bios_table);
1974
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001975 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07001976 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08001977 ssize_t bytes;
1978 bytes = write(targetfd, amd_romsig, ctx.current - romsig_offset);
1979 if (bytes != ctx.current - romsig_offset) {
1980 fprintf(stderr, "Error: Writing to file %s failed\n", output);
1981 retval = 1;
1982 }
Martin Roth31d95a22016-11-08 11:22:12 -07001983 close(targetfd);
1984 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08001985 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07001986 retval = 1;
1987 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001988
Martin Roth31d95a22016-11-08 11:22:12 -07001989 free(rom);
1990 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001991}