blob: 6822b2ad3e8609dcaace7de293b5d8f72aafacf8 [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 Bao1a0c99f2023-02-11 15:17:22 +080091#define MAX_MAPPED_WINDOW (16 * MiB)
92#define MAX_MAPPED_WINDOW_MASK (MAX_MAPPED_WINDOW - 1)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080093
Marshall Dawson7c1e1422019-04-11 09:44:43 -060094#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080095
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060096#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
97
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060098#define EFS_FILE_SUFFIX ".efs"
99#define TMP_FILE_SUFFIX ".tmp"
Zheng Bao69ea83c2023-01-22 21:08:18 +0800100#define BODY_FILE_SUFFIX ".body"
Kangheui Won5b84dfd2021-12-21 15:45:06 +1100101
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000102static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry);
103
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800104/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700105 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
106 * can support an optional "combo" implementation. If the PSP sees the
107 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
108 * tables. Using this, support for multiple product generations may be
109 * built into one image. If the PSP$ cookie is found, the table is a
110 * normal directory table.
111 *
112 * Modern generations supporting the combo directories require the
113 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
Zheng Baoc91867a2023-02-26 12:31:31 +0800114 * regardless of the type of directory used. The --use-combo
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700115 * argument enforces this placement.
116 *
117 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800118 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800119
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800120/*
121 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
122 * The checksum field of the passed PDU does not need to be reset to zero.
123 *
124 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
125 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
126 * alternative to cyclical redundancy checks because it provides error-
127 * detection properties similar to cyclical redundancy checks but at the
128 * cost of a simple summation technique. Its characteristics were first
129 * published in IEEE Transactions on Communications in January 1982. One
130 * version has been adopted by ISO for use in the class-4 transport layer
131 * of the network protocol.
132 *
133 * This program expects:
134 * stdin: The input file to compute a checksum for. The input file
135 * not be longer than 256 bytes.
136 * stdout: Copied from the input file with the Fletcher's Checksum
137 * inserted 8 bytes after the beginning of the file.
138 * stderr: Used to print out error messages.
139 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700140static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800141{
142 uint32_t c0;
143 uint32_t c1;
144 uint32_t checksum;
145 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700146 const uint16_t *pptr = data;
147
148 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800149
150 c0 = 0xFFFF;
151 c1 = 0xFFFF;
152
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600153 while (length) {
154 index = length >= 359 ? 359 : length;
155 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800156 do {
157 c0 += *(pptr++);
158 c1 += c0;
159 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600160 c0 = (c0 & 0xFFFF) + (c0 >> 16);
161 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800162 }
163
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700164 /* Sums[0,1] mod 64K + overflow */
165 c0 = (c0 & 0xFFFF) + (c0 >> 16);
166 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800167 checksum = (c1 << 16) | c0;
168
169 return checksum;
170}
171
Martin Roth8806f7f2016-11-08 10:44:18 -0700172static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800173{
Martin Roth0e940622016-11-08 10:37:53 -0700174 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800175 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
176 printf("--xhci <FILE> Add XHCI blob\n");
177 printf("--imc <FILE> Add IMC blob\n");
178 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700179
180 printf("\nPSP options:\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800181 printf("--use-combo Use the COMBO layout\n");
Zheng Baoe3ebc4f2023-03-23 10:52:59 +0800182 printf("--combo-config1 <config file> Config for 1st combo entry\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800183 printf("--multilevel Generate primary and secondary tables\n");
184 printf("--nvram <FILE> Add nvram binary\n");
185 printf("--soft-fuse Set soft fuse\n");
186 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530187 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
188 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800189 printf("--whitelist Set if there is a whitelist\n");
190 printf("--use-pspsecureos Set if psp secure OS is needed\n");
191 printf("--load-mp2-fw Set if load MP2 firmware\n");
192 printf("--load-s0i3 Set if load s0i3 firmware\n");
193 printf("--verstage <FILE> Add verstage\n");
194 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800195 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600196 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800197 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800198 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800199 printf("--apcb <FILE> Add AGESA PSP customization block\n");
Zheng Baofa259542021-10-26 19:46:55 +0800200 printf("--apcb-combo1 <FILE> Add APCB for 1st combo\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800201 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
202 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
203 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
204 printf("--ucode <FILE> Add microcode patch\n");
205 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
206 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
207 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
208 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
209 printf("--output <filename> output filename\n");
210 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600211 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700212 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600213 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800214 printf("--location Location of Directory\n");
215 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
216 printf("--sharedmem Location of PSP/FW shared memory\n");
217 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800218 printf(" area\n");
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000219 printf("--output-manifest <FILE> Writes a manifest with the blobs versions\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500220 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
221 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
222 printf(" 0x0 66.66Mhz\n");
223 printf(" 0x1 33.33MHz\n");
224 printf(" 0x2 22.22MHz\n");
225 printf(" 0x3 16.66MHz\n");
226 printf(" 0x4 100MHz\n");
227 printf(" 0x5 800KHz\n");
228 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
229 printf(" 0x0 Normal Read (up to 33M)\n");
230 printf(" 0x1 Reserved\n");
231 printf(" 0x2 Dual IO (1-1-2)\n");
232 printf(" 0x3 Quad IO (1-1-4)\n");
233 printf(" 0x4 Dual IO (1-2-2)\n");
234 printf(" 0x5 Quad IO (1-4-4)\n");
235 printf(" 0x6 Normal Read (up to 66M)\n");
236 printf(" 0x7 Fast Read\n");
237 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
238 printf(" 0x0 Micron parts are not used\n");
239 printf(" 0x1 Micron parts are always used\n");
240 printf(" 0x2 Micron parts optional, this option is only\n");
241 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800242 printf("\nGeneral options:\n");
243 printf("-c|--config <config file> Config file\n");
244 printf("-d|--debug Print debug message\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800245 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800246}
247
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800248amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100249 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000250 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000251 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800252 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200253 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800254 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200255 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000256 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB,
257 .generate_manifest = true },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200258 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800259 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100260 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
261 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200262 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000263 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800264 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
265 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000266 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200267 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
268 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800269 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
270 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
271 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
272 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000273 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao9bb62cb2023-03-07 19:48:11 +0800274 { .type = AMD_HW_IPCFG, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
275 { .type = AMD_HW_IPCFG, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100276 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800277 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
278 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800279 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200280 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800281 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200282 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
283 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800284 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
285 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200286 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
287 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
288 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800289 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000290 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB,
291 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800292 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
293 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
294 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
295 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
296 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
297 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
298 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200299 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
300 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600301 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200302 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200303 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200304 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
305 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
306 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
307 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
308 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600309 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
310 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200311 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000312 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200313 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
314 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
315 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
316 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Nikolai Vyssotskibfc9ca72023-03-07 15:09:09 -0600317 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800318 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200319 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000320 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB,
321 .generate_manifest = true },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800322 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200324 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200325 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200326 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
327 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800328 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
329 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
330 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
331 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
332 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
333 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
334 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
335 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
336 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
337 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
338 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
339 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
340 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
341 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500342 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800343 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800344};
345
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800346amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800347 { .type = AMD_FW_XHCI },
348 { .type = AMD_FW_IMC },
349 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800350 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800351};
352
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800353amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800354 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530355 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600356 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
357 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700361 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
362 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
366 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700372 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700377 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
378 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
379 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
380 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
381 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
382 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
383 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
384 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
385 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
386 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
387 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600388 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
389 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800390 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600391 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
392 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
393 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800394 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
395 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200396 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
397 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600398 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
399 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800400 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
401 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
403 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
405 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200406 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
407 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
409 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800410 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
411 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
413 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
415 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600416 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800418 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
419 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200420 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600422 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
423 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800424 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
425 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
427 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
429 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200430 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
431 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
432 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
433 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800434 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
435 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
436 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
437 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
438 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
439 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600440 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
441 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
442 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200443 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
444 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
445 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
446 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600447 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600448 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600449 { .type = AMD_BIOS_INVALID },
450};
451
Marshall Dawson2794a862019-03-04 16:53:15 -0700452typedef struct _context {
453 char *rom; /* target buffer, size of flash device */
454 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800455 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700456 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Baoc26108f2023-02-17 11:01:07 +0800457 uint32_t current_pointer_saved;
Zheng Bao6fff2492021-11-15 19:53:21 +0800458 uint32_t current_table;
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800459 void *amd_psp_fw_table_clean;
460 void *amd_bios_table_clean;
Marshall Dawson2794a862019-03-04 16:53:15 -0700461} context;
462
463#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800464#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600465 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
466 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
Zheng Baoc38f7642023-02-21 10:43:08 +0800467 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800468#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600469#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800470 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700471#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800472/* The mode in entry can not be higher than the header's.
473 For example, if table mode is 0, all the entry mode will be 0. */
474#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
475 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700476#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
477#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
478#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800479#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
480 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700481#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800482/* Only set the address mode in entry if the table is mode 2. */
483#define SET_ADDR_MODE(table, mode) \
484 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600485 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800486#define SET_ADDR_MODE_BY_TABLE(table) \
487 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700488
Zheng Bao7c5ad882023-02-19 13:02:52 +0800489
490static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
491{
492 amd_fw_entry *index;
493
494 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
495 if (index->filename &&
496 index->type != AMD_FW_VERSTAGE_SIG &&
497 index->type != AMD_FW_PSP_VERSTAGE &&
498 index->type != AMD_FW_SPL &&
499 index->type != AMD_FW_PSP_WHITELIST) {
500 free(index->filename);
501 index->filename = NULL;
502 }
503 }
504}
505
506static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
507{
508 amd_bios_entry *index;
509
510 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
511 if (index->filename &&
512 index->type != AMD_BIOS_APCB &&
513 index->type != AMD_BIOS_BIN &&
514 index->type != AMD_BIOS_APCB_BK &&
515 index->type != AMD_BIOS_UCODE) {
516 free(index->filename);
517 index->filename = NULL;
518 }
519 }
520}
521
522static void amdfwtool_cleanup(context *ctx)
523{
524 free(ctx->rom);
525 ctx->rom = NULL;
526
527 /* Free the filename. */
528 free_psp_firmware_filenames(amd_psp_fw_table);
529 free_bdt_firmware_filenames(amd_bios_table);
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800530
531 free(ctx->amd_psp_fw_table_clean);
532 ctx->amd_psp_fw_table_clean = NULL;
533 free(ctx->amd_bios_table_clean);
534 ctx->amd_bios_table_clean = NULL;
Zheng Bao7c5ad882023-02-19 13:02:52 +0800535}
536
Zheng Bao5164e4b2021-10-30 12:09:07 +0800537void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
538{
539 if (count >= max) {
540 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
541 "(%d)\n", count, max);
Zheng Bao7c5ad882023-02-19 13:02:52 +0800542 amdfwtool_cleanup(ctx);
Zheng Bao5164e4b2021-10-30 12:09:07 +0800543 exit(1);
544 }
545}
546
Zheng Baoc26108f2023-02-17 11:01:07 +0800547static void set_current_pointer(context *ctx, uint32_t value)
548{
549 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
550 ctx->current_pointer_saved != ctx->current) {
551 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800552 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800553 exit(1);
554 }
555
556 ctx->current = value;
557
558 if (ctx->current > ctx->rom_size) {
559 fprintf(stderr, "Error: Packing data causes overflow\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800560 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800561 exit(1);
562 }
563
564 ctx->current_pointer_saved = ctx->current;
565}
566
567static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
568{
569 /* Get */
570 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
571}
572
Marshall Dawson24f73d42019-04-01 10:48:43 -0600573static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700574{
575 void *ptr;
576
Marshall Dawson24f73d42019-04-01 10:48:43 -0600577 /*
578 * Force both onto boundary when multi. Primary table is after
579 * updatable table, so alignment ensures primary can stay intact
580 * if secondary is reprogrammed.
581 */
582 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +0800583 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600584 else
Zheng Baoc26108f2023-02-17 11:01:07 +0800585 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600586
Marshall Dawson2794a862019-03-04 16:53:15 -0700587 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800588 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800589 ((psp_directory_header *)ptr)->additional_info = 0;
590 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +0800591 adjust_current_pointer(ctx,
592 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
593 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700594 return ptr;
595}
596
Zheng Baofdd47ef2021-09-17 13:30:08 +0800597static void *new_ish_dir(context *ctx)
598{
599 void *ptr;
Zheng Baoc26108f2023-02-17 11:01:07 +0800600 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800601 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800602 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
603
Zheng Baofdd47ef2021-09-17 13:30:08 +0800604 return ptr;
605}
606
Marshall Dawson2794a862019-03-04 16:53:15 -0700607static void *new_combo_dir(context *ctx)
608{
609 void *ptr;
610
Zheng Baoc26108f2023-02-17 11:01:07 +0800611 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700612 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800613 adjust_current_pointer(ctx,
614 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
615 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700616 return ptr;
617}
618
Zheng Baobf29a0d2020-12-03 23:00:48 +0800619static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800620{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600621 psp_combo_directory *cdir = directory;
622 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600623 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800624 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600625
626 if (!count)
627 return;
Zheng Baob035f582021-05-27 11:26:12 +0800628 if (ctx == NULL || directory == NULL) {
629 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
630 return;
631 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600632
Zheng Baobf29a0d2020-12-03 23:00:48 +0800633 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baoc26108f2023-02-17 11:01:07 +0800634 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800635
Marshall Dawson24f73d42019-04-01 10:48:43 -0600636 switch (cookie) {
637 case PSP2_COOKIE:
Zheng Bao84fb9ea2022-08-18 15:54:47 +0800638 case BHD2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700639 cdir->header.cookie = cookie;
Zheng Baofd51af62022-08-18 15:26:39 +0800640 /* lookup mode is hardcoded for now. */
641 cdir->header.lookup = 1;
Marshall Dawsona378c222019-03-04 16:52:07 -0700642 cdir->header.num_entries = count;
643 cdir->header.reserved[0] = 0;
644 cdir->header.reserved[1] = 0;
645 /* checksum everything that comes after the Checksum field */
646 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
647 count * sizeof(psp_combo_entry)
648 + sizeof(cdir->header.num_entries)
649 + sizeof(cdir->header.lookup)
650 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600651 break;
652 case PSP_COOKIE:
653 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800654 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800655 if ((table_size % TABLE_ALIGNMENT) != 0) {
656 fprintf(stderr, "The PSP table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800657 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800658 exit(1);
659 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700660 dir->header.cookie = cookie;
661 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800662 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
663 dir->header.additional_info_fields.spi_block_size = 1;
664 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700665 /* checksum everything that comes after the Checksum field */
666 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700667 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700668 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800669 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600670 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800671 case BHD_COOKIE:
672 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800673 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800674 if ((table_size % TABLE_ALIGNMENT) != 0) {
675 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800676 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800677 exit(1);
678 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600679 bdir->header.cookie = cookie;
680 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800681 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
682 bdir->header.additional_info_fields.spi_block_size = 1;
683 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600684 /* checksum everything that comes after the Checksum field */
685 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
686 count * sizeof(bios_directory_entry)
687 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800688 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600689 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700690 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800691
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800692}
693
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800694static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
695 context *ctx, amd_cb_config *cb_config)
696{
697 switch (cb_config->soc_id) {
698 case PLATFORM_UNKNOWN:
699 amd_romsig->psp_directory =
700 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
701 break;
702 case PLATFORM_CEZANNE:
703 case PLATFORM_MENDOCINO:
704 case PLATFORM_PHOENIX:
705 case PLATFORM_GLINDA:
706 case PLATFORM_CARRIZO:
707 case PLATFORM_STONEYRIDGE:
708 case PLATFORM_RAVEN:
709 case PLATFORM_PICASSO:
710 case PLATFORM_LUCIENNE:
711 case PLATFORM_RENOIR:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200712 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800713 default:
714 /* for combo, it is also combo_psp_directory */
715 amd_romsig->new_psp_directory =
716 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
717 break;
718 }
719}
720
721static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
722 context *ctx, amd_cb_config *cb_config)
723{
724 switch (cb_config->soc_id) {
725 case PLATFORM_RENOIR:
726 case PLATFORM_LUCIENNE:
727 case PLATFORM_CEZANNE:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200728 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800729 if (!cb_config->recovery_ab)
730 amd_romsig->bios3_entry =
731 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
732 break;
733 case PLATFORM_MENDOCINO:
734 case PLATFORM_PHOENIX:
735 case PLATFORM_GLINDA:
736 break;
737 case PLATFORM_CARRIZO:
738 case PLATFORM_STONEYRIDGE:
739 case PLATFORM_RAVEN:
740 case PLATFORM_PICASSO:
741 default:
742 amd_romsig->bios1_entry =
743 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
744 break;
745 }
746}
747
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700748static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
749{
750 int fd;
751 struct stat fd_stat;
752 ssize_t bytes;
753
754 fd = open(src_file, O_RDONLY);
755 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800756 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700757 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700758 return -1;
759 }
760
761 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800762 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600763 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700764 return -2;
765 }
766
Zheng Bao6d402ac2020-10-01 16:16:30 +0800767 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800768 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600769 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700770 return -3;
771 }
772
773 bytes = read(fd, dest, (size_t)fd_stat.st_size);
774 close(fd);
775 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800776 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700777 return -4;
778 }
779
780 return bytes;
781}
782
Zheng Baoeb0404e2021-10-14 15:09:09 +0800783static uint32_t get_psp_id(enum platform soc_id)
784{
785 uint32_t psp_id;
786 switch (soc_id) {
787 case PLATFORM_RAVEN:
788 case PLATFORM_PICASSO:
789 psp_id = 0xBC0A0000;
790 break;
791 case PLATFORM_RENOIR:
792 case PLATFORM_LUCIENNE:
793 psp_id = 0xBC0C0000;
794 break;
795 case PLATFORM_CEZANNE:
796 psp_id = 0xBC0C0140;
797 break;
798 case PLATFORM_MENDOCINO:
799 psp_id = 0xBC0D0900;
800 break;
801 case PLATFORM_STONEYRIDGE:
802 psp_id = 0x10220B00;
803 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800804 case PLATFORM_GLINDA:
805 psp_id = 0xBC0E0200;
806 break;
807 case PLATFORM_PHOENIX:
808 psp_id = 0xBC0D0400;
809 break;
Arthur Heymans563f7af2023-07-13 11:40:08 +0200810 case PLATFORM_GENOA:
811 psp_id = 0xBC0C0111;
812 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800813 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800814 default:
815 psp_id = 0;
816 break;
817 }
818 return psp_id;
819}
820
Marshall Dawson2794a862019-03-04 16:53:15 -0700821static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700822 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700823 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800824{
Richard Spiegel137484d2018-01-17 10:23:19 -0700825 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800826 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700827
Zheng Baoc26108f2023-02-17 11:01:07 +0800828 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800829
Martin Rothcd15bc82016-11-08 11:34:02 -0700830 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800831 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800832 switch (fw_table[i].type) {
833 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800834 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700835 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800836 break;
837 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700838 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800839 break;
840 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700841 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800842 break;
843 default:
844 /* Error */
845 break;
846 }
847
Marshall Dawson2794a862019-03-04 16:53:15 -0700848 bytes = copy_blob(BUFF_CURRENT(*ctx),
849 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600850 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800851 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700852 exit(1);
853 }
854
Zheng Baoc26108f2023-02-17 11:01:07 +0800855 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800856 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800857 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800858}
859
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000860static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
861{
862 struct amd_fw_header hdr;
863 int blob_fd;
864 ssize_t bytes;
865
866 blob_fd = open(fw_entry->filename, O_RDONLY);
867 if (blob_fd < 0) {
868 fprintf(stderr, "Error opening file: %s: %s\n",
869 fw_entry->filename, strerror(errno));
870 return;
871 }
872
873 bytes = read(blob_fd, &hdr, sizeof(hdr));
874 if (bytes != sizeof(hdr)) {
875 close(blob_fd);
876 fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
877 return;
878 }
879
880 dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
881 fw_entry->type, hdr.version[3], hdr.version[2],
882 hdr.version[1], hdr.version[0]);
883
884 close(blob_fd);
885
886}
887
888static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
889{
890 amd_fw_entry *index;
891 int manifest_fd;
892
893 manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
894 if (manifest_fd < 0) {
895 fprintf(stderr, "Error opening file: %s: %s\n",
896 manifest_file, strerror(errno));
897 return;
898 }
899
900 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
901 if (!(index->filename))
902 continue;
903
904 if (index->generate_manifest == true)
905 output_manifest(manifest_fd, index);
906 }
907
908 close(manifest_fd);
909}
910
Zheng Bao9e908072020-10-28 11:39:13 +0800911/* For debugging */
912static void dump_psp_firmwares(amd_fw_entry *fw_table)
913{
914 amd_fw_entry *index;
915
Zheng Bao29514472023-08-25 19:12:47 +0800916 printf("PSP firmware components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800917 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
Zheng Bao730c3ba2023-08-25 19:20:37 +0800918 if (index->type == AMD_PSP_FUSE_CHAIN)
919 printf(" %2x: level=%x, subprog=%x, inst=%x\n",
920 index->type, index->level, index->subprog, index->inst);
921 else if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800922 printf(" %2x: level=%x, subprog=%x, inst=%x, %s\n",
923 index->type, index->level, index->subprog, index->inst,
924 index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800925 }
926}
927
928static void dump_bdt_firmwares(amd_bios_entry *fw_table)
929{
930 amd_bios_entry *index;
931
Zheng Bao29514472023-08-25 19:12:47 +0800932 printf("BIOS Directory Table (BDT) components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800933 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
934 if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800935 printf(" %2x: level=%x, %s\n",
936 index->type, index->level, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800937 }
938}
939
Zheng Bao990d1542021-09-17 13:24:54 +0800940static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800941 psp_directory_table *pspdir2, ish_directory_table *ish,
942 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800943{
944 uint32_t count;
945 uint32_t current_table_save;
946
947 current_table_save = ctx->current_table;
948 ctx->current_table = (char *)pspdir - ctx->rom;
949 count = pspdir->header.num_entries;
950 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
951 pspdir->entries[count].type = (uint8_t)ab;
952 pspdir->entries[count].subprog = 0;
953 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800954 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600955 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800956 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
957 ish->update_retry_count = 2;
958 ish->glitch_retry_count = 0;
959 ish->psp_id = get_psp_id(soc_id);
960 ish->checksum = fletcher32(&ish->boot_priority,
961 sizeof(ish_directory_table) - sizeof(uint32_t));
962 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600963 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800964 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600965 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800966 pspdir->entries[count].size = TABLE_ALIGNMENT;
967 } else {
968 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600969 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800970 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600971 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao948c0b72023-05-11 10:03:46 +0800972 pspdir->entries[count].size = _MAX(TABLE_ALIGNMENT,
973 pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800974 sizeof(psp_directory_entry) +
Zheng Bao948c0b72023-05-11 10:03:46 +0800975 sizeof(psp_directory_header));
Zheng Baofdd47ef2021-09-17 13:30:08 +0800976 }
Zheng Bao990d1542021-09-17 13:24:54 +0800977
978 count++;
979 pspdir->header.num_entries = count;
980 ctx->current_table = current_table_save;
981}
982
Marshall Dawson2794a862019-03-04 16:53:15 -0700983static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700984 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600985 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800986 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600987 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800988 uint32_t cookie,
989 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800990{
Richard Spiegel137484d2018-01-17 10:23:19 -0700991 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700992 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600993 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530994 uint32_t size;
995 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800996 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800997 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800998 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Fred Reitberger9d6008e2023-05-05 13:40:50 -0400999 bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
Marshall Dawson24f73d42019-04-01 10:48:43 -06001000
1001 /* This function can create a primary table, a secondary table, or a
1002 * flattened table which contains all applicable types. These if-else
1003 * statements infer what the caller intended. If a 2nd-level cookie
1004 * is passed, clearly a 2nd-level table is intended. However, a
1005 * 1st-level cookie may indicate level 1 or flattened. If the caller
1006 * passes a pointer to a 2nd-level table, then assume not flat.
1007 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001008 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001009 level = PSP_BOTH;
1010 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -06001011 level = PSP_LVL2;
1012 else if (pspdir2)
1013 level = PSP_LVL1;
1014 else
1015 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -07001016
Zheng Bao990d1542021-09-17 13:24:54 +08001017 if (recovery_ab) {
1018 if (cookie == PSPL2_COOKIE)
1019 level = PSP_LVL2_AB;
1020 else if (pspdir2)
1021 level = PSP_LVL1_AB;
1022 else
1023 level = PSP_BOTH_AB;
1024 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001025 current_table_save = ctx->current_table;
1026 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +08001027 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001028
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001029 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -06001030 if (!(fw_table[i].level & level))
1031 continue;
1032
Zheng Bao5164e4b2021-10-30 12:09:07 +08001033 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1034
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001035 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1036 if (!fw_table[i].other)
1037 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +08001038 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001039 pspdir->entries[count].type = fw_table[i].type;
1040 pspdir->entries[count].size = 4096; /* TODO: doc? */
1041 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001042 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001043 pspdir->entries[count].subprog = fw_table[i].subprog;
1044 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +08001045 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001046 count++;
1047 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001048 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001049 pspdir->entries[count].subprog = fw_table[i].subprog;
1050 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001051 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001052 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001053 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001054 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001055 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301056 if (fw_table[i].filename == NULL) {
1057 if (fw_table[i].size == 0)
1058 continue;
1059 size = fw_table[i].size;
1060 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001061 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301062 fprintf(stderr,
1063 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001064 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301065 exit(1);
1066 }
1067 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +08001068 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301069 bytes = copy_blob(BUFF_CURRENT(*ctx),
1070 fw_table[i].filename, BUFF_ROOM(*ctx));
1071 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001072 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301073 exit(1);
1074 }
1075
Elyes Haouas7d67a192022-10-14 09:58:29 +02001076 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301077 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001078 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001079 }
1080
1081 pspdir->entries[count].type = fw_table[i].type;
1082 pspdir->entries[count].subprog = fw_table[i].subprog;
1083 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301084 pspdir->entries[count].size = size;
1085 pspdir->entries[count].addr = addr;
1086
Zheng Bao6fff2492021-11-15 19:53:21 +08001087 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001088 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001089
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001090 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001091 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001092 if (fw_table[i].addr_signed) {
1093 pspdir->entries[count].addr =
1094 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1095 pspdir->entries[count].address_mode =
1096 SET_ADDR_MODE_BY_TABLE(pspdir);
1097 bytes = fw_table[i].file_size;
1098 } else {
1099 bytes = copy_blob(BUFF_CURRENT(*ctx),
1100 fw_table[i].filename, BUFF_ROOM(*ctx));
1101 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001102 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001103 exit(1);
1104 }
1105 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1106 pspdir->entries[count].address_mode =
1107 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001108 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001109 }
1110
Marshall Dawson239286c2019-02-23 16:42:46 -07001111 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001112 pspdir->entries[count].subprog = fw_table[i].subprog;
1113 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001114 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001115 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001116
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001117 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001118 } else {
1119 /* This APU doesn't have this firmware. */
1120 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001121 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001122
Zheng Bao990d1542021-09-17 13:24:54 +08001123 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001124 if (cb_config->need_ish) { /* Need ISH */
1125 ish_a_dir = new_ish_dir(ctx);
1126 if (pspdir2_b != NULL)
1127 ish_b_dir = new_ish_dir(ctx);
1128 }
Zheng Bao990d1542021-09-17 13:24:54 +08001129 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001130 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001131 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001132 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001133 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001134 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1135 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001136 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001137 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Fred Reitberger9d6008e2023-05-05 13:40:50 -04001138 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
1139 cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001140
Zheng Bao990d1542021-09-17 13:24:54 +08001141 count = pspdir->header.num_entries;
1142 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001143 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001144 pspdir->entries[count].type = AMD_FW_L2_PTR;
1145 pspdir->entries[count].subprog = 0;
1146 pspdir->entries[count].rsvd = 0;
1147 pspdir->entries[count].size = sizeof(pspdir2->header)
1148 + pspdir2->header.num_entries
1149 * sizeof(psp_directory_entry);
1150
Zheng Bao6fff2492021-11-15 19:53:21 +08001151 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001152 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001153 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001154 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001155 count++;
1156 }
1157
Zheng Baobf29a0d2020-12-03 23:00:48 +08001158 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001159 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001160}
1161
Zheng Bao990d1542021-09-17 13:24:54 +08001162static void add_psp_firmware_entry(context *ctx,
1163 psp_directory_table *pspdir,
1164 void *table, amd_fw_type type, uint32_t size)
1165{
1166 uint32_t count = pspdir->header.num_entries;
1167 uint32_t index;
1168 uint32_t current_table_save;
1169
1170 current_table_save = ctx->current_table;
1171 ctx->current_table = (char *)pspdir - ctx->rom;
1172
1173 /* If there is an entry of "type", replace it. */
1174 for (index = 0; index < count; index++) {
1175 if (pspdir->entries[index].type == (uint8_t)type)
1176 break;
1177 }
1178
1179 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1180 pspdir->entries[index].type = (uint8_t)type;
1181 pspdir->entries[index].subprog = 0;
1182 pspdir->entries[index].rsvd = 0;
1183 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1184 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1185 pspdir->entries[index].size = size;
1186 if (index == count)
1187 count++;
1188
1189 pspdir->header.num_entries = count;
1190 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1191 count * sizeof(psp_directory_entry)
1192 + sizeof(pspdir->header.num_entries)
1193 + sizeof(pspdir->header.additional_info));
1194
1195 ctx->current_table = current_table_save;
1196}
1197
Zheng Baoba3af5e2021-11-04 18:56:47 +08001198static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001199{
1200 void *ptr;
1201
1202 /*
1203 * Force both onto boundary when multi. Primary table is after
1204 * updatable table, so alignment ensures primary can stay intact
1205 * if secondary is reprogrammed.
1206 */
1207 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001208 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001209 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001210 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001211 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001212 ((bios_directory_hdr *) ptr)->additional_info = 0;
1213 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1214 ctx->current_table = ctx->current;
Zheng Baoc26108f2023-02-17 11:01:07 +08001215 adjust_current_pointer(ctx,
1216 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1217 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001218 return ptr;
1219}
1220
1221static int locate_bdt2_bios(bios_directory_table *level2,
1222 uint64_t *source, uint32_t *size)
1223{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001224 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001225
1226 *source = 0;
1227 *size = 0;
1228 if (!level2)
1229 return 0;
1230
1231 for (i = 0 ; i < level2->header.num_entries ; i++) {
1232 if (level2->entries[i].type == AMD_BIOS_BIN) {
1233 *source = level2->entries[i].source;
1234 *size = level2->entries[i].size;
1235 return 1;
1236 }
1237 }
1238 return 0;
1239}
1240
1241static int have_bios_tables(amd_bios_entry *table)
1242{
1243 int i;
1244
1245 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1246 if (table[i].level & BDT_LVL1 && table[i].filename)
1247 return 1;
1248 }
1249 return 0;
1250}
1251
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001252static int find_bios_entry(amd_bios_type type)
1253{
1254 int i;
1255
1256 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1257 if (amd_bios_table[i].type == type)
1258 return i;
1259 }
1260 return -1;
1261}
1262
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001263static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1264 int inst, uint32_t size, uint64_t source)
1265{
1266 int i;
1267
1268 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1269 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1270 amd_bios_table[i].inst == inst)
1271 break;
1272 }
1273
1274 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1275 return;
1276
1277 biosdir->entries[idx].type = amd_bios_table[i].type;
1278 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1279 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1280 amd_bios_table[i].dest : (uint64_t)-1;
1281 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1282 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1283 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1284 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1285 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1286 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1287 biosdir->entries[idx].size = size;
1288 biosdir->entries[idx].source = source;
1289 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1290}
1291
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001292static void integrate_bios_firmwares(context *ctx,
1293 bios_directory_table *biosdir,
1294 bios_directory_table *biosdir2,
1295 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001296 uint32_t cookie,
1297 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001298{
1299 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001300 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001301 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001302 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001303 uint32_t size;
1304 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001305
1306 /* This function can create a primary table, a secondary table, or a
1307 * flattened table which contains all applicable types. These if-else
1308 * statements infer what the caller intended. If a 2nd-level cookie
1309 * is passed, clearly a 2nd-level table is intended. However, a
1310 * 1st-level cookie may indicate level 1 or flattened. If the caller
1311 * passes a pointer to a 2nd-level table, then assume not flat.
1312 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001313 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001314 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001315 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001316 level = BDT_LVL2;
1317 else if (biosdir2)
1318 level = BDT_LVL1;
1319 else
1320 level = BDT_BOTH;
1321
Zheng Baoc26108f2023-02-17 11:01:07 +08001322 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001323
1324 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1325 if (!(fw_table[i].level & level))
1326 continue;
1327 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301328 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001329 fw_table[i].type != AMD_BIOS_APOB &&
1330 fw_table[i].type != AMD_BIOS_APOB_NV &&
1331 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001332 fw_table[i].type != AMD_BIOS_BIN &&
1333 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001334 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001335
1336 /* BIOS Directory items may have additional requirements */
1337
Ritul Guru9a321f32022-07-29 11:06:40 +05301338 /* SIG needs a size, else no choice but to skip */
1339 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1340 continue;
1341
Martin Roth48dd9fe2020-07-29 16:32:25 -06001342 /* Check APOB_NV requirements */
1343 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1344 if (!fw_table[i].size && !fw_table[i].src)
1345 continue; /* APOB_NV not used */
1346 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001347 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001348 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001349 exit(1);
1350 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001351 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001352 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001353 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1354 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001355 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001356
1357 /* APOB_DATA needs destination */
1358 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001359 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001360 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001361 exit(1);
1362 }
1363
1364 /* BIOS binary must have destination and uncompressed size. If
1365 * no filename given, then user must provide a source address.
1366 */
1367 if (fw_table[i].type == AMD_BIOS_BIN) {
1368 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001369 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001370 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001371 exit(1);
1372 }
1373 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001374 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001375 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001376 exit(1);
1377 }
1378 }
1379
Martin Roth94554742020-04-14 14:59:36 -06001380 /* PSP_SHARED_MEM needs a destination and size */
1381 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1382 (!fw_table[i].dest || !fw_table[i].size))
1383 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001384 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001385
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001386 biosdir->entries[count].type = fw_table[i].type;
1387 biosdir->entries[count].region_type = fw_table[i].region_type;
1388 biosdir->entries[count].dest = fw_table[i].dest ?
1389 fw_table[i].dest : (uint64_t)-1;
1390 biosdir->entries[count].reset = fw_table[i].reset;
1391 biosdir->entries[count].copy = fw_table[i].copy;
1392 biosdir->entries[count].ro = fw_table[i].ro;
1393 biosdir->entries[count].compressed = fw_table[i].zlib;
1394 biosdir->entries[count].inst = fw_table[i].inst;
1395 biosdir->entries[count].subprog = fw_table[i].subpr;
1396
1397 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301398 case AMD_BIOS_SIG:
1399 /* Reserve size bytes within amdfw.rom */
1400 biosdir->entries[count].size = fw_table[i].size;
1401 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1402 biosdir->entries[count].address_mode =
1403 SET_ADDR_MODE_BY_TABLE(biosdir);
1404 memset(BUFF_CURRENT(*ctx), 0xff,
1405 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001406 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301407 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001408 case AMD_BIOS_APOB:
1409 biosdir->entries[count].size = fw_table[i].size;
1410 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001411 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001412 break;
1413 case AMD_BIOS_APOB_NV:
1414 if (fw_table[i].src) {
1415 /* If source is given, use that and its size */
1416 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001417 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001418 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001419 biosdir->entries[count].size = fw_table[i].size;
1420 } else {
1421 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001422 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001423 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001424 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001425 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001426 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001427 fw_table[i].size, ERASE_ALIGNMENT);
1428 memset(BUFF_CURRENT(*ctx), 0xff,
1429 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001430 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001431 }
1432 break;
1433 case AMD_BIOS_BIN:
1434 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001435 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1436 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001437 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001438 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001439 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001440 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001441 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001442
1443 /* level 2, or level 1 and no copy found in level 2 */
1444 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001445 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001446 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001447 biosdir->entries[count].dest = fw_table[i].dest;
1448 biosdir->entries[count].size = fw_table[i].size;
1449
1450 if (!fw_table[i].filename)
1451 break;
1452
1453 bytes = copy_blob(BUFF_CURRENT(*ctx),
1454 fw_table[i].filename, BUFF_ROOM(*ctx));
1455 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001456 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001457 exit(1);
1458 }
1459
Zheng Bao6fff2492021-11-15 19:53:21 +08001460 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001461 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001462 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001463 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001464
Zheng Baoc26108f2023-02-17 11:01:07 +08001465 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001466 break;
Martin Roth94554742020-04-14 14:59:36 -06001467 case AMD_BIOS_PSP_SHARED_MEM:
1468 biosdir->entries[count].dest = fw_table[i].dest;
1469 biosdir->entries[count].size = fw_table[i].size;
1470 break;
1471
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001472 default: /* everything else is copied from input */
1473 if (fw_table[i].type == AMD_BIOS_APCB ||
1474 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001475 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001476 bytes = copy_blob(BUFF_CURRENT(*ctx),
1477 fw_table[i].filename, BUFF_ROOM(*ctx));
1478 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001479 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001480 exit(1);
1481 }
1482
1483 biosdir->entries[count].size = (uint32_t)bytes;
1484 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001485 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001486
Zheng Baoc26108f2023-02-17 11:01:07 +08001487 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001488 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1489 size = biosdir->entries[count].size;
1490 source = biosdir->entries[count].source;
1491 count++;
1492 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1493 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001494 break;
1495 }
1496
1497 count++;
1498 }
1499
1500 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001501 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001502 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001503 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001504 biosdir->entries[count].size =
1505 + MAX_BIOS_ENTRIES
1506 * sizeof(bios_directory_entry);
1507 biosdir->entries[count].source =
1508 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001509 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001510 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001511 biosdir->entries[count].subprog = 0;
1512 biosdir->entries[count].inst = 0;
1513 biosdir->entries[count].copy = 0;
1514 biosdir->entries[count].compressed = 0;
1515 biosdir->entries[count].dest = -1;
1516 biosdir->entries[count].reset = 0;
1517 biosdir->entries[count].ro = 0;
1518 count++;
1519 }
1520
Zheng Baobf29a0d2020-12-03 23:00:48 +08001521 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001522}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001523
1524enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001525 AMDFW_OPT_CONFIG = 'c',
1526 AMDFW_OPT_DEBUG = 'd',
1527 AMDFW_OPT_HELP = 'h',
Zheng Bao806892a2021-04-27 17:21:54 +08001528
1529 AMDFW_OPT_XHCI = 128,
1530 AMDFW_OPT_IMC,
1531 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001532 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001533 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001534 AMDFW_OPT_USE_COMBO,
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001535 AMDFW_OPT_COMBO1_CONFIG,
Zheng Bao806892a2021-04-27 17:21:54 +08001536 AMDFW_OPT_MULTILEVEL,
1537 AMDFW_OPT_NVRAM,
1538
1539 AMDFW_OPT_FUSE,
1540 AMDFW_OPT_UNLOCK,
1541 AMDFW_OPT_WHITELIST,
1542 AMDFW_OPT_USE_PSPSECUREOS,
1543 AMDFW_OPT_LOAD_MP2FW,
1544 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001545 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001546 AMDFW_OPT_VERSTAGE,
1547 AMDFW_OPT_VERSTAGE_SIG,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001548 AMDFW_OPT_OUTPUT_MANIFEST,
Zheng Bao806892a2021-04-27 17:21:54 +08001549
1550 AMDFW_OPT_INSTANCE,
1551 AMDFW_OPT_APCB,
Zheng Baofa259542021-10-26 19:46:55 +08001552 AMDFW_OPT_APCB_COMBO1,
Zheng Bao806892a2021-04-27 17:21:54 +08001553 AMDFW_OPT_APOBBASE,
1554 AMDFW_OPT_BIOSBIN,
1555 AMDFW_OPT_BIOSBIN_SOURCE,
1556 AMDFW_OPT_BIOSBIN_DEST,
1557 AMDFW_OPT_BIOS_UNCOMP_SIZE,
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001558 AMDFW_OPT_BIOSBIN_UNCOMP,
Zheng Bao806892a2021-04-27 17:21:54 +08001559 AMDFW_OPT_UCODE,
1560 AMDFW_OPT_APOB_NVBASE,
1561 AMDFW_OPT_APOB_NVSIZE,
1562
1563 AMDFW_OPT_OUTPUT,
1564 AMDFW_OPT_FLASHSIZE,
1565 AMDFW_OPT_LOCATION,
1566 AMDFW_OPT_ANYWHERE,
1567 AMDFW_OPT_SHAREDMEM,
1568 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001569 AMDFW_OPT_SIGNED_OUTPUT,
1570 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001571 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001572 /* begin after ASCII characters */
1573 LONGOPT_SPI_READ_MODE = 256,
1574 LONGOPT_SPI_SPEED = 257,
1575 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301576 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301577 LONGOPT_NVRAM_BASE = 260,
1578 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001579};
1580
Zheng Bao806892a2021-04-27 17:21:54 +08001581static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
Zheng Bao994ff522023-03-09 11:43:55 +08001582 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
Zheng Bao806892a2021-04-27 17:21:54 +08001583};
Marc Jones90099b62016-09-20 21:05:45 -06001584
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001585static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001586 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1587 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1588 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001589 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001590 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001591 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001592 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001593 {"combo-config1", required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001594 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1595 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301596 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1597 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001598 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1599 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1600 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1601 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1602 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1603 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001604 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001605 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1606 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001607 {"output-manifest", required_argument, 0, AMDFW_OPT_OUTPUT_MANIFEST },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001608 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001609 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1610 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
Zheng Baofa259542021-10-26 19:46:55 +08001611 {"apcb-combo1", required_argument, 0, AMDFW_OPT_APCB_COMBO1 },
Zheng Bao806892a2021-04-27 17:21:54 +08001612 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1613 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1614 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1615 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1616 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001617 {"bios-bin-uncomp", no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
Ritul Guru9a321f32022-07-29 11:06:40 +05301618 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001619 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1620 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1621 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001622 /* Embedded Firmware Structure items*/
1623 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1624 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1625 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001626 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001627 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001628 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1629 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1630 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1631 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1632 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1633 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001634
Kangheui Won3c164e12021-12-03 20:25:05 +11001635 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1636 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1637
Zheng Bao806892a2021-04-27 17:21:54 +08001638 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1639 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1640 {"help", no_argument, 0, AMDFW_OPT_HELP },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001641 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001642};
1643
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001644void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001645{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001646 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001647
1648 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1649 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1650 continue;
1651
1652 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1653 return;
1654 }
1655}
1656
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001657static void register_fw_token_unlock(void)
1658{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001659 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001660
1661 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1662 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1663 continue;
1664
1665 amd_psp_fw_table[i].other = 1;
1666 return;
1667 }
1668}
1669
Marshall Dawsondbae6322019-03-04 10:31:03 -07001670static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001671{
Martin Roth8806f7f2016-11-08 10:44:18 -07001672 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001673
Martin Rothcd15bc82016-11-08 11:34:02 -07001674 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001675 if (amd_fw_table[i].type == type) {
1676 amd_fw_table[i].filename = filename;
1677 return;
1678 }
1679 }
1680
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001681 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001682 if (amd_psp_fw_table[i].type != type)
1683 continue;
1684
1685 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001686 amd_psp_fw_table[i].filename = filename;
1687 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001688 }
1689 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001690}
1691
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001692static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1693{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001694 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001695
1696 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1697 if (amd_bios_table[i].type == type
1698 && amd_bios_table[i].inst == ins
1699 && amd_bios_table[i].subpr == sub) {
1700 amd_bios_table[i].filename = name;
1701 return;
1702 }
1703 }
1704}
1705
Ritul Gurua2cb3402022-08-29 00:51:08 +05301706static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1707 char *dst_str, char *size_str)
1708{
1709 unsigned int i;
1710
1711 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1712 if (amd_psp_fw_table[i].type != type)
1713 continue;
1714
1715 if (amd_psp_fw_table[i].subprog == sub) {
1716 if (dst_str)
1717 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1718 if (size_str)
1719 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1720 return;
1721 }
1722 }
1723}
1724
1725static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001726 char *dst_str, char *size_str)
1727{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001728 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001729 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1730 if (amd_bios_table[i].type != type)
1731 continue;
1732
1733 if (src_str)
1734 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1735 if (dst_str)
1736 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1737 if (size_str)
1738 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1739
1740 return;
1741 }
1742}
1743
Zheng Baoc3007f32022-04-03 12:53:51 +08001744static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1745 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1746 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001747{
1748 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001749 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001750 return 1;
1751 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001752
1753 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1754 * Leave as 0xffffffff for first gen */
1755 if (cb_config->second_gen) {
1756 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1757 amd_romsig->efs_gen.reserved = 0;
1758 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001759 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1760 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001761 }
1762
1763 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001764 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001765 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001766 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1767 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1768 break;
1769 case PLATFORM_RAVEN:
1770 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001771 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1772 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1773 switch (efs_spi_micron_flag) {
1774 case 0:
1775 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1776 break;
1777 case 1:
1778 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1779 break;
1780 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001781 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001782 return 1;
1783 }
1784 break;
1785 case PLATFORM_RENOIR:
1786 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001787 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001788 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001789 case PLATFORM_PHOENIX:
1790 case PLATFORM_GLINDA:
Arthur Heymans563f7af2023-07-13 11:40:08 +02001791 case PLATFORM_GENOA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001792 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1793 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1794 switch (efs_spi_micron_flag) {
1795 case 0:
1796 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1797 break;
1798 case 1:
1799 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1800 break;
1801 case 2:
1802 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1803 break;
1804 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001805 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001806 return 1;
1807 }
1808 break;
1809 case PLATFORM_UNKNOWN:
1810 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001811 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001812 return 1;
1813 }
1814 return 0;
1815}
1816
Zheng Bao69ea83c2023-01-22 21:08:18 +08001817static ssize_t write_body(char *output, void *body_offset, ssize_t body_size, context *ctx)
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001818{
Zheng Bao69ea83c2023-01-22 21:08:18 +08001819 char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001820 int ret;
1821 int fd;
1822 ssize_t bytes = -1;
1823
1824 /* Create a tmp file and rename it at the end so that make does not get confused
1825 if amdfwtool is killed for some unexpected reasons. */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001826 ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
1827 output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001828 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001829 fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001830 strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001831 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001832 exit(1);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001833 } else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
1834 fprintf(stderr, "BODY File name %d > %zu\n", ret, sizeof(body_tmp_name));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001835 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001836 exit(1);
1837 }
1838
Zheng Bao69ea83c2023-01-22 21:08:18 +08001839 fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001840 if (fd < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001841 fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001842 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001843 exit(1);
1844 }
1845
Zheng Bao69ea83c2023-01-22 21:08:18 +08001846 bytes = write_from_buf_to_file(fd, body_offset, body_size);
1847 if (bytes != body_size) {
1848 fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001849 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001850 exit(1);
1851 }
1852 close(fd);
1853
1854 /* Rename the tmp file */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001855 ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001856 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001857 fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001858 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001859 exit(1);
1860 }
1861
Zheng Bao69ea83c2023-01-22 21:08:18 +08001862 if (rename(body_tmp_name, body_name)) {
1863 fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001864 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001865 exit(1);
1866 }
1867
1868 return bytes;
1869}
1870
Zheng Bao994ff522023-03-09 11:43:55 +08001871void open_process_config(char *config, amd_cb_config *cb_config, int debug)
Zheng Bao39cae562023-03-07 18:37:43 +08001872{
1873 FILE *config_handle;
1874
1875 if (config) {
1876 config_handle = fopen(config, "r");
1877 if (config_handle == NULL) {
1878 fprintf(stderr, "Can not open file %s for reading: %s\n",
1879 config, strerror(errno));
1880 exit(1);
1881 }
Zheng Bao994ff522023-03-09 11:43:55 +08001882 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001883 fprintf(stderr, "Configuration file %s parsing error\n",
1884 config);
1885 fclose(config_handle);
1886 exit(1);
1887 }
1888 fclose(config_handle);
1889 }
1890
1891 /* For debug. */
1892 if (debug) {
1893 dump_psp_firmwares(amd_psp_fw_table);
1894 dump_bdt_firmwares(amd_bios_table);
1895 }
1896}
1897
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001898static bool is_initial_alignment_required(enum platform soc_id)
1899{
1900 switch (soc_id) {
1901 case PLATFORM_MENDOCINO:
1902 case PLATFORM_PHOENIX:
1903 case PLATFORM_GLINDA:
1904 return false;
1905 default:
1906 return true;
1907 }
1908}
1909
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001910int main(int argc, char **argv)
1911{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001912 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001913 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001914 char *tmp;
Marshall Dawson239286c2019-02-23 16:42:46 -07001915 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001916 psp_directory_table *pspdir = NULL;
1917 psp_directory_table *pspdir2 = NULL;
1918 psp_directory_table *pspdir2_b = NULL;
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001919 psp_combo_directory *psp_combo_dir = NULL, *bhd_combo_dir = NULL;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001920 char *combo_config[MAX_COMBO_ENTRIES] = { 0 };
Zheng Baofa259542021-10-26 19:46:55 +08001921 struct _combo_apcb {
1922 char *filename;
1923 uint8_t ins;
1924 uint8_t sub;
1925 } combo_apcb[MAX_COMBO_ENTRIES] = {0}, combo_apcb_bk[MAX_COMBO_ENTRIES] = {0};
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001926 int combo_index = 0;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001927 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001928 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001929 char *output = NULL, *config = NULL;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001930 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001931 /* Values cleared after each firmware or parameter, regardless if N/A */
1932 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08001933 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001934 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001935 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001936 uint32_t romsig_offset;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001937 uint8_t efs_spi_readmode = 0xff;
1938 uint8_t efs_spi_speed = 0xff;
1939 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11001940 const char *signed_output_file = NULL;
1941 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001942
Fred Reitbergerf36b0132022-06-29 13:54:57 -04001943 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08001944 int debug = 0;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001945 char *manifest_file = NULL;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001946
Zheng Baoc26108f2023-02-17 11:01:07 +08001947 ctx.current_pointer_saved = 0xFFFFFFFF;
1948
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001949 while (1) {
1950 int optindex = 0;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001951 int bios_tbl_index = -1;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001952
1953 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1954
1955 if (c == -1)
1956 break;
1957
1958 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001959 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001960 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001961 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001962 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001963 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001964 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001965 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001966 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001967 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001968 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001969 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001970 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001971 case AMDFW_OPT_RECOVERY_AB:
1972 cb_config.recovery_ab = true;
1973 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001974 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1975 cb_config.recovery_ab = true;
1976 cb_config.recovery_ab_single_copy = true;
1977 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001978 case AMDFW_OPT_USE_COMBO:
1979 cb_config.use_combo = true;
1980 break;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001981 case AMDFW_OPT_COMBO1_CONFIG:
1982 cb_config.use_combo = true;
Zheng Bao73917222023-03-15 16:14:03 +08001983 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001984 combo_config[1] = optarg;
1985 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001986 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001987 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001988 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001989 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001990 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001991 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001992 sub = instance = 0;
1993 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001994 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001995 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001996 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001997 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001998 instance = strtoul(optarg, &tmp, 16);
1999 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002000 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002001 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002002 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002003 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07002004 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002005 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002006 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002007 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002008 register_fw_fuse(optarg);
2009 fuse_defined = 1;
2010 sub = 0;
2011 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002012 case AMDFW_OPT_APCB:
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002013 if ((instance & 0xF0) == 0) {
Zheng Bao5caca942020-12-04 16:39:38 +08002014 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
Zheng Baofa259542021-10-26 19:46:55 +08002015 combo_apcb[0].filename = optarg;
2016 combo_apcb[0].ins = instance;
2017 combo_apcb[0].sub = sub;
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002018 } else {
Zheng Bao5caca942020-12-04 16:39:38 +08002019 register_bdt_data(AMD_BIOS_APCB_BK, sub,
2020 instance & 0xF, optarg);
Zheng Baofa259542021-10-26 19:46:55 +08002021 combo_apcb_bk[0].filename = optarg;
2022 combo_apcb_bk[0].ins = instance;
2023 combo_apcb_bk[0].sub = sub;
2024 cb_config.have_apcb_bk = 1;
2025 }
2026 sub = instance = 0;
2027 break;
2028 case AMDFW_OPT_APCB_COMBO1:
2029 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
2030 if ((instance & 0xF0) == 0) {
2031 combo_apcb[1].filename = optarg;
2032 combo_apcb[1].ins = instance;
2033 combo_apcb[1].sub = sub;
2034 } else {
2035 combo_apcb_bk[1].filename = optarg;
2036 combo_apcb_bk[1].ins = instance;
2037 combo_apcb_bk[1].sub = sub;
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07002038 cb_config.have_apcb_bk = 1;
2039 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002040 sub = instance = 0;
2041 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002042 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002043 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302044 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002045 sub = instance = 0;
2046 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002047 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002048 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302049 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002050 sub = instance = 0;
2051 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002052 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002053 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302054 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002055 sub = instance = 0;
2056 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002057 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002058 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
2059 sub = instance = 0;
2060 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002061 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002062 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302063 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002064 sub = instance = 0;
2065 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002066 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002067 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302068 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002069 sub = instance = 0;
2070 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002071 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002072 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302073 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002074 sub = instance = 0;
2075 break;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07002076 case AMDFW_OPT_BIOSBIN_UNCOMP:
2077 bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
2078 if (bios_tbl_index != -1)
2079 amd_bios_table[bios_tbl_index].zlib = 0;
2080 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05302081 case LONGOPT_BIOS_SIG:
2082 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302083 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05302084 sub = instance = 0;
2085 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002086 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002087 register_bdt_data(AMD_BIOS_UCODE, sub,
2088 instance, optarg);
2089 sub = instance = 0;
2090 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002091 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08002092 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002093 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08002094 case AMDFW_OPT_SPL_TABLE:
2095 register_fw_filename(AMD_FW_SPL, sub, optarg);
2096 sub = instance = 0;
2097 cb_config.have_mb_spl = true;
2098 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002099 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002100 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
2101 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08002102 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002103 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002104 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06002105 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
2106 sub = instance = 0;
2107 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002108 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06002109 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
2110 sub = instance = 0;
2111 break;
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002112 case AMDFW_OPT_OUTPUT_MANIFEST:
2113 manifest_file = optarg;
2114 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11002115 case AMDFW_OPT_SIGNED_OUTPUT:
2116 signed_output_file = optarg;
2117 sub = instance = 0;
2118 break;
2119 case AMDFW_OPT_SIGNED_ADDR:
2120 signed_start_addr = strtoull(optarg, NULL, 10);
2121 sub = instance = 0;
2122 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002123 case LONGOPT_SPI_READ_MODE:
2124 efs_spi_readmode = strtoull(optarg, NULL, 16);
2125 sub = instance = 0;
2126 break;
2127 case LONGOPT_SPI_SPEED:
2128 efs_spi_speed = strtoull(optarg, NULL, 16);
2129 sub = instance = 0;
2130 break;
2131 case LONGOPT_SPI_MICRON_FLAG:
2132 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2133 sub = instance = 0;
2134 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002135 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002136 output = optarg;
2137 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002138 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002139 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002140 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002141 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002142 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002143 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002144 }
2145 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002146 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002147 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002148 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002149 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002150 " incorrectly (%s)\n\n", optarg);
2151 retval = 1;
2152 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002153 if (body_location == 0)
2154 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002155 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002156 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002157 any_location = 1;
2158 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002159 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002160 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302161 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002162 sub = instance = 0;
2163 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002164 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002165 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302166 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002167 sub = instance = 0;
2168 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302169 case LONGOPT_NVRAM_BASE:
2170 /* PSP NV base */
2171 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2172 sub = instance = 0;
2173 break;
2174 case LONGOPT_NVRAM_SIZE:
2175 /* PSP NV size */
2176 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2177 sub = instance = 0;
2178 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002179 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002180 config = optarg;
2181 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002182 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002183 debug = 1;
2184 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002185 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002186 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002187 return 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002188 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002189 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002190 if (*tmp != '\0') {
2191 fprintf(stderr, "Error: Body Location specified"
2192 " incorrectly (%s)\n\n", optarg);
2193 retval = 1;
2194 }
2195 break;
2196
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002197 default:
2198 break;
2199 }
2200 }
2201
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002202 if (cb_config.use_combo) {
2203 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
2204 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
2205 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
2206 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
2207 }
2208
Zheng Bao994ff522023-03-09 11:43:55 +08002209 open_process_config(config, &cb_config, debug);
Zheng Bao9e908072020-10-28 11:39:13 +08002210
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002211 if (!fuse_defined)
2212 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2213
Zheng Bao994ff522023-03-09 11:43:55 +08002214 if (!output) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002215 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002216 retval = 1;
2217 }
2218
Zheng Baoa7731cc2023-03-11 09:27:53 +08002219 if (ctx.rom_size % 1024 != 0) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002220 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002221 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002222 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002223 }
2224
Zheng Baoa7731cc2023-03-11 09:27:53 +08002225 if (ctx.rom_size < MIN_ROM_KB * 1024) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002226 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002227 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002228 retval = 1;
2229 }
2230
2231 if (retval) {
2232 usage();
2233 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002234 }
2235
Marshall Dawson2794a862019-03-04 16:53:15 -07002236 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002237
Zheng Bao1a0c99f2023-02-11 15:17:22 +08002238 if (ctx.rom_size <= MAX_MAPPED_WINDOW) {
2239 uint32_t rom_base_address;
Zheng Bao9770df12023-02-14 13:23:35 +08002240
Zheng Bao1a0c99f2023-02-11 15:17:22 +08002241 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
2242 if (efs_location & ~MAX_MAPPED_WINDOW_MASK)
2243 efs_location = efs_location - rom_base_address;
2244 if (body_location & ~MAX_MAPPED_WINDOW_MASK)
2245 body_location = body_location - rom_base_address;
2246 }
Zheng Bao9770df12023-02-14 13:23:35 +08002247
Zheng Bao1a0c99f2023-02-11 15:17:22 +08002248 /* If the flash size is larger than 16M, we assume the given
2249 addresses are already relative ones. Otherwise we print error.*/
Zheng Bao9770df12023-02-14 13:23:35 +08002250 if (efs_location && efs_location > ctx.rom_size) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002251 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2252 return 1;
2253 }
Zheng Bao9770df12023-02-14 13:23:35 +08002254 if (body_location && body_location > ctx.rom_size) {
2255 fprintf(stderr, "Error: Body location outside of ROM.\n\n");
2256 return 1;
2257 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002258
Zheng Bao99945dc2023-01-02 10:55:56 +08002259 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002260 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2261 return 1;
2262 }
2263
Zheng Bao99945dc2023-01-02 10:55:56 +08002264 if (body_location != efs_location &&
2265 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002266 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2267 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002268 return 1;
2269 }
2270
Martin Roth37305e72020-04-07 14:16:39 -06002271 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002272 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002273 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002274 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002275 return 1;
2276 }
2277 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002278 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002279 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002280 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002281 case 0xFA0000:
2282 case 0xF20000:
2283 case 0xE20000:
2284 case 0xC20000:
2285 case 0x820000:
2286 case 0x020000:
2287 break;
2288 case 0x7A0000:
2289 case 0x720000:
2290 case 0x620000:
2291 case 0x420000:
2292 /* Special cases for 8M. */
2293 if (ctx.rom_size != 0x800000) {
2294 fprintf(stderr, "Error: Invalid Directory location.\n");
2295 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2296 return 1;
2297 }
2298 break;
2299 case 0x3A0000:
2300 case 0x320000:
2301 case 0x220000:
2302 /* Special cases for 4M. */
2303 if (ctx.rom_size != 0x400000) {
2304 fprintf(stderr, "Error: Invalid Directory location.\n");
2305 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2306 return 1;
2307 }
Martin Roth37305e72020-04-07 14:16:39 -06002308 break;
2309 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002310 fprintf(stderr, "Error: Invalid Directory location.\n");
2311 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2312 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002313 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2314 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002315 return 1;
2316 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002317 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002318 ctx.rom = malloc(ctx.rom_size);
2319 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002320 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002321 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002322 }
2323 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002324
Zheng Bao6095cd12023-02-21 10:52:47 +08002325 romsig_offset = efs_location ? efs_location : AMD_ROMSIG_OFFSET;
2326 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06002327
Marshall Dawson2794a862019-03-04 16:53:15 -07002328 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002329 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2330 amd_romsig->imc_entry = 0;
2331 amd_romsig->gec_entry = 0;
2332 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002333
Zheng Bao4bf6f492023-01-25 22:37:29 +08002334 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2335 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2336 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002337 if (retval) {
2338 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2339 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002340 }
2341 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002342 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002343 }
2344
Felix Held21a8e382022-03-29 23:10:45 +02002345 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002346 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002347 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002348 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002349 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002350 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002351 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2352 efs_location);
2353 if (body_location != efs_location)
2354 printf(" with a split body at: 0x%08x\n", body_location);
2355 else
2356 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002357
Zheng Bao6095cd12023-02-21 10:52:47 +08002358 if (efs_location != body_location)
2359 set_current_pointer(&ctx, body_location);
2360 else
2361 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
2362
Marshall Dawson2794a862019-03-04 16:53:15 -07002363 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002364
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07002365 if (is_initial_alignment_required(cb_config.soc_id)) {
2366 /* TODO: Check for older platforms. */
2367 adjust_current_pointer(&ctx, 0, 0x10000U);
2368 }
Zheng Bao6fff2492021-11-15 19:53:21 +08002369 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002370
Kangheui Won3c164e12021-12-03 20:25:05 +11002371 /* If the tool is invoked with command-line options to keep the signed PSP
2372 binaries separate, process the signed binaries first. */
2373 if (signed_output_file && signed_start_addr)
2374 process_signed_psp_firmwares(signed_output_file,
2375 amd_psp_fw_table,
2376 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002377 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002378
Zheng Baob2ae6a52022-08-18 15:45:27 +08002379 if (cb_config.use_combo) {
2380 psp_combo_dir = new_combo_dir(&ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002381
2382 adjust_current_pointer(&ctx, 0, 0x1000U);
2383
2384 bhd_combo_dir = new_combo_dir(&ctx);
Zheng Baob2ae6a52022-08-18 15:45:27 +08002385 }
2386
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002387 combo_index = 0;
2388 if (config)
2389 combo_config[0] = config;
2390
Zheng Bao4b6aa192023-03-09 11:28:47 +08002391 do {
Zheng Bao3e7008d2023-03-15 16:15:13 +08002392 if (cb_config.use_combo && debug)
2393 printf("Processing %dth combo entry\n", combo_index);
2394
Zheng Bao4b6aa192023-03-09 11:28:47 +08002395 /* for non-combo image, combo_config[0] == config, and
2396 * it already is processed. Actually "combo_index >
2397 * 0" is enough. Put both of them here to make sure
2398 * and make it clear this will not affect non-combo
2399 * case.
2400 */
2401 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08002402 /* Restore the table as clean data. */
2403 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
2404 sizeof(amd_psp_fw_table));
2405 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
2406 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08002407 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08002408 open_process_config(combo_config[combo_index], &cb_config,
Zheng Bao994ff522023-03-09 11:43:55 +08002409 debug);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002410
Zheng Bao4b6aa192023-03-09 11:28:47 +08002411 /* In most cases, the address modes are same. */
2412 if (cb_config.need_ish)
2413 ctx.address_mode = AMD_ADDR_REL_TAB;
2414 else if (cb_config.second_gen)
2415 ctx.address_mode = AMD_ADDR_REL_BIOS;
2416 else
2417 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baofa259542021-10-26 19:46:55 +08002418
2419 if (combo_apcb[combo_index].filename != NULL) {
2420 register_bdt_data(AMD_BIOS_APCB,
2421 combo_apcb[combo_index].sub,
2422 combo_apcb[combo_index].ins & 0xF,
2423 combo_apcb[combo_index].filename);
2424 if (cb_config.have_apcb_bk)
2425 register_bdt_data(AMD_BIOS_APCB_BK,
2426 combo_apcb_bk[combo_index].sub,
2427 combo_apcb_bk[combo_index].ins & 0xF,
2428 combo_apcb_bk[combo_index].filename);
2429 } else {
2430 /* Use main APCB if no Combo APCB is provided */
2431 register_bdt_data(AMD_BIOS_APCB, combo_apcb[0].sub,
2432 combo_apcb[0].ins & 0xF, combo_apcb[0].filename);
2433 if (cb_config.have_apcb_bk)
2434 register_bdt_data(AMD_BIOS_APCB_BK,
2435 combo_apcb_bk[0].sub,
2436 combo_apcb_bk[0].ins & 0xF,
2437 combo_apcb_bk[0].filename);
2438 }
Zheng Bao990d1542021-09-17 13:24:54 +08002439 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002440
Zheng Bao481661e2021-08-20 14:47:46 +08002441 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002442 /* Do 2nd PSP directory followed by 1st */
2443 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2444 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
2445 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
2446 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2447 /* Create a copy of PSP Directory 2 in the backup slot B.
2448 Related biosdir2_b copy will be created later. */
2449 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2450 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
2451 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002452 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002453 /*
2454 * Either the platform is using only
2455 * one slot or B is same as above
2456 * directories for A. Skip creating
2457 * pspdir2_b here to save flash space.
2458 * Related biosdir2_b will be skipped
2459 * automatically.
2460 */
2461 pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08002462 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002463 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2464 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
2465 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002466 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002467 /* flat: PSP 1 cookie and no pointer to 2nd table */
2468 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2469 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
2470 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002471 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002472
Zheng Bao4b6aa192023-03-09 11:28:47 +08002473 if (!cb_config.use_combo) {
2474 fill_psp_directory_to_efs(amd_romsig, pspdir, &ctx, &cb_config);
2475 } else {
2476 fill_psp_directory_to_efs(amd_romsig, psp_combo_dir, &ctx, &cb_config);
2477 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2478 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2479 psp_combo_dir->entries[combo_index].id_sel = 0;
2480 psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
2481 psp_combo_dir->entries[combo_index].lvl2_addr =
2482 BUFF_TO_RUN_MODE(ctx, pspdir, AMD_ADDR_REL_BIOS);
2483
2484 fill_dir_header(psp_combo_dir, combo_index + 1, PSP2_COOKIE, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002485 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002486
2487 if (have_bios_tables(amd_bios_table)) {
2488 bios_directory_table *biosdir = NULL;
2489 if (cb_config.multi_level) {
2490 /* Do 2nd level BIOS directory followed by 1st */
2491 bios_directory_table *biosdir2 = NULL;
2492 bios_directory_table *biosdir2_b = NULL;
2493
2494 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2495
2496 integrate_bios_firmwares(&ctx, biosdir2, NULL,
2497 amd_bios_table, BHDL2_COOKIE, &cb_config);
2498 if (cb_config.recovery_ab) {
2499 if (pspdir2_b != NULL) {
2500 biosdir2_b = new_bios_dir(&ctx,
2501 cb_config.multi_level);
2502 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
2503 amd_bios_table, BHDL2_COOKIE,
2504 &cb_config);
2505 }
2506 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2507 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2508 if (pspdir2_b != NULL)
2509 add_psp_firmware_entry(&ctx, pspdir2_b,
2510 biosdir2_b, AMD_FW_BIOS_TABLE,
2511 TABLE_ALIGNMENT);
2512 } else {
2513 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2514 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
2515 amd_bios_table, BHD_COOKIE, &cb_config);
2516 }
2517 } else {
2518 /* flat: BHD1 cookie and no pointer to 2nd table */
2519 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2520 integrate_bios_firmwares(&ctx, biosdir, NULL,
2521 amd_bios_table, BHD_COOKIE, &cb_config);
2522 }
2523 if (!cb_config.use_combo) {
2524 fill_bios_directory_to_efs(amd_romsig, biosdir,
2525 &ctx, &cb_config);
2526 } else {
2527 fill_bios_directory_to_efs(amd_romsig, bhd_combo_dir,
2528 &ctx, &cb_config);
2529 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2530 bhd_combo_dir->entries[combo_index].id_sel = 0;
2531 bhd_combo_dir->entries[combo_index].id =
2532 get_psp_id(cb_config.soc_id);
2533 bhd_combo_dir->entries[combo_index].lvl2_addr =
2534 BUFF_TO_RUN_MODE(ctx, biosdir, AMD_ADDR_REL_BIOS);
2535
2536 fill_dir_header(bhd_combo_dir, combo_index + 1,
2537 BHD2_COOKIE, &ctx);
2538 }
2539 }
Zheng Bao17551ae2023-03-11 10:29:56 +08002540 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
2541 combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002542
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002543 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002544 if (targetfd >= 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08002545 uint32_t offset = efs_location;
2546 uint32_t bytes = efs_location == body_location ?
2547 ctx.current - offset : sizeof(*amd_romsig);
2548 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002549
Zheng Baoc25d5932023-03-22 12:51:47 +08002550 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08002551 if (bytes != ret_bytes) {
Zheng Bao47396912020-09-29 17:33:17 +08002552 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2553 retval = 1;
2554 }
Martin Roth31d95a22016-11-08 11:22:12 -07002555 close(targetfd);
2556 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002557 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002558 retval = 1;
2559 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002560
Zheng Bao99945dc2023-01-02 10:55:56 +08002561 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002562 ssize_t bytes;
2563
Zheng Bao69ea83c2023-01-22 21:08:18 +08002564 bytes = write_body(output, BUFF_OFFSET(ctx, body_location),
2565 ctx.current - body_location, &ctx);
2566 if (bytes != ctx.current - body_location) {
2567 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002568 retval = 1;
2569 }
2570 }
2571
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00002572 if (manifest_file) {
2573 dump_blob_version(manifest_file, amd_psp_fw_table);
2574 }
2575
Zheng Bao7c5ad882023-02-19 13:02:52 +08002576 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07002577 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002578}