blob: ac25bd2087d794d13d72fbfbdc79ca4fc2d9fa49 [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
Zheng Baodd4c5422021-10-14 16:14:09 +08004 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +08009 * | PSPDIR ADDR|PSPDIR ADDR(C) | BDT ADDR 0 | BDT ADDR 1 |
10 * +------------+---------------+----------------+------------+
11 * | BDT ADDR 2 | | BDT ADDR 3(C) | |
12 * +------------+---------------+----------------+------------+
13 * (C): Could be a combo header
14 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080015 * EC ROM should be 64K aligned.
16 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080017 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080018 * +------------+---------------+----------------+------------+
19 * | 'PSP$' | Fletcher | Count | Reserved |
20 * +------------+---------------+----------------+------------+
21 * | 0 | size | Base address | Reserved | Pubkey
22 * +------------+---------------+----------------+------------+
23 * | 1 | size | Base address | Reserved | Bootloader
24 * +------------+---------------+----------------+------------+
25 * | 8 | size | Base address | Reserved | Smu Firmware
26 * +------------+---------------+----------------+------------+
27 * | 3 | size | Base address | Reserved | Recovery Firmware
28 * +------------+---------------+----------------+------------+
29 * | |
30 * | |
Zheng Baodd4c5422021-10-14 16:14:09 +080031 * | Other PSP Firmware |
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080032 * | |
33 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080034 * | 40 | size | Base address | Reserved |---+
35 * +------------+---------------+----------------+------------+ |
36 * :or 48(A/B A): size : Base address : Reserved : |
37 * + - - + - - + - - + - - + |
38 * : 4A(A/B B): size : Base address : Reserved : |
39 * +------------+---------------+----------------+------------+ |
40 * (A/B A) & (A/B B): Similar as 40, pointing to PSP level 2 |
41 * for A/B recovery |
42 * |
43 * |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
47 * | |
48 * | |
49 * | PSP Firmware |
50 * | (2nd-level is not required on all families) |
51 * | |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
Zheng Bao4fcc9f22015-11-20 12:29:04 +080054 *
zbaoc3b0b722016-02-19 13:47:31 +080055 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080056 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080057 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080058 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080059 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080061 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080062 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080063 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080064 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080069 * BDT Combo is similar
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080070 */
71
Elyes Haouas7d67a192022-10-14 09:58:29 +020072#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080073#include <fcntl.h>
74#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060075#include <limits.h>
Kangheui Won5b84dfd2021-12-21 15:45:06 +110076#include <openssl/sha.h>
Martin Roth37305e72020-04-07 14:16:39 -060077#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080078#include <stdio.h>
79#include <sys/stat.h>
80#include <sys/types.h>
81#include <unistd.h>
82#include <string.h>
83#include <stdlib.h>
84#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080085#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010086#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080087
88#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080089
Martin Roth60f15512016-11-08 09:55:01 -070090#define AMD_ROMSIG_OFFSET 0x20000
91#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092
Marshall Dawson7c1e1422019-04-11 09:44:43 -060093#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
94#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070095#define TABLE_ALIGNMENT 0x1000U
96#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060097#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060098#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080099
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600100#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
101
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100102/* Defines related to hashing signed binaries */
103enum hash_header_ver {
104 HASH_HDR_V1 = 1,
105};
106/* Signature ID enums are defined by PSP based on the algorithm used. */
107enum signature_id {
108 SIG_ID_RSA2048,
109 SIG_ID_RSA4096 = 2,
110};
111#define HASH_FILE_SUFFIX ".hash"
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -0600112#define EFS_FILE_SUFFIX ".efs"
113#define TMP_FILE_SUFFIX ".tmp"
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100114
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800115/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700116 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
117 * can support an optional "combo" implementation. If the PSP sees the
118 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
119 * tables. Using this, support for multiple product generations may be
120 * built into one image. If the PSP$ cookie is found, the table is a
121 * normal directory table.
122 *
123 * Modern generations supporting the combo directories require the
124 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
125 * regardless of the type of directory used. The --combo-capable
126 * argument enforces this placement.
127 *
128 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800129 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800130
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800131/*
132 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
133 * The checksum field of the passed PDU does not need to be reset to zero.
134 *
135 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
136 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
137 * alternative to cyclical redundancy checks because it provides error-
138 * detection properties similar to cyclical redundancy checks but at the
139 * cost of a simple summation technique. Its characteristics were first
140 * published in IEEE Transactions on Communications in January 1982. One
141 * version has been adopted by ISO for use in the class-4 transport layer
142 * of the network protocol.
143 *
144 * This program expects:
145 * stdin: The input file to compute a checksum for. The input file
146 * not be longer than 256 bytes.
147 * stdout: Copied from the input file with the Fletcher's Checksum
148 * inserted 8 bytes after the beginning of the file.
149 * stderr: Used to print out error messages.
150 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700151static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800152{
153 uint32_t c0;
154 uint32_t c1;
155 uint32_t checksum;
156 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700157 const uint16_t *pptr = data;
158
159 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800160
161 c0 = 0xFFFF;
162 c1 = 0xFFFF;
163
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600164 while (length) {
165 index = length >= 359 ? 359 : length;
166 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800167 do {
168 c0 += *(pptr++);
169 c1 += c0;
170 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600171 c0 = (c0 & 0xFFFF) + (c0 >> 16);
172 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800173 }
174
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700175 /* Sums[0,1] mod 64K + overflow */
176 c0 = (c0 & 0xFFFF) + (c0 >> 16);
177 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800178 checksum = (c1 << 16) | c0;
179
180 return checksum;
181}
182
Martin Roth8806f7f2016-11-08 10:44:18 -0700183static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800184{
Martin Roth0e940622016-11-08 10:37:53 -0700185 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800186 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
187 printf("--xhci <FILE> Add XHCI blob\n");
188 printf("--imc <FILE> Add IMC blob\n");
189 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700190
191 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800192 printf("--combo-capable Place PSP directory pointer at Embedded\n");
193 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700194 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800195 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800196 printf("--multilevel Generate primary and secondary tables\n");
197 printf("--nvram <FILE> Add nvram binary\n");
198 printf("--soft-fuse Set soft fuse\n");
199 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530200 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
201 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800202 printf("--whitelist Set if there is a whitelist\n");
203 printf("--use-pspsecureos Set if psp secure OS is needed\n");
204 printf("--load-mp2-fw Set if load MP2 firmware\n");
205 printf("--load-s0i3 Set if load s0i3 firmware\n");
206 printf("--verstage <FILE> Add verstage\n");
207 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800208 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600209 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800210 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800211 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800212 printf("--apcb <FILE> Add AGESA PSP customization block\n");
213 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
214 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
215 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
216 printf("--ucode <FILE> Add microcode patch\n");
217 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
218 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
219 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
220 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
221 printf("--output <filename> output filename\n");
222 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600223 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700224 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600225 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800226 printf("--location Location of Directory\n");
227 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
228 printf("--sharedmem Location of PSP/FW shared memory\n");
229 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800230 printf(" area\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500231 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
232 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
233 printf(" 0x0 66.66Mhz\n");
234 printf(" 0x1 33.33MHz\n");
235 printf(" 0x2 22.22MHz\n");
236 printf(" 0x3 16.66MHz\n");
237 printf(" 0x4 100MHz\n");
238 printf(" 0x5 800KHz\n");
239 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
240 printf(" 0x0 Normal Read (up to 33M)\n");
241 printf(" 0x1 Reserved\n");
242 printf(" 0x2 Dual IO (1-1-2)\n");
243 printf(" 0x3 Quad IO (1-1-4)\n");
244 printf(" 0x4 Dual IO (1-2-2)\n");
245 printf(" 0x5 Quad IO (1-4-4)\n");
246 printf(" 0x6 Normal Read (up to 66M)\n");
247 printf(" 0x7 Fast Read\n");
248 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
249 printf(" 0x0 Micron parts are not used\n");
250 printf(" 0x1 Micron parts are always used\n");
251 printf(" 0x2 Micron parts optional, this option is only\n");
252 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800253 printf("\nGeneral options:\n");
254 printf("-c|--config <config file> Config file\n");
255 printf("-d|--debug Print debug message\n");
256 printf("-l|--list List out the firmware files\n");
257 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800258}
259
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800260amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100261 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800262 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800263 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200264 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800265 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200266 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
267 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
268 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800269 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100270 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
271 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200272 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200273 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800274 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
275 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800276 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200277 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
278 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800279 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
280 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
281 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800283 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
284 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100285 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800286 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
287 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800288 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200289 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800290 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200291 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
292 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800293 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
294 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200295 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
296 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
297 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800298 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800299 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
300 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
301 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
302 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
303 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
304 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
305 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
306 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200307 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
308 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600309 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200310 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200311 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200312 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
313 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
314 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
315 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
316 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600317 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
318 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200319 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
321 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
322 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800325 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_BOTH_AB },
326 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200327 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
328 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800329 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
330 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200331 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200332 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200333 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
334 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800335 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
336 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
337 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
338 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
339 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
340 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
341 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
342 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
343 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
344 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
345 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
346 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
347 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
348 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500349 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800350 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800351};
352
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800353amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800354 { .type = AMD_FW_XHCI },
355 { .type = AMD_FW_IMC },
356 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800357 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800358};
359
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800360amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800361 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530362 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600363 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700368 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
377 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
378 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700379 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
380 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
381 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
382 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
383 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700384 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
385 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
386 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
387 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
388 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
389 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
390 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
391 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
392 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
393 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
394 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600395 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
396 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800397 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600398 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
399 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
400 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800401 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200403 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600405 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800407 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
409 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200413 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
415 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800417 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
419 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600423 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800425 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200427 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600429 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
430 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800431 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
432 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
433 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
434 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
435 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
436 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200437 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
438 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
439 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
440 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800441 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
442 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
443 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
444 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
445 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
446 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600447 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
448 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
449 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200450 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
451 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
452 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
453 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600454 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600455 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600456 { .type = AMD_BIOS_INVALID },
457};
458
Marshall Dawson2794a862019-03-04 16:53:15 -0700459typedef struct _context {
460 char *rom; /* target buffer, size of flash device */
461 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800462 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700463 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800464 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700465} context;
466
467#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800468#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600469 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
470 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
471 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800472#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600473#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800474 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700475#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800476/* The mode in entry can not be higher than the header's.
477 For example, if table mode is 0, all the entry mode will be 0. */
478#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
479 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700480#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
481#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
482#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800483#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
484 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700485#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800486/* Only set the address mode in entry if the table is mode 2. */
487#define SET_ADDR_MODE(table, mode) \
488 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600489 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800490#define SET_ADDR_MODE_BY_TABLE(table) \
491 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700492
Zheng Bao5164e4b2021-10-30 12:09:07 +0800493void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
494{
495 if (count >= max) {
496 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
497 "(%d)\n", count, max);
498 free(ctx->rom);
499 exit(1);
500 }
501}
502
Marshall Dawson24f73d42019-04-01 10:48:43 -0600503static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700504{
505 void *ptr;
506
Marshall Dawson24f73d42019-04-01 10:48:43 -0600507 /*
508 * Force both onto boundary when multi. Primary table is after
509 * updatable table, so alignment ensures primary can stay intact
510 * if secondary is reprogrammed.
511 */
512 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200513 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600514 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200515 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600516
Marshall Dawson2794a862019-03-04 16:53:15 -0700517 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800518 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800519 ((psp_directory_header *)ptr)->additional_info = 0;
520 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700521 ctx->current += sizeof(psp_directory_header)
522 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
523 return ptr;
524}
525
Zheng Baofdd47ef2021-09-17 13:30:08 +0800526static void *new_ish_dir(context *ctx)
527{
528 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200529 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800530 ptr = BUFF_CURRENT(*ctx);
531 ctx->current += TABLE_ALIGNMENT;
532 return ptr;
533}
534
Marshall Dawson2794a862019-03-04 16:53:15 -0700535static void *new_combo_dir(context *ctx)
536{
537 void *ptr;
538
Elyes Haouas7d67a192022-10-14 09:58:29 +0200539 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700540 ptr = BUFF_CURRENT(*ctx);
541 ctx->current += sizeof(psp_combo_header)
542 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
543 return ptr;
544}
545
Zheng Baobf29a0d2020-12-03 23:00:48 +0800546static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800547{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600548 psp_combo_directory *cdir = directory;
549 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600550 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800551 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600552
553 if (!count)
554 return;
Zheng Baob035f582021-05-27 11:26:12 +0800555 if (ctx == NULL || directory == NULL) {
556 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
557 return;
558 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600559
Zheng Baobf29a0d2020-12-03 23:00:48 +0800560 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200561 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800562
Marshall Dawson24f73d42019-04-01 10:48:43 -0600563 switch (cookie) {
564 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700565 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700566 cdir->header.cookie = cookie;
567 cdir->header.num_entries = count;
568 cdir->header.reserved[0] = 0;
569 cdir->header.reserved[1] = 0;
570 /* checksum everything that comes after the Checksum field */
571 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
572 count * sizeof(psp_combo_entry)
573 + sizeof(cdir->header.num_entries)
574 + sizeof(cdir->header.lookup)
575 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600576 break;
577 case PSP_COOKIE:
578 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800579 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800580 if ((table_size % TABLE_ALIGNMENT) != 0) {
581 fprintf(stderr, "The PSP table size should be 4K aligned\n");
582 exit(1);
583 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700584 dir->header.cookie = cookie;
585 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800586 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
587 dir->header.additional_info_fields.spi_block_size = 1;
588 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700589 /* checksum everything that comes after the Checksum field */
590 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700591 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700592 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800593 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600594 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800595 case BHD_COOKIE:
596 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800597 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800598 if ((table_size % TABLE_ALIGNMENT) != 0) {
599 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
600 exit(1);
601 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600602 bdir->header.cookie = cookie;
603 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800604 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
605 bdir->header.additional_info_fields.spi_block_size = 1;
606 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600607 /* checksum everything that comes after the Checksum field */
608 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
609 count * sizeof(bios_directory_entry)
610 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800611 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600612 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700613 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800614
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800615}
616
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700617static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
618{
619 int fd;
620 struct stat fd_stat;
621 ssize_t bytes;
622
623 fd = open(src_file, O_RDONLY);
624 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800625 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700626 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700627 return -1;
628 }
629
630 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800631 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600632 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700633 return -2;
634 }
635
Zheng Bao6d402ac2020-10-01 16:16:30 +0800636 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800637 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600638 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700639 return -3;
640 }
641
642 bytes = read(fd, dest, (size_t)fd_stat.st_size);
643 close(fd);
644 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800645 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700646 return -4;
647 }
648
649 return bytes;
650}
651
Kangheui Won3c164e12021-12-03 20:25:05 +1100652static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
653{
654 ssize_t bytes;
655 size_t total_bytes = 0;
656
657 do {
658 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
659 if (bytes == 0) {
660 fprintf(stderr, "Reached EOF probably\n");
661 break;
662 }
663
664 if (bytes < 0 && errno == EAGAIN)
665 bytes = 0;
666
667 if (bytes < 0) {
668 fprintf(stderr, "Read failure %s\n", strerror(errno));
669 return bytes;
670 }
671
672 total_bytes += bytes;
673 } while (total_bytes < buf_size);
674
675 if (total_bytes != buf_size) {
676 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
677 total_bytes, buf_size);
678 return -1;
679 }
680 return buf_size;
681}
682
683static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
684{
685 ssize_t bytes;
686 size_t total_bytes = 0;
687
688 do {
689 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
690 if (bytes < 0 && errno == EAGAIN)
691 bytes = 0;
692
693 if (bytes < 0) {
694 fprintf(stderr, "Write failure %s\n", strerror(errno));
695 lseek(fd, SEEK_CUR, -total_bytes);
696 return bytes;
697 }
698
699 total_bytes += bytes;
700 } while (total_bytes < buf_size);
701
702 if (total_bytes != buf_size) {
703 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
704 total_bytes, buf_size);
705 lseek(fd, SEEK_CUR, -total_bytes);
706 return -1;
707 }
708
709 return buf_size;
710}
711
Zheng Baoeb0404e2021-10-14 15:09:09 +0800712static uint32_t get_psp_id(enum platform soc_id)
713{
714 uint32_t psp_id;
715 switch (soc_id) {
716 case PLATFORM_RAVEN:
717 case PLATFORM_PICASSO:
718 psp_id = 0xBC0A0000;
719 break;
720 case PLATFORM_RENOIR:
721 case PLATFORM_LUCIENNE:
722 psp_id = 0xBC0C0000;
723 break;
724 case PLATFORM_CEZANNE:
725 psp_id = 0xBC0C0140;
726 break;
727 case PLATFORM_MENDOCINO:
728 psp_id = 0xBC0D0900;
729 break;
730 case PLATFORM_STONEYRIDGE:
731 psp_id = 0x10220B00;
732 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800733 case PLATFORM_GLINDA:
734 psp_id = 0xBC0E0200;
735 break;
736 case PLATFORM_PHOENIX:
737 psp_id = 0xBC0D0400;
738 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800739 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800740 default:
741 psp_id = 0;
742 break;
743 }
744 return psp_id;
745}
746
Kangheui Won3c164e12021-12-03 20:25:05 +1100747static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
748{
749 switch (soc_id) {
750 case PLATFORM_MENDOCINO:
Zheng Bao4044e852023-02-02 09:26:20 +0800751 case PLATFORM_PHOENIX:
752 case PLATFORM_GLINDA:
Kangheui Won3c164e12021-12-03 20:25:05 +1100753 /* Fallback to fw_type if fw_id is not populated, which serves the same
754 purpose on older SoCs. */
755 return header->fw_id ? header->fw_id : header->fw_type;
756 default:
757 return header->fw_type;
758 }
759}
760
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100761static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
762{
763 uint8_t hash[SHA384_DIGEST_LENGTH];
764 struct amd_fw_header *header = (struct amd_fw_header *)buf;
765 /* Include only signed part for hash calculation. */
766 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
767 uint8_t *body = (uint8_t *)buf;
768
769 if (len > header->size_total)
770 return -1;
771
772 if (header->sig_id == SIG_ID_RSA4096) {
773 SHA384(body, len, hash);
774 entry->sha_len = SHA384_DIGEST_LENGTH;
775 } else if (header->sig_id == SIG_ID_RSA2048) {
776 SHA256(body, len, hash);
777 entry->sha_len = SHA256_DIGEST_LENGTH;
778 } else {
779 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
780 __func__, header->sig_id);
781 return -1;
782 }
783
784 memcpy(entry->sha, hash, entry->sha_len);
785 entry->fw_id = get_psp_fw_type(soc_id, header);
786 entry->subtype = header->fw_subtype;
787
788 return 0;
789}
790
791static int get_num_binaries(void *buf, size_t buf_size)
792{
793 struct amd_fw_header *header = (struct amd_fw_header *)buf;
794 size_t total_len = 0;
795 int num_binaries = 0;
796
797 while (total_len < buf_size) {
798 num_binaries++;
799 total_len += header->size_total;
800 header = (struct amd_fw_header *)(buf + total_len);
801 }
802
803 if (total_len != buf_size) {
804 fprintf(stderr, "Malformed binary\n");
805 return -1;
806 }
807 return num_binaries;
808}
809
810static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
811{
812 struct amd_fw_header *header = (struct amd_fw_header *)buf;
813 /* Include only signed part for hash calculation. */
814 size_t total_len = 0;
815 int num_binaries = get_num_binaries(buf, buf_size);
816
817 if (num_binaries <= 0)
818 return num_binaries;
819
820 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
821 if (!entry->hash_entries) {
822 fprintf(stderr, "Error allocating memory to add FW hash\n");
823 return -1;
824 }
825 entry->num_hash_entries = num_binaries;
826
827 /* Iterate through each binary */
828 for (int i = 0; i < num_binaries; i++) {
829 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
830 free(entry->hash_entries);
831 return -1;
832 }
833 total_len += header->size_total;
834 header = (struct amd_fw_header *)(buf + total_len);
835 }
836
837 return 0;
838}
839
Marshall Dawson2794a862019-03-04 16:53:15 -0700840static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700841 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700842 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800843{
Richard Spiegel137484d2018-01-17 10:23:19 -0700844 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800845 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700846
Elyes Haouas7d67a192022-10-14 09:58:29 +0200847 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800848
Martin Rothcd15bc82016-11-08 11:34:02 -0700849 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800850 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800851 switch (fw_table[i].type) {
852 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200853 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700854 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800855 break;
856 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700857 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800858 break;
859 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700860 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800861 break;
862 default:
863 /* Error */
864 break;
865 }
866
Marshall Dawson2794a862019-03-04 16:53:15 -0700867 bytes = copy_blob(BUFF_CURRENT(*ctx),
868 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600869 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700870 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700871 exit(1);
872 }
873
Elyes Haouas7d67a192022-10-14 09:58:29 +0200874 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700875 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800876 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800877 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800878}
879
Zheng Bao9e908072020-10-28 11:39:13 +0800880/* For debugging */
881static void dump_psp_firmwares(amd_fw_entry *fw_table)
882{
883 amd_fw_entry *index;
884
885 printf("PSP firmware components:");
886 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
887 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800888 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800889 }
890}
891
892static void dump_bdt_firmwares(amd_bios_entry *fw_table)
893{
894 amd_bios_entry *index;
895
896 printf("BIOS Directory Table (BDT) components:");
897 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
898 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800899 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800900 }
901}
902
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800903static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
904{
905 amd_fw_entry *index;
906
907 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
908 if (index->filename &&
909 index->type != AMD_FW_VERSTAGE_SIG &&
910 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800911 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800912 index->type != AMD_FW_PSP_WHITELIST) {
913 free(index->filename);
914 }
915 }
916}
917
918static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
919{
920 amd_bios_entry *index;
921
922 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
923 if (index->filename &&
924 index->type != AMD_BIOS_APCB &&
925 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200926 index->type != AMD_BIOS_APCB_BK &&
927 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800928 free(index->filename);
929 }
930}
931
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100932static void write_or_fail(int fd, void *ptr, size_t size)
933{
934 ssize_t written;
935
936 written = write_from_buf_to_file(fd, ptr, size);
937 if (written < 0 || (size_t)written != size) {
938 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
939 __func__, size, written);
940 exit(-1);
941 }
942}
943
944static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
945{
946 uint16_t type = entry->fw_id;
947 uint16_t subtype = entry->subtype;
948
949 write_or_fail(fd, &type, sizeof(type));
950 write_or_fail(fd, &subtype, sizeof(subtype));
951 write_or_fail(fd, entry->sha, entry->sha_len);
952}
953
954static void write_psp_firmware_hash(const char *filename,
955 amd_fw_entry *fw_table)
956{
957 struct psp_fw_hash_table hash_header = {0};
958 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
959
960 if (fd < 0) {
961 fprintf(stderr, "Error opening file: %s: %s\n",
962 filename, strerror(errno));
963 exit(-1);
964 }
965
966 hash_header.version = HASH_HDR_V1;
967 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
968 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
969 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
970 hash_header.no_of_entries_256++;
971 } else if (fw_table[i].hash_entries[j].sha_len ==
972 SHA384_DIGEST_LENGTH) {
973 hash_header.no_of_entries_384++;
974 } else if (fw_table[i].hash_entries[j].sha_len) {
975 fprintf(stderr, "%s: Error invalid sha_len %d\n",
976 __func__, fw_table[i].hash_entries[j].sha_len);
977 exit(-1);
978 }
979 }
980 }
981
982 write_or_fail(fd, &hash_header, sizeof(hash_header));
983
984 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
985 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
986 will cause the hash verification failure at run-time. */
987 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
988 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
989 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
990 write_one_psp_firmware_hash_entry(fd,
991 &fw_table[i].hash_entries[j]);
992 }
993 }
994
995 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
996 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
997 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
998 write_one_psp_firmware_hash_entry(fd,
999 &fw_table[i].hash_entries[j]);
1000 }
1001 }
1002
1003 close(fd);
1004 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1005 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
1006 continue;
1007
1008 free(fw_table[i].hash_entries);
1009 fw_table[i].hash_entries = NULL;
1010 fw_table[i].num_hash_entries = 0;
1011 }
1012}
1013
Kangheui Won3c164e12021-12-03 20:25:05 +11001014/**
1015 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
1016 * @signed_rom: Output file path grouping all the signed PSP binaries.
1017 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
1018 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
1019 * the signed PSP binaries.
1020 * @soc_id: SoC ID of the PSP binaries.
1021 */
1022static void process_signed_psp_firmwares(const char *signed_rom,
1023 amd_fw_entry *fw_table,
1024 uint64_t signed_start_addr,
1025 enum platform soc_id)
1026{
1027 unsigned int i;
1028 int fd;
1029 int signed_rom_fd;
1030 ssize_t bytes, align_bytes;
1031 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001032 char *signed_rom_hash;
1033 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +11001034 struct amd_fw_header header;
1035 struct stat fd_stat;
1036 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
1037 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
1038 uint8_t align_data[BLOB_ALIGNMENT - 1];
1039
1040 memset(align_data, 0xff, sizeof(align_data));
1041 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
1042 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1043 if (signed_rom_fd < 0) {
1044 fprintf(stderr, "Error opening file: %s: %s\n",
1045 signed_rom, strerror(errno));
1046 return;
1047 }
1048
1049 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001050 fw_table[i].num_hash_entries = 0;
1051 fw_table[i].hash_entries = NULL;
1052
Kangheui Won3c164e12021-12-03 20:25:05 +11001053 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
1054 continue;
1055
1056 memset(&header, 0, sizeof(header));
1057
1058 fd = open(fw_table[i].filename, O_RDONLY);
1059 if (fd < 0) {
1060 /* Keep the file along with set of unsigned PSP binaries & continue. */
1061 fprintf(stderr, "Error opening file: %s: %s\n",
1062 fw_table[i].filename, strerror(errno));
1063 continue;
1064 }
1065
1066 if (fstat(fd, &fd_stat)) {
1067 /* Keep the file along with set of unsigned PSP binaries & continue. */
1068 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1069 close(fd);
1070 continue;
1071 }
1072
1073 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1074 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1075 /* Keep the file along with set of unsigned PSP binaries & continue. */
1076 fprintf(stderr, "%s: Error reading header from %s\n",
1077 __func__, fw_table[i].filename);
1078 close(fd);
1079 continue;
1080 }
1081
1082 /* If firmware header looks like invalid, assume it's not signed */
1083 if (!header.fw_type && !header.fw_id) {
1084 fprintf(stderr, "%s: Invalid FWID for %s\n",
1085 __func__, fw_table[i].filename);
1086 close(fd);
1087 continue;
1088 }
1089
Kangheui Won3c164e12021-12-03 20:25:05 +11001090
1091 /* PSP binary is not signed and should not be part of signed PSP binaries
1092 set. */
1093 if (header.sig_opt != 1) {
1094 close(fd);
1095 continue;
1096 }
1097
1098 buf = malloc(fd_stat.st_size);
1099 if (!buf) {
1100 /* Keep the file along with set of unsigned PSP binaries & continue. */
1101 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1102 __func__, (long long)fd_stat.st_size);
1103 close(fd);
1104 continue;
1105 }
1106
1107 lseek(fd, SEEK_SET, 0);
1108 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1109 if (bytes != fd_stat.st_size) {
1110 /* Keep the file along with set of unsigned PSP binaries & continue. */
1111 fprintf(stderr, "%s: failed to read %s\n",
1112 __func__, fw_table[i].filename);
1113 free(buf);
1114 close(fd);
1115 continue;
1116 }
1117
1118 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1119 if (bytes != fd_stat.st_size) {
1120 /* Keep the file along with set of unsigned PSP binaries & continue. */
1121 fprintf(stderr, "%s: failed to write %s\n",
1122 __func__, fw_table[i].filename);
1123 free(buf);
1124 close(fd);
1125 continue;
1126 }
1127
1128 /* Write Blob alignment bytes */
1129 align_bytes = 0;
1130 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1131 align_bytes = BLOB_ALIGNMENT -
1132 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1133 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1134 if (bytes != align_bytes) {
1135 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1136 __func__, fw_table[i].filename);
1137 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1138 free(buf);
1139 close(fd);
1140 continue;
1141 }
1142 }
1143
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001144 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1145 exit(-1);
1146
Kangheui Won3c164e12021-12-03 20:25:05 +11001147 /* File is successfully processed and is part of signed PSP binaries set. */
1148 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1149 fw_table[i].addr_signed = signed_start_addr;
1150 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1151
1152 signed_start_addr += fd_stat.st_size + align_bytes;
1153
1154 free(buf);
1155 close(fd);
1156 }
1157
1158 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001159
1160 /* signed_rom file name + ".hash" + '\0' */
1161 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1162 signed_rom_hash = malloc(signed_rom_hash_strlen);
1163 if (!signed_rom_hash) {
1164 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1165 exit(-1);
1166 }
1167 strcpy(signed_rom_hash, signed_rom);
1168 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1169 write_psp_firmware_hash(signed_rom_hash, fw_table);
1170 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001171}
1172
Zheng Bao990d1542021-09-17 13:24:54 +08001173static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001174 psp_directory_table *pspdir2, ish_directory_table *ish,
1175 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001176{
1177 uint32_t count;
1178 uint32_t current_table_save;
1179
1180 current_table_save = ctx->current_table;
1181 ctx->current_table = (char *)pspdir - ctx->rom;
1182 count = pspdir->header.num_entries;
1183 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1184 pspdir->entries[count].type = (uint8_t)ab;
1185 pspdir->entries[count].subprog = 0;
1186 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001187 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001188 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001189 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1190 ish->update_retry_count = 2;
1191 ish->glitch_retry_count = 0;
1192 ish->psp_id = get_psp_id(soc_id);
1193 ish->checksum = fletcher32(&ish->boot_priority,
1194 sizeof(ish_directory_table) - sizeof(uint32_t));
1195 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001196 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001197 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001198 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001199 pspdir->entries[count].size = TABLE_ALIGNMENT;
1200 } else {
1201 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001202 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001203 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001204 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001205 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001206 sizeof(psp_directory_entry) +
1207 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001208 }
Zheng Bao990d1542021-09-17 13:24:54 +08001209
1210 count++;
1211 pspdir->header.num_entries = count;
1212 ctx->current_table = current_table_save;
1213}
1214
Marshall Dawson2794a862019-03-04 16:53:15 -07001215static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001216 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001217 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001218 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001219 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001220 uint32_t cookie,
1221 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001222{
Richard Spiegel137484d2018-01-17 10:23:19 -07001223 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001224 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001225 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301226 uint32_t size;
1227 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001228 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001229 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001230 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001231
1232 /* This function can create a primary table, a secondary table, or a
1233 * flattened table which contains all applicable types. These if-else
1234 * statements infer what the caller intended. If a 2nd-level cookie
1235 * is passed, clearly a 2nd-level table is intended. However, a
1236 * 1st-level cookie may indicate level 1 or flattened. If the caller
1237 * passes a pointer to a 2nd-level table, then assume not flat.
1238 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001239 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001240 level = PSP_BOTH;
1241 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001242 level = PSP_LVL2;
1243 else if (pspdir2)
1244 level = PSP_LVL1;
1245 else
1246 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001247
Zheng Bao990d1542021-09-17 13:24:54 +08001248 if (recovery_ab) {
1249 if (cookie == PSPL2_COOKIE)
1250 level = PSP_LVL2_AB;
1251 else if (pspdir2)
1252 level = PSP_LVL1_AB;
1253 else
1254 level = PSP_BOTH_AB;
1255 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001256 current_table_save = ctx->current_table;
1257 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001258 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001259
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001260 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001261 if (!(fw_table[i].level & level))
1262 continue;
1263
Zheng Bao5164e4b2021-10-30 12:09:07 +08001264 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1265
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001266 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1267 if (!fw_table[i].other)
1268 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001269 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001270 pspdir->entries[count].type = fw_table[i].type;
1271 pspdir->entries[count].size = 4096; /* TODO: doc? */
1272 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001273 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001274 pspdir->entries[count].subprog = fw_table[i].subprog;
1275 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001276 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001277 count++;
1278 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001279 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001280 pspdir->entries[count].subprog = fw_table[i].subprog;
1281 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001282 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001283 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001284 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001285 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001286 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301287 if (fw_table[i].filename == NULL) {
1288 if (fw_table[i].size == 0)
1289 continue;
1290 size = fw_table[i].size;
1291 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001292 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301293 fprintf(stderr,
1294 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1295 exit(1);
1296 }
1297 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001298 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301299 bytes = copy_blob(BUFF_CURRENT(*ctx),
1300 fw_table[i].filename, BUFF_ROOM(*ctx));
1301 if (bytes <= 0) {
1302 free(ctx->rom);
1303 exit(1);
1304 }
1305
Elyes Haouas7d67a192022-10-14 09:58:29 +02001306 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301307 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001308 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301309 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001310 }
1311
1312 pspdir->entries[count].type = fw_table[i].type;
1313 pspdir->entries[count].subprog = fw_table[i].subprog;
1314 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301315 pspdir->entries[count].size = size;
1316 pspdir->entries[count].addr = addr;
1317
Zheng Bao6fff2492021-11-15 19:53:21 +08001318 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001319 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001320
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001321 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001322 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001323 if (fw_table[i].addr_signed) {
1324 pspdir->entries[count].addr =
1325 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1326 pspdir->entries[count].address_mode =
1327 SET_ADDR_MODE_BY_TABLE(pspdir);
1328 bytes = fw_table[i].file_size;
1329 } else {
1330 bytes = copy_blob(BUFF_CURRENT(*ctx),
1331 fw_table[i].filename, BUFF_ROOM(*ctx));
1332 if (bytes < 0) {
1333 free(ctx->rom);
1334 exit(1);
1335 }
1336 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1337 pspdir->entries[count].address_mode =
1338 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001339 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001340 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001341 }
1342
Marshall Dawson239286c2019-02-23 16:42:46 -07001343 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001344 pspdir->entries[count].subprog = fw_table[i].subprog;
1345 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001346 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001347
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001348 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001349 } else {
1350 /* This APU doesn't have this firmware. */
1351 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001352 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001353
Zheng Bao990d1542021-09-17 13:24:54 +08001354 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001355 if (cb_config->need_ish) { /* Need ISH */
1356 ish_a_dir = new_ish_dir(ctx);
1357 if (pspdir2_b != NULL)
1358 ish_b_dir = new_ish_dir(ctx);
1359 }
Zheng Bao990d1542021-09-17 13:24:54 +08001360 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001361 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001362 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001363 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001364 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001365 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001366 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001367 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001368 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001369
Zheng Bao990d1542021-09-17 13:24:54 +08001370 count = pspdir->header.num_entries;
1371 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001372 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001373 pspdir->entries[count].type = AMD_FW_L2_PTR;
1374 pspdir->entries[count].subprog = 0;
1375 pspdir->entries[count].rsvd = 0;
1376 pspdir->entries[count].size = sizeof(pspdir2->header)
1377 + pspdir2->header.num_entries
1378 * sizeof(psp_directory_entry);
1379
Zheng Bao6fff2492021-11-15 19:53:21 +08001380 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001381 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001382 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001383 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001384 count++;
1385 }
1386
Zheng Baobf29a0d2020-12-03 23:00:48 +08001387 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001388 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001389}
1390
Zheng Bao990d1542021-09-17 13:24:54 +08001391static void add_psp_firmware_entry(context *ctx,
1392 psp_directory_table *pspdir,
1393 void *table, amd_fw_type type, uint32_t size)
1394{
1395 uint32_t count = pspdir->header.num_entries;
1396 uint32_t index;
1397 uint32_t current_table_save;
1398
1399 current_table_save = ctx->current_table;
1400 ctx->current_table = (char *)pspdir - ctx->rom;
1401
1402 /* If there is an entry of "type", replace it. */
1403 for (index = 0; index < count; index++) {
1404 if (pspdir->entries[index].type == (uint8_t)type)
1405 break;
1406 }
1407
1408 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1409 pspdir->entries[index].type = (uint8_t)type;
1410 pspdir->entries[index].subprog = 0;
1411 pspdir->entries[index].rsvd = 0;
1412 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1413 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1414 pspdir->entries[index].size = size;
1415 if (index == count)
1416 count++;
1417
1418 pspdir->header.num_entries = count;
1419 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1420 count * sizeof(psp_directory_entry)
1421 + sizeof(pspdir->header.num_entries)
1422 + sizeof(pspdir->header.additional_info));
1423
1424 ctx->current_table = current_table_save;
1425}
1426
Zheng Baoba3af5e2021-11-04 18:56:47 +08001427static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001428{
1429 void *ptr;
1430
1431 /*
1432 * Force both onto boundary when multi. Primary table is after
1433 * updatable table, so alignment ensures primary can stay intact
1434 * if secondary is reprogrammed.
1435 */
1436 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001437 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001438 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001439 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001440 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001441 ((bios_directory_hdr *) ptr)->additional_info = 0;
1442 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1443 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001444 ctx->current += sizeof(bios_directory_hdr)
1445 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1446 return ptr;
1447}
1448
1449static int locate_bdt2_bios(bios_directory_table *level2,
1450 uint64_t *source, uint32_t *size)
1451{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001452 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001453
1454 *source = 0;
1455 *size = 0;
1456 if (!level2)
1457 return 0;
1458
1459 for (i = 0 ; i < level2->header.num_entries ; i++) {
1460 if (level2->entries[i].type == AMD_BIOS_BIN) {
1461 *source = level2->entries[i].source;
1462 *size = level2->entries[i].size;
1463 return 1;
1464 }
1465 }
1466 return 0;
1467}
1468
1469static int have_bios_tables(amd_bios_entry *table)
1470{
1471 int i;
1472
1473 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1474 if (table[i].level & BDT_LVL1 && table[i].filename)
1475 return 1;
1476 }
1477 return 0;
1478}
1479
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001480static int find_bios_entry(amd_bios_type type)
1481{
1482 int i;
1483
1484 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1485 if (amd_bios_table[i].type == type)
1486 return i;
1487 }
1488 return -1;
1489}
1490
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001491static void integrate_bios_firmwares(context *ctx,
1492 bios_directory_table *biosdir,
1493 bios_directory_table *biosdir2,
1494 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001495 uint32_t cookie,
1496 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001497{
1498 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001499 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001500 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001501 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001502 uint32_t size;
1503 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001504
1505 /* This function can create a primary table, a secondary table, or a
1506 * flattened table which contains all applicable types. These if-else
1507 * statements infer what the caller intended. If a 2nd-level cookie
1508 * is passed, clearly a 2nd-level table is intended. However, a
1509 * 1st-level cookie may indicate level 1 or flattened. If the caller
1510 * passes a pointer to a 2nd-level table, then assume not flat.
1511 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001512 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001513 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001514 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001515 level = BDT_LVL2;
1516 else if (biosdir2)
1517 level = BDT_LVL1;
1518 else
1519 level = BDT_BOTH;
1520
Elyes Haouas7d67a192022-10-14 09:58:29 +02001521 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001522
1523 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1524 if (!(fw_table[i].level & level))
1525 continue;
1526 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301527 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001528 fw_table[i].type != AMD_BIOS_APOB &&
1529 fw_table[i].type != AMD_BIOS_APOB_NV &&
1530 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001531 fw_table[i].type != AMD_BIOS_BIN &&
1532 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001533 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001534
1535 /* BIOS Directory items may have additional requirements */
1536
Ritul Guru9a321f32022-07-29 11:06:40 +05301537 /* SIG needs a size, else no choice but to skip */
1538 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1539 continue;
1540
Martin Roth48dd9fe2020-07-29 16:32:25 -06001541 /* Check APOB_NV requirements */
1542 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1543 if (!fw_table[i].size && !fw_table[i].src)
1544 continue; /* APOB_NV not used */
1545 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001546 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001547 free(ctx->rom);
1548 exit(1);
1549 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001550 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001551 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001552 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1553 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001554 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001555
1556 /* APOB_DATA needs destination */
1557 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001558 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001559 free(ctx->rom);
1560 exit(1);
1561 }
1562
1563 /* BIOS binary must have destination and uncompressed size. If
1564 * no filename given, then user must provide a source address.
1565 */
1566 if (fw_table[i].type == AMD_BIOS_BIN) {
1567 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001568 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001569 free(ctx->rom);
1570 exit(1);
1571 }
1572 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001573 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001574 free(ctx->rom);
1575 exit(1);
1576 }
1577 }
1578
Martin Roth94554742020-04-14 14:59:36 -06001579 /* PSP_SHARED_MEM needs a destination and size */
1580 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1581 (!fw_table[i].dest || !fw_table[i].size))
1582 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001583 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001584
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001585 biosdir->entries[count].type = fw_table[i].type;
1586 biosdir->entries[count].region_type = fw_table[i].region_type;
1587 biosdir->entries[count].dest = fw_table[i].dest ?
1588 fw_table[i].dest : (uint64_t)-1;
1589 biosdir->entries[count].reset = fw_table[i].reset;
1590 biosdir->entries[count].copy = fw_table[i].copy;
1591 biosdir->entries[count].ro = fw_table[i].ro;
1592 biosdir->entries[count].compressed = fw_table[i].zlib;
1593 biosdir->entries[count].inst = fw_table[i].inst;
1594 biosdir->entries[count].subprog = fw_table[i].subpr;
1595
1596 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301597 case AMD_BIOS_SIG:
1598 /* Reserve size bytes within amdfw.rom */
1599 biosdir->entries[count].size = fw_table[i].size;
1600 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1601 biosdir->entries[count].address_mode =
1602 SET_ADDR_MODE_BY_TABLE(biosdir);
1603 memset(BUFF_CURRENT(*ctx), 0xff,
1604 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001605 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301606 + biosdir->entries[count].size, 0x100U);
1607 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001608 case AMD_BIOS_APOB:
1609 biosdir->entries[count].size = fw_table[i].size;
1610 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001611 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001612 break;
1613 case AMD_BIOS_APOB_NV:
1614 if (fw_table[i].src) {
1615 /* If source is given, use that and its size */
1616 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001617 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001618 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001619 biosdir->entries[count].size = fw_table[i].size;
1620 } else {
1621 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001622 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001623 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001624 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001625 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001626 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001627 fw_table[i].size, ERASE_ALIGNMENT);
1628 memset(BUFF_CURRENT(*ctx), 0xff,
1629 biosdir->entries[count].size);
1630 ctx->current = ctx->current
1631 + biosdir->entries[count].size;
1632 }
1633 break;
1634 case AMD_BIOS_BIN:
1635 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001636 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1637 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001638 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001639 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001640 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001641 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001642 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001643
1644 /* level 2, or level 1 and no copy found in level 2 */
1645 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001646 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001647 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001648 biosdir->entries[count].dest = fw_table[i].dest;
1649 biosdir->entries[count].size = fw_table[i].size;
1650
1651 if (!fw_table[i].filename)
1652 break;
1653
1654 bytes = copy_blob(BUFF_CURRENT(*ctx),
1655 fw_table[i].filename, BUFF_ROOM(*ctx));
1656 if (bytes <= 0) {
1657 free(ctx->rom);
1658 exit(1);
1659 }
1660
Zheng Bao6fff2492021-11-15 19:53:21 +08001661 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001662 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001663 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001664 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001665
Elyes Haouas7d67a192022-10-14 09:58:29 +02001666 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001667 break;
Martin Roth94554742020-04-14 14:59:36 -06001668 case AMD_BIOS_PSP_SHARED_MEM:
1669 biosdir->entries[count].dest = fw_table[i].dest;
1670 biosdir->entries[count].size = fw_table[i].size;
1671 break;
1672
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001673 default: /* everything else is copied from input */
1674 if (fw_table[i].type == AMD_BIOS_APCB ||
1675 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001676 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001677 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001678 bytes = copy_blob(BUFF_CURRENT(*ctx),
1679 fw_table[i].filename, BUFF_ROOM(*ctx));
1680 if (bytes <= 0) {
1681 free(ctx->rom);
1682 exit(1);
1683 }
1684
1685 biosdir->entries[count].size = (uint32_t)bytes;
1686 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001687 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001688
Elyes Haouas7d67a192022-10-14 09:58:29 +02001689 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001690 break;
1691 }
1692
1693 count++;
1694 }
1695
1696 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001697 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001698 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001699 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001700 biosdir->entries[count].size =
1701 + MAX_BIOS_ENTRIES
1702 * sizeof(bios_directory_entry);
1703 biosdir->entries[count].source =
1704 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001705 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001706 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001707 biosdir->entries[count].subprog = 0;
1708 biosdir->entries[count].inst = 0;
1709 biosdir->entries[count].copy = 0;
1710 biosdir->entries[count].compressed = 0;
1711 biosdir->entries[count].dest = -1;
1712 biosdir->entries[count].reset = 0;
1713 biosdir->entries[count].ro = 0;
1714 count++;
1715 }
1716
Zheng Baobf29a0d2020-12-03 23:00:48 +08001717 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001718}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001719
1720enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001721 AMDFW_OPT_CONFIG = 'c',
1722 AMDFW_OPT_DEBUG = 'd',
1723 AMDFW_OPT_HELP = 'h',
1724 AMDFW_OPT_LIST_DEPEND = 'l',
1725
1726 AMDFW_OPT_XHCI = 128,
1727 AMDFW_OPT_IMC,
1728 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001729 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001730 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001731 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001732 AMDFW_OPT_MULTILEVEL,
1733 AMDFW_OPT_NVRAM,
1734
1735 AMDFW_OPT_FUSE,
1736 AMDFW_OPT_UNLOCK,
1737 AMDFW_OPT_WHITELIST,
1738 AMDFW_OPT_USE_PSPSECUREOS,
1739 AMDFW_OPT_LOAD_MP2FW,
1740 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001741 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001742 AMDFW_OPT_VERSTAGE,
1743 AMDFW_OPT_VERSTAGE_SIG,
1744
1745 AMDFW_OPT_INSTANCE,
1746 AMDFW_OPT_APCB,
1747 AMDFW_OPT_APOBBASE,
1748 AMDFW_OPT_BIOSBIN,
1749 AMDFW_OPT_BIOSBIN_SOURCE,
1750 AMDFW_OPT_BIOSBIN_DEST,
1751 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1752 AMDFW_OPT_UCODE,
1753 AMDFW_OPT_APOB_NVBASE,
1754 AMDFW_OPT_APOB_NVSIZE,
1755
1756 AMDFW_OPT_OUTPUT,
1757 AMDFW_OPT_FLASHSIZE,
1758 AMDFW_OPT_LOCATION,
1759 AMDFW_OPT_ANYWHERE,
1760 AMDFW_OPT_SHAREDMEM,
1761 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001762 AMDFW_OPT_SIGNED_OUTPUT,
1763 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001764 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001765 /* begin after ASCII characters */
1766 LONGOPT_SPI_READ_MODE = 256,
1767 LONGOPT_SPI_SPEED = 257,
1768 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301769 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301770 LONGOPT_NVRAM_BASE = 260,
1771 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001772};
1773
Zheng Bao806892a2021-04-27 17:21:54 +08001774static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1775 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1776};
Marc Jones90099b62016-09-20 21:05:45 -06001777
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001778static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001779 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1780 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1781 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001782 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001783 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001784 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001785 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001786 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1787 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301788 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1789 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001790 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1791 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1792 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1793 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1794 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1795 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001796 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001797 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1798 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001799 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001800 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1801 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1802 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1803 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1804 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1805 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1806 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301807 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001808 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1809 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1810 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001811 /* Embedded Firmware Structure items*/
1812 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1813 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1814 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001815 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001816 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001817 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1818 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1819 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1820 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1821 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1822 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001823
Kangheui Won3c164e12021-12-03 20:25:05 +11001824 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1825 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1826
Zheng Bao806892a2021-04-27 17:21:54 +08001827 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1828 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1829 {"help", no_argument, 0, AMDFW_OPT_HELP },
1830 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001831 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001832};
1833
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001834void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001835{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001836 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001837
1838 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1839 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1840 continue;
1841
1842 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1843 return;
1844 }
1845}
1846
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001847static void register_fw_token_unlock(void)
1848{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001849 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001850
1851 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1852 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1853 continue;
1854
1855 amd_psp_fw_table[i].other = 1;
1856 return;
1857 }
1858}
1859
Marshall Dawsondbae6322019-03-04 10:31:03 -07001860static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001861{
Martin Roth8806f7f2016-11-08 10:44:18 -07001862 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001863
Martin Rothcd15bc82016-11-08 11:34:02 -07001864 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001865 if (amd_fw_table[i].type == type) {
1866 amd_fw_table[i].filename = filename;
1867 return;
1868 }
1869 }
1870
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001871 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001872 if (amd_psp_fw_table[i].type != type)
1873 continue;
1874
1875 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001876 amd_psp_fw_table[i].filename = filename;
1877 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001878 }
1879 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001880}
1881
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001882static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1883{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001884 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001885
1886 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1887 if (amd_bios_table[i].type == type
1888 && amd_bios_table[i].inst == ins
1889 && amd_bios_table[i].subpr == sub) {
1890 amd_bios_table[i].filename = name;
1891 return;
1892 }
1893 }
1894}
1895
Ritul Gurua2cb3402022-08-29 00:51:08 +05301896static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1897 char *dst_str, char *size_str)
1898{
1899 unsigned int i;
1900
1901 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1902 if (amd_psp_fw_table[i].type != type)
1903 continue;
1904
1905 if (amd_psp_fw_table[i].subprog == sub) {
1906 if (dst_str)
1907 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1908 if (size_str)
1909 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1910 return;
1911 }
1912 }
1913}
1914
1915static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001916 char *dst_str, char *size_str)
1917{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001918 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001919 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1920 if (amd_bios_table[i].type != type)
1921 continue;
1922
1923 if (src_str)
1924 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1925 if (dst_str)
1926 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1927 if (size_str)
1928 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1929
1930 return;
1931 }
1932}
1933
Zheng Baoc3007f32022-04-03 12:53:51 +08001934static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1935 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1936 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001937{
1938 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001939 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001940 return 1;
1941 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001942
1943 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1944 * Leave as 0xffffffff for first gen */
1945 if (cb_config->second_gen) {
1946 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1947 amd_romsig->efs_gen.reserved = 0;
1948 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001949 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1950 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001951 }
1952
1953 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001954 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001955 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001956 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1957 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1958 break;
1959 case PLATFORM_RAVEN:
1960 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001961 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1962 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1963 switch (efs_spi_micron_flag) {
1964 case 0:
1965 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1966 break;
1967 case 1:
1968 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1969 break;
1970 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001971 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001972 return 1;
1973 }
1974 break;
1975 case PLATFORM_RENOIR:
1976 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001977 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001978 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001979 case PLATFORM_PHOENIX:
1980 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001981 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1982 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1983 switch (efs_spi_micron_flag) {
1984 case 0:
1985 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1986 break;
1987 case 1:
1988 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1989 break;
1990 case 2:
1991 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1992 break;
1993 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001994 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001995 return 1;
1996 }
1997 break;
1998 case PLATFORM_UNKNOWN:
1999 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002000 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002001 return 1;
2002 }
2003 return 0;
2004}
2005
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002006static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
2007{
2008 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
2009 int ret;
2010 int fd;
2011 ssize_t bytes = -1;
2012
2013 /* Create a tmp file and rename it at the end so that make does not get confused
2014 if amdfwtool is killed for some unexpected reasons. */
2015 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
2016 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
2017 if (ret < 0) {
2018 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
2019 strerror(errno), ret);
2020 exit(1);
2021 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
2022 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
2023 exit(1);
2024 }
2025
2026 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
2027 if (fd < 0) {
2028 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
2029 exit(1);
2030 }
2031
2032 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
2033 if (bytes != sizeof(*amd_romsig)) {
2034 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
2035 exit(1);
2036 }
2037 close(fd);
2038
2039 /* Rename the tmp file */
2040 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
2041 if (ret < 0) {
2042 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
2043 exit(1);
2044 }
2045
2046 if (rename(efs_tmp_name, efs_name)) {
2047 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
2048 exit(1);
2049 }
2050
2051 return bytes;
2052}
2053
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002054int main(int argc, char **argv)
2055{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002056 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002057 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002058 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002059 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002060 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002061 psp_directory_table *pspdir = NULL;
2062 psp_directory_table *pspdir2 = NULL;
2063 psp_directory_table *pspdir2_b = NULL;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002064 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002065 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002066 char *output = NULL, *config = NULL;
2067 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002068 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002069 /* Values cleared after each firmware or parameter, regardless if N/A */
2070 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08002071 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002072 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002073 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002074 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002075 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002076 uint8_t efs_spi_readmode = 0xff;
2077 uint8_t efs_spi_speed = 0xff;
2078 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002079 const char *signed_output_file = NULL;
2080 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002081
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002082 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002083 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002084 int list_deps = 0;
2085
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002086 while (1) {
2087 int optindex = 0;
2088
2089 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2090
2091 if (c == -1)
2092 break;
2093
2094 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002095 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002096 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002097 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002098 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002099 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002100 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002101 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002102 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002103 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002104 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002105 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002106 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002107 case AMDFW_OPT_RECOVERY_AB:
2108 cb_config.recovery_ab = true;
2109 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002110 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2111 cb_config.recovery_ab = true;
2112 cb_config.recovery_ab_single_copy = true;
2113 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002114 case AMDFW_OPT_USE_COMBO:
2115 cb_config.use_combo = true;
2116 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002117 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002118 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002119 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002120 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002121 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002122 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002123 sub = instance = 0;
2124 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002125 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002126 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002127 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002128 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002129 instance = strtoul(optarg, &tmp, 16);
2130 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002131 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002132 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002133 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002134 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002135 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002136 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002137 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002138 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002139 register_fw_fuse(optarg);
2140 fuse_defined = 1;
2141 sub = 0;
2142 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002143 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002144 if ((instance & 0xF0) == 0)
2145 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2146 else
2147 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2148 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002149 sub = instance = 0;
2150 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002151 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002152 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302153 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002154 sub = instance = 0;
2155 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002156 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002157 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302158 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002159 sub = instance = 0;
2160 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002161 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002162 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302163 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002164 sub = instance = 0;
2165 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002166 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002167 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2168 sub = instance = 0;
2169 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002170 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002171 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302172 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002173 sub = instance = 0;
2174 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002175 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002176 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302177 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002178 sub = instance = 0;
2179 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002180 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002181 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302182 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002183 sub = instance = 0;
2184 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302185 case LONGOPT_BIOS_SIG:
2186 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302187 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302188 sub = instance = 0;
2189 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002190 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002191 register_bdt_data(AMD_BIOS_UCODE, sub,
2192 instance, optarg);
2193 sub = instance = 0;
2194 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002195 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002196 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002197 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002198 case AMDFW_OPT_SPL_TABLE:
2199 register_fw_filename(AMD_FW_SPL, sub, optarg);
2200 sub = instance = 0;
2201 cb_config.have_mb_spl = true;
2202 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002203 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002204 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2205 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002206 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002207 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002208 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002209 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2210 sub = instance = 0;
2211 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002212 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002213 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2214 sub = instance = 0;
2215 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002216 case AMDFW_OPT_SIGNED_OUTPUT:
2217 signed_output_file = optarg;
2218 sub = instance = 0;
2219 break;
2220 case AMDFW_OPT_SIGNED_ADDR:
2221 signed_start_addr = strtoull(optarg, NULL, 10);
2222 sub = instance = 0;
2223 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002224 case LONGOPT_SPI_READ_MODE:
2225 efs_spi_readmode = strtoull(optarg, NULL, 16);
2226 sub = instance = 0;
2227 break;
2228 case LONGOPT_SPI_SPEED:
2229 efs_spi_speed = strtoull(optarg, NULL, 16);
2230 sub = instance = 0;
2231 break;
2232 case LONGOPT_SPI_MICRON_FLAG:
2233 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2234 sub = instance = 0;
2235 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002236 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002237 output = optarg;
2238 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002239 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002240 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002241 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002242 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002243 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002244 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002245 }
2246 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002247 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002248 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002249 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002250 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002251 " incorrectly (%s)\n\n", optarg);
2252 retval = 1;
2253 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002254 if (body_location == 0)
2255 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002256 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002257 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002258 any_location = 1;
2259 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002260 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002261 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302262 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002263 sub = instance = 0;
2264 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002265 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002266 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302267 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002268 sub = instance = 0;
2269 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302270 case LONGOPT_NVRAM_BASE:
2271 /* PSP NV base */
2272 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2273 sub = instance = 0;
2274 break;
2275 case LONGOPT_NVRAM_SIZE:
2276 /* PSP NV size */
2277 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2278 sub = instance = 0;
2279 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002280 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002281 config = optarg;
2282 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002283 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002284 debug = 1;
2285 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002286 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002287 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002288 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002289 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002290 list_deps = 1;
2291 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002292 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002293 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002294 if (*tmp != '\0') {
2295 fprintf(stderr, "Error: Body Location specified"
2296 " incorrectly (%s)\n\n", optarg);
2297 retval = 1;
2298 }
2299 break;
2300
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002301 default:
2302 break;
2303 }
2304 }
2305
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002306 if (config) {
2307 config_handle = fopen(config, "r");
2308 if (config_handle == NULL) {
2309 fprintf(stderr, "Can not open file %s for reading: %s\n",
2310 config, strerror(errno));
2311 exit(1);
2312 }
2313 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2314 fprintf(stderr, "Configuration file %s parsing error\n", config);
2315 fclose(config_handle);
2316 exit(1);
2317 }
2318 fclose(config_handle);
2319 }
Zheng Bao9e908072020-10-28 11:39:13 +08002320 /* For debug. */
2321 if (debug) {
2322 dump_psp_firmwares(amd_psp_fw_table);
2323 dump_bdt_firmwares(amd_bios_table);
2324 }
2325
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002326 if (!fuse_defined)
2327 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2328
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002329 if (!output && !list_deps) {
2330 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002331 retval = 1;
2332 }
2333
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002334 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2335 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002336 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002337 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002338 }
2339
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002340 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2341 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002342 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002343 retval = 1;
2344 }
2345
2346 if (retval) {
2347 usage();
2348 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002349 }
2350
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002351 if (list_deps) {
2352 return retval;
2353 }
2354
Marshall Dawson2794a862019-03-04 16:53:15 -07002355 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002356
Marshall Dawson2794a862019-03-04 16:53:15 -07002357 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002358 if (efs_location && (efs_location < rom_base_address)) {
2359 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2360 return 1;
2361 }
2362
Zheng Bao99945dc2023-01-02 10:55:56 +08002363 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002364 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2365 return 1;
2366 }
2367
2368 /*
2369 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2370 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2371 * currently. This condition is to ensure that it is not accidentally split. Revisit
2372 * this condition if such a need arises in the future.
2373 */
Zheng Bao99945dc2023-01-02 10:55:56 +08002374 if (!any_location && body_location != efs_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002375 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2376 return 1;
2377 }
2378
Zheng Bao99945dc2023-01-02 10:55:56 +08002379 if (body_location != efs_location &&
2380 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002381 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2382 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002383 return 1;
2384 }
Zheng Bao4e8fb352022-11-21 21:34:45 +08002385 if (efs_location & 0xFF000000)
2386 efs_location = efs_location - rom_base_address;
2387 if (body_location & 0xFF000000)
2388 body_location = body_location - rom_base_address;
Martin Roth0d3b1182017-10-03 14:16:04 -06002389
Martin Roth37305e72020-04-07 14:16:39 -06002390 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002391 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002392 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002393 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002394 return 1;
2395 }
2396 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002397 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002398 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002399 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002400 case 0xFA0000:
2401 case 0xF20000:
2402 case 0xE20000:
2403 case 0xC20000:
2404 case 0x820000:
2405 case 0x020000:
2406 break;
2407 case 0x7A0000:
2408 case 0x720000:
2409 case 0x620000:
2410 case 0x420000:
2411 /* Special cases for 8M. */
2412 if (ctx.rom_size != 0x800000) {
2413 fprintf(stderr, "Error: Invalid Directory location.\n");
2414 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2415 return 1;
2416 }
2417 break;
2418 case 0x3A0000:
2419 case 0x320000:
2420 case 0x220000:
2421 /* Special cases for 4M. */
2422 if (ctx.rom_size != 0x400000) {
2423 fprintf(stderr, "Error: Invalid Directory location.\n");
2424 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2425 return 1;
2426 }
Martin Roth37305e72020-04-07 14:16:39 -06002427 break;
2428 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002429 fprintf(stderr, "Error: Invalid Directory location.\n");
2430 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2431 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002432 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2433 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002434 return 1;
2435 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002436 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002437 ctx.rom = malloc(ctx.rom_size);
2438 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002439 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002440 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002441 }
2442 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002443
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002444 if (efs_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002445 if (efs_location != body_location) {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002446 romsig_offset = efs_location;
2447 ctx.current = body_location;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002448 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002449 romsig_offset = efs_location;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002450 ctx.current = romsig_offset + sizeof(embedded_firmware);
2451 }
2452 } else {
2453 romsig_offset = AMD_ROMSIG_OFFSET;
2454 ctx.current = romsig_offset + sizeof(embedded_firmware);
2455 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002456
Marshall Dawson2794a862019-03-04 16:53:15 -07002457 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002458 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2459 amd_romsig->imc_entry = 0;
2460 amd_romsig->gec_entry = 0;
2461 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002462
Zheng Bao4bf6f492023-01-25 22:37:29 +08002463 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2464 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2465 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002466 if (retval) {
2467 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2468 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002469 }
2470 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002471 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002472 }
2473
Felix Held21a8e382022-03-29 23:10:45 +02002474 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002475 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002476 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002477 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002478 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002479 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002480 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2481 efs_location);
2482 if (body_location != efs_location)
2483 printf(" with a split body at: 0x%08x\n", body_location);
2484 else
2485 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002486
Marshall Dawson2794a862019-03-04 16:53:15 -07002487 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002488
Elyes Haouas7d67a192022-10-14 09:58:29 +02002489 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002490 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002491
Kangheui Won3c164e12021-12-03 20:25:05 +11002492 /* If the tool is invoked with command-line options to keep the signed PSP
2493 binaries separate, process the signed binaries first. */
2494 if (signed_output_file && signed_start_addr)
2495 process_signed_psp_firmwares(signed_output_file,
2496 amd_psp_fw_table,
2497 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002498 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002499
Zheng Bao481661e2021-08-20 14:47:46 +08002500 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002501 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002502 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2503 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002504 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002505 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2506 /* Create a copy of PSP Directory 2 in the backup slot B.
2507 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002508 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2509 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002510 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002511 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002512 /*
2513 * Either the platform is using only one slot or B is same as above
2514 * directories for A. Skip creating pspdir2_b here to save flash space.
2515 * Related biosdir2_b will be skipped automatically.
2516 */
Zheng Bao990d1542021-09-17 13:24:54 +08002517 pspdir2_b = NULL; /* More explicitly */
2518 }
Zheng Bao481661e2021-08-20 14:47:46 +08002519 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002520 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002521 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002522 } else {
2523 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002524 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002525 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002526 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002527 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002528
Zheng Bao4bfb36e2023-02-11 22:13:36 +08002529 switch (cb_config.soc_id) {
2530 case PLATFORM_UNKNOWN:
Felix Heldad68b072021-10-18 14:00:35 +02002531 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4bfb36e2023-02-11 22:13:36 +08002532 break;
2533 case PLATFORM_CEZANNE:
2534 case PLATFORM_MENDOCINO:
2535 case PLATFORM_PHOENIX:
2536 case PLATFORM_GLINDA:
2537 case PLATFORM_CARRIZO:
2538 case PLATFORM_STONEYRIDGE:
2539 case PLATFORM_RAVEN:
2540 case PLATFORM_PICASSO:
2541 case PLATFORM_LUCIENNE:
2542 case PLATFORM_RENOIR:
2543 default:
2544 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
2545 break;
2546 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002547
Zheng Bao993b43f2021-11-10 12:21:46 +08002548 if (cb_config.use_combo) {
2549 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2550 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2551 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2552 combo_dir->entries[0].id_sel = 0;
Zheng Bao4bf6f492023-01-25 22:37:29 +08002553 combo_dir->entries[0].id = get_psp_id(cb_config.soc_id);
Zheng Bao993b43f2021-11-10 12:21:46 +08002554 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002555
Zheng Bao993b43f2021-11-10 12:21:46 +08002556 combo_dir->header.lookup = 1;
2557 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2558 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002559
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002560 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002561 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002562 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002563 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002564 bios_directory_table *biosdir2 = NULL;
2565 bios_directory_table *biosdir2_b = NULL;
2566
2567 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2568
Zheng Baoedd1e362021-11-04 17:47:07 +08002569 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002570 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002571 if (cb_config.recovery_ab) {
2572 if (pspdir2_b != NULL) {
2573 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2574 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002575 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002576 }
2577 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2578 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2579 if (pspdir2_b != NULL)
2580 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2581 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2582 } else {
2583 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2584 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002585 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002586 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002587 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002588 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002589 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002590 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002591 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002592 }
Zheng Bao4bf6f492023-01-25 22:37:29 +08002593 switch (cb_config.soc_id) {
Zheng Baobf29a0d2020-12-03 23:00:48 +08002594 case PLATFORM_RENOIR:
2595 case PLATFORM_LUCIENNE:
2596 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002597 if (!cb_config.recovery_ab)
2598 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002599 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002600 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002601 case PLATFORM_PHOENIX:
2602 case PLATFORM_GLINDA:
Zheng Bao535ec532021-08-12 16:30:19 +08002603 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +08002604 case PLATFORM_CARRIZO:
Zheng Baobf29a0d2020-12-03 23:00:48 +08002605 case PLATFORM_STONEYRIDGE:
2606 case PLATFORM_RAVEN:
2607 case PLATFORM_PICASSO:
2608 default:
2609 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2610 break;
2611 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002612 }
2613
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002614 /* Free the filename. */
2615 free_psp_firmware_filenames(amd_psp_fw_table);
2616 free_bdt_firmware_filenames(amd_bios_table);
2617
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002618 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002619 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002620 ssize_t bytes;
Zheng Bao4e8fb352022-11-21 21:34:45 +08002621 uint32_t offset = body_location ? body_location : AMD_ROMSIG_OFFSET;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002622
2623 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2624 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002625 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2626 retval = 1;
2627 }
Martin Roth31d95a22016-11-08 11:22:12 -07002628 close(targetfd);
2629 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002630 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002631 retval = 1;
2632 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002633
Zheng Bao99945dc2023-01-02 10:55:56 +08002634 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002635 ssize_t bytes;
2636
2637 bytes = write_efs(output, amd_romsig);
2638 if (bytes != sizeof(*amd_romsig)) {
2639 fprintf(stderr, "Error: Writing EFS\n");
2640 retval = 1;
2641 }
2642 }
2643
Martin Roth31d95a22016-11-08 11:22:12 -07002644 free(rom);
2645 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002646}