blob: 4d821bdf76518663277953e133816e9962691b44 [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
Zheng Baodd4c5422021-10-14 16:14:09 +08004 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +08009 * | PSPDIR ADDR|PSPDIR ADDR(C) | BDT ADDR 0 | BDT ADDR 1 |
10 * +------------+---------------+----------------+------------+
11 * | BDT ADDR 2 | | BDT ADDR 3(C) | |
12 * +------------+---------------+----------------+------------+
13 * (C): Could be a combo header
14 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080015 * EC ROM should be 64K aligned.
16 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080017 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080018 * +------------+---------------+----------------+------------+
19 * | 'PSP$' | Fletcher | Count | Reserved |
20 * +------------+---------------+----------------+------------+
21 * | 0 | size | Base address | Reserved | Pubkey
22 * +------------+---------------+----------------+------------+
23 * | 1 | size | Base address | Reserved | Bootloader
24 * +------------+---------------+----------------+------------+
25 * | 8 | size | Base address | Reserved | Smu Firmware
26 * +------------+---------------+----------------+------------+
27 * | 3 | size | Base address | Reserved | Recovery Firmware
28 * +------------+---------------+----------------+------------+
29 * | |
30 * | |
Zheng Baodd4c5422021-10-14 16:14:09 +080031 * | Other PSP Firmware |
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080032 * | |
33 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080034 * | 40 | size | Base address | Reserved |---+
35 * +------------+---------------+----------------+------------+ |
36 * :or 48(A/B A): size : Base address : Reserved : |
37 * + - - + - - + - - + - - + |
38 * : 4A(A/B B): size : Base address : Reserved : |
39 * +------------+---------------+----------------+------------+ |
40 * (A/B A) & (A/B B): Similar as 40, pointing to PSP level 2 |
41 * for A/B recovery |
42 * |
43 * |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
47 * | |
48 * | |
49 * | PSP Firmware |
50 * | (2nd-level is not required on all families) |
51 * | |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
Zheng Bao4fcc9f22015-11-20 12:29:04 +080054 *
zbaoc3b0b722016-02-19 13:47:31 +080055 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080056 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080057 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080058 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080059 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080061 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080062 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080063 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080064 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080069 * BDT Combo is similar
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080070 */
71
Elyes Haouas7d67a192022-10-14 09:58:29 +020072#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080073#include <fcntl.h>
74#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060075#include <limits.h>
Martin Roth37305e72020-04-07 14:16:39 -060076#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080077#include <stdio.h>
78#include <sys/stat.h>
79#include <sys/types.h>
80#include <unistd.h>
81#include <string.h>
82#include <stdlib.h>
83#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080084#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010085#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080086
87#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080088
Martin Roth60f15512016-11-08 09:55:01 -070089#define AMD_ROMSIG_OFFSET 0x20000
90#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080091
Marshall Dawson7c1e1422019-04-11 09:44:43 -060092#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080093
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060094#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
95
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060096#define EFS_FILE_SUFFIX ".efs"
97#define TMP_FILE_SUFFIX ".tmp"
Zheng Bao69ea83c2023-01-22 21:08:18 +080098#define BODY_FILE_SUFFIX ".body"
Kangheui Won5b84dfd2021-12-21 15:45:06 +110099
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800100/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700101 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
102 * can support an optional "combo" implementation. If the PSP sees the
103 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
104 * tables. Using this, support for multiple product generations may be
105 * built into one image. If the PSP$ cookie is found, the table is a
106 * normal directory table.
107 *
108 * Modern generations supporting the combo directories require the
109 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
Zheng Baoc91867a2023-02-26 12:31:31 +0800110 * regardless of the type of directory used. The --use-combo
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700111 * argument enforces this placement.
112 *
113 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800114 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800115
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800116/*
117 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
118 * The checksum field of the passed PDU does not need to be reset to zero.
119 *
120 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
121 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
122 * alternative to cyclical redundancy checks because it provides error-
123 * detection properties similar to cyclical redundancy checks but at the
124 * cost of a simple summation technique. Its characteristics were first
125 * published in IEEE Transactions on Communications in January 1982. One
126 * version has been adopted by ISO for use in the class-4 transport layer
127 * of the network protocol.
128 *
129 * This program expects:
130 * stdin: The input file to compute a checksum for. The input file
131 * not be longer than 256 bytes.
132 * stdout: Copied from the input file with the Fletcher's Checksum
133 * inserted 8 bytes after the beginning of the file.
134 * stderr: Used to print out error messages.
135 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700136static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800137{
138 uint32_t c0;
139 uint32_t c1;
140 uint32_t checksum;
141 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700142 const uint16_t *pptr = data;
143
144 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800145
146 c0 = 0xFFFF;
147 c1 = 0xFFFF;
148
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600149 while (length) {
150 index = length >= 359 ? 359 : length;
151 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800152 do {
153 c0 += *(pptr++);
154 c1 += c0;
155 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600156 c0 = (c0 & 0xFFFF) + (c0 >> 16);
157 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800158 }
159
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700160 /* Sums[0,1] mod 64K + overflow */
161 c0 = (c0 & 0xFFFF) + (c0 >> 16);
162 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800163 checksum = (c1 << 16) | c0;
164
165 return checksum;
166}
167
Martin Roth8806f7f2016-11-08 10:44:18 -0700168static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800169{
Martin Roth0e940622016-11-08 10:37:53 -0700170 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800171 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
172 printf("--xhci <FILE> Add XHCI blob\n");
173 printf("--imc <FILE> Add IMC blob\n");
174 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700175
176 printf("\nPSP options:\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800177 printf("--use-combo Use the COMBO layout\n");
Zheng Baoe3ebc4f2023-03-23 10:52:59 +0800178 printf("--combo-config1 <config file> Config for 1st combo entry\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800179 printf("--multilevel Generate primary and secondary tables\n");
180 printf("--nvram <FILE> Add nvram binary\n");
181 printf("--soft-fuse Set soft fuse\n");
182 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530183 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
184 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800185 printf("--whitelist Set if there is a whitelist\n");
186 printf("--use-pspsecureos Set if psp secure OS is needed\n");
187 printf("--load-mp2-fw Set if load MP2 firmware\n");
188 printf("--load-s0i3 Set if load s0i3 firmware\n");
189 printf("--verstage <FILE> Add verstage\n");
190 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800191 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600192 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800193 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800194 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800195 printf("--apcb <FILE> Add AGESA PSP customization block\n");
196 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
197 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
198 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
199 printf("--ucode <FILE> Add microcode patch\n");
200 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
201 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
202 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
203 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
204 printf("--output <filename> output filename\n");
205 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600206 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700207 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600208 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800209 printf("--location Location of Directory\n");
210 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
211 printf("--sharedmem Location of PSP/FW shared memory\n");
212 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800213 printf(" area\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500214 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
215 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
216 printf(" 0x0 66.66Mhz\n");
217 printf(" 0x1 33.33MHz\n");
218 printf(" 0x2 22.22MHz\n");
219 printf(" 0x3 16.66MHz\n");
220 printf(" 0x4 100MHz\n");
221 printf(" 0x5 800KHz\n");
222 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
223 printf(" 0x0 Normal Read (up to 33M)\n");
224 printf(" 0x1 Reserved\n");
225 printf(" 0x2 Dual IO (1-1-2)\n");
226 printf(" 0x3 Quad IO (1-1-4)\n");
227 printf(" 0x4 Dual IO (1-2-2)\n");
228 printf(" 0x5 Quad IO (1-4-4)\n");
229 printf(" 0x6 Normal Read (up to 66M)\n");
230 printf(" 0x7 Fast Read\n");
231 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
232 printf(" 0x0 Micron parts are not used\n");
233 printf(" 0x1 Micron parts are always used\n");
234 printf(" 0x2 Micron parts optional, this option is only\n");
235 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800236 printf("\nGeneral options:\n");
237 printf("-c|--config <config file> Config file\n");
238 printf("-d|--debug Print debug message\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800239 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800240}
241
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800242amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100243 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800244 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800245 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200246 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800247 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200248 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
249 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
250 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800251 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100252 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
253 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200254 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200255 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800256 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
257 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800258 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200259 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
260 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800261 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
262 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
263 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
264 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800265 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao9bb62cb2023-03-07 19:48:11 +0800266 { .type = AMD_HW_IPCFG, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
267 { .type = AMD_HW_IPCFG, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100268 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800269 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
270 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800271 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200272 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800273 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200274 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
275 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800276 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
277 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200278 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
279 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
280 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800281 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800282 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
283 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
286 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
287 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
288 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
289 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200290 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
291 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600292 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200293 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200294 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200295 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
296 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
297 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
298 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
299 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600300 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
301 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200302 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
303 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
305 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
306 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
307 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Nikolai Vyssotskibfc9ca72023-03-07 15:09:09 -0600308 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800309 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200310 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
311 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800312 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
313 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200314 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200315 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200316 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
317 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800318 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
319 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
321 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
322 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
325 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
326 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
327 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
328 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
329 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
330 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
331 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500332 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800333 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800334};
335
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800336amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800337 { .type = AMD_FW_XHCI },
338 { .type = AMD_FW_IMC },
339 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800340 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800341};
342
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800343amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800344 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530345 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600346 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
347 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
348 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
349 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
350 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700351 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
352 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
353 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
355 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
356 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
357 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
361 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700362 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700367 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
377 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600378 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
379 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800380 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600381 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
382 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
383 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800384 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
385 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200386 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
387 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600388 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
389 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800390 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
391 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
392 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
393 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
394 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
395 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200396 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
397 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
398 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
399 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800400 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
401 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
403 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
405 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600406 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
407 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800408 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
409 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200410 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600412 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800414 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
415 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
419 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200420 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800424 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
425 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
427 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
429 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600430 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
431 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
432 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200433 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
434 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
435 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
436 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600437 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600438 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600439 { .type = AMD_BIOS_INVALID },
440};
441
Marshall Dawson2794a862019-03-04 16:53:15 -0700442typedef struct _context {
443 char *rom; /* target buffer, size of flash device */
444 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800445 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700446 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Baoc26108f2023-02-17 11:01:07 +0800447 uint32_t current_pointer_saved;
Zheng Bao6fff2492021-11-15 19:53:21 +0800448 uint32_t current_table;
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800449 void *amd_psp_fw_table_clean;
450 void *amd_bios_table_clean;
Marshall Dawson2794a862019-03-04 16:53:15 -0700451} context;
452
453#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800454#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600455 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
456 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
Zheng Baoc38f7642023-02-21 10:43:08 +0800457 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800458#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600459#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800460 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700461#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800462/* The mode in entry can not be higher than the header's.
463 For example, if table mode is 0, all the entry mode will be 0. */
464#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
465 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700466#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
467#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
468#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800469#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
470 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700471#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800472/* Only set the address mode in entry if the table is mode 2. */
473#define SET_ADDR_MODE(table, mode) \
474 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600475 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800476#define SET_ADDR_MODE_BY_TABLE(table) \
477 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700478
Zheng Bao7c5ad882023-02-19 13:02:52 +0800479
480static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
481{
482 amd_fw_entry *index;
483
484 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
485 if (index->filename &&
486 index->type != AMD_FW_VERSTAGE_SIG &&
487 index->type != AMD_FW_PSP_VERSTAGE &&
488 index->type != AMD_FW_SPL &&
489 index->type != AMD_FW_PSP_WHITELIST) {
490 free(index->filename);
491 index->filename = NULL;
492 }
493 }
494}
495
496static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
497{
498 amd_bios_entry *index;
499
500 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
501 if (index->filename &&
502 index->type != AMD_BIOS_APCB &&
503 index->type != AMD_BIOS_BIN &&
504 index->type != AMD_BIOS_APCB_BK &&
505 index->type != AMD_BIOS_UCODE) {
506 free(index->filename);
507 index->filename = NULL;
508 }
509 }
510}
511
512static void amdfwtool_cleanup(context *ctx)
513{
514 free(ctx->rom);
515 ctx->rom = NULL;
516
517 /* Free the filename. */
518 free_psp_firmware_filenames(amd_psp_fw_table);
519 free_bdt_firmware_filenames(amd_bios_table);
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800520
521 free(ctx->amd_psp_fw_table_clean);
522 ctx->amd_psp_fw_table_clean = NULL;
523 free(ctx->amd_bios_table_clean);
524 ctx->amd_bios_table_clean = NULL;
Zheng Bao7c5ad882023-02-19 13:02:52 +0800525}
526
Zheng Bao5164e4b2021-10-30 12:09:07 +0800527void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
528{
529 if (count >= max) {
530 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
531 "(%d)\n", count, max);
Zheng Bao7c5ad882023-02-19 13:02:52 +0800532 amdfwtool_cleanup(ctx);
Zheng Bao5164e4b2021-10-30 12:09:07 +0800533 exit(1);
534 }
535}
536
Zheng Baoc26108f2023-02-17 11:01:07 +0800537static void set_current_pointer(context *ctx, uint32_t value)
538{
539 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
540 ctx->current_pointer_saved != ctx->current) {
541 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800542 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800543 exit(1);
544 }
545
546 ctx->current = value;
547
548 if (ctx->current > ctx->rom_size) {
549 fprintf(stderr, "Error: Packing data causes overflow\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800550 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800551 exit(1);
552 }
553
554 ctx->current_pointer_saved = ctx->current;
555}
556
557static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
558{
559 /* Get */
560 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
561}
562
Marshall Dawson24f73d42019-04-01 10:48:43 -0600563static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700564{
565 void *ptr;
566
Marshall Dawson24f73d42019-04-01 10:48:43 -0600567 /*
568 * Force both onto boundary when multi. Primary table is after
569 * updatable table, so alignment ensures primary can stay intact
570 * if secondary is reprogrammed.
571 */
572 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +0800573 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600574 else
Zheng Baoc26108f2023-02-17 11:01:07 +0800575 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600576
Marshall Dawson2794a862019-03-04 16:53:15 -0700577 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800578 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800579 ((psp_directory_header *)ptr)->additional_info = 0;
580 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +0800581 adjust_current_pointer(ctx,
582 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
583 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700584 return ptr;
585}
586
Zheng Baofdd47ef2021-09-17 13:30:08 +0800587static void *new_ish_dir(context *ctx)
588{
589 void *ptr;
Zheng Baoc26108f2023-02-17 11:01:07 +0800590 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800591 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800592 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
593
Zheng Baofdd47ef2021-09-17 13:30:08 +0800594 return ptr;
595}
596
Marshall Dawson2794a862019-03-04 16:53:15 -0700597static void *new_combo_dir(context *ctx)
598{
599 void *ptr;
600
Zheng Baoc26108f2023-02-17 11:01:07 +0800601 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700602 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800603 adjust_current_pointer(ctx,
604 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
605 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700606 return ptr;
607}
608
Zheng Baobf29a0d2020-12-03 23:00:48 +0800609static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800610{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600611 psp_combo_directory *cdir = directory;
612 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600613 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800614 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600615
616 if (!count)
617 return;
Zheng Baob035f582021-05-27 11:26:12 +0800618 if (ctx == NULL || directory == NULL) {
619 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
620 return;
621 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600622
Zheng Baobf29a0d2020-12-03 23:00:48 +0800623 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baoc26108f2023-02-17 11:01:07 +0800624 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800625
Marshall Dawson24f73d42019-04-01 10:48:43 -0600626 switch (cookie) {
627 case PSP2_COOKIE:
Zheng Bao84fb9ea2022-08-18 15:54:47 +0800628 case BHD2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700629 cdir->header.cookie = cookie;
Zheng Baofd51af62022-08-18 15:26:39 +0800630 /* lookup mode is hardcoded for now. */
631 cdir->header.lookup = 1;
Marshall Dawsona378c222019-03-04 16:52:07 -0700632 cdir->header.num_entries = count;
633 cdir->header.reserved[0] = 0;
634 cdir->header.reserved[1] = 0;
635 /* checksum everything that comes after the Checksum field */
636 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
637 count * sizeof(psp_combo_entry)
638 + sizeof(cdir->header.num_entries)
639 + sizeof(cdir->header.lookup)
640 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600641 break;
642 case PSP_COOKIE:
643 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800644 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800645 if ((table_size % TABLE_ALIGNMENT) != 0) {
646 fprintf(stderr, "The PSP table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800647 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800648 exit(1);
649 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700650 dir->header.cookie = cookie;
651 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800652 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
653 dir->header.additional_info_fields.spi_block_size = 1;
654 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700655 /* checksum everything that comes after the Checksum field */
656 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700657 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700658 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800659 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600660 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800661 case BHD_COOKIE:
662 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800663 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800664 if ((table_size % TABLE_ALIGNMENT) != 0) {
665 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800666 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800667 exit(1);
668 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600669 bdir->header.cookie = cookie;
670 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800671 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
672 bdir->header.additional_info_fields.spi_block_size = 1;
673 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600674 /* checksum everything that comes after the Checksum field */
675 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
676 count * sizeof(bios_directory_entry)
677 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800678 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600679 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700680 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800681
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800682}
683
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800684static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
685 context *ctx, amd_cb_config *cb_config)
686{
687 switch (cb_config->soc_id) {
688 case PLATFORM_UNKNOWN:
689 amd_romsig->psp_directory =
690 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
691 break;
692 case PLATFORM_CEZANNE:
693 case PLATFORM_MENDOCINO:
694 case PLATFORM_PHOENIX:
695 case PLATFORM_GLINDA:
696 case PLATFORM_CARRIZO:
697 case PLATFORM_STONEYRIDGE:
698 case PLATFORM_RAVEN:
699 case PLATFORM_PICASSO:
700 case PLATFORM_LUCIENNE:
701 case PLATFORM_RENOIR:
702 default:
703 /* for combo, it is also combo_psp_directory */
704 amd_romsig->new_psp_directory =
705 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
706 break;
707 }
708}
709
710static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
711 context *ctx, amd_cb_config *cb_config)
712{
713 switch (cb_config->soc_id) {
714 case PLATFORM_RENOIR:
715 case PLATFORM_LUCIENNE:
716 case PLATFORM_CEZANNE:
717 if (!cb_config->recovery_ab)
718 amd_romsig->bios3_entry =
719 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
720 break;
721 case PLATFORM_MENDOCINO:
722 case PLATFORM_PHOENIX:
723 case PLATFORM_GLINDA:
724 break;
725 case PLATFORM_CARRIZO:
726 case PLATFORM_STONEYRIDGE:
727 case PLATFORM_RAVEN:
728 case PLATFORM_PICASSO:
729 default:
730 amd_romsig->bios1_entry =
731 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
732 break;
733 }
734}
735
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700736static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
737{
738 int fd;
739 struct stat fd_stat;
740 ssize_t bytes;
741
742 fd = open(src_file, O_RDONLY);
743 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800744 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700745 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700746 return -1;
747 }
748
749 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800750 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600751 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700752 return -2;
753 }
754
Zheng Bao6d402ac2020-10-01 16:16:30 +0800755 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800756 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600757 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700758 return -3;
759 }
760
761 bytes = read(fd, dest, (size_t)fd_stat.st_size);
762 close(fd);
763 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800764 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700765 return -4;
766 }
767
768 return bytes;
769}
770
Zheng Baoeb0404e2021-10-14 15:09:09 +0800771static uint32_t get_psp_id(enum platform soc_id)
772{
773 uint32_t psp_id;
774 switch (soc_id) {
775 case PLATFORM_RAVEN:
776 case PLATFORM_PICASSO:
777 psp_id = 0xBC0A0000;
778 break;
779 case PLATFORM_RENOIR:
780 case PLATFORM_LUCIENNE:
781 psp_id = 0xBC0C0000;
782 break;
783 case PLATFORM_CEZANNE:
784 psp_id = 0xBC0C0140;
785 break;
786 case PLATFORM_MENDOCINO:
787 psp_id = 0xBC0D0900;
788 break;
789 case PLATFORM_STONEYRIDGE:
790 psp_id = 0x10220B00;
791 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800792 case PLATFORM_GLINDA:
793 psp_id = 0xBC0E0200;
794 break;
795 case PLATFORM_PHOENIX:
796 psp_id = 0xBC0D0400;
797 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800798 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800799 default:
800 psp_id = 0;
801 break;
802 }
803 return psp_id;
804}
805
Marshall Dawson2794a862019-03-04 16:53:15 -0700806static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700807 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700808 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800809{
Richard Spiegel137484d2018-01-17 10:23:19 -0700810 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800811 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700812
Zheng Baoc26108f2023-02-17 11:01:07 +0800813 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800814
Martin Rothcd15bc82016-11-08 11:34:02 -0700815 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800816 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800817 switch (fw_table[i].type) {
818 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800819 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700820 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800821 break;
822 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700823 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800824 break;
825 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700826 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800827 break;
828 default:
829 /* Error */
830 break;
831 }
832
Marshall Dawson2794a862019-03-04 16:53:15 -0700833 bytes = copy_blob(BUFF_CURRENT(*ctx),
834 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600835 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800836 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700837 exit(1);
838 }
839
Zheng Baoc26108f2023-02-17 11:01:07 +0800840 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800841 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800842 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800843}
844
Zheng Bao9e908072020-10-28 11:39:13 +0800845/* For debugging */
846static void dump_psp_firmwares(amd_fw_entry *fw_table)
847{
848 amd_fw_entry *index;
849
850 printf("PSP firmware components:");
851 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
852 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800853 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800854 }
855}
856
857static void dump_bdt_firmwares(amd_bios_entry *fw_table)
858{
859 amd_bios_entry *index;
860
861 printf("BIOS Directory Table (BDT) components:");
862 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
863 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800864 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800865 }
866}
867
Zheng Bao990d1542021-09-17 13:24:54 +0800868static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800869 psp_directory_table *pspdir2, ish_directory_table *ish,
870 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800871{
872 uint32_t count;
873 uint32_t current_table_save;
874
875 current_table_save = ctx->current_table;
876 ctx->current_table = (char *)pspdir - ctx->rom;
877 count = pspdir->header.num_entries;
878 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
879 pspdir->entries[count].type = (uint8_t)ab;
880 pspdir->entries[count].subprog = 0;
881 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800882 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600883 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800884 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
885 ish->update_retry_count = 2;
886 ish->glitch_retry_count = 0;
887 ish->psp_id = get_psp_id(soc_id);
888 ish->checksum = fletcher32(&ish->boot_priority,
889 sizeof(ish_directory_table) - sizeof(uint32_t));
890 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600891 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800892 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600893 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800894 pspdir->entries[count].size = TABLE_ALIGNMENT;
895 } else {
896 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600897 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800898 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600899 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800900 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800901 sizeof(psp_directory_entry) +
902 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800903 }
Zheng Bao990d1542021-09-17 13:24:54 +0800904
905 count++;
906 pspdir->header.num_entries = count;
907 ctx->current_table = current_table_save;
908}
909
Marshall Dawson2794a862019-03-04 16:53:15 -0700910static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700911 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600912 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800913 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600914 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800915 uint32_t cookie,
916 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800917{
Richard Spiegel137484d2018-01-17 10:23:19 -0700918 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700919 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600920 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530921 uint32_t size;
922 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800923 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800924 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800925 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600926
927 /* This function can create a primary table, a secondary table, or a
928 * flattened table which contains all applicable types. These if-else
929 * statements infer what the caller intended. If a 2nd-level cookie
930 * is passed, clearly a 2nd-level table is intended. However, a
931 * 1st-level cookie may indicate level 1 or flattened. If the caller
932 * passes a pointer to a 2nd-level table, then assume not flat.
933 */
Zheng Baoba3af5e2021-11-04 18:56:47 +0800934 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800935 level = PSP_BOTH;
936 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600937 level = PSP_LVL2;
938 else if (pspdir2)
939 level = PSP_LVL1;
940 else
941 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -0700942
Zheng Bao990d1542021-09-17 13:24:54 +0800943 if (recovery_ab) {
944 if (cookie == PSPL2_COOKIE)
945 level = PSP_LVL2_AB;
946 else if (pspdir2)
947 level = PSP_LVL1_AB;
948 else
949 level = PSP_BOTH_AB;
950 }
Zheng Bao6fff2492021-11-15 19:53:21 +0800951 current_table_save = ctx->current_table;
952 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +0800953 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800954
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700955 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -0600956 if (!(fw_table[i].level & level))
957 continue;
958
Zheng Bao5164e4b2021-10-30 12:09:07 +0800959 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
960
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600961 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
962 if (!fw_table[i].other)
963 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +0800964 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600965 pspdir->entries[count].type = fw_table[i].type;
966 pspdir->entries[count].size = 4096; /* TODO: doc? */
967 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800968 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600969 pspdir->entries[count].subprog = fw_table[i].subprog;
970 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +0800971 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600972 count++;
973 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -0700974 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -0700975 pspdir->entries[count].subprog = fw_table[i].subprog;
976 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -0700977 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600978 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +0800979 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700980 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -0600981 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +0530982 if (fw_table[i].filename == NULL) {
983 if (fw_table[i].size == 0)
984 continue;
985 size = fw_table[i].size;
986 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200987 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +0530988 fprintf(stderr,
989 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800990 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530991 exit(1);
992 }
993 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +0800994 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530995 bytes = copy_blob(BUFF_CURRENT(*ctx),
996 fw_table[i].filename, BUFF_ROOM(*ctx));
997 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800998 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530999 exit(1);
1000 }
1001
Elyes Haouas7d67a192022-10-14 09:58:29 +02001002 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301003 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001004 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001005 }
1006
1007 pspdir->entries[count].type = fw_table[i].type;
1008 pspdir->entries[count].subprog = fw_table[i].subprog;
1009 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301010 pspdir->entries[count].size = size;
1011 pspdir->entries[count].addr = addr;
1012
Zheng Bao6fff2492021-11-15 19:53:21 +08001013 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001014 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001015
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001016 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001017 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001018 if (fw_table[i].addr_signed) {
1019 pspdir->entries[count].addr =
1020 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1021 pspdir->entries[count].address_mode =
1022 SET_ADDR_MODE_BY_TABLE(pspdir);
1023 bytes = fw_table[i].file_size;
1024 } else {
1025 bytes = copy_blob(BUFF_CURRENT(*ctx),
1026 fw_table[i].filename, BUFF_ROOM(*ctx));
1027 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001028 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001029 exit(1);
1030 }
1031 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1032 pspdir->entries[count].address_mode =
1033 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001034 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001035 }
1036
Marshall Dawson239286c2019-02-23 16:42:46 -07001037 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001038 pspdir->entries[count].subprog = fw_table[i].subprog;
1039 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001040 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001041 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001042
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001043 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001044 } else {
1045 /* This APU doesn't have this firmware. */
1046 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001047 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001048
Zheng Bao990d1542021-09-17 13:24:54 +08001049 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001050 if (cb_config->need_ish) { /* Need ISH */
1051 ish_a_dir = new_ish_dir(ctx);
1052 if (pspdir2_b != NULL)
1053 ish_b_dir = new_ish_dir(ctx);
1054 }
Zheng Bao990d1542021-09-17 13:24:54 +08001055 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001056 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001057 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001058 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001059 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001060 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001061 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001062 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001063 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001064
Zheng Bao990d1542021-09-17 13:24:54 +08001065 count = pspdir->header.num_entries;
1066 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001067 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001068 pspdir->entries[count].type = AMD_FW_L2_PTR;
1069 pspdir->entries[count].subprog = 0;
1070 pspdir->entries[count].rsvd = 0;
1071 pspdir->entries[count].size = sizeof(pspdir2->header)
1072 + pspdir2->header.num_entries
1073 * sizeof(psp_directory_entry);
1074
Zheng Bao6fff2492021-11-15 19:53:21 +08001075 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001076 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001077 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001078 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001079 count++;
1080 }
1081
Zheng Baobf29a0d2020-12-03 23:00:48 +08001082 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001083 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001084}
1085
Zheng Bao990d1542021-09-17 13:24:54 +08001086static void add_psp_firmware_entry(context *ctx,
1087 psp_directory_table *pspdir,
1088 void *table, amd_fw_type type, uint32_t size)
1089{
1090 uint32_t count = pspdir->header.num_entries;
1091 uint32_t index;
1092 uint32_t current_table_save;
1093
1094 current_table_save = ctx->current_table;
1095 ctx->current_table = (char *)pspdir - ctx->rom;
1096
1097 /* If there is an entry of "type", replace it. */
1098 for (index = 0; index < count; index++) {
1099 if (pspdir->entries[index].type == (uint8_t)type)
1100 break;
1101 }
1102
1103 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1104 pspdir->entries[index].type = (uint8_t)type;
1105 pspdir->entries[index].subprog = 0;
1106 pspdir->entries[index].rsvd = 0;
1107 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1108 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1109 pspdir->entries[index].size = size;
1110 if (index == count)
1111 count++;
1112
1113 pspdir->header.num_entries = count;
1114 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1115 count * sizeof(psp_directory_entry)
1116 + sizeof(pspdir->header.num_entries)
1117 + sizeof(pspdir->header.additional_info));
1118
1119 ctx->current_table = current_table_save;
1120}
1121
Zheng Baoba3af5e2021-11-04 18:56:47 +08001122static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001123{
1124 void *ptr;
1125
1126 /*
1127 * Force both onto boundary when multi. Primary table is after
1128 * updatable table, so alignment ensures primary can stay intact
1129 * if secondary is reprogrammed.
1130 */
1131 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001132 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001133 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001134 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001135 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001136 ((bios_directory_hdr *) ptr)->additional_info = 0;
1137 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1138 ctx->current_table = ctx->current;
Zheng Baoc26108f2023-02-17 11:01:07 +08001139 adjust_current_pointer(ctx,
1140 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1141 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001142 return ptr;
1143}
1144
1145static int locate_bdt2_bios(bios_directory_table *level2,
1146 uint64_t *source, uint32_t *size)
1147{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001148 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001149
1150 *source = 0;
1151 *size = 0;
1152 if (!level2)
1153 return 0;
1154
1155 for (i = 0 ; i < level2->header.num_entries ; i++) {
1156 if (level2->entries[i].type == AMD_BIOS_BIN) {
1157 *source = level2->entries[i].source;
1158 *size = level2->entries[i].size;
1159 return 1;
1160 }
1161 }
1162 return 0;
1163}
1164
1165static int have_bios_tables(amd_bios_entry *table)
1166{
1167 int i;
1168
1169 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1170 if (table[i].level & BDT_LVL1 && table[i].filename)
1171 return 1;
1172 }
1173 return 0;
1174}
1175
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001176static int find_bios_entry(amd_bios_type type)
1177{
1178 int i;
1179
1180 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1181 if (amd_bios_table[i].type == type)
1182 return i;
1183 }
1184 return -1;
1185}
1186
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001187static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1188 int inst, uint32_t size, uint64_t source)
1189{
1190 int i;
1191
1192 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1193 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1194 amd_bios_table[i].inst == inst)
1195 break;
1196 }
1197
1198 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1199 return;
1200
1201 biosdir->entries[idx].type = amd_bios_table[i].type;
1202 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1203 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1204 amd_bios_table[i].dest : (uint64_t)-1;
1205 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1206 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1207 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1208 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1209 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1210 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1211 biosdir->entries[idx].size = size;
1212 biosdir->entries[idx].source = source;
1213 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1214}
1215
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001216static void integrate_bios_firmwares(context *ctx,
1217 bios_directory_table *biosdir,
1218 bios_directory_table *biosdir2,
1219 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001220 uint32_t cookie,
1221 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001222{
1223 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001224 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001225 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001226 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001227 uint32_t size;
1228 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001229
1230 /* This function can create a primary table, a secondary table, or a
1231 * flattened table which contains all applicable types. These if-else
1232 * statements infer what the caller intended. If a 2nd-level cookie
1233 * is passed, clearly a 2nd-level table is intended. However, a
1234 * 1st-level cookie may indicate level 1 or flattened. If the caller
1235 * passes a pointer to a 2nd-level table, then assume not flat.
1236 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001237 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001238 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001239 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001240 level = BDT_LVL2;
1241 else if (biosdir2)
1242 level = BDT_LVL1;
1243 else
1244 level = BDT_BOTH;
1245
Zheng Baoc26108f2023-02-17 11:01:07 +08001246 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001247
1248 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1249 if (!(fw_table[i].level & level))
1250 continue;
1251 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301252 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001253 fw_table[i].type != AMD_BIOS_APOB &&
1254 fw_table[i].type != AMD_BIOS_APOB_NV &&
1255 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001256 fw_table[i].type != AMD_BIOS_BIN &&
1257 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001258 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001259
1260 /* BIOS Directory items may have additional requirements */
1261
Ritul Guru9a321f32022-07-29 11:06:40 +05301262 /* SIG needs a size, else no choice but to skip */
1263 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1264 continue;
1265
Martin Roth48dd9fe2020-07-29 16:32:25 -06001266 /* Check APOB_NV requirements */
1267 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1268 if (!fw_table[i].size && !fw_table[i].src)
1269 continue; /* APOB_NV not used */
1270 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001271 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001272 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001273 exit(1);
1274 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001275 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001276 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001277 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1278 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001279 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001280
1281 /* APOB_DATA needs destination */
1282 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001283 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001284 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001285 exit(1);
1286 }
1287
1288 /* BIOS binary must have destination and uncompressed size. If
1289 * no filename given, then user must provide a source address.
1290 */
1291 if (fw_table[i].type == AMD_BIOS_BIN) {
1292 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001293 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001294 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001295 exit(1);
1296 }
1297 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001298 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001299 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001300 exit(1);
1301 }
1302 }
1303
Martin Roth94554742020-04-14 14:59:36 -06001304 /* PSP_SHARED_MEM needs a destination and size */
1305 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1306 (!fw_table[i].dest || !fw_table[i].size))
1307 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001308 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001309
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001310 biosdir->entries[count].type = fw_table[i].type;
1311 biosdir->entries[count].region_type = fw_table[i].region_type;
1312 biosdir->entries[count].dest = fw_table[i].dest ?
1313 fw_table[i].dest : (uint64_t)-1;
1314 biosdir->entries[count].reset = fw_table[i].reset;
1315 biosdir->entries[count].copy = fw_table[i].copy;
1316 biosdir->entries[count].ro = fw_table[i].ro;
1317 biosdir->entries[count].compressed = fw_table[i].zlib;
1318 biosdir->entries[count].inst = fw_table[i].inst;
1319 biosdir->entries[count].subprog = fw_table[i].subpr;
1320
1321 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301322 case AMD_BIOS_SIG:
1323 /* Reserve size bytes within amdfw.rom */
1324 biosdir->entries[count].size = fw_table[i].size;
1325 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1326 biosdir->entries[count].address_mode =
1327 SET_ADDR_MODE_BY_TABLE(biosdir);
1328 memset(BUFF_CURRENT(*ctx), 0xff,
1329 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001330 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301331 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001332 case AMD_BIOS_APOB:
1333 biosdir->entries[count].size = fw_table[i].size;
1334 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001335 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001336 break;
1337 case AMD_BIOS_APOB_NV:
1338 if (fw_table[i].src) {
1339 /* If source is given, use that and its size */
1340 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001341 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001342 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001343 biosdir->entries[count].size = fw_table[i].size;
1344 } else {
1345 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001346 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001347 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001348 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001349 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001350 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001351 fw_table[i].size, ERASE_ALIGNMENT);
1352 memset(BUFF_CURRENT(*ctx), 0xff,
1353 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001354 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001355 }
1356 break;
1357 case AMD_BIOS_BIN:
1358 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001359 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1360 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001361 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001362 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001363 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001364 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001365 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001366
1367 /* level 2, or level 1 and no copy found in level 2 */
1368 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001369 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001370 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001371 biosdir->entries[count].dest = fw_table[i].dest;
1372 biosdir->entries[count].size = fw_table[i].size;
1373
1374 if (!fw_table[i].filename)
1375 break;
1376
1377 bytes = copy_blob(BUFF_CURRENT(*ctx),
1378 fw_table[i].filename, BUFF_ROOM(*ctx));
1379 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001380 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001381 exit(1);
1382 }
1383
Zheng Bao6fff2492021-11-15 19:53:21 +08001384 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001385 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001386 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001387 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001388
Zheng Baoc26108f2023-02-17 11:01:07 +08001389 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001390 break;
Martin Roth94554742020-04-14 14:59:36 -06001391 case AMD_BIOS_PSP_SHARED_MEM:
1392 biosdir->entries[count].dest = fw_table[i].dest;
1393 biosdir->entries[count].size = fw_table[i].size;
1394 break;
1395
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001396 default: /* everything else is copied from input */
1397 if (fw_table[i].type == AMD_BIOS_APCB ||
1398 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001399 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001400 bytes = copy_blob(BUFF_CURRENT(*ctx),
1401 fw_table[i].filename, BUFF_ROOM(*ctx));
1402 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001403 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001404 exit(1);
1405 }
1406
1407 biosdir->entries[count].size = (uint32_t)bytes;
1408 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001409 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001410
Zheng Baoc26108f2023-02-17 11:01:07 +08001411 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001412 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1413 size = biosdir->entries[count].size;
1414 source = biosdir->entries[count].source;
1415 count++;
1416 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1417 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001418 break;
1419 }
1420
1421 count++;
1422 }
1423
1424 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001425 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001426 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001427 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001428 biosdir->entries[count].size =
1429 + MAX_BIOS_ENTRIES
1430 * sizeof(bios_directory_entry);
1431 biosdir->entries[count].source =
1432 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001433 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001434 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001435 biosdir->entries[count].subprog = 0;
1436 biosdir->entries[count].inst = 0;
1437 biosdir->entries[count].copy = 0;
1438 biosdir->entries[count].compressed = 0;
1439 biosdir->entries[count].dest = -1;
1440 biosdir->entries[count].reset = 0;
1441 biosdir->entries[count].ro = 0;
1442 count++;
1443 }
1444
Zheng Baobf29a0d2020-12-03 23:00:48 +08001445 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001446}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001447
1448enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001449 AMDFW_OPT_CONFIG = 'c',
1450 AMDFW_OPT_DEBUG = 'd',
1451 AMDFW_OPT_HELP = 'h',
Zheng Bao806892a2021-04-27 17:21:54 +08001452
1453 AMDFW_OPT_XHCI = 128,
1454 AMDFW_OPT_IMC,
1455 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001456 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001457 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001458 AMDFW_OPT_USE_COMBO,
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001459 AMDFW_OPT_COMBO1_CONFIG,
Zheng Bao806892a2021-04-27 17:21:54 +08001460 AMDFW_OPT_MULTILEVEL,
1461 AMDFW_OPT_NVRAM,
1462
1463 AMDFW_OPT_FUSE,
1464 AMDFW_OPT_UNLOCK,
1465 AMDFW_OPT_WHITELIST,
1466 AMDFW_OPT_USE_PSPSECUREOS,
1467 AMDFW_OPT_LOAD_MP2FW,
1468 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001469 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001470 AMDFW_OPT_VERSTAGE,
1471 AMDFW_OPT_VERSTAGE_SIG,
1472
1473 AMDFW_OPT_INSTANCE,
1474 AMDFW_OPT_APCB,
1475 AMDFW_OPT_APOBBASE,
1476 AMDFW_OPT_BIOSBIN,
1477 AMDFW_OPT_BIOSBIN_SOURCE,
1478 AMDFW_OPT_BIOSBIN_DEST,
1479 AMDFW_OPT_BIOS_UNCOMP_SIZE,
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001480 AMDFW_OPT_BIOSBIN_UNCOMP,
Zheng Bao806892a2021-04-27 17:21:54 +08001481 AMDFW_OPT_UCODE,
1482 AMDFW_OPT_APOB_NVBASE,
1483 AMDFW_OPT_APOB_NVSIZE,
1484
1485 AMDFW_OPT_OUTPUT,
1486 AMDFW_OPT_FLASHSIZE,
1487 AMDFW_OPT_LOCATION,
1488 AMDFW_OPT_ANYWHERE,
1489 AMDFW_OPT_SHAREDMEM,
1490 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001491 AMDFW_OPT_SIGNED_OUTPUT,
1492 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001493 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001494 /* begin after ASCII characters */
1495 LONGOPT_SPI_READ_MODE = 256,
1496 LONGOPT_SPI_SPEED = 257,
1497 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301498 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301499 LONGOPT_NVRAM_BASE = 260,
1500 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001501};
1502
Zheng Bao806892a2021-04-27 17:21:54 +08001503static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
Zheng Bao994ff522023-03-09 11:43:55 +08001504 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
Zheng Bao806892a2021-04-27 17:21:54 +08001505};
Marc Jones90099b62016-09-20 21:05:45 -06001506
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001507static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001508 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1509 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1510 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001511 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001512 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001513 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001514 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001515 {"combo-config1", required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001516 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1517 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301518 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1519 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001520 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1521 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1522 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1523 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1524 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1525 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001526 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001527 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1528 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001529 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001530 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1531 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1532 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1533 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1534 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1535 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1536 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001537 {"bios-bin-uncomp", no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
Ritul Guru9a321f32022-07-29 11:06:40 +05301538 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001539 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1540 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1541 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001542 /* Embedded Firmware Structure items*/
1543 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1544 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1545 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001546 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001547 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001548 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1549 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1550 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1551 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1552 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1553 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001554
Kangheui Won3c164e12021-12-03 20:25:05 +11001555 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1556 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1557
Zheng Bao806892a2021-04-27 17:21:54 +08001558 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1559 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1560 {"help", no_argument, 0, AMDFW_OPT_HELP },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001561 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001562};
1563
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001564void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001565{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001566 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001567
1568 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1569 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1570 continue;
1571
1572 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1573 return;
1574 }
1575}
1576
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001577static void register_fw_token_unlock(void)
1578{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001579 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001580
1581 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1582 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1583 continue;
1584
1585 amd_psp_fw_table[i].other = 1;
1586 return;
1587 }
1588}
1589
Marshall Dawsondbae6322019-03-04 10:31:03 -07001590static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001591{
Martin Roth8806f7f2016-11-08 10:44:18 -07001592 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001593
Martin Rothcd15bc82016-11-08 11:34:02 -07001594 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001595 if (amd_fw_table[i].type == type) {
1596 amd_fw_table[i].filename = filename;
1597 return;
1598 }
1599 }
1600
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001601 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001602 if (amd_psp_fw_table[i].type != type)
1603 continue;
1604
1605 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001606 amd_psp_fw_table[i].filename = filename;
1607 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001608 }
1609 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001610}
1611
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001612static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1613{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001614 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001615
1616 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1617 if (amd_bios_table[i].type == type
1618 && amd_bios_table[i].inst == ins
1619 && amd_bios_table[i].subpr == sub) {
1620 amd_bios_table[i].filename = name;
1621 return;
1622 }
1623 }
1624}
1625
Ritul Gurua2cb3402022-08-29 00:51:08 +05301626static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1627 char *dst_str, char *size_str)
1628{
1629 unsigned int i;
1630
1631 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1632 if (amd_psp_fw_table[i].type != type)
1633 continue;
1634
1635 if (amd_psp_fw_table[i].subprog == sub) {
1636 if (dst_str)
1637 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1638 if (size_str)
1639 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1640 return;
1641 }
1642 }
1643}
1644
1645static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001646 char *dst_str, char *size_str)
1647{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001648 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001649 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1650 if (amd_bios_table[i].type != type)
1651 continue;
1652
1653 if (src_str)
1654 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1655 if (dst_str)
1656 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1657 if (size_str)
1658 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1659
1660 return;
1661 }
1662}
1663
Zheng Baoc3007f32022-04-03 12:53:51 +08001664static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1665 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1666 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001667{
1668 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001669 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001670 return 1;
1671 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001672
1673 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1674 * Leave as 0xffffffff for first gen */
1675 if (cb_config->second_gen) {
1676 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1677 amd_romsig->efs_gen.reserved = 0;
1678 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001679 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1680 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001681 }
1682
1683 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001684 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001685 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001686 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1687 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1688 break;
1689 case PLATFORM_RAVEN:
1690 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001691 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1692 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1693 switch (efs_spi_micron_flag) {
1694 case 0:
1695 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1696 break;
1697 case 1:
1698 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1699 break;
1700 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001701 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001702 return 1;
1703 }
1704 break;
1705 case PLATFORM_RENOIR:
1706 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001707 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001708 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001709 case PLATFORM_PHOENIX:
1710 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001711 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1712 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1713 switch (efs_spi_micron_flag) {
1714 case 0:
1715 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1716 break;
1717 case 1:
1718 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1719 break;
1720 case 2:
1721 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1722 break;
1723 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001724 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001725 return 1;
1726 }
1727 break;
1728 case PLATFORM_UNKNOWN:
1729 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001730 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001731 return 1;
1732 }
1733 return 0;
1734}
1735
Zheng Bao69ea83c2023-01-22 21:08:18 +08001736static ssize_t write_body(char *output, void *body_offset, ssize_t body_size, context *ctx)
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001737{
Zheng Bao69ea83c2023-01-22 21:08:18 +08001738 char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001739 int ret;
1740 int fd;
1741 ssize_t bytes = -1;
1742
1743 /* Create a tmp file and rename it at the end so that make does not get confused
1744 if amdfwtool is killed for some unexpected reasons. */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001745 ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
1746 output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001747 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001748 fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001749 strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001750 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001751 exit(1);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001752 } else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
1753 fprintf(stderr, "BODY File name %d > %zu\n", ret, sizeof(body_tmp_name));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001754 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001755 exit(1);
1756 }
1757
Zheng Bao69ea83c2023-01-22 21:08:18 +08001758 fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001759 if (fd < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001760 fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001761 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001762 exit(1);
1763 }
1764
Zheng Bao69ea83c2023-01-22 21:08:18 +08001765 bytes = write_from_buf_to_file(fd, body_offset, body_size);
1766 if (bytes != body_size) {
1767 fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001768 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001769 exit(1);
1770 }
1771 close(fd);
1772
1773 /* Rename the tmp file */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001774 ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001775 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001776 fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001777 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001778 exit(1);
1779 }
1780
Zheng Bao69ea83c2023-01-22 21:08:18 +08001781 if (rename(body_tmp_name, body_name)) {
1782 fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001783 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001784 exit(1);
1785 }
1786
1787 return bytes;
1788}
1789
Zheng Bao994ff522023-03-09 11:43:55 +08001790void open_process_config(char *config, amd_cb_config *cb_config, int debug)
Zheng Bao39cae562023-03-07 18:37:43 +08001791{
1792 FILE *config_handle;
1793
1794 if (config) {
1795 config_handle = fopen(config, "r");
1796 if (config_handle == NULL) {
1797 fprintf(stderr, "Can not open file %s for reading: %s\n",
1798 config, strerror(errno));
1799 exit(1);
1800 }
Zheng Bao994ff522023-03-09 11:43:55 +08001801 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001802 fprintf(stderr, "Configuration file %s parsing error\n",
1803 config);
1804 fclose(config_handle);
1805 exit(1);
1806 }
1807 fclose(config_handle);
1808 }
1809
1810 /* For debug. */
1811 if (debug) {
1812 dump_psp_firmwares(amd_psp_fw_table);
1813 dump_bdt_firmwares(amd_bios_table);
1814 }
1815}
1816
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001817static bool is_initial_alignment_required(enum platform soc_id)
1818{
1819 switch (soc_id) {
1820 case PLATFORM_MENDOCINO:
1821 case PLATFORM_PHOENIX:
1822 case PLATFORM_GLINDA:
1823 return false;
1824 default:
1825 return true;
1826 }
1827}
1828
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001829int main(int argc, char **argv)
1830{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001831 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001832 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001833 char *tmp;
Marshall Dawson239286c2019-02-23 16:42:46 -07001834 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001835 psp_directory_table *pspdir = NULL;
1836 psp_directory_table *pspdir2 = NULL;
1837 psp_directory_table *pspdir2_b = NULL;
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001838 psp_combo_directory *psp_combo_dir = NULL, *bhd_combo_dir = NULL;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001839 char *combo_config[MAX_COMBO_ENTRIES] = { 0 };
1840 int combo_index = 0;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001841 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001842 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001843 char *output = NULL, *config = NULL;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001844 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001845 /* Values cleared after each firmware or parameter, regardless if N/A */
1846 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08001847 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001848 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001849 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001850 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07001851 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001852 uint8_t efs_spi_readmode = 0xff;
1853 uint8_t efs_spi_speed = 0xff;
1854 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11001855 const char *signed_output_file = NULL;
1856 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001857
Fred Reitbergerf36b0132022-06-29 13:54:57 -04001858 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08001859 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001860
Zheng Baoc26108f2023-02-17 11:01:07 +08001861 ctx.current_pointer_saved = 0xFFFFFFFF;
1862
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001863 while (1) {
1864 int optindex = 0;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001865 int bios_tbl_index = -1;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001866
1867 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1868
1869 if (c == -1)
1870 break;
1871
1872 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001873 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001874 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001875 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001876 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001877 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001878 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001879 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001880 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001881 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001882 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001883 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001884 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001885 case AMDFW_OPT_RECOVERY_AB:
1886 cb_config.recovery_ab = true;
1887 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001888 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1889 cb_config.recovery_ab = true;
1890 cb_config.recovery_ab_single_copy = true;
1891 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001892 case AMDFW_OPT_USE_COMBO:
1893 cb_config.use_combo = true;
1894 break;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001895 case AMDFW_OPT_COMBO1_CONFIG:
1896 cb_config.use_combo = true;
Zheng Bao73917222023-03-15 16:14:03 +08001897 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001898 combo_config[1] = optarg;
1899 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001900 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001901 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001902 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001903 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001904 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001905 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001906 sub = instance = 0;
1907 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001908 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001909 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001910 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001911 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001912 instance = strtoul(optarg, &tmp, 16);
1913 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001914 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001915 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001916 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001917 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001918 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001919 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001920 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001921 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001922 register_fw_fuse(optarg);
1923 fuse_defined = 1;
1924 sub = 0;
1925 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001926 case AMDFW_OPT_APCB:
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001927 if ((instance & 0xF0) == 0) {
Zheng Bao5caca942020-12-04 16:39:38 +08001928 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001929 } else {
Zheng Bao5caca942020-12-04 16:39:38 +08001930 register_bdt_data(AMD_BIOS_APCB_BK, sub,
1931 instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001932 cb_config.have_apcb_bk = 1;
1933 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001934 sub = instance = 0;
1935 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001936 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001937 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301938 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001939 sub = instance = 0;
1940 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001941 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001942 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301943 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001944 sub = instance = 0;
1945 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001946 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001947 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301948 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001949 sub = instance = 0;
1950 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001951 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001952 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
1953 sub = instance = 0;
1954 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001955 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001956 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301957 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001958 sub = instance = 0;
1959 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001960 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001961 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301962 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001963 sub = instance = 0;
1964 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001965 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001966 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301967 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001968 sub = instance = 0;
1969 break;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001970 case AMDFW_OPT_BIOSBIN_UNCOMP:
1971 bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
1972 if (bios_tbl_index != -1)
1973 amd_bios_table[bios_tbl_index].zlib = 0;
1974 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05301975 case LONGOPT_BIOS_SIG:
1976 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301977 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05301978 sub = instance = 0;
1979 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001980 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001981 register_bdt_data(AMD_BIOS_UCODE, sub,
1982 instance, optarg);
1983 sub = instance = 0;
1984 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001985 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001986 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001987 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001988 case AMDFW_OPT_SPL_TABLE:
1989 register_fw_filename(AMD_FW_SPL, sub, optarg);
1990 sub = instance = 0;
1991 cb_config.have_mb_spl = true;
1992 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001993 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001994 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
1995 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08001996 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001997 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001998 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06001999 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2000 sub = instance = 0;
2001 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002002 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002003 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2004 sub = instance = 0;
2005 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002006 case AMDFW_OPT_SIGNED_OUTPUT:
2007 signed_output_file = optarg;
2008 sub = instance = 0;
2009 break;
2010 case AMDFW_OPT_SIGNED_ADDR:
2011 signed_start_addr = strtoull(optarg, NULL, 10);
2012 sub = instance = 0;
2013 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002014 case LONGOPT_SPI_READ_MODE:
2015 efs_spi_readmode = strtoull(optarg, NULL, 16);
2016 sub = instance = 0;
2017 break;
2018 case LONGOPT_SPI_SPEED:
2019 efs_spi_speed = strtoull(optarg, NULL, 16);
2020 sub = instance = 0;
2021 break;
2022 case LONGOPT_SPI_MICRON_FLAG:
2023 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2024 sub = instance = 0;
2025 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002026 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002027 output = optarg;
2028 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002029 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002030 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002031 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002032 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002033 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002034 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002035 }
2036 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002037 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002038 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002039 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002040 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002041 " incorrectly (%s)\n\n", optarg);
2042 retval = 1;
2043 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002044 if (body_location == 0)
2045 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002046 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002047 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002048 any_location = 1;
2049 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002050 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002051 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302052 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002053 sub = instance = 0;
2054 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002055 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002056 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302057 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002058 sub = instance = 0;
2059 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302060 case LONGOPT_NVRAM_BASE:
2061 /* PSP NV base */
2062 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2063 sub = instance = 0;
2064 break;
2065 case LONGOPT_NVRAM_SIZE:
2066 /* PSP NV size */
2067 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2068 sub = instance = 0;
2069 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002070 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002071 config = optarg;
2072 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002073 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002074 debug = 1;
2075 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002076 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002077 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002078 return 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002079 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002080 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002081 if (*tmp != '\0') {
2082 fprintf(stderr, "Error: Body Location specified"
2083 " incorrectly (%s)\n\n", optarg);
2084 retval = 1;
2085 }
2086 break;
2087
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002088 default:
2089 break;
2090 }
2091 }
2092
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002093 if (cb_config.use_combo) {
2094 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
2095 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
2096 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
2097 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
2098 }
2099
Zheng Bao994ff522023-03-09 11:43:55 +08002100 open_process_config(config, &cb_config, debug);
Zheng Bao9e908072020-10-28 11:39:13 +08002101
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002102 if (!fuse_defined)
2103 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2104
Zheng Bao994ff522023-03-09 11:43:55 +08002105 if (!output) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002106 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002107 retval = 1;
2108 }
2109
Zheng Baoa7731cc2023-03-11 09:27:53 +08002110 if (ctx.rom_size % 1024 != 0) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002111 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002112 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002113 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002114 }
2115
Zheng Baoa7731cc2023-03-11 09:27:53 +08002116 if (ctx.rom_size < MIN_ROM_KB * 1024) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002117 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002118 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002119 retval = 1;
2120 }
2121
2122 if (retval) {
2123 usage();
2124 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002125 }
2126
Marshall Dawson2794a862019-03-04 16:53:15 -07002127 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002128
Marshall Dawson2794a862019-03-04 16:53:15 -07002129 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Zheng Bao9770df12023-02-14 13:23:35 +08002130
2131 if (efs_location & 0xFF000000)
2132 efs_location = efs_location - rom_base_address;
2133 if (body_location & 0xFF000000)
2134 body_location = body_location - rom_base_address;
2135
2136 if (efs_location && efs_location > ctx.rom_size) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002137 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2138 return 1;
2139 }
Zheng Bao9770df12023-02-14 13:23:35 +08002140 if (body_location && body_location > ctx.rom_size) {
2141 fprintf(stderr, "Error: Body location outside of ROM.\n\n");
2142 return 1;
2143 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002144
Zheng Bao99945dc2023-01-02 10:55:56 +08002145 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002146 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2147 return 1;
2148 }
2149
Zheng Bao99945dc2023-01-02 10:55:56 +08002150 if (body_location != efs_location &&
2151 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002152 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2153 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002154 return 1;
2155 }
2156
Martin Roth37305e72020-04-07 14:16:39 -06002157 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002158 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002159 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002160 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002161 return 1;
2162 }
2163 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002164 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002165 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002166 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002167 case 0xFA0000:
2168 case 0xF20000:
2169 case 0xE20000:
2170 case 0xC20000:
2171 case 0x820000:
2172 case 0x020000:
2173 break;
2174 case 0x7A0000:
2175 case 0x720000:
2176 case 0x620000:
2177 case 0x420000:
2178 /* Special cases for 8M. */
2179 if (ctx.rom_size != 0x800000) {
2180 fprintf(stderr, "Error: Invalid Directory location.\n");
2181 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2182 return 1;
2183 }
2184 break;
2185 case 0x3A0000:
2186 case 0x320000:
2187 case 0x220000:
2188 /* Special cases for 4M. */
2189 if (ctx.rom_size != 0x400000) {
2190 fprintf(stderr, "Error: Invalid Directory location.\n");
2191 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2192 return 1;
2193 }
Martin Roth37305e72020-04-07 14:16:39 -06002194 break;
2195 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002196 fprintf(stderr, "Error: Invalid Directory location.\n");
2197 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2198 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002199 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2200 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002201 return 1;
2202 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002203 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002204 ctx.rom = malloc(ctx.rom_size);
2205 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002206 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002207 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002208 }
2209 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002210
Zheng Bao6095cd12023-02-21 10:52:47 +08002211 romsig_offset = efs_location ? efs_location : AMD_ROMSIG_OFFSET;
2212 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06002213
Marshall Dawson2794a862019-03-04 16:53:15 -07002214 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002215 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2216 amd_romsig->imc_entry = 0;
2217 amd_romsig->gec_entry = 0;
2218 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002219
Zheng Bao4bf6f492023-01-25 22:37:29 +08002220 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2221 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2222 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002223 if (retval) {
2224 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2225 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002226 }
2227 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002228 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002229 }
2230
Felix Held21a8e382022-03-29 23:10:45 +02002231 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002232 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002233 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002234 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002235 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002236 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002237 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2238 efs_location);
2239 if (body_location != efs_location)
2240 printf(" with a split body at: 0x%08x\n", body_location);
2241 else
2242 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002243
Zheng Bao6095cd12023-02-21 10:52:47 +08002244 if (efs_location != body_location)
2245 set_current_pointer(&ctx, body_location);
2246 else
2247 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
2248
Marshall Dawson2794a862019-03-04 16:53:15 -07002249 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002250
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07002251 if (is_initial_alignment_required(cb_config.soc_id)) {
2252 /* TODO: Check for older platforms. */
2253 adjust_current_pointer(&ctx, 0, 0x10000U);
2254 }
Zheng Bao6fff2492021-11-15 19:53:21 +08002255 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002256
Kangheui Won3c164e12021-12-03 20:25:05 +11002257 /* If the tool is invoked with command-line options to keep the signed PSP
2258 binaries separate, process the signed binaries first. */
2259 if (signed_output_file && signed_start_addr)
2260 process_signed_psp_firmwares(signed_output_file,
2261 amd_psp_fw_table,
2262 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002263 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002264
Zheng Baob2ae6a52022-08-18 15:45:27 +08002265 if (cb_config.use_combo) {
2266 psp_combo_dir = new_combo_dir(&ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002267
2268 adjust_current_pointer(&ctx, 0, 0x1000U);
2269
2270 bhd_combo_dir = new_combo_dir(&ctx);
Zheng Baob2ae6a52022-08-18 15:45:27 +08002271 }
2272
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002273 combo_index = 0;
2274 if (config)
2275 combo_config[0] = config;
2276
Zheng Bao4b6aa192023-03-09 11:28:47 +08002277 do {
Zheng Bao3e7008d2023-03-15 16:15:13 +08002278 if (cb_config.use_combo && debug)
2279 printf("Processing %dth combo entry\n", combo_index);
2280
Zheng Bao4b6aa192023-03-09 11:28:47 +08002281 /* for non-combo image, combo_config[0] == config, and
2282 * it already is processed. Actually "combo_index >
2283 * 0" is enough. Put both of them here to make sure
2284 * and make it clear this will not affect non-combo
2285 * case.
2286 */
2287 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002288 /* Restore the table as clean data. */
2289 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
2290 sizeof(amd_psp_fw_table));
2291 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
2292 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08002293 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08002294 open_process_config(combo_config[combo_index], &cb_config,
Zheng Bao994ff522023-03-09 11:43:55 +08002295 debug);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002296
Zheng Bao4b6aa192023-03-09 11:28:47 +08002297 /* In most cases, the address modes are same. */
2298 if (cb_config.need_ish)
2299 ctx.address_mode = AMD_ADDR_REL_TAB;
2300 else if (cb_config.second_gen)
2301 ctx.address_mode = AMD_ADDR_REL_BIOS;
2302 else
2303 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao990d1542021-09-17 13:24:54 +08002304 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002305
Zheng Bao481661e2021-08-20 14:47:46 +08002306 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002307 /* Do 2nd PSP directory followed by 1st */
2308 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2309 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
2310 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
2311 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2312 /* Create a copy of PSP Directory 2 in the backup slot B.
2313 Related biosdir2_b copy will be created later. */
2314 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2315 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
2316 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002317 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002318 /*
2319 * Either the platform is using only
2320 * one slot or B is same as above
2321 * directories for A. Skip creating
2322 * pspdir2_b here to save flash space.
2323 * Related biosdir2_b will be skipped
2324 * automatically.
2325 */
2326 pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08002327 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002328 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2329 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
2330 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002331 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002332 /* flat: PSP 1 cookie and no pointer to 2nd table */
2333 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2334 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
2335 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002336 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002337
Zheng Bao4b6aa192023-03-09 11:28:47 +08002338 if (!cb_config.use_combo) {
2339 fill_psp_directory_to_efs(amd_romsig, pspdir, &ctx, &cb_config);
2340 } else {
2341 fill_psp_directory_to_efs(amd_romsig, psp_combo_dir, &ctx, &cb_config);
2342 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2343 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2344 psp_combo_dir->entries[combo_index].id_sel = 0;
2345 psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
2346 psp_combo_dir->entries[combo_index].lvl2_addr =
2347 BUFF_TO_RUN_MODE(ctx, pspdir, AMD_ADDR_REL_BIOS);
2348
2349 fill_dir_header(psp_combo_dir, combo_index + 1, PSP2_COOKIE, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002350 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002351
2352 if (have_bios_tables(amd_bios_table)) {
2353 bios_directory_table *biosdir = NULL;
2354 if (cb_config.multi_level) {
2355 /* Do 2nd level BIOS directory followed by 1st */
2356 bios_directory_table *biosdir2 = NULL;
2357 bios_directory_table *biosdir2_b = NULL;
2358
2359 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2360
2361 integrate_bios_firmwares(&ctx, biosdir2, NULL,
2362 amd_bios_table, BHDL2_COOKIE, &cb_config);
2363 if (cb_config.recovery_ab) {
2364 if (pspdir2_b != NULL) {
2365 biosdir2_b = new_bios_dir(&ctx,
2366 cb_config.multi_level);
2367 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
2368 amd_bios_table, BHDL2_COOKIE,
2369 &cb_config);
2370 }
2371 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2372 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2373 if (pspdir2_b != NULL)
2374 add_psp_firmware_entry(&ctx, pspdir2_b,
2375 biosdir2_b, AMD_FW_BIOS_TABLE,
2376 TABLE_ALIGNMENT);
2377 } else {
2378 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2379 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
2380 amd_bios_table, BHD_COOKIE, &cb_config);
2381 }
2382 } else {
2383 /* flat: BHD1 cookie and no pointer to 2nd table */
2384 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2385 integrate_bios_firmwares(&ctx, biosdir, NULL,
2386 amd_bios_table, BHD_COOKIE, &cb_config);
2387 }
2388 if (!cb_config.use_combo) {
2389 fill_bios_directory_to_efs(amd_romsig, biosdir,
2390 &ctx, &cb_config);
2391 } else {
2392 fill_bios_directory_to_efs(amd_romsig, bhd_combo_dir,
2393 &ctx, &cb_config);
2394 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2395 bhd_combo_dir->entries[combo_index].id_sel = 0;
2396 bhd_combo_dir->entries[combo_index].id =
2397 get_psp_id(cb_config.soc_id);
2398 bhd_combo_dir->entries[combo_index].lvl2_addr =
2399 BUFF_TO_RUN_MODE(ctx, biosdir, AMD_ADDR_REL_BIOS);
2400
2401 fill_dir_header(bhd_combo_dir, combo_index + 1,
2402 BHD2_COOKIE, &ctx);
2403 }
2404 }
Zheng Bao17551ae2023-03-11 10:29:56 +08002405 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
2406 combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002407
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002408 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002409 if (targetfd >= 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08002410 uint32_t offset = efs_location;
2411 uint32_t bytes = efs_location == body_location ?
2412 ctx.current - offset : sizeof(*amd_romsig);
2413 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002414
Zheng Baoc25d5932023-03-22 12:51:47 +08002415 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08002416 if (bytes != ret_bytes) {
Zheng Bao47396912020-09-29 17:33:17 +08002417 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2418 retval = 1;
2419 }
Martin Roth31d95a22016-11-08 11:22:12 -07002420 close(targetfd);
2421 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002422 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002423 retval = 1;
2424 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002425
Zheng Bao99945dc2023-01-02 10:55:56 +08002426 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002427 ssize_t bytes;
2428
Zheng Bao69ea83c2023-01-22 21:08:18 +08002429 bytes = write_body(output, BUFF_OFFSET(ctx, body_location),
2430 ctx.current - body_location, &ctx);
2431 if (bytes != ctx.current - body_location) {
2432 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002433 retval = 1;
2434 }
2435 }
2436
Zheng Bao7c5ad882023-02-19 13:02:52 +08002437 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07002438 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002439}