blob: fc7a531f34fed0973dfac5591df4f794b0f0834c [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
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000100static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry);
101
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800102/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700103 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
104 * can support an optional "combo" implementation. If the PSP sees the
105 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
106 * tables. Using this, support for multiple product generations may be
107 * built into one image. If the PSP$ cookie is found, the table is a
108 * normal directory table.
109 *
110 * Modern generations supporting the combo directories require the
111 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
Zheng Baoc91867a2023-02-26 12:31:31 +0800112 * regardless of the type of directory used. The --use-combo
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700113 * argument enforces this placement.
114 *
115 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800116 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800117
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800118/*
119 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
120 * The checksum field of the passed PDU does not need to be reset to zero.
121 *
122 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
123 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
124 * alternative to cyclical redundancy checks because it provides error-
125 * detection properties similar to cyclical redundancy checks but at the
126 * cost of a simple summation technique. Its characteristics were first
127 * published in IEEE Transactions on Communications in January 1982. One
128 * version has been adopted by ISO for use in the class-4 transport layer
129 * of the network protocol.
130 *
131 * This program expects:
132 * stdin: The input file to compute a checksum for. The input file
133 * not be longer than 256 bytes.
134 * stdout: Copied from the input file with the Fletcher's Checksum
135 * inserted 8 bytes after the beginning of the file.
136 * stderr: Used to print out error messages.
137 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700138static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800139{
140 uint32_t c0;
141 uint32_t c1;
142 uint32_t checksum;
143 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700144 const uint16_t *pptr = data;
145
146 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800147
148 c0 = 0xFFFF;
149 c1 = 0xFFFF;
150
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600151 while (length) {
152 index = length >= 359 ? 359 : length;
153 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800154 do {
155 c0 += *(pptr++);
156 c1 += c0;
157 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600158 c0 = (c0 & 0xFFFF) + (c0 >> 16);
159 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800160 }
161
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700162 /* Sums[0,1] mod 64K + overflow */
163 c0 = (c0 & 0xFFFF) + (c0 >> 16);
164 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800165 checksum = (c1 << 16) | c0;
166
167 return checksum;
168}
169
Martin Roth8806f7f2016-11-08 10:44:18 -0700170static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800171{
Martin Roth0e940622016-11-08 10:37:53 -0700172 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800173 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
174 printf("--xhci <FILE> Add XHCI blob\n");
175 printf("--imc <FILE> Add IMC blob\n");
176 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700177
178 printf("\nPSP options:\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800179 printf("--use-combo Use the COMBO layout\n");
Zheng Baoe3ebc4f2023-03-23 10:52:59 +0800180 printf("--combo-config1 <config file> Config for 1st combo entry\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800181 printf("--multilevel Generate primary and secondary tables\n");
182 printf("--nvram <FILE> Add nvram binary\n");
183 printf("--soft-fuse Set soft fuse\n");
184 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530185 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
186 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800187 printf("--whitelist Set if there is a whitelist\n");
188 printf("--use-pspsecureos Set if psp secure OS is needed\n");
189 printf("--load-mp2-fw Set if load MP2 firmware\n");
190 printf("--load-s0i3 Set if load s0i3 firmware\n");
191 printf("--verstage <FILE> Add verstage\n");
192 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800193 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600194 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800195 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800196 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800197 printf("--apcb <FILE> Add AGESA PSP customization block\n");
198 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
199 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
200 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
201 printf("--ucode <FILE> Add microcode patch\n");
202 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
203 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
204 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
205 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
206 printf("--output <filename> output filename\n");
207 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600208 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700209 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600210 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800211 printf("--location Location of Directory\n");
212 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
213 printf("--sharedmem Location of PSP/FW shared memory\n");
214 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800215 printf(" area\n");
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000216 printf("--output-manifest <FILE> Writes a manifest with the blobs versions\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500217 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
218 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
219 printf(" 0x0 66.66Mhz\n");
220 printf(" 0x1 33.33MHz\n");
221 printf(" 0x2 22.22MHz\n");
222 printf(" 0x3 16.66MHz\n");
223 printf(" 0x4 100MHz\n");
224 printf(" 0x5 800KHz\n");
225 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
226 printf(" 0x0 Normal Read (up to 33M)\n");
227 printf(" 0x1 Reserved\n");
228 printf(" 0x2 Dual IO (1-1-2)\n");
229 printf(" 0x3 Quad IO (1-1-4)\n");
230 printf(" 0x4 Dual IO (1-2-2)\n");
231 printf(" 0x5 Quad IO (1-4-4)\n");
232 printf(" 0x6 Normal Read (up to 66M)\n");
233 printf(" 0x7 Fast Read\n");
234 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
235 printf(" 0x0 Micron parts are not used\n");
236 printf(" 0x1 Micron parts are always used\n");
237 printf(" 0x2 Micron parts optional, this option is only\n");
238 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800239 printf("\nGeneral options:\n");
240 printf("-c|--config <config file> Config file\n");
241 printf("-d|--debug Print debug message\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800242 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800243}
244
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800245amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100246 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000247 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000248 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800249 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200250 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800251 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200252 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000253 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB,
254 .generate_manifest = true },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200255 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800256 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100257 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
258 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200259 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000260 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800261 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
262 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000263 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200264 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
265 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800266 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
267 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
268 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
269 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000270 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao9bb62cb2023-03-07 19:48:11 +0800271 { .type = AMD_HW_IPCFG, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
272 { .type = AMD_HW_IPCFG, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100273 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800274 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
275 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800276 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200277 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800278 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200279 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
280 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800281 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
282 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200283 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
284 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
285 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800286 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000287 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB,
288 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800289 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
290 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
291 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
292 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
293 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
294 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
295 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200296 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
297 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600298 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200299 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200300 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200301 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
302 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
303 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
305 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600306 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
307 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200308 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000309 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200310 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
311 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
312 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
313 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Nikolai Vyssotskibfc9ca72023-03-07 15:09:09 -0600314 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800315 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200316 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000317 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB,
318 .generate_manifest = true },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800319 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200321 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200322 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200323 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
324 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800325 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
326 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
327 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
328 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
329 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
330 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
331 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
332 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
333 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
334 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
335 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
336 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
337 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
338 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500339 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
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_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800344 { .type = AMD_FW_XHCI },
345 { .type = AMD_FW_IMC },
346 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800347 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800348};
349
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800350amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800351 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530352 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600353 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
355 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
356 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
357 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700358 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
361 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
362 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700369 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700374 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
377 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
378 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
379 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
380 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
381 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
382 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
383 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
384 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600385 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
386 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800387 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600388 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
389 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
390 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800391 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
392 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200393 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
394 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600395 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
396 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800397 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
398 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
399 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
400 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
401 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200403 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
405 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800407 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
409 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600413 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800415 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200417 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600419 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800421 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
425 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200427 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
429 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
430 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800431 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
432 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
433 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
434 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
435 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
436 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600437 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
438 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
439 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200440 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
441 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
442 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
443 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600444 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600445 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600446 { .type = AMD_BIOS_INVALID },
447};
448
Marshall Dawson2794a862019-03-04 16:53:15 -0700449typedef struct _context {
450 char *rom; /* target buffer, size of flash device */
451 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800452 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700453 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Baoc26108f2023-02-17 11:01:07 +0800454 uint32_t current_pointer_saved;
Zheng Bao6fff2492021-11-15 19:53:21 +0800455 uint32_t current_table;
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800456 void *amd_psp_fw_table_clean;
457 void *amd_bios_table_clean;
Marshall Dawson2794a862019-03-04 16:53:15 -0700458} context;
459
460#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800461#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600462 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
463 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
Zheng Baoc38f7642023-02-21 10:43:08 +0800464 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800465#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600466#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800467 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700468#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800469/* The mode in entry can not be higher than the header's.
470 For example, if table mode is 0, all the entry mode will be 0. */
471#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
472 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700473#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
474#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
475#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800476#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
477 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700478#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800479/* Only set the address mode in entry if the table is mode 2. */
480#define SET_ADDR_MODE(table, mode) \
481 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600482 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800483#define SET_ADDR_MODE_BY_TABLE(table) \
484 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700485
Zheng Bao7c5ad882023-02-19 13:02:52 +0800486
487static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
488{
489 amd_fw_entry *index;
490
491 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
492 if (index->filename &&
493 index->type != AMD_FW_VERSTAGE_SIG &&
494 index->type != AMD_FW_PSP_VERSTAGE &&
495 index->type != AMD_FW_SPL &&
496 index->type != AMD_FW_PSP_WHITELIST) {
497 free(index->filename);
498 index->filename = NULL;
499 }
500 }
501}
502
503static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
504{
505 amd_bios_entry *index;
506
507 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
508 if (index->filename &&
509 index->type != AMD_BIOS_APCB &&
510 index->type != AMD_BIOS_BIN &&
511 index->type != AMD_BIOS_APCB_BK &&
512 index->type != AMD_BIOS_UCODE) {
513 free(index->filename);
514 index->filename = NULL;
515 }
516 }
517}
518
519static void amdfwtool_cleanup(context *ctx)
520{
521 free(ctx->rom);
522 ctx->rom = NULL;
523
524 /* Free the filename. */
525 free_psp_firmware_filenames(amd_psp_fw_table);
526 free_bdt_firmware_filenames(amd_bios_table);
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800527
528 free(ctx->amd_psp_fw_table_clean);
529 ctx->amd_psp_fw_table_clean = NULL;
530 free(ctx->amd_bios_table_clean);
531 ctx->amd_bios_table_clean = NULL;
Zheng Bao7c5ad882023-02-19 13:02:52 +0800532}
533
Zheng Bao5164e4b2021-10-30 12:09:07 +0800534void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
535{
536 if (count >= max) {
537 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
538 "(%d)\n", count, max);
Zheng Bao7c5ad882023-02-19 13:02:52 +0800539 amdfwtool_cleanup(ctx);
Zheng Bao5164e4b2021-10-30 12:09:07 +0800540 exit(1);
541 }
542}
543
Zheng Baoc26108f2023-02-17 11:01:07 +0800544static void set_current_pointer(context *ctx, uint32_t value)
545{
546 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
547 ctx->current_pointer_saved != ctx->current) {
548 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800549 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800550 exit(1);
551 }
552
553 ctx->current = value;
554
555 if (ctx->current > ctx->rom_size) {
556 fprintf(stderr, "Error: Packing data causes overflow\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800557 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800558 exit(1);
559 }
560
561 ctx->current_pointer_saved = ctx->current;
562}
563
564static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
565{
566 /* Get */
567 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
568}
569
Marshall Dawson24f73d42019-04-01 10:48:43 -0600570static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700571{
572 void *ptr;
573
Marshall Dawson24f73d42019-04-01 10:48:43 -0600574 /*
575 * Force both onto boundary when multi. Primary table is after
576 * updatable table, so alignment ensures primary can stay intact
577 * if secondary is reprogrammed.
578 */
579 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +0800580 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600581 else
Zheng Baoc26108f2023-02-17 11:01:07 +0800582 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600583
Marshall Dawson2794a862019-03-04 16:53:15 -0700584 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800585 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800586 ((psp_directory_header *)ptr)->additional_info = 0;
587 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +0800588 adjust_current_pointer(ctx,
589 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
590 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700591 return ptr;
592}
593
Zheng Baofdd47ef2021-09-17 13:30:08 +0800594static void *new_ish_dir(context *ctx)
595{
596 void *ptr;
Zheng Baoc26108f2023-02-17 11:01:07 +0800597 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800598 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800599 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
600
Zheng Baofdd47ef2021-09-17 13:30:08 +0800601 return ptr;
602}
603
Marshall Dawson2794a862019-03-04 16:53:15 -0700604static void *new_combo_dir(context *ctx)
605{
606 void *ptr;
607
Zheng Baoc26108f2023-02-17 11:01:07 +0800608 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700609 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800610 adjust_current_pointer(ctx,
611 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
612 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700613 return ptr;
614}
615
Zheng Baobf29a0d2020-12-03 23:00:48 +0800616static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800617{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600618 psp_combo_directory *cdir = directory;
619 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600620 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800621 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600622
623 if (!count)
624 return;
Zheng Baob035f582021-05-27 11:26:12 +0800625 if (ctx == NULL || directory == NULL) {
626 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
627 return;
628 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600629
Zheng Baobf29a0d2020-12-03 23:00:48 +0800630 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baoc26108f2023-02-17 11:01:07 +0800631 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800632
Marshall Dawson24f73d42019-04-01 10:48:43 -0600633 switch (cookie) {
634 case PSP2_COOKIE:
Zheng Bao84fb9ea2022-08-18 15:54:47 +0800635 case BHD2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700636 cdir->header.cookie = cookie;
Zheng Baofd51af62022-08-18 15:26:39 +0800637 /* lookup mode is hardcoded for now. */
638 cdir->header.lookup = 1;
Marshall Dawsona378c222019-03-04 16:52:07 -0700639 cdir->header.num_entries = count;
640 cdir->header.reserved[0] = 0;
641 cdir->header.reserved[1] = 0;
642 /* checksum everything that comes after the Checksum field */
643 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
644 count * sizeof(psp_combo_entry)
645 + sizeof(cdir->header.num_entries)
646 + sizeof(cdir->header.lookup)
647 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600648 break;
649 case PSP_COOKIE:
650 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800651 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800652 if ((table_size % TABLE_ALIGNMENT) != 0) {
653 fprintf(stderr, "The PSP table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800654 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800655 exit(1);
656 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700657 dir->header.cookie = cookie;
658 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800659 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
660 dir->header.additional_info_fields.spi_block_size = 1;
661 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700662 /* checksum everything that comes after the Checksum field */
663 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700664 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700665 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800666 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600667 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800668 case BHD_COOKIE:
669 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800670 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800671 if ((table_size % TABLE_ALIGNMENT) != 0) {
672 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800673 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800674 exit(1);
675 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600676 bdir->header.cookie = cookie;
677 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800678 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
679 bdir->header.additional_info_fields.spi_block_size = 1;
680 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600681 /* checksum everything that comes after the Checksum field */
682 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
683 count * sizeof(bios_directory_entry)
684 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800685 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600686 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700687 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800688
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800689}
690
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800691static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
692 context *ctx, amd_cb_config *cb_config)
693{
694 switch (cb_config->soc_id) {
695 case PLATFORM_UNKNOWN:
696 amd_romsig->psp_directory =
697 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
698 break;
699 case PLATFORM_CEZANNE:
700 case PLATFORM_MENDOCINO:
701 case PLATFORM_PHOENIX:
702 case PLATFORM_GLINDA:
703 case PLATFORM_CARRIZO:
704 case PLATFORM_STONEYRIDGE:
705 case PLATFORM_RAVEN:
706 case PLATFORM_PICASSO:
707 case PLATFORM_LUCIENNE:
708 case PLATFORM_RENOIR:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200709 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800710 default:
711 /* for combo, it is also combo_psp_directory */
712 amd_romsig->new_psp_directory =
713 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
714 break;
715 }
716}
717
718static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
719 context *ctx, amd_cb_config *cb_config)
720{
721 switch (cb_config->soc_id) {
722 case PLATFORM_RENOIR:
723 case PLATFORM_LUCIENNE:
724 case PLATFORM_CEZANNE:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200725 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800726 if (!cb_config->recovery_ab)
727 amd_romsig->bios3_entry =
728 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
729 break;
730 case PLATFORM_MENDOCINO:
731 case PLATFORM_PHOENIX:
732 case PLATFORM_GLINDA:
733 break;
734 case PLATFORM_CARRIZO:
735 case PLATFORM_STONEYRIDGE:
736 case PLATFORM_RAVEN:
737 case PLATFORM_PICASSO:
738 default:
739 amd_romsig->bios1_entry =
740 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
741 break;
742 }
743}
744
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700745static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
746{
747 int fd;
748 struct stat fd_stat;
749 ssize_t bytes;
750
751 fd = open(src_file, O_RDONLY);
752 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800753 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700754 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700755 return -1;
756 }
757
758 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800759 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600760 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700761 return -2;
762 }
763
Zheng Bao6d402ac2020-10-01 16:16:30 +0800764 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800765 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600766 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700767 return -3;
768 }
769
770 bytes = read(fd, dest, (size_t)fd_stat.st_size);
771 close(fd);
772 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800773 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700774 return -4;
775 }
776
777 return bytes;
778}
779
Zheng Baoeb0404e2021-10-14 15:09:09 +0800780static uint32_t get_psp_id(enum platform soc_id)
781{
782 uint32_t psp_id;
783 switch (soc_id) {
784 case PLATFORM_RAVEN:
785 case PLATFORM_PICASSO:
786 psp_id = 0xBC0A0000;
787 break;
788 case PLATFORM_RENOIR:
789 case PLATFORM_LUCIENNE:
790 psp_id = 0xBC0C0000;
791 break;
792 case PLATFORM_CEZANNE:
793 psp_id = 0xBC0C0140;
794 break;
795 case PLATFORM_MENDOCINO:
796 psp_id = 0xBC0D0900;
797 break;
798 case PLATFORM_STONEYRIDGE:
799 psp_id = 0x10220B00;
800 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800801 case PLATFORM_GLINDA:
802 psp_id = 0xBC0E0200;
803 break;
804 case PLATFORM_PHOENIX:
805 psp_id = 0xBC0D0400;
806 break;
Arthur Heymans563f7af2023-07-13 11:40:08 +0200807 case PLATFORM_GENOA:
808 psp_id = 0xBC0C0111;
809 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800810 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800811 default:
812 psp_id = 0;
813 break;
814 }
815 return psp_id;
816}
817
Marshall Dawson2794a862019-03-04 16:53:15 -0700818static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700819 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700820 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800821{
Richard Spiegel137484d2018-01-17 10:23:19 -0700822 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800823 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700824
Zheng Baoc26108f2023-02-17 11:01:07 +0800825 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800826
Martin Rothcd15bc82016-11-08 11:34:02 -0700827 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800828 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800829 switch (fw_table[i].type) {
830 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800831 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700832 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800833 break;
834 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700835 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800836 break;
837 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700838 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800839 break;
840 default:
841 /* Error */
842 break;
843 }
844
Marshall Dawson2794a862019-03-04 16:53:15 -0700845 bytes = copy_blob(BUFF_CURRENT(*ctx),
846 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600847 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800848 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700849 exit(1);
850 }
851
Zheng Baoc26108f2023-02-17 11:01:07 +0800852 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800853 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800854 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800855}
856
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000857static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
858{
859 struct amd_fw_header hdr;
860 int blob_fd;
861 ssize_t bytes;
862
863 blob_fd = open(fw_entry->filename, O_RDONLY);
864 if (blob_fd < 0) {
865 fprintf(stderr, "Error opening file: %s: %s\n",
866 fw_entry->filename, strerror(errno));
867 return;
868 }
869
870 bytes = read(blob_fd, &hdr, sizeof(hdr));
871 if (bytes != sizeof(hdr)) {
872 close(blob_fd);
873 fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
874 return;
875 }
876
877 dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
878 fw_entry->type, hdr.version[3], hdr.version[2],
879 hdr.version[1], hdr.version[0]);
880
881 close(blob_fd);
882
883}
884
885static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
886{
887 amd_fw_entry *index;
888 int manifest_fd;
889
890 manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
891 if (manifest_fd < 0) {
892 fprintf(stderr, "Error opening file: %s: %s\n",
893 manifest_file, strerror(errno));
894 return;
895 }
896
897 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
898 if (!(index->filename))
899 continue;
900
901 if (index->generate_manifest == true)
902 output_manifest(manifest_fd, index);
903 }
904
905 close(manifest_fd);
906}
907
Zheng Bao9e908072020-10-28 11:39:13 +0800908/* For debugging */
909static void dump_psp_firmwares(amd_fw_entry *fw_table)
910{
911 amd_fw_entry *index;
912
Zheng Bao29514472023-08-25 19:12:47 +0800913 printf("PSP firmware components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800914 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
915 if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800916 printf(" %2x: level=%x, subprog=%x, inst=%x, %s\n",
917 index->type, index->level, index->subprog, index->inst,
918 index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800919 }
920}
921
922static void dump_bdt_firmwares(amd_bios_entry *fw_table)
923{
924 amd_bios_entry *index;
925
Zheng Bao29514472023-08-25 19:12:47 +0800926 printf("BIOS Directory Table (BDT) components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800927 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
928 if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800929 printf(" %2x: level=%x, %s\n",
930 index->type, index->level, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800931 }
932}
933
Zheng Bao990d1542021-09-17 13:24:54 +0800934static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800935 psp_directory_table *pspdir2, ish_directory_table *ish,
936 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800937{
938 uint32_t count;
939 uint32_t current_table_save;
940
941 current_table_save = ctx->current_table;
942 ctx->current_table = (char *)pspdir - ctx->rom;
943 count = pspdir->header.num_entries;
944 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
945 pspdir->entries[count].type = (uint8_t)ab;
946 pspdir->entries[count].subprog = 0;
947 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800948 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600949 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800950 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
951 ish->update_retry_count = 2;
952 ish->glitch_retry_count = 0;
953 ish->psp_id = get_psp_id(soc_id);
954 ish->checksum = fletcher32(&ish->boot_priority,
955 sizeof(ish_directory_table) - sizeof(uint32_t));
956 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600957 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800958 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600959 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800960 pspdir->entries[count].size = TABLE_ALIGNMENT;
961 } else {
962 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600963 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800964 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600965 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao948c0b72023-05-11 10:03:46 +0800966 pspdir->entries[count].size = _MAX(TABLE_ALIGNMENT,
967 pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800968 sizeof(psp_directory_entry) +
Zheng Bao948c0b72023-05-11 10:03:46 +0800969 sizeof(psp_directory_header));
Zheng Baofdd47ef2021-09-17 13:30:08 +0800970 }
Zheng Bao990d1542021-09-17 13:24:54 +0800971
972 count++;
973 pspdir->header.num_entries = count;
974 ctx->current_table = current_table_save;
975}
976
Marshall Dawson2794a862019-03-04 16:53:15 -0700977static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700978 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600979 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800980 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600981 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800982 uint32_t cookie,
983 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800984{
Richard Spiegel137484d2018-01-17 10:23:19 -0700985 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700986 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600987 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530988 uint32_t size;
989 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800990 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800991 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800992 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Fred Reitberger9d6008e2023-05-05 13:40:50 -0400993 bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
Marshall Dawson24f73d42019-04-01 10:48:43 -0600994
995 /* This function can create a primary table, a secondary table, or a
996 * flattened table which contains all applicable types. These if-else
997 * statements infer what the caller intended. If a 2nd-level cookie
998 * is passed, clearly a 2nd-level table is intended. However, a
999 * 1st-level cookie may indicate level 1 or flattened. If the caller
1000 * passes a pointer to a 2nd-level table, then assume not flat.
1001 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001002 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001003 level = PSP_BOTH;
1004 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001005 level = PSP_LVL2;
1006 else if (pspdir2)
1007 level = PSP_LVL1;
1008 else
1009 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001010
Zheng Bao990d1542021-09-17 13:24:54 +08001011 if (recovery_ab) {
1012 if (cookie == PSPL2_COOKIE)
1013 level = PSP_LVL2_AB;
1014 else if (pspdir2)
1015 level = PSP_LVL1_AB;
1016 else
1017 level = PSP_BOTH_AB;
1018 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001019 current_table_save = ctx->current_table;
1020 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +08001021 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001022
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001023 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001024 if (!(fw_table[i].level & level))
1025 continue;
1026
Zheng Bao5164e4b2021-10-30 12:09:07 +08001027 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1028
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001029 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1030 if (!fw_table[i].other)
1031 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +08001032 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001033 pspdir->entries[count].type = fw_table[i].type;
1034 pspdir->entries[count].size = 4096; /* TODO: doc? */
1035 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001036 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001037 pspdir->entries[count].subprog = fw_table[i].subprog;
1038 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +08001039 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001040 count++;
1041 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001042 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001043 pspdir->entries[count].subprog = fw_table[i].subprog;
1044 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001045 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001046 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001047 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001048 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001049 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301050 if (fw_table[i].filename == NULL) {
1051 if (fw_table[i].size == 0)
1052 continue;
1053 size = fw_table[i].size;
1054 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001055 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301056 fprintf(stderr,
1057 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001058 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301059 exit(1);
1060 }
1061 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +08001062 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301063 bytes = copy_blob(BUFF_CURRENT(*ctx),
1064 fw_table[i].filename, BUFF_ROOM(*ctx));
1065 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001066 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301067 exit(1);
1068 }
1069
Elyes Haouas7d67a192022-10-14 09:58:29 +02001070 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301071 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001072 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001073 }
1074
1075 pspdir->entries[count].type = fw_table[i].type;
1076 pspdir->entries[count].subprog = fw_table[i].subprog;
1077 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301078 pspdir->entries[count].size = size;
1079 pspdir->entries[count].addr = addr;
1080
Zheng Bao6fff2492021-11-15 19:53:21 +08001081 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001082 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001083
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001084 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001085 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001086 if (fw_table[i].addr_signed) {
1087 pspdir->entries[count].addr =
1088 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1089 pspdir->entries[count].address_mode =
1090 SET_ADDR_MODE_BY_TABLE(pspdir);
1091 bytes = fw_table[i].file_size;
1092 } else {
1093 bytes = copy_blob(BUFF_CURRENT(*ctx),
1094 fw_table[i].filename, BUFF_ROOM(*ctx));
1095 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001096 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001097 exit(1);
1098 }
1099 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1100 pspdir->entries[count].address_mode =
1101 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001102 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001103 }
1104
Marshall Dawson239286c2019-02-23 16:42:46 -07001105 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001106 pspdir->entries[count].subprog = fw_table[i].subprog;
1107 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001108 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001109 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001110
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001111 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001112 } else {
1113 /* This APU doesn't have this firmware. */
1114 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001115 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001116
Zheng Bao990d1542021-09-17 13:24:54 +08001117 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001118 if (cb_config->need_ish) { /* Need ISH */
1119 ish_a_dir = new_ish_dir(ctx);
1120 if (pspdir2_b != NULL)
1121 ish_b_dir = new_ish_dir(ctx);
1122 }
Zheng Bao990d1542021-09-17 13:24:54 +08001123 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001124 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001125 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001126 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001127 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001128 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1129 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001130 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001131 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001132 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1133 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001134
Zheng Bao990d1542021-09-17 13:24:54 +08001135 count = pspdir->header.num_entries;
1136 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001137 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001138 pspdir->entries[count].type = AMD_FW_L2_PTR;
1139 pspdir->entries[count].subprog = 0;
1140 pspdir->entries[count].rsvd = 0;
1141 pspdir->entries[count].size = sizeof(pspdir2->header)
1142 + pspdir2->header.num_entries
1143 * sizeof(psp_directory_entry);
1144
Zheng Bao6fff2492021-11-15 19:53:21 +08001145 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001146 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001147 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001148 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001149 count++;
1150 }
1151
Zheng Baobf29a0d2020-12-03 23:00:48 +08001152 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001153 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001154}
1155
Zheng Bao990d1542021-09-17 13:24:54 +08001156static void add_psp_firmware_entry(context *ctx,
1157 psp_directory_table *pspdir,
1158 void *table, amd_fw_type type, uint32_t size)
1159{
1160 uint32_t count = pspdir->header.num_entries;
1161 uint32_t index;
1162 uint32_t current_table_save;
1163
1164 current_table_save = ctx->current_table;
1165 ctx->current_table = (char *)pspdir - ctx->rom;
1166
1167 /* If there is an entry of "type", replace it. */
1168 for (index = 0; index < count; index++) {
1169 if (pspdir->entries[index].type == (uint8_t)type)
1170 break;
1171 }
1172
1173 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1174 pspdir->entries[index].type = (uint8_t)type;
1175 pspdir->entries[index].subprog = 0;
1176 pspdir->entries[index].rsvd = 0;
1177 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1178 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1179 pspdir->entries[index].size = size;
1180 if (index == count)
1181 count++;
1182
1183 pspdir->header.num_entries = count;
1184 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1185 count * sizeof(psp_directory_entry)
1186 + sizeof(pspdir->header.num_entries)
1187 + sizeof(pspdir->header.additional_info));
1188
1189 ctx->current_table = current_table_save;
1190}
1191
Zheng Baoba3af5e2021-11-04 18:56:47 +08001192static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001193{
1194 void *ptr;
1195
1196 /*
1197 * Force both onto boundary when multi. Primary table is after
1198 * updatable table, so alignment ensures primary can stay intact
1199 * if secondary is reprogrammed.
1200 */
1201 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001202 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001203 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001204 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001205 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001206 ((bios_directory_hdr *) ptr)->additional_info = 0;
1207 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1208 ctx->current_table = ctx->current;
Zheng Baoc26108f2023-02-17 11:01:07 +08001209 adjust_current_pointer(ctx,
1210 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1211 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001212 return ptr;
1213}
1214
1215static int locate_bdt2_bios(bios_directory_table *level2,
1216 uint64_t *source, uint32_t *size)
1217{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001218 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001219
1220 *source = 0;
1221 *size = 0;
1222 if (!level2)
1223 return 0;
1224
1225 for (i = 0 ; i < level2->header.num_entries ; i++) {
1226 if (level2->entries[i].type == AMD_BIOS_BIN) {
1227 *source = level2->entries[i].source;
1228 *size = level2->entries[i].size;
1229 return 1;
1230 }
1231 }
1232 return 0;
1233}
1234
1235static int have_bios_tables(amd_bios_entry *table)
1236{
1237 int i;
1238
1239 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1240 if (table[i].level & BDT_LVL1 && table[i].filename)
1241 return 1;
1242 }
1243 return 0;
1244}
1245
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001246static int find_bios_entry(amd_bios_type type)
1247{
1248 int i;
1249
1250 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1251 if (amd_bios_table[i].type == type)
1252 return i;
1253 }
1254 return -1;
1255}
1256
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001257static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1258 int inst, uint32_t size, uint64_t source)
1259{
1260 int i;
1261
1262 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1263 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1264 amd_bios_table[i].inst == inst)
1265 break;
1266 }
1267
1268 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1269 return;
1270
1271 biosdir->entries[idx].type = amd_bios_table[i].type;
1272 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1273 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1274 amd_bios_table[i].dest : (uint64_t)-1;
1275 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1276 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1277 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1278 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1279 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1280 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1281 biosdir->entries[idx].size = size;
1282 biosdir->entries[idx].source = source;
1283 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1284}
1285
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001286static void integrate_bios_firmwares(context *ctx,
1287 bios_directory_table *biosdir,
1288 bios_directory_table *biosdir2,
1289 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001290 uint32_t cookie,
1291 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001292{
1293 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001294 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001295 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001296 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001297 uint32_t size;
1298 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001299
1300 /* This function can create a primary table, a secondary table, or a
1301 * flattened table which contains all applicable types. These if-else
1302 * statements infer what the caller intended. If a 2nd-level cookie
1303 * is passed, clearly a 2nd-level table is intended. However, a
1304 * 1st-level cookie may indicate level 1 or flattened. If the caller
1305 * passes a pointer to a 2nd-level table, then assume not flat.
1306 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001307 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001308 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001309 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001310 level = BDT_LVL2;
1311 else if (biosdir2)
1312 level = BDT_LVL1;
1313 else
1314 level = BDT_BOTH;
1315
Zheng Baoc26108f2023-02-17 11:01:07 +08001316 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001317
1318 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1319 if (!(fw_table[i].level & level))
1320 continue;
1321 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301322 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001323 fw_table[i].type != AMD_BIOS_APOB &&
1324 fw_table[i].type != AMD_BIOS_APOB_NV &&
1325 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001326 fw_table[i].type != AMD_BIOS_BIN &&
1327 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001328 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001329
1330 /* BIOS Directory items may have additional requirements */
1331
Ritul Guru9a321f32022-07-29 11:06:40 +05301332 /* SIG needs a size, else no choice but to skip */
1333 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1334 continue;
1335
Martin Roth48dd9fe2020-07-29 16:32:25 -06001336 /* Check APOB_NV requirements */
1337 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1338 if (!fw_table[i].size && !fw_table[i].src)
1339 continue; /* APOB_NV not used */
1340 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001341 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001342 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001343 exit(1);
1344 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001345 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001346 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001347 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1348 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001349 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001350
1351 /* APOB_DATA needs destination */
1352 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001353 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001354 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001355 exit(1);
1356 }
1357
1358 /* BIOS binary must have destination and uncompressed size. If
1359 * no filename given, then user must provide a source address.
1360 */
1361 if (fw_table[i].type == AMD_BIOS_BIN) {
1362 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001363 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001364 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001365 exit(1);
1366 }
1367 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001368 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001369 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001370 exit(1);
1371 }
1372 }
1373
Martin Roth94554742020-04-14 14:59:36 -06001374 /* PSP_SHARED_MEM needs a destination and size */
1375 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1376 (!fw_table[i].dest || !fw_table[i].size))
1377 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001378 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001379
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001380 biosdir->entries[count].type = fw_table[i].type;
1381 biosdir->entries[count].region_type = fw_table[i].region_type;
1382 biosdir->entries[count].dest = fw_table[i].dest ?
1383 fw_table[i].dest : (uint64_t)-1;
1384 biosdir->entries[count].reset = fw_table[i].reset;
1385 biosdir->entries[count].copy = fw_table[i].copy;
1386 biosdir->entries[count].ro = fw_table[i].ro;
1387 biosdir->entries[count].compressed = fw_table[i].zlib;
1388 biosdir->entries[count].inst = fw_table[i].inst;
1389 biosdir->entries[count].subprog = fw_table[i].subpr;
1390
1391 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301392 case AMD_BIOS_SIG:
1393 /* Reserve size bytes within amdfw.rom */
1394 biosdir->entries[count].size = fw_table[i].size;
1395 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1396 biosdir->entries[count].address_mode =
1397 SET_ADDR_MODE_BY_TABLE(biosdir);
1398 memset(BUFF_CURRENT(*ctx), 0xff,
1399 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001400 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301401 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001402 case AMD_BIOS_APOB:
1403 biosdir->entries[count].size = fw_table[i].size;
1404 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001405 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001406 break;
1407 case AMD_BIOS_APOB_NV:
1408 if (fw_table[i].src) {
1409 /* If source is given, use that and its size */
1410 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001411 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001412 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001413 biosdir->entries[count].size = fw_table[i].size;
1414 } else {
1415 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001416 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001417 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001418 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001419 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001420 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001421 fw_table[i].size, ERASE_ALIGNMENT);
1422 memset(BUFF_CURRENT(*ctx), 0xff,
1423 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001424 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001425 }
1426 break;
1427 case AMD_BIOS_BIN:
1428 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001429 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1430 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001431 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001432 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001433 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001434 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001435 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001436
1437 /* level 2, or level 1 and no copy found in level 2 */
1438 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001439 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001440 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001441 biosdir->entries[count].dest = fw_table[i].dest;
1442 biosdir->entries[count].size = fw_table[i].size;
1443
1444 if (!fw_table[i].filename)
1445 break;
1446
1447 bytes = copy_blob(BUFF_CURRENT(*ctx),
1448 fw_table[i].filename, BUFF_ROOM(*ctx));
1449 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001450 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001451 exit(1);
1452 }
1453
Zheng Bao6fff2492021-11-15 19:53:21 +08001454 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001455 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001456 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001457 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001458
Zheng Baoc26108f2023-02-17 11:01:07 +08001459 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001460 break;
Martin Roth94554742020-04-14 14:59:36 -06001461 case AMD_BIOS_PSP_SHARED_MEM:
1462 biosdir->entries[count].dest = fw_table[i].dest;
1463 biosdir->entries[count].size = fw_table[i].size;
1464 break;
1465
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001466 default: /* everything else is copied from input */
1467 if (fw_table[i].type == AMD_BIOS_APCB ||
1468 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001469 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001470 bytes = copy_blob(BUFF_CURRENT(*ctx),
1471 fw_table[i].filename, BUFF_ROOM(*ctx));
1472 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001473 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001474 exit(1);
1475 }
1476
1477 biosdir->entries[count].size = (uint32_t)bytes;
1478 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001479 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001480
Zheng Baoc26108f2023-02-17 11:01:07 +08001481 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001482 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1483 size = biosdir->entries[count].size;
1484 source = biosdir->entries[count].source;
1485 count++;
1486 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1487 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001488 break;
1489 }
1490
1491 count++;
1492 }
1493
1494 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001495 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001496 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001497 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001498 biosdir->entries[count].size =
1499 + MAX_BIOS_ENTRIES
1500 * sizeof(bios_directory_entry);
1501 biosdir->entries[count].source =
1502 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001503 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001504 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001505 biosdir->entries[count].subprog = 0;
1506 biosdir->entries[count].inst = 0;
1507 biosdir->entries[count].copy = 0;
1508 biosdir->entries[count].compressed = 0;
1509 biosdir->entries[count].dest = -1;
1510 biosdir->entries[count].reset = 0;
1511 biosdir->entries[count].ro = 0;
1512 count++;
1513 }
1514
Zheng Baobf29a0d2020-12-03 23:00:48 +08001515 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001516}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001517
1518enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001519 AMDFW_OPT_CONFIG = 'c',
1520 AMDFW_OPT_DEBUG = 'd',
1521 AMDFW_OPT_HELP = 'h',
Zheng Bao806892a2021-04-27 17:21:54 +08001522
1523 AMDFW_OPT_XHCI = 128,
1524 AMDFW_OPT_IMC,
1525 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001526 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001527 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001528 AMDFW_OPT_USE_COMBO,
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001529 AMDFW_OPT_COMBO1_CONFIG,
Zheng Bao806892a2021-04-27 17:21:54 +08001530 AMDFW_OPT_MULTILEVEL,
1531 AMDFW_OPT_NVRAM,
1532
1533 AMDFW_OPT_FUSE,
1534 AMDFW_OPT_UNLOCK,
1535 AMDFW_OPT_WHITELIST,
1536 AMDFW_OPT_USE_PSPSECUREOS,
1537 AMDFW_OPT_LOAD_MP2FW,
1538 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001539 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001540 AMDFW_OPT_VERSTAGE,
1541 AMDFW_OPT_VERSTAGE_SIG,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001542 AMDFW_OPT_OUTPUT_MANIFEST,
Zheng Bao806892a2021-04-27 17:21:54 +08001543
1544 AMDFW_OPT_INSTANCE,
1545 AMDFW_OPT_APCB,
1546 AMDFW_OPT_APOBBASE,
1547 AMDFW_OPT_BIOSBIN,
1548 AMDFW_OPT_BIOSBIN_SOURCE,
1549 AMDFW_OPT_BIOSBIN_DEST,
1550 AMDFW_OPT_BIOS_UNCOMP_SIZE,
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001551 AMDFW_OPT_BIOSBIN_UNCOMP,
Zheng Bao806892a2021-04-27 17:21:54 +08001552 AMDFW_OPT_UCODE,
1553 AMDFW_OPT_APOB_NVBASE,
1554 AMDFW_OPT_APOB_NVSIZE,
1555
1556 AMDFW_OPT_OUTPUT,
1557 AMDFW_OPT_FLASHSIZE,
1558 AMDFW_OPT_LOCATION,
1559 AMDFW_OPT_ANYWHERE,
1560 AMDFW_OPT_SHAREDMEM,
1561 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001562 AMDFW_OPT_SIGNED_OUTPUT,
1563 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001564 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001565 /* begin after ASCII characters */
1566 LONGOPT_SPI_READ_MODE = 256,
1567 LONGOPT_SPI_SPEED = 257,
1568 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301569 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301570 LONGOPT_NVRAM_BASE = 260,
1571 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001572};
1573
Zheng Bao806892a2021-04-27 17:21:54 +08001574static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
Zheng Bao994ff522023-03-09 11:43:55 +08001575 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
Zheng Bao806892a2021-04-27 17:21:54 +08001576};
Marc Jones90099b62016-09-20 21:05:45 -06001577
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001578static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001579 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1580 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1581 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001582 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001583 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001584 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001585 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001586 {"combo-config1", required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001587 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1588 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301589 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1590 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001591 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1592 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1593 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1594 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1595 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1596 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001597 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001598 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1599 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001600 {"output-manifest", required_argument, 0, AMDFW_OPT_OUTPUT_MANIFEST },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001601 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001602 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1603 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1604 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1605 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1606 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1607 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1608 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001609 {"bios-bin-uncomp", no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
Ritul Guru9a321f32022-07-29 11:06:40 +05301610 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001611 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1612 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1613 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001614 /* Embedded Firmware Structure items*/
1615 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1616 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1617 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001618 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001619 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001620 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1621 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1622 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1623 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1624 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1625 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001626
Kangheui Won3c164e12021-12-03 20:25:05 +11001627 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1628 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1629
Zheng Bao806892a2021-04-27 17:21:54 +08001630 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1631 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1632 {"help", no_argument, 0, AMDFW_OPT_HELP },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001633 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001634};
1635
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001636void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001637{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001638 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001639
1640 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1641 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1642 continue;
1643
1644 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1645 return;
1646 }
1647}
1648
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001649static void register_fw_token_unlock(void)
1650{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001651 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001652
1653 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1654 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1655 continue;
1656
1657 amd_psp_fw_table[i].other = 1;
1658 return;
1659 }
1660}
1661
Marshall Dawsondbae6322019-03-04 10:31:03 -07001662static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001663{
Martin Roth8806f7f2016-11-08 10:44:18 -07001664 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001665
Martin Rothcd15bc82016-11-08 11:34:02 -07001666 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001667 if (amd_fw_table[i].type == type) {
1668 amd_fw_table[i].filename = filename;
1669 return;
1670 }
1671 }
1672
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001673 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001674 if (amd_psp_fw_table[i].type != type)
1675 continue;
1676
1677 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001678 amd_psp_fw_table[i].filename = filename;
1679 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001680 }
1681 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001682}
1683
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001684static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1685{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001686 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001687
1688 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1689 if (amd_bios_table[i].type == type
1690 && amd_bios_table[i].inst == ins
1691 && amd_bios_table[i].subpr == sub) {
1692 amd_bios_table[i].filename = name;
1693 return;
1694 }
1695 }
1696}
1697
Ritul Gurua2cb3402022-08-29 00:51:08 +05301698static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1699 char *dst_str, char *size_str)
1700{
1701 unsigned int i;
1702
1703 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1704 if (amd_psp_fw_table[i].type != type)
1705 continue;
1706
1707 if (amd_psp_fw_table[i].subprog == sub) {
1708 if (dst_str)
1709 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1710 if (size_str)
1711 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1712 return;
1713 }
1714 }
1715}
1716
1717static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001718 char *dst_str, char *size_str)
1719{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001720 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001721 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1722 if (amd_bios_table[i].type != type)
1723 continue;
1724
1725 if (src_str)
1726 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1727 if (dst_str)
1728 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1729 if (size_str)
1730 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1731
1732 return;
1733 }
1734}
1735
Zheng Baoc3007f32022-04-03 12:53:51 +08001736static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1737 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1738 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001739{
1740 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001741 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001742 return 1;
1743 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001744
1745 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1746 * Leave as 0xffffffff for first gen */
1747 if (cb_config->second_gen) {
1748 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1749 amd_romsig->efs_gen.reserved = 0;
1750 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001751 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1752 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001753 }
1754
1755 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001756 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001757 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001758 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1759 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1760 break;
1761 case PLATFORM_RAVEN:
1762 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001763 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1764 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1765 switch (efs_spi_micron_flag) {
1766 case 0:
1767 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1768 break;
1769 case 1:
1770 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1771 break;
1772 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001773 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001774 return 1;
1775 }
1776 break;
1777 case PLATFORM_RENOIR:
1778 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001779 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001780 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001781 case PLATFORM_PHOENIX:
1782 case PLATFORM_GLINDA:
Arthur Heymans563f7af2023-07-13 11:40:08 +02001783 case PLATFORM_GENOA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001784 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1785 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1786 switch (efs_spi_micron_flag) {
1787 case 0:
1788 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1789 break;
1790 case 1:
1791 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1792 break;
1793 case 2:
1794 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1795 break;
1796 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001797 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001798 return 1;
1799 }
1800 break;
1801 case PLATFORM_UNKNOWN:
1802 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001803 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001804 return 1;
1805 }
1806 return 0;
1807}
1808
Zheng Bao69ea83c2023-01-22 21:08:18 +08001809static ssize_t write_body(char *output, void *body_offset, ssize_t body_size, context *ctx)
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001810{
Zheng Bao69ea83c2023-01-22 21:08:18 +08001811 char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001812 int ret;
1813 int fd;
1814 ssize_t bytes = -1;
1815
1816 /* Create a tmp file and rename it at the end so that make does not get confused
1817 if amdfwtool is killed for some unexpected reasons. */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001818 ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
1819 output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001820 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001821 fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001822 strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001823 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001824 exit(1);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001825 } else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
1826 fprintf(stderr, "BODY File name %d > %zu\n", ret, sizeof(body_tmp_name));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001827 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001828 exit(1);
1829 }
1830
Zheng Bao69ea83c2023-01-22 21:08:18 +08001831 fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001832 if (fd < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001833 fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001834 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001835 exit(1);
1836 }
1837
Zheng Bao69ea83c2023-01-22 21:08:18 +08001838 bytes = write_from_buf_to_file(fd, body_offset, body_size);
1839 if (bytes != body_size) {
1840 fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001841 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001842 exit(1);
1843 }
1844 close(fd);
1845
1846 /* Rename the tmp file */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001847 ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001848 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001849 fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001850 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001851 exit(1);
1852 }
1853
Zheng Bao69ea83c2023-01-22 21:08:18 +08001854 if (rename(body_tmp_name, body_name)) {
1855 fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001856 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001857 exit(1);
1858 }
1859
1860 return bytes;
1861}
1862
Zheng Bao994ff522023-03-09 11:43:55 +08001863void open_process_config(char *config, amd_cb_config *cb_config, int debug)
Zheng Bao39cae562023-03-07 18:37:43 +08001864{
1865 FILE *config_handle;
1866
1867 if (config) {
1868 config_handle = fopen(config, "r");
1869 if (config_handle == NULL) {
1870 fprintf(stderr, "Can not open file %s for reading: %s\n",
1871 config, strerror(errno));
1872 exit(1);
1873 }
Zheng Bao994ff522023-03-09 11:43:55 +08001874 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001875 fprintf(stderr, "Configuration file %s parsing error\n",
1876 config);
1877 fclose(config_handle);
1878 exit(1);
1879 }
1880 fclose(config_handle);
1881 }
1882
1883 /* For debug. */
1884 if (debug) {
1885 dump_psp_firmwares(amd_psp_fw_table);
1886 dump_bdt_firmwares(amd_bios_table);
1887 }
1888}
1889
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001890static bool is_initial_alignment_required(enum platform soc_id)
1891{
1892 switch (soc_id) {
1893 case PLATFORM_MENDOCINO:
1894 case PLATFORM_PHOENIX:
1895 case PLATFORM_GLINDA:
1896 return false;
1897 default:
1898 return true;
1899 }
1900}
1901
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001902int main(int argc, char **argv)
1903{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001904 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001905 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001906 char *tmp;
Marshall Dawson239286c2019-02-23 16:42:46 -07001907 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001908 psp_directory_table *pspdir = NULL;
1909 psp_directory_table *pspdir2 = NULL;
1910 psp_directory_table *pspdir2_b = NULL;
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001911 psp_combo_directory *psp_combo_dir = NULL, *bhd_combo_dir = NULL;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001912 char *combo_config[MAX_COMBO_ENTRIES] = { 0 };
1913 int combo_index = 0;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001914 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001915 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001916 char *output = NULL, *config = NULL;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001917 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001918 /* Values cleared after each firmware or parameter, regardless if N/A */
1919 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08001920 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001921 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001922 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001923 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07001924 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001925 uint8_t efs_spi_readmode = 0xff;
1926 uint8_t efs_spi_speed = 0xff;
1927 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11001928 const char *signed_output_file = NULL;
1929 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001930
Fred Reitbergerf36b0132022-06-29 13:54:57 -04001931 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08001932 int debug = 0;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001933 char *manifest_file = NULL;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001934
Zheng Baoc26108f2023-02-17 11:01:07 +08001935 ctx.current_pointer_saved = 0xFFFFFFFF;
1936
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001937 while (1) {
1938 int optindex = 0;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001939 int bios_tbl_index = -1;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001940
1941 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1942
1943 if (c == -1)
1944 break;
1945
1946 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001947 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001948 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001949 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001950 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001951 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001952 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001953 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001954 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001955 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001956 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001957 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001958 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001959 case AMDFW_OPT_RECOVERY_AB:
1960 cb_config.recovery_ab = true;
1961 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001962 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1963 cb_config.recovery_ab = true;
1964 cb_config.recovery_ab_single_copy = true;
1965 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001966 case AMDFW_OPT_USE_COMBO:
1967 cb_config.use_combo = true;
1968 break;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001969 case AMDFW_OPT_COMBO1_CONFIG:
1970 cb_config.use_combo = true;
Zheng Bao73917222023-03-15 16:14:03 +08001971 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001972 combo_config[1] = optarg;
1973 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001974 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001975 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001976 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001977 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001978 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001979 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001980 sub = instance = 0;
1981 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001982 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001983 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001984 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001985 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001986 instance = strtoul(optarg, &tmp, 16);
1987 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001988 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001989 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001990 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001991 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001992 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001993 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001994 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001995 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001996 register_fw_fuse(optarg);
1997 fuse_defined = 1;
1998 sub = 0;
1999 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002000 case AMDFW_OPT_APCB:
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002001 if ((instance & 0xF0) == 0) {
Zheng Bao5caca942020-12-04 16:39:38 +08002002 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002003 } else {
Zheng Bao5caca942020-12-04 16:39:38 +08002004 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2005 instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002006 cb_config.have_apcb_bk = 1;
2007 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002008 sub = instance = 0;
2009 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002010 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002011 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302012 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002013 sub = instance = 0;
2014 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002015 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002016 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302017 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002018 sub = instance = 0;
2019 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002020 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002021 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302022 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002023 sub = instance = 0;
2024 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002025 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002026 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2027 sub = instance = 0;
2028 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002029 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002030 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302031 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002032 sub = instance = 0;
2033 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002034 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002035 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302036 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002037 sub = instance = 0;
2038 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002039 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002040 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302041 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002042 sub = instance = 0;
2043 break;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07002044 case AMDFW_OPT_BIOSBIN_UNCOMP:
2045 bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
2046 if (bios_tbl_index != -1)
2047 amd_bios_table[bios_tbl_index].zlib = 0;
2048 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302049 case LONGOPT_BIOS_SIG:
2050 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302051 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302052 sub = instance = 0;
2053 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002054 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002055 register_bdt_data(AMD_BIOS_UCODE, sub,
2056 instance, optarg);
2057 sub = instance = 0;
2058 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002059 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002060 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002061 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002062 case AMDFW_OPT_SPL_TABLE:
2063 register_fw_filename(AMD_FW_SPL, sub, optarg);
2064 sub = instance = 0;
2065 cb_config.have_mb_spl = true;
2066 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002067 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002068 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2069 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002070 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002071 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002072 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002073 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2074 sub = instance = 0;
2075 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002076 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002077 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2078 sub = instance = 0;
2079 break;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002080 case AMDFW_OPT_OUTPUT_MANIFEST:
2081 manifest_file = optarg;
2082 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002083 case AMDFW_OPT_SIGNED_OUTPUT:
2084 signed_output_file = optarg;
2085 sub = instance = 0;
2086 break;
2087 case AMDFW_OPT_SIGNED_ADDR:
2088 signed_start_addr = strtoull(optarg, NULL, 10);
2089 sub = instance = 0;
2090 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002091 case LONGOPT_SPI_READ_MODE:
2092 efs_spi_readmode = strtoull(optarg, NULL, 16);
2093 sub = instance = 0;
2094 break;
2095 case LONGOPT_SPI_SPEED:
2096 efs_spi_speed = strtoull(optarg, NULL, 16);
2097 sub = instance = 0;
2098 break;
2099 case LONGOPT_SPI_MICRON_FLAG:
2100 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2101 sub = instance = 0;
2102 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002103 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002104 output = optarg;
2105 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002106 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002107 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002108 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002109 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002110 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002111 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002112 }
2113 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002114 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002115 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002116 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002117 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002118 " incorrectly (%s)\n\n", optarg);
2119 retval = 1;
2120 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002121 if (body_location == 0)
2122 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002123 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002124 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002125 any_location = 1;
2126 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002127 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002128 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302129 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002130 sub = instance = 0;
2131 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002132 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002133 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302134 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002135 sub = instance = 0;
2136 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302137 case LONGOPT_NVRAM_BASE:
2138 /* PSP NV base */
2139 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2140 sub = instance = 0;
2141 break;
2142 case LONGOPT_NVRAM_SIZE:
2143 /* PSP NV size */
2144 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2145 sub = instance = 0;
2146 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002147 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002148 config = optarg;
2149 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002150 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002151 debug = 1;
2152 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002153 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002154 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002155 return 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002156 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002157 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002158 if (*tmp != '\0') {
2159 fprintf(stderr, "Error: Body Location specified"
2160 " incorrectly (%s)\n\n", optarg);
2161 retval = 1;
2162 }
2163 break;
2164
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002165 default:
2166 break;
2167 }
2168 }
2169
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002170 if (cb_config.use_combo) {
2171 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
2172 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
2173 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
2174 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
2175 }
2176
Zheng Bao994ff522023-03-09 11:43:55 +08002177 open_process_config(config, &cb_config, debug);
Zheng Bao9e908072020-10-28 11:39:13 +08002178
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002179 if (!fuse_defined)
2180 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2181
Zheng Bao994ff522023-03-09 11:43:55 +08002182 if (!output) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002183 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002184 retval = 1;
2185 }
2186
Zheng Baoa7731cc2023-03-11 09:27:53 +08002187 if (ctx.rom_size % 1024 != 0) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002188 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002189 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002190 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002191 }
2192
Zheng Baoa7731cc2023-03-11 09:27:53 +08002193 if (ctx.rom_size < MIN_ROM_KB * 1024) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002194 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002195 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002196 retval = 1;
2197 }
2198
2199 if (retval) {
2200 usage();
2201 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002202 }
2203
Marshall Dawson2794a862019-03-04 16:53:15 -07002204 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002205
Marshall Dawson2794a862019-03-04 16:53:15 -07002206 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Zheng Bao9770df12023-02-14 13:23:35 +08002207
2208 if (efs_location & 0xFF000000)
2209 efs_location = efs_location - rom_base_address;
2210 if (body_location & 0xFF000000)
2211 body_location = body_location - rom_base_address;
2212
2213 if (efs_location && efs_location > ctx.rom_size) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002214 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2215 return 1;
2216 }
Zheng Bao9770df12023-02-14 13:23:35 +08002217 if (body_location && body_location > ctx.rom_size) {
2218 fprintf(stderr, "Error: Body location outside of ROM.\n\n");
2219 return 1;
2220 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002221
Zheng Bao99945dc2023-01-02 10:55:56 +08002222 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002223 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2224 return 1;
2225 }
2226
Zheng Bao99945dc2023-01-02 10:55:56 +08002227 if (body_location != efs_location &&
2228 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002229 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2230 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002231 return 1;
2232 }
2233
Martin Roth37305e72020-04-07 14:16:39 -06002234 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002235 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002236 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002237 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002238 return 1;
2239 }
2240 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002241 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002242 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002243 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002244 case 0xFA0000:
2245 case 0xF20000:
2246 case 0xE20000:
2247 case 0xC20000:
2248 case 0x820000:
2249 case 0x020000:
2250 break;
2251 case 0x7A0000:
2252 case 0x720000:
2253 case 0x620000:
2254 case 0x420000:
2255 /* Special cases for 8M. */
2256 if (ctx.rom_size != 0x800000) {
2257 fprintf(stderr, "Error: Invalid Directory location.\n");
2258 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2259 return 1;
2260 }
2261 break;
2262 case 0x3A0000:
2263 case 0x320000:
2264 case 0x220000:
2265 /* Special cases for 4M. */
2266 if (ctx.rom_size != 0x400000) {
2267 fprintf(stderr, "Error: Invalid Directory location.\n");
2268 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2269 return 1;
2270 }
Martin Roth37305e72020-04-07 14:16:39 -06002271 break;
2272 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002273 fprintf(stderr, "Error: Invalid Directory location.\n");
2274 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2275 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002276 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2277 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002278 return 1;
2279 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002280 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002281 ctx.rom = malloc(ctx.rom_size);
2282 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002283 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002284 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002285 }
2286 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002287
Zheng Bao6095cd12023-02-21 10:52:47 +08002288 romsig_offset = efs_location ? efs_location : AMD_ROMSIG_OFFSET;
2289 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06002290
Marshall Dawson2794a862019-03-04 16:53:15 -07002291 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002292 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2293 amd_romsig->imc_entry = 0;
2294 amd_romsig->gec_entry = 0;
2295 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002296
Zheng Bao4bf6f492023-01-25 22:37:29 +08002297 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2298 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2299 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002300 if (retval) {
2301 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2302 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002303 }
2304 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002305 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002306 }
2307
Felix Held21a8e382022-03-29 23:10:45 +02002308 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002309 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002310 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002311 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002312 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002313 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002314 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2315 efs_location);
2316 if (body_location != efs_location)
2317 printf(" with a split body at: 0x%08x\n", body_location);
2318 else
2319 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002320
Zheng Bao6095cd12023-02-21 10:52:47 +08002321 if (efs_location != body_location)
2322 set_current_pointer(&ctx, body_location);
2323 else
2324 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
2325
Marshall Dawson2794a862019-03-04 16:53:15 -07002326 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002327
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07002328 if (is_initial_alignment_required(cb_config.soc_id)) {
2329 /* TODO: Check for older platforms. */
2330 adjust_current_pointer(&ctx, 0, 0x10000U);
2331 }
Zheng Bao6fff2492021-11-15 19:53:21 +08002332 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002333
Kangheui Won3c164e12021-12-03 20:25:05 +11002334 /* If the tool is invoked with command-line options to keep the signed PSP
2335 binaries separate, process the signed binaries first. */
2336 if (signed_output_file && signed_start_addr)
2337 process_signed_psp_firmwares(signed_output_file,
2338 amd_psp_fw_table,
2339 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002340 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002341
Zheng Baob2ae6a52022-08-18 15:45:27 +08002342 if (cb_config.use_combo) {
2343 psp_combo_dir = new_combo_dir(&ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002344
2345 adjust_current_pointer(&ctx, 0, 0x1000U);
2346
2347 bhd_combo_dir = new_combo_dir(&ctx);
Zheng Baob2ae6a52022-08-18 15:45:27 +08002348 }
2349
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002350 combo_index = 0;
2351 if (config)
2352 combo_config[0] = config;
2353
Zheng Bao4b6aa192023-03-09 11:28:47 +08002354 do {
Zheng Bao3e7008d2023-03-15 16:15:13 +08002355 if (cb_config.use_combo && debug)
2356 printf("Processing %dth combo entry\n", combo_index);
2357
Zheng Bao4b6aa192023-03-09 11:28:47 +08002358 /* for non-combo image, combo_config[0] == config, and
2359 * it already is processed. Actually "combo_index >
2360 * 0" is enough. Put both of them here to make sure
2361 * and make it clear this will not affect non-combo
2362 * case.
2363 */
2364 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002365 /* Restore the table as clean data. */
2366 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
2367 sizeof(amd_psp_fw_table));
2368 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
2369 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08002370 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08002371 open_process_config(combo_config[combo_index], &cb_config,
Zheng Bao994ff522023-03-09 11:43:55 +08002372 debug);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002373
Zheng Bao4b6aa192023-03-09 11:28:47 +08002374 /* In most cases, the address modes are same. */
2375 if (cb_config.need_ish)
2376 ctx.address_mode = AMD_ADDR_REL_TAB;
2377 else if (cb_config.second_gen)
2378 ctx.address_mode = AMD_ADDR_REL_BIOS;
2379 else
2380 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao990d1542021-09-17 13:24:54 +08002381 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002382
Zheng Bao481661e2021-08-20 14:47:46 +08002383 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002384 /* Do 2nd PSP directory followed by 1st */
2385 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2386 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
2387 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
2388 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2389 /* Create a copy of PSP Directory 2 in the backup slot B.
2390 Related biosdir2_b copy will be created later. */
2391 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2392 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
2393 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002394 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002395 /*
2396 * Either the platform is using only
2397 * one slot or B is same as above
2398 * directories for A. Skip creating
2399 * pspdir2_b here to save flash space.
2400 * Related biosdir2_b will be skipped
2401 * automatically.
2402 */
2403 pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08002404 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002405 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2406 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
2407 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002408 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002409 /* flat: PSP 1 cookie and no pointer to 2nd table */
2410 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2411 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
2412 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002413 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002414
Zheng Bao4b6aa192023-03-09 11:28:47 +08002415 if (!cb_config.use_combo) {
2416 fill_psp_directory_to_efs(amd_romsig, pspdir, &ctx, &cb_config);
2417 } else {
2418 fill_psp_directory_to_efs(amd_romsig, psp_combo_dir, &ctx, &cb_config);
2419 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2420 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2421 psp_combo_dir->entries[combo_index].id_sel = 0;
2422 psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
2423 psp_combo_dir->entries[combo_index].lvl2_addr =
2424 BUFF_TO_RUN_MODE(ctx, pspdir, AMD_ADDR_REL_BIOS);
2425
2426 fill_dir_header(psp_combo_dir, combo_index + 1, PSP2_COOKIE, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002427 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002428
2429 if (have_bios_tables(amd_bios_table)) {
2430 bios_directory_table *biosdir = NULL;
2431 if (cb_config.multi_level) {
2432 /* Do 2nd level BIOS directory followed by 1st */
2433 bios_directory_table *biosdir2 = NULL;
2434 bios_directory_table *biosdir2_b = NULL;
2435
2436 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2437
2438 integrate_bios_firmwares(&ctx, biosdir2, NULL,
2439 amd_bios_table, BHDL2_COOKIE, &cb_config);
2440 if (cb_config.recovery_ab) {
2441 if (pspdir2_b != NULL) {
2442 biosdir2_b = new_bios_dir(&ctx,
2443 cb_config.multi_level);
2444 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
2445 amd_bios_table, BHDL2_COOKIE,
2446 &cb_config);
2447 }
2448 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2449 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2450 if (pspdir2_b != NULL)
2451 add_psp_firmware_entry(&ctx, pspdir2_b,
2452 biosdir2_b, AMD_FW_BIOS_TABLE,
2453 TABLE_ALIGNMENT);
2454 } else {
2455 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2456 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
2457 amd_bios_table, BHD_COOKIE, &cb_config);
2458 }
2459 } else {
2460 /* flat: BHD1 cookie and no pointer to 2nd table */
2461 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2462 integrate_bios_firmwares(&ctx, biosdir, NULL,
2463 amd_bios_table, BHD_COOKIE, &cb_config);
2464 }
2465 if (!cb_config.use_combo) {
2466 fill_bios_directory_to_efs(amd_romsig, biosdir,
2467 &ctx, &cb_config);
2468 } else {
2469 fill_bios_directory_to_efs(amd_romsig, bhd_combo_dir,
2470 &ctx, &cb_config);
2471 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2472 bhd_combo_dir->entries[combo_index].id_sel = 0;
2473 bhd_combo_dir->entries[combo_index].id =
2474 get_psp_id(cb_config.soc_id);
2475 bhd_combo_dir->entries[combo_index].lvl2_addr =
2476 BUFF_TO_RUN_MODE(ctx, biosdir, AMD_ADDR_REL_BIOS);
2477
2478 fill_dir_header(bhd_combo_dir, combo_index + 1,
2479 BHD2_COOKIE, &ctx);
2480 }
2481 }
Zheng Bao17551ae2023-03-11 10:29:56 +08002482 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
2483 combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002484
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002485 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002486 if (targetfd >= 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08002487 uint32_t offset = efs_location;
2488 uint32_t bytes = efs_location == body_location ?
2489 ctx.current - offset : sizeof(*amd_romsig);
2490 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002491
Zheng Baoc25d5932023-03-22 12:51:47 +08002492 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08002493 if (bytes != ret_bytes) {
Zheng Bao47396912020-09-29 17:33:17 +08002494 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2495 retval = 1;
2496 }
Martin Roth31d95a22016-11-08 11:22:12 -07002497 close(targetfd);
2498 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002499 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002500 retval = 1;
2501 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002502
Zheng Bao99945dc2023-01-02 10:55:56 +08002503 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002504 ssize_t bytes;
2505
Zheng Bao69ea83c2023-01-22 21:08:18 +08002506 bytes = write_body(output, BUFF_OFFSET(ctx, body_location),
2507 ctx.current - body_location, &ctx);
2508 if (bytes != ctx.current - body_location) {
2509 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002510 retval = 1;
2511 }
2512 }
2513
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002514 if (manifest_file) {
2515 dump_blob_version(manifest_file, amd_psp_fw_table);
2516 }
2517
Zheng Bao7c5ad882023-02-19 13:02:52 +08002518 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07002519 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002520}