blob: 997a948baeb7b1530431c8003cb27f5014b0854e [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");
Fred Reitberger7e980112022-10-07 14:00:23 -0400210 printf(" Mendocino, Morgana, 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 Bao990d1542021-09-17 13:24:54 +0800259 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
260 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100261 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800262 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
263 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800264 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200265 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800266 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200267 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
268 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800269 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
270 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200271 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
272 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
273 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800274 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800275 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
276 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
277 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
278 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
279 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
280 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
281 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200283 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
284 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600285 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200286 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200287 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200288 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
289 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
290 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
291 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
292 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600293 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
294 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200295 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
296 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
297 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
298 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
299 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
300 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200301 { .type = AMD_FW_MPIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200302 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH },
303 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200305 { .type = AMD_RIB, .level = PSP_BOTH | PSP_BOTH_AB },
306 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200307 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200308 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
309 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800310 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800311};
312
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800313amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800314 { .type = AMD_FW_XHCI },
315 { .type = AMD_FW_IMC },
316 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800317 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800318};
319
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800320amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800321 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530322 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600323 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
324 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
325 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
326 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
327 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700328 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
329 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
330 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
331 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
332 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
333 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
334 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
335 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
336 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
337 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
338 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700339 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
340 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
341 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
342 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
343 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700344 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
345 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
346 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
347 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
348 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
349 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
350 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
351 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
352 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
353 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600355 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
356 { .type = AMD_BIOS_BIN,
357 .reset = 1, .copy = 1, .zlib = 1, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
359 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
360 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800361 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
362 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200363 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
364 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600365 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
366 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200367 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
368 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
369 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
370 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600371 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
372 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800373 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
374 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200375 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
376 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600377 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
378 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200379 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
380 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
381 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
382 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600383 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
384 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
385 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200386 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
387 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
388 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
389 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600390 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600391 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600392 { .type = AMD_BIOS_INVALID },
393};
394
Marshall Dawson2794a862019-03-04 16:53:15 -0700395typedef struct _context {
396 char *rom; /* target buffer, size of flash device */
397 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800398 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700399 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800400 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700401} context;
402
403#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800404#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600405 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
406 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
407 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800408#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600409#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800410 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700411#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800412/* The mode in entry can not be higher than the header's.
413 For example, if table mode is 0, all the entry mode will be 0. */
414#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
415 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700416#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
417#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
418#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800419#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
420 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700421#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800422/* Only set the address mode in entry if the table is mode 2. */
423#define SET_ADDR_MODE(table, mode) \
424 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600425 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800426#define SET_ADDR_MODE_BY_TABLE(table) \
427 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700428
Zheng Bao5164e4b2021-10-30 12:09:07 +0800429void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
430{
431 if (count >= max) {
432 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
433 "(%d)\n", count, max);
434 free(ctx->rom);
435 exit(1);
436 }
437}
438
Marshall Dawson24f73d42019-04-01 10:48:43 -0600439static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700440{
441 void *ptr;
442
Marshall Dawson24f73d42019-04-01 10:48:43 -0600443 /*
444 * Force both onto boundary when multi. Primary table is after
445 * updatable table, so alignment ensures primary can stay intact
446 * if secondary is reprogrammed.
447 */
448 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200449 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600450 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200451 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600452
Marshall Dawson2794a862019-03-04 16:53:15 -0700453 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800454 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800455 ((psp_directory_header *)ptr)->additional_info = 0;
456 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700457 ctx->current += sizeof(psp_directory_header)
458 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
459 return ptr;
460}
461
Zheng Baofdd47ef2021-09-17 13:30:08 +0800462static void *new_ish_dir(context *ctx)
463{
464 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200465 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800466 ptr = BUFF_CURRENT(*ctx);
467 ctx->current += TABLE_ALIGNMENT;
468 return ptr;
469}
470
Marshall Dawson2794a862019-03-04 16:53:15 -0700471static void *new_combo_dir(context *ctx)
472{
473 void *ptr;
474
Elyes Haouas7d67a192022-10-14 09:58:29 +0200475 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700476 ptr = BUFF_CURRENT(*ctx);
477 ctx->current += sizeof(psp_combo_header)
478 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
479 return ptr;
480}
481
Zheng Baobf29a0d2020-12-03 23:00:48 +0800482static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800483{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600484 psp_combo_directory *cdir = directory;
485 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600486 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800487 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600488
489 if (!count)
490 return;
Zheng Baob035f582021-05-27 11:26:12 +0800491 if (ctx == NULL || directory == NULL) {
492 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
493 return;
494 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600495
Zheng Baobf29a0d2020-12-03 23:00:48 +0800496 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200497 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800498
Marshall Dawson24f73d42019-04-01 10:48:43 -0600499 switch (cookie) {
500 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700501 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700502 cdir->header.cookie = cookie;
503 cdir->header.num_entries = count;
504 cdir->header.reserved[0] = 0;
505 cdir->header.reserved[1] = 0;
506 /* checksum everything that comes after the Checksum field */
507 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
508 count * sizeof(psp_combo_entry)
509 + sizeof(cdir->header.num_entries)
510 + sizeof(cdir->header.lookup)
511 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600512 break;
513 case PSP_COOKIE:
514 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800515 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800516 if ((table_size % TABLE_ALIGNMENT) != 0) {
517 fprintf(stderr, "The PSP table size should be 4K aligned\n");
518 exit(1);
519 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700520 dir->header.cookie = cookie;
521 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800522 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
523 dir->header.additional_info_fields.spi_block_size = 1;
524 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700525 /* checksum everything that comes after the Checksum field */
526 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700527 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700528 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800529 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600530 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800531 case BHD_COOKIE:
532 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800533 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800534 if ((table_size % TABLE_ALIGNMENT) != 0) {
535 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
536 exit(1);
537 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600538 bdir->header.cookie = cookie;
539 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800540 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
541 bdir->header.additional_info_fields.spi_block_size = 1;
542 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600543 /* checksum everything that comes after the Checksum field */
544 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
545 count * sizeof(bios_directory_entry)
546 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800547 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600548 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700549 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800550
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800551}
552
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700553static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
554{
555 int fd;
556 struct stat fd_stat;
557 ssize_t bytes;
558
559 fd = open(src_file, O_RDONLY);
560 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800561 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700562 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700563 return -1;
564 }
565
566 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800567 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600568 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700569 return -2;
570 }
571
Zheng Bao6d402ac2020-10-01 16:16:30 +0800572 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800573 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600574 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700575 return -3;
576 }
577
578 bytes = read(fd, dest, (size_t)fd_stat.st_size);
579 close(fd);
580 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800581 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700582 return -4;
583 }
584
585 return bytes;
586}
587
Kangheui Won3c164e12021-12-03 20:25:05 +1100588static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
589{
590 ssize_t bytes;
591 size_t total_bytes = 0;
592
593 do {
594 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
595 if (bytes == 0) {
596 fprintf(stderr, "Reached EOF probably\n");
597 break;
598 }
599
600 if (bytes < 0 && errno == EAGAIN)
601 bytes = 0;
602
603 if (bytes < 0) {
604 fprintf(stderr, "Read failure %s\n", strerror(errno));
605 return bytes;
606 }
607
608 total_bytes += bytes;
609 } while (total_bytes < buf_size);
610
611 if (total_bytes != buf_size) {
612 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
613 total_bytes, buf_size);
614 return -1;
615 }
616 return buf_size;
617}
618
619static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
620{
621 ssize_t bytes;
622 size_t total_bytes = 0;
623
624 do {
625 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
626 if (bytes < 0 && errno == EAGAIN)
627 bytes = 0;
628
629 if (bytes < 0) {
630 fprintf(stderr, "Write failure %s\n", strerror(errno));
631 lseek(fd, SEEK_CUR, -total_bytes);
632 return bytes;
633 }
634
635 total_bytes += bytes;
636 } while (total_bytes < buf_size);
637
638 if (total_bytes != buf_size) {
639 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
640 total_bytes, buf_size);
641 lseek(fd, SEEK_CUR, -total_bytes);
642 return -1;
643 }
644
645 return buf_size;
646}
647
Zheng Baoeb0404e2021-10-14 15:09:09 +0800648enum platform {
649 PLATFORM_UNKNOWN,
650 PLATFORM_STONEYRIDGE,
651 PLATFORM_RAVEN,
652 PLATFORM_PICASSO,
653 PLATFORM_RENOIR,
654 PLATFORM_CEZANNE,
655 PLATFORM_MENDOCINO,
656 PLATFORM_LUCIENNE,
Martin Roth13490832022-10-06 17:18:02 -0600657 PLATFORM_MORGANA,
658 PLATFORM_GLINDA
Zheng Baoeb0404e2021-10-14 15:09:09 +0800659};
660
661static uint32_t get_psp_id(enum platform soc_id)
662{
663 uint32_t psp_id;
664 switch (soc_id) {
665 case PLATFORM_RAVEN:
666 case PLATFORM_PICASSO:
667 psp_id = 0xBC0A0000;
668 break;
669 case PLATFORM_RENOIR:
670 case PLATFORM_LUCIENNE:
671 psp_id = 0xBC0C0000;
672 break;
673 case PLATFORM_CEZANNE:
674 psp_id = 0xBC0C0140;
675 break;
676 case PLATFORM_MENDOCINO:
677 psp_id = 0xBC0D0900;
678 break;
679 case PLATFORM_STONEYRIDGE:
680 psp_id = 0x10220B00;
681 break;
682 default:
683 psp_id = 0;
684 break;
685 }
686 return psp_id;
687}
688
Kangheui Won3c164e12021-12-03 20:25:05 +1100689static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
690{
691 switch (soc_id) {
692 case PLATFORM_MENDOCINO:
693 /* Fallback to fw_type if fw_id is not populated, which serves the same
694 purpose on older SoCs. */
695 return header->fw_id ? header->fw_id : header->fw_type;
696 default:
697 return header->fw_type;
698 }
699}
700
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100701static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
702{
703 uint8_t hash[SHA384_DIGEST_LENGTH];
704 struct amd_fw_header *header = (struct amd_fw_header *)buf;
705 /* Include only signed part for hash calculation. */
706 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
707 uint8_t *body = (uint8_t *)buf;
708
709 if (len > header->size_total)
710 return -1;
711
712 if (header->sig_id == SIG_ID_RSA4096) {
713 SHA384(body, len, hash);
714 entry->sha_len = SHA384_DIGEST_LENGTH;
715 } else if (header->sig_id == SIG_ID_RSA2048) {
716 SHA256(body, len, hash);
717 entry->sha_len = SHA256_DIGEST_LENGTH;
718 } else {
719 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
720 __func__, header->sig_id);
721 return -1;
722 }
723
724 memcpy(entry->sha, hash, entry->sha_len);
725 entry->fw_id = get_psp_fw_type(soc_id, header);
726 entry->subtype = header->fw_subtype;
727
728 return 0;
729}
730
731static int get_num_binaries(void *buf, size_t buf_size)
732{
733 struct amd_fw_header *header = (struct amd_fw_header *)buf;
734 size_t total_len = 0;
735 int num_binaries = 0;
736
737 while (total_len < buf_size) {
738 num_binaries++;
739 total_len += header->size_total;
740 header = (struct amd_fw_header *)(buf + total_len);
741 }
742
743 if (total_len != buf_size) {
744 fprintf(stderr, "Malformed binary\n");
745 return -1;
746 }
747 return num_binaries;
748}
749
750static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
751{
752 struct amd_fw_header *header = (struct amd_fw_header *)buf;
753 /* Include only signed part for hash calculation. */
754 size_t total_len = 0;
755 int num_binaries = get_num_binaries(buf, buf_size);
756
757 if (num_binaries <= 0)
758 return num_binaries;
759
760 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
761 if (!entry->hash_entries) {
762 fprintf(stderr, "Error allocating memory to add FW hash\n");
763 return -1;
764 }
765 entry->num_hash_entries = num_binaries;
766
767 /* Iterate through each binary */
768 for (int i = 0; i < num_binaries; i++) {
769 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
770 free(entry->hash_entries);
771 return -1;
772 }
773 total_len += header->size_total;
774 header = (struct amd_fw_header *)(buf + total_len);
775 }
776
777 return 0;
778}
779
Marshall Dawson2794a862019-03-04 16:53:15 -0700780static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700781 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700782 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800783{
Richard Spiegel137484d2018-01-17 10:23:19 -0700784 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800785 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700786
Elyes Haouas7d67a192022-10-14 09:58:29 +0200787 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800788
Martin Rothcd15bc82016-11-08 11:34:02 -0700789 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800790 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800791 switch (fw_table[i].type) {
792 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200793 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700794 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800795 break;
796 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700797 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800798 break;
799 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700800 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800801 break;
802 default:
803 /* Error */
804 break;
805 }
806
Marshall Dawson2794a862019-03-04 16:53:15 -0700807 bytes = copy_blob(BUFF_CURRENT(*ctx),
808 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600809 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700810 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700811 exit(1);
812 }
813
Elyes Haouas7d67a192022-10-14 09:58:29 +0200814 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700815 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800816 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800817 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800818}
819
Zheng Bao9e908072020-10-28 11:39:13 +0800820/* For debugging */
821static void dump_psp_firmwares(amd_fw_entry *fw_table)
822{
823 amd_fw_entry *index;
824
825 printf("PSP firmware components:");
826 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
827 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800828 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800829 }
830}
831
832static void dump_bdt_firmwares(amd_bios_entry *fw_table)
833{
834 amd_bios_entry *index;
835
836 printf("BIOS Directory Table (BDT) components:");
837 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
838 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800839 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800840 }
841}
842
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800843static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
844{
845 amd_fw_entry *index;
846
847 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
848 if (index->filename &&
849 index->type != AMD_FW_VERSTAGE_SIG &&
850 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800851 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800852 index->type != AMD_FW_PSP_WHITELIST) {
853 free(index->filename);
854 }
855 }
856}
857
858static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
859{
860 amd_bios_entry *index;
861
862 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
863 if (index->filename &&
864 index->type != AMD_BIOS_APCB &&
865 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200866 index->type != AMD_BIOS_APCB_BK &&
867 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800868 free(index->filename);
869 }
870}
871
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100872static void write_or_fail(int fd, void *ptr, size_t size)
873{
874 ssize_t written;
875
876 written = write_from_buf_to_file(fd, ptr, size);
877 if (written < 0 || (size_t)written != size) {
878 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
879 __func__, size, written);
880 exit(-1);
881 }
882}
883
884static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
885{
886 uint16_t type = entry->fw_id;
887 uint16_t subtype = entry->subtype;
888
889 write_or_fail(fd, &type, sizeof(type));
890 write_or_fail(fd, &subtype, sizeof(subtype));
891 write_or_fail(fd, entry->sha, entry->sha_len);
892}
893
894static void write_psp_firmware_hash(const char *filename,
895 amd_fw_entry *fw_table)
896{
897 struct psp_fw_hash_table hash_header = {0};
898 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
899
900 if (fd < 0) {
901 fprintf(stderr, "Error opening file: %s: %s\n",
902 filename, strerror(errno));
903 exit(-1);
904 }
905
906 hash_header.version = HASH_HDR_V1;
907 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
908 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
909 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
910 hash_header.no_of_entries_256++;
911 } else if (fw_table[i].hash_entries[j].sha_len ==
912 SHA384_DIGEST_LENGTH) {
913 hash_header.no_of_entries_384++;
914 } else if (fw_table[i].hash_entries[j].sha_len) {
915 fprintf(stderr, "%s: Error invalid sha_len %d\n",
916 __func__, fw_table[i].hash_entries[j].sha_len);
917 exit(-1);
918 }
919 }
920 }
921
922 write_or_fail(fd, &hash_header, sizeof(hash_header));
923
924 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
925 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
926 will cause the hash verification failure at run-time. */
927 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
928 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
929 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
930 write_one_psp_firmware_hash_entry(fd,
931 &fw_table[i].hash_entries[j]);
932 }
933 }
934
935 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
936 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
937 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
938 write_one_psp_firmware_hash_entry(fd,
939 &fw_table[i].hash_entries[j]);
940 }
941 }
942
943 close(fd);
944 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
945 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
946 continue;
947
948 free(fw_table[i].hash_entries);
949 fw_table[i].hash_entries = NULL;
950 fw_table[i].num_hash_entries = 0;
951 }
952}
953
Kangheui Won3c164e12021-12-03 20:25:05 +1100954/**
955 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
956 * @signed_rom: Output file path grouping all the signed PSP binaries.
957 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
958 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
959 * the signed PSP binaries.
960 * @soc_id: SoC ID of the PSP binaries.
961 */
962static void process_signed_psp_firmwares(const char *signed_rom,
963 amd_fw_entry *fw_table,
964 uint64_t signed_start_addr,
965 enum platform soc_id)
966{
967 unsigned int i;
968 int fd;
969 int signed_rom_fd;
970 ssize_t bytes, align_bytes;
971 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100972 char *signed_rom_hash;
973 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +1100974 struct amd_fw_header header;
975 struct stat fd_stat;
976 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
977 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
978 uint8_t align_data[BLOB_ALIGNMENT - 1];
979
980 memset(align_data, 0xff, sizeof(align_data));
981 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
982 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
983 if (signed_rom_fd < 0) {
984 fprintf(stderr, "Error opening file: %s: %s\n",
985 signed_rom, strerror(errno));
986 return;
987 }
988
989 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100990 fw_table[i].num_hash_entries = 0;
991 fw_table[i].hash_entries = NULL;
992
Kangheui Won3c164e12021-12-03 20:25:05 +1100993 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
994 continue;
995
996 memset(&header, 0, sizeof(header));
997
998 fd = open(fw_table[i].filename, O_RDONLY);
999 if (fd < 0) {
1000 /* Keep the file along with set of unsigned PSP binaries & continue. */
1001 fprintf(stderr, "Error opening file: %s: %s\n",
1002 fw_table[i].filename, strerror(errno));
1003 continue;
1004 }
1005
1006 if (fstat(fd, &fd_stat)) {
1007 /* Keep the file along with set of unsigned PSP binaries & continue. */
1008 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1009 close(fd);
1010 continue;
1011 }
1012
1013 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1014 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1015 /* Keep the file along with set of unsigned PSP binaries & continue. */
1016 fprintf(stderr, "%s: Error reading header from %s\n",
1017 __func__, fw_table[i].filename);
1018 close(fd);
1019 continue;
1020 }
1021
1022 /* If firmware header looks like invalid, assume it's not signed */
1023 if (!header.fw_type && !header.fw_id) {
1024 fprintf(stderr, "%s: Invalid FWID for %s\n",
1025 __func__, fw_table[i].filename);
1026 close(fd);
1027 continue;
1028 }
1029
Kangheui Won3c164e12021-12-03 20:25:05 +11001030
1031 /* PSP binary is not signed and should not be part of signed PSP binaries
1032 set. */
1033 if (header.sig_opt != 1) {
1034 close(fd);
1035 continue;
1036 }
1037
1038 buf = malloc(fd_stat.st_size);
1039 if (!buf) {
1040 /* Keep the file along with set of unsigned PSP binaries & continue. */
1041 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1042 __func__, (long long)fd_stat.st_size);
1043 close(fd);
1044 continue;
1045 }
1046
1047 lseek(fd, SEEK_SET, 0);
1048 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1049 if (bytes != fd_stat.st_size) {
1050 /* Keep the file along with set of unsigned PSP binaries & continue. */
1051 fprintf(stderr, "%s: failed to read %s\n",
1052 __func__, fw_table[i].filename);
1053 free(buf);
1054 close(fd);
1055 continue;
1056 }
1057
1058 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1059 if (bytes != fd_stat.st_size) {
1060 /* Keep the file along with set of unsigned PSP binaries & continue. */
1061 fprintf(stderr, "%s: failed to write %s\n",
1062 __func__, fw_table[i].filename);
1063 free(buf);
1064 close(fd);
1065 continue;
1066 }
1067
1068 /* Write Blob alignment bytes */
1069 align_bytes = 0;
1070 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1071 align_bytes = BLOB_ALIGNMENT -
1072 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1073 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1074 if (bytes != align_bytes) {
1075 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1076 __func__, fw_table[i].filename);
1077 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1078 free(buf);
1079 close(fd);
1080 continue;
1081 }
1082 }
1083
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001084 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1085 exit(-1);
1086
Kangheui Won3c164e12021-12-03 20:25:05 +11001087 /* File is successfully processed and is part of signed PSP binaries set. */
1088 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1089 fw_table[i].addr_signed = signed_start_addr;
1090 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1091
1092 signed_start_addr += fd_stat.st_size + align_bytes;
1093
1094 free(buf);
1095 close(fd);
1096 }
1097
1098 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001099
1100 /* signed_rom file name + ".hash" + '\0' */
1101 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1102 signed_rom_hash = malloc(signed_rom_hash_strlen);
1103 if (!signed_rom_hash) {
1104 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1105 exit(-1);
1106 }
1107 strcpy(signed_rom_hash, signed_rom);
1108 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1109 write_psp_firmware_hash(signed_rom_hash, fw_table);
1110 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001111}
1112
Zheng Bao990d1542021-09-17 13:24:54 +08001113static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001114 psp_directory_table *pspdir2, ish_directory_table *ish,
1115 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001116{
1117 uint32_t count;
1118 uint32_t current_table_save;
1119
1120 current_table_save = ctx->current_table;
1121 ctx->current_table = (char *)pspdir - ctx->rom;
1122 count = pspdir->header.num_entries;
1123 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1124 pspdir->entries[count].type = (uint8_t)ab;
1125 pspdir->entries[count].subprog = 0;
1126 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001127 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001128 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001129 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1130 ish->update_retry_count = 2;
1131 ish->glitch_retry_count = 0;
1132 ish->psp_id = get_psp_id(soc_id);
1133 ish->checksum = fletcher32(&ish->boot_priority,
1134 sizeof(ish_directory_table) - sizeof(uint32_t));
1135 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001136 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001137 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001138 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001139 pspdir->entries[count].size = TABLE_ALIGNMENT;
1140 } else {
1141 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001142 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001143 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001144 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001145 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001146 sizeof(psp_directory_entry) +
1147 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001148 }
Zheng Bao990d1542021-09-17 13:24:54 +08001149
1150 count++;
1151 pspdir->header.num_entries = count;
1152 ctx->current_table = current_table_save;
1153}
1154
Marshall Dawson2794a862019-03-04 16:53:15 -07001155static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001156 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001157 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001158 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001159 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001160 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001161 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +08001162 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001163{
Richard Spiegel137484d2018-01-17 10:23:19 -07001164 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001165 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001166 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301167 uint32_t size;
1168 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001169 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001170 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001171 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001172
1173 /* This function can create a primary table, a secondary table, or a
1174 * flattened table which contains all applicable types. These if-else
1175 * statements infer what the caller intended. If a 2nd-level cookie
1176 * is passed, clearly a 2nd-level table is intended. However, a
1177 * 1st-level cookie may indicate level 1 or flattened. If the caller
1178 * passes a pointer to a 2nd-level table, then assume not flat.
1179 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001180 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001181 level = PSP_BOTH;
1182 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001183 level = PSP_LVL2;
1184 else if (pspdir2)
1185 level = PSP_LVL1;
1186 else
1187 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001188
Zheng Bao990d1542021-09-17 13:24:54 +08001189 if (recovery_ab) {
1190 if (cookie == PSPL2_COOKIE)
1191 level = PSP_LVL2_AB;
1192 else if (pspdir2)
1193 level = PSP_LVL1_AB;
1194 else
1195 level = PSP_BOTH_AB;
1196 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001197 current_table_save = ctx->current_table;
1198 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001199 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001200
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001201 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001202 if (!(fw_table[i].level & level))
1203 continue;
1204
Zheng Bao5164e4b2021-10-30 12:09:07 +08001205 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1206
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001207 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1208 if (!fw_table[i].other)
1209 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001210 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001211 pspdir->entries[count].type = fw_table[i].type;
1212 pspdir->entries[count].size = 4096; /* TODO: doc? */
1213 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001214 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001215 pspdir->entries[count].subprog = fw_table[i].subprog;
1216 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001217 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001218 count++;
1219 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001220 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001221 pspdir->entries[count].subprog = fw_table[i].subprog;
1222 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001223 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001224 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001225 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001226 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001227 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301228 if (fw_table[i].filename == NULL) {
1229 if (fw_table[i].size == 0)
1230 continue;
1231 size = fw_table[i].size;
1232 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001233 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301234 fprintf(stderr,
1235 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1236 exit(1);
1237 }
1238 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001239 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301240 bytes = copy_blob(BUFF_CURRENT(*ctx),
1241 fw_table[i].filename, BUFF_ROOM(*ctx));
1242 if (bytes <= 0) {
1243 free(ctx->rom);
1244 exit(1);
1245 }
1246
Elyes Haouas7d67a192022-10-14 09:58:29 +02001247 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301248 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001249 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301250 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001251 }
1252
1253 pspdir->entries[count].type = fw_table[i].type;
1254 pspdir->entries[count].subprog = fw_table[i].subprog;
1255 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301256 pspdir->entries[count].size = size;
1257 pspdir->entries[count].addr = addr;
1258
Zheng Bao6fff2492021-11-15 19:53:21 +08001259 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001260 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001261
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001262 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001263 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001264 if (fw_table[i].addr_signed) {
1265 pspdir->entries[count].addr =
1266 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1267 pspdir->entries[count].address_mode =
1268 SET_ADDR_MODE_BY_TABLE(pspdir);
1269 bytes = fw_table[i].file_size;
1270 } else {
1271 bytes = copy_blob(BUFF_CURRENT(*ctx),
1272 fw_table[i].filename, BUFF_ROOM(*ctx));
1273 if (bytes < 0) {
1274 free(ctx->rom);
1275 exit(1);
1276 }
1277 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1278 pspdir->entries[count].address_mode =
1279 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001280 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001281 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001282 }
1283
Marshall Dawson239286c2019-02-23 16:42:46 -07001284 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001285 pspdir->entries[count].subprog = fw_table[i].subprog;
1286 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001287 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001288
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001289 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001290 } else {
1291 /* This APU doesn't have this firmware. */
1292 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001293 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001294
Zheng Bao990d1542021-09-17 13:24:54 +08001295 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001296 if (cb_config->need_ish) { /* Need ISH */
1297 ish_a_dir = new_ish_dir(ctx);
1298 if (pspdir2_b != NULL)
1299 ish_b_dir = new_ish_dir(ctx);
1300 }
Zheng Bao990d1542021-09-17 13:24:54 +08001301 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001302 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
1303 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001304 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001305 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
1306 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001307 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001308 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001309 AMD_FW_RECOVERYAB_B, soc_id);
1310
Zheng Bao990d1542021-09-17 13:24:54 +08001311 count = pspdir->header.num_entries;
1312 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001313 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001314 pspdir->entries[count].type = AMD_FW_L2_PTR;
1315 pspdir->entries[count].subprog = 0;
1316 pspdir->entries[count].rsvd = 0;
1317 pspdir->entries[count].size = sizeof(pspdir2->header)
1318 + pspdir2->header.num_entries
1319 * sizeof(psp_directory_entry);
1320
Zheng Bao6fff2492021-11-15 19:53:21 +08001321 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001322 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001323 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001324 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001325 count++;
1326 }
1327
Zheng Baobf29a0d2020-12-03 23:00:48 +08001328 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001329 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001330}
1331
Zheng Bao990d1542021-09-17 13:24:54 +08001332static void add_psp_firmware_entry(context *ctx,
1333 psp_directory_table *pspdir,
1334 void *table, amd_fw_type type, uint32_t size)
1335{
1336 uint32_t count = pspdir->header.num_entries;
1337 uint32_t index;
1338 uint32_t current_table_save;
1339
1340 current_table_save = ctx->current_table;
1341 ctx->current_table = (char *)pspdir - ctx->rom;
1342
1343 /* If there is an entry of "type", replace it. */
1344 for (index = 0; index < count; index++) {
1345 if (pspdir->entries[index].type == (uint8_t)type)
1346 break;
1347 }
1348
1349 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1350 pspdir->entries[index].type = (uint8_t)type;
1351 pspdir->entries[index].subprog = 0;
1352 pspdir->entries[index].rsvd = 0;
1353 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1354 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1355 pspdir->entries[index].size = size;
1356 if (index == count)
1357 count++;
1358
1359 pspdir->header.num_entries = count;
1360 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1361 count * sizeof(psp_directory_entry)
1362 + sizeof(pspdir->header.num_entries)
1363 + sizeof(pspdir->header.additional_info));
1364
1365 ctx->current_table = current_table_save;
1366}
1367
Zheng Baoba3af5e2021-11-04 18:56:47 +08001368static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001369{
1370 void *ptr;
1371
1372 /*
1373 * Force both onto boundary when multi. Primary table is after
1374 * updatable table, so alignment ensures primary can stay intact
1375 * if secondary is reprogrammed.
1376 */
1377 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001378 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001379 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001380 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001381 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001382 ((bios_directory_hdr *) ptr)->additional_info = 0;
1383 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1384 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001385 ctx->current += sizeof(bios_directory_hdr)
1386 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1387 return ptr;
1388}
1389
1390static int locate_bdt2_bios(bios_directory_table *level2,
1391 uint64_t *source, uint32_t *size)
1392{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001393 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001394
1395 *source = 0;
1396 *size = 0;
1397 if (!level2)
1398 return 0;
1399
1400 for (i = 0 ; i < level2->header.num_entries ; i++) {
1401 if (level2->entries[i].type == AMD_BIOS_BIN) {
1402 *source = level2->entries[i].source;
1403 *size = level2->entries[i].size;
1404 return 1;
1405 }
1406 }
1407 return 0;
1408}
1409
1410static int have_bios_tables(amd_bios_entry *table)
1411{
1412 int i;
1413
1414 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1415 if (table[i].level & BDT_LVL1 && table[i].filename)
1416 return 1;
1417 }
1418 return 0;
1419}
1420
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001421static int find_bios_entry(amd_bios_type type)
1422{
1423 int i;
1424
1425 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1426 if (amd_bios_table[i].type == type)
1427 return i;
1428 }
1429 return -1;
1430}
1431
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001432static void integrate_bios_firmwares(context *ctx,
1433 bios_directory_table *biosdir,
1434 bios_directory_table *biosdir2,
1435 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001436 uint32_t cookie,
1437 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001438{
1439 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001440 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001441 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001442 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001443 uint32_t size;
1444 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001445
1446 /* This function can create a primary table, a secondary table, or a
1447 * flattened table which contains all applicable types. These if-else
1448 * statements infer what the caller intended. If a 2nd-level cookie
1449 * is passed, clearly a 2nd-level table is intended. However, a
1450 * 1st-level cookie may indicate level 1 or flattened. If the caller
1451 * passes a pointer to a 2nd-level table, then assume not flat.
1452 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001453 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001454 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001455 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001456 level = BDT_LVL2;
1457 else if (biosdir2)
1458 level = BDT_LVL1;
1459 else
1460 level = BDT_BOTH;
1461
Elyes Haouas7d67a192022-10-14 09:58:29 +02001462 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001463
1464 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1465 if (!(fw_table[i].level & level))
1466 continue;
1467 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301468 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001469 fw_table[i].type != AMD_BIOS_APOB &&
1470 fw_table[i].type != AMD_BIOS_APOB_NV &&
1471 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001472 fw_table[i].type != AMD_BIOS_BIN &&
1473 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001474 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001475
1476 /* BIOS Directory items may have additional requirements */
1477
Ritul Guru9a321f32022-07-29 11:06:40 +05301478 /* SIG needs a size, else no choice but to skip */
1479 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1480 continue;
1481
Martin Roth48dd9fe2020-07-29 16:32:25 -06001482 /* Check APOB_NV requirements */
1483 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1484 if (!fw_table[i].size && !fw_table[i].src)
1485 continue; /* APOB_NV not used */
1486 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001487 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001488 free(ctx->rom);
1489 exit(1);
1490 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001491 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001492 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001493 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1494 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001495 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001496
1497 /* APOB_DATA needs destination */
1498 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001499 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001500 free(ctx->rom);
1501 exit(1);
1502 }
1503
1504 /* BIOS binary must have destination and uncompressed size. If
1505 * no filename given, then user must provide a source address.
1506 */
1507 if (fw_table[i].type == AMD_BIOS_BIN) {
1508 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001509 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001510 free(ctx->rom);
1511 exit(1);
1512 }
1513 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001514 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001515 free(ctx->rom);
1516 exit(1);
1517 }
1518 }
1519
Martin Roth94554742020-04-14 14:59:36 -06001520 /* PSP_SHARED_MEM needs a destination and size */
1521 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1522 (!fw_table[i].dest || !fw_table[i].size))
1523 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001524 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001525
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001526 biosdir->entries[count].type = fw_table[i].type;
1527 biosdir->entries[count].region_type = fw_table[i].region_type;
1528 biosdir->entries[count].dest = fw_table[i].dest ?
1529 fw_table[i].dest : (uint64_t)-1;
1530 biosdir->entries[count].reset = fw_table[i].reset;
1531 biosdir->entries[count].copy = fw_table[i].copy;
1532 biosdir->entries[count].ro = fw_table[i].ro;
1533 biosdir->entries[count].compressed = fw_table[i].zlib;
1534 biosdir->entries[count].inst = fw_table[i].inst;
1535 biosdir->entries[count].subprog = fw_table[i].subpr;
1536
1537 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301538 case AMD_BIOS_SIG:
1539 /* Reserve size bytes within amdfw.rom */
1540 biosdir->entries[count].size = fw_table[i].size;
1541 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1542 biosdir->entries[count].address_mode =
1543 SET_ADDR_MODE_BY_TABLE(biosdir);
1544 memset(BUFF_CURRENT(*ctx), 0xff,
1545 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001546 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301547 + biosdir->entries[count].size, 0x100U);
1548 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001549 case AMD_BIOS_APOB:
1550 biosdir->entries[count].size = fw_table[i].size;
1551 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001552 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001553 break;
1554 case AMD_BIOS_APOB_NV:
1555 if (fw_table[i].src) {
1556 /* If source is given, use that and its size */
1557 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001558 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001559 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001560 biosdir->entries[count].size = fw_table[i].size;
1561 } else {
1562 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001563 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001564 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001565 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001566 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001567 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001568 fw_table[i].size, ERASE_ALIGNMENT);
1569 memset(BUFF_CURRENT(*ctx), 0xff,
1570 biosdir->entries[count].size);
1571 ctx->current = ctx->current
1572 + biosdir->entries[count].size;
1573 }
1574 break;
1575 case AMD_BIOS_BIN:
1576 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001577 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1578 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001579 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001580 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001581 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001582 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001583 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001584
1585 /* level 2, or level 1 and no copy found in level 2 */
1586 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001587 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001588 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001589 biosdir->entries[count].dest = fw_table[i].dest;
1590 biosdir->entries[count].size = fw_table[i].size;
1591
1592 if (!fw_table[i].filename)
1593 break;
1594
1595 bytes = copy_blob(BUFF_CURRENT(*ctx),
1596 fw_table[i].filename, BUFF_ROOM(*ctx));
1597 if (bytes <= 0) {
1598 free(ctx->rom);
1599 exit(1);
1600 }
1601
Zheng Bao6fff2492021-11-15 19:53:21 +08001602 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001603 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001604 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001605 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001606
Elyes Haouas7d67a192022-10-14 09:58:29 +02001607 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001608 break;
Martin Roth94554742020-04-14 14:59:36 -06001609 case AMD_BIOS_PSP_SHARED_MEM:
1610 biosdir->entries[count].dest = fw_table[i].dest;
1611 biosdir->entries[count].size = fw_table[i].size;
1612 break;
1613
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001614 default: /* everything else is copied from input */
1615 if (fw_table[i].type == AMD_BIOS_APCB ||
1616 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001617 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001618 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001619 bytes = copy_blob(BUFF_CURRENT(*ctx),
1620 fw_table[i].filename, BUFF_ROOM(*ctx));
1621 if (bytes <= 0) {
1622 free(ctx->rom);
1623 exit(1);
1624 }
1625
1626 biosdir->entries[count].size = (uint32_t)bytes;
1627 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001628 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001629
Elyes Haouas7d67a192022-10-14 09:58:29 +02001630 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001631 break;
1632 }
1633
1634 count++;
1635 }
1636
1637 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001638 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001639 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001640 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001641 biosdir->entries[count].size =
1642 + MAX_BIOS_ENTRIES
1643 * sizeof(bios_directory_entry);
1644 biosdir->entries[count].source =
1645 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001646 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001647 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001648 biosdir->entries[count].subprog = 0;
1649 biosdir->entries[count].inst = 0;
1650 biosdir->entries[count].copy = 0;
1651 biosdir->entries[count].compressed = 0;
1652 biosdir->entries[count].dest = -1;
1653 biosdir->entries[count].reset = 0;
1654 biosdir->entries[count].ro = 0;
1655 count++;
1656 }
1657
Zheng Baobf29a0d2020-12-03 23:00:48 +08001658 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001659}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001660
1661enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001662 AMDFW_OPT_CONFIG = 'c',
1663 AMDFW_OPT_DEBUG = 'd',
1664 AMDFW_OPT_HELP = 'h',
1665 AMDFW_OPT_LIST_DEPEND = 'l',
1666
1667 AMDFW_OPT_XHCI = 128,
1668 AMDFW_OPT_IMC,
1669 AMDFW_OPT_GEC,
1670 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001671 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001672 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001673 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001674 AMDFW_OPT_MULTILEVEL,
1675 AMDFW_OPT_NVRAM,
1676
1677 AMDFW_OPT_FUSE,
1678 AMDFW_OPT_UNLOCK,
1679 AMDFW_OPT_WHITELIST,
1680 AMDFW_OPT_USE_PSPSECUREOS,
1681 AMDFW_OPT_LOAD_MP2FW,
1682 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001683 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001684 AMDFW_OPT_VERSTAGE,
1685 AMDFW_OPT_VERSTAGE_SIG,
1686
1687 AMDFW_OPT_INSTANCE,
1688 AMDFW_OPT_APCB,
1689 AMDFW_OPT_APOBBASE,
1690 AMDFW_OPT_BIOSBIN,
1691 AMDFW_OPT_BIOSBIN_SOURCE,
1692 AMDFW_OPT_BIOSBIN_DEST,
1693 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1694 AMDFW_OPT_UCODE,
1695 AMDFW_OPT_APOB_NVBASE,
1696 AMDFW_OPT_APOB_NVSIZE,
1697
1698 AMDFW_OPT_OUTPUT,
1699 AMDFW_OPT_FLASHSIZE,
1700 AMDFW_OPT_LOCATION,
1701 AMDFW_OPT_ANYWHERE,
1702 AMDFW_OPT_SHAREDMEM,
1703 AMDFW_OPT_SHAREDMEM_SIZE,
1704 AMDFW_OPT_SOC_NAME,
Kangheui Won3c164e12021-12-03 20:25:05 +11001705 AMDFW_OPT_SIGNED_OUTPUT,
1706 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001707 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001708 /* begin after ASCII characters */
1709 LONGOPT_SPI_READ_MODE = 256,
1710 LONGOPT_SPI_SPEED = 257,
1711 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301712 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301713 LONGOPT_NVRAM_BASE = 260,
1714 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001715};
1716
Zheng Bao806892a2021-04-27 17:21:54 +08001717static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1718 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1719};
Marc Jones90099b62016-09-20 21:05:45 -06001720
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001721static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001722 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1723 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1724 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001725 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001726 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001727 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001728 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001729 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001730 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1731 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301732 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1733 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001734 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1735 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1736 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1737 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1738 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1739 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001740 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001741 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1742 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001743 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001744 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1745 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1746 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1747 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1748 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1749 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1750 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301751 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001752 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1753 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1754 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001755 /* Embedded Firmware Structure items*/
1756 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1757 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1758 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001759 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001760 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001761 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1762 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1763 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1764 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1765 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1766 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1767 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001768
Kangheui Won3c164e12021-12-03 20:25:05 +11001769 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1770 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1771
Zheng Bao806892a2021-04-27 17:21:54 +08001772 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1773 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1774 {"help", no_argument, 0, AMDFW_OPT_HELP },
1775 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001776 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001777};
1778
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001779void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001780{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001781 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001782
1783 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1784 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1785 continue;
1786
1787 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1788 return;
1789 }
1790}
1791
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001792static void register_fw_token_unlock(void)
1793{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001794 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001795
1796 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1797 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1798 continue;
1799
1800 amd_psp_fw_table[i].other = 1;
1801 return;
1802 }
1803}
1804
Marshall Dawsondbae6322019-03-04 10:31:03 -07001805static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001806{
Martin Roth8806f7f2016-11-08 10:44:18 -07001807 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001808
Martin Rothcd15bc82016-11-08 11:34:02 -07001809 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001810 if (amd_fw_table[i].type == type) {
1811 amd_fw_table[i].filename = filename;
1812 return;
1813 }
1814 }
1815
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001816 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001817 if (amd_psp_fw_table[i].type != type)
1818 continue;
1819
1820 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001821 amd_psp_fw_table[i].filename = filename;
1822 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001823 }
1824 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001825}
1826
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001827static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1828{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001829 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001830
1831 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1832 if (amd_bios_table[i].type == type
1833 && amd_bios_table[i].inst == ins
1834 && amd_bios_table[i].subpr == sub) {
1835 amd_bios_table[i].filename = name;
1836 return;
1837 }
1838 }
1839}
1840
Ritul Gurua2cb3402022-08-29 00:51:08 +05301841static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1842 char *dst_str, char *size_str)
1843{
1844 unsigned int i;
1845
1846 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1847 if (amd_psp_fw_table[i].type != type)
1848 continue;
1849
1850 if (amd_psp_fw_table[i].subprog == sub) {
1851 if (dst_str)
1852 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1853 if (size_str)
1854 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1855 return;
1856 }
1857 }
1858}
1859
1860static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001861 char *dst_str, char *size_str)
1862{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001863 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001864 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1865 if (amd_bios_table[i].type != type)
1866 continue;
1867
1868 if (src_str)
1869 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1870 if (dst_str)
1871 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1872 if (size_str)
1873 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1874
1875 return;
1876 }
1877}
1878
Zheng Baoc3007f32022-04-03 12:53:51 +08001879static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1880 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1881 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001882{
1883 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001884 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001885 return 1;
1886 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001887
1888 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1889 * Leave as 0xffffffff for first gen */
1890 if (cb_config->second_gen) {
1891 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1892 amd_romsig->efs_gen.reserved = 0;
1893 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001894 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1895 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001896 }
1897
1898 switch (soc_id) {
1899 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001900 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1901 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1902 break;
1903 case PLATFORM_RAVEN:
1904 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001905 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1906 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1907 switch (efs_spi_micron_flag) {
1908 case 0:
1909 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1910 break;
1911 case 1:
1912 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1913 break;
1914 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001915 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001916 return 1;
1917 }
1918 break;
1919 case PLATFORM_RENOIR:
1920 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001921 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001922 case PLATFORM_MENDOCINO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001923 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1924 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1925 switch (efs_spi_micron_flag) {
1926 case 0:
1927 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1928 break;
1929 case 1:
1930 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1931 break;
1932 case 2:
1933 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1934 break;
1935 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001936 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001937 return 1;
1938 }
1939 break;
Martin Roth13490832022-10-06 17:18:02 -06001940 /* TODO: Update for morgana and glinda */
1941 case PLATFORM_MORGANA:
1942 case PLATFORM_GLINDA:
1943 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001944 case PLATFORM_UNKNOWN:
1945 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001946 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001947 return 1;
1948 }
1949 return 0;
1950}
1951
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001952static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
1953{
1954 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
1955 int ret;
1956 int fd;
1957 ssize_t bytes = -1;
1958
1959 /* Create a tmp file and rename it at the end so that make does not get confused
1960 if amdfwtool is killed for some unexpected reasons. */
1961 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
1962 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
1963 if (ret < 0) {
1964 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
1965 strerror(errno), ret);
1966 exit(1);
1967 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
1968 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
1969 exit(1);
1970 }
1971
1972 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
1973 if (fd < 0) {
1974 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
1975 exit(1);
1976 }
1977
1978 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
1979 if (bytes != sizeof(*amd_romsig)) {
1980 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
1981 exit(1);
1982 }
1983 close(fd);
1984
1985 /* Rename the tmp file */
1986 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
1987 if (ret < 0) {
1988 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
1989 exit(1);
1990 }
1991
1992 if (rename(efs_tmp_name, efs_name)) {
1993 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
1994 exit(1);
1995 }
1996
1997 return bytes;
1998}
1999
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002000static int identify_platform(char *soc_name)
2001{
2002 if (!strcasecmp(soc_name, "Stoneyridge"))
2003 return PLATFORM_STONEYRIDGE;
2004 else if (!strcasecmp(soc_name, "Raven"))
2005 return PLATFORM_RAVEN;
2006 else if (!strcasecmp(soc_name, "Picasso"))
2007 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002008 else if (!strcasecmp(soc_name, "Cezanne"))
2009 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08002010 else if (!strcasecmp(soc_name, "Mendocino"))
2011 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002012 else if (!strcasecmp(soc_name, "Renoir"))
2013 return PLATFORM_RENOIR;
2014 else if (!strcasecmp(soc_name, "Lucienne"))
2015 return PLATFORM_LUCIENNE;
Martin Roth13490832022-10-06 17:18:02 -06002016 else if (!strcasecmp(soc_name, "Morgana"))
2017 return PLATFORM_MORGANA;
2018 else if (!strcasecmp(soc_name, "Glinda"))
2019 return PLATFORM_GLINDA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002020 else
2021 return PLATFORM_UNKNOWN;
2022
2023}
2024
Felix Heldf8e2e472022-03-29 23:28:49 +02002025static bool needs_ish(enum platform platform_type)
2026{
Jon Murphy9969f4b2022-08-05 13:56:38 -06002027 if (platform_type == PLATFORM_MENDOCINO)
Felix Heldf8e2e472022-03-29 23:28:49 +02002028 return true;
2029 else
2030 return false;
2031}
2032
Zheng Baoc3007f32022-04-03 12:53:51 +08002033static bool is_second_gen(enum platform platform_type)
2034{
2035 switch (platform_type) {
2036 case PLATFORM_STONEYRIDGE:
2037 case PLATFORM_RAVEN:
2038 case PLATFORM_PICASSO:
2039 return false;
2040 case PLATFORM_RENOIR:
2041 case PLATFORM_LUCIENNE:
2042 case PLATFORM_CEZANNE:
Jon Murphy9969f4b2022-08-05 13:56:38 -06002043 case PLATFORM_MENDOCINO:
Zheng Baoc3007f32022-04-03 12:53:51 +08002044 return true;
2045 case PLATFORM_UNKNOWN:
2046 default:
2047 fprintf(stderr, "Error: Invalid SOC name.\n\n");
2048 return false;
2049 }
2050}
2051
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002052int main(int argc, char **argv)
2053{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002054 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002055 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002056 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002057 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002058 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002059 psp_directory_table *pspdir = NULL;
2060 psp_directory_table *pspdir2 = NULL;
2061 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08002062 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002063 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002064 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002065 char *output = NULL, *config = NULL;
2066 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002067 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002068 /* Values cleared after each firmware or parameter, regardless if N/A */
2069 uint8_t sub = 0, instance = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002070 uint32_t dir_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002071 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002072 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002073 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002074 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002075 uint8_t soc_id = PLATFORM_UNKNOWN;
2076 uint8_t efs_spi_readmode = 0xff;
2077 uint8_t efs_spi_speed = 0xff;
2078 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002079 const char *signed_output_file = NULL;
2080 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002081
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002082 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002083 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002084 int list_deps = 0;
2085
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002086 while (1) {
2087 int optindex = 0;
2088
2089 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2090
2091 if (c == -1)
2092 break;
2093
2094 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002095 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002096 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002097 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002098 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002099 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002100 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002101 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002102 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002103 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002104 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002105 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002106 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002107 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002108 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07002109 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002110 case AMDFW_OPT_RECOVERY_AB:
2111 cb_config.recovery_ab = true;
2112 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002113 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2114 cb_config.recovery_ab = true;
2115 cb_config.recovery_ab_single_copy = true;
2116 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002117 case AMDFW_OPT_USE_COMBO:
2118 cb_config.use_combo = true;
2119 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002120 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002121 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002122 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002123 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002124 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002125 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002126 sub = instance = 0;
2127 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002128 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002129 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002130 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002131 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002132 instance = strtoul(optarg, &tmp, 16);
2133 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002134 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002135 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002136 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002137 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002138 register_fw_filename(AMD_FW_PSP_NVRAM, 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_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002142 register_fw_fuse(optarg);
2143 fuse_defined = 1;
2144 sub = 0;
2145 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002146 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002147 if ((instance & 0xF0) == 0)
2148 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2149 else
2150 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2151 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002152 sub = instance = 0;
2153 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002154 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002155 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302156 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002157 sub = instance = 0;
2158 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002159 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002160 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302161 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002162 sub = instance = 0;
2163 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002164 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002165 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302166 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002167 sub = instance = 0;
2168 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002169 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002170 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2171 sub = instance = 0;
2172 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002173 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002174 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302175 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002176 sub = instance = 0;
2177 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002178 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002179 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302180 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002181 sub = instance = 0;
2182 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002183 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002184 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302185 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002186 sub = instance = 0;
2187 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302188 case LONGOPT_BIOS_SIG:
2189 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302190 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302191 sub = instance = 0;
2192 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002193 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002194 register_bdt_data(AMD_BIOS_UCODE, sub,
2195 instance, optarg);
2196 sub = instance = 0;
2197 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002198 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002199 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002200 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002201 case AMDFW_OPT_SPL_TABLE:
2202 register_fw_filename(AMD_FW_SPL, sub, optarg);
2203 sub = instance = 0;
2204 cb_config.have_mb_spl = true;
2205 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002206 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002207 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2208 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002209 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002210 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002211 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002212 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2213 sub = instance = 0;
2214 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002215 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002216 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2217 sub = instance = 0;
2218 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002219 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002220 soc_id = identify_platform(optarg);
2221 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002222 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002223 retval = 1;
2224 }
2225 sub = instance = 0;
2226 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002227 case AMDFW_OPT_SIGNED_OUTPUT:
2228 signed_output_file = optarg;
2229 sub = instance = 0;
2230 break;
2231 case AMDFW_OPT_SIGNED_ADDR:
2232 signed_start_addr = strtoull(optarg, NULL, 10);
2233 sub = instance = 0;
2234 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002235 case LONGOPT_SPI_READ_MODE:
2236 efs_spi_readmode = strtoull(optarg, NULL, 16);
2237 sub = instance = 0;
2238 break;
2239 case LONGOPT_SPI_SPEED:
2240 efs_spi_speed = strtoull(optarg, NULL, 16);
2241 sub = instance = 0;
2242 break;
2243 case LONGOPT_SPI_MICRON_FLAG:
2244 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2245 sub = instance = 0;
2246 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002247 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002248 output = optarg;
2249 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002250 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002251 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002252 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002253 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002254 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002255 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002256 }
2257 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002258 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002259 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002260 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002261 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002262 " incorrectly (%s)\n\n", optarg);
2263 retval = 1;
2264 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002265 dir_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002266 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002267 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002268 any_location = 1;
2269 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002270 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002271 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302272 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002273 sub = instance = 0;
2274 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002275 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002276 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302277 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002278 sub = instance = 0;
2279 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302280 case LONGOPT_NVRAM_BASE:
2281 /* PSP NV base */
2282 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2283 sub = instance = 0;
2284 break;
2285 case LONGOPT_NVRAM_SIZE:
2286 /* PSP NV size */
2287 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2288 sub = instance = 0;
2289 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002290 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002291 config = optarg;
2292 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002293 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002294 debug = 1;
2295 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002296 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002297 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002298 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002299 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002300 list_deps = 1;
2301 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002302 case AMDFW_OPT_BODY_LOCATION:
2303 dir_location = (uint32_t)strtoul(optarg, &tmp, 16);
2304 if (*tmp != '\0') {
2305 fprintf(stderr, "Error: Body Location specified"
2306 " incorrectly (%s)\n\n", optarg);
2307 retval = 1;
2308 }
2309 break;
2310
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002311 default:
2312 break;
2313 }
2314 }
2315
Zheng Baoc3007f32022-04-03 12:53:51 +08002316 cb_config.second_gen = is_second_gen(soc_id);
2317
Felix Heldf8e2e472022-03-29 23:28:49 +02002318 if (needs_ish(soc_id))
2319 cb_config.need_ish = true;
2320
Felix Held830add62022-03-29 23:28:10 +02002321 if (cb_config.need_ish)
2322 cb_config.recovery_ab = true;
2323
2324 if (cb_config.recovery_ab)
2325 cb_config.multi_level = true;
2326
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002327 if (config) {
2328 config_handle = fopen(config, "r");
2329 if (config_handle == NULL) {
2330 fprintf(stderr, "Can not open file %s for reading: %s\n",
2331 config, strerror(errno));
2332 exit(1);
2333 }
2334 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2335 fprintf(stderr, "Configuration file %s parsing error\n", config);
2336 fclose(config_handle);
2337 exit(1);
2338 }
2339 fclose(config_handle);
2340 }
Zheng Bao9e908072020-10-28 11:39:13 +08002341 /* For debug. */
2342 if (debug) {
2343 dump_psp_firmwares(amd_psp_fw_table);
2344 dump_bdt_firmwares(amd_bios_table);
2345 }
2346
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002347 if (!fuse_defined)
2348 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2349
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002350 if (!output && !list_deps) {
2351 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002352 retval = 1;
2353 }
2354
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002355 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2356 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002357 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002358 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002359 }
2360
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002361 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2362 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002363 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002364 retval = 1;
2365 }
2366
2367 if (retval) {
2368 usage();
2369 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002370 }
2371
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002372 if (list_deps) {
2373 return retval;
2374 }
2375
Marshall Dawson2794a862019-03-04 16:53:15 -07002376 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002377
Marshall Dawson2794a862019-03-04 16:53:15 -07002378 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002379 if (efs_location && (efs_location < rom_base_address)) {
2380 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2381 return 1;
2382 }
2383
2384 if (!efs_location && dir_location) {
2385 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2386 return 1;
2387 }
2388
2389 /*
2390 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2391 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2392 * currently. This condition is to ensure that it is not accidentally split. Revisit
2393 * this condition if such a need arises in the future.
2394 */
2395 if (!any_location && dir_location != efs_location) {
2396 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2397 return 1;
2398 }
2399
2400 if (dir_location != efs_location &&
2401 dir_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
2402 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2403 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002404 return 1;
2405 }
2406
Martin Roth37305e72020-04-07 14:16:39 -06002407 if (any_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002408 if ((dir_location & 0x3f) || (efs_location & 0x3f)) {
2409 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002410 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002411 return 1;
2412 }
2413 } else {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002414 switch (efs_location) {
Martin Roth37305e72020-04-07 14:16:39 -06002415 case 0: /* Fall through */
2416 case 0xFFFA0000: /* Fall through */
2417 case 0xFFF20000: /* Fall through */
2418 case 0xFFE20000: /* Fall through */
2419 case 0xFFC20000: /* Fall through */
2420 case 0xFF820000: /* Fall through */
2421 case 0xFF020000: /* Fall through */
2422 break;
2423 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002424 fprintf(stderr, "Error: Invalid Directory location.\n");
2425 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2426 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002427 return 1;
2428 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002429 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002430 ctx.rom = malloc(ctx.rom_size);
2431 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002432 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002433 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002434 }
2435 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002436
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002437 if (efs_location) {
2438 if (efs_location != dir_location) {
2439 romsig_offset = efs_location - rom_base_address;
2440 ctx.current = dir_location - rom_base_address;
2441 } else {
2442 romsig_offset = efs_location - rom_base_address;
2443 ctx.current = romsig_offset + sizeof(embedded_firmware);
2444 }
2445 } else {
2446 romsig_offset = AMD_ROMSIG_OFFSET;
2447 ctx.current = romsig_offset + sizeof(embedded_firmware);
2448 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002449
Marshall Dawson2794a862019-03-04 16:53:15 -07002450 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002451 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2452 amd_romsig->imc_entry = 0;
2453 amd_romsig->gec_entry = 0;
2454 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002455
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002456 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08002457 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08002458 efs_spi_speed, efs_spi_micron_flag);
2459 if (retval) {
2460 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2461 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002462 }
2463 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002464 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002465 }
2466
Felix Held21a8e382022-03-29 23:10:45 +02002467 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002468 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002469 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002470 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002471 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002472 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002473 printf(" AMDFWTOOL Using firmware directory location of %s address: 0x%08x\n",
Robert Zieba29bc79f2022-03-14 15:59:12 -06002474 ctx.address_mode == AMD_ADDR_PHYSICAL ? "absolute" : "relative",
Zheng Bao6fff2492021-11-15 19:53:21 +08002475 RUN_CURRENT(ctx));
Zheng Baoda83d2c2021-06-04 19:03:10 +08002476
Marshall Dawson2794a862019-03-04 16:53:15 -07002477 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002478
Elyes Haouas7d67a192022-10-14 09:58:29 +02002479 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002480 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002481
Kangheui Won3c164e12021-12-03 20:25:05 +11002482 /* If the tool is invoked with command-line options to keep the signed PSP
2483 binaries separate, process the signed binaries first. */
2484 if (signed_output_file && signed_start_addr)
2485 process_signed_psp_firmwares(signed_output_file,
2486 amd_psp_fw_table,
2487 signed_start_addr,
2488 soc_id);
2489
Zheng Bao481661e2021-08-20 14:47:46 +08002490 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002491 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002492 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2493 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002494 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002495 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2496 /* Create a copy of PSP Directory 2 in the backup slot B.
2497 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002498 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2499 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002500 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002501 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002502 /*
2503 * Either the platform is using only one slot or B is same as above
2504 * directories for A. Skip creating pspdir2_b here to save flash space.
2505 * Related biosdir2_b will be skipped automatically.
2506 */
Zheng Bao990d1542021-09-17 13:24:54 +08002507 pspdir2_b = NULL; /* More explicitly */
2508 }
Zheng Bao481661e2021-08-20 14:47:46 +08002509 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002510 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002511 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002512 } else {
2513 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002514 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002515 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002516 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002517 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002518
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002519 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08002520 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07002521 else
Felix Heldad68b072021-10-18 14:00:35 +02002522 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002523
Zheng Bao993b43f2021-11-10 12:21:46 +08002524 if (cb_config.use_combo) {
2525 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2526 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2527 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2528 combo_dir->entries[0].id_sel = 0;
2529 combo_dir->entries[0].id = get_psp_id(soc_id);
2530 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002531
Zheng Bao993b43f2021-11-10 12:21:46 +08002532 combo_dir->header.lookup = 1;
2533 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2534 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002535
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002536 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002537 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002538 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002539 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002540 bios_directory_table *biosdir2 = NULL;
2541 bios_directory_table *biosdir2_b = NULL;
2542
2543 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2544
Zheng Baoedd1e362021-11-04 17:47:07 +08002545 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002546 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002547 if (cb_config.recovery_ab) {
2548 if (pspdir2_b != NULL) {
2549 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2550 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002551 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002552 }
2553 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2554 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2555 if (pspdir2_b != NULL)
2556 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2557 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2558 } else {
2559 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2560 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002561 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002562 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002563 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002564 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002565 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002566 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002567 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002568 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08002569 switch (soc_id) {
2570 case PLATFORM_RENOIR:
2571 case PLATFORM_LUCIENNE:
2572 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002573 if (!cb_config.recovery_ab)
2574 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002575 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002576 case PLATFORM_MENDOCINO:
2577 break;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002578 case PLATFORM_STONEYRIDGE:
2579 case PLATFORM_RAVEN:
2580 case PLATFORM_PICASSO:
2581 default:
2582 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2583 break;
2584 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002585 }
2586
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002587 /* Free the filename. */
2588 free_psp_firmware_filenames(amd_psp_fw_table);
2589 free_bdt_firmware_filenames(amd_bios_table);
2590
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002591 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002592 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002593 ssize_t bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002594 uint32_t offset = dir_location ? dir_location - rom_base_address : AMD_ROMSIG_OFFSET;
2595
2596 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2597 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002598 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2599 retval = 1;
2600 }
Martin Roth31d95a22016-11-08 11:22:12 -07002601 close(targetfd);
2602 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002603 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002604 retval = 1;
2605 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002606
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002607 if (efs_location != dir_location) {
2608 ssize_t bytes;
2609
2610 bytes = write_efs(output, amd_romsig);
2611 if (bytes != sizeof(*amd_romsig)) {
2612 fprintf(stderr, "Error: Writing EFS\n");
2613 retval = 1;
2614 }
2615 }
2616
Martin Roth31d95a22016-11-08 11:22:12 -07002617 free(rom);
2618 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002619}