blob: f9d53d0ae538efda99b2ac96190302a36959d2b1 [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
4 * ROMSIG At ROMBASE + 0x20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
zbaoc3b0b722016-02-19 13:47:31 +08009 * | PSPDIR ADDR|PSPDIR ADDR |<-- Field 0x14 could be either
10 * +------------+---------------+ 2nd PSP directory or PSP COMBO directory
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080011 * EC ROM should be 64K aligned.
12 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080013 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080014 * +------------+---------------+----------------+------------+
15 * | 'PSP$' | Fletcher | Count | Reserved |
16 * +------------+---------------+----------------+------------+
17 * | 0 | size | Base address | Reserved | Pubkey
18 * +------------+---------------+----------------+------------+
19 * | 1 | size | Base address | Reserved | Bootloader
20 * +------------+---------------+----------------+------------+
21 * | 8 | size | Base address | Reserved | Smu Firmware
22 * +------------+---------------+----------------+------------+
23 * | 3 | size | Base address | Reserved | Recovery Firmware
24 * +------------+---------------+----------------+------------+
25 * | |
26 * | |
27 * | Other PSP Firmware |
28 * | |
29 * | |
30 * +------------+---------------+----------------+------------+
Zheng Bao4fcc9f22015-11-20 12:29:04 +080031 *
zbaoc3b0b722016-02-19 13:47:31 +080032 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080033 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080034 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080035 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080036 * | R e s e r v e d |
37 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080038 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080039 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080040 * | ID-Sel | PSP ID | PSPDIR ADDR | | 3rd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080041 * +------------+---------------+----------------+------------+
42 * | |
43 * | Other PSP |
44 * | |
45 * +------------+---------------+----------------+------------+
46 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080047 */
48
Elyes Haouas7d67a192022-10-14 09:58:29 +020049#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080050#include <fcntl.h>
51#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060052#include <limits.h>
Kangheui Won5b84dfd2021-12-21 15:45:06 +110053#include <openssl/sha.h>
Martin Roth37305e72020-04-07 14:16:39 -060054#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080055#include <stdio.h>
56#include <sys/stat.h>
57#include <sys/types.h>
58#include <unistd.h>
59#include <string.h>
60#include <stdlib.h>
61#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080062#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010063#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080064
65#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080066
Martin Roth60f15512016-11-08 09:55:01 -070067#define AMD_ROMSIG_OFFSET 0x20000
68#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080069
Marshall Dawson7c1e1422019-04-11 09:44:43 -060070#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
71#define ERASE_ALIGNMENT 0x1000U
Marshall Dawson2794a862019-03-04 16:53:15 -070072#define TABLE_ALIGNMENT 0x1000U
73#define BLOB_ALIGNMENT 0x100U
Marshall Dawson24f73d42019-04-01 10:48:43 -060074#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
Marshall Dawson7c1e1422019-04-11 09:44:43 -060075#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080076
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060077#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
78
Kangheui Won5b84dfd2021-12-21 15:45:06 +110079/* Defines related to hashing signed binaries */
80enum hash_header_ver {
81 HASH_HDR_V1 = 1,
82};
83/* Signature ID enums are defined by PSP based on the algorithm used. */
84enum signature_id {
85 SIG_ID_RSA2048,
86 SIG_ID_RSA4096 = 2,
87};
88#define HASH_FILE_SUFFIX ".hash"
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060089#define EFS_FILE_SUFFIX ".efs"
90#define TMP_FILE_SUFFIX ".tmp"
Kangheui Won5b84dfd2021-12-21 15:45:06 +110091
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080092/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -070093 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
94 * can support an optional "combo" implementation. If the PSP sees the
95 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
96 * tables. Using this, support for multiple product generations may be
97 * built into one image. If the PSP$ cookie is found, the table is a
98 * normal directory table.
99 *
100 * Modern generations supporting the combo directories require the
101 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
102 * regardless of the type of directory used. The --combo-capable
103 * argument enforces this placement.
104 *
105 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800106 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800107
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800108/*
109 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
110 * The checksum field of the passed PDU does not need to be reset to zero.
111 *
112 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
113 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
114 * alternative to cyclical redundancy checks because it provides error-
115 * detection properties similar to cyclical redundancy checks but at the
116 * cost of a simple summation technique. Its characteristics were first
117 * published in IEEE Transactions on Communications in January 1982. One
118 * version has been adopted by ISO for use in the class-4 transport layer
119 * of the network protocol.
120 *
121 * This program expects:
122 * stdin: The input file to compute a checksum for. The input file
123 * not be longer than 256 bytes.
124 * stdout: Copied from the input file with the Fletcher's Checksum
125 * inserted 8 bytes after the beginning of the file.
126 * stderr: Used to print out error messages.
127 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700128static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800129{
130 uint32_t c0;
131 uint32_t c1;
132 uint32_t checksum;
133 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700134 const uint16_t *pptr = data;
135
136 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800137
138 c0 = 0xFFFF;
139 c1 = 0xFFFF;
140
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600141 while (length) {
142 index = length >= 359 ? 359 : length;
143 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800144 do {
145 c0 += *(pptr++);
146 c1 += c0;
147 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600148 c0 = (c0 & 0xFFFF) + (c0 >> 16);
149 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800150 }
151
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700152 /* Sums[0,1] mod 64K + overflow */
153 c0 = (c0 & 0xFFFF) + (c0 >> 16);
154 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800155 checksum = (c1 << 16) | c0;
156
157 return checksum;
158}
159
Martin Roth8806f7f2016-11-08 10:44:18 -0700160static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800161{
Martin Roth0e940622016-11-08 10:37:53 -0700162 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800163 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
164 printf("--xhci <FILE> Add XHCI blob\n");
165 printf("--imc <FILE> Add IMC blob\n");
166 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700167
168 printf("\nPSP options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800169 printf("--combo-capable Place PSP directory pointer at Embedded\n");
170 printf(" Firmware\n");
Marshall Dawson67d868d2019-02-28 11:43:40 -0700171 printf(" offset able to support combo directory\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800172 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800173 printf("--multilevel Generate primary and secondary tables\n");
174 printf("--nvram <FILE> Add nvram binary\n");
175 printf("--soft-fuse Set soft fuse\n");
176 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530177 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
178 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800179 printf("--whitelist Set if there is a whitelist\n");
180 printf("--use-pspsecureos Set if psp secure OS is needed\n");
181 printf("--load-mp2-fw Set if load MP2 firmware\n");
182 printf("--load-s0i3 Set if load s0i3 firmware\n");
183 printf("--verstage <FILE> Add verstage\n");
184 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800185 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600186 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800187 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800188 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800189 printf("--apcb <FILE> Add AGESA PSP customization block\n");
190 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
191 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
192 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
193 printf("--ucode <FILE> Add microcode patch\n");
194 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
195 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
196 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
197 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
198 printf("--output <filename> output filename\n");
199 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600200 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700201 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600202 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800203 printf("--location Location of Directory\n");
204 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
205 printf("--sharedmem Location of PSP/FW shared memory\n");
206 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800207 printf(" area\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800208 printf("--soc-name <socname> Specify SOC name. Supported names are\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800209 printf(" Stoneyridge, Raven, Picasso, Renoir, Cezanne\n");
Martin Roth20646cd2023-01-04 21:27:06 -0700210 printf(" Mendocino, Phoenix, Glinda, or Lucienne\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500211 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
212 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
213 printf(" 0x0 66.66Mhz\n");
214 printf(" 0x1 33.33MHz\n");
215 printf(" 0x2 22.22MHz\n");
216 printf(" 0x3 16.66MHz\n");
217 printf(" 0x4 100MHz\n");
218 printf(" 0x5 800KHz\n");
219 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
220 printf(" 0x0 Normal Read (up to 33M)\n");
221 printf(" 0x1 Reserved\n");
222 printf(" 0x2 Dual IO (1-1-2)\n");
223 printf(" 0x3 Quad IO (1-1-4)\n");
224 printf(" 0x4 Dual IO (1-2-2)\n");
225 printf(" 0x5 Quad IO (1-4-4)\n");
226 printf(" 0x6 Normal Read (up to 66M)\n");
227 printf(" 0x7 Fast Read\n");
228 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
229 printf(" 0x0 Micron parts are not used\n");
230 printf(" 0x1 Micron parts are always used\n");
231 printf(" 0x2 Micron parts optional, this option is only\n");
232 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800233 printf("\nGeneral options:\n");
234 printf("-c|--config <config file> Config file\n");
235 printf("-d|--debug Print debug message\n");
236 printf("-l|--list List out the firmware files\n");
237 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800238}
239
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800240amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100241 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800242 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800243 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200244 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800245 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200246 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
247 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
248 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800249 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100250 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
251 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200252 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200253 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800254 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
255 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800256 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200257 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
258 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800259 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
260 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
261 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
262 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800263 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
264 { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100265 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800266 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
267 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800268 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200269 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800270 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200271 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
272 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800273 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
274 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200275 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
276 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
277 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800278 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800279 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
280 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
281 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
283 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
286 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200287 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
288 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600289 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200290 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200291 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200292 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
293 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
294 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
295 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
296 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600297 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
298 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200299 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
300 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
301 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
302 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
303 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800305 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_BOTH_AB },
306 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200307 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
308 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800309 { .type = AMD_RIB, .level = PSP_LVL2 | PSP_BOTH_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200310 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200311 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200312 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
313 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800314 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
315 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
316 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
317 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
318 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
319 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
321 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
322 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
325 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
326 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
327 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800328 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800329};
330
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800331amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800332 { .type = AMD_FW_XHCI },
333 { .type = AMD_FW_IMC },
334 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800335 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800336};
337
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800338amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800339 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530340 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600341 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
342 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
343 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
344 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
345 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700346 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
347 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
348 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
349 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
350 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
351 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
352 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
353 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
355 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
356 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700357 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
361 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700362 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600373 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
374 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800375 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600376 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
377 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
378 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800379 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
380 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200381 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
382 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600383 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
384 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800385 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
386 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
387 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
388 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
389 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
390 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200391 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
392 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
393 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
394 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800395 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
396 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
397 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
398 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
399 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
400 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600401 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800403 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200405 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600407 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800409 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200415 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800419 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600425 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
426 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
427 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200428 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
429 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
430 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
431 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600432 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600433 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600434 { .type = AMD_BIOS_INVALID },
435};
436
Marshall Dawson2794a862019-03-04 16:53:15 -0700437typedef struct _context {
438 char *rom; /* target buffer, size of flash device */
439 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800440 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700441 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Bao6fff2492021-11-15 19:53:21 +0800442 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700443} context;
444
445#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800446#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600447 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
448 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
449 ((mode) == AMD_ADDR_REL_TAB ? (offset) - ctx.current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800450#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600451#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800452 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700453#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800454/* The mode in entry can not be higher than the header's.
455 For example, if table mode is 0, all the entry mode will be 0. */
456#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
457 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700458#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
459#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
460#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800461#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
462 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700463#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800464/* Only set the address mode in entry if the table is mode 2. */
465#define SET_ADDR_MODE(table, mode) \
466 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600467 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800468#define SET_ADDR_MODE_BY_TABLE(table) \
469 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700470
Zheng Bao5164e4b2021-10-30 12:09:07 +0800471void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
472{
473 if (count >= max) {
474 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
475 "(%d)\n", count, max);
476 free(ctx->rom);
477 exit(1);
478 }
479}
480
Marshall Dawson24f73d42019-04-01 10:48:43 -0600481static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700482{
483 void *ptr;
484
Marshall Dawson24f73d42019-04-01 10:48:43 -0600485 /*
486 * Force both onto boundary when multi. Primary table is after
487 * updatable table, so alignment ensures primary can stay intact
488 * if secondary is reprogrammed.
489 */
490 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +0200491 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600492 else
Elyes Haouas7d67a192022-10-14 09:58:29 +0200493 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600494
Marshall Dawson2794a862019-03-04 16:53:15 -0700495 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800496 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800497 ((psp_directory_header *)ptr)->additional_info = 0;
498 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Marshall Dawson2794a862019-03-04 16:53:15 -0700499 ctx->current += sizeof(psp_directory_header)
500 + MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
501 return ptr;
502}
503
Zheng Baofdd47ef2021-09-17 13:30:08 +0800504static void *new_ish_dir(context *ctx)
505{
506 void *ptr;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200507 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800508 ptr = BUFF_CURRENT(*ctx);
509 ctx->current += TABLE_ALIGNMENT;
510 return ptr;
511}
512
Marshall Dawson2794a862019-03-04 16:53:15 -0700513static void *new_combo_dir(context *ctx)
514{
515 void *ptr;
516
Elyes Haouas7d67a192022-10-14 09:58:29 +0200517 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700518 ptr = BUFF_CURRENT(*ctx);
519 ctx->current += sizeof(psp_combo_header)
520 + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
521 return ptr;
522}
523
Zheng Baobf29a0d2020-12-03 23:00:48 +0800524static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800525{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600526 psp_combo_directory *cdir = directory;
527 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600528 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800529 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600530
531 if (!count)
532 return;
Zheng Baob035f582021-05-27 11:26:12 +0800533 if (ctx == NULL || directory == NULL) {
534 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
535 return;
536 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600537
Zheng Baobf29a0d2020-12-03 23:00:48 +0800538 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Elyes Haouas7d67a192022-10-14 09:58:29 +0200539 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800540
Marshall Dawson24f73d42019-04-01 10:48:43 -0600541 switch (cookie) {
542 case PSP2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700543 /* caller is responsible for lookup mode */
Marshall Dawsona378c222019-03-04 16:52:07 -0700544 cdir->header.cookie = cookie;
545 cdir->header.num_entries = count;
546 cdir->header.reserved[0] = 0;
547 cdir->header.reserved[1] = 0;
548 /* checksum everything that comes after the Checksum field */
549 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
550 count * sizeof(psp_combo_entry)
551 + sizeof(cdir->header.num_entries)
552 + sizeof(cdir->header.lookup)
553 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600554 break;
555 case PSP_COOKIE:
556 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800557 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800558 if ((table_size % TABLE_ALIGNMENT) != 0) {
559 fprintf(stderr, "The PSP table size should be 4K aligned\n");
560 exit(1);
561 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700562 dir->header.cookie = cookie;
563 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800564 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
565 dir->header.additional_info_fields.spi_block_size = 1;
566 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700567 /* checksum everything that comes after the Checksum field */
568 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700569 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700570 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800571 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600572 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800573 case BHD_COOKIE:
574 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800575 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800576 if ((table_size % TABLE_ALIGNMENT) != 0) {
577 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
578 exit(1);
579 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600580 bdir->header.cookie = cookie;
581 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800582 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
583 bdir->header.additional_info_fields.spi_block_size = 1;
584 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600585 /* checksum everything that comes after the Checksum field */
586 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
587 count * sizeof(bios_directory_entry)
588 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800589 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600590 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700591 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800592
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800593}
594
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700595static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
596{
597 int fd;
598 struct stat fd_stat;
599 ssize_t bytes;
600
601 fd = open(src_file, O_RDONLY);
602 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800603 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700604 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700605 return -1;
606 }
607
608 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800609 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600610 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700611 return -2;
612 }
613
Zheng Bao6d402ac2020-10-01 16:16:30 +0800614 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800615 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600616 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700617 return -3;
618 }
619
620 bytes = read(fd, dest, (size_t)fd_stat.st_size);
621 close(fd);
622 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800623 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700624 return -4;
625 }
626
627 return bytes;
628}
629
Kangheui Won3c164e12021-12-03 20:25:05 +1100630static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
631{
632 ssize_t bytes;
633 size_t total_bytes = 0;
634
635 do {
636 bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
637 if (bytes == 0) {
638 fprintf(stderr, "Reached EOF probably\n");
639 break;
640 }
641
642 if (bytes < 0 && errno == EAGAIN)
643 bytes = 0;
644
645 if (bytes < 0) {
646 fprintf(stderr, "Read failure %s\n", strerror(errno));
647 return bytes;
648 }
649
650 total_bytes += bytes;
651 } while (total_bytes < buf_size);
652
653 if (total_bytes != buf_size) {
654 fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
655 total_bytes, buf_size);
656 return -1;
657 }
658 return buf_size;
659}
660
661static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
662{
663 ssize_t bytes;
664 size_t total_bytes = 0;
665
666 do {
667 bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
668 if (bytes < 0 && errno == EAGAIN)
669 bytes = 0;
670
671 if (bytes < 0) {
672 fprintf(stderr, "Write failure %s\n", strerror(errno));
673 lseek(fd, SEEK_CUR, -total_bytes);
674 return bytes;
675 }
676
677 total_bytes += bytes;
678 } while (total_bytes < buf_size);
679
680 if (total_bytes != buf_size) {
681 fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
682 total_bytes, buf_size);
683 lseek(fd, SEEK_CUR, -total_bytes);
684 return -1;
685 }
686
687 return buf_size;
688}
689
Zheng Baoeb0404e2021-10-14 15:09:09 +0800690enum platform {
691 PLATFORM_UNKNOWN,
692 PLATFORM_STONEYRIDGE,
693 PLATFORM_RAVEN,
694 PLATFORM_PICASSO,
695 PLATFORM_RENOIR,
696 PLATFORM_CEZANNE,
697 PLATFORM_MENDOCINO,
698 PLATFORM_LUCIENNE,
Martin Roth20646cd2023-01-04 21:27:06 -0700699 PLATFORM_PHOENIX,
Martin Roth13490832022-10-06 17:18:02 -0600700 PLATFORM_GLINDA
Zheng Baoeb0404e2021-10-14 15:09:09 +0800701};
702
703static uint32_t get_psp_id(enum platform soc_id)
704{
705 uint32_t psp_id;
706 switch (soc_id) {
707 case PLATFORM_RAVEN:
708 case PLATFORM_PICASSO:
709 psp_id = 0xBC0A0000;
710 break;
711 case PLATFORM_RENOIR:
712 case PLATFORM_LUCIENNE:
713 psp_id = 0xBC0C0000;
714 break;
715 case PLATFORM_CEZANNE:
716 psp_id = 0xBC0C0140;
717 break;
718 case PLATFORM_MENDOCINO:
719 psp_id = 0xBC0D0900;
720 break;
721 case PLATFORM_STONEYRIDGE:
722 psp_id = 0x10220B00;
723 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800724 case PLATFORM_GLINDA:
725 psp_id = 0xBC0E0200;
726 break;
727 case PLATFORM_PHOENIX:
728 psp_id = 0xBC0D0400;
729 break;
Zheng Baoeb0404e2021-10-14 15:09:09 +0800730 default:
731 psp_id = 0;
732 break;
733 }
734 return psp_id;
735}
736
Kangheui Won3c164e12021-12-03 20:25:05 +1100737static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
738{
739 switch (soc_id) {
740 case PLATFORM_MENDOCINO:
741 /* Fallback to fw_type if fw_id is not populated, which serves the same
742 purpose on older SoCs. */
743 return header->fw_id ? header->fw_id : header->fw_type;
744 default:
745 return header->fw_type;
746 }
747}
748
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100749static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
750{
751 uint8_t hash[SHA384_DIGEST_LENGTH];
752 struct amd_fw_header *header = (struct amd_fw_header *)buf;
753 /* Include only signed part for hash calculation. */
754 size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
755 uint8_t *body = (uint8_t *)buf;
756
757 if (len > header->size_total)
758 return -1;
759
760 if (header->sig_id == SIG_ID_RSA4096) {
761 SHA384(body, len, hash);
762 entry->sha_len = SHA384_DIGEST_LENGTH;
763 } else if (header->sig_id == SIG_ID_RSA2048) {
764 SHA256(body, len, hash);
765 entry->sha_len = SHA256_DIGEST_LENGTH;
766 } else {
767 fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
768 __func__, header->sig_id);
769 return -1;
770 }
771
772 memcpy(entry->sha, hash, entry->sha_len);
773 entry->fw_id = get_psp_fw_type(soc_id, header);
774 entry->subtype = header->fw_subtype;
775
776 return 0;
777}
778
779static int get_num_binaries(void *buf, size_t buf_size)
780{
781 struct amd_fw_header *header = (struct amd_fw_header *)buf;
782 size_t total_len = 0;
783 int num_binaries = 0;
784
785 while (total_len < buf_size) {
786 num_binaries++;
787 total_len += header->size_total;
788 header = (struct amd_fw_header *)(buf + total_len);
789 }
790
791 if (total_len != buf_size) {
792 fprintf(stderr, "Malformed binary\n");
793 return -1;
794 }
795 return num_binaries;
796}
797
798static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
799{
800 struct amd_fw_header *header = (struct amd_fw_header *)buf;
801 /* Include only signed part for hash calculation. */
802 size_t total_len = 0;
803 int num_binaries = get_num_binaries(buf, buf_size);
804
805 if (num_binaries <= 0)
806 return num_binaries;
807
808 entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
809 if (!entry->hash_entries) {
810 fprintf(stderr, "Error allocating memory to add FW hash\n");
811 return -1;
812 }
813 entry->num_hash_entries = num_binaries;
814
815 /* Iterate through each binary */
816 for (int i = 0; i < num_binaries; i++) {
817 if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) {
818 free(entry->hash_entries);
819 return -1;
820 }
821 total_len += header->size_total;
822 header = (struct amd_fw_header *)(buf + total_len);
823 }
824
825 return 0;
826}
827
Marshall Dawson2794a862019-03-04 16:53:15 -0700828static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700829 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700830 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800831{
Richard Spiegel137484d2018-01-17 10:23:19 -0700832 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800833 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700834
Elyes Haouas7d67a192022-10-14 09:58:29 +0200835 ctx->current = ALIGN_UP(ctx->current, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800836
Martin Rothcd15bc82016-11-08 11:34:02 -0700837 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800838 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800839 switch (fw_table[i].type) {
840 case AMD_FW_IMC:
Elyes Haouas7d67a192022-10-14 09:58:29 +0200841 ctx->current = ALIGN_UP(ctx->current, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700842 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800843 break;
844 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700845 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800846 break;
847 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700848 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800849 break;
850 default:
851 /* Error */
852 break;
853 }
854
Marshall Dawson2794a862019-03-04 16:53:15 -0700855 bytes = copy_blob(BUFF_CURRENT(*ctx),
856 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600857 if (bytes < 0) {
Marshall Dawson2794a862019-03-04 16:53:15 -0700858 free(ctx->rom);
Martin Roth60f15512016-11-08 09:55:01 -0700859 exit(1);
860 }
861
Elyes Haouas7d67a192022-10-14 09:58:29 +0200862 ctx->current = ALIGN_UP(ctx->current + bytes,
Marshall Dawson2794a862019-03-04 16:53:15 -0700863 BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800864 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800865 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800866}
867
Zheng Bao9e908072020-10-28 11:39:13 +0800868/* For debugging */
869static void dump_psp_firmwares(amd_fw_entry *fw_table)
870{
871 amd_fw_entry *index;
872
873 printf("PSP firmware components:");
874 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
875 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800876 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800877 }
878}
879
880static void dump_bdt_firmwares(amd_bios_entry *fw_table)
881{
882 amd_bios_entry *index;
883
884 printf("BIOS Directory Table (BDT) components:");
885 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
886 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800887 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800888 }
889}
890
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800891static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
892{
893 amd_fw_entry *index;
894
895 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
896 if (index->filename &&
897 index->type != AMD_FW_VERSTAGE_SIG &&
898 index->type != AMD_FW_PSP_VERSTAGE &&
Zheng Bao6c5ec8e2022-02-11 11:51:26 +0800899 index->type != AMD_FW_SPL &&
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800900 index->type != AMD_FW_PSP_WHITELIST) {
901 free(index->filename);
902 }
903 }
904}
905
906static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
907{
908 amd_bios_entry *index;
909
910 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
911 if (index->filename &&
912 index->type != AMD_BIOS_APCB &&
913 index->type != AMD_BIOS_BIN &&
Arthur Heymans1cffc552022-10-19 20:08:35 +0200914 index->type != AMD_BIOS_APCB_BK &&
915 index->type != AMD_BIOS_UCODE)
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800916 free(index->filename);
917 }
918}
919
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100920static void write_or_fail(int fd, void *ptr, size_t size)
921{
922 ssize_t written;
923
924 written = write_from_buf_to_file(fd, ptr, size);
925 if (written < 0 || (size_t)written != size) {
926 fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
927 __func__, size, written);
928 exit(-1);
929 }
930}
931
932static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
933{
934 uint16_t type = entry->fw_id;
935 uint16_t subtype = entry->subtype;
936
937 write_or_fail(fd, &type, sizeof(type));
938 write_or_fail(fd, &subtype, sizeof(subtype));
939 write_or_fail(fd, entry->sha, entry->sha_len);
940}
941
942static void write_psp_firmware_hash(const char *filename,
943 amd_fw_entry *fw_table)
944{
945 struct psp_fw_hash_table hash_header = {0};
946 int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
947
948 if (fd < 0) {
949 fprintf(stderr, "Error opening file: %s: %s\n",
950 filename, strerror(errno));
951 exit(-1);
952 }
953
954 hash_header.version = HASH_HDR_V1;
955 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
956 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
957 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) {
958 hash_header.no_of_entries_256++;
959 } else if (fw_table[i].hash_entries[j].sha_len ==
960 SHA384_DIGEST_LENGTH) {
961 hash_header.no_of_entries_384++;
962 } else if (fw_table[i].hash_entries[j].sha_len) {
963 fprintf(stderr, "%s: Error invalid sha_len %d\n",
964 __func__, fw_table[i].hash_entries[j].sha_len);
965 exit(-1);
966 }
967 }
968 }
969
970 write_or_fail(fd, &hash_header, sizeof(hash_header));
971
972 /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
973 processes the table in that order. Mixing and matching SHA256 and SHA384 entries
974 will cause the hash verification failure at run-time. */
975 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
976 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
977 if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH)
978 write_one_psp_firmware_hash_entry(fd,
979 &fw_table[i].hash_entries[j]);
980 }
981 }
982
983 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
984 for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) {
985 if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH)
986 write_one_psp_firmware_hash_entry(fd,
987 &fw_table[i].hash_entries[j]);
988 }
989 }
990
991 close(fd);
992 for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
993 if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
994 continue;
995
996 free(fw_table[i].hash_entries);
997 fw_table[i].hash_entries = NULL;
998 fw_table[i].num_hash_entries = 0;
999 }
1000}
1001
Kangheui Won3c164e12021-12-03 20:25:05 +11001002/**
1003 * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
1004 * @signed_rom: Output file path grouping all the signed PSP binaries.
1005 * @fw_table: Table of all the PSP firmware entries/binaries to be processed.
1006 * @signed_start_addr: Offset of the FMAP section, within the flash device, to hold
1007 * the signed PSP binaries.
1008 * @soc_id: SoC ID of the PSP binaries.
1009 */
1010static void process_signed_psp_firmwares(const char *signed_rom,
1011 amd_fw_entry *fw_table,
1012 uint64_t signed_start_addr,
1013 enum platform soc_id)
1014{
1015 unsigned int i;
1016 int fd;
1017 int signed_rom_fd;
1018 ssize_t bytes, align_bytes;
1019 uint8_t *buf;
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001020 char *signed_rom_hash;
1021 size_t signed_rom_hash_strlen;
Kangheui Won3c164e12021-12-03 20:25:05 +11001022 struct amd_fw_header header;
1023 struct stat fd_stat;
1024 /* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
1025 alignment data with 0xff to pad the blobs and meet the alignment requirement. */
1026 uint8_t align_data[BLOB_ALIGNMENT - 1];
1027
1028 memset(align_data, 0xff, sizeof(align_data));
1029 signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
1030 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1031 if (signed_rom_fd < 0) {
1032 fprintf(stderr, "Error opening file: %s: %s\n",
1033 signed_rom, strerror(errno));
1034 return;
1035 }
1036
1037 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001038 fw_table[i].num_hash_entries = 0;
1039 fw_table[i].hash_entries = NULL;
1040
Kangheui Won3c164e12021-12-03 20:25:05 +11001041 if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
1042 continue;
1043
1044 memset(&header, 0, sizeof(header));
1045
1046 fd = open(fw_table[i].filename, O_RDONLY);
1047 if (fd < 0) {
1048 /* Keep the file along with set of unsigned PSP binaries & continue. */
1049 fprintf(stderr, "Error opening file: %s: %s\n",
1050 fw_table[i].filename, strerror(errno));
1051 continue;
1052 }
1053
1054 if (fstat(fd, &fd_stat)) {
1055 /* Keep the file along with set of unsigned PSP binaries & continue. */
1056 fprintf(stderr, "fstat error: %s\n", strerror(errno));
1057 close(fd);
1058 continue;
1059 }
1060
1061 bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
1062 if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
1063 /* Keep the file along with set of unsigned PSP binaries & continue. */
1064 fprintf(stderr, "%s: Error reading header from %s\n",
1065 __func__, fw_table[i].filename);
1066 close(fd);
1067 continue;
1068 }
1069
1070 /* If firmware header looks like invalid, assume it's not signed */
1071 if (!header.fw_type && !header.fw_id) {
1072 fprintf(stderr, "%s: Invalid FWID for %s\n",
1073 __func__, fw_table[i].filename);
1074 close(fd);
1075 continue;
1076 }
1077
Kangheui Won3c164e12021-12-03 20:25:05 +11001078
1079 /* PSP binary is not signed and should not be part of signed PSP binaries
1080 set. */
1081 if (header.sig_opt != 1) {
1082 close(fd);
1083 continue;
1084 }
1085
1086 buf = malloc(fd_stat.st_size);
1087 if (!buf) {
1088 /* Keep the file along with set of unsigned PSP binaries & continue. */
1089 fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
1090 __func__, (long long)fd_stat.st_size);
1091 close(fd);
1092 continue;
1093 }
1094
1095 lseek(fd, SEEK_SET, 0);
1096 bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
1097 if (bytes != fd_stat.st_size) {
1098 /* Keep the file along with set of unsigned PSP binaries & continue. */
1099 fprintf(stderr, "%s: failed to read %s\n",
1100 __func__, fw_table[i].filename);
1101 free(buf);
1102 close(fd);
1103 continue;
1104 }
1105
1106 bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
1107 if (bytes != fd_stat.st_size) {
1108 /* Keep the file along with set of unsigned PSP binaries & continue. */
1109 fprintf(stderr, "%s: failed to write %s\n",
1110 __func__, fw_table[i].filename);
1111 free(buf);
1112 close(fd);
1113 continue;
1114 }
1115
1116 /* Write Blob alignment bytes */
1117 align_bytes = 0;
1118 if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
1119 align_bytes = BLOB_ALIGNMENT -
1120 (fd_stat.st_size & (BLOB_ALIGNMENT - 1));
1121 bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
1122 if (bytes != align_bytes) {
1123 fprintf(stderr, "%s: failed to write alignment data for %s\n",
1124 __func__, fw_table[i].filename);
1125 lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
1126 free(buf);
1127 close(fd);
1128 continue;
1129 }
1130 }
1131
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001132 if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
1133 exit(-1);
1134
Kangheui Won3c164e12021-12-03 20:25:05 +11001135 /* File is successfully processed and is part of signed PSP binaries set. */
1136 fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
1137 fw_table[i].addr_signed = signed_start_addr;
1138 fw_table[i].file_size = (uint32_t)fd_stat.st_size;
1139
1140 signed_start_addr += fd_stat.st_size + align_bytes;
1141
1142 free(buf);
1143 close(fd);
1144 }
1145
1146 close(signed_rom_fd);
Kangheui Won5b84dfd2021-12-21 15:45:06 +11001147
1148 /* signed_rom file name + ".hash" + '\0' */
1149 signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
1150 signed_rom_hash = malloc(signed_rom_hash_strlen);
1151 if (!signed_rom_hash) {
1152 fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
1153 exit(-1);
1154 }
1155 strcpy(signed_rom_hash, signed_rom);
1156 strcat(signed_rom_hash, HASH_FILE_SUFFIX);
1157 write_psp_firmware_hash(signed_rom_hash, fw_table);
1158 free(signed_rom_hash);
Kangheui Won3c164e12021-12-03 20:25:05 +11001159}
1160
Zheng Bao990d1542021-09-17 13:24:54 +08001161static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001162 psp_directory_table *pspdir2, ish_directory_table *ish,
1163 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +08001164{
1165 uint32_t count;
1166 uint32_t current_table_save;
1167
1168 current_table_save = ctx->current_table;
1169 ctx->current_table = (char *)pspdir - ctx->rom;
1170 count = pspdir->header.num_entries;
1171 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1172 pspdir->entries[count].type = (uint8_t)ab;
1173 pspdir->entries[count].subprog = 0;
1174 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001175 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -06001176 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001177 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
1178 ish->update_retry_count = 2;
1179 ish->glitch_retry_count = 0;
1180 ish->psp_id = get_psp_id(soc_id);
1181 ish->checksum = fletcher32(&ish->boot_priority,
1182 sizeof(ish_directory_table) - sizeof(uint32_t));
1183 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001184 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001185 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001186 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001187 pspdir->entries[count].size = TABLE_ALIGNMENT;
1188 } else {
1189 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001190 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001191 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001192 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001193 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +08001194 sizeof(psp_directory_entry) +
1195 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +08001196 }
Zheng Bao990d1542021-09-17 13:24:54 +08001197
1198 count++;
1199 pspdir->header.num_entries = count;
1200 ctx->current_table = current_table_save;
1201}
1202
Marshall Dawson2794a862019-03-04 16:53:15 -07001203static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -07001204 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001205 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +08001206 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -06001207 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001208 uint32_t cookie,
Zheng Baofdd47ef2021-09-17 13:30:08 +08001209 enum platform soc_id,
Zheng Bao20795892021-08-20 14:58:22 +08001210 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001211{
Richard Spiegel137484d2018-01-17 10:23:19 -07001212 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001213 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001214 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301215 uint32_t size;
1216 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +08001217 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +08001218 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001219 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001220
1221 /* This function can create a primary table, a secondary table, or a
1222 * flattened table which contains all applicable types. These if-else
1223 * statements infer what the caller intended. If a 2nd-level cookie
1224 * is passed, clearly a 2nd-level table is intended. However, a
1225 * 1st-level cookie may indicate level 1 or flattened. If the caller
1226 * passes a pointer to a 2nd-level table, then assume not flat.
1227 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001228 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001229 level = PSP_BOTH;
1230 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001231 level = PSP_LVL2;
1232 else if (pspdir2)
1233 level = PSP_LVL1;
1234 else
1235 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001236
Zheng Bao990d1542021-09-17 13:24:54 +08001237 if (recovery_ab) {
1238 if (cookie == PSPL2_COOKIE)
1239 level = PSP_LVL2_AB;
1240 else if (pspdir2)
1241 level = PSP_LVL1_AB;
1242 else
1243 level = PSP_BOTH_AB;
1244 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001245 current_table_save = ctx->current_table;
1246 ctx->current_table = (char *)pspdir - ctx->rom;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001247 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001248
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001249 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001250 if (!(fw_table[i].level & level))
1251 continue;
1252
Zheng Bao5164e4b2021-10-30 12:09:07 +08001253 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1254
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001255 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1256 if (!fw_table[i].other)
1257 continue;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001258 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001259 pspdir->entries[count].type = fw_table[i].type;
1260 pspdir->entries[count].size = 4096; /* TODO: doc? */
1261 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001262 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001263 pspdir->entries[count].subprog = fw_table[i].subprog;
1264 pspdir->entries[count].rsvd = 0;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001265 ctx->current = ALIGN_UP(ctx->current + 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001266 count++;
1267 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001268 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001269 pspdir->entries[count].subprog = fw_table[i].subprog;
1270 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001271 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001272 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001273 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001274 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001275 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301276 if (fw_table[i].filename == NULL) {
1277 if (fw_table[i].size == 0)
1278 continue;
1279 size = fw_table[i].size;
1280 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001281 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301282 fprintf(stderr,
1283 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1284 exit(1);
1285 }
1286 } else {
Elyes Haouas7d67a192022-10-14 09:58:29 +02001287 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301288 bytes = copy_blob(BUFF_CURRENT(*ctx),
1289 fw_table[i].filename, BUFF_ROOM(*ctx));
1290 if (bytes <= 0) {
1291 free(ctx->rom);
1292 exit(1);
1293 }
1294
Elyes Haouas7d67a192022-10-14 09:58:29 +02001295 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301296 addr = RUN_CURRENT(*ctx);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001297 ctx->current = ALIGN_UP(ctx->current + bytes,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301298 BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001299 }
1300
1301 pspdir->entries[count].type = fw_table[i].type;
1302 pspdir->entries[count].subprog = fw_table[i].subprog;
1303 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301304 pspdir->entries[count].size = size;
1305 pspdir->entries[count].addr = addr;
1306
Zheng Bao6fff2492021-11-15 19:53:21 +08001307 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001308 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001309
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001310 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001311 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001312 if (fw_table[i].addr_signed) {
1313 pspdir->entries[count].addr =
1314 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1315 pspdir->entries[count].address_mode =
1316 SET_ADDR_MODE_BY_TABLE(pspdir);
1317 bytes = fw_table[i].file_size;
1318 } else {
1319 bytes = copy_blob(BUFF_CURRENT(*ctx),
1320 fw_table[i].filename, BUFF_ROOM(*ctx));
1321 if (bytes < 0) {
1322 free(ctx->rom);
1323 exit(1);
1324 }
1325 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1326 pspdir->entries[count].address_mode =
1327 SET_ADDR_MODE_BY_TABLE(pspdir);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001328 ctx->current = ALIGN_UP(ctx->current + bytes,
Kangheui Won3c164e12021-12-03 20:25:05 +11001329 BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001330 }
1331
Marshall Dawson239286c2019-02-23 16:42:46 -07001332 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001333 pspdir->entries[count].subprog = fw_table[i].subprog;
1334 pspdir->entries[count].rsvd = 0;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001335 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001336
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001337 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001338 } else {
1339 /* This APU doesn't have this firmware. */
1340 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001341 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001342
Zheng Bao990d1542021-09-17 13:24:54 +08001343 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001344 if (cb_config->need_ish) { /* Need ISH */
1345 ish_a_dir = new_ish_dir(ctx);
1346 if (pspdir2_b != NULL)
1347 ish_b_dir = new_ish_dir(ctx);
1348 }
Zheng Bao990d1542021-09-17 13:24:54 +08001349 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001350 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
1351 AMD_FW_RECOVERYAB_A, soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001352 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001353 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
1354 AMD_FW_RECOVERYAB_B, soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001355 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001356 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001357 AMD_FW_RECOVERYAB_B, soc_id);
1358
Zheng Bao990d1542021-09-17 13:24:54 +08001359 count = pspdir->header.num_entries;
1360 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001361 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001362 pspdir->entries[count].type = AMD_FW_L2_PTR;
1363 pspdir->entries[count].subprog = 0;
1364 pspdir->entries[count].rsvd = 0;
1365 pspdir->entries[count].size = sizeof(pspdir2->header)
1366 + pspdir2->header.num_entries
1367 * sizeof(psp_directory_entry);
1368
Zheng Bao6fff2492021-11-15 19:53:21 +08001369 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001370 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001371 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001372 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001373 count++;
1374 }
1375
Zheng Baobf29a0d2020-12-03 23:00:48 +08001376 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001377 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001378}
1379
Zheng Bao990d1542021-09-17 13:24:54 +08001380static void add_psp_firmware_entry(context *ctx,
1381 psp_directory_table *pspdir,
1382 void *table, amd_fw_type type, uint32_t size)
1383{
1384 uint32_t count = pspdir->header.num_entries;
1385 uint32_t index;
1386 uint32_t current_table_save;
1387
1388 current_table_save = ctx->current_table;
1389 ctx->current_table = (char *)pspdir - ctx->rom;
1390
1391 /* If there is an entry of "type", replace it. */
1392 for (index = 0; index < count; index++) {
1393 if (pspdir->entries[index].type == (uint8_t)type)
1394 break;
1395 }
1396
1397 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1398 pspdir->entries[index].type = (uint8_t)type;
1399 pspdir->entries[index].subprog = 0;
1400 pspdir->entries[index].rsvd = 0;
1401 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1402 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1403 pspdir->entries[index].size = size;
1404 if (index == count)
1405 count++;
1406
1407 pspdir->header.num_entries = count;
1408 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1409 count * sizeof(psp_directory_entry)
1410 + sizeof(pspdir->header.num_entries)
1411 + sizeof(pspdir->header.additional_info));
1412
1413 ctx->current_table = current_table_save;
1414}
1415
Zheng Baoba3af5e2021-11-04 18:56:47 +08001416static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001417{
1418 void *ptr;
1419
1420 /*
1421 * Force both onto boundary when multi. Primary table is after
1422 * updatable table, so alignment ensures primary can stay intact
1423 * if secondary is reprogrammed.
1424 */
1425 if (multi)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001426 ctx->current = ALIGN_UP(ctx->current, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001427 else
Elyes Haouas7d67a192022-10-14 09:58:29 +02001428 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001429 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001430 ((bios_directory_hdr *) ptr)->additional_info = 0;
1431 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1432 ctx->current_table = ctx->current;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001433 ctx->current += sizeof(bios_directory_hdr)
1434 + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry);
1435 return ptr;
1436}
1437
1438static int locate_bdt2_bios(bios_directory_table *level2,
1439 uint64_t *source, uint32_t *size)
1440{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001441 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001442
1443 *source = 0;
1444 *size = 0;
1445 if (!level2)
1446 return 0;
1447
1448 for (i = 0 ; i < level2->header.num_entries ; i++) {
1449 if (level2->entries[i].type == AMD_BIOS_BIN) {
1450 *source = level2->entries[i].source;
1451 *size = level2->entries[i].size;
1452 return 1;
1453 }
1454 }
1455 return 0;
1456}
1457
1458static int have_bios_tables(amd_bios_entry *table)
1459{
1460 int i;
1461
1462 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1463 if (table[i].level & BDT_LVL1 && table[i].filename)
1464 return 1;
1465 }
1466 return 0;
1467}
1468
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001469static int find_bios_entry(amd_bios_type type)
1470{
1471 int i;
1472
1473 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1474 if (amd_bios_table[i].type == type)
1475 return i;
1476 }
1477 return -1;
1478}
1479
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001480static void integrate_bios_firmwares(context *ctx,
1481 bios_directory_table *biosdir,
1482 bios_directory_table *biosdir2,
1483 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001484 uint32_t cookie,
1485 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001486{
1487 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001488 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001489 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001490 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001491 uint32_t size;
1492 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001493
1494 /* This function can create a primary table, a secondary table, or a
1495 * flattened table which contains all applicable types. These if-else
1496 * statements infer what the caller intended. If a 2nd-level cookie
1497 * is passed, clearly a 2nd-level table is intended. However, a
1498 * 1st-level cookie may indicate level 1 or flattened. If the caller
1499 * passes a pointer to a 2nd-level table, then assume not flat.
1500 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001501 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001502 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001503 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001504 level = BDT_LVL2;
1505 else if (biosdir2)
1506 level = BDT_LVL1;
1507 else
1508 level = BDT_BOTH;
1509
Elyes Haouas7d67a192022-10-14 09:58:29 +02001510 ctx->current = ALIGN_UP(ctx->current, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001511
1512 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1513 if (!(fw_table[i].level & level))
1514 continue;
1515 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301516 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001517 fw_table[i].type != AMD_BIOS_APOB &&
1518 fw_table[i].type != AMD_BIOS_APOB_NV &&
1519 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001520 fw_table[i].type != AMD_BIOS_BIN &&
1521 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001522 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001523
1524 /* BIOS Directory items may have additional requirements */
1525
Ritul Guru9a321f32022-07-29 11:06:40 +05301526 /* SIG needs a size, else no choice but to skip */
1527 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1528 continue;
1529
Martin Roth48dd9fe2020-07-29 16:32:25 -06001530 /* Check APOB_NV requirements */
1531 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1532 if (!fw_table[i].size && !fw_table[i].src)
1533 continue; /* APOB_NV not used */
1534 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001535 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001536 free(ctx->rom);
1537 exit(1);
1538 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001539 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001540 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001541 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1542 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001543 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001544
1545 /* APOB_DATA needs destination */
1546 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001547 fprintf(stderr, "Error: APOB destination not provided\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001548 free(ctx->rom);
1549 exit(1);
1550 }
1551
1552 /* BIOS binary must have destination and uncompressed size. If
1553 * no filename given, then user must provide a source address.
1554 */
1555 if (fw_table[i].type == AMD_BIOS_BIN) {
1556 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001557 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001558 free(ctx->rom);
1559 exit(1);
1560 }
1561 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001562 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001563 free(ctx->rom);
1564 exit(1);
1565 }
1566 }
1567
Martin Roth94554742020-04-14 14:59:36 -06001568 /* PSP_SHARED_MEM needs a destination and size */
1569 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1570 (!fw_table[i].dest || !fw_table[i].size))
1571 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001572 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001573
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001574 biosdir->entries[count].type = fw_table[i].type;
1575 biosdir->entries[count].region_type = fw_table[i].region_type;
1576 biosdir->entries[count].dest = fw_table[i].dest ?
1577 fw_table[i].dest : (uint64_t)-1;
1578 biosdir->entries[count].reset = fw_table[i].reset;
1579 biosdir->entries[count].copy = fw_table[i].copy;
1580 biosdir->entries[count].ro = fw_table[i].ro;
1581 biosdir->entries[count].compressed = fw_table[i].zlib;
1582 biosdir->entries[count].inst = fw_table[i].inst;
1583 biosdir->entries[count].subprog = fw_table[i].subpr;
1584
1585 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301586 case AMD_BIOS_SIG:
1587 /* Reserve size bytes within amdfw.rom */
1588 biosdir->entries[count].size = fw_table[i].size;
1589 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1590 biosdir->entries[count].address_mode =
1591 SET_ADDR_MODE_BY_TABLE(biosdir);
1592 memset(BUFF_CURRENT(*ctx), 0xff,
1593 biosdir->entries[count].size);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001594 ctx->current = ALIGN_UP(ctx->current
Ritul Guru9a321f32022-07-29 11:06:40 +05301595 + biosdir->entries[count].size, 0x100U);
1596 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001597 case AMD_BIOS_APOB:
1598 biosdir->entries[count].size = fw_table[i].size;
1599 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001600 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001601 break;
1602 case AMD_BIOS_APOB_NV:
1603 if (fw_table[i].src) {
1604 /* If source is given, use that and its size */
1605 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001606 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001607 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001608 biosdir->entries[count].size = fw_table[i].size;
1609 } else {
1610 /* Else reserve size bytes within amdfw.rom */
Elyes Haouas7d67a192022-10-14 09:58:29 +02001611 ctx->current = ALIGN_UP(ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001612 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001613 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001614 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001615 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001616 fw_table[i].size, ERASE_ALIGNMENT);
1617 memset(BUFF_CURRENT(*ctx), 0xff,
1618 biosdir->entries[count].size);
1619 ctx->current = ctx->current
1620 + biosdir->entries[count].size;
1621 }
1622 break;
1623 case AMD_BIOS_BIN:
1624 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001625 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1626 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001627 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001628 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001629 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001630 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001631 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001632
1633 /* level 2, or level 1 and no copy found in level 2 */
1634 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001635 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001636 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001637 biosdir->entries[count].dest = fw_table[i].dest;
1638 biosdir->entries[count].size = fw_table[i].size;
1639
1640 if (!fw_table[i].filename)
1641 break;
1642
1643 bytes = copy_blob(BUFF_CURRENT(*ctx),
1644 fw_table[i].filename, BUFF_ROOM(*ctx));
1645 if (bytes <= 0) {
1646 free(ctx->rom);
1647 exit(1);
1648 }
1649
Zheng Bao6fff2492021-11-15 19:53:21 +08001650 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001651 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001652 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001653 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001654
Elyes Haouas7d67a192022-10-14 09:58:29 +02001655 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001656 break;
Martin Roth94554742020-04-14 14:59:36 -06001657 case AMD_BIOS_PSP_SHARED_MEM:
1658 biosdir->entries[count].dest = fw_table[i].dest;
1659 biosdir->entries[count].size = fw_table[i].size;
1660 break;
1661
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001662 default: /* everything else is copied from input */
1663 if (fw_table[i].type == AMD_BIOS_APCB ||
1664 fw_table[i].type == AMD_BIOS_APCB_BK)
Elyes Haouas7d67a192022-10-14 09:58:29 +02001665 ctx->current = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001666 ctx->current, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001667 bytes = copy_blob(BUFF_CURRENT(*ctx),
1668 fw_table[i].filename, BUFF_ROOM(*ctx));
1669 if (bytes <= 0) {
1670 free(ctx->rom);
1671 exit(1);
1672 }
1673
1674 biosdir->entries[count].size = (uint32_t)bytes;
1675 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001676 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001677
Elyes Haouas7d67a192022-10-14 09:58:29 +02001678 ctx->current = ALIGN_UP(ctx->current + bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001679 break;
1680 }
1681
1682 count++;
1683 }
1684
1685 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001686 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001687 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001688 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001689 biosdir->entries[count].size =
1690 + MAX_BIOS_ENTRIES
1691 * sizeof(bios_directory_entry);
1692 biosdir->entries[count].source =
1693 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001694 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001695 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001696 biosdir->entries[count].subprog = 0;
1697 biosdir->entries[count].inst = 0;
1698 biosdir->entries[count].copy = 0;
1699 biosdir->entries[count].compressed = 0;
1700 biosdir->entries[count].dest = -1;
1701 biosdir->entries[count].reset = 0;
1702 biosdir->entries[count].ro = 0;
1703 count++;
1704 }
1705
Zheng Baobf29a0d2020-12-03 23:00:48 +08001706 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001707}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001708
1709enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001710 AMDFW_OPT_CONFIG = 'c',
1711 AMDFW_OPT_DEBUG = 'd',
1712 AMDFW_OPT_HELP = 'h',
1713 AMDFW_OPT_LIST_DEPEND = 'l',
1714
1715 AMDFW_OPT_XHCI = 128,
1716 AMDFW_OPT_IMC,
1717 AMDFW_OPT_GEC,
1718 AMDFW_OPT_COMBO,
Zheng Bao990d1542021-09-17 13:24:54 +08001719 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001720 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001721 AMDFW_OPT_USE_COMBO,
Zheng Bao806892a2021-04-27 17:21:54 +08001722 AMDFW_OPT_MULTILEVEL,
1723 AMDFW_OPT_NVRAM,
1724
1725 AMDFW_OPT_FUSE,
1726 AMDFW_OPT_UNLOCK,
1727 AMDFW_OPT_WHITELIST,
1728 AMDFW_OPT_USE_PSPSECUREOS,
1729 AMDFW_OPT_LOAD_MP2FW,
1730 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001731 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001732 AMDFW_OPT_VERSTAGE,
1733 AMDFW_OPT_VERSTAGE_SIG,
1734
1735 AMDFW_OPT_INSTANCE,
1736 AMDFW_OPT_APCB,
1737 AMDFW_OPT_APOBBASE,
1738 AMDFW_OPT_BIOSBIN,
1739 AMDFW_OPT_BIOSBIN_SOURCE,
1740 AMDFW_OPT_BIOSBIN_DEST,
1741 AMDFW_OPT_BIOS_UNCOMP_SIZE,
1742 AMDFW_OPT_UCODE,
1743 AMDFW_OPT_APOB_NVBASE,
1744 AMDFW_OPT_APOB_NVSIZE,
1745
1746 AMDFW_OPT_OUTPUT,
1747 AMDFW_OPT_FLASHSIZE,
1748 AMDFW_OPT_LOCATION,
1749 AMDFW_OPT_ANYWHERE,
1750 AMDFW_OPT_SHAREDMEM,
1751 AMDFW_OPT_SHAREDMEM_SIZE,
1752 AMDFW_OPT_SOC_NAME,
Kangheui Won3c164e12021-12-03 20:25:05 +11001753 AMDFW_OPT_SIGNED_OUTPUT,
1754 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001755 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001756 /* begin after ASCII characters */
1757 LONGOPT_SPI_READ_MODE = 256,
1758 LONGOPT_SPI_SPEED = 257,
1759 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301760 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301761 LONGOPT_NVRAM_BASE = 260,
1762 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001763};
1764
Zheng Bao806892a2021-04-27 17:21:54 +08001765static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
1766 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP, AMDFW_OPT_LIST_DEPEND
1767};
Marc Jones90099b62016-09-20 21:05:45 -06001768
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001769static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001770 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1771 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1772 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001773 /* PSP Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001774 {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO },
Zheng Bao990d1542021-09-17 13:24:54 +08001775 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001776 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001777 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao806892a2021-04-27 17:21:54 +08001778 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1779 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301780 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1781 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001782 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1783 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1784 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1785 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1786 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1787 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001788 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001789 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1790 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001791 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001792 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1793 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1794 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1795 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1796 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1797 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1798 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Ritul Guru9a321f32022-07-29 11:06:40 +05301799 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001800 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1801 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1802 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001803 /* Embedded Firmware Structure items*/
1804 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1805 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1806 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001807 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001808 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001809 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1810 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1811 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1812 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1813 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1814 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
1815 {"soc-name", required_argument, 0, AMDFW_OPT_SOC_NAME },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001816
Kangheui Won3c164e12021-12-03 20:25:05 +11001817 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1818 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1819
Zheng Bao806892a2021-04-27 17:21:54 +08001820 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1821 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1822 {"help", no_argument, 0, AMDFW_OPT_HELP },
1823 {"list", no_argument, 0, AMDFW_OPT_LIST_DEPEND },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001824 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001825};
1826
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001827void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001828{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001829 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001830
1831 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1832 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1833 continue;
1834
1835 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1836 return;
1837 }
1838}
1839
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001840static void register_fw_token_unlock(void)
1841{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001842 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001843
1844 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1845 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1846 continue;
1847
1848 amd_psp_fw_table[i].other = 1;
1849 return;
1850 }
1851}
1852
Marshall Dawsondbae6322019-03-04 10:31:03 -07001853static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001854{
Martin Roth8806f7f2016-11-08 10:44:18 -07001855 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001856
Martin Rothcd15bc82016-11-08 11:34:02 -07001857 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001858 if (amd_fw_table[i].type == type) {
1859 amd_fw_table[i].filename = filename;
1860 return;
1861 }
1862 }
1863
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001864 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001865 if (amd_psp_fw_table[i].type != type)
1866 continue;
1867
1868 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001869 amd_psp_fw_table[i].filename = filename;
1870 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001871 }
1872 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001873}
1874
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001875static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1876{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001877 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001878
1879 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1880 if (amd_bios_table[i].type == type
1881 && amd_bios_table[i].inst == ins
1882 && amd_bios_table[i].subpr == sub) {
1883 amd_bios_table[i].filename = name;
1884 return;
1885 }
1886 }
1887}
1888
Ritul Gurua2cb3402022-08-29 00:51:08 +05301889static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1890 char *dst_str, char *size_str)
1891{
1892 unsigned int i;
1893
1894 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1895 if (amd_psp_fw_table[i].type != type)
1896 continue;
1897
1898 if (amd_psp_fw_table[i].subprog == sub) {
1899 if (dst_str)
1900 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1901 if (size_str)
1902 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1903 return;
1904 }
1905 }
1906}
1907
1908static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001909 char *dst_str, char *size_str)
1910{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001911 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001912 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1913 if (amd_bios_table[i].type != type)
1914 continue;
1915
1916 if (src_str)
1917 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1918 if (dst_str)
1919 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1920 if (size_str)
1921 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1922
1923 return;
1924 }
1925}
1926
Zheng Baoc3007f32022-04-03 12:53:51 +08001927static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1928 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1929 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001930{
1931 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001932 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001933 return 1;
1934 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001935
1936 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1937 * Leave as 0xffffffff for first gen */
1938 if (cb_config->second_gen) {
1939 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1940 amd_romsig->efs_gen.reserved = 0;
1941 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001942 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1943 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001944 }
1945
1946 switch (soc_id) {
1947 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001948 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1949 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1950 break;
1951 case PLATFORM_RAVEN:
1952 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001953 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1954 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1955 switch (efs_spi_micron_flag) {
1956 case 0:
1957 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1958 break;
1959 case 1:
1960 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1961 break;
1962 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001963 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001964 return 1;
1965 }
1966 break;
1967 case PLATFORM_RENOIR:
1968 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001969 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001970 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001971 case PLATFORM_PHOENIX:
1972 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001973 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1974 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1975 switch (efs_spi_micron_flag) {
1976 case 0:
1977 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1978 break;
1979 case 1:
1980 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1981 break;
1982 case 2:
1983 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1984 break;
1985 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001986 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001987 return 1;
1988 }
1989 break;
1990 case PLATFORM_UNKNOWN:
1991 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001992 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001993 return 1;
1994 }
1995 return 0;
1996}
1997
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001998static ssize_t write_efs(char *output, embedded_firmware *amd_romsig)
1999{
2000 char efs_name[PATH_MAX], efs_tmp_name[PATH_MAX];
2001 int ret;
2002 int fd;
2003 ssize_t bytes = -1;
2004
2005 /* Create a tmp file and rename it at the end so that make does not get confused
2006 if amdfwtool is killed for some unexpected reasons. */
2007 ret = snprintf(efs_tmp_name, sizeof(efs_tmp_name), "%s%s%s",
2008 output, EFS_FILE_SUFFIX, TMP_FILE_SUFFIX);
2009 if (ret < 0) {
2010 fprintf(stderr, "Error %s forming EFS tmp file name: %d\n",
2011 strerror(errno), ret);
2012 exit(1);
2013 } else if ((unsigned int)ret >= sizeof(efs_tmp_name)) {
2014 fprintf(stderr, "EFS File name %d > %zu\n", ret, sizeof(efs_tmp_name));
2015 exit(1);
2016 }
2017
2018 fd = open(efs_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
2019 if (fd < 0) {
2020 fprintf(stderr, "Error: Opening %s file: %s\n", efs_tmp_name, strerror(errno));
2021 exit(1);
2022 }
2023
2024 bytes = write_from_buf_to_file(fd, amd_romsig, sizeof(*amd_romsig));
2025 if (bytes != sizeof(*amd_romsig)) {
2026 fprintf(stderr, "Error: Writing to file %s failed\n", efs_tmp_name);
2027 exit(1);
2028 }
2029 close(fd);
2030
2031 /* Rename the tmp file */
2032 ret = snprintf(efs_name, sizeof(efs_name), "%s%s", output, EFS_FILE_SUFFIX);
2033 if (ret < 0) {
2034 fprintf(stderr, "Error %s forming EFS file name: %d\n", strerror(errno), ret);
2035 exit(1);
2036 }
2037
2038 if (rename(efs_tmp_name, efs_name)) {
2039 fprintf(stderr, "Error: renaming file %s to %s\n", efs_tmp_name, efs_name);
2040 exit(1);
2041 }
2042
2043 return bytes;
2044}
2045
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002046static int identify_platform(char *soc_name)
2047{
2048 if (!strcasecmp(soc_name, "Stoneyridge"))
2049 return PLATFORM_STONEYRIDGE;
2050 else if (!strcasecmp(soc_name, "Raven"))
2051 return PLATFORM_RAVEN;
2052 else if (!strcasecmp(soc_name, "Picasso"))
2053 return PLATFORM_PICASSO;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002054 else if (!strcasecmp(soc_name, "Cezanne"))
2055 return PLATFORM_CEZANNE;
Zheng Bao535ec532021-08-12 16:30:19 +08002056 else if (!strcasecmp(soc_name, "Mendocino"))
2057 return PLATFORM_MENDOCINO;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002058 else if (!strcasecmp(soc_name, "Renoir"))
2059 return PLATFORM_RENOIR;
2060 else if (!strcasecmp(soc_name, "Lucienne"))
2061 return PLATFORM_LUCIENNE;
Martin Roth20646cd2023-01-04 21:27:06 -07002062 else if (!strcasecmp(soc_name, "Phoenix"))
2063 return PLATFORM_PHOENIX;
Martin Roth13490832022-10-06 17:18:02 -06002064 else if (!strcasecmp(soc_name, "Glinda"))
2065 return PLATFORM_GLINDA;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002066 else
2067 return PLATFORM_UNKNOWN;
2068
2069}
2070
Felix Heldf8e2e472022-03-29 23:28:49 +02002071static bool needs_ish(enum platform platform_type)
2072{
Zheng Baode6f1982022-10-16 20:32:43 +08002073 if (platform_type == PLATFORM_MENDOCINO || platform_type == PLATFORM_PHOENIX || platform_type == PLATFORM_GLINDA)
Felix Heldf8e2e472022-03-29 23:28:49 +02002074 return true;
2075 else
2076 return false;
2077}
2078
Zheng Baoc3007f32022-04-03 12:53:51 +08002079static bool is_second_gen(enum platform platform_type)
2080{
2081 switch (platform_type) {
2082 case PLATFORM_STONEYRIDGE:
2083 case PLATFORM_RAVEN:
2084 case PLATFORM_PICASSO:
2085 return false;
2086 case PLATFORM_RENOIR:
2087 case PLATFORM_LUCIENNE:
2088 case PLATFORM_CEZANNE:
Jon Murphy9969f4b2022-08-05 13:56:38 -06002089 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002090 case PLATFORM_PHOENIX:
2091 case PLATFORM_GLINDA:
Zheng Baoc3007f32022-04-03 12:53:51 +08002092 return true;
2093 case PLATFORM_UNKNOWN:
2094 default:
2095 fprintf(stderr, "Error: Invalid SOC name.\n\n");
2096 return false;
2097 }
2098}
2099
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002100int main(int argc, char **argv)
2101{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002102 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07002103 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002104 char *tmp;
Martin Roth8806f7f2016-11-08 10:44:18 -07002105 char *rom = NULL;
Marshall Dawson239286c2019-02-23 16:42:46 -07002106 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08002107 psp_directory_table *pspdir = NULL;
2108 psp_directory_table *pspdir2 = NULL;
2109 psp_directory_table *pspdir2_b = NULL;
Zheng Bao6e2c5a32021-11-10 14:09:06 +08002110 bool comboable = false;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002111 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002112 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002113 char *output = NULL, *config = NULL;
2114 FILE *config_handle;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08002115 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002116 /* Values cleared after each firmware or parameter, regardless if N/A */
2117 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08002118 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002119 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06002120 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06002121 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07002122 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002123 uint8_t soc_id = PLATFORM_UNKNOWN;
2124 uint8_t efs_spi_readmode = 0xff;
2125 uint8_t efs_spi_speed = 0xff;
2126 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11002127 const char *signed_output_file = NULL;
2128 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002129
Fred Reitbergerf36b0132022-06-29 13:54:57 -04002130 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08002131 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002132 int list_deps = 0;
2133
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002134 while (1) {
2135 int optindex = 0;
2136
2137 c = getopt_long(argc, argv, optstring, long_options, &optindex);
2138
2139 if (c == -1)
2140 break;
2141
2142 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08002143 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002144 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002145 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002146 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002147 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002148 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002149 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002150 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002151 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002152 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002153 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002154 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002155 case AMDFW_OPT_COMBO:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002156 comboable = true;
Marshall Dawson67d868d2019-02-28 11:43:40 -07002157 break;
Zheng Bao990d1542021-09-17 13:24:54 +08002158 case AMDFW_OPT_RECOVERY_AB:
2159 cb_config.recovery_ab = true;
2160 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002161 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
2162 cb_config.recovery_ab = true;
2163 cb_config.recovery_ab_single_copy = true;
2164 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08002165 case AMDFW_OPT_USE_COMBO:
2166 cb_config.use_combo = true;
2167 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002168 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002169 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06002170 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002171 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002172 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08002173 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002174 sub = instance = 0;
2175 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002176 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002177 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07002178 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002179 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002180 instance = strtoul(optarg, &tmp, 16);
2181 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002182 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002183 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002184 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002185 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002186 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002187 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002188 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002189 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002190 register_fw_fuse(optarg);
2191 fuse_defined = 1;
2192 sub = 0;
2193 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002194 case AMDFW_OPT_APCB:
Zheng Bao5caca942020-12-04 16:39:38 +08002195 if ((instance & 0xF0) == 0)
2196 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
2197 else
2198 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2199 instance & 0xF, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002200 sub = instance = 0;
2201 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002202 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002203 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302204 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002205 sub = instance = 0;
2206 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002207 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002208 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302209 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002210 sub = instance = 0;
2211 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002212 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002213 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302214 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002215 sub = instance = 0;
2216 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002217 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002218 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2219 sub = instance = 0;
2220 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002221 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002222 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302223 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002224 sub = instance = 0;
2225 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002226 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002227 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302228 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002229 sub = instance = 0;
2230 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002231 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002232 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302233 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002234 sub = instance = 0;
2235 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302236 case LONGOPT_BIOS_SIG:
2237 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302238 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302239 sub = instance = 0;
2240 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002241 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002242 register_bdt_data(AMD_BIOS_UCODE, sub,
2243 instance, optarg);
2244 sub = instance = 0;
2245 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002246 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002247 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002248 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002249 case AMDFW_OPT_SPL_TABLE:
2250 register_fw_filename(AMD_FW_SPL, sub, optarg);
2251 sub = instance = 0;
2252 cb_config.have_mb_spl = true;
2253 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002254 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002255 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2256 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002257 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002258 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002259 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002260 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2261 sub = instance = 0;
2262 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002263 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002264 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2265 sub = instance = 0;
2266 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002267 case AMDFW_OPT_SOC_NAME:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002268 soc_id = identify_platform(optarg);
2269 if (soc_id == PLATFORM_UNKNOWN) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002270 fprintf(stderr, "Error: Invalid SOC name specified\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002271 retval = 1;
2272 }
2273 sub = instance = 0;
2274 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002275 case AMDFW_OPT_SIGNED_OUTPUT:
2276 signed_output_file = optarg;
2277 sub = instance = 0;
2278 break;
2279 case AMDFW_OPT_SIGNED_ADDR:
2280 signed_start_addr = strtoull(optarg, NULL, 10);
2281 sub = instance = 0;
2282 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002283 case LONGOPT_SPI_READ_MODE:
2284 efs_spi_readmode = strtoull(optarg, NULL, 16);
2285 sub = instance = 0;
2286 break;
2287 case LONGOPT_SPI_SPEED:
2288 efs_spi_speed = strtoull(optarg, NULL, 16);
2289 sub = instance = 0;
2290 break;
2291 case LONGOPT_SPI_MICRON_FLAG:
2292 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2293 sub = instance = 0;
2294 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002295 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002296 output = optarg;
2297 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002298 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002299 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002300 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002301 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002302 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002303 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002304 }
2305 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002306 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002307 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002308 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002309 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002310 " incorrectly (%s)\n\n", optarg);
2311 retval = 1;
2312 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002313 if (body_location == 0)
2314 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002315 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002316 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002317 any_location = 1;
2318 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002319 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002320 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302321 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002322 sub = instance = 0;
2323 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002324 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002325 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302326 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002327 sub = instance = 0;
2328 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302329 case LONGOPT_NVRAM_BASE:
2330 /* PSP NV base */
2331 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2332 sub = instance = 0;
2333 break;
2334 case LONGOPT_NVRAM_SIZE:
2335 /* PSP NV size */
2336 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2337 sub = instance = 0;
2338 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002339 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002340 config = optarg;
2341 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002342 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002343 debug = 1;
2344 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002345 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002346 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002347 return 0;
Zheng Bao806892a2021-04-27 17:21:54 +08002348 case AMDFW_OPT_LIST_DEPEND:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002349 list_deps = 1;
2350 break;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002351 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002352 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002353 if (*tmp != '\0') {
2354 fprintf(stderr, "Error: Body Location specified"
2355 " incorrectly (%s)\n\n", optarg);
2356 retval = 1;
2357 }
2358 break;
2359
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002360 default:
2361 break;
2362 }
2363 }
2364
Zheng Baoc3007f32022-04-03 12:53:51 +08002365 cb_config.second_gen = is_second_gen(soc_id);
2366
Felix Heldf8e2e472022-03-29 23:28:49 +02002367 if (needs_ish(soc_id))
2368 cb_config.need_ish = true;
2369
Felix Held830add62022-03-29 23:28:10 +02002370 if (cb_config.need_ish)
2371 cb_config.recovery_ab = true;
2372
2373 if (cb_config.recovery_ab)
2374 cb_config.multi_level = true;
2375
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002376 if (config) {
2377 config_handle = fopen(config, "r");
2378 if (config_handle == NULL) {
2379 fprintf(stderr, "Can not open file %s for reading: %s\n",
2380 config, strerror(errno));
2381 exit(1);
2382 }
2383 if (process_config(config_handle, &cb_config, list_deps) == 0) {
2384 fprintf(stderr, "Configuration file %s parsing error\n", config);
2385 fclose(config_handle);
2386 exit(1);
2387 }
2388 fclose(config_handle);
2389 }
Zheng Bao9e908072020-10-28 11:39:13 +08002390 /* For debug. */
2391 if (debug) {
2392 dump_psp_firmwares(amd_psp_fw_table);
2393 dump_bdt_firmwares(amd_bios_table);
2394 }
2395
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002396 if (!fuse_defined)
2397 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2398
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002399 if (!output && !list_deps) {
2400 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002401 retval = 1;
2402 }
2403
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002404 if ((ctx.rom_size % 1024 != 0) && !list_deps) {
2405 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002406 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002407 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002408 }
2409
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002410 if ((ctx.rom_size < MIN_ROM_KB * 1024) && !list_deps) {
2411 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002412 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002413 retval = 1;
2414 }
2415
2416 if (retval) {
2417 usage();
2418 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002419 }
2420
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002421 if (list_deps) {
2422 return retval;
2423 }
2424
Marshall Dawson2794a862019-03-04 16:53:15 -07002425 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002426
Marshall Dawson2794a862019-03-04 16:53:15 -07002427 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002428 if (efs_location && (efs_location < rom_base_address)) {
2429 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2430 return 1;
2431 }
2432
Zheng Bao99945dc2023-01-02 10:55:56 +08002433 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002434 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2435 return 1;
2436 }
2437
2438 /*
2439 * On boards using vboot, there can be more than one instance of EFS + AMDFW Body.
2440 * For the instance in the RO section, there is no need to split EFS + AMDFW body
2441 * currently. This condition is to ensure that it is not accidentally split. Revisit
2442 * this condition if such a need arises in the future.
2443 */
Zheng Bao99945dc2023-01-02 10:55:56 +08002444 if (!any_location && body_location != efs_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002445 fprintf(stderr, "Error: EFS cannot be separate from AMDFW Body.\n");
2446 return 1;
2447 }
2448
Zheng Bao99945dc2023-01-02 10:55:56 +08002449 if (body_location != efs_location &&
2450 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002451 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2452 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002453 return 1;
2454 }
2455
Martin Roth37305e72020-04-07 14:16:39 -06002456 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002457 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002458 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002459 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002460 return 1;
2461 }
2462 } else {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002463 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002464 case 0:
2465 case 0xFFFA0000:
2466 case 0xFFF20000:
2467 case 0xFFE20000:
2468 case 0xFFC20000:
2469 case 0xFF820000:
2470 case 0xFF020000:
Martin Roth37305e72020-04-07 14:16:39 -06002471 break;
2472 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002473 fprintf(stderr, "Error: Invalid Directory location.\n");
2474 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2475 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002476 return 1;
2477 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002478 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002479 ctx.rom = malloc(ctx.rom_size);
2480 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002481 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002482 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002483 }
2484 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002485
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002486 if (efs_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002487 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002488 romsig_offset = efs_location - rom_base_address;
Zheng Bao99945dc2023-01-02 10:55:56 +08002489 ctx.current = body_location - rom_base_address;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002490 } else {
2491 romsig_offset = efs_location - rom_base_address;
2492 ctx.current = romsig_offset + sizeof(embedded_firmware);
2493 }
2494 } else {
2495 romsig_offset = AMD_ROMSIG_OFFSET;
2496 ctx.current = romsig_offset + sizeof(embedded_firmware);
2497 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002498
Marshall Dawson2794a862019-03-04 16:53:15 -07002499 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002500 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2501 amd_romsig->imc_entry = 0;
2502 amd_romsig->gec_entry = 0;
2503 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002504
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002505 if (soc_id != PLATFORM_UNKNOWN) {
Zheng Baoc3007f32022-04-03 12:53:51 +08002506 retval = set_efs_table(soc_id, &cb_config, amd_romsig, efs_spi_readmode,
Zheng Bao570645d2021-11-03 10:25:03 +08002507 efs_spi_speed, efs_spi_micron_flag);
2508 if (retval) {
2509 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2510 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002511 }
2512 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002513 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002514 }
2515
Felix Held21a8e382022-03-29 23:10:45 +02002516 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002517 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002518 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002519 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002520 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002521 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002522 printf(" AMDFWTOOL Using firmware directory location of %s address: 0x%08x\n",
Robert Zieba29bc79f2022-03-14 15:59:12 -06002523 ctx.address_mode == AMD_ADDR_PHYSICAL ? "absolute" : "relative",
Zheng Bao6fff2492021-11-15 19:53:21 +08002524 RUN_CURRENT(ctx));
Zheng Baoda83d2c2021-06-04 19:03:10 +08002525
Marshall Dawson2794a862019-03-04 16:53:15 -07002526 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002527
Elyes Haouas7d67a192022-10-14 09:58:29 +02002528 ctx.current = ALIGN_UP(ctx.current, 0x10000U); /* TODO: is it necessary? */
Zheng Bao6fff2492021-11-15 19:53:21 +08002529 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002530
Kangheui Won3c164e12021-12-03 20:25:05 +11002531 /* If the tool is invoked with command-line options to keep the signed PSP
2532 binaries separate, process the signed binaries first. */
2533 if (signed_output_file && signed_start_addr)
2534 process_signed_psp_firmwares(signed_output_file,
2535 amd_psp_fw_table,
2536 signed_start_addr,
2537 soc_id);
2538
Zheng Bao481661e2021-08-20 14:47:46 +08002539 if (cb_config.multi_level) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06002540 /* Do 2nd PSP directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002541 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2542 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002543 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002544 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2545 /* Create a copy of PSP Directory 2 in the backup slot B.
2546 Related biosdir2_b copy will be created later. */
Zheng Bao990d1542021-09-17 13:24:54 +08002547 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2548 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002549 amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002550 } else {
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06002551 /*
2552 * Either the platform is using only one slot or B is same as above
2553 * directories for A. Skip creating pspdir2_b here to save flash space.
2554 * Related biosdir2_b will be skipped automatically.
2555 */
Zheng Bao990d1542021-09-17 13:24:54 +08002556 pspdir2_b = NULL; /* More explicitly */
2557 }
Zheng Bao481661e2021-08-20 14:47:46 +08002558 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002559 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002560 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002561 } else {
2562 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002563 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
Zheng Bao990d1542021-09-17 13:24:54 +08002564 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
Zheng Baofdd47ef2021-09-17 13:30:08 +08002565 amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config);
Marshall Dawson24f73d42019-04-01 10:48:43 -06002566 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002567
Marshall Dawson0e02ce82019-03-04 16:50:37 -07002568 if (comboable)
Zheng Baob749d3f2021-10-23 20:20:21 +08002569 amd_romsig->new_psp_directory = BUFF_TO_RUN(ctx, pspdir);
Marshall Dawson67d868d2019-02-28 11:43:40 -07002570 else
Felix Heldad68b072021-10-18 14:00:35 +02002571 amd_romsig->psp_directory = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002572
Zheng Bao993b43f2021-11-10 12:21:46 +08002573 if (cb_config.use_combo) {
2574 psp_combo_directory *combo_dir = new_combo_dir(&ctx);
2575 amd_romsig->combo_psp_directory = BUFF_TO_RUN(ctx, combo_dir);
2576 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2577 combo_dir->entries[0].id_sel = 0;
2578 combo_dir->entries[0].id = get_psp_id(soc_id);
2579 combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002580
Zheng Bao993b43f2021-11-10 12:21:46 +08002581 combo_dir->header.lookup = 1;
2582 fill_dir_header(combo_dir, 1, PSP2_COOKIE, &ctx);
2583 }
Zheng Bao4fcc9f22015-11-20 12:29:04 +08002584
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002585 if (have_bios_tables(amd_bios_table)) {
Zheng Bao990d1542021-09-17 13:24:54 +08002586 bios_directory_table *biosdir = NULL;
Zheng Bao481661e2021-08-20 14:47:46 +08002587 if (cb_config.multi_level) {
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002588 /* Do 2nd level BIOS directory followed by 1st */
Zheng Bao990d1542021-09-17 13:24:54 +08002589 bios_directory_table *biosdir2 = NULL;
2590 bios_directory_table *biosdir2_b = NULL;
2591
2592 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2593
Zheng Baoedd1e362021-11-04 17:47:07 +08002594 integrate_bios_firmwares(&ctx, biosdir2, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002595 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002596 if (cb_config.recovery_ab) {
2597 if (pspdir2_b != NULL) {
2598 biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level);
2599 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002600 amd_bios_table, BHDL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002601 }
2602 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2603 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2604 if (pspdir2_b != NULL)
2605 add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b,
2606 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2607 } else {
2608 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2609 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
Zheng Bao96a33712021-06-11 15:54:40 +08002610 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002611 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002612 } else {
Zheng Bao96a33712021-06-11 15:54:40 +08002613 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Bao481661e2021-08-20 14:47:46 +08002614 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
Zheng Baoedd1e362021-11-04 17:47:07 +08002615 integrate_bios_firmwares(&ctx, biosdir, NULL,
Zheng Bao96a33712021-06-11 15:54:40 +08002616 amd_bios_table, BHD_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002617 }
Zheng Baobf29a0d2020-12-03 23:00:48 +08002618 switch (soc_id) {
2619 case PLATFORM_RENOIR:
2620 case PLATFORM_LUCIENNE:
2621 case PLATFORM_CEZANNE:
Zheng Bao990d1542021-09-17 13:24:54 +08002622 if (!cb_config.recovery_ab)
2623 amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir);
Zheng Baobf29a0d2020-12-03 23:00:48 +08002624 break;
Zheng Bao535ec532021-08-12 16:30:19 +08002625 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08002626 case PLATFORM_PHOENIX:
2627 case PLATFORM_GLINDA:
Zheng Bao535ec532021-08-12 16:30:19 +08002628 break;
Zheng Baobf29a0d2020-12-03 23:00:48 +08002629 case PLATFORM_STONEYRIDGE:
2630 case PLATFORM_RAVEN:
2631 case PLATFORM_PICASSO:
2632 default:
2633 amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir);
2634 break;
2635 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002636 }
2637
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002638 /* Free the filename. */
2639 free_psp_firmware_filenames(amd_psp_fw_table);
2640 free_bdt_firmware_filenames(amd_bios_table);
2641
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002642 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002643 if (targetfd >= 0) {
Zheng Bao47396912020-09-29 17:33:17 +08002644 ssize_t bytes;
Zheng Bao99945dc2023-01-02 10:55:56 +08002645 uint32_t offset = body_location ? body_location - rom_base_address : AMD_ROMSIG_OFFSET;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002646
2647 bytes = write(targetfd, BUFF_OFFSET(ctx, offset), ctx.current - offset);
2648 if (bytes != ctx.current - offset) {
Zheng Bao47396912020-09-29 17:33:17 +08002649 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2650 retval = 1;
2651 }
Martin Roth31d95a22016-11-08 11:22:12 -07002652 close(targetfd);
2653 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002654 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002655 retval = 1;
2656 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002657
Zheng Bao99945dc2023-01-02 10:55:56 +08002658 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002659 ssize_t bytes;
2660
2661 bytes = write_efs(output, amd_romsig);
2662 if (bytes != sizeof(*amd_romsig)) {
2663 fprintf(stderr, "Error: Writing EFS\n");
2664 retval = 1;
2665 }
2666 }
2667
Martin Roth31d95a22016-11-08 11:22:12 -07002668 free(rom);
2669 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002670}