blob: 1b2b0054b59c0370bbf2d4d88e4dd30d83ce9287 [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 },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000247 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB,
248 .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 },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200260 { .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 },
Zheng Bao990d1542021-09-17 13:24:54 +0800263 { .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 },
Zheng Bao990d1542021-09-17 13:24:54 +0800270 { .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 },
309 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
310 { .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:
709 default:
710 /* for combo, it is also combo_psp_directory */
711 amd_romsig->new_psp_directory =
712 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
713 break;
714 }
715}
716
717static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
718 context *ctx, amd_cb_config *cb_config)
719{
720 switch (cb_config->soc_id) {
721 case PLATFORM_RENOIR:
722 case PLATFORM_LUCIENNE:
723 case PLATFORM_CEZANNE:
724 if (!cb_config->recovery_ab)
725 amd_romsig->bios3_entry =
726 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
727 break;
728 case PLATFORM_MENDOCINO:
729 case PLATFORM_PHOENIX:
730 case PLATFORM_GLINDA:
731 break;
732 case PLATFORM_CARRIZO:
733 case PLATFORM_STONEYRIDGE:
734 case PLATFORM_RAVEN:
735 case PLATFORM_PICASSO:
736 default:
737 amd_romsig->bios1_entry =
738 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
739 break;
740 }
741}
742
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700743static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
744{
745 int fd;
746 struct stat fd_stat;
747 ssize_t bytes;
748
749 fd = open(src_file, O_RDONLY);
750 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800751 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700752 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700753 return -1;
754 }
755
756 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800757 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600758 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700759 return -2;
760 }
761
Zheng Bao6d402ac2020-10-01 16:16:30 +0800762 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800763 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600764 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700765 return -3;
766 }
767
768 bytes = read(fd, dest, (size_t)fd_stat.st_size);
769 close(fd);
770 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800771 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700772 return -4;
773 }
774
775 return bytes;
776}
777
Zheng Baoeb0404e2021-10-14 15:09:09 +0800778static uint32_t get_psp_id(enum platform soc_id)
779{
780 uint32_t psp_id;
781 switch (soc_id) {
782 case PLATFORM_RAVEN:
783 case PLATFORM_PICASSO:
784 psp_id = 0xBC0A0000;
785 break;
786 case PLATFORM_RENOIR:
787 case PLATFORM_LUCIENNE:
788 psp_id = 0xBC0C0000;
789 break;
790 case PLATFORM_CEZANNE:
791 psp_id = 0xBC0C0140;
792 break;
793 case PLATFORM_MENDOCINO:
794 psp_id = 0xBC0D0900;
795 break;
796 case PLATFORM_STONEYRIDGE:
797 psp_id = 0x10220B00;
798 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800799 case PLATFORM_GLINDA:
800 psp_id = 0xBC0E0200;
801 break;
802 case PLATFORM_PHOENIX:
803 psp_id = 0xBC0D0400;
804 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800805 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800806 default:
807 psp_id = 0;
808 break;
809 }
810 return psp_id;
811}
812
Marshall Dawson2794a862019-03-04 16:53:15 -0700813static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700814 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700815 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800816{
Richard Spiegel137484d2018-01-17 10:23:19 -0700817 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800818 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700819
Zheng Baoc26108f2023-02-17 11:01:07 +0800820 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800821
Martin Rothcd15bc82016-11-08 11:34:02 -0700822 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800823 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800824 switch (fw_table[i].type) {
825 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800826 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700827 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800828 break;
829 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700830 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800831 break;
832 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700833 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800834 break;
835 default:
836 /* Error */
837 break;
838 }
839
Marshall Dawson2794a862019-03-04 16:53:15 -0700840 bytes = copy_blob(BUFF_CURRENT(*ctx),
841 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600842 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800843 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700844 exit(1);
845 }
846
Zheng Baoc26108f2023-02-17 11:01:07 +0800847 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800848 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800849 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800850}
851
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000852static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
853{
854 struct amd_fw_header hdr;
855 int blob_fd;
856 ssize_t bytes;
857
858 blob_fd = open(fw_entry->filename, O_RDONLY);
859 if (blob_fd < 0) {
860 fprintf(stderr, "Error opening file: %s: %s\n",
861 fw_entry->filename, strerror(errno));
862 return;
863 }
864
865 bytes = read(blob_fd, &hdr, sizeof(hdr));
866 if (bytes != sizeof(hdr)) {
867 close(blob_fd);
868 fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
869 return;
870 }
871
872 dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
873 fw_entry->type, hdr.version[3], hdr.version[2],
874 hdr.version[1], hdr.version[0]);
875
876 close(blob_fd);
877
878}
879
880static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
881{
882 amd_fw_entry *index;
883 int manifest_fd;
884
885 manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
886 if (manifest_fd < 0) {
887 fprintf(stderr, "Error opening file: %s: %s\n",
888 manifest_file, strerror(errno));
889 return;
890 }
891
892 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
893 if (!(index->filename))
894 continue;
895
896 if (index->generate_manifest == true)
897 output_manifest(manifest_fd, index);
898 }
899
900 close(manifest_fd);
901}
902
Zheng Bao9e908072020-10-28 11:39:13 +0800903/* For debugging */
904static void dump_psp_firmwares(amd_fw_entry *fw_table)
905{
906 amd_fw_entry *index;
907
908 printf("PSP firmware components:");
909 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
910 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800911 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800912 }
913}
914
915static void dump_bdt_firmwares(amd_bios_entry *fw_table)
916{
917 amd_bios_entry *index;
918
919 printf("BIOS Directory Table (BDT) components:");
920 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
921 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800922 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800923 }
924}
925
Zheng Bao990d1542021-09-17 13:24:54 +0800926static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800927 psp_directory_table *pspdir2, ish_directory_table *ish,
928 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800929{
930 uint32_t count;
931 uint32_t current_table_save;
932
933 current_table_save = ctx->current_table;
934 ctx->current_table = (char *)pspdir - ctx->rom;
935 count = pspdir->header.num_entries;
936 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
937 pspdir->entries[count].type = (uint8_t)ab;
938 pspdir->entries[count].subprog = 0;
939 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800940 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600941 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800942 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
943 ish->update_retry_count = 2;
944 ish->glitch_retry_count = 0;
945 ish->psp_id = get_psp_id(soc_id);
946 ish->checksum = fletcher32(&ish->boot_priority,
947 sizeof(ish_directory_table) - sizeof(uint32_t));
948 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600949 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800950 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600951 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800952 pspdir->entries[count].size = TABLE_ALIGNMENT;
953 } else {
954 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600955 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800956 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600957 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao948c0b72023-05-11 10:03:46 +0800958 pspdir->entries[count].size = _MAX(TABLE_ALIGNMENT,
959 pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800960 sizeof(psp_directory_entry) +
Zheng Bao948c0b72023-05-11 10:03:46 +0800961 sizeof(psp_directory_header));
Zheng Baofdd47ef2021-09-17 13:30:08 +0800962 }
Zheng Bao990d1542021-09-17 13:24:54 +0800963
964 count++;
965 pspdir->header.num_entries = count;
966 ctx->current_table = current_table_save;
967}
968
Marshall Dawson2794a862019-03-04 16:53:15 -0700969static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700970 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600971 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800972 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600973 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800974 uint32_t cookie,
975 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800976{
Richard Spiegel137484d2018-01-17 10:23:19 -0700977 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700978 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600979 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530980 uint32_t size;
981 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800982 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800983 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800984 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Fred Reitberger9d6008e2023-05-05 13:40:50 -0400985 bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
Marshall Dawson24f73d42019-04-01 10:48:43 -0600986
987 /* This function can create a primary table, a secondary table, or a
988 * flattened table which contains all applicable types. These if-else
989 * statements infer what the caller intended. If a 2nd-level cookie
990 * is passed, clearly a 2nd-level table is intended. However, a
991 * 1st-level cookie may indicate level 1 or flattened. If the caller
992 * passes a pointer to a 2nd-level table, then assume not flat.
993 */
Zheng Baoba3af5e2021-11-04 18:56:47 +0800994 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800995 level = PSP_BOTH;
996 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600997 level = PSP_LVL2;
998 else if (pspdir2)
999 level = PSP_LVL1;
1000 else
1001 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001002
Zheng Bao990d1542021-09-17 13:24:54 +08001003 if (recovery_ab) {
1004 if (cookie == PSPL2_COOKIE)
1005 level = PSP_LVL2_AB;
1006 else if (pspdir2)
1007 level = PSP_LVL1_AB;
1008 else
1009 level = PSP_BOTH_AB;
1010 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001011 current_table_save = ctx->current_table;
1012 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +08001013 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001014
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001015 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001016 if (!(fw_table[i].level & level))
1017 continue;
1018
Zheng Bao5164e4b2021-10-30 12:09:07 +08001019 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1020
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001021 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1022 if (!fw_table[i].other)
1023 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +08001024 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001025 pspdir->entries[count].type = fw_table[i].type;
1026 pspdir->entries[count].size = 4096; /* TODO: doc? */
1027 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001028 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001029 pspdir->entries[count].subprog = fw_table[i].subprog;
1030 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +08001031 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001032 count++;
1033 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001034 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001035 pspdir->entries[count].subprog = fw_table[i].subprog;
1036 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001037 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001038 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001039 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001040 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001041 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301042 if (fw_table[i].filename == NULL) {
1043 if (fw_table[i].size == 0)
1044 continue;
1045 size = fw_table[i].size;
1046 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001047 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301048 fprintf(stderr,
1049 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001050 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301051 exit(1);
1052 }
1053 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +08001054 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301055 bytes = copy_blob(BUFF_CURRENT(*ctx),
1056 fw_table[i].filename, BUFF_ROOM(*ctx));
1057 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001058 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301059 exit(1);
1060 }
1061
Elyes Haouas7d67a192022-10-14 09:58:29 +02001062 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301063 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001064 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001065 }
1066
1067 pspdir->entries[count].type = fw_table[i].type;
1068 pspdir->entries[count].subprog = fw_table[i].subprog;
1069 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301070 pspdir->entries[count].size = size;
1071 pspdir->entries[count].addr = addr;
1072
Zheng Bao6fff2492021-11-15 19:53:21 +08001073 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001074 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001075
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001076 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001077 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001078 if (fw_table[i].addr_signed) {
1079 pspdir->entries[count].addr =
1080 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1081 pspdir->entries[count].address_mode =
1082 SET_ADDR_MODE_BY_TABLE(pspdir);
1083 bytes = fw_table[i].file_size;
1084 } else {
1085 bytes = copy_blob(BUFF_CURRENT(*ctx),
1086 fw_table[i].filename, BUFF_ROOM(*ctx));
1087 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001088 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001089 exit(1);
1090 }
1091 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1092 pspdir->entries[count].address_mode =
1093 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001094 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001095 }
1096
Marshall Dawson239286c2019-02-23 16:42:46 -07001097 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001098 pspdir->entries[count].subprog = fw_table[i].subprog;
1099 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001100 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001101 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001102
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001103 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001104 } else {
1105 /* This APU doesn't have this firmware. */
1106 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001107 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001108
Zheng Bao990d1542021-09-17 13:24:54 +08001109 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001110 if (cb_config->need_ish) { /* Need ISH */
1111 ish_a_dir = new_ish_dir(ctx);
1112 if (pspdir2_b != NULL)
1113 ish_b_dir = new_ish_dir(ctx);
1114 }
Zheng Bao990d1542021-09-17 13:24:54 +08001115 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001116 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001117 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001118 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001119 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001120 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1121 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001122 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001123 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001124 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1125 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001126
Zheng Bao990d1542021-09-17 13:24:54 +08001127 count = pspdir->header.num_entries;
1128 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001129 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001130 pspdir->entries[count].type = AMD_FW_L2_PTR;
1131 pspdir->entries[count].subprog = 0;
1132 pspdir->entries[count].rsvd = 0;
1133 pspdir->entries[count].size = sizeof(pspdir2->header)
1134 + pspdir2->header.num_entries
1135 * sizeof(psp_directory_entry);
1136
Zheng Bao6fff2492021-11-15 19:53:21 +08001137 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001138 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001139 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001140 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001141 count++;
1142 }
1143
Zheng Baobf29a0d2020-12-03 23:00:48 +08001144 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001145 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001146}
1147
Zheng Bao990d1542021-09-17 13:24:54 +08001148static void add_psp_firmware_entry(context *ctx,
1149 psp_directory_table *pspdir,
1150 void *table, amd_fw_type type, uint32_t size)
1151{
1152 uint32_t count = pspdir->header.num_entries;
1153 uint32_t index;
1154 uint32_t current_table_save;
1155
1156 current_table_save = ctx->current_table;
1157 ctx->current_table = (char *)pspdir - ctx->rom;
1158
1159 /* If there is an entry of "type", replace it. */
1160 for (index = 0; index < count; index++) {
1161 if (pspdir->entries[index].type == (uint8_t)type)
1162 break;
1163 }
1164
1165 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1166 pspdir->entries[index].type = (uint8_t)type;
1167 pspdir->entries[index].subprog = 0;
1168 pspdir->entries[index].rsvd = 0;
1169 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1170 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1171 pspdir->entries[index].size = size;
1172 if (index == count)
1173 count++;
1174
1175 pspdir->header.num_entries = count;
1176 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1177 count * sizeof(psp_directory_entry)
1178 + sizeof(pspdir->header.num_entries)
1179 + sizeof(pspdir->header.additional_info));
1180
1181 ctx->current_table = current_table_save;
1182}
1183
Zheng Baoba3af5e2021-11-04 18:56:47 +08001184static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001185{
1186 void *ptr;
1187
1188 /*
1189 * Force both onto boundary when multi. Primary table is after
1190 * updatable table, so alignment ensures primary can stay intact
1191 * if secondary is reprogrammed.
1192 */
1193 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001194 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001195 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001196 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001197 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001198 ((bios_directory_hdr *) ptr)->additional_info = 0;
1199 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1200 ctx->current_table = ctx->current;
Zheng Baoc26108f2023-02-17 11:01:07 +08001201 adjust_current_pointer(ctx,
1202 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1203 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001204 return ptr;
1205}
1206
1207static int locate_bdt2_bios(bios_directory_table *level2,
1208 uint64_t *source, uint32_t *size)
1209{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001210 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001211
1212 *source = 0;
1213 *size = 0;
1214 if (!level2)
1215 return 0;
1216
1217 for (i = 0 ; i < level2->header.num_entries ; i++) {
1218 if (level2->entries[i].type == AMD_BIOS_BIN) {
1219 *source = level2->entries[i].source;
1220 *size = level2->entries[i].size;
1221 return 1;
1222 }
1223 }
1224 return 0;
1225}
1226
1227static int have_bios_tables(amd_bios_entry *table)
1228{
1229 int i;
1230
1231 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1232 if (table[i].level & BDT_LVL1 && table[i].filename)
1233 return 1;
1234 }
1235 return 0;
1236}
1237
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001238static int find_bios_entry(amd_bios_type type)
1239{
1240 int i;
1241
1242 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1243 if (amd_bios_table[i].type == type)
1244 return i;
1245 }
1246 return -1;
1247}
1248
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001249static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1250 int inst, uint32_t size, uint64_t source)
1251{
1252 int i;
1253
1254 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1255 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1256 amd_bios_table[i].inst == inst)
1257 break;
1258 }
1259
1260 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1261 return;
1262
1263 biosdir->entries[idx].type = amd_bios_table[i].type;
1264 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1265 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1266 amd_bios_table[i].dest : (uint64_t)-1;
1267 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1268 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1269 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1270 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1271 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1272 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1273 biosdir->entries[idx].size = size;
1274 biosdir->entries[idx].source = source;
1275 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1276}
1277
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001278static void integrate_bios_firmwares(context *ctx,
1279 bios_directory_table *biosdir,
1280 bios_directory_table *biosdir2,
1281 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001282 uint32_t cookie,
1283 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001284{
1285 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001286 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001287 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001288 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001289 uint32_t size;
1290 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001291
1292 /* This function can create a primary table, a secondary table, or a
1293 * flattened table which contains all applicable types. These if-else
1294 * statements infer what the caller intended. If a 2nd-level cookie
1295 * is passed, clearly a 2nd-level table is intended. However, a
1296 * 1st-level cookie may indicate level 1 or flattened. If the caller
1297 * passes a pointer to a 2nd-level table, then assume not flat.
1298 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001299 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001300 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001301 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001302 level = BDT_LVL2;
1303 else if (biosdir2)
1304 level = BDT_LVL1;
1305 else
1306 level = BDT_BOTH;
1307
Zheng Baoc26108f2023-02-17 11:01:07 +08001308 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001309
1310 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1311 if (!(fw_table[i].level & level))
1312 continue;
1313 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301314 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001315 fw_table[i].type != AMD_BIOS_APOB &&
1316 fw_table[i].type != AMD_BIOS_APOB_NV &&
1317 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001318 fw_table[i].type != AMD_BIOS_BIN &&
1319 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001320 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001321
1322 /* BIOS Directory items may have additional requirements */
1323
Ritul Guru9a321f32022-07-29 11:06:40 +05301324 /* SIG needs a size, else no choice but to skip */
1325 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1326 continue;
1327
Martin Roth48dd9fe2020-07-29 16:32:25 -06001328 /* Check APOB_NV requirements */
1329 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1330 if (!fw_table[i].size && !fw_table[i].src)
1331 continue; /* APOB_NV not used */
1332 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001333 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001334 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001335 exit(1);
1336 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001337 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001338 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001339 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1340 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001341 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001342
1343 /* APOB_DATA needs destination */
1344 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001345 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001346 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001347 exit(1);
1348 }
1349
1350 /* BIOS binary must have destination and uncompressed size. If
1351 * no filename given, then user must provide a source address.
1352 */
1353 if (fw_table[i].type == AMD_BIOS_BIN) {
1354 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001355 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001356 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001357 exit(1);
1358 }
1359 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001360 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001361 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001362 exit(1);
1363 }
1364 }
1365
Martin Roth94554742020-04-14 14:59:36 -06001366 /* PSP_SHARED_MEM needs a destination and size */
1367 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1368 (!fw_table[i].dest || !fw_table[i].size))
1369 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001370 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001371
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001372 biosdir->entries[count].type = fw_table[i].type;
1373 biosdir->entries[count].region_type = fw_table[i].region_type;
1374 biosdir->entries[count].dest = fw_table[i].dest ?
1375 fw_table[i].dest : (uint64_t)-1;
1376 biosdir->entries[count].reset = fw_table[i].reset;
1377 biosdir->entries[count].copy = fw_table[i].copy;
1378 biosdir->entries[count].ro = fw_table[i].ro;
1379 biosdir->entries[count].compressed = fw_table[i].zlib;
1380 biosdir->entries[count].inst = fw_table[i].inst;
1381 biosdir->entries[count].subprog = fw_table[i].subpr;
1382
1383 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301384 case AMD_BIOS_SIG:
1385 /* Reserve size bytes within amdfw.rom */
1386 biosdir->entries[count].size = fw_table[i].size;
1387 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1388 biosdir->entries[count].address_mode =
1389 SET_ADDR_MODE_BY_TABLE(biosdir);
1390 memset(BUFF_CURRENT(*ctx), 0xff,
1391 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001392 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301393 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001394 case AMD_BIOS_APOB:
1395 biosdir->entries[count].size = fw_table[i].size;
1396 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001397 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001398 break;
1399 case AMD_BIOS_APOB_NV:
1400 if (fw_table[i].src) {
1401 /* If source is given, use that and its size */
1402 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001403 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001404 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001405 biosdir->entries[count].size = fw_table[i].size;
1406 } else {
1407 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001408 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001409 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001410 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001411 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001412 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001413 fw_table[i].size, ERASE_ALIGNMENT);
1414 memset(BUFF_CURRENT(*ctx), 0xff,
1415 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001416 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001417 }
1418 break;
1419 case AMD_BIOS_BIN:
1420 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001421 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1422 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001423 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001424 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001425 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001426 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001427 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001428
1429 /* level 2, or level 1 and no copy found in level 2 */
1430 biosdir->entries[count].source = fw_table[i].src;
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);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001433 biosdir->entries[count].dest = fw_table[i].dest;
1434 biosdir->entries[count].size = fw_table[i].size;
1435
1436 if (!fw_table[i].filename)
1437 break;
1438
1439 bytes = copy_blob(BUFF_CURRENT(*ctx),
1440 fw_table[i].filename, BUFF_ROOM(*ctx));
1441 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001442 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001443 exit(1);
1444 }
1445
Zheng Bao6fff2492021-11-15 19:53:21 +08001446 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001447 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001448 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001449 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001450
Zheng Baoc26108f2023-02-17 11:01:07 +08001451 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001452 break;
Martin Roth94554742020-04-14 14:59:36 -06001453 case AMD_BIOS_PSP_SHARED_MEM:
1454 biosdir->entries[count].dest = fw_table[i].dest;
1455 biosdir->entries[count].size = fw_table[i].size;
1456 break;
1457
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001458 default: /* everything else is copied from input */
1459 if (fw_table[i].type == AMD_BIOS_APCB ||
1460 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001461 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001462 bytes = copy_blob(BUFF_CURRENT(*ctx),
1463 fw_table[i].filename, BUFF_ROOM(*ctx));
1464 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001465 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001466 exit(1);
1467 }
1468
1469 biosdir->entries[count].size = (uint32_t)bytes;
1470 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001471 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001472
Zheng Baoc26108f2023-02-17 11:01:07 +08001473 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001474 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1475 size = biosdir->entries[count].size;
1476 source = biosdir->entries[count].source;
1477 count++;
1478 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1479 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001480 break;
1481 }
1482
1483 count++;
1484 }
1485
1486 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001487 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001488 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001489 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001490 biosdir->entries[count].size =
1491 + MAX_BIOS_ENTRIES
1492 * sizeof(bios_directory_entry);
1493 biosdir->entries[count].source =
1494 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001495 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001496 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001497 biosdir->entries[count].subprog = 0;
1498 biosdir->entries[count].inst = 0;
1499 biosdir->entries[count].copy = 0;
1500 biosdir->entries[count].compressed = 0;
1501 biosdir->entries[count].dest = -1;
1502 biosdir->entries[count].reset = 0;
1503 biosdir->entries[count].ro = 0;
1504 count++;
1505 }
1506
Zheng Baobf29a0d2020-12-03 23:00:48 +08001507 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001508}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001509
1510enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001511 AMDFW_OPT_CONFIG = 'c',
1512 AMDFW_OPT_DEBUG = 'd',
1513 AMDFW_OPT_HELP = 'h',
Zheng Bao806892a2021-04-27 17:21:54 +08001514
1515 AMDFW_OPT_XHCI = 128,
1516 AMDFW_OPT_IMC,
1517 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001518 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001519 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001520 AMDFW_OPT_USE_COMBO,
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001521 AMDFW_OPT_COMBO1_CONFIG,
Zheng Bao806892a2021-04-27 17:21:54 +08001522 AMDFW_OPT_MULTILEVEL,
1523 AMDFW_OPT_NVRAM,
1524
1525 AMDFW_OPT_FUSE,
1526 AMDFW_OPT_UNLOCK,
1527 AMDFW_OPT_WHITELIST,
1528 AMDFW_OPT_USE_PSPSECUREOS,
1529 AMDFW_OPT_LOAD_MP2FW,
1530 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001531 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001532 AMDFW_OPT_VERSTAGE,
1533 AMDFW_OPT_VERSTAGE_SIG,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001534 AMDFW_OPT_OUTPUT_MANIFEST,
Zheng Bao806892a2021-04-27 17:21:54 +08001535
1536 AMDFW_OPT_INSTANCE,
1537 AMDFW_OPT_APCB,
1538 AMDFW_OPT_APOBBASE,
1539 AMDFW_OPT_BIOSBIN,
1540 AMDFW_OPT_BIOSBIN_SOURCE,
1541 AMDFW_OPT_BIOSBIN_DEST,
1542 AMDFW_OPT_BIOS_UNCOMP_SIZE,
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001543 AMDFW_OPT_BIOSBIN_UNCOMP,
Zheng Bao806892a2021-04-27 17:21:54 +08001544 AMDFW_OPT_UCODE,
1545 AMDFW_OPT_APOB_NVBASE,
1546 AMDFW_OPT_APOB_NVSIZE,
1547
1548 AMDFW_OPT_OUTPUT,
1549 AMDFW_OPT_FLASHSIZE,
1550 AMDFW_OPT_LOCATION,
1551 AMDFW_OPT_ANYWHERE,
1552 AMDFW_OPT_SHAREDMEM,
1553 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001554 AMDFW_OPT_SIGNED_OUTPUT,
1555 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001556 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001557 /* begin after ASCII characters */
1558 LONGOPT_SPI_READ_MODE = 256,
1559 LONGOPT_SPI_SPEED = 257,
1560 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301561 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301562 LONGOPT_NVRAM_BASE = 260,
1563 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001564};
1565
Zheng Bao806892a2021-04-27 17:21:54 +08001566static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
Zheng Bao994ff522023-03-09 11:43:55 +08001567 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
Zheng Bao806892a2021-04-27 17:21:54 +08001568};
Marc Jones90099b62016-09-20 21:05:45 -06001569
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001570static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001571 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1572 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1573 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001574 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001575 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001576 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001577 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001578 {"combo-config1", required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001579 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1580 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301581 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1582 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001583 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1584 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1585 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1586 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1587 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1588 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001589 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001590 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1591 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001592 {"output-manifest", required_argument, 0, AMDFW_OPT_OUTPUT_MANIFEST },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001593 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001594 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1595 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1596 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1597 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1598 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1599 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1600 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001601 {"bios-bin-uncomp", no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
Ritul Guru9a321f32022-07-29 11:06:40 +05301602 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001603 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1604 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1605 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001606 /* Embedded Firmware Structure items*/
1607 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1608 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1609 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001610 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001611 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001612 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1613 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1614 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1615 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1616 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1617 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001618
Kangheui Won3c164e12021-12-03 20:25:05 +11001619 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1620 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1621
Zheng Bao806892a2021-04-27 17:21:54 +08001622 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1623 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1624 {"help", no_argument, 0, AMDFW_OPT_HELP },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001625 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001626};
1627
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001628void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001629{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001630 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001631
1632 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1633 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1634 continue;
1635
1636 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1637 return;
1638 }
1639}
1640
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001641static void register_fw_token_unlock(void)
1642{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001643 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001644
1645 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1646 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1647 continue;
1648
1649 amd_psp_fw_table[i].other = 1;
1650 return;
1651 }
1652}
1653
Marshall Dawsondbae6322019-03-04 10:31:03 -07001654static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001655{
Martin Roth8806f7f2016-11-08 10:44:18 -07001656 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001657
Martin Rothcd15bc82016-11-08 11:34:02 -07001658 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001659 if (amd_fw_table[i].type == type) {
1660 amd_fw_table[i].filename = filename;
1661 return;
1662 }
1663 }
1664
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001665 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001666 if (amd_psp_fw_table[i].type != type)
1667 continue;
1668
1669 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001670 amd_psp_fw_table[i].filename = filename;
1671 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001672 }
1673 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001674}
1675
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001676static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1677{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001678 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001679
1680 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1681 if (amd_bios_table[i].type == type
1682 && amd_bios_table[i].inst == ins
1683 && amd_bios_table[i].subpr == sub) {
1684 amd_bios_table[i].filename = name;
1685 return;
1686 }
1687 }
1688}
1689
Ritul Gurua2cb3402022-08-29 00:51:08 +05301690static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1691 char *dst_str, char *size_str)
1692{
1693 unsigned int i;
1694
1695 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1696 if (amd_psp_fw_table[i].type != type)
1697 continue;
1698
1699 if (amd_psp_fw_table[i].subprog == sub) {
1700 if (dst_str)
1701 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1702 if (size_str)
1703 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1704 return;
1705 }
1706 }
1707}
1708
1709static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001710 char *dst_str, char *size_str)
1711{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001712 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001713 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1714 if (amd_bios_table[i].type != type)
1715 continue;
1716
1717 if (src_str)
1718 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1719 if (dst_str)
1720 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1721 if (size_str)
1722 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1723
1724 return;
1725 }
1726}
1727
Zheng Baoc3007f32022-04-03 12:53:51 +08001728static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1729 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1730 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001731{
1732 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001733 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001734 return 1;
1735 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001736
1737 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1738 * Leave as 0xffffffff for first gen */
1739 if (cb_config->second_gen) {
1740 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1741 amd_romsig->efs_gen.reserved = 0;
1742 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001743 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1744 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001745 }
1746
1747 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001748 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001749 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001750 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1751 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1752 break;
1753 case PLATFORM_RAVEN:
1754 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001755 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1756 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1757 switch (efs_spi_micron_flag) {
1758 case 0:
1759 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1760 break;
1761 case 1:
1762 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1763 break;
1764 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001765 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001766 return 1;
1767 }
1768 break;
1769 case PLATFORM_RENOIR:
1770 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001771 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001772 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001773 case PLATFORM_PHOENIX:
1774 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001775 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1776 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1777 switch (efs_spi_micron_flag) {
1778 case 0:
1779 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1780 break;
1781 case 1:
1782 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1783 break;
1784 case 2:
1785 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1786 break;
1787 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001788 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001789 return 1;
1790 }
1791 break;
1792 case PLATFORM_UNKNOWN:
1793 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001794 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001795 return 1;
1796 }
1797 return 0;
1798}
1799
Zheng Bao69ea83c2023-01-22 21:08:18 +08001800static ssize_t write_body(char *output, void *body_offset, ssize_t body_size, context *ctx)
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001801{
Zheng Bao69ea83c2023-01-22 21:08:18 +08001802 char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001803 int ret;
1804 int fd;
1805 ssize_t bytes = -1;
1806
1807 /* Create a tmp file and rename it at the end so that make does not get confused
1808 if amdfwtool is killed for some unexpected reasons. */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001809 ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
1810 output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001811 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001812 fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001813 strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001814 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001815 exit(1);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001816 } else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
1817 fprintf(stderr, "BODY File name %d > %zu\n", ret, sizeof(body_tmp_name));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001818 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001819 exit(1);
1820 }
1821
Zheng Bao69ea83c2023-01-22 21:08:18 +08001822 fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001823 if (fd < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001824 fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001825 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001826 exit(1);
1827 }
1828
Zheng Bao69ea83c2023-01-22 21:08:18 +08001829 bytes = write_from_buf_to_file(fd, body_offset, body_size);
1830 if (bytes != body_size) {
1831 fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001832 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001833 exit(1);
1834 }
1835 close(fd);
1836
1837 /* Rename the tmp file */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001838 ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001839 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001840 fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001841 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001842 exit(1);
1843 }
1844
Zheng Bao69ea83c2023-01-22 21:08:18 +08001845 if (rename(body_tmp_name, body_name)) {
1846 fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001847 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001848 exit(1);
1849 }
1850
1851 return bytes;
1852}
1853
Zheng Bao994ff522023-03-09 11:43:55 +08001854void open_process_config(char *config, amd_cb_config *cb_config, int debug)
Zheng Bao39cae562023-03-07 18:37:43 +08001855{
1856 FILE *config_handle;
1857
1858 if (config) {
1859 config_handle = fopen(config, "r");
1860 if (config_handle == NULL) {
1861 fprintf(stderr, "Can not open file %s for reading: %s\n",
1862 config, strerror(errno));
1863 exit(1);
1864 }
Zheng Bao994ff522023-03-09 11:43:55 +08001865 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001866 fprintf(stderr, "Configuration file %s parsing error\n",
1867 config);
1868 fclose(config_handle);
1869 exit(1);
1870 }
1871 fclose(config_handle);
1872 }
1873
1874 /* For debug. */
1875 if (debug) {
1876 dump_psp_firmwares(amd_psp_fw_table);
1877 dump_bdt_firmwares(amd_bios_table);
1878 }
1879}
1880
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001881static bool is_initial_alignment_required(enum platform soc_id)
1882{
1883 switch (soc_id) {
1884 case PLATFORM_MENDOCINO:
1885 case PLATFORM_PHOENIX:
1886 case PLATFORM_GLINDA:
1887 return false;
1888 default:
1889 return true;
1890 }
1891}
1892
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001893int main(int argc, char **argv)
1894{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001895 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001896 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001897 char *tmp;
Marshall Dawson239286c2019-02-23 16:42:46 -07001898 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001899 psp_directory_table *pspdir = NULL;
1900 psp_directory_table *pspdir2 = NULL;
1901 psp_directory_table *pspdir2_b = NULL;
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001902 psp_combo_directory *psp_combo_dir = NULL, *bhd_combo_dir = NULL;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001903 char *combo_config[MAX_COMBO_ENTRIES] = { 0 };
1904 int combo_index = 0;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001905 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001906 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001907 char *output = NULL, *config = NULL;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001908 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001909 /* Values cleared after each firmware or parameter, regardless if N/A */
1910 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08001911 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001912 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001913 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001914 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07001915 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001916 uint8_t efs_spi_readmode = 0xff;
1917 uint8_t efs_spi_speed = 0xff;
1918 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11001919 const char *signed_output_file = NULL;
1920 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001921
Fred Reitbergerf36b0132022-06-29 13:54:57 -04001922 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08001923 int debug = 0;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001924 char *manifest_file = NULL;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001925
Zheng Baoc26108f2023-02-17 11:01:07 +08001926 ctx.current_pointer_saved = 0xFFFFFFFF;
1927
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001928 while (1) {
1929 int optindex = 0;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001930 int bios_tbl_index = -1;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001931
1932 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1933
1934 if (c == -1)
1935 break;
1936
1937 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001938 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001939 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001940 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001941 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001942 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001943 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001944 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001945 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001946 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001947 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001948 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001949 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001950 case AMDFW_OPT_RECOVERY_AB:
1951 cb_config.recovery_ab = true;
1952 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001953 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1954 cb_config.recovery_ab = true;
1955 cb_config.recovery_ab_single_copy = true;
1956 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001957 case AMDFW_OPT_USE_COMBO:
1958 cb_config.use_combo = true;
1959 break;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001960 case AMDFW_OPT_COMBO1_CONFIG:
1961 cb_config.use_combo = true;
Zheng Bao73917222023-03-15 16:14:03 +08001962 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001963 combo_config[1] = optarg;
1964 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001965 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001966 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001967 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001968 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001969 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001970 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001971 sub = instance = 0;
1972 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001973 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001974 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001975 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001976 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001977 instance = strtoul(optarg, &tmp, 16);
1978 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001979 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001980 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001981 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001982 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001983 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001984 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001985 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001986 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001987 register_fw_fuse(optarg);
1988 fuse_defined = 1;
1989 sub = 0;
1990 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001991 case AMDFW_OPT_APCB:
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001992 if ((instance & 0xF0) == 0) {
Zheng Bao5caca942020-12-04 16:39:38 +08001993 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001994 } else {
Zheng Bao5caca942020-12-04 16:39:38 +08001995 register_bdt_data(AMD_BIOS_APCB_BK, sub,
1996 instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001997 cb_config.have_apcb_bk = 1;
1998 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001999 sub = instance = 0;
2000 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002001 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002002 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302003 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002004 sub = instance = 0;
2005 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002006 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002007 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302008 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002009 sub = instance = 0;
2010 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002011 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002012 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302013 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002014 sub = instance = 0;
2015 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002016 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002017 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2018 sub = instance = 0;
2019 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002020 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002021 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302022 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
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_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002026 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302027 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002028 sub = instance = 0;
2029 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002030 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002031 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302032 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002033 sub = instance = 0;
2034 break;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07002035 case AMDFW_OPT_BIOSBIN_UNCOMP:
2036 bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
2037 if (bios_tbl_index != -1)
2038 amd_bios_table[bios_tbl_index].zlib = 0;
2039 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302040 case LONGOPT_BIOS_SIG:
2041 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302042 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302043 sub = instance = 0;
2044 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002045 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002046 register_bdt_data(AMD_BIOS_UCODE, sub,
2047 instance, optarg);
2048 sub = instance = 0;
2049 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002050 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002051 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002052 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002053 case AMDFW_OPT_SPL_TABLE:
2054 register_fw_filename(AMD_FW_SPL, sub, optarg);
2055 sub = instance = 0;
2056 cb_config.have_mb_spl = true;
2057 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002058 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002059 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2060 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002061 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002062 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002063 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002064 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2065 sub = instance = 0;
2066 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002067 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002068 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2069 sub = instance = 0;
2070 break;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002071 case AMDFW_OPT_OUTPUT_MANIFEST:
2072 manifest_file = optarg;
2073 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002074 case AMDFW_OPT_SIGNED_OUTPUT:
2075 signed_output_file = optarg;
2076 sub = instance = 0;
2077 break;
2078 case AMDFW_OPT_SIGNED_ADDR:
2079 signed_start_addr = strtoull(optarg, NULL, 10);
2080 sub = instance = 0;
2081 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002082 case LONGOPT_SPI_READ_MODE:
2083 efs_spi_readmode = strtoull(optarg, NULL, 16);
2084 sub = instance = 0;
2085 break;
2086 case LONGOPT_SPI_SPEED:
2087 efs_spi_speed = strtoull(optarg, NULL, 16);
2088 sub = instance = 0;
2089 break;
2090 case LONGOPT_SPI_MICRON_FLAG:
2091 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2092 sub = instance = 0;
2093 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002094 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002095 output = optarg;
2096 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002097 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002098 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002099 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002100 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002101 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002102 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002103 }
2104 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002105 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002106 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002107 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002108 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002109 " incorrectly (%s)\n\n", optarg);
2110 retval = 1;
2111 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002112 if (body_location == 0)
2113 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002114 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002115 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002116 any_location = 1;
2117 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002118 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002119 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302120 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002121 sub = instance = 0;
2122 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002123 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002124 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302125 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002126 sub = instance = 0;
2127 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302128 case LONGOPT_NVRAM_BASE:
2129 /* PSP NV base */
2130 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2131 sub = instance = 0;
2132 break;
2133 case LONGOPT_NVRAM_SIZE:
2134 /* PSP NV size */
2135 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2136 sub = instance = 0;
2137 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002138 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002139 config = optarg;
2140 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002141 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002142 debug = 1;
2143 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002144 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002145 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002146 return 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002147 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002148 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002149 if (*tmp != '\0') {
2150 fprintf(stderr, "Error: Body Location specified"
2151 " incorrectly (%s)\n\n", optarg);
2152 retval = 1;
2153 }
2154 break;
2155
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002156 default:
2157 break;
2158 }
2159 }
2160
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002161 if (cb_config.use_combo) {
2162 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
2163 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
2164 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
2165 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
2166 }
2167
Zheng Bao994ff522023-03-09 11:43:55 +08002168 open_process_config(config, &cb_config, debug);
Zheng Bao9e908072020-10-28 11:39:13 +08002169
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002170 if (!fuse_defined)
2171 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2172
Zheng Bao994ff522023-03-09 11:43:55 +08002173 if (!output) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002174 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002175 retval = 1;
2176 }
2177
Zheng Baoa7731cc2023-03-11 09:27:53 +08002178 if (ctx.rom_size % 1024 != 0) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002179 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002180 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002181 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002182 }
2183
Zheng Baoa7731cc2023-03-11 09:27:53 +08002184 if (ctx.rom_size < MIN_ROM_KB * 1024) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002185 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002186 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002187 retval = 1;
2188 }
2189
2190 if (retval) {
2191 usage();
2192 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002193 }
2194
Marshall Dawson2794a862019-03-04 16:53:15 -07002195 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002196
Marshall Dawson2794a862019-03-04 16:53:15 -07002197 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Zheng Bao9770df12023-02-14 13:23:35 +08002198
2199 if (efs_location & 0xFF000000)
2200 efs_location = efs_location - rom_base_address;
2201 if (body_location & 0xFF000000)
2202 body_location = body_location - rom_base_address;
2203
2204 if (efs_location && efs_location > ctx.rom_size) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002205 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2206 return 1;
2207 }
Zheng Bao9770df12023-02-14 13:23:35 +08002208 if (body_location && body_location > ctx.rom_size) {
2209 fprintf(stderr, "Error: Body location outside of ROM.\n\n");
2210 return 1;
2211 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002212
Zheng Bao99945dc2023-01-02 10:55:56 +08002213 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002214 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2215 return 1;
2216 }
2217
Zheng Bao99945dc2023-01-02 10:55:56 +08002218 if (body_location != efs_location &&
2219 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002220 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2221 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002222 return 1;
2223 }
2224
Martin Roth37305e72020-04-07 14:16:39 -06002225 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002226 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002227 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002228 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002229 return 1;
2230 }
2231 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002232 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002233 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002234 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002235 case 0xFA0000:
2236 case 0xF20000:
2237 case 0xE20000:
2238 case 0xC20000:
2239 case 0x820000:
2240 case 0x020000:
2241 break;
2242 case 0x7A0000:
2243 case 0x720000:
2244 case 0x620000:
2245 case 0x420000:
2246 /* Special cases for 8M. */
2247 if (ctx.rom_size != 0x800000) {
2248 fprintf(stderr, "Error: Invalid Directory location.\n");
2249 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2250 return 1;
2251 }
2252 break;
2253 case 0x3A0000:
2254 case 0x320000:
2255 case 0x220000:
2256 /* Special cases for 4M. */
2257 if (ctx.rom_size != 0x400000) {
2258 fprintf(stderr, "Error: Invalid Directory location.\n");
2259 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2260 return 1;
2261 }
Martin Roth37305e72020-04-07 14:16:39 -06002262 break;
2263 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002264 fprintf(stderr, "Error: Invalid Directory location.\n");
2265 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2266 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002267 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2268 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002269 return 1;
2270 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002271 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002272 ctx.rom = malloc(ctx.rom_size);
2273 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002274 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002275 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002276 }
2277 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002278
Zheng Bao6095cd12023-02-21 10:52:47 +08002279 romsig_offset = efs_location ? efs_location : AMD_ROMSIG_OFFSET;
2280 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06002281
Marshall Dawson2794a862019-03-04 16:53:15 -07002282 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002283 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2284 amd_romsig->imc_entry = 0;
2285 amd_romsig->gec_entry = 0;
2286 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002287
Zheng Bao4bf6f492023-01-25 22:37:29 +08002288 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2289 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2290 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002291 if (retval) {
2292 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2293 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002294 }
2295 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002296 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002297 }
2298
Felix Held21a8e382022-03-29 23:10:45 +02002299 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002300 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002301 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002302 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002303 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002304 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002305 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2306 efs_location);
2307 if (body_location != efs_location)
2308 printf(" with a split body at: 0x%08x\n", body_location);
2309 else
2310 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002311
Zheng Bao6095cd12023-02-21 10:52:47 +08002312 if (efs_location != body_location)
2313 set_current_pointer(&ctx, body_location);
2314 else
2315 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
2316
Marshall Dawson2794a862019-03-04 16:53:15 -07002317 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002318
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07002319 if (is_initial_alignment_required(cb_config.soc_id)) {
2320 /* TODO: Check for older platforms. */
2321 adjust_current_pointer(&ctx, 0, 0x10000U);
2322 }
Zheng Bao6fff2492021-11-15 19:53:21 +08002323 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002324
Kangheui Won3c164e12021-12-03 20:25:05 +11002325 /* If the tool is invoked with command-line options to keep the signed PSP
2326 binaries separate, process the signed binaries first. */
2327 if (signed_output_file && signed_start_addr)
2328 process_signed_psp_firmwares(signed_output_file,
2329 amd_psp_fw_table,
2330 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002331 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002332
Zheng Baob2ae6a52022-08-18 15:45:27 +08002333 if (cb_config.use_combo) {
2334 psp_combo_dir = new_combo_dir(&ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002335
2336 adjust_current_pointer(&ctx, 0, 0x1000U);
2337
2338 bhd_combo_dir = new_combo_dir(&ctx);
Zheng Baob2ae6a52022-08-18 15:45:27 +08002339 }
2340
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002341 combo_index = 0;
2342 if (config)
2343 combo_config[0] = config;
2344
Zheng Bao4b6aa192023-03-09 11:28:47 +08002345 do {
Zheng Bao3e7008d2023-03-15 16:15:13 +08002346 if (cb_config.use_combo && debug)
2347 printf("Processing %dth combo entry\n", combo_index);
2348
Zheng Bao4b6aa192023-03-09 11:28:47 +08002349 /* for non-combo image, combo_config[0] == config, and
2350 * it already is processed. Actually "combo_index >
2351 * 0" is enough. Put both of them here to make sure
2352 * and make it clear this will not affect non-combo
2353 * case.
2354 */
2355 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002356 /* Restore the table as clean data. */
2357 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
2358 sizeof(amd_psp_fw_table));
2359 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
2360 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08002361 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08002362 open_process_config(combo_config[combo_index], &cb_config,
Zheng Bao994ff522023-03-09 11:43:55 +08002363 debug);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002364
Zheng Bao4b6aa192023-03-09 11:28:47 +08002365 /* In most cases, the address modes are same. */
2366 if (cb_config.need_ish)
2367 ctx.address_mode = AMD_ADDR_REL_TAB;
2368 else if (cb_config.second_gen)
2369 ctx.address_mode = AMD_ADDR_REL_BIOS;
2370 else
2371 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao990d1542021-09-17 13:24:54 +08002372 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002373
Zheng Bao481661e2021-08-20 14:47:46 +08002374 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002375 /* Do 2nd PSP directory followed by 1st */
2376 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2377 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
2378 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
2379 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2380 /* Create a copy of PSP Directory 2 in the backup slot B.
2381 Related biosdir2_b copy will be created later. */
2382 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2383 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
2384 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002385 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002386 /*
2387 * Either the platform is using only
2388 * one slot or B is same as above
2389 * directories for A. Skip creating
2390 * pspdir2_b here to save flash space.
2391 * Related biosdir2_b will be skipped
2392 * automatically.
2393 */
2394 pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08002395 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002396 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2397 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
2398 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002399 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002400 /* flat: PSP 1 cookie and no pointer to 2nd table */
2401 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2402 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
2403 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002404 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002405
Zheng Bao4b6aa192023-03-09 11:28:47 +08002406 if (!cb_config.use_combo) {
2407 fill_psp_directory_to_efs(amd_romsig, pspdir, &ctx, &cb_config);
2408 } else {
2409 fill_psp_directory_to_efs(amd_romsig, psp_combo_dir, &ctx, &cb_config);
2410 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2411 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2412 psp_combo_dir->entries[combo_index].id_sel = 0;
2413 psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
2414 psp_combo_dir->entries[combo_index].lvl2_addr =
2415 BUFF_TO_RUN_MODE(ctx, pspdir, AMD_ADDR_REL_BIOS);
2416
2417 fill_dir_header(psp_combo_dir, combo_index + 1, PSP2_COOKIE, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002418 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002419
2420 if (have_bios_tables(amd_bios_table)) {
2421 bios_directory_table *biosdir = NULL;
2422 if (cb_config.multi_level) {
2423 /* Do 2nd level BIOS directory followed by 1st */
2424 bios_directory_table *biosdir2 = NULL;
2425 bios_directory_table *biosdir2_b = NULL;
2426
2427 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2428
2429 integrate_bios_firmwares(&ctx, biosdir2, NULL,
2430 amd_bios_table, BHDL2_COOKIE, &cb_config);
2431 if (cb_config.recovery_ab) {
2432 if (pspdir2_b != NULL) {
2433 biosdir2_b = new_bios_dir(&ctx,
2434 cb_config.multi_level);
2435 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
2436 amd_bios_table, BHDL2_COOKIE,
2437 &cb_config);
2438 }
2439 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2440 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2441 if (pspdir2_b != NULL)
2442 add_psp_firmware_entry(&ctx, pspdir2_b,
2443 biosdir2_b, AMD_FW_BIOS_TABLE,
2444 TABLE_ALIGNMENT);
2445 } else {
2446 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2447 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
2448 amd_bios_table, BHD_COOKIE, &cb_config);
2449 }
2450 } else {
2451 /* flat: BHD1 cookie and no pointer to 2nd table */
2452 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2453 integrate_bios_firmwares(&ctx, biosdir, NULL,
2454 amd_bios_table, BHD_COOKIE, &cb_config);
2455 }
2456 if (!cb_config.use_combo) {
2457 fill_bios_directory_to_efs(amd_romsig, biosdir,
2458 &ctx, &cb_config);
2459 } else {
2460 fill_bios_directory_to_efs(amd_romsig, bhd_combo_dir,
2461 &ctx, &cb_config);
2462 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2463 bhd_combo_dir->entries[combo_index].id_sel = 0;
2464 bhd_combo_dir->entries[combo_index].id =
2465 get_psp_id(cb_config.soc_id);
2466 bhd_combo_dir->entries[combo_index].lvl2_addr =
2467 BUFF_TO_RUN_MODE(ctx, biosdir, AMD_ADDR_REL_BIOS);
2468
2469 fill_dir_header(bhd_combo_dir, combo_index + 1,
2470 BHD2_COOKIE, &ctx);
2471 }
2472 }
Zheng Bao17551ae2023-03-11 10:29:56 +08002473 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
2474 combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002475
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002476 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002477 if (targetfd >= 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08002478 uint32_t offset = efs_location;
2479 uint32_t bytes = efs_location == body_location ?
2480 ctx.current - offset : sizeof(*amd_romsig);
2481 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002482
Zheng Baoc25d5932023-03-22 12:51:47 +08002483 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08002484 if (bytes != ret_bytes) {
Zheng Bao47396912020-09-29 17:33:17 +08002485 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2486 retval = 1;
2487 }
Martin Roth31d95a22016-11-08 11:22:12 -07002488 close(targetfd);
2489 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002490 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002491 retval = 1;
2492 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002493
Zheng Bao99945dc2023-01-02 10:55:56 +08002494 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002495 ssize_t bytes;
2496
Zheng Bao69ea83c2023-01-22 21:08:18 +08002497 bytes = write_body(output, BUFF_OFFSET(ctx, body_location),
2498 ctx.current - body_location, &ctx);
2499 if (bytes != ctx.current - body_location) {
2500 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002501 retval = 1;
2502 }
2503 }
2504
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002505 if (manifest_file) {
2506 dump_blob_version(manifest_file, amd_psp_fw_table);
2507 }
2508
Zheng Bao7c5ad882023-02-19 13:02:52 +08002509 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07002510 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002511}