blob: b23ee4701d90e0f93a474a6d980b38a57a8e6c9f [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
4 * ROMSIG At ROMBASE + 0x20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
zbaoc3b0b722016-02-19 13:47:31 +08009 * | PSPDIR ADDR|PSPDIR ADDR |<-- Field 0x14 could be either
10 * +------------+---------------+ 2nd PSP directory or PSP COMBO directory
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080011 * EC ROM should be 64K aligned.
12 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080013 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080014 * +------------+---------------+----------------+------------+
15 * | 'PSP$' | Fletcher | Count | Reserved |
16 * +------------+---------------+----------------+------------+
17 * | 0 | size | Base address | Reserved | Pubkey
18 * +------------+---------------+----------------+------------+
19 * | 1 | size | Base address | Reserved | Bootloader
20 * +------------+---------------+----------------+------------+
21 * | 8 | size | Base address | Reserved | Smu Firmware
22 * +------------+---------------+----------------+------------+
23 * | 3 | size | Base address | Reserved | Recovery Firmware
24 * +------------+---------------+----------------+------------+
25 * | |
26 * | |
27 * | Other PSP Firmware |
28 * | |
29 * | |
30 * +------------+---------------+----------------+------------+
Zheng Bao4fcc9f22015-11-20 12:29:04 +080031 *
zbaoc3b0b722016-02-19 13:47:31 +080032 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080033 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080034 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080035 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080036 * | R e s e r v e d |
37 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080038 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080039 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080040 * | ID-Sel | PSP ID | PSPDIR ADDR | | 3rd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080041 * +------------+---------------+----------------+------------+
42 * | |
43 * | Other PSP |
44 * | |
45 * +------------+---------------+----------------+------------+
46 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080047 */
48
Elyes Haouas7d67a192022-10-14 09:58:29 +020049#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080050#include <fcntl.h>
51#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060052#include <limits.h>
Kangheui Won5b84dfd2021-12-21 15:45:06 +110053#include <openssl/sha.h>
Martin Roth37305e72020-04-07 14:16:39 -060054#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080055#include <stdio.h>
56#include <sys/stat.h>
57#include <sys/types.h>
58#include <unistd.h>
59#include <string.h>
60#include <stdlib.h>
61#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080062#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010063#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080064
65#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080066
Martin Roth60f15512016-11-08 09:55:01 -070067#define AMD_ROMSIG_OFFSET 0x20000
68#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080069
Marshall Dawson7c1e1422019-04-11 09:44:43 -060070#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
71#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070072#define TABLE_ALIGNMENT 0x1000U
73#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060074#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060075#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080076
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060077#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
78
Kangheui Won5b84dfd2021-12-21 15:45:06 +110079/* Defines related to hashing signed binaries */
80enum hash_header_ver {
81 HASH_HDR_V1 = 1,
82};
83/* Signature ID enums are defined by PSP based on the algorithm used. */
84enum signature_id {
85 SIG_ID_RSA2048,
86 SIG_ID_RSA4096 = 2,
87};
88#define HASH_FILE_SUFFIX ".hash"
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060089#define EFS_FILE_SUFFIX ".efs"
90#define TMP_FILE_SUFFIX ".tmp"
Kangheui Won5b84dfd2021-12-21 15:45:06 +110091
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -070093 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
94 * can support an optional "combo" implementation. If the PSP sees the
95 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
96 * tables. Using this, support for multiple product generations may be
97 * built into one image. If the PSP$ cookie is found, the table is a
98 * normal directory table.
99 *
100 * Modern generations supporting the combo directories require the
101 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
102 * regardless of the type of directory used. The --combo-capable
103 * argument enforces this placement.
104 *
105 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800106 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800107
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800108/*
109 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
110 * The checksum field of the passed PDU does not need to be reset to zero.
111 *
112 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
113 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
114 * alternative to cyclical redundancy checks because it provides error-
115 * detection properties similar to cyclical redundancy checks but at the
116 * cost of a simple summation technique. Its characteristics were first
117 * published in IEEE Transactions on Communications in January 1982. One
118 * version has been adopted by ISO for use in the class-4 transport layer
119 * of the network protocol.
120 *
121 * This program expects:
122 * stdin: The input file to compute a checksum for. The input file
123 * not be longer than 256 bytes.
124 * stdout: Copied from the input file with the Fletcher's Checksum
125 * inserted 8 bytes after the beginning of the file.
126 * stderr: Used to print out error messages.
127 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700128static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800129{
130 uint32_t c0;
131 uint32_t c1;
132 uint32_t checksum;
133 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700134 const uint16_t *pptr = data;
135
136 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800137
138 c0 = 0xFFFF;
139 c1 = 0xFFFF;
140
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600141 while (length) {
142 index = length >= 359 ? 359 : length;
143 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800144 do {
145 c0 += *(pptr++);
146 c1 += c0;
147 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600148 c0 = (c0 & 0xFFFF) + (c0 >> 16);
149 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800150 }
151
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700152 /* Sums[0,1] mod 64K + overflow */
153 c0 = (c0 & 0xFFFF) + (c0 >> 16);
154 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800155 checksum = (c1 << 16) | c0;
156
157 return checksum;
158}
159
Martin Roth8806f7f2016-11-08 10:44:18 -0700160static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800161{
Martin Roth0e940622016-11-08 10:37:53 -0700162 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800163 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
164 printf("--xhci <FILE> Add XHCI blob\n");
165 printf("--imc <FILE> Add IMC blob\n");
166 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700167
168 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800169 printf("--combo-capable Place PSP directory pointer at Embedded\n");
170 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700171 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800172 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800173 printf("--multilevel Generate primary and secondary tables\n");
174 printf("--nvram <FILE> Add nvram binary\n");
175 printf("--soft-fuse Set soft fuse\n");
176 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530177 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
178 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800179 printf("--whitelist Set if there is a whitelist\n");
180 printf("--use-pspsecureos Set if psp secure OS is needed\n");
181 printf("--load-mp2-fw Set if load MP2 firmware\n");
182 printf("--load-s0i3 Set if load s0i3 firmware\n");
183 printf("--verstage <FILE> Add verstage\n");
184 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800185 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600186 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800187 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800188 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800189 printf("--apcb <FILE> Add AGESA PSP customization block\n");
190 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
191 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
192 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
193 printf("--ucode <FILE> Add microcode patch\n");
194 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
195 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
196 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
197 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
198 printf("--output <filename> output filename\n");
199 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600200 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700201 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600202 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800203 printf("--location Location of Directory\n");
204 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
205 printf("--sharedmem Location of PSP/FW shared memory\n");
206 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800207 printf(" area\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800208 printf("--soc-name <socname> Specify SOC name. Supported names are\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800209 printf(" Stoneyridge, Raven, Picasso, Renoir, Cezanne\n");
Martin Roth20646cd2023-01-04 21:27:06 -0700210 printf(" Mendocino, Phoenix, Glinda, or Lucienne\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500211 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
212 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
213 printf(" 0x0 66.66Mhz\n");
214 printf(" 0x1 33.33MHz\n");
215 printf(" 0x2 22.22MHz\n");
216 printf(" 0x3 16.66MHz\n");
217 printf(" 0x4 100MHz\n");
218 printf(" 0x5 800KHz\n");
219 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
220 printf(" 0x0 Normal Read (up to 33M)\n");
221 printf(" 0x1 Reserved\n");
222 printf(" 0x2 Dual IO (1-1-2)\n");
223 printf(" 0x3 Quad IO (1-1-4)\n");
224 printf(" 0x4 Dual IO (1-2-2)\n");
225 printf(" 0x5 Quad IO (1-4-4)\n");
226 printf(" 0x6 Normal Read (up to 66M)\n");
227 printf(" 0x7 Fast Read\n");
228 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
229 printf(" 0x0 Micron parts are not used\n");
230 printf(" 0x1 Micron parts are always used\n");
231 printf(" 0x2 Micron parts optional, this option is only\n");
232 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800233 printf("\nGeneral options:\n");
234 printf("-c|--config <config file> Config file\n");
235 printf("-d|--debug Print debug message\n");
236 printf("-l|--list List out the firmware files\n");
237 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800238}
239
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800240amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100241 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800242 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800243 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200244 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800245 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200246 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
247 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
248 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800249 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100250 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
251 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200252 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200253 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800254 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
255 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800256 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200257 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
258 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800259 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
260 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
261 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
262 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800263 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
264 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100265 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800266 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
267 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800268 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200269 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800270 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200271 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
272 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800273 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
274 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200275 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
276 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
277 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800278 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800279 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
280 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
281 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
283 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
286 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200287 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
288 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600289 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200290 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200291 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200292 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
293 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
294 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
295 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
296 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600297 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
298 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200299 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
300 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
301 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
302 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
303 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800305 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_BOTH_AB },
306 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200307 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
308 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800309 { .type = AMD_RIB, .level = PSP_LVL2 | PSP_BOTH_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200310 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200311 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200312 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
313 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800314 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
315 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
316 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
317 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
318 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
319 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
321 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
322 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
325 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
326 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
327 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800328 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800329};
330
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800331amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800332 { .type = AMD_FW_XHCI },
333 { .type = AMD_FW_IMC },
334 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800335 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800336};
337
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800338amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800339 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530340 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600341 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
342 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
343 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
344 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
345 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700346 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
347 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
348 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
349 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
350 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
351 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
352 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
353 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
355 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
356 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700357 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
361 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700362 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600373 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
374 { .type = AMD_BIOS_BIN,
375 .reset = 1, .copy = 1, .zlib = 1, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
377 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
378 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800379 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
380 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200381 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
382 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600383 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
384 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800385 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
386 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
387 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
388 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
389 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
390 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200391 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
392 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
393 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
394 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800395 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
396 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
397 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
398 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
399 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
400 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600401 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800403 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200405 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600407 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800409 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200415 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800419 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600425 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
426 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
427 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200428 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
429 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
430 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
431 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600432 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600433 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600434 { .type = AMD_BIOS_INVALID },
435};
436
Marshall Dawson2794a862019-03-04 16:53:15 -0700437typedef struct _context {
438 char *rom; /* target buffer, size of flash device */
439 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800440 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700441 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800442 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700443} context;
444
445#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800446#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600447 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
448 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
449 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800450#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600451#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800452 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700453#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800454/* The mode in entry can not be higher than the header's.
455 For example, if table mode is 0, all the entry mode will be 0. */
456#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
457 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700458#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
459#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
460#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800461#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
462 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700463#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800464/* Only set the address mode in entry if the table is mode 2. */
465#define SET_ADDR_MODE(table, mode) \
466 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600467 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800468#define SET_ADDR_MODE_BY_TABLE(table) \
469 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700470
Zheng Bao5164e4b2021-10-30 12:09:07 +0800471void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
472{
473 if (count >= max) {
474 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
475 "(%d)\n", count, max);
476 free(ctx->rom);
477 exit(1);
478 }
479}
480
Marshall Dawson24f73d42019-04-01 10:48:43 -0600481static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700482{
483 void *ptr;
484
Marshall Dawson24f73d42019-04-01 10:48:43 -0600485 /*
486 * Force both onto boundary when multi. Primary table is after
487 * updatable table, so alignment ensures primary can stay intact
488 * if secondary is reprogrammed.
489 */
490 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200491 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600492 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200493 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600494
Marshall Dawson2794a862019-03-04 16:53:15 -0700495 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800496 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800497 ((psp_directory_header *)ptr)->additional_info = 0;
498 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700499 ctx->current += sizeof(psp_directory_header)
500 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
501 return ptr;
502}
503
Zheng Baofdd47ef2021-09-17 13:30:08 +0800504static void *new_ish_dir(context *ctx)
505{
506 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200507 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800508 ptr = BUFF_CURRENT(*ctx);
509 ctx->current += TABLE_ALIGNMENT;
510 return ptr;
511}
512
Marshall Dawson2794a862019-03-04 16:53:15 -0700513static void *new_combo_dir(context *ctx)
514{
515 void *ptr;
516
Elyes Haouas7d67a192022-10-14 09:58:29 +0200517 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700518 ptr = BUFF_CURRENT(*ctx);
519 ctx->current += sizeof(psp_combo_header)
520 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
521 return ptr;
522}
523
Zheng Baobf29a0d2020-12-03 23:00:48 +0800524static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800525{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600526 psp_combo_directory *cdir = directory;
527 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600528 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800529 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600530
531 if (!count)
532 return;
Zheng Baob035f582021-05-27 11:26:12 +0800533 if (ctx == NULL || directory == NULL) {
534 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
535 return;
536 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600537
Zheng Baobf29a0d2020-12-03 23:00:48 +0800538 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200539 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800540
Marshall Dawson24f73d42019-04-01 10:48:43 -0600541 switch (cookie) {
542 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700543 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700544 cdir->header.cookie = cookie;
545 cdir->header.num_entries = count;
546 cdir->header.reserved[0] = 0;
547 cdir->header.reserved[1] = 0;
548 /* checksum everything that comes after the Checksum field */
549 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
550 count * sizeof(psp_combo_entry)
551 + sizeof(cdir->header.num_entries)
552 + sizeof(cdir->header.lookup)
553 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600554 break;
555 case PSP_COOKIE:
556 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800557 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800558 if ((table_size % TABLE_ALIGNMENT) != 0) {
559 fprintf(stderr, "The PSP table size should be 4K aligned\n");
560 exit(1);
561 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700562 dir->header.cookie = cookie;
563 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800564 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
565 dir->header.additional_info_fields.spi_block_size = 1;
566 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700567 /* checksum everything that comes after the Checksum field */
568 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700569 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700570 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800571 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600572 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800573 case BHD_COOKIE:
574 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800575 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800576 if ((table_size % TABLE_ALIGNMENT) != 0) {
577 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
578 exit(1);
579 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600580 bdir->header.cookie = cookie;
581 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800582 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
583 bdir->header.additional_info_fields.spi_block_size = 1;
584 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600585 /* checksum everything that comes after the Checksum field */
586 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
587 count * sizeof(bios_directory_entry)
588 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800589 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600590 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700591 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800592
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800593}
594
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700595static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
596{
597 int fd;
598 struct stat fd_stat;
599 ssize_t bytes;
600
601 fd = open(src_file, O_RDONLY);
602 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800603 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700604 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700605 return -1;
606 }
607
608 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800609 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600610 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700611 return -2;
612 }
613
Zheng Bao6d402ac2020-10-01 16:16:30 +0800614 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800615 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600616 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700617 return -3;
618 }
619
620 bytes = read(fd, dest, (size_t)fd_stat.st_size);
621 close(fd);
622 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800623 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700624 return -4;
625 }
626
627 return bytes;
628}
629
Kangheui Won3c164e12021-12-03 20:25:05 +1100630static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
631{
632 ssize_t bytes;
633 size_t total_bytes = 0;
634
635 do {
636 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
637 if (bytes == 0) {
638 fprintf(stderr, "Reached EOF probably\n");
639 break;
640 }
641
642 if (bytes < 0 && errno == EAGAIN)
643 bytes = 0;
644
645 if (bytes < 0) {
646 fprintf(stderr, "Read failure %s\n", strerror(errno));
647 return bytes;
648 }
649
650 total_bytes += bytes;
651 } while (total_bytes < buf_size);
652
653 if (total_bytes != buf_size) {
654 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
655 total_bytes, buf_size);
656 return -1;
657 }
658 return buf_size;
659}
660
661static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
662{
663 ssize_t bytes;
664 size_t total_bytes = 0;
665
666 do {
667 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
668 if (bytes < 0 && errno == EAGAIN)
669 bytes = 0;
670
671 if (bytes < 0) {
672 fprintf(stderr, "Write failure %s\n", strerror(errno));
673 lseek(fd, SEEK_CUR, -total_bytes);
674 return bytes;
675 }
676
677 total_bytes += bytes;
678 } while (total_bytes < buf_size);
679
680 if (total_bytes != buf_size) {
681 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
682 total_bytes, buf_size);
683 lseek(fd, SEEK_CUR, -total_bytes);
684 return -1;
685 }
686
687 return buf_size;
688}
689
Zheng Baoeb0404e2021-10-14 15:09:09 +0800690enum platform {
691 PLATFORM_UNKNOWN,
692 PLATFORM_STONEYRIDGE,
693 PLATFORM_RAVEN,
694 PLATFORM_PICASSO,
695 PLATFORM_RENOIR,
696 PLATFORM_CEZANNE,
697 PLATFORM_MENDOCINO,
698 PLATFORM_LUCIENNE,
Martin Roth20646cd2023-01-04 21:27:06 -0700699 PLATFORM_PHOENIX,
Martin Roth13490832022-10-06 17:18:02 -0600700 PLATFORM_GLINDA
Zheng Baoeb0404e2021-10-14 15:09:09 +0800701};
702
703static uint32_t get_psp_id(enum platform soc_id)
704{
705 uint32_t psp_id;
706 switch (soc_id) {
707 case PLATFORM_RAVEN:
708 case PLATFORM_PICASSO:
709 psp_id = 0xBC0A0000;
710 break;
711 case PLATFORM_RENOIR:
712 case PLATFORM_LUCIENNE:
713 psp_id = 0xBC0C0000;
714 break;
715 case PLATFORM_CEZANNE:
716 psp_id = 0xBC0C0140;
717 break;
718 case PLATFORM_MENDOCINO:
719 psp_id = 0xBC0D0900;
720 break;
721 case PLATFORM_STONEYRIDGE:
722 psp_id = 0x10220B00;
723 break;
724 default:
725 psp_id = 0;
726 break;
727 }
728 return psp_id;
729}
730
Kangheui Won3c164e12021-12-03 20:25:05 +1100731static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
732{
733 switch (soc_id) {
734 case PLATFORM_MENDOCINO:
735 /* Fallback to fw_type if fw_id is not populated, which serves the same
736 purpose on older SoCs. */
737 return header->fw_id ? header->fw_id : header->fw_type;
738 default:
739 return header->fw_type;
740 }
741}
742
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100743static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
744{
745 uint8_t hash[SHA384_DIGEST_LENGTH];
746 struct amd_fw_header *header = (struct amd_fw_header *)buf;
747 /* Include only signed part for hash calculation. */
748 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
749 uint8_t *body = (uint8_t *)buf;
750
751 if (len > header->size_total)
752 return -1;
753
754 if (header->sig_id == SIG_ID_RSA4096) {
755 SHA384(body, len, hash);
756 entry->sha_len = SHA384_DIGEST_LENGTH;
757 } else if (header->sig_id == SIG_ID_RSA2048) {
758 SHA256(body, len, hash);
759 entry->sha_len = SHA256_DIGEST_LENGTH;
760 } else {
761 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
762 __func__, header->sig_id);
763 return -1;
764 }
765
766 memcpy(entry->sha, hash, entry->sha_len);
767 entry->fw_id = get_psp_fw_type(soc_id, header);
768 entry->subtype = header->fw_subtype;
769
770 return 0;
771}
772
773static int get_num_binaries(void *buf, size_t buf_size)
774{
775 struct amd_fw_header *header = (struct amd_fw_header *)buf;
776 size_t total_len = 0;
777 int num_binaries = 0;
778
779 while (total_len < buf_size) {
780 num_binaries++;
781 total_len += header->size_total;
782 header = (struct amd_fw_header *)(buf + total_len);
783 }
784
785 if (total_len != buf_size) {
786 fprintf(stderr, "Malformed binary\n");
787 return -1;
788 }
789 return num_binaries;
790}
791
792static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
793{
794 struct amd_fw_header *header = (struct amd_fw_header *)buf;
795 /* Include only signed part for hash calculation. */
796 size_t total_len = 0;
797 int num_binaries = get_num_binaries(buf, buf_size);
798
799 if (num_binaries <= 0)
800 return num_binaries;
801
802 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
803 if (!entry->hash_entries) {
804 fprintf(stderr, "Error allocating memory to add FW hash\n");
805 return -1;
806 }
807 entry->num_hash_entries = num_binaries;
808
809 /* Iterate through each binary */
810 for (int i = 0; i < num_binaries; i++) {
811 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
812 free(entry->hash_entries);
813 return -1;
814 }
815 total_len += header->size_total;
816 header = (struct amd_fw_header *)(buf + total_len);
817 }
818
819 return 0;
820}
821
Marshall Dawson2794a862019-03-04 16:53:15 -0700822static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700823 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700824 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800825{
Richard Spiegel137484d2018-01-17 10:23:19 -0700826 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800827 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700828
Elyes Haouas7d67a192022-10-14 09:58:29 +0200829 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800830
Martin Rothcd15bc82016-11-08 11:34:02 -0700831 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800832 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800833 switch (fw_table[i].type) {
834 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200835 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700836 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800837 break;
838 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700839 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800840 break;
841 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700842 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800843 break;
844 default:
845 /* Error */
846 break;
847 }
848
Marshall Dawson2794a862019-03-04 16:53:15 -0700849 bytes = copy_blob(BUFF_CURRENT(*ctx),
850 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600851 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700852 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700853 exit(1);
854 }
855
Elyes Haouas7d67a192022-10-14 09:58:29 +0200856 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700857 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800858 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800859 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800860}
861
Zheng Bao9e908072020-10-28 11:39:13 +0800862/* For debugging */
863static void dump_psp_firmwares(amd_fw_entry *fw_table)
864{
865 amd_fw_entry *index;
866
867 printf("PSP firmware components:");
868 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
869 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800870 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800871 }
872}
873
874static void dump_bdt_firmwares(amd_bios_entry *fw_table)
875{
876 amd_bios_entry *index;
877
878 printf("BIOS Directory Table (BDT) components:");
879 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
880 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800881 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800882 }
883}
884
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800885static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
886{
887 amd_fw_entry *index;
888
889 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
890 if (index->filename &&
891 index->type != AMD_FW_VERSTAGE_SIG &&
892 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800893 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800894 index->type != AMD_FW_PSP_WHITELIST) {
895 free(index->filename);
896 }
897 }
898}
899
900static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
901{
902 amd_bios_entry *index;
903
904 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
905 if (index->filename &&
906 index->type != AMD_BIOS_APCB &&
907 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200908 index->type != AMD_BIOS_APCB_BK &&
909 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800910 free(index->filename);
911 }
912}
913
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100914static void write_or_fail(int fd, void *ptr, size_t size)
915{
916 ssize_t written;
917
918 written = write_from_buf_to_file(fd, ptr, size);
919 if (written < 0 || (size_t)written != size) {
920 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
921 __func__, size, written);
922 exit(-1);
923 }
924}
925
926static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
927{
928 uint16_t type = entry->fw_id;
929 uint16_t subtype = entry->subtype;
930
931 write_or_fail(fd, &type, sizeof(type));
932 write_or_fail(fd, &subtype, sizeof(subtype));
933 write_or_fail(fd, entry->sha, entry->sha_len);
934}
935
936static void write_psp_firmware_hash(const char *filename,
937 amd_fw_entry *fw_table)
938{
939 struct psp_fw_hash_table hash_header = {0};
940 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
941
942 if (fd < 0) {
943 fprintf(stderr, "Error opening file: %s: %s\n",
944 filename, strerror(errno));
945 exit(-1);
946 }
947
948 hash_header.version = HASH_HDR_V1;
949 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
950 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
951 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
952 hash_header.no_of_entries_256++;
953 } else if (fw_table[i].hash_entries[j].sha_len ==
954 SHA384_DIGEST_LENGTH) {
955 hash_header.no_of_entries_384++;
956 } else if (fw_table[i].hash_entries[j].sha_len) {
957 fprintf(stderr, "%s: Error invalid sha_len %d\n",
958 __func__, fw_table[i].hash_entries[j].sha_len);
959 exit(-1);
960 }
961 }
962 }
963
964 write_or_fail(fd, &hash_header, sizeof(hash_header));
965
966 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
967 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
968 will cause the hash verification failure at run-time. */
969 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
970 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
971 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
972 write_one_psp_firmware_hash_entry(fd,
973 &fw_table[i].hash_entries[j]);
974 }
975 }
976
977 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
978 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
979 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
980 write_one_psp_firmware_hash_entry(fd,
981 &fw_table[i].hash_entries[j]);
982 }
983 }
984
985 close(fd);
986 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
987 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
988 continue;
989
990 free(fw_table[i].hash_entries);
991 fw_table[i].hash_entries = NULL;
992 fw_table[i].num_hash_entries = 0;
993 }
994}
995
Kangheui Won3c164e12021-12-03 20:25:05 +1100996/**
997 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
998 * @signed_rom: Output file path grouping all the signed PSP binaries.
999 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
1000 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
1001 * the signed PSP binaries.
1002 * @soc_id: SoC ID of the PSP binaries.
1003 */
1004static void process_signed_psp_firmwares(const char *signed_rom,
1005 amd_fw_entry *fw_table,
1006 uint64_t signed_start_addr,
1007 enum platform soc_id)
1008{
1009 unsigned int i;
1010 int fd;
1011 int signed_rom_fd;
1012 ssize_t bytes, align_bytes;
1013 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001014 char *signed_rom_hash;
1015 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +11001016 struct amd_fw_header header;
1017 struct stat fd_stat;
1018 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
1019 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
1020 uint8_t align_data[BLOB_ALIGNMENT - 1];
1021
1022 memset(align_data, 0xff, sizeof(align_data));
1023 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
1024 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1025 if (signed_rom_fd < 0) {
1026 fprintf(stderr, "Error opening file: %s: %s\n",
1027 signed_rom, strerror(errno));
1028 return;
1029 }
1030
1031 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001032 fw_table[i].num_hash_entries = 0;
1033 fw_table[i].hash_entries = NULL;
1034
Kangheui Won3c164e12021-12-03 20:25:05 +11001035 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
1036 continue;
1037
1038 memset(&header, 0, sizeof(header));
1039
1040 fd = open(fw_table[i].filename, O_RDONLY);
1041 if (fd < 0) {
1042 /* Keep the file along with set of unsigned PSP binaries & continue. */
1043 fprintf(stderr, "Error opening file: %s: %s\n",
1044 fw_table[i].filename, strerror(errno));
1045 continue;
1046 }
1047
1048 if (fstat(fd, &fd_stat)) {
1049 /* Keep the file along with set of unsigned PSP binaries & continue. */
1050 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1051 close(fd);
1052 continue;
1053 }
1054
1055 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1056 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1057 /* Keep the file along with set of unsigned PSP binaries & continue. */
1058 fprintf(stderr, "%s: Error reading header from %s\n",
1059 __func__, fw_table[i].filename);
1060 close(fd);
1061 continue;
1062 }
1063
1064 /* If firmware header looks like invalid, assume it's not signed */
1065 if (!header.fw_type && !header.fw_id) {
1066 fprintf(stderr, "%s: Invalid FWID for %s\n",
1067 __func__, fw_table[i].filename);
1068 close(fd);
1069 continue;
1070 }
1071
Kangheui Won3c164e12021-12-03 20:25:05 +11001072
1073 /* PSP binary is not signed and should not be part of signed PSP binaries
1074 set. */
1075 if (header.sig_opt != 1) {
1076 close(fd);
1077 continue;
1078 }
1079
1080 buf = malloc(fd_stat.st_size);
1081 if (!buf) {
1082 /* Keep the file along with set of unsigned PSP binaries & continue. */
1083 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1084 __func__, (long long)fd_stat.st_size);
1085 close(fd);
1086 continue;
1087 }
1088
1089 lseek(fd, SEEK_SET, 0);
1090 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1091 if (bytes != fd_stat.st_size) {
1092 /* Keep the file along with set of unsigned PSP binaries & continue. */
1093 fprintf(stderr, "%s: failed to read %s\n",
1094 __func__, fw_table[i].filename);
1095 free(buf);
1096 close(fd);
1097 continue;
1098 }
1099
1100 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1101 if (bytes != fd_stat.st_size) {
1102 /* Keep the file along with set of unsigned PSP binaries & continue. */
1103 fprintf(stderr, "%s: failed to write %s\n",
1104 __func__, fw_table[i].filename);
1105 free(buf);
1106 close(fd);
1107 continue;
1108 }
1109
1110 /* Write Blob alignment bytes */
1111 align_bytes = 0;
1112 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1113 align_bytes = BLOB_ALIGNMENT -
1114 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1115 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1116 if (bytes != align_bytes) {
1117 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1118 __func__, fw_table[i].filename);
1119 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1120 free(buf);
1121 close(fd);
1122 continue;
1123 }
1124 }
1125
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001126 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1127 exit(-1);
1128
Kangheui Won3c164e12021-12-03 20:25:05 +11001129 /* File is successfully processed and is part of signed PSP binaries set. */
1130 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1131 fw_table[i].addr_signed = signed_start_addr;
1132 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1133
1134 signed_start_addr += fd_stat.st_size + align_bytes;
1135
1136 free(buf);
1137 close(fd);
1138 }
1139
1140 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001141
1142 /* signed_rom file name + ".hash" + '\0' */
1143 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1144 signed_rom_hash = malloc(signed_rom_hash_strlen);
1145 if (!signed_rom_hash) {
1146 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1147 exit(-1);
1148 }
1149 strcpy(signed_rom_hash, signed_rom);
1150 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1151 write_psp_firmware_hash(signed_rom_hash, fw_table);
1152 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001153}
1154
Zheng Bao990d1542021-09-17 13:24:54 +08001155static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001156 psp_directory_table *pspdir2, ish_directory_table *ish,
1157 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001158{
1159 uint32_t count;
1160 uint32_t current_table_save;
1161
1162 current_table_save = ctx->current_table;
1163 ctx->current_table = (char *)pspdir - ctx->rom;
1164 count = pspdir->header.num_entries;
1165 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1166 pspdir->entries[count].type = (uint8_t)ab;
1167 pspdir->entries[count].subprog = 0;
1168 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001169 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001170 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001171 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1172 ish->update_retry_count = 2;
1173 ish->glitch_retry_count = 0;
1174 ish->psp_id = get_psp_id(soc_id);
1175 ish->checksum = fletcher32(&ish->boot_priority,
1176 sizeof(ish_directory_table) - sizeof(uint32_t));
1177 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001178 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001179 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001180 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001181 pspdir->entries[count].size = TABLE_ALIGNMENT;
1182 } else {
1183 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001184 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001185 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001186 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001187 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001188 sizeof(psp_directory_entry) +
1189 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001190 }
Zheng Bao990d1542021-09-17 13:24:54 +08001191
1192 count++;
1193 pspdir->header.num_entries = count;
1194 ctx->current_table = current_table_save;
1195}
1196
Marshall Dawson2794a862019-03-04 16:53:15 -07001197static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001198 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001199 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001200 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001201 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001202 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001203 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +08001204 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001205{
Richard Spiegel137484d2018-01-17 10:23:19 -07001206 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001207 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001208 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301209 uint32_t size;
1210 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001211 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001212 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001213 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001214
1215 /* This function can create a primary table, a secondary table, or a
1216 * flattened table which contains all applicable types. These if-else
1217 * statements infer what the caller intended. If a 2nd-level cookie
1218 * is passed, clearly a 2nd-level table is intended. However, a
1219 * 1st-level cookie may indicate level 1 or flattened. If the caller
1220 * passes a pointer to a 2nd-level table, then assume not flat.
1221 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001222 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001223 level = PSP_BOTH;
1224 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001225 level = PSP_LVL2;
1226 else if (pspdir2)
1227 level = PSP_LVL1;
1228 else
1229 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001230
Zheng Bao990d1542021-09-17 13:24:54 +08001231 if (recovery_ab) {
1232 if (cookie == PSPL2_COOKIE)
1233 level = PSP_LVL2_AB;
1234 else if (pspdir2)
1235 level = PSP_LVL1_AB;
1236 else
1237 level = PSP_BOTH_AB;
1238 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001239 current_table_save = ctx->current_table;
1240 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001241 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001242
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001243 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001244 if (!(fw_table[i].level & level))
1245 continue;
1246
Zheng Bao5164e4b2021-10-30 12:09:07 +08001247 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1248
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001249 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1250 if (!fw_table[i].other)
1251 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001252 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001253 pspdir->entries[count].type = fw_table[i].type;
1254 pspdir->entries[count].size = 4096; /* TODO: doc? */
1255 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001256 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001257 pspdir->entries[count].subprog = fw_table[i].subprog;
1258 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001259 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001260 count++;
1261 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001262 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001263 pspdir->entries[count].subprog = fw_table[i].subprog;
1264 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001265 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001266 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001267 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001268 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001269 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301270 if (fw_table[i].filename == NULL) {
1271 if (fw_table[i].size == 0)
1272 continue;
1273 size = fw_table[i].size;
1274 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001275 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301276 fprintf(stderr,
1277 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1278 exit(1);
1279 }
1280 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001281 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301282 bytes = copy_blob(BUFF_CURRENT(*ctx),
1283 fw_table[i].filename, BUFF_ROOM(*ctx));
1284 if (bytes <= 0) {
1285 free(ctx->rom);
1286 exit(1);
1287 }
1288
Elyes Haouas7d67a192022-10-14 09:58:29 +02001289 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301290 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001291 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301292 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001293 }
1294
1295 pspdir->entries[count].type = fw_table[i].type;
1296 pspdir->entries[count].subprog = fw_table[i].subprog;
1297 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301298 pspdir->entries[count].size = size;
1299 pspdir->entries[count].addr = addr;
1300
Zheng Bao6fff2492021-11-15 19:53:21 +08001301 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001302 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001303
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001304 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001305 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001306 if (fw_table[i].addr_signed) {
1307 pspdir->entries[count].addr =
1308 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1309 pspdir->entries[count].address_mode =
1310 SET_ADDR_MODE_BY_TABLE(pspdir);
1311 bytes = fw_table[i].file_size;
1312 } else {
1313 bytes = copy_blob(BUFF_CURRENT(*ctx),
1314 fw_table[i].filename, BUFF_ROOM(*ctx));
1315 if (bytes < 0) {
1316 free(ctx->rom);
1317 exit(1);
1318 }
1319 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1320 pspdir->entries[count].address_mode =
1321 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001322 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001323 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001324 }
1325
Marshall Dawson239286c2019-02-23 16:42:46 -07001326 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001327 pspdir->entries[count].subprog = fw_table[i].subprog;
1328 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001329 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001330
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001331 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001332 } else {
1333 /* This APU doesn't have this firmware. */
1334 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001335 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001336
Zheng Bao990d1542021-09-17 13:24:54 +08001337 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001338 if (cb_config->need_ish) { /* Need ISH */
1339 ish_a_dir = new_ish_dir(ctx);
1340 if (pspdir2_b != NULL)
1341 ish_b_dir = new_ish_dir(ctx);
1342 }
Zheng Bao990d1542021-09-17 13:24:54 +08001343 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001344 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
1345 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001346 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001347 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
1348 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001349 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001350 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001351 AMD_FW_RECOVERYAB_B, soc_id);
1352
Zheng Bao990d1542021-09-17 13:24:54 +08001353 count = pspdir->header.num_entries;
1354 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001355 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001356 pspdir->entries[count].type = AMD_FW_L2_PTR;
1357 pspdir->entries[count].subprog = 0;
1358 pspdir->entries[count].rsvd = 0;
1359 pspdir->entries[count].size = sizeof(pspdir2->header)
1360 + pspdir2->header.num_entries
1361 * sizeof(psp_directory_entry);
1362
Zheng Bao6fff2492021-11-15 19:53:21 +08001363 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001364 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001365 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001366 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001367 count++;
1368 }
1369
Zheng Baobf29a0d2020-12-03 23:00:48 +08001370 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001371 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001372}
1373
Zheng Bao990d1542021-09-17 13:24:54 +08001374static void add_psp_firmware_entry(context *ctx,
1375 psp_directory_table *pspdir,
1376 void *table, amd_fw_type type, uint32_t size)
1377{
1378 uint32_t count = pspdir->header.num_entries;
1379 uint32_t index;
1380 uint32_t current_table_save;
1381
1382 current_table_save = ctx->current_table;
1383 ctx->current_table = (char *)pspdir - ctx->rom;
1384
1385 /* If there is an entry of "type", replace it. */
1386 for (index = 0; index < count; index++) {
1387 if (pspdir->entries[index].type == (uint8_t)type)
1388 break;
1389 }
1390
1391 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1392 pspdir->entries[index].type = (uint8_t)type;
1393 pspdir->entries[index].subprog = 0;
1394 pspdir->entries[index].rsvd = 0;
1395 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1396 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1397 pspdir->entries[index].size = size;
1398 if (index == count)
1399 count++;
1400
1401 pspdir->header.num_entries = count;
1402 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1403 count * sizeof(psp_directory_entry)
1404 + sizeof(pspdir->header.num_entries)
1405 + sizeof(pspdir->header.additional_info));
1406
1407 ctx->current_table = current_table_save;
1408}
1409
Zheng Baoba3af5e2021-11-04 18:56:47 +08001410static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001411{
1412 void *ptr;
1413
1414 /*
1415 * Force both onto boundary when multi. Primary table is after
1416 * updatable table, so alignment ensures primary can stay intact
1417 * if secondary is reprogrammed.
1418 */
1419 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001420 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001421 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001422 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001423 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001424 ((bios_directory_hdr *) ptr)->additional_info = 0;
1425 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1426 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001427 ctx->current += sizeof(bios_directory_hdr)
1428 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1429 return ptr;
1430}
1431
1432static int locate_bdt2_bios(bios_directory_table *level2,
1433 uint64_t *source, uint32_t *size)
1434{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001435 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001436
1437 *source = 0;
1438 *size = 0;
1439 if (!level2)
1440 return 0;
1441
1442 for (i = 0 ; i < level2->header.num_entries ; i++) {
1443 if (level2->entries[i].type == AMD_BIOS_BIN) {
1444 *source = level2->entries[i].source;
1445 *size = level2->entries[i].size;
1446 return 1;
1447 }
1448 }
1449 return 0;
1450}
1451
1452static int have_bios_tables(amd_bios_entry *table)
1453{
1454 int i;
1455
1456 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1457 if (table[i].level & BDT_LVL1 && table[i].filename)
1458 return 1;
1459 }
1460 return 0;
1461}
1462
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001463static int find_bios_entry(amd_bios_type type)
1464{
1465 int i;
1466
1467 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1468 if (amd_bios_table[i].type == type)
1469 return i;
1470 }
1471 return -1;
1472}
1473
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001474static void integrate_bios_firmwares(context *ctx,
1475 bios_directory_table *biosdir,
1476 bios_directory_table *biosdir2,
1477 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001478 uint32_t cookie,
1479 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001480{
1481 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001482 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001483 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001484 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001485 uint32_t size;
1486 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001487
1488 /* This function can create a primary table, a secondary table, or a
1489 * flattened table which contains all applicable types. These if-else
1490 * statements infer what the caller intended. If a 2nd-level cookie
1491 * is passed, clearly a 2nd-level table is intended. However, a
1492 * 1st-level cookie may indicate level 1 or flattened. If the caller
1493 * passes a pointer to a 2nd-level table, then assume not flat.
1494 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001495 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001496 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001497 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001498 level = BDT_LVL2;
1499 else if (biosdir2)
1500 level = BDT_LVL1;
1501 else
1502 level = BDT_BOTH;
1503
Elyes Haouas7d67a192022-10-14 09:58:29 +02001504 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001505
1506 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1507 if (!(fw_table[i].level & level))
1508 continue;
1509 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301510 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001511 fw_table[i].type != AMD_BIOS_APOB &&
1512 fw_table[i].type != AMD_BIOS_APOB_NV &&
1513 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001514 fw_table[i].type != AMD_BIOS_BIN &&
1515 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001516 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001517
1518 /* BIOS Directory items may have additional requirements */
1519
Ritul Guru9a321f32022-07-29 11:06:40 +05301520 /* SIG needs a size, else no choice but to skip */
1521 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1522 continue;
1523
Martin Roth48dd9fe2020-07-29 16:32:25 -06001524 /* Check APOB_NV requirements */
1525 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1526 if (!fw_table[i].size && !fw_table[i].src)
1527 continue; /* APOB_NV not used */
1528 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001529 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001530 free(ctx->rom);
1531 exit(1);
1532 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001533 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001534 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001535 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1536 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001537 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001538
1539 /* APOB_DATA needs destination */
1540 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001541 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001542 free(ctx->rom);
1543 exit(1);
1544 }
1545
1546 /* BIOS binary must have destination and uncompressed size. If
1547 * no filename given, then user must provide a source address.
1548 */
1549 if (fw_table[i].type == AMD_BIOS_BIN) {
1550 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001551 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001552 free(ctx->rom);
1553 exit(1);
1554 }
1555 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001556 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001557 free(ctx->rom);
1558 exit(1);
1559 }
1560 }
1561
Martin Roth94554742020-04-14 14:59:36 -06001562 /* PSP_SHARED_MEM needs a destination and size */
1563 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1564 (!fw_table[i].dest || !fw_table[i].size))
1565 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001566 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001567
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001568 biosdir->entries[count].type = fw_table[i].type;
1569 biosdir->entries[count].region_type = fw_table[i].region_type;
1570 biosdir->entries[count].dest = fw_table[i].dest ?
1571 fw_table[i].dest : (uint64_t)-1;
1572 biosdir->entries[count].reset = fw_table[i].reset;
1573 biosdir->entries[count].copy = fw_table[i].copy;
1574 biosdir->entries[count].ro = fw_table[i].ro;
1575 biosdir->entries[count].compressed = fw_table[i].zlib;
1576 biosdir->entries[count].inst = fw_table[i].inst;
1577 biosdir->entries[count].subprog = fw_table[i].subpr;
1578
1579 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301580 case AMD_BIOS_SIG:
1581 /* Reserve size bytes within amdfw.rom */
1582 biosdir->entries[count].size = fw_table[i].size;
1583 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1584 biosdir->entries[count].address_mode =
1585 SET_ADDR_MODE_BY_TABLE(biosdir);
1586 memset(BUFF_CURRENT(*ctx), 0xff,
1587 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001588 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301589 + biosdir->entries[count].size, 0x100U);
1590 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001591 case AMD_BIOS_APOB:
1592 biosdir->entries[count].size = fw_table[i].size;
1593 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001594 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001595 break;
1596 case AMD_BIOS_APOB_NV:
1597 if (fw_table[i].src) {
1598 /* If source is given, use that and its size */
1599 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001600 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001601 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001602 biosdir->entries[count].size = fw_table[i].size;
1603 } else {
1604 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001605 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001606 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001607 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001608 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001609 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001610 fw_table[i].size, ERASE_ALIGNMENT);
1611 memset(BUFF_CURRENT(*ctx), 0xff,
1612 biosdir->entries[count].size);
1613 ctx->current = ctx->current
1614 + biosdir->entries[count].size;
1615 }
1616 break;
1617 case AMD_BIOS_BIN:
1618 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001619 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1620 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001621 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001622 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001623 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001624 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001625 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001626
1627 /* level 2, or level 1 and no copy found in level 2 */
1628 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001629 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001630 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001631 biosdir->entries[count].dest = fw_table[i].dest;
1632 biosdir->entries[count].size = fw_table[i].size;
1633
1634 if (!fw_table[i].filename)
1635 break;
1636
1637 bytes = copy_blob(BUFF_CURRENT(*ctx),
1638 fw_table[i].filename, BUFF_ROOM(*ctx));
1639 if (bytes <= 0) {
1640 free(ctx->rom);
1641 exit(1);
1642 }
1643
Zheng Bao6fff2492021-11-15 19:53:21 +08001644 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001645 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001646 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001647 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001648
Elyes Haouas7d67a192022-10-14 09:58:29 +02001649 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001650 break;
Martin Roth94554742020-04-14 14:59:36 -06001651 case AMD_BIOS_PSP_SHARED_MEM:
1652 biosdir->entries[count].dest = fw_table[i].dest;
1653 biosdir->entries[count].size = fw_table[i].size;
1654 break;
1655
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001656 default: /* everything else is copied from input */
1657 if (fw_table[i].type == AMD_BIOS_APCB ||
1658 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001659 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001660 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001661 bytes = copy_blob(BUFF_CURRENT(*ctx),
1662 fw_table[i].filename, BUFF_ROOM(*ctx));
1663 if (bytes <= 0) {
1664 free(ctx->rom);
1665 exit(1);
1666 }
1667
1668 biosdir->entries[count].size = (uint32_t)bytes;
1669 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001670 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001671
Elyes Haouas7d67a192022-10-14 09:58:29 +02001672 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001673 break;
1674 }
1675
1676 count++;
1677 }
1678
1679 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001680 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001681 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001682 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001683 biosdir->entries[count].size =
1684 + MAX_BIOS_ENTRIES
1685 * sizeof(bios_directory_entry);
1686 biosdir->entries[count].source =
1687 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001688 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001689 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001690 biosdir->entries[count].subprog = 0;
1691 biosdir->entries[count].inst = 0;
1692 biosdir->entries[count].copy = 0;
1693 biosdir->entries[count].compressed = 0;
1694 biosdir->entries[count].dest = -1;
1695 biosdir->entries[count].reset = 0;
1696 biosdir->entries[count].ro = 0;
1697 count++;
1698 }
1699
Zheng Baobf29a0d2020-12-03 23:00:48 +08001700 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001701}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001702
1703enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001704 AMDFW_OPT_CONFIG = 'c',
1705 AMDFW_OPT_DEBUG = 'd',
1706 AMDFW_OPT_HELP = 'h',
1707 AMDFW_OPT_LIST_DEPEND = 'l',
1708
1709 AMDFW_OPT_XHCI = 128,
1710 AMDFW_OPT_IMC,
1711 AMDFW_OPT_GEC,
1712 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001713 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001714 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001715 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001716 AMDFW_OPT_MULTILEVEL,
1717 AMDFW_OPT_NVRAM,
1718
1719 AMDFW_OPT_FUSE,
1720 AMDFW_OPT_UNLOCK,
1721 AMDFW_OPT_WHITELIST,
1722 AMDFW_OPT_USE_PSPSECUREOS,
1723 AMDFW_OPT_LOAD_MP2FW,
1724 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001725 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001726 AMDFW_OPT_VERSTAGE,
1727 AMDFW_OPT_VERSTAGE_SIG,
1728
1729 AMDFW_OPT_INSTANCE,
1730 AMDFW_OPT_APCB,
1731 AMDFW_OPT_APOBBASE,
1732 AMDFW_OPT_BIOSBIN,
1733 AMDFW_OPT_BIOSBIN_SOURCE,
1734 AMDFW_OPT_BIOSBIN_DEST,
1735 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1736 AMDFW_OPT_UCODE,
1737 AMDFW_OPT_APOB_NVBASE,
1738 AMDFW_OPT_APOB_NVSIZE,
1739
1740 AMDFW_OPT_OUTPUT,
1741 AMDFW_OPT_FLASHSIZE,
1742 AMDFW_OPT_LOCATION,
1743 AMDFW_OPT_ANYWHERE,
1744 AMDFW_OPT_SHAREDMEM,
1745 AMDFW_OPT_SHAREDMEM_SIZE,
1746 AMDFW_OPT_SOC_NAME,
Kangheui Won3c164e12021-12-03 20:25:05 +11001747 AMDFW_OPT_SIGNED_OUTPUT,
1748 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001749 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001750 /* begin after ASCII characters */
1751 LONGOPT_SPI_READ_MODE = 256,
1752 LONGOPT_SPI_SPEED = 257,
1753 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301754 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301755 LONGOPT_NVRAM_BASE = 260,
1756 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001757};
1758
Zheng Bao806892a2021-04-27 17:21:54 +08001759static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1760 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1761};
Marc Jones90099b62016-09-20 21:05:45 -06001762
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001763static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001764 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1765 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1766 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001767 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001768 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001769 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001770 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001771 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001772 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1773 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301774 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1775 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001776 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1777 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1778 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1779 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1780 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1781 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001782 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001783 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1784 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001785 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001786 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1787 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1788 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1789 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1790 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1791 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1792 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301793 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001794 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1795 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1796 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001797 /* Embedded Firmware Structure items*/
1798 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1799 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1800 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001801 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001802 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001803 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1804 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1805 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1806 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1807 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1808 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1809 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001810
Kangheui Won3c164e12021-12-03 20:25:05 +11001811 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1812 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1813
Zheng Bao806892a2021-04-27 17:21:54 +08001814 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1815 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1816 {"help", no_argument, 0, AMDFW_OPT_HELP },
1817 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001818 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001819};
1820
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001821void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001822{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001823 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001824
1825 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1826 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1827 continue;
1828
1829 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1830 return;
1831 }
1832}
1833
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001834static void register_fw_token_unlock(void)
1835{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001836 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001837
1838 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1839 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1840 continue;
1841
1842 amd_psp_fw_table[i].other = 1;
1843 return;
1844 }
1845}
1846
Marshall Dawsondbae6322019-03-04 10:31:03 -07001847static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001848{
Martin Roth8806f7f2016-11-08 10:44:18 -07001849 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001850
Martin Rothcd15bc82016-11-08 11:34:02 -07001851 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001852 if (amd_fw_table[i].type == type) {
1853 amd_fw_table[i].filename = filename;
1854 return;
1855 }
1856 }
1857
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001858 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001859 if (amd_psp_fw_table[i].type != type)
1860 continue;
1861
1862 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001863 amd_psp_fw_table[i].filename = filename;
1864 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001865 }
1866 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001867}
1868
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001869static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1870{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001871 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001872
1873 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1874 if (amd_bios_table[i].type == type
1875 && amd_bios_table[i].inst == ins
1876 && amd_bios_table[i].subpr == sub) {
1877 amd_bios_table[i].filename = name;
1878 return;
1879 }
1880 }
1881}
1882
Ritul Gurua2cb3402022-08-29 00:51:08 +05301883static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1884 char *dst_str, char *size_str)
1885{
1886 unsigned int i;
1887
1888 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1889 if (amd_psp_fw_table[i].type != type)
1890 continue;
1891
1892 if (amd_psp_fw_table[i].subprog == sub) {
1893 if (dst_str)
1894 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1895 if (size_str)
1896 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1897 return;
1898 }
1899 }
1900}
1901
1902static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001903 char *dst_str, char *size_str)
1904{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001905 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001906 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1907 if (amd_bios_table[i].type != type)
1908 continue;
1909
1910 if (src_str)
1911 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1912 if (dst_str)
1913 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1914 if (size_str)
1915 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1916
1917 return;
1918 }
1919}
1920
Zheng Baoc3007f32022-04-03 12:53:51 +08001921static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1922 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1923 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001924{
1925 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001926 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001927 return 1;
1928 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001929
1930 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1931 * Leave as 0xffffffff for first gen */
1932 if (cb_config->second_gen) {
1933 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1934 amd_romsig->efs_gen.reserved = 0;
1935 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001936 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1937 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001938 }
1939
1940 switch (soc_id) {
1941 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001942 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1943 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1944 break;
1945 case PLATFORM_RAVEN:
1946 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001947 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1948 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1949 switch (efs_spi_micron_flag) {
1950 case 0:
1951 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1952 break;
1953 case 1:
1954 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1955 break;
1956 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001957 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001958 return 1;
1959 }
1960 break;
1961 case PLATFORM_RENOIR:
1962 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001963 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001964 case PLATFORM_MENDOCINO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001965 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1966 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1967 switch (efs_spi_micron_flag) {
1968 case 0:
1969 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1970 break;
1971 case 1:
1972 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1973 break;
1974 case 2:
1975 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1976 break;
1977 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001978 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001979 return 1;
1980 }
1981 break;
Martin Roth20646cd2023-01-04 21:27:06 -07001982 /* TODO: Update for phoenix and glinda */
1983 case PLATFORM_PHOENIX:
Martin Roth13490832022-10-06 17:18:02 -06001984 case PLATFORM_GLINDA:
1985 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001986 case PLATFORM_UNKNOWN:
1987 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001988 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001989 return 1;
1990 }
1991 return 0;
1992}
1993
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001994static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
1995{
1996 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
1997 int ret;
1998 int fd;
1999 ssize_t bytes = -1;
2000
2001 /* Create a tmp file and rename it at the end so that make does not get confused
2002 if amdfwtool is killed for some unexpected reasons. */
2003 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
2004 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
2005 if (ret < 0) {
2006 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
2007 strerror(errno), ret);
2008 exit(1);
2009 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
2010 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
2011 exit(1);
2012 }
2013
2014 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
2015 if (fd < 0) {
2016 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
2017 exit(1);
2018 }
2019
2020 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
2021 if (bytes != sizeof(*amd_romsig)) {
2022 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
2023 exit(1);
2024 }
2025 close(fd);
2026
2027 /* Rename the tmp file */
2028 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
2029 if (ret < 0) {
2030 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
2031 exit(1);
2032 }
2033
2034 if (rename(efs_tmp_name, efs_name)) {
2035 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
2036 exit(1);
2037 }
2038
2039 return bytes;
2040}
2041
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002042static int identify_platform(char *soc_name)
2043{
2044 if (!strcasecmp(soc_name, "Stoneyridge"))
2045 return PLATFORM_STONEYRIDGE;
2046 else if (!strcasecmp(soc_name, "Raven"))
2047 return PLATFORM_RAVEN;
2048 else if (!strcasecmp(soc_name, "Picasso"))
2049 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002050 else if (!strcasecmp(soc_name, "Cezanne"))
2051 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08002052 else if (!strcasecmp(soc_name, "Mendocino"))
2053 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002054 else if (!strcasecmp(soc_name, "Renoir"))
2055 return PLATFORM_RENOIR;
2056 else if (!strcasecmp(soc_name, "Lucienne"))
2057 return PLATFORM_LUCIENNE;
Martin Roth20646cd2023-01-04 21:27:06 -07002058 else if (!strcasecmp(soc_name, "Phoenix"))
2059 return PLATFORM_PHOENIX;
Martin Roth13490832022-10-06 17:18:02 -06002060 else if (!strcasecmp(soc_name, "Glinda"))
2061 return PLATFORM_GLINDA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002062 else
2063 return PLATFORM_UNKNOWN;
2064
2065}
2066
Felix Heldf8e2e472022-03-29 23:28:49 +02002067static bool needs_ish(enum platform platform_type)
2068{
Jon Murphy9969f4b2022-08-05 13:56:38 -06002069 if (platform_type == PLATFORM_MENDOCINO)
Felix Heldf8e2e472022-03-29 23:28:49 +02002070 return true;
2071 else
2072 return false;
2073}
2074
Zheng Baoc3007f32022-04-03 12:53:51 +08002075static bool is_second_gen(enum platform platform_type)
2076{
2077 switch (platform_type) {
2078 case PLATFORM_STONEYRIDGE:
2079 case PLATFORM_RAVEN:
2080 case PLATFORM_PICASSO:
2081 return false;
2082 case PLATFORM_RENOIR:
2083 case PLATFORM_LUCIENNE:
2084 case PLATFORM_CEZANNE:
Jon Murphy9969f4b2022-08-05 13:56:38 -06002085 case PLATFORM_MENDOCINO:
Zheng Baoc3007f32022-04-03 12:53:51 +08002086 return true;
2087 case PLATFORM_UNKNOWN:
2088 default:
2089 fprintf(stderr, "Error: Invalid SOC name.\n\n");
2090 return false;
2091 }
2092}
2093
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002094int main(int argc, char **argv)
2095{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002096 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002097 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002098 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002099 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002100 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002101 psp_directory_table *pspdir = NULL;
2102 psp_directory_table *pspdir2 = NULL;
2103 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08002104 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002105 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002106 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002107 char *output = NULL, *config = NULL;
2108 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002109 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002110 /* Values cleared after each firmware or parameter, regardless if N/A */
2111 uint8_t sub = 0, instance = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002112 uint32_t dir_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002113 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002114 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002115 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002116 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002117 uint8_t soc_id = PLATFORM_UNKNOWN;
2118 uint8_t efs_spi_readmode = 0xff;
2119 uint8_t efs_spi_speed = 0xff;
2120 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002121 const char *signed_output_file = NULL;
2122 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002123
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002124 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002125 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002126 int list_deps = 0;
2127
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002128 while (1) {
2129 int optindex = 0;
2130
2131 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2132
2133 if (c == -1)
2134 break;
2135
2136 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002137 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002138 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002139 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002140 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002141 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002142 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002143 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002144 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002145 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002146 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002147 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002148 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002149 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002150 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07002151 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002152 case AMDFW_OPT_RECOVERY_AB:
2153 cb_config.recovery_ab = true;
2154 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002155 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2156 cb_config.recovery_ab = true;
2157 cb_config.recovery_ab_single_copy = true;
2158 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002159 case AMDFW_OPT_USE_COMBO:
2160 cb_config.use_combo = true;
2161 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002162 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002163 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002164 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002165 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002166 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002167 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002168 sub = instance = 0;
2169 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002170 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002171 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002172 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002173 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002174 instance = strtoul(optarg, &tmp, 16);
2175 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002176 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002177 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002178 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002179 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002180 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002181 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002182 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002183 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002184 register_fw_fuse(optarg);
2185 fuse_defined = 1;
2186 sub = 0;
2187 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002188 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002189 if ((instance & 0xF0) == 0)
2190 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2191 else
2192 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2193 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002194 sub = instance = 0;
2195 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002196 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002197 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302198 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002199 sub = instance = 0;
2200 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002201 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002202 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302203 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002204 sub = instance = 0;
2205 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002206 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002207 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302208 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002209 sub = instance = 0;
2210 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002211 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002212 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2213 sub = instance = 0;
2214 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002215 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002216 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302217 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002218 sub = instance = 0;
2219 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002220 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002221 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302222 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002223 sub = instance = 0;
2224 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002225 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002226 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302227 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002228 sub = instance = 0;
2229 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302230 case LONGOPT_BIOS_SIG:
2231 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302232 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302233 sub = instance = 0;
2234 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002235 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002236 register_bdt_data(AMD_BIOS_UCODE, sub,
2237 instance, optarg);
2238 sub = instance = 0;
2239 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002240 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002241 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002242 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002243 case AMDFW_OPT_SPL_TABLE:
2244 register_fw_filename(AMD_FW_SPL, sub, optarg);
2245 sub = instance = 0;
2246 cb_config.have_mb_spl = true;
2247 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002248 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002249 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2250 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002251 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002252 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002253 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002254 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2255 sub = instance = 0;
2256 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002257 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002258 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2259 sub = instance = 0;
2260 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002261 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002262 soc_id = identify_platform(optarg);
2263 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002264 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002265 retval = 1;
2266 }
2267 sub = instance = 0;
2268 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002269 case AMDFW_OPT_SIGNED_OUTPUT:
2270 signed_output_file = optarg;
2271 sub = instance = 0;
2272 break;
2273 case AMDFW_OPT_SIGNED_ADDR:
2274 signed_start_addr = strtoull(optarg, NULL, 10);
2275 sub = instance = 0;
2276 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002277 case LONGOPT_SPI_READ_MODE:
2278 efs_spi_readmode = strtoull(optarg, NULL, 16);
2279 sub = instance = 0;
2280 break;
2281 case LONGOPT_SPI_SPEED:
2282 efs_spi_speed = strtoull(optarg, NULL, 16);
2283 sub = instance = 0;
2284 break;
2285 case LONGOPT_SPI_MICRON_FLAG:
2286 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2287 sub = instance = 0;
2288 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002289 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002290 output = optarg;
2291 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002292 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002293 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002294 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002295 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002296 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002297 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002298 }
2299 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002300 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002301 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002302 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002303 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002304 " incorrectly (%s)\n\n", optarg);
2305 retval = 1;
2306 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002307 dir_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002308 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002309 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002310 any_location = 1;
2311 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002312 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002313 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302314 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002315 sub = instance = 0;
2316 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002317 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002318 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302319 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002320 sub = instance = 0;
2321 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302322 case LONGOPT_NVRAM_BASE:
2323 /* PSP NV base */
2324 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2325 sub = instance = 0;
2326 break;
2327 case LONGOPT_NVRAM_SIZE:
2328 /* PSP NV size */
2329 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2330 sub = instance = 0;
2331 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002332 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002333 config = optarg;
2334 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002335 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002336 debug = 1;
2337 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002338 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002339 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002340 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002341 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002342 list_deps = 1;
2343 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002344 case AMDFW_OPT_BODY_LOCATION:
2345 dir_location = (uint32_t)strtoul(optarg, &tmp, 16);
2346 if (*tmp != '\0') {
2347 fprintf(stderr, "Error: Body Location specified"
2348 " incorrectly (%s)\n\n", optarg);
2349 retval = 1;
2350 }
2351 break;
2352
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002353 default:
2354 break;
2355 }
2356 }
2357
Zheng Baoc3007f32022-04-03 12:53:51 +08002358 cb_config.second_gen = is_second_gen(soc_id);
2359
Felix Heldf8e2e472022-03-29 23:28:49 +02002360 if (needs_ish(soc_id))
2361 cb_config.need_ish = true;
2362
Felix Held830add62022-03-29 23:28:10 +02002363 if (cb_config.need_ish)
2364 cb_config.recovery_ab = true;
2365
2366 if (cb_config.recovery_ab)
2367 cb_config.multi_level = true;
2368
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002369 if (config) {
2370 config_handle = fopen(config, "r");
2371 if (config_handle == NULL) {
2372 fprintf(stderr, "Can not open file %s for reading: %s\n",
2373 config, strerror(errno));
2374 exit(1);
2375 }
2376 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2377 fprintf(stderr, "Configuration file %s parsing error\n", config);
2378 fclose(config_handle);
2379 exit(1);
2380 }
2381 fclose(config_handle);
2382 }
Zheng Bao9e908072020-10-28 11:39:13 +08002383 /* For debug. */
2384 if (debug) {
2385 dump_psp_firmwares(amd_psp_fw_table);
2386 dump_bdt_firmwares(amd_bios_table);
2387 }
2388
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002389 if (!fuse_defined)
2390 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2391
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002392 if (!output && !list_deps) {
2393 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002394 retval = 1;
2395 }
2396
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002397 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2398 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002399 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002400 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002401 }
2402
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002403 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2404 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002405 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002406 retval = 1;
2407 }
2408
2409 if (retval) {
2410 usage();
2411 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002412 }
2413
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002414 if (list_deps) {
2415 return retval;
2416 }
2417
Marshall Dawson2794a862019-03-04 16:53:15 -07002418 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002419
Marshall Dawson2794a862019-03-04 16:53:15 -07002420 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002421 if (efs_location && (efs_location < rom_base_address)) {
2422 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2423 return 1;
2424 }
2425
2426 if (!efs_location && dir_location) {
2427 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2428 return 1;
2429 }
2430
2431 /*
2432 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2433 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2434 * currently. This condition is to ensure that it is not accidentally split. Revisit
2435 * this condition if such a need arises in the future.
2436 */
2437 if (!any_location && dir_location != efs_location) {
2438 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2439 return 1;
2440 }
2441
2442 if (dir_location != efs_location &&
2443 dir_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
2444 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2445 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002446 return 1;
2447 }
2448
Martin Roth37305e72020-04-07 14:16:39 -06002449 if (any_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002450 if ((dir_location & 0x3f) || (efs_location & 0x3f)) {
2451 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002452 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002453 return 1;
2454 }
2455 } else {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002456 switch (efs_location) {
Martin Roth37305e72020-04-07 14:16:39 -06002457 case 0: /* Fall through */
2458 case 0xFFFA0000: /* Fall through */
2459 case 0xFFF20000: /* Fall through */
2460 case 0xFFE20000: /* Fall through */
2461 case 0xFFC20000: /* Fall through */
2462 case 0xFF820000: /* Fall through */
2463 case 0xFF020000: /* Fall through */
2464 break;
2465 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002466 fprintf(stderr, "Error: Invalid Directory location.\n");
2467 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2468 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002469 return 1;
2470 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002471 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002472 ctx.rom = malloc(ctx.rom_size);
2473 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002474 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002475 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002476 }
2477 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002478
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002479 if (efs_location) {
2480 if (efs_location != dir_location) {
2481 romsig_offset = efs_location - rom_base_address;
2482 ctx.current = dir_location - rom_base_address;
2483 } else {
2484 romsig_offset = efs_location - rom_base_address;
2485 ctx.current = romsig_offset + sizeof(embedded_firmware);
2486 }
2487 } else {
2488 romsig_offset = AMD_ROMSIG_OFFSET;
2489 ctx.current = romsig_offset + sizeof(embedded_firmware);
2490 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002491
Marshall Dawson2794a862019-03-04 16:53:15 -07002492 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002493 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2494 amd_romsig->imc_entry = 0;
2495 amd_romsig->gec_entry = 0;
2496 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002497
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002498 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08002499 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08002500 efs_spi_speed, efs_spi_micron_flag);
2501 if (retval) {
2502 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2503 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002504 }
2505 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002506 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002507 }
2508
Felix Held21a8e382022-03-29 23:10:45 +02002509 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002510 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002511 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002512 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002513 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002514 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002515 printf(" AMDFWTOOL Using firmware directory location of %s address: 0x%08x\n",
Robert Zieba29bc79f2022-03-14 15:59:12 -06002516 ctx.address_mode == AMD_ADDR_PHYSICAL ? "absolute" : "relative",
Zheng Bao6fff2492021-11-15 19:53:21 +08002517 RUN_CURRENT(ctx));
Zheng Baoda83d2c2021-06-04 19:03:10 +08002518
Marshall Dawson2794a862019-03-04 16:53:15 -07002519 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002520
Elyes Haouas7d67a192022-10-14 09:58:29 +02002521 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002522 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002523
Kangheui Won3c164e12021-12-03 20:25:05 +11002524 /* If the tool is invoked with command-line options to keep the signed PSP
2525 binaries separate, process the signed binaries first. */
2526 if (signed_output_file && signed_start_addr)
2527 process_signed_psp_firmwares(signed_output_file,
2528 amd_psp_fw_table,
2529 signed_start_addr,
2530 soc_id);
2531
Zheng Bao481661e2021-08-20 14:47:46 +08002532 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002533 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002534 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2535 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002536 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002537 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2538 /* Create a copy of PSP Directory 2 in the backup slot B.
2539 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002540 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2541 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002542 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002543 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002544 /*
2545 * Either the platform is using only one slot or B is same as above
2546 * directories for A. Skip creating pspdir2_b here to save flash space.
2547 * Related biosdir2_b will be skipped automatically.
2548 */
Zheng Bao990d1542021-09-17 13:24:54 +08002549 pspdir2_b = NULL; /* More explicitly */
2550 }
Zheng Bao481661e2021-08-20 14:47:46 +08002551 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002552 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002553 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002554 } else {
2555 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002556 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002557 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002558 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002559 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002560
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002561 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08002562 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07002563 else
Felix Heldad68b072021-10-18 14:00:35 +02002564 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002565
Zheng Bao993b43f2021-11-10 12:21:46 +08002566 if (cb_config.use_combo) {
2567 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2568 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2569 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2570 combo_dir->entries[0].id_sel = 0;
2571 combo_dir->entries[0].id = get_psp_id(soc_id);
2572 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002573
Zheng Bao993b43f2021-11-10 12:21:46 +08002574 combo_dir->header.lookup = 1;
2575 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2576 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002577
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002578 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002579 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002580 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002581 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002582 bios_directory_table *biosdir2 = NULL;
2583 bios_directory_table *biosdir2_b = NULL;
2584
2585 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2586
Zheng Baoedd1e362021-11-04 17:47:07 +08002587 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002588 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002589 if (cb_config.recovery_ab) {
2590 if (pspdir2_b != NULL) {
2591 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2592 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002593 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002594 }
2595 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2596 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2597 if (pspdir2_b != NULL)
2598 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2599 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2600 } else {
2601 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2602 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002603 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002604 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002605 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002606 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002607 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002608 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002609 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002610 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08002611 switch (soc_id) {
2612 case PLATFORM_RENOIR:
2613 case PLATFORM_LUCIENNE:
2614 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002615 if (!cb_config.recovery_ab)
2616 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002617 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002618 case PLATFORM_MENDOCINO:
2619 break;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002620 case PLATFORM_STONEYRIDGE:
2621 case PLATFORM_RAVEN:
2622 case PLATFORM_PICASSO:
2623 default:
2624 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2625 break;
2626 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002627 }
2628
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002629 /* Free the filename. */
2630 free_psp_firmware_filenames(amd_psp_fw_table);
2631 free_bdt_firmware_filenames(amd_bios_table);
2632
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002633 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002634 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002635 ssize_t bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002636 uint32_t offset = dir_location ? dir_location - rom_base_address : AMD_ROMSIG_OFFSET;
2637
2638 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2639 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002640 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2641 retval = 1;
2642 }
Martin Roth31d95a22016-11-08 11:22:12 -07002643 close(targetfd);
2644 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002645 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002646 retval = 1;
2647 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002648
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002649 if (efs_location != dir_location) {
2650 ssize_t bytes;
2651
2652 bytes = write_efs(output, amd_romsig);
2653 if (bytes != sizeof(*amd_romsig)) {
2654 fprintf(stderr, "Error: Writing EFS\n");
2655 retval = 1;
2656 }
2657 }
2658
Martin Roth31d95a22016-11-08 11:22:12 -07002659 free(rom);
2660 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002661}