blob: f4fd6eeca4652eb0f302193fae8f11bfe6118475 [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
Zheng Baodd4c5422021-10-14 16:14:09 +08004 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +08009 * | PSPDIR ADDR|PSPDIR ADDR(C) | BDT ADDR 0 | BDT ADDR 1 |
10 * +------------+---------------+----------------+------------+
11 * | BDT ADDR 2 | | BDT ADDR 3(C) | |
12 * +------------+---------------+----------------+------------+
13 * (C): Could be a combo header
14 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080015 * EC ROM should be 64K aligned.
16 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080017 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080018 * +------------+---------------+----------------+------------+
19 * | 'PSP$' | Fletcher | Count | Reserved |
20 * +------------+---------------+----------------+------------+
21 * | 0 | size | Base address | Reserved | Pubkey
22 * +------------+---------------+----------------+------------+
23 * | 1 | size | Base address | Reserved | Bootloader
24 * +------------+---------------+----------------+------------+
25 * | 8 | size | Base address | Reserved | Smu Firmware
26 * +------------+---------------+----------------+------------+
27 * | 3 | size | Base address | Reserved | Recovery Firmware
28 * +------------+---------------+----------------+------------+
29 * | |
30 * | |
Zheng Baodd4c5422021-10-14 16:14:09 +080031 * | Other PSP Firmware |
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080032 * | |
33 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080034 * | 40 | size | Base address | Reserved |---+
35 * +------------+---------------+----------------+------------+ |
36 * :or 48(A/B A): size : Base address : Reserved : |
37 * + - - + - - + - - + - - + |
38 * : 4A(A/B B): size : Base address : Reserved : |
39 * +------------+---------------+----------------+------------+ |
40 * (A/B A) & (A/B B): Similar as 40, pointing to PSP level 2 |
41 * for A/B recovery |
42 * |
43 * |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
47 * | |
48 * | |
49 * | PSP Firmware |
50 * | (2nd-level is not required on all families) |
51 * | |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
Zheng Bao4fcc9f22015-11-20 12:29:04 +080054 *
zbaoc3b0b722016-02-19 13:47:31 +080055 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080056 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080057 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080058 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080059 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080061 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080062 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080063 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080064 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080069 * BDT Combo is similar
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080070 */
71
Elyes Haouas7d67a192022-10-14 09:58:29 +020072#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080073#include <fcntl.h>
74#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060075#include <limits.h>
Kangheui Won5b84dfd2021-12-21 15:45:06 +110076#include <openssl/sha.h>
Martin Roth37305e72020-04-07 14:16:39 -060077#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080078#include <stdio.h>
79#include <sys/stat.h>
80#include <sys/types.h>
81#include <unistd.h>
82#include <string.h>
83#include <stdlib.h>
84#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080085#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010086#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080087
88#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080089
Martin Roth60f15512016-11-08 09:55:01 -070090#define AMD_ROMSIG_OFFSET 0x20000
91#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092
Marshall Dawson7c1e1422019-04-11 09:44:43 -060093#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
94#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070095#define TABLE_ALIGNMENT 0x1000U
96#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060097#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060098#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080099
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600100#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
101
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100102/* Defines related to hashing signed binaries */
103enum hash_header_ver {
104 HASH_HDR_V1 = 1,
105};
106/* Signature ID enums are defined by PSP based on the algorithm used. */
107enum signature_id {
108 SIG_ID_RSA2048,
109 SIG_ID_RSA4096 = 2,
110};
111#define HASH_FILE_SUFFIX ".hash"
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -0600112#define EFS_FILE_SUFFIX ".efs"
113#define TMP_FILE_SUFFIX ".tmp"
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100114
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800115/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700116 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
117 * can support an optional "combo" implementation. If the PSP sees the
118 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
119 * tables. Using this, support for multiple product generations may be
120 * built into one image. If the PSP$ cookie is found, the table is a
121 * normal directory table.
122 *
123 * Modern generations supporting the combo directories require the
124 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
125 * regardless of the type of directory used. The --combo-capable
126 * argument enforces this placement.
127 *
128 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800129 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800130
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800131/*
132 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
133 * The checksum field of the passed PDU does not need to be reset to zero.
134 *
135 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
136 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
137 * alternative to cyclical redundancy checks because it provides error-
138 * detection properties similar to cyclical redundancy checks but at the
139 * cost of a simple summation technique. Its characteristics were first
140 * published in IEEE Transactions on Communications in January 1982. One
141 * version has been adopted by ISO for use in the class-4 transport layer
142 * of the network protocol.
143 *
144 * This program expects:
145 * stdin: The input file to compute a checksum for. The input file
146 * not be longer than 256 bytes.
147 * stdout: Copied from the input file with the Fletcher's Checksum
148 * inserted 8 bytes after the beginning of the file.
149 * stderr: Used to print out error messages.
150 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700151static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800152{
153 uint32_t c0;
154 uint32_t c1;
155 uint32_t checksum;
156 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700157 const uint16_t *pptr = data;
158
159 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800160
161 c0 = 0xFFFF;
162 c1 = 0xFFFF;
163
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600164 while (length) {
165 index = length >= 359 ? 359 : length;
166 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800167 do {
168 c0 += *(pptr++);
169 c1 += c0;
170 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600171 c0 = (c0 & 0xFFFF) + (c0 >> 16);
172 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800173 }
174
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700175 /* Sums[0,1] mod 64K + overflow */
176 c0 = (c0 & 0xFFFF) + (c0 >> 16);
177 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800178 checksum = (c1 << 16) | c0;
179
180 return checksum;
181}
182
Martin Roth8806f7f2016-11-08 10:44:18 -0700183static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800184{
Martin Roth0e940622016-11-08 10:37:53 -0700185 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800186 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
187 printf("--xhci <FILE> Add XHCI blob\n");
188 printf("--imc <FILE> Add IMC blob\n");
189 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700190
191 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800192 printf("--combo-capable Place PSP directory pointer at Embedded\n");
193 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700194 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800195 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800196 printf("--multilevel Generate primary and secondary tables\n");
197 printf("--nvram <FILE> Add nvram binary\n");
198 printf("--soft-fuse Set soft fuse\n");
199 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530200 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
201 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800202 printf("--whitelist Set if there is a whitelist\n");
203 printf("--use-pspsecureos Set if psp secure OS is needed\n");
204 printf("--load-mp2-fw Set if load MP2 firmware\n");
205 printf("--load-s0i3 Set if load s0i3 firmware\n");
206 printf("--verstage <FILE> Add verstage\n");
207 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800208 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600209 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800210 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800211 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800212 printf("--apcb <FILE> Add AGESA PSP customization block\n");
213 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
214 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
215 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
216 printf("--ucode <FILE> Add microcode patch\n");
217 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
218 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
219 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
220 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
221 printf("--output <filename> output filename\n");
222 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600223 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700224 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600225 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800226 printf("--location Location of Directory\n");
227 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
228 printf("--sharedmem Location of PSP/FW shared memory\n");
229 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800230 printf(" area\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800231 printf("--soc-name <socname> Specify SOC name. Supported names are\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800232 printf(" Stoneyridge, Raven, Picasso, Renoir, Cezanne\n");
Martin Roth20646cd2023-01-04 21:27:06 -0700233 printf(" Mendocino, Phoenix, Glinda, or Lucienne\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500234 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
235 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
236 printf(" 0x0 66.66Mhz\n");
237 printf(" 0x1 33.33MHz\n");
238 printf(" 0x2 22.22MHz\n");
239 printf(" 0x3 16.66MHz\n");
240 printf(" 0x4 100MHz\n");
241 printf(" 0x5 800KHz\n");
242 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
243 printf(" 0x0 Normal Read (up to 33M)\n");
244 printf(" 0x1 Reserved\n");
245 printf(" 0x2 Dual IO (1-1-2)\n");
246 printf(" 0x3 Quad IO (1-1-4)\n");
247 printf(" 0x4 Dual IO (1-2-2)\n");
248 printf(" 0x5 Quad IO (1-4-4)\n");
249 printf(" 0x6 Normal Read (up to 66M)\n");
250 printf(" 0x7 Fast Read\n");
251 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
252 printf(" 0x0 Micron parts are not used\n");
253 printf(" 0x1 Micron parts are always used\n");
254 printf(" 0x2 Micron parts optional, this option is only\n");
255 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800256 printf("\nGeneral options:\n");
257 printf("-c|--config <config file> Config file\n");
258 printf("-d|--debug Print debug message\n");
259 printf("-l|--list List out the firmware files\n");
260 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800261}
262
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800263amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100264 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800265 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800266 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200267 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800268 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200269 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
270 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
271 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800272 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100273 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
274 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200275 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200276 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800277 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
278 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800279 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200280 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
281 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800282 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
283 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800286 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
287 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100288 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800289 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
290 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800291 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200292 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800293 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200294 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
295 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800296 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
297 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200298 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
299 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
300 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800301 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800302 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
303 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
304 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
305 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
306 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
307 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
308 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
309 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200310 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
311 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600312 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200313 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200314 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200315 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
316 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
317 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
318 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
319 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600320 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
321 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200322 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
325 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
326 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
327 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800328 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_BOTH_AB },
329 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200330 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
331 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800332 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
333 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200334 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200335 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200336 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
337 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800338 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
339 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
340 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
341 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
342 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
343 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
344 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
345 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
346 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
347 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
348 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
349 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
350 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
351 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800352 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800353};
354
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800355amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800356 { .type = AMD_FW_XHCI },
357 { .type = AMD_FW_IMC },
358 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800359 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800360};
361
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800362amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800363 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530364 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600365 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700370 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
377 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
378 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
379 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
380 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700381 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
382 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
383 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
384 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
385 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700386 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
387 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
388 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
389 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
390 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
391 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
392 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
393 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
394 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
395 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
396 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600397 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
398 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800399 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600400 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
401 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800403 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200405 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600407 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800409 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200415 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800419 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600425 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800427 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200429 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
430 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600431 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
432 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800433 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
434 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
435 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
436 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
437 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
438 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200439 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
440 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
441 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
442 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800443 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
444 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
445 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
446 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
447 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
448 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600449 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
450 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
451 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200452 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
453 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
454 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
455 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600456 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600457 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600458 { .type = AMD_BIOS_INVALID },
459};
460
Marshall Dawson2794a862019-03-04 16:53:15 -0700461typedef struct _context {
462 char *rom; /* target buffer, size of flash device */
463 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800464 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700465 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800466 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700467} context;
468
469#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800470#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600471 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
472 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
473 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800474#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600475#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800476 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700477#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800478/* The mode in entry can not be higher than the header's.
479 For example, if table mode is 0, all the entry mode will be 0. */
480#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
481 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700482#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
483#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
484#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800485#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
486 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700487#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800488/* Only set the address mode in entry if the table is mode 2. */
489#define SET_ADDR_MODE(table, mode) \
490 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600491 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800492#define SET_ADDR_MODE_BY_TABLE(table) \
493 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700494
Zheng Bao5164e4b2021-10-30 12:09:07 +0800495void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
496{
497 if (count >= max) {
498 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
499 "(%d)\n", count, max);
500 free(ctx->rom);
501 exit(1);
502 }
503}
504
Marshall Dawson24f73d42019-04-01 10:48:43 -0600505static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700506{
507 void *ptr;
508
Marshall Dawson24f73d42019-04-01 10:48:43 -0600509 /*
510 * Force both onto boundary when multi. Primary table is after
511 * updatable table, so alignment ensures primary can stay intact
512 * if secondary is reprogrammed.
513 */
514 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200515 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600516 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200517 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600518
Marshall Dawson2794a862019-03-04 16:53:15 -0700519 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800520 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800521 ((psp_directory_header *)ptr)->additional_info = 0;
522 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700523 ctx->current += sizeof(psp_directory_header)
524 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
525 return ptr;
526}
527
Zheng Baofdd47ef2021-09-17 13:30:08 +0800528static void *new_ish_dir(context *ctx)
529{
530 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200531 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800532 ptr = BUFF_CURRENT(*ctx);
533 ctx->current += TABLE_ALIGNMENT;
534 return ptr;
535}
536
Marshall Dawson2794a862019-03-04 16:53:15 -0700537static void *new_combo_dir(context *ctx)
538{
539 void *ptr;
540
Elyes Haouas7d67a192022-10-14 09:58:29 +0200541 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700542 ptr = BUFF_CURRENT(*ctx);
543 ctx->current += sizeof(psp_combo_header)
544 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
545 return ptr;
546}
547
Zheng Baobf29a0d2020-12-03 23:00:48 +0800548static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800549{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600550 psp_combo_directory *cdir = directory;
551 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600552 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800553 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600554
555 if (!count)
556 return;
Zheng Baob035f582021-05-27 11:26:12 +0800557 if (ctx == NULL || directory == NULL) {
558 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
559 return;
560 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600561
Zheng Baobf29a0d2020-12-03 23:00:48 +0800562 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200563 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800564
Marshall Dawson24f73d42019-04-01 10:48:43 -0600565 switch (cookie) {
566 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700567 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700568 cdir->header.cookie = cookie;
569 cdir->header.num_entries = count;
570 cdir->header.reserved[0] = 0;
571 cdir->header.reserved[1] = 0;
572 /* checksum everything that comes after the Checksum field */
573 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
574 count * sizeof(psp_combo_entry)
575 + sizeof(cdir->header.num_entries)
576 + sizeof(cdir->header.lookup)
577 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600578 break;
579 case PSP_COOKIE:
580 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800581 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800582 if ((table_size % TABLE_ALIGNMENT) != 0) {
583 fprintf(stderr, "The PSP table size should be 4K aligned\n");
584 exit(1);
585 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700586 dir->header.cookie = cookie;
587 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800588 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
589 dir->header.additional_info_fields.spi_block_size = 1;
590 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700591 /* checksum everything that comes after the Checksum field */
592 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700593 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700594 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800595 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600596 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800597 case BHD_COOKIE:
598 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800599 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800600 if ((table_size % TABLE_ALIGNMENT) != 0) {
601 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
602 exit(1);
603 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600604 bdir->header.cookie = cookie;
605 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800606 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
607 bdir->header.additional_info_fields.spi_block_size = 1;
608 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600609 /* checksum everything that comes after the Checksum field */
610 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
611 count * sizeof(bios_directory_entry)
612 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800613 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600614 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700615 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800616
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800617}
618
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700619static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
620{
621 int fd;
622 struct stat fd_stat;
623 ssize_t bytes;
624
625 fd = open(src_file, O_RDONLY);
626 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800627 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700628 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700629 return -1;
630 }
631
632 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800633 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600634 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700635 return -2;
636 }
637
Zheng Bao6d402ac2020-10-01 16:16:30 +0800638 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800639 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600640 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700641 return -3;
642 }
643
644 bytes = read(fd, dest, (size_t)fd_stat.st_size);
645 close(fd);
646 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800647 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700648 return -4;
649 }
650
651 return bytes;
652}
653
Kangheui Won3c164e12021-12-03 20:25:05 +1100654static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
655{
656 ssize_t bytes;
657 size_t total_bytes = 0;
658
659 do {
660 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
661 if (bytes == 0) {
662 fprintf(stderr, "Reached EOF probably\n");
663 break;
664 }
665
666 if (bytes < 0 && errno == EAGAIN)
667 bytes = 0;
668
669 if (bytes < 0) {
670 fprintf(stderr, "Read failure %s\n", strerror(errno));
671 return bytes;
672 }
673
674 total_bytes += bytes;
675 } while (total_bytes < buf_size);
676
677 if (total_bytes != buf_size) {
678 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
679 total_bytes, buf_size);
680 return -1;
681 }
682 return buf_size;
683}
684
685static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
686{
687 ssize_t bytes;
688 size_t total_bytes = 0;
689
690 do {
691 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
692 if (bytes < 0 && errno == EAGAIN)
693 bytes = 0;
694
695 if (bytes < 0) {
696 fprintf(stderr, "Write failure %s\n", strerror(errno));
697 lseek(fd, SEEK_CUR, -total_bytes);
698 return bytes;
699 }
700
701 total_bytes += bytes;
702 } while (total_bytes < buf_size);
703
704 if (total_bytes != buf_size) {
705 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
706 total_bytes, buf_size);
707 lseek(fd, SEEK_CUR, -total_bytes);
708 return -1;
709 }
710
711 return buf_size;
712}
713
Zheng Baoeb0404e2021-10-14 15:09:09 +0800714enum platform {
715 PLATFORM_UNKNOWN,
716 PLATFORM_STONEYRIDGE,
717 PLATFORM_RAVEN,
718 PLATFORM_PICASSO,
719 PLATFORM_RENOIR,
720 PLATFORM_CEZANNE,
721 PLATFORM_MENDOCINO,
722 PLATFORM_LUCIENNE,
Martin Roth20646cd2023-01-04 21:27:06 -0700723 PLATFORM_PHOENIX,
Martin Roth13490832022-10-06 17:18:02 -0600724 PLATFORM_GLINDA
Zheng Baoeb0404e2021-10-14 15:09:09 +0800725};
726
727static uint32_t get_psp_id(enum platform soc_id)
728{
729 uint32_t psp_id;
730 switch (soc_id) {
731 case PLATFORM_RAVEN:
732 case PLATFORM_PICASSO:
733 psp_id = 0xBC0A0000;
734 break;
735 case PLATFORM_RENOIR:
736 case PLATFORM_LUCIENNE:
737 psp_id = 0xBC0C0000;
738 break;
739 case PLATFORM_CEZANNE:
740 psp_id = 0xBC0C0140;
741 break;
742 case PLATFORM_MENDOCINO:
743 psp_id = 0xBC0D0900;
744 break;
745 case PLATFORM_STONEYRIDGE:
746 psp_id = 0x10220B00;
747 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800748 case PLATFORM_GLINDA:
749 psp_id = 0xBC0E0200;
750 break;
751 case PLATFORM_PHOENIX:
752 psp_id = 0xBC0D0400;
753 break;
Zheng Baoeb0404e2021-10-14 15:09:09 +0800754 default:
755 psp_id = 0;
756 break;
757 }
758 return psp_id;
759}
760
Kangheui Won3c164e12021-12-03 20:25:05 +1100761static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
762{
763 switch (soc_id) {
764 case PLATFORM_MENDOCINO:
765 /* Fallback to fw_type if fw_id is not populated, which serves the same
766 purpose on older SoCs. */
767 return header->fw_id ? header->fw_id : header->fw_type;
768 default:
769 return header->fw_type;
770 }
771}
772
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100773static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
774{
775 uint8_t hash[SHA384_DIGEST_LENGTH];
776 struct amd_fw_header *header = (struct amd_fw_header *)buf;
777 /* Include only signed part for hash calculation. */
778 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
779 uint8_t *body = (uint8_t *)buf;
780
781 if (len > header->size_total)
782 return -1;
783
784 if (header->sig_id == SIG_ID_RSA4096) {
785 SHA384(body, len, hash);
786 entry->sha_len = SHA384_DIGEST_LENGTH;
787 } else if (header->sig_id == SIG_ID_RSA2048) {
788 SHA256(body, len, hash);
789 entry->sha_len = SHA256_DIGEST_LENGTH;
790 } else {
791 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
792 __func__, header->sig_id);
793 return -1;
794 }
795
796 memcpy(entry->sha, hash, entry->sha_len);
797 entry->fw_id = get_psp_fw_type(soc_id, header);
798 entry->subtype = header->fw_subtype;
799
800 return 0;
801}
802
803static int get_num_binaries(void *buf, size_t buf_size)
804{
805 struct amd_fw_header *header = (struct amd_fw_header *)buf;
806 size_t total_len = 0;
807 int num_binaries = 0;
808
809 while (total_len < buf_size) {
810 num_binaries++;
811 total_len += header->size_total;
812 header = (struct amd_fw_header *)(buf + total_len);
813 }
814
815 if (total_len != buf_size) {
816 fprintf(stderr, "Malformed binary\n");
817 return -1;
818 }
819 return num_binaries;
820}
821
822static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
823{
824 struct amd_fw_header *header = (struct amd_fw_header *)buf;
825 /* Include only signed part for hash calculation. */
826 size_t total_len = 0;
827 int num_binaries = get_num_binaries(buf, buf_size);
828
829 if (num_binaries <= 0)
830 return num_binaries;
831
832 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
833 if (!entry->hash_entries) {
834 fprintf(stderr, "Error allocating memory to add FW hash\n");
835 return -1;
836 }
837 entry->num_hash_entries = num_binaries;
838
839 /* Iterate through each binary */
840 for (int i = 0; i < num_binaries; i++) {
841 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
842 free(entry->hash_entries);
843 return -1;
844 }
845 total_len += header->size_total;
846 header = (struct amd_fw_header *)(buf + total_len);
847 }
848
849 return 0;
850}
851
Marshall Dawson2794a862019-03-04 16:53:15 -0700852static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700853 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700854 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800855{
Richard Spiegel137484d2018-01-17 10:23:19 -0700856 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800857 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700858
Elyes Haouas7d67a192022-10-14 09:58:29 +0200859 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800860
Martin Rothcd15bc82016-11-08 11:34:02 -0700861 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800862 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800863 switch (fw_table[i].type) {
864 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200865 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700866 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800867 break;
868 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700869 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800870 break;
871 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700872 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800873 break;
874 default:
875 /* Error */
876 break;
877 }
878
Marshall Dawson2794a862019-03-04 16:53:15 -0700879 bytes = copy_blob(BUFF_CURRENT(*ctx),
880 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600881 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700882 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700883 exit(1);
884 }
885
Elyes Haouas7d67a192022-10-14 09:58:29 +0200886 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700887 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800888 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800889 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800890}
891
Zheng Bao9e908072020-10-28 11:39:13 +0800892/* For debugging */
893static void dump_psp_firmwares(amd_fw_entry *fw_table)
894{
895 amd_fw_entry *index;
896
897 printf("PSP firmware components:");
898 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
899 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800900 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800901 }
902}
903
904static void dump_bdt_firmwares(amd_bios_entry *fw_table)
905{
906 amd_bios_entry *index;
907
908 printf("BIOS Directory Table (BDT) components:");
909 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
910 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800911 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800912 }
913}
914
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800915static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
916{
917 amd_fw_entry *index;
918
919 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
920 if (index->filename &&
921 index->type != AMD_FW_VERSTAGE_SIG &&
922 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800923 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800924 index->type != AMD_FW_PSP_WHITELIST) {
925 free(index->filename);
926 }
927 }
928}
929
930static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
931{
932 amd_bios_entry *index;
933
934 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
935 if (index->filename &&
936 index->type != AMD_BIOS_APCB &&
937 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200938 index->type != AMD_BIOS_APCB_BK &&
939 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800940 free(index->filename);
941 }
942}
943
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100944static void write_or_fail(int fd, void *ptr, size_t size)
945{
946 ssize_t written;
947
948 written = write_from_buf_to_file(fd, ptr, size);
949 if (written < 0 || (size_t)written != size) {
950 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
951 __func__, size, written);
952 exit(-1);
953 }
954}
955
956static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
957{
958 uint16_t type = entry->fw_id;
959 uint16_t subtype = entry->subtype;
960
961 write_or_fail(fd, &type, sizeof(type));
962 write_or_fail(fd, &subtype, sizeof(subtype));
963 write_or_fail(fd, entry->sha, entry->sha_len);
964}
965
966static void write_psp_firmware_hash(const char *filename,
967 amd_fw_entry *fw_table)
968{
969 struct psp_fw_hash_table hash_header = {0};
970 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
971
972 if (fd < 0) {
973 fprintf(stderr, "Error opening file: %s: %s\n",
974 filename, strerror(errno));
975 exit(-1);
976 }
977
978 hash_header.version = HASH_HDR_V1;
979 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
980 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
981 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
982 hash_header.no_of_entries_256++;
983 } else if (fw_table[i].hash_entries[j].sha_len ==
984 SHA384_DIGEST_LENGTH) {
985 hash_header.no_of_entries_384++;
986 } else if (fw_table[i].hash_entries[j].sha_len) {
987 fprintf(stderr, "%s: Error invalid sha_len %d\n",
988 __func__, fw_table[i].hash_entries[j].sha_len);
989 exit(-1);
990 }
991 }
992 }
993
994 write_or_fail(fd, &hash_header, sizeof(hash_header));
995
996 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
997 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
998 will cause the hash verification failure at run-time. */
999 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1000 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
1001 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
1002 write_one_psp_firmware_hash_entry(fd,
1003 &fw_table[i].hash_entries[j]);
1004 }
1005 }
1006
1007 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1008 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
1009 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
1010 write_one_psp_firmware_hash_entry(fd,
1011 &fw_table[i].hash_entries[j]);
1012 }
1013 }
1014
1015 close(fd);
1016 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1017 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
1018 continue;
1019
1020 free(fw_table[i].hash_entries);
1021 fw_table[i].hash_entries = NULL;
1022 fw_table[i].num_hash_entries = 0;
1023 }
1024}
1025
Kangheui Won3c164e12021-12-03 20:25:05 +11001026/**
1027 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
1028 * @signed_rom: Output file path grouping all the signed PSP binaries.
1029 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
1030 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
1031 * the signed PSP binaries.
1032 * @soc_id: SoC ID of the PSP binaries.
1033 */
1034static void process_signed_psp_firmwares(const char *signed_rom,
1035 amd_fw_entry *fw_table,
1036 uint64_t signed_start_addr,
1037 enum platform soc_id)
1038{
1039 unsigned int i;
1040 int fd;
1041 int signed_rom_fd;
1042 ssize_t bytes, align_bytes;
1043 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001044 char *signed_rom_hash;
1045 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +11001046 struct amd_fw_header header;
1047 struct stat fd_stat;
1048 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
1049 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
1050 uint8_t align_data[BLOB_ALIGNMENT - 1];
1051
1052 memset(align_data, 0xff, sizeof(align_data));
1053 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
1054 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1055 if (signed_rom_fd < 0) {
1056 fprintf(stderr, "Error opening file: %s: %s\n",
1057 signed_rom, strerror(errno));
1058 return;
1059 }
1060
1061 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001062 fw_table[i].num_hash_entries = 0;
1063 fw_table[i].hash_entries = NULL;
1064
Kangheui Won3c164e12021-12-03 20:25:05 +11001065 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
1066 continue;
1067
1068 memset(&header, 0, sizeof(header));
1069
1070 fd = open(fw_table[i].filename, O_RDONLY);
1071 if (fd < 0) {
1072 /* Keep the file along with set of unsigned PSP binaries & continue. */
1073 fprintf(stderr, "Error opening file: %s: %s\n",
1074 fw_table[i].filename, strerror(errno));
1075 continue;
1076 }
1077
1078 if (fstat(fd, &fd_stat)) {
1079 /* Keep the file along with set of unsigned PSP binaries & continue. */
1080 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1081 close(fd);
1082 continue;
1083 }
1084
1085 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1086 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1087 /* Keep the file along with set of unsigned PSP binaries & continue. */
1088 fprintf(stderr, "%s: Error reading header from %s\n",
1089 __func__, fw_table[i].filename);
1090 close(fd);
1091 continue;
1092 }
1093
1094 /* If firmware header looks like invalid, assume it's not signed */
1095 if (!header.fw_type && !header.fw_id) {
1096 fprintf(stderr, "%s: Invalid FWID for %s\n",
1097 __func__, fw_table[i].filename);
1098 close(fd);
1099 continue;
1100 }
1101
Kangheui Won3c164e12021-12-03 20:25:05 +11001102
1103 /* PSP binary is not signed and should not be part of signed PSP binaries
1104 set. */
1105 if (header.sig_opt != 1) {
1106 close(fd);
1107 continue;
1108 }
1109
1110 buf = malloc(fd_stat.st_size);
1111 if (!buf) {
1112 /* Keep the file along with set of unsigned PSP binaries & continue. */
1113 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1114 __func__, (long long)fd_stat.st_size);
1115 close(fd);
1116 continue;
1117 }
1118
1119 lseek(fd, SEEK_SET, 0);
1120 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1121 if (bytes != fd_stat.st_size) {
1122 /* Keep the file along with set of unsigned PSP binaries & continue. */
1123 fprintf(stderr, "%s: failed to read %s\n",
1124 __func__, fw_table[i].filename);
1125 free(buf);
1126 close(fd);
1127 continue;
1128 }
1129
1130 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1131 if (bytes != fd_stat.st_size) {
1132 /* Keep the file along with set of unsigned PSP binaries & continue. */
1133 fprintf(stderr, "%s: failed to write %s\n",
1134 __func__, fw_table[i].filename);
1135 free(buf);
1136 close(fd);
1137 continue;
1138 }
1139
1140 /* Write Blob alignment bytes */
1141 align_bytes = 0;
1142 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1143 align_bytes = BLOB_ALIGNMENT -
1144 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1145 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1146 if (bytes != align_bytes) {
1147 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1148 __func__, fw_table[i].filename);
1149 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1150 free(buf);
1151 close(fd);
1152 continue;
1153 }
1154 }
1155
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001156 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1157 exit(-1);
1158
Kangheui Won3c164e12021-12-03 20:25:05 +11001159 /* File is successfully processed and is part of signed PSP binaries set. */
1160 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1161 fw_table[i].addr_signed = signed_start_addr;
1162 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1163
1164 signed_start_addr += fd_stat.st_size + align_bytes;
1165
1166 free(buf);
1167 close(fd);
1168 }
1169
1170 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001171
1172 /* signed_rom file name + ".hash" + '\0' */
1173 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1174 signed_rom_hash = malloc(signed_rom_hash_strlen);
1175 if (!signed_rom_hash) {
1176 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1177 exit(-1);
1178 }
1179 strcpy(signed_rom_hash, signed_rom);
1180 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1181 write_psp_firmware_hash(signed_rom_hash, fw_table);
1182 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001183}
1184
Zheng Bao990d1542021-09-17 13:24:54 +08001185static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001186 psp_directory_table *pspdir2, ish_directory_table *ish,
1187 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001188{
1189 uint32_t count;
1190 uint32_t current_table_save;
1191
1192 current_table_save = ctx->current_table;
1193 ctx->current_table = (char *)pspdir - ctx->rom;
1194 count = pspdir->header.num_entries;
1195 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1196 pspdir->entries[count].type = (uint8_t)ab;
1197 pspdir->entries[count].subprog = 0;
1198 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001199 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001200 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001201 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1202 ish->update_retry_count = 2;
1203 ish->glitch_retry_count = 0;
1204 ish->psp_id = get_psp_id(soc_id);
1205 ish->checksum = fletcher32(&ish->boot_priority,
1206 sizeof(ish_directory_table) - sizeof(uint32_t));
1207 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001208 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001209 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001210 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001211 pspdir->entries[count].size = TABLE_ALIGNMENT;
1212 } else {
1213 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001214 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001215 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001216 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001217 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001218 sizeof(psp_directory_entry) +
1219 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001220 }
Zheng Bao990d1542021-09-17 13:24:54 +08001221
1222 count++;
1223 pspdir->header.num_entries = count;
1224 ctx->current_table = current_table_save;
1225}
1226
Marshall Dawson2794a862019-03-04 16:53:15 -07001227static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001228 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001229 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001230 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001231 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001232 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001233 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +08001234 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001235{
Richard Spiegel137484d2018-01-17 10:23:19 -07001236 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001237 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001238 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301239 uint32_t size;
1240 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001241 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001242 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001243 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001244
1245 /* This function can create a primary table, a secondary table, or a
1246 * flattened table which contains all applicable types. These if-else
1247 * statements infer what the caller intended. If a 2nd-level cookie
1248 * is passed, clearly a 2nd-level table is intended. However, a
1249 * 1st-level cookie may indicate level 1 or flattened. If the caller
1250 * passes a pointer to a 2nd-level table, then assume not flat.
1251 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001252 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001253 level = PSP_BOTH;
1254 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001255 level = PSP_LVL2;
1256 else if (pspdir2)
1257 level = PSP_LVL1;
1258 else
1259 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001260
Zheng Bao990d1542021-09-17 13:24:54 +08001261 if (recovery_ab) {
1262 if (cookie == PSPL2_COOKIE)
1263 level = PSP_LVL2_AB;
1264 else if (pspdir2)
1265 level = PSP_LVL1_AB;
1266 else
1267 level = PSP_BOTH_AB;
1268 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001269 current_table_save = ctx->current_table;
1270 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001271 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001272
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001273 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001274 if (!(fw_table[i].level & level))
1275 continue;
1276
Zheng Bao5164e4b2021-10-30 12:09:07 +08001277 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1278
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001279 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1280 if (!fw_table[i].other)
1281 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001282 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001283 pspdir->entries[count].type = fw_table[i].type;
1284 pspdir->entries[count].size = 4096; /* TODO: doc? */
1285 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001286 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001287 pspdir->entries[count].subprog = fw_table[i].subprog;
1288 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001289 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001290 count++;
1291 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001292 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001293 pspdir->entries[count].subprog = fw_table[i].subprog;
1294 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001295 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001296 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001297 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001298 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001299 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301300 if (fw_table[i].filename == NULL) {
1301 if (fw_table[i].size == 0)
1302 continue;
1303 size = fw_table[i].size;
1304 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001305 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301306 fprintf(stderr,
1307 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1308 exit(1);
1309 }
1310 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001311 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301312 bytes = copy_blob(BUFF_CURRENT(*ctx),
1313 fw_table[i].filename, BUFF_ROOM(*ctx));
1314 if (bytes <= 0) {
1315 free(ctx->rom);
1316 exit(1);
1317 }
1318
Elyes Haouas7d67a192022-10-14 09:58:29 +02001319 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301320 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001321 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301322 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001323 }
1324
1325 pspdir->entries[count].type = fw_table[i].type;
1326 pspdir->entries[count].subprog = fw_table[i].subprog;
1327 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301328 pspdir->entries[count].size = size;
1329 pspdir->entries[count].addr = addr;
1330
Zheng Bao6fff2492021-11-15 19:53:21 +08001331 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001332 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001333
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001334 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001335 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001336 if (fw_table[i].addr_signed) {
1337 pspdir->entries[count].addr =
1338 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1339 pspdir->entries[count].address_mode =
1340 SET_ADDR_MODE_BY_TABLE(pspdir);
1341 bytes = fw_table[i].file_size;
1342 } else {
1343 bytes = copy_blob(BUFF_CURRENT(*ctx),
1344 fw_table[i].filename, BUFF_ROOM(*ctx));
1345 if (bytes < 0) {
1346 free(ctx->rom);
1347 exit(1);
1348 }
1349 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1350 pspdir->entries[count].address_mode =
1351 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001352 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001353 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001354 }
1355
Marshall Dawson239286c2019-02-23 16:42:46 -07001356 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001357 pspdir->entries[count].subprog = fw_table[i].subprog;
1358 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001359 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001360
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001361 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001362 } else {
1363 /* This APU doesn't have this firmware. */
1364 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001365 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001366
Zheng Bao990d1542021-09-17 13:24:54 +08001367 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001368 if (cb_config->need_ish) { /* Need ISH */
1369 ish_a_dir = new_ish_dir(ctx);
1370 if (pspdir2_b != NULL)
1371 ish_b_dir = new_ish_dir(ctx);
1372 }
Zheng Bao990d1542021-09-17 13:24:54 +08001373 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001374 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
1375 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001376 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001377 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
1378 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001379 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001380 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001381 AMD_FW_RECOVERYAB_B, soc_id);
1382
Zheng Bao990d1542021-09-17 13:24:54 +08001383 count = pspdir->header.num_entries;
1384 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001385 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001386 pspdir->entries[count].type = AMD_FW_L2_PTR;
1387 pspdir->entries[count].subprog = 0;
1388 pspdir->entries[count].rsvd = 0;
1389 pspdir->entries[count].size = sizeof(pspdir2->header)
1390 + pspdir2->header.num_entries
1391 * sizeof(psp_directory_entry);
1392
Zheng Bao6fff2492021-11-15 19:53:21 +08001393 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001394 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001395 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001396 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001397 count++;
1398 }
1399
Zheng Baobf29a0d2020-12-03 23:00:48 +08001400 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001401 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001402}
1403
Zheng Bao990d1542021-09-17 13:24:54 +08001404static void add_psp_firmware_entry(context *ctx,
1405 psp_directory_table *pspdir,
1406 void *table, amd_fw_type type, uint32_t size)
1407{
1408 uint32_t count = pspdir->header.num_entries;
1409 uint32_t index;
1410 uint32_t current_table_save;
1411
1412 current_table_save = ctx->current_table;
1413 ctx->current_table = (char *)pspdir - ctx->rom;
1414
1415 /* If there is an entry of "type", replace it. */
1416 for (index = 0; index < count; index++) {
1417 if (pspdir->entries[index].type == (uint8_t)type)
1418 break;
1419 }
1420
1421 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1422 pspdir->entries[index].type = (uint8_t)type;
1423 pspdir->entries[index].subprog = 0;
1424 pspdir->entries[index].rsvd = 0;
1425 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1426 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1427 pspdir->entries[index].size = size;
1428 if (index == count)
1429 count++;
1430
1431 pspdir->header.num_entries = count;
1432 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1433 count * sizeof(psp_directory_entry)
1434 + sizeof(pspdir->header.num_entries)
1435 + sizeof(pspdir->header.additional_info));
1436
1437 ctx->current_table = current_table_save;
1438}
1439
Zheng Baoba3af5e2021-11-04 18:56:47 +08001440static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001441{
1442 void *ptr;
1443
1444 /*
1445 * Force both onto boundary when multi. Primary table is after
1446 * updatable table, so alignment ensures primary can stay intact
1447 * if secondary is reprogrammed.
1448 */
1449 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001450 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001451 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001452 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001453 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001454 ((bios_directory_hdr *) ptr)->additional_info = 0;
1455 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1456 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001457 ctx->current += sizeof(bios_directory_hdr)
1458 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1459 return ptr;
1460}
1461
1462static int locate_bdt2_bios(bios_directory_table *level2,
1463 uint64_t *source, uint32_t *size)
1464{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001465 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001466
1467 *source = 0;
1468 *size = 0;
1469 if (!level2)
1470 return 0;
1471
1472 for (i = 0 ; i < level2->header.num_entries ; i++) {
1473 if (level2->entries[i].type == AMD_BIOS_BIN) {
1474 *source = level2->entries[i].source;
1475 *size = level2->entries[i].size;
1476 return 1;
1477 }
1478 }
1479 return 0;
1480}
1481
1482static int have_bios_tables(amd_bios_entry *table)
1483{
1484 int i;
1485
1486 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1487 if (table[i].level & BDT_LVL1 && table[i].filename)
1488 return 1;
1489 }
1490 return 0;
1491}
1492
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001493static int find_bios_entry(amd_bios_type type)
1494{
1495 int i;
1496
1497 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1498 if (amd_bios_table[i].type == type)
1499 return i;
1500 }
1501 return -1;
1502}
1503
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001504static void integrate_bios_firmwares(context *ctx,
1505 bios_directory_table *biosdir,
1506 bios_directory_table *biosdir2,
1507 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001508 uint32_t cookie,
1509 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001510{
1511 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001512 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001513 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001514 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001515 uint32_t size;
1516 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001517
1518 /* This function can create a primary table, a secondary table, or a
1519 * flattened table which contains all applicable types. These if-else
1520 * statements infer what the caller intended. If a 2nd-level cookie
1521 * is passed, clearly a 2nd-level table is intended. However, a
1522 * 1st-level cookie may indicate level 1 or flattened. If the caller
1523 * passes a pointer to a 2nd-level table, then assume not flat.
1524 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001525 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001526 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001527 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001528 level = BDT_LVL2;
1529 else if (biosdir2)
1530 level = BDT_LVL1;
1531 else
1532 level = BDT_BOTH;
1533
Elyes Haouas7d67a192022-10-14 09:58:29 +02001534 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001535
1536 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1537 if (!(fw_table[i].level & level))
1538 continue;
1539 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301540 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001541 fw_table[i].type != AMD_BIOS_APOB &&
1542 fw_table[i].type != AMD_BIOS_APOB_NV &&
1543 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001544 fw_table[i].type != AMD_BIOS_BIN &&
1545 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001546 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001547
1548 /* BIOS Directory items may have additional requirements */
1549
Ritul Guru9a321f32022-07-29 11:06:40 +05301550 /* SIG needs a size, else no choice but to skip */
1551 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1552 continue;
1553
Martin Roth48dd9fe2020-07-29 16:32:25 -06001554 /* Check APOB_NV requirements */
1555 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1556 if (!fw_table[i].size && !fw_table[i].src)
1557 continue; /* APOB_NV not used */
1558 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001559 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001560 free(ctx->rom);
1561 exit(1);
1562 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001563 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001564 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001565 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1566 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001567 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001568
1569 /* APOB_DATA needs destination */
1570 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001571 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001572 free(ctx->rom);
1573 exit(1);
1574 }
1575
1576 /* BIOS binary must have destination and uncompressed size. If
1577 * no filename given, then user must provide a source address.
1578 */
1579 if (fw_table[i].type == AMD_BIOS_BIN) {
1580 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001581 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001582 free(ctx->rom);
1583 exit(1);
1584 }
1585 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001586 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001587 free(ctx->rom);
1588 exit(1);
1589 }
1590 }
1591
Martin Roth94554742020-04-14 14:59:36 -06001592 /* PSP_SHARED_MEM needs a destination and size */
1593 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1594 (!fw_table[i].dest || !fw_table[i].size))
1595 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001596 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001597
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001598 biosdir->entries[count].type = fw_table[i].type;
1599 biosdir->entries[count].region_type = fw_table[i].region_type;
1600 biosdir->entries[count].dest = fw_table[i].dest ?
1601 fw_table[i].dest : (uint64_t)-1;
1602 biosdir->entries[count].reset = fw_table[i].reset;
1603 biosdir->entries[count].copy = fw_table[i].copy;
1604 biosdir->entries[count].ro = fw_table[i].ro;
1605 biosdir->entries[count].compressed = fw_table[i].zlib;
1606 biosdir->entries[count].inst = fw_table[i].inst;
1607 biosdir->entries[count].subprog = fw_table[i].subpr;
1608
1609 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301610 case AMD_BIOS_SIG:
1611 /* Reserve size bytes within amdfw.rom */
1612 biosdir->entries[count].size = fw_table[i].size;
1613 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1614 biosdir->entries[count].address_mode =
1615 SET_ADDR_MODE_BY_TABLE(biosdir);
1616 memset(BUFF_CURRENT(*ctx), 0xff,
1617 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001618 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301619 + biosdir->entries[count].size, 0x100U);
1620 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001621 case AMD_BIOS_APOB:
1622 biosdir->entries[count].size = fw_table[i].size;
1623 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001624 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001625 break;
1626 case AMD_BIOS_APOB_NV:
1627 if (fw_table[i].src) {
1628 /* If source is given, use that and its size */
1629 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001630 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001631 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001632 biosdir->entries[count].size = fw_table[i].size;
1633 } else {
1634 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001635 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001636 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001637 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001638 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001639 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001640 fw_table[i].size, ERASE_ALIGNMENT);
1641 memset(BUFF_CURRENT(*ctx), 0xff,
1642 biosdir->entries[count].size);
1643 ctx->current = ctx->current
1644 + biosdir->entries[count].size;
1645 }
1646 break;
1647 case AMD_BIOS_BIN:
1648 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001649 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1650 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001651 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001652 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001653 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001654 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001655 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001656
1657 /* level 2, or level 1 and no copy found in level 2 */
1658 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001659 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001660 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001661 biosdir->entries[count].dest = fw_table[i].dest;
1662 biosdir->entries[count].size = fw_table[i].size;
1663
1664 if (!fw_table[i].filename)
1665 break;
1666
1667 bytes = copy_blob(BUFF_CURRENT(*ctx),
1668 fw_table[i].filename, BUFF_ROOM(*ctx));
1669 if (bytes <= 0) {
1670 free(ctx->rom);
1671 exit(1);
1672 }
1673
Zheng Bao6fff2492021-11-15 19:53:21 +08001674 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001675 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001676 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001677 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001678
Elyes Haouas7d67a192022-10-14 09:58:29 +02001679 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001680 break;
Martin Roth94554742020-04-14 14:59:36 -06001681 case AMD_BIOS_PSP_SHARED_MEM:
1682 biosdir->entries[count].dest = fw_table[i].dest;
1683 biosdir->entries[count].size = fw_table[i].size;
1684 break;
1685
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001686 default: /* everything else is copied from input */
1687 if (fw_table[i].type == AMD_BIOS_APCB ||
1688 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001689 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001690 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001691 bytes = copy_blob(BUFF_CURRENT(*ctx),
1692 fw_table[i].filename, BUFF_ROOM(*ctx));
1693 if (bytes <= 0) {
1694 free(ctx->rom);
1695 exit(1);
1696 }
1697
1698 biosdir->entries[count].size = (uint32_t)bytes;
1699 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001700 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001701
Elyes Haouas7d67a192022-10-14 09:58:29 +02001702 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001703 break;
1704 }
1705
1706 count++;
1707 }
1708
1709 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001710 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001711 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001712 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001713 biosdir->entries[count].size =
1714 + MAX_BIOS_ENTRIES
1715 * sizeof(bios_directory_entry);
1716 biosdir->entries[count].source =
1717 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001718 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001719 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001720 biosdir->entries[count].subprog = 0;
1721 biosdir->entries[count].inst = 0;
1722 biosdir->entries[count].copy = 0;
1723 biosdir->entries[count].compressed = 0;
1724 biosdir->entries[count].dest = -1;
1725 biosdir->entries[count].reset = 0;
1726 biosdir->entries[count].ro = 0;
1727 count++;
1728 }
1729
Zheng Baobf29a0d2020-12-03 23:00:48 +08001730 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001731}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001732
1733enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001734 AMDFW_OPT_CONFIG = 'c',
1735 AMDFW_OPT_DEBUG = 'd',
1736 AMDFW_OPT_HELP = 'h',
1737 AMDFW_OPT_LIST_DEPEND = 'l',
1738
1739 AMDFW_OPT_XHCI = 128,
1740 AMDFW_OPT_IMC,
1741 AMDFW_OPT_GEC,
1742 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001743 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001744 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001745 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001746 AMDFW_OPT_MULTILEVEL,
1747 AMDFW_OPT_NVRAM,
1748
1749 AMDFW_OPT_FUSE,
1750 AMDFW_OPT_UNLOCK,
1751 AMDFW_OPT_WHITELIST,
1752 AMDFW_OPT_USE_PSPSECUREOS,
1753 AMDFW_OPT_LOAD_MP2FW,
1754 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001755 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001756 AMDFW_OPT_VERSTAGE,
1757 AMDFW_OPT_VERSTAGE_SIG,
1758
1759 AMDFW_OPT_INSTANCE,
1760 AMDFW_OPT_APCB,
1761 AMDFW_OPT_APOBBASE,
1762 AMDFW_OPT_BIOSBIN,
1763 AMDFW_OPT_BIOSBIN_SOURCE,
1764 AMDFW_OPT_BIOSBIN_DEST,
1765 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1766 AMDFW_OPT_UCODE,
1767 AMDFW_OPT_APOB_NVBASE,
1768 AMDFW_OPT_APOB_NVSIZE,
1769
1770 AMDFW_OPT_OUTPUT,
1771 AMDFW_OPT_FLASHSIZE,
1772 AMDFW_OPT_LOCATION,
1773 AMDFW_OPT_ANYWHERE,
1774 AMDFW_OPT_SHAREDMEM,
1775 AMDFW_OPT_SHAREDMEM_SIZE,
1776 AMDFW_OPT_SOC_NAME,
Kangheui Won3c164e12021-12-03 20:25:05 +11001777 AMDFW_OPT_SIGNED_OUTPUT,
1778 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001779 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001780 /* begin after ASCII characters */
1781 LONGOPT_SPI_READ_MODE = 256,
1782 LONGOPT_SPI_SPEED = 257,
1783 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301784 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301785 LONGOPT_NVRAM_BASE = 260,
1786 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001787};
1788
Zheng Bao806892a2021-04-27 17:21:54 +08001789static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1790 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1791};
Marc Jones90099b62016-09-20 21:05:45 -06001792
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001793static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001794 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1795 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1796 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001797 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001798 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001799 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001800 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001801 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001802 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1803 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301804 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1805 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001806 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1807 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1808 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1809 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1810 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1811 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001812 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001813 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1814 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001815 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001816 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1817 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1818 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1819 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1820 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1821 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1822 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301823 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001824 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1825 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1826 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001827 /* Embedded Firmware Structure items*/
1828 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1829 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1830 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001831 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001832 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001833 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1834 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1835 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1836 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1837 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1838 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1839 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001840
Kangheui Won3c164e12021-12-03 20:25:05 +11001841 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1842 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1843
Zheng Bao806892a2021-04-27 17:21:54 +08001844 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1845 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1846 {"help", no_argument, 0, AMDFW_OPT_HELP },
1847 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001848 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001849};
1850
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001851void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001852{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001853 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001854
1855 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1856 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1857 continue;
1858
1859 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1860 return;
1861 }
1862}
1863
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001864static void register_fw_token_unlock(void)
1865{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001866 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001867
1868 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1869 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1870 continue;
1871
1872 amd_psp_fw_table[i].other = 1;
1873 return;
1874 }
1875}
1876
Marshall Dawsondbae6322019-03-04 10:31:03 -07001877static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001878{
Martin Roth8806f7f2016-11-08 10:44:18 -07001879 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001880
Martin Rothcd15bc82016-11-08 11:34:02 -07001881 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001882 if (amd_fw_table[i].type == type) {
1883 amd_fw_table[i].filename = filename;
1884 return;
1885 }
1886 }
1887
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001888 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001889 if (amd_psp_fw_table[i].type != type)
1890 continue;
1891
1892 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001893 amd_psp_fw_table[i].filename = filename;
1894 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001895 }
1896 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001897}
1898
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001899static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1900{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001901 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001902
1903 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1904 if (amd_bios_table[i].type == type
1905 && amd_bios_table[i].inst == ins
1906 && amd_bios_table[i].subpr == sub) {
1907 amd_bios_table[i].filename = name;
1908 return;
1909 }
1910 }
1911}
1912
Ritul Gurua2cb3402022-08-29 00:51:08 +05301913static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1914 char *dst_str, char *size_str)
1915{
1916 unsigned int i;
1917
1918 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1919 if (amd_psp_fw_table[i].type != type)
1920 continue;
1921
1922 if (amd_psp_fw_table[i].subprog == sub) {
1923 if (dst_str)
1924 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1925 if (size_str)
1926 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1927 return;
1928 }
1929 }
1930}
1931
1932static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001933 char *dst_str, char *size_str)
1934{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001935 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001936 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1937 if (amd_bios_table[i].type != type)
1938 continue;
1939
1940 if (src_str)
1941 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1942 if (dst_str)
1943 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1944 if (size_str)
1945 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1946
1947 return;
1948 }
1949}
1950
Zheng Baoc3007f32022-04-03 12:53:51 +08001951static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1952 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1953 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001954{
1955 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001956 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001957 return 1;
1958 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001959
1960 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1961 * Leave as 0xffffffff for first gen */
1962 if (cb_config->second_gen) {
1963 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1964 amd_romsig->efs_gen.reserved = 0;
1965 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001966 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1967 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001968 }
1969
1970 switch (soc_id) {
1971 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001972 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1973 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1974 break;
1975 case PLATFORM_RAVEN:
1976 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001977 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1978 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1979 switch (efs_spi_micron_flag) {
1980 case 0:
1981 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1982 break;
1983 case 1:
1984 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1985 break;
1986 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001987 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001988 return 1;
1989 }
1990 break;
1991 case PLATFORM_RENOIR:
1992 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001993 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001994 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001995 case PLATFORM_PHOENIX:
1996 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001997 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1998 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1999 switch (efs_spi_micron_flag) {
2000 case 0:
2001 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
2002 break;
2003 case 1:
2004 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
2005 break;
2006 case 2:
2007 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
2008 break;
2009 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002010 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002011 return 1;
2012 }
2013 break;
2014 case PLATFORM_UNKNOWN:
2015 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002016 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002017 return 1;
2018 }
2019 return 0;
2020}
2021
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002022static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
2023{
2024 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
2025 int ret;
2026 int fd;
2027 ssize_t bytes = -1;
2028
2029 /* Create a tmp file and rename it at the end so that make does not get confused
2030 if amdfwtool is killed for some unexpected reasons. */
2031 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
2032 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
2033 if (ret < 0) {
2034 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
2035 strerror(errno), ret);
2036 exit(1);
2037 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
2038 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
2039 exit(1);
2040 }
2041
2042 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
2043 if (fd < 0) {
2044 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
2045 exit(1);
2046 }
2047
2048 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
2049 if (bytes != sizeof(*amd_romsig)) {
2050 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
2051 exit(1);
2052 }
2053 close(fd);
2054
2055 /* Rename the tmp file */
2056 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
2057 if (ret < 0) {
2058 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
2059 exit(1);
2060 }
2061
2062 if (rename(efs_tmp_name, efs_name)) {
2063 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
2064 exit(1);
2065 }
2066
2067 return bytes;
2068}
2069
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002070static int identify_platform(char *soc_name)
2071{
2072 if (!strcasecmp(soc_name, "Stoneyridge"))
2073 return PLATFORM_STONEYRIDGE;
2074 else if (!strcasecmp(soc_name, "Raven"))
2075 return PLATFORM_RAVEN;
2076 else if (!strcasecmp(soc_name, "Picasso"))
2077 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002078 else if (!strcasecmp(soc_name, "Cezanne"))
2079 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08002080 else if (!strcasecmp(soc_name, "Mendocino"))
2081 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002082 else if (!strcasecmp(soc_name, "Renoir"))
2083 return PLATFORM_RENOIR;
2084 else if (!strcasecmp(soc_name, "Lucienne"))
2085 return PLATFORM_LUCIENNE;
Martin Roth20646cd2023-01-04 21:27:06 -07002086 else if (!strcasecmp(soc_name, "Phoenix"))
2087 return PLATFORM_PHOENIX;
Martin Roth13490832022-10-06 17:18:02 -06002088 else if (!strcasecmp(soc_name, "Glinda"))
2089 return PLATFORM_GLINDA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002090 else
2091 return PLATFORM_UNKNOWN;
2092
2093}
2094
Felix Heldf8e2e472022-03-29 23:28:49 +02002095static bool needs_ish(enum platform platform_type)
2096{
Zheng Baode6f1982022-10-16 20:32:43 +08002097 if (platform_type == PLATFORM_MENDOCINO || platform_type == PLATFORM_PHOENIX || platform_type == PLATFORM_GLINDA)
Felix Heldf8e2e472022-03-29 23:28:49 +02002098 return true;
2099 else
2100 return false;
2101}
2102
Zheng Baoc3007f32022-04-03 12:53:51 +08002103static bool is_second_gen(enum platform platform_type)
2104{
2105 switch (platform_type) {
2106 case PLATFORM_STONEYRIDGE:
2107 case PLATFORM_RAVEN:
2108 case PLATFORM_PICASSO:
2109 return false;
2110 case PLATFORM_RENOIR:
2111 case PLATFORM_LUCIENNE:
2112 case PLATFORM_CEZANNE:
Jon Murphy9969f4b2022-08-05 13:56:38 -06002113 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002114 case PLATFORM_PHOENIX:
2115 case PLATFORM_GLINDA:
Zheng Baoc3007f32022-04-03 12:53:51 +08002116 return true;
2117 case PLATFORM_UNKNOWN:
2118 default:
2119 fprintf(stderr, "Error: Invalid SOC name.\n\n");
2120 return false;
2121 }
2122}
2123
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002124int main(int argc, char **argv)
2125{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002126 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002127 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002128 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002129 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002130 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002131 psp_directory_table *pspdir = NULL;
2132 psp_directory_table *pspdir2 = NULL;
2133 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08002134 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002135 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002136 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002137 char *output = NULL, *config = NULL;
2138 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002139 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002140 /* Values cleared after each firmware or parameter, regardless if N/A */
2141 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08002142 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002143 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002144 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002145 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002146 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002147 uint8_t soc_id = PLATFORM_UNKNOWN;
2148 uint8_t efs_spi_readmode = 0xff;
2149 uint8_t efs_spi_speed = 0xff;
2150 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002151 const char *signed_output_file = NULL;
2152 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002153
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002154 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002155 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002156 int list_deps = 0;
2157
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002158 while (1) {
2159 int optindex = 0;
2160
2161 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2162
2163 if (c == -1)
2164 break;
2165
2166 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002167 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002168 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002169 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002170 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002171 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002172 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002173 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002174 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002175 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002176 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002177 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002178 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002179 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002180 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07002181 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002182 case AMDFW_OPT_RECOVERY_AB:
2183 cb_config.recovery_ab = true;
2184 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002185 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2186 cb_config.recovery_ab = true;
2187 cb_config.recovery_ab_single_copy = true;
2188 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002189 case AMDFW_OPT_USE_COMBO:
2190 cb_config.use_combo = true;
2191 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002192 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002193 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002194 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002195 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002196 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002197 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002198 sub = instance = 0;
2199 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002200 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002201 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002202 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002203 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002204 instance = strtoul(optarg, &tmp, 16);
2205 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002206 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002207 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002208 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002209 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002210 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002211 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002212 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002213 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002214 register_fw_fuse(optarg);
2215 fuse_defined = 1;
2216 sub = 0;
2217 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002218 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002219 if ((instance & 0xF0) == 0)
2220 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2221 else
2222 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2223 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002224 sub = instance = 0;
2225 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002226 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002227 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302228 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002229 sub = instance = 0;
2230 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002231 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002232 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302233 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002234 sub = instance = 0;
2235 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002236 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002237 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302238 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002239 sub = instance = 0;
2240 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002241 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002242 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2243 sub = instance = 0;
2244 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002245 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002246 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302247 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002248 sub = instance = 0;
2249 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002250 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002251 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302252 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002253 sub = instance = 0;
2254 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002255 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002256 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302257 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002258 sub = instance = 0;
2259 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302260 case LONGOPT_BIOS_SIG:
2261 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302262 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302263 sub = instance = 0;
2264 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002265 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002266 register_bdt_data(AMD_BIOS_UCODE, sub,
2267 instance, optarg);
2268 sub = instance = 0;
2269 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002270 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002271 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002272 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002273 case AMDFW_OPT_SPL_TABLE:
2274 register_fw_filename(AMD_FW_SPL, sub, optarg);
2275 sub = instance = 0;
2276 cb_config.have_mb_spl = true;
2277 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002278 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002279 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2280 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002281 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002282 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002283 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002284 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2285 sub = instance = 0;
2286 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002287 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002288 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2289 sub = instance = 0;
2290 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002291 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002292 soc_id = identify_platform(optarg);
2293 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002294 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002295 retval = 1;
2296 }
2297 sub = instance = 0;
2298 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002299 case AMDFW_OPT_SIGNED_OUTPUT:
2300 signed_output_file = optarg;
2301 sub = instance = 0;
2302 break;
2303 case AMDFW_OPT_SIGNED_ADDR:
2304 signed_start_addr = strtoull(optarg, NULL, 10);
2305 sub = instance = 0;
2306 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002307 case LONGOPT_SPI_READ_MODE:
2308 efs_spi_readmode = strtoull(optarg, NULL, 16);
2309 sub = instance = 0;
2310 break;
2311 case LONGOPT_SPI_SPEED:
2312 efs_spi_speed = strtoull(optarg, NULL, 16);
2313 sub = instance = 0;
2314 break;
2315 case LONGOPT_SPI_MICRON_FLAG:
2316 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2317 sub = instance = 0;
2318 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002319 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002320 output = optarg;
2321 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002322 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002323 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002324 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002325 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002326 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002327 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002328 }
2329 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002330 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002331 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002332 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002333 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002334 " incorrectly (%s)\n\n", optarg);
2335 retval = 1;
2336 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002337 if (body_location == 0)
2338 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002339 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002340 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002341 any_location = 1;
2342 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002343 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002344 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302345 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002346 sub = instance = 0;
2347 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002348 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002349 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302350 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002351 sub = instance = 0;
2352 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302353 case LONGOPT_NVRAM_BASE:
2354 /* PSP NV base */
2355 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2356 sub = instance = 0;
2357 break;
2358 case LONGOPT_NVRAM_SIZE:
2359 /* PSP NV size */
2360 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2361 sub = instance = 0;
2362 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002363 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002364 config = optarg;
2365 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002366 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002367 debug = 1;
2368 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002369 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002370 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002371 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002372 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002373 list_deps = 1;
2374 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002375 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002376 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002377 if (*tmp != '\0') {
2378 fprintf(stderr, "Error: Body Location specified"
2379 " incorrectly (%s)\n\n", optarg);
2380 retval = 1;
2381 }
2382 break;
2383
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002384 default:
2385 break;
2386 }
2387 }
2388
Zheng Baoc3007f32022-04-03 12:53:51 +08002389 cb_config.second_gen = is_second_gen(soc_id);
2390
Felix Heldf8e2e472022-03-29 23:28:49 +02002391 if (needs_ish(soc_id))
2392 cb_config.need_ish = true;
2393
Felix Held830add62022-03-29 23:28:10 +02002394 if (cb_config.need_ish)
2395 cb_config.recovery_ab = true;
2396
2397 if (cb_config.recovery_ab)
2398 cb_config.multi_level = true;
2399
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002400 if (config) {
2401 config_handle = fopen(config, "r");
2402 if (config_handle == NULL) {
2403 fprintf(stderr, "Can not open file %s for reading: %s\n",
2404 config, strerror(errno));
2405 exit(1);
2406 }
2407 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2408 fprintf(stderr, "Configuration file %s parsing error\n", config);
2409 fclose(config_handle);
2410 exit(1);
2411 }
2412 fclose(config_handle);
2413 }
Zheng Bao9e908072020-10-28 11:39:13 +08002414 /* For debug. */
2415 if (debug) {
2416 dump_psp_firmwares(amd_psp_fw_table);
2417 dump_bdt_firmwares(amd_bios_table);
2418 }
2419
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002420 if (!fuse_defined)
2421 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2422
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002423 if (!output && !list_deps) {
2424 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002425 retval = 1;
2426 }
2427
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002428 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2429 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002430 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002431 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002432 }
2433
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002434 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2435 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002436 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002437 retval = 1;
2438 }
2439
2440 if (retval) {
2441 usage();
2442 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002443 }
2444
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002445 if (list_deps) {
2446 return retval;
2447 }
2448
Marshall Dawson2794a862019-03-04 16:53:15 -07002449 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002450
Marshall Dawson2794a862019-03-04 16:53:15 -07002451 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002452 if (efs_location && (efs_location < rom_base_address)) {
2453 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2454 return 1;
2455 }
2456
Zheng Bao99945dc2023-01-02 10:55:56 +08002457 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002458 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2459 return 1;
2460 }
2461
2462 /*
2463 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2464 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2465 * currently. This condition is to ensure that it is not accidentally split. Revisit
2466 * this condition if such a need arises in the future.
2467 */
Zheng Bao99945dc2023-01-02 10:55:56 +08002468 if (!any_location && body_location != efs_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002469 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2470 return 1;
2471 }
2472
Zheng Bao99945dc2023-01-02 10:55:56 +08002473 if (body_location != efs_location &&
2474 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002475 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2476 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002477 return 1;
2478 }
2479
Martin Roth37305e72020-04-07 14:16:39 -06002480 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002481 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002482 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002483 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002484 return 1;
2485 }
2486 } else {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002487 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002488 case 0:
2489 case 0xFFFA0000:
2490 case 0xFFF20000:
2491 case 0xFFE20000:
2492 case 0xFFC20000:
2493 case 0xFF820000:
2494 case 0xFF020000:
Martin Roth37305e72020-04-07 14:16:39 -06002495 break;
2496 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002497 fprintf(stderr, "Error: Invalid Directory location.\n");
2498 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2499 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002500 return 1;
2501 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002502 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002503 ctx.rom = malloc(ctx.rom_size);
2504 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002505 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002506 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002507 }
2508 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002509
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002510 if (efs_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002511 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002512 romsig_offset = efs_location - rom_base_address;
Zheng Bao99945dc2023-01-02 10:55:56 +08002513 ctx.current = body_location - rom_base_address;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002514 } else {
2515 romsig_offset = efs_location - rom_base_address;
2516 ctx.current = romsig_offset + sizeof(embedded_firmware);
2517 }
2518 } else {
2519 romsig_offset = AMD_ROMSIG_OFFSET;
2520 ctx.current = romsig_offset + sizeof(embedded_firmware);
2521 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002522
Marshall Dawson2794a862019-03-04 16:53:15 -07002523 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002524 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2525 amd_romsig->imc_entry = 0;
2526 amd_romsig->gec_entry = 0;
2527 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002528
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002529 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08002530 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08002531 efs_spi_speed, efs_spi_micron_flag);
2532 if (retval) {
2533 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2534 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002535 }
2536 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002537 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002538 }
2539
Felix Held21a8e382022-03-29 23:10:45 +02002540 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002541 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002542 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002543 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002544 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002545 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002546 printf(" AMDFWTOOL Using firmware directory location of %s address: 0x%08x\n",
Robert Zieba29bc79f2022-03-14 15:59:12 -06002547 ctx.address_mode == AMD_ADDR_PHYSICAL ? "absolute" : "relative",
Zheng Bao6fff2492021-11-15 19:53:21 +08002548 RUN_CURRENT(ctx));
Zheng Baoda83d2c2021-06-04 19:03:10 +08002549
Marshall Dawson2794a862019-03-04 16:53:15 -07002550 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002551
Elyes Haouas7d67a192022-10-14 09:58:29 +02002552 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002553 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002554
Kangheui Won3c164e12021-12-03 20:25:05 +11002555 /* If the tool is invoked with command-line options to keep the signed PSP
2556 binaries separate, process the signed binaries first. */
2557 if (signed_output_file && signed_start_addr)
2558 process_signed_psp_firmwares(signed_output_file,
2559 amd_psp_fw_table,
2560 signed_start_addr,
2561 soc_id);
2562
Zheng Bao481661e2021-08-20 14:47:46 +08002563 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002564 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002565 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2566 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002567 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002568 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2569 /* Create a copy of PSP Directory 2 in the backup slot B.
2570 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002571 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2572 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002573 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002574 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002575 /*
2576 * Either the platform is using only one slot or B is same as above
2577 * directories for A. Skip creating pspdir2_b here to save flash space.
2578 * Related biosdir2_b will be skipped automatically.
2579 */
Zheng Bao990d1542021-09-17 13:24:54 +08002580 pspdir2_b = NULL; /* More explicitly */
2581 }
Zheng Bao481661e2021-08-20 14:47:46 +08002582 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002583 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002584 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002585 } else {
2586 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002587 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002588 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002589 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002590 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002591
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002592 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08002593 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07002594 else
Felix Heldad68b072021-10-18 14:00:35 +02002595 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002596
Zheng Bao993b43f2021-11-10 12:21:46 +08002597 if (cb_config.use_combo) {
2598 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2599 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2600 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2601 combo_dir->entries[0].id_sel = 0;
2602 combo_dir->entries[0].id = get_psp_id(soc_id);
2603 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002604
Zheng Bao993b43f2021-11-10 12:21:46 +08002605 combo_dir->header.lookup = 1;
2606 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2607 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002608
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002609 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002610 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002611 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002612 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002613 bios_directory_table *biosdir2 = NULL;
2614 bios_directory_table *biosdir2_b = NULL;
2615
2616 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2617
Zheng Baoedd1e362021-11-04 17:47:07 +08002618 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002619 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002620 if (cb_config.recovery_ab) {
2621 if (pspdir2_b != NULL) {
2622 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2623 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002624 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002625 }
2626 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2627 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2628 if (pspdir2_b != NULL)
2629 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2630 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2631 } else {
2632 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2633 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002634 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002635 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002636 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002637 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002638 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002639 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002640 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002641 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08002642 switch (soc_id) {
2643 case PLATFORM_RENOIR:
2644 case PLATFORM_LUCIENNE:
2645 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002646 if (!cb_config.recovery_ab)
2647 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002648 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002649 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002650 case PLATFORM_PHOENIX:
2651 case PLATFORM_GLINDA:
Zheng Bao535ec532021-08-12 16:30:19 +08002652 break;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002653 case PLATFORM_STONEYRIDGE:
2654 case PLATFORM_RAVEN:
2655 case PLATFORM_PICASSO:
2656 default:
2657 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2658 break;
2659 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002660 }
2661
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002662 /* Free the filename. */
2663 free_psp_firmware_filenames(amd_psp_fw_table);
2664 free_bdt_firmware_filenames(amd_bios_table);
2665
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002666 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002667 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002668 ssize_t bytes;
Zheng Bao99945dc2023-01-02 10:55:56 +08002669 uint32_t offset = body_location ? body_location - rom_base_address : AMD_ROMSIG_OFFSET;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002670
2671 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2672 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002673 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2674 retval = 1;
2675 }
Martin Roth31d95a22016-11-08 11:22:12 -07002676 close(targetfd);
2677 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002678 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002679 retval = 1;
2680 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002681
Zheng Bao99945dc2023-01-02 10:55:56 +08002682 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002683 ssize_t bytes;
2684
2685 bytes = write_efs(output, amd_romsig);
2686 if (bytes != sizeof(*amd_romsig)) {
2687 fprintf(stderr, "Error: Writing EFS\n");
2688 retval = 1;
2689 }
2690 }
2691
Martin Roth31d95a22016-11-08 11:22:12 -07002692 free(rom);
2693 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002694}