blob: 8190b8dc2a4835869bb21b49f82e9c364f25971a [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002
3/*
Zheng Baodd4c5422021-10-14 16:14:09 +08004 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
zbaoc3b0b722016-02-19 13:47:31 +08005 * 0 4 8 C
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08006 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +08009 * | PSPDIR ADDR|PSPDIR ADDR(C) | BDT ADDR 0 | BDT ADDR 1 |
10 * +------------+---------------+----------------+------------+
11 * | BDT ADDR 2 | | BDT ADDR 3(C) | |
12 * +------------+---------------+----------------+------------+
13 * (C): Could be a combo header
14 *
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080015 * EC ROM should be 64K aligned.
16 *
Zheng Bao4fcc9f22015-11-20 12:29:04 +080017 * PSP directory (Where "PSPDIR ADDR" points)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080018 * +------------+---------------+----------------+------------+
19 * | 'PSP$' | Fletcher | Count | Reserved |
20 * +------------+---------------+----------------+------------+
21 * | 0 | size | Base address | Reserved | Pubkey
22 * +------------+---------------+----------------+------------+
23 * | 1 | size | Base address | Reserved | Bootloader
24 * +------------+---------------+----------------+------------+
25 * | 8 | size | Base address | Reserved | Smu Firmware
26 * +------------+---------------+----------------+------------+
27 * | 3 | size | Base address | Reserved | Recovery Firmware
28 * +------------+---------------+----------------+------------+
29 * | |
30 * | |
Zheng Baodd4c5422021-10-14 16:14:09 +080031 * | Other PSP Firmware |
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080032 * | |
33 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080034 * | 40 | size | Base address | Reserved |---+
35 * +------------+---------------+----------------+------------+ |
36 * :or 48(A/B A): size : Base address : Reserved : |
37 * + - - + - - + - - + - - + |
38 * : 4A(A/B B): size : Base address : Reserved : |
39 * +------------+---------------+----------------+------------+ |
40 * (A/B A) & (A/B B): Similar as 40, pointing to PSP level 2 |
41 * for A/B recovery |
42 * |
43 * |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
47 * | |
48 * | |
49 * | PSP Firmware |
50 * | (2nd-level is not required on all families) |
51 * | |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
Zheng Bao4fcc9f22015-11-20 12:29:04 +080054 *
zbaoc3b0b722016-02-19 13:47:31 +080055 * PSP Combo directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080056 * +------------+---------------+----------------+------------+
zbao6e2f3d12016-02-19 13:34:59 +080057 * | 'PSP2' | Fletcher | Count |Look up mode|
Zheng Bao4fcc9f22015-11-20 12:29:04 +080058 * +------------+---------------+----------------+------------+
zbaoc3a08a92016-03-02 14:47:27 +080059 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080061 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080062 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080063 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
Zheng Bao4fcc9f22015-11-20 12:29:04 +080064 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
Zheng Baodd4c5422021-10-14 16:14:09 +080069 * BDT Combo is similar
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080070 */
71
Elyes Haouas7d67a192022-10-14 09:58:29 +020072#include <commonlib/bsd/helpers.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080073#include <fcntl.h>
74#include <errno.h>
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060075#include <limits.h>
Martin Roth37305e72020-04-07 14:16:39 -060076#include <stdbool.h>
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080077#include <stdio.h>
78#include <sys/stat.h>
79#include <sys/types.h>
80#include <unistd.h>
81#include <string.h>
82#include <stdlib.h>
83#include <getopt.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080084#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010085#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080086
87#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080088
Martin Roth60f15512016-11-08 09:55:01 -070089#define AMD_ROMSIG_OFFSET 0x20000
90#define MIN_ROM_KB 256
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080091
Marshall Dawson7c1e1422019-04-11 09:44:43 -060092#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080093
Marshall Dawsonef79fcc2019-04-01 10:16:41 -060094#define DEFAULT_SOFT_FUSE_CHAIN "0x1"
95
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -060096#define EFS_FILE_SUFFIX ".efs"
97#define TMP_FILE_SUFFIX ".tmp"
Zheng Bao69ea83c2023-01-22 21:08:18 +080098#define BODY_FILE_SUFFIX ".body"
Kangheui Won5b84dfd2021-12-21 15:45:06 +110099
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800100/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700101 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
102 * can support an optional "combo" implementation. If the PSP sees the
103 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
104 * tables. Using this, support for multiple product generations may be
105 * built into one image. If the PSP$ cookie is found, the table is a
106 * normal directory table.
107 *
108 * Modern generations supporting the combo directories require the
109 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
Zheng Baoc91867a2023-02-26 12:31:31 +0800110 * regardless of the type of directory used. The --use-combo
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700111 * argument enforces this placement.
112 *
113 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800114 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800115
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800116/*
117 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
118 * The checksum field of the passed PDU does not need to be reset to zero.
119 *
120 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
121 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
122 * alternative to cyclical redundancy checks because it provides error-
123 * detection properties similar to cyclical redundancy checks but at the
124 * cost of a simple summation technique. Its characteristics were first
125 * published in IEEE Transactions on Communications in January 1982. One
126 * version has been adopted by ISO for use in the class-4 transport layer
127 * of the network protocol.
128 *
129 * This program expects:
130 * stdin: The input file to compute a checksum for. The input file
131 * not be longer than 256 bytes.
132 * stdout: Copied from the input file with the Fletcher's Checksum
133 * inserted 8 bytes after the beginning of the file.
134 * stderr: Used to print out error messages.
135 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700136static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800137{
138 uint32_t c0;
139 uint32_t c1;
140 uint32_t checksum;
141 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700142 const uint16_t *pptr = data;
143
144 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800145
146 c0 = 0xFFFF;
147 c1 = 0xFFFF;
148
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600149 while (length) {
150 index = length >= 359 ? 359 : length;
151 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800152 do {
153 c0 += *(pptr++);
154 c1 += c0;
155 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600156 c0 = (c0 & 0xFFFF) + (c0 >> 16);
157 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800158 }
159
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700160 /* Sums[0,1] mod 64K + overflow */
161 c0 = (c0 & 0xFFFF) + (c0 >> 16);
162 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800163 checksum = (c1 << 16) | c0;
164
165 return checksum;
166}
167
Martin Roth8806f7f2016-11-08 10:44:18 -0700168static void usage(void)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800169{
Martin Roth0e940622016-11-08 10:37:53 -0700170 printf("amdfwtool: Create AMD Firmware combination\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800171 printf("Usage: amdfwtool [options] --flashsize <size> --output <filename>\n");
172 printf("--xhci <FILE> Add XHCI blob\n");
173 printf("--imc <FILE> Add IMC blob\n");
174 printf("--gec <FILE> Add GEC blob\n");
Martin Roth0e940622016-11-08 10:37:53 -0700175
176 printf("\nPSP options:\n");
Zheng Bao993b43f2021-11-10 12:21:46 +0800177 printf("--use-combo Use the COMBO layout\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800178 printf("--multilevel Generate primary and secondary tables\n");
179 printf("--nvram <FILE> Add nvram binary\n");
180 printf("--soft-fuse Set soft fuse\n");
181 printf("--token-unlock Set token unlock\n");
Ritul Gurua2cb3402022-08-29 00:51:08 +0530182 printf("--nvram-base <HEX_VAL> Base address of nvram\n");
183 printf("--nvram-size <HEX_VAL> Size of nvram\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800184 printf("--whitelist Set if there is a whitelist\n");
185 printf("--use-pspsecureos Set if psp secure OS is needed\n");
186 printf("--load-mp2-fw Set if load MP2 firmware\n");
187 printf("--load-s0i3 Set if load s0i3 firmware\n");
188 printf("--verstage <FILE> Add verstage\n");
189 printf("--verstage_sig Add verstage signature\n");
Zheng Bao990d1542021-09-17 13:24:54 +0800190 printf("--recovery-ab Use the recovery A/B layout\n");
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600191 printf("\nBIOS options:\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800192 printf("--instance <number> Sets instance field for the next BIOS\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800193 printf(" firmware\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800194 printf("--apcb <FILE> Add AGESA PSP customization block\n");
195 printf("--apob-base <HEX_VAL> Destination for AGESA PSP output block\n");
196 printf("--apob-nv-base <HEX_VAL> Location of S3 resume data\n");
197 printf("--apob-nv-size <HEX_VAL> Size of S3 resume data\n");
198 printf("--ucode <FILE> Add microcode patch\n");
199 printf("--bios-bin <FILE> Add compressed image; auto source address\n");
200 printf("--bios-bin-src <HEX_VAL> Address in flash of source if -V not used\n");
201 printf("--bios-bin-dest <HEX_VAL> Destination for uncompressed BIOS\n");
202 printf("--bios-uncomp-size <HEX> Uncompressed size of BIOS image\n");
203 printf("--output <filename> output filename\n");
204 printf("--flashsize <HEX_VAL> ROM size in bytes\n");
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600205 printf(" size must be larger than %dKB\n",
Martin Roth0e940622016-11-08 10:37:53 -0700206 MIN_ROM_KB);
Marshall Dawsonf4b9b412017-03-17 16:30:51 -0600207 printf(" and must a multiple of 1024\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800208 printf("--location Location of Directory\n");
209 printf("--anywhere Use any 64-byte aligned addr for Directory\n");
210 printf("--sharedmem Location of PSP/FW shared memory\n");
211 printf("--sharedmem-size Maximum size of the PSP/FW shared memory\n");
Zheng Bao6f0b3612021-04-27 17:19:43 +0800212 printf(" area\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -0500213 printf("\nEmbedded Firmware Structure options used by the PSP:\n");
214 printf("--spi-speed <HEX_VAL> SPI fast speed to place in EFS Table\n");
215 printf(" 0x0 66.66Mhz\n");
216 printf(" 0x1 33.33MHz\n");
217 printf(" 0x2 22.22MHz\n");
218 printf(" 0x3 16.66MHz\n");
219 printf(" 0x4 100MHz\n");
220 printf(" 0x5 800KHz\n");
221 printf("--spi-read-mode <HEX_VAL> SPI read mode to place in EFS Table\n");
222 printf(" 0x0 Normal Read (up to 33M)\n");
223 printf(" 0x1 Reserved\n");
224 printf(" 0x2 Dual IO (1-1-2)\n");
225 printf(" 0x3 Quad IO (1-1-4)\n");
226 printf(" 0x4 Dual IO (1-2-2)\n");
227 printf(" 0x5 Quad IO (1-4-4)\n");
228 printf(" 0x6 Normal Read (up to 66M)\n");
229 printf(" 0x7 Fast Read\n");
230 printf("--spi-micron-flag <HEX_VAL> Micron SPI part support for RV and later SOC\n");
231 printf(" 0x0 Micron parts are not used\n");
232 printf(" 0x1 Micron parts are always used\n");
233 printf(" 0x2 Micron parts optional, this option is only\n");
234 printf(" supported with RN/LCN SOC\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800235 printf("\nGeneral options:\n");
236 printf("-c|--config <config file> Config file\n");
237 printf("-d|--debug Print debug message\n");
Zheng Bao806892a2021-04-27 17:21:54 +0800238 printf("-h|--help Show this help\n");
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800239}
240
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800241amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100242 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Baofb9b7842022-02-24 15:15:50 +0800243 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800244 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200245 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800246 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200247 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
248 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
249 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800250 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100251 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
252 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200253 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200254 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800255 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
256 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800257 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200258 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
259 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800260 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
261 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
262 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
263 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800264 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao9bb62cb2023-03-07 19:48:11 +0800265 { .type = AMD_HW_IPCFG, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
266 { .type = AMD_HW_IPCFG, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100267 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800268 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
269 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800270 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200271 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800272 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200273 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
274 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800275 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
276 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200277 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
278 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
279 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800280 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800281 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB },
282 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
283 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
284 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
285 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
286 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
287 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
288 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200289 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
290 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600291 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200292 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200293 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200294 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
295 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
296 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
297 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
298 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600299 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
300 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200301 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
302 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
303 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
304 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
305 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
306 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Nikolai Vyssotskibfc9ca72023-03-07 15:09:09 -0600307 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800308 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200309 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
310 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800311 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
312 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200313 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200314 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200315 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
316 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800317 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
318 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
319 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
320 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
321 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
322 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
323 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
324 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
325 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
326 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
327 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
328 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
329 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
330 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500331 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800332 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800333};
334
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800335amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800336 { .type = AMD_FW_XHCI },
337 { .type = AMD_FW_IMC },
338 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800339 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800340};
341
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800342amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800343 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530344 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600345 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
346 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
347 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
348 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
349 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700350 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
351 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
352 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
353 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
354 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
355 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
356 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
357 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
358 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
359 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
360 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700361 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
362 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
363 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
364 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
365 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700366 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
367 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
368 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
369 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
370 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
371 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
372 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
373 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
374 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
375 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
376 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600377 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
378 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800379 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600380 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
381 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
382 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800383 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
384 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200385 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
386 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600387 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
388 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800389 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
390 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
391 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
392 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
393 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
394 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200395 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
396 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
397 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
398 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800399 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
400 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
401 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
402 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
403 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
404 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600405 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
406 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800407 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
408 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200409 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
410 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600411 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
412 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800413 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
414 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
415 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
416 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
417 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
418 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200419 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
420 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
421 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
422 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800423 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
424 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
425 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
426 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
427 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
428 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600429 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
430 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
431 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200432 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
433 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
434 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
435 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600436 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600437 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600438 { .type = AMD_BIOS_INVALID },
439};
440
Marshall Dawson2794a862019-03-04 16:53:15 -0700441typedef struct _context {
442 char *rom; /* target buffer, size of flash device */
443 uint32_t rom_size; /* size of flash device */
Zheng Bao6fff2492021-11-15 19:53:21 +0800444 uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */
Marshall Dawson2794a862019-03-04 16:53:15 -0700445 uint32_t current; /* pointer within flash & proxy buffer */
Zheng Baoc26108f2023-02-17 11:01:07 +0800446 uint32_t current_pointer_saved;
Zheng Bao6fff2492021-11-15 19:53:21 +0800447 uint32_t current_table;
Marshall Dawson2794a862019-03-04 16:53:15 -0700448} context;
449
450#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800451#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600452 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
453 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
Zheng Baoc38f7642023-02-21 10:43:08 +0800454 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800455#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600456#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800457 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700458#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800459/* The mode in entry can not be higher than the header's.
460 For example, if table mode is 0, all the entry mode will be 0. */
461#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
462 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700463#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
464#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
465#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800466#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
467 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700468#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800469/* Only set the address mode in entry if the table is mode 2. */
470#define SET_ADDR_MODE(table, mode) \
471 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600472 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800473#define SET_ADDR_MODE_BY_TABLE(table) \
474 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700475
Zheng Bao7c5ad882023-02-19 13:02:52 +0800476
477static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
478{
479 amd_fw_entry *index;
480
481 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
482 if (index->filename &&
483 index->type != AMD_FW_VERSTAGE_SIG &&
484 index->type != AMD_FW_PSP_VERSTAGE &&
485 index->type != AMD_FW_SPL &&
486 index->type != AMD_FW_PSP_WHITELIST) {
487 free(index->filename);
488 index->filename = NULL;
489 }
490 }
491}
492
493static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
494{
495 amd_bios_entry *index;
496
497 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
498 if (index->filename &&
499 index->type != AMD_BIOS_APCB &&
500 index->type != AMD_BIOS_BIN &&
501 index->type != AMD_BIOS_APCB_BK &&
502 index->type != AMD_BIOS_UCODE) {
503 free(index->filename);
504 index->filename = NULL;
505 }
506 }
507}
508
509static void amdfwtool_cleanup(context *ctx)
510{
511 free(ctx->rom);
512 ctx->rom = NULL;
513
514 /* Free the filename. */
515 free_psp_firmware_filenames(amd_psp_fw_table);
516 free_bdt_firmware_filenames(amd_bios_table);
517}
518
Zheng Bao5164e4b2021-10-30 12:09:07 +0800519void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
520{
521 if (count >= max) {
522 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
523 "(%d)\n", count, max);
Zheng Bao7c5ad882023-02-19 13:02:52 +0800524 amdfwtool_cleanup(ctx);
Zheng Bao5164e4b2021-10-30 12:09:07 +0800525 exit(1);
526 }
527}
528
Zheng Baoc26108f2023-02-17 11:01:07 +0800529static void set_current_pointer(context *ctx, uint32_t value)
530{
531 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
532 ctx->current_pointer_saved != ctx->current) {
533 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800534 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800535 exit(1);
536 }
537
538 ctx->current = value;
539
540 if (ctx->current > ctx->rom_size) {
541 fprintf(stderr, "Error: Packing data causes overflow\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800542 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800543 exit(1);
544 }
545
546 ctx->current_pointer_saved = ctx->current;
547}
548
549static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
550{
551 /* Get */
552 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
553}
554
Marshall Dawson24f73d42019-04-01 10:48:43 -0600555static void *new_psp_dir(context *ctx, int multi)
Marshall Dawson2794a862019-03-04 16:53:15 -0700556{
557 void *ptr;
558
Marshall Dawson24f73d42019-04-01 10:48:43 -0600559 /*
560 * Force both onto boundary when multi. Primary table is after
561 * updatable table, so alignment ensures primary can stay intact
562 * if secondary is reprogrammed.
563 */
564 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +0800565 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600566 else
Zheng Baoc26108f2023-02-17 11:01:07 +0800567 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600568
Marshall Dawson2794a862019-03-04 16:53:15 -0700569 ptr = BUFF_CURRENT(*ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800570 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800571 ((psp_directory_header *)ptr)->additional_info = 0;
572 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +0800573 adjust_current_pointer(ctx,
574 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
575 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700576 return ptr;
577}
578
Zheng Baofdd47ef2021-09-17 13:30:08 +0800579static void *new_ish_dir(context *ctx)
580{
581 void *ptr;
Zheng Baoc26108f2023-02-17 11:01:07 +0800582 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800583 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800584 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
585
Zheng Baofdd47ef2021-09-17 13:30:08 +0800586 return ptr;
587}
588
Marshall Dawson2794a862019-03-04 16:53:15 -0700589static void *new_combo_dir(context *ctx)
590{
591 void *ptr;
592
Zheng Baoc26108f2023-02-17 11:01:07 +0800593 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700594 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800595 adjust_current_pointer(ctx,
596 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
597 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700598 return ptr;
599}
600
Zheng Baobf29a0d2020-12-03 23:00:48 +0800601static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800602{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600603 psp_combo_directory *cdir = directory;
604 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600605 bios_directory_table *bdir = directory;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800606 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600607
608 if (!count)
609 return;
Zheng Baob035f582021-05-27 11:26:12 +0800610 if (ctx == NULL || directory == NULL) {
611 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
612 return;
613 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600614
Zheng Baobf29a0d2020-12-03 23:00:48 +0800615 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baoc26108f2023-02-17 11:01:07 +0800616 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800617
Marshall Dawson24f73d42019-04-01 10:48:43 -0600618 switch (cookie) {
619 case PSP2_COOKIE:
Zheng Bao84fb9ea2022-08-18 15:54:47 +0800620 case BHD2_COOKIE:
Marshall Dawsona378c222019-03-04 16:52:07 -0700621 cdir->header.cookie = cookie;
Zheng Baofd51af62022-08-18 15:26:39 +0800622 /* lookup mode is hardcoded for now. */
623 cdir->header.lookup = 1;
Marshall Dawsona378c222019-03-04 16:52:07 -0700624 cdir->header.num_entries = count;
625 cdir->header.reserved[0] = 0;
626 cdir->header.reserved[1] = 0;
627 /* checksum everything that comes after the Checksum field */
628 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
629 count * sizeof(psp_combo_entry)
630 + sizeof(cdir->header.num_entries)
631 + sizeof(cdir->header.lookup)
632 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600633 break;
634 case PSP_COOKIE:
635 case PSPL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800636 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800637 if ((table_size % TABLE_ALIGNMENT) != 0) {
638 fprintf(stderr, "The PSP table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800639 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800640 exit(1);
641 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700642 dir->header.cookie = cookie;
643 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800644 dir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
645 dir->header.additional_info_fields.spi_block_size = 1;
646 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700647 /* checksum everything that comes after the Checksum field */
648 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700649 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700650 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800651 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600652 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800653 case BHD_COOKIE:
654 case BHDL2_COOKIE:
Zheng Bao6fff2492021-11-15 19:53:21 +0800655 table_size = ctx->current - ctx->current_table;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800656 if ((table_size % TABLE_ALIGNMENT) != 0) {
657 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800658 amdfwtool_cleanup(ctx);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800659 exit(1);
660 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600661 bdir->header.cookie = cookie;
662 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800663 bdir->header.additional_info_fields.dir_size = table_size / TABLE_ALIGNMENT;
664 bdir->header.additional_info_fields.spi_block_size = 1;
665 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600666 /* checksum everything that comes after the Checksum field */
667 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
668 count * sizeof(bios_directory_entry)
669 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800670 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600671 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700672 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800673
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800674}
675
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800676static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
677 context *ctx, amd_cb_config *cb_config)
678{
679 switch (cb_config->soc_id) {
680 case PLATFORM_UNKNOWN:
681 amd_romsig->psp_directory =
682 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
683 break;
684 case PLATFORM_CEZANNE:
685 case PLATFORM_MENDOCINO:
686 case PLATFORM_PHOENIX:
687 case PLATFORM_GLINDA:
688 case PLATFORM_CARRIZO:
689 case PLATFORM_STONEYRIDGE:
690 case PLATFORM_RAVEN:
691 case PLATFORM_PICASSO:
692 case PLATFORM_LUCIENNE:
693 case PLATFORM_RENOIR:
694 default:
695 /* for combo, it is also combo_psp_directory */
696 amd_romsig->new_psp_directory =
697 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
698 break;
699 }
700}
701
702static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
703 context *ctx, amd_cb_config *cb_config)
704{
705 switch (cb_config->soc_id) {
706 case PLATFORM_RENOIR:
707 case PLATFORM_LUCIENNE:
708 case PLATFORM_CEZANNE:
709 if (!cb_config->recovery_ab)
710 amd_romsig->bios3_entry =
711 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
712 break;
713 case PLATFORM_MENDOCINO:
714 case PLATFORM_PHOENIX:
715 case PLATFORM_GLINDA:
716 break;
717 case PLATFORM_CARRIZO:
718 case PLATFORM_STONEYRIDGE:
719 case PLATFORM_RAVEN:
720 case PLATFORM_PICASSO:
721 default:
722 amd_romsig->bios1_entry =
723 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
724 break;
725 }
726}
727
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700728static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
729{
730 int fd;
731 struct stat fd_stat;
732 ssize_t bytes;
733
734 fd = open(src_file, O_RDONLY);
735 if (fd < 0) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800736 fprintf(stderr, "Error opening file: %s: %s\n",
Eric Peersaf505672020-03-05 16:04:15 -0700737 src_file, strerror(errno));
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700738 return -1;
739 }
740
741 if (fstat(fd, &fd_stat)) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800742 fprintf(stderr, "fstat error: %s\n", strerror(errno));
Jacob Garber967f8622019-07-02 10:35:10 -0600743 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700744 return -2;
745 }
746
Zheng Bao6d402ac2020-10-01 16:16:30 +0800747 if ((size_t)fd_stat.st_size > room) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800748 fprintf(stderr, "Error: %s will not fit. Exiting.\n", src_file);
Jacob Garber967f8622019-07-02 10:35:10 -0600749 close(fd);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700750 return -3;
751 }
752
753 bytes = read(fd, dest, (size_t)fd_stat.st_size);
754 close(fd);
755 if (bytes != (ssize_t)fd_stat.st_size) {
Zheng Bao77a2c672020-10-01 17:05:43 +0800756 fprintf(stderr, "Error while reading %s\n", src_file);
Marshall Dawson8e0dca02019-02-27 18:40:49 -0700757 return -4;
758 }
759
760 return bytes;
761}
762
Zheng Baoeb0404e2021-10-14 15:09:09 +0800763static uint32_t get_psp_id(enum platform soc_id)
764{
765 uint32_t psp_id;
766 switch (soc_id) {
767 case PLATFORM_RAVEN:
768 case PLATFORM_PICASSO:
769 psp_id = 0xBC0A0000;
770 break;
771 case PLATFORM_RENOIR:
772 case PLATFORM_LUCIENNE:
773 psp_id = 0xBC0C0000;
774 break;
775 case PLATFORM_CEZANNE:
776 psp_id = 0xBC0C0140;
777 break;
778 case PLATFORM_MENDOCINO:
779 psp_id = 0xBC0D0900;
780 break;
781 case PLATFORM_STONEYRIDGE:
782 psp_id = 0x10220B00;
783 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800784 case PLATFORM_GLINDA:
785 psp_id = 0xBC0E0200;
786 break;
787 case PLATFORM_PHOENIX:
788 psp_id = 0xBC0D0400;
789 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800790 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800791 default:
792 psp_id = 0;
793 break;
794 }
795 return psp_id;
796}
797
Marshall Dawson2794a862019-03-04 16:53:15 -0700798static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700799 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700800 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800801{
Richard Spiegel137484d2018-01-17 10:23:19 -0700802 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800803 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700804
Zheng Baoc26108f2023-02-17 11:01:07 +0800805 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800806
Martin Rothcd15bc82016-11-08 11:34:02 -0700807 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800808 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800809 switch (fw_table[i].type) {
810 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800811 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700812 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800813 break;
814 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700815 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800816 break;
817 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700818 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800819 break;
820 default:
821 /* Error */
822 break;
823 }
824
Marshall Dawson2794a862019-03-04 16:53:15 -0700825 bytes = copy_blob(BUFF_CURRENT(*ctx),
826 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600827 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800828 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700829 exit(1);
830 }
831
Zheng Baoc26108f2023-02-17 11:01:07 +0800832 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800833 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800834 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800835}
836
Zheng Bao9e908072020-10-28 11:39:13 +0800837/* For debugging */
838static void dump_psp_firmwares(amd_fw_entry *fw_table)
839{
840 amd_fw_entry *index;
841
842 printf("PSP firmware components:");
843 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
844 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800845 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800846 }
847}
848
849static void dump_bdt_firmwares(amd_bios_entry *fw_table)
850{
851 amd_bios_entry *index;
852
853 printf("BIOS Directory Table (BDT) components:");
854 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
855 if (index->filename)
Zheng Bao826f1c42021-05-25 16:26:55 +0800856 printf(" %2x: %s\n", index->type, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800857 }
858}
859
Zheng Bao990d1542021-09-17 13:24:54 +0800860static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800861 psp_directory_table *pspdir2, ish_directory_table *ish,
862 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800863{
864 uint32_t count;
865 uint32_t current_table_save;
866
867 current_table_save = ctx->current_table;
868 ctx->current_table = (char *)pspdir - ctx->rom;
869 count = pspdir->header.num_entries;
870 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
871 pspdir->entries[count].type = (uint8_t)ab;
872 pspdir->entries[count].subprog = 0;
873 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800874 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600875 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800876 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
877 ish->update_retry_count = 2;
878 ish->glitch_retry_count = 0;
879 ish->psp_id = get_psp_id(soc_id);
880 ish->checksum = fletcher32(&ish->boot_priority,
881 sizeof(ish_directory_table) - sizeof(uint32_t));
882 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600883 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800884 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600885 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800886 pspdir->entries[count].size = TABLE_ALIGNMENT;
887 } else {
888 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600889 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800890 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600891 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800892 pspdir->entries[count].size = pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800893 sizeof(psp_directory_entry) +
894 sizeof(psp_directory_header);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800895 }
Zheng Bao990d1542021-09-17 13:24:54 +0800896
897 count++;
898 pspdir->header.num_entries = count;
899 ctx->current_table = current_table_save;
900}
901
Marshall Dawson2794a862019-03-04 16:53:15 -0700902static void integrate_psp_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700903 psp_directory_table *pspdir,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600904 psp_directory_table *pspdir2,
Zheng Bao990d1542021-09-17 13:24:54 +0800905 psp_directory_table *pspdir2_b,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600906 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800907 uint32_t cookie,
908 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800909{
Richard Spiegel137484d2018-01-17 10:23:19 -0700910 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700911 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600912 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530913 uint32_t size;
914 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800915 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800916 bool recovery_ab = cb_config->recovery_ab;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800917 ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600918
919 /* This function can create a primary table, a secondary table, or a
920 * flattened table which contains all applicable types. These if-else
921 * statements infer what the caller intended. If a 2nd-level cookie
922 * is passed, clearly a 2nd-level table is intended. However, a
923 * 1st-level cookie may indicate level 1 or flattened. If the caller
924 * passes a pointer to a 2nd-level table, then assume not flat.
925 */
Zheng Baoba3af5e2021-11-04 18:56:47 +0800926 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800927 level = PSP_BOTH;
928 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600929 level = PSP_LVL2;
930 else if (pspdir2)
931 level = PSP_LVL1;
932 else
933 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -0700934
Zheng Bao990d1542021-09-17 13:24:54 +0800935 if (recovery_ab) {
936 if (cookie == PSPL2_COOKIE)
937 level = PSP_LVL2_AB;
938 else if (pspdir2)
939 level = PSP_LVL1_AB;
940 else
941 level = PSP_BOTH_AB;
942 }
Zheng Bao6fff2492021-11-15 19:53:21 +0800943 current_table_save = ctx->current_table;
944 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +0800945 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800946
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700947 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -0600948 if (!(fw_table[i].level & level))
949 continue;
950
Zheng Bao5164e4b2021-10-30 12:09:07 +0800951 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
952
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600953 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
954 if (!fw_table[i].other)
955 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +0800956 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600957 pspdir->entries[count].type = fw_table[i].type;
958 pspdir->entries[count].size = 4096; /* TODO: doc? */
959 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +0800960 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600961 pspdir->entries[count].subprog = fw_table[i].subprog;
962 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +0800963 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600964 count++;
965 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -0700966 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -0700967 pspdir->entries[count].subprog = fw_table[i].subprog;
968 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -0700969 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -0600970 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +0800971 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700972 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -0600973 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +0530974 if (fw_table[i].filename == NULL) {
975 if (fw_table[i].size == 0)
976 continue;
977 size = fw_table[i].size;
978 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +0200979 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +0530980 fprintf(stderr,
981 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800982 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530983 exit(1);
984 }
985 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +0800986 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530987 bytes = copy_blob(BUFF_CURRENT(*ctx),
988 fw_table[i].filename, BUFF_ROOM(*ctx));
989 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800990 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530991 exit(1);
992 }
993
Elyes Haouas7d67a192022-10-14 09:58:29 +0200994 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +0530995 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800996 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -0600997 }
998
999 pspdir->entries[count].type = fw_table[i].type;
1000 pspdir->entries[count].subprog = fw_table[i].subprog;
1001 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301002 pspdir->entries[count].size = size;
1003 pspdir->entries[count].addr = addr;
1004
Zheng Bao6fff2492021-11-15 19:53:21 +08001005 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001006 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001007
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001008 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001009 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001010 if (fw_table[i].addr_signed) {
1011 pspdir->entries[count].addr =
1012 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1013 pspdir->entries[count].address_mode =
1014 SET_ADDR_MODE_BY_TABLE(pspdir);
1015 bytes = fw_table[i].file_size;
1016 } else {
1017 bytes = copy_blob(BUFF_CURRENT(*ctx),
1018 fw_table[i].filename, BUFF_ROOM(*ctx));
1019 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001020 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001021 exit(1);
1022 }
1023 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1024 pspdir->entries[count].address_mode =
1025 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001026 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001027 }
1028
Marshall Dawson239286c2019-02-23 16:42:46 -07001029 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001030 pspdir->entries[count].subprog = fw_table[i].subprog;
1031 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001032 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001033 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001034
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001035 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001036 } else {
1037 /* This APU doesn't have this firmware. */
1038 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001039 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001040
Zheng Bao990d1542021-09-17 13:24:54 +08001041 if (recovery_ab && (pspdir2 != NULL)) {
Zheng Baofdd47ef2021-09-17 13:30:08 +08001042 if (cb_config->need_ish) { /* Need ISH */
1043 ish_a_dir = new_ish_dir(ctx);
1044 if (pspdir2_b != NULL)
1045 ish_b_dir = new_ish_dir(ctx);
1046 }
Zheng Bao990d1542021-09-17 13:24:54 +08001047 pspdir->header.num_entries = count;
Zheng Baofdd47ef2021-09-17 13:30:08 +08001048 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001049 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
Zheng Bao990d1542021-09-17 13:24:54 +08001050 if (pspdir2_b != NULL)
Zheng Baofdd47ef2021-09-17 13:30:08 +08001051 integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001052 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001053 else
Karthikeyan Ramasubramaniane5af14a2022-08-02 11:34:48 -06001054 integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001055 AMD_FW_RECOVERYAB_B, cb_config->soc_id);
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001056
Zheng Bao990d1542021-09-17 13:24:54 +08001057 count = pspdir->header.num_entries;
1058 } else if (pspdir2 != NULL) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001059 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001060 pspdir->entries[count].type = AMD_FW_L2_PTR;
1061 pspdir->entries[count].subprog = 0;
1062 pspdir->entries[count].rsvd = 0;
1063 pspdir->entries[count].size = sizeof(pspdir2->header)
1064 + pspdir2->header.num_entries
1065 * sizeof(psp_directory_entry);
1066
Zheng Bao6fff2492021-11-15 19:53:21 +08001067 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001068 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001069 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001070 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson24f73d42019-04-01 10:48:43 -06001071 count++;
1072 }
1073
Zheng Baobf29a0d2020-12-03 23:00:48 +08001074 fill_dir_header(pspdir, count, cookie, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001075 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001076}
1077
Zheng Bao990d1542021-09-17 13:24:54 +08001078static void add_psp_firmware_entry(context *ctx,
1079 psp_directory_table *pspdir,
1080 void *table, amd_fw_type type, uint32_t size)
1081{
1082 uint32_t count = pspdir->header.num_entries;
1083 uint32_t index;
1084 uint32_t current_table_save;
1085
1086 current_table_save = ctx->current_table;
1087 ctx->current_table = (char *)pspdir - ctx->rom;
1088
1089 /* If there is an entry of "type", replace it. */
1090 for (index = 0; index < count; index++) {
1091 if (pspdir->entries[index].type == (uint8_t)type)
1092 break;
1093 }
1094
1095 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1096 pspdir->entries[index].type = (uint8_t)type;
1097 pspdir->entries[index].subprog = 0;
1098 pspdir->entries[index].rsvd = 0;
1099 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1100 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1101 pspdir->entries[index].size = size;
1102 if (index == count)
1103 count++;
1104
1105 pspdir->header.num_entries = count;
1106 pspdir->header.checksum = fletcher32(&pspdir->header.num_entries,
1107 count * sizeof(psp_directory_entry)
1108 + sizeof(pspdir->header.num_entries)
1109 + sizeof(pspdir->header.additional_info));
1110
1111 ctx->current_table = current_table_save;
1112}
1113
Zheng Baoba3af5e2021-11-04 18:56:47 +08001114static void *new_bios_dir(context *ctx, bool multi)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001115{
1116 void *ptr;
1117
1118 /*
1119 * Force both onto boundary when multi. Primary table is after
1120 * updatable table, so alignment ensures primary can stay intact
1121 * if secondary is reprogrammed.
1122 */
1123 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001124 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001125 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001126 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001127 ptr = BUFF_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001128 ((bios_directory_hdr *) ptr)->additional_info = 0;
1129 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1130 ctx->current_table = ctx->current;
Zheng Baoc26108f2023-02-17 11:01:07 +08001131 adjust_current_pointer(ctx,
1132 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1133 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001134 return ptr;
1135}
1136
1137static int locate_bdt2_bios(bios_directory_table *level2,
1138 uint64_t *source, uint32_t *size)
1139{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001140 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001141
1142 *source = 0;
1143 *size = 0;
1144 if (!level2)
1145 return 0;
1146
1147 for (i = 0 ; i < level2->header.num_entries ; i++) {
1148 if (level2->entries[i].type == AMD_BIOS_BIN) {
1149 *source = level2->entries[i].source;
1150 *size = level2->entries[i].size;
1151 return 1;
1152 }
1153 }
1154 return 0;
1155}
1156
1157static int have_bios_tables(amd_bios_entry *table)
1158{
1159 int i;
1160
1161 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1162 if (table[i].level & BDT_LVL1 && table[i].filename)
1163 return 1;
1164 }
1165 return 0;
1166}
1167
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001168static int find_bios_entry(amd_bios_type type)
1169{
1170 int i;
1171
1172 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1173 if (amd_bios_table[i].type == type)
1174 return i;
1175 }
1176 return -1;
1177}
1178
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001179static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1180 int inst, uint32_t size, uint64_t source)
1181{
1182 int i;
1183
1184 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1185 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1186 amd_bios_table[i].inst == inst)
1187 break;
1188 }
1189
1190 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1191 return;
1192
1193 biosdir->entries[idx].type = amd_bios_table[i].type;
1194 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1195 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1196 amd_bios_table[i].dest : (uint64_t)-1;
1197 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1198 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1199 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1200 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1201 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1202 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1203 biosdir->entries[idx].size = size;
1204 biosdir->entries[idx].source = source;
1205 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1206}
1207
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001208static void integrate_bios_firmwares(context *ctx,
1209 bios_directory_table *biosdir,
1210 bios_directory_table *biosdir2,
1211 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001212 uint32_t cookie,
1213 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001214{
1215 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001216 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001217 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001218 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001219 uint32_t size;
1220 uint64_t source;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001221
1222 /* This function can create a primary table, a secondary table, or a
1223 * flattened table which contains all applicable types. These if-else
1224 * statements infer what the caller intended. If a 2nd-level cookie
1225 * is passed, clearly a 2nd-level table is intended. However, a
1226 * 1st-level cookie may indicate level 1 or flattened. If the caller
1227 * passes a pointer to a 2nd-level table, then assume not flat.
1228 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001229 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001230 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001231 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001232 level = BDT_LVL2;
1233 else if (biosdir2)
1234 level = BDT_LVL1;
1235 else
1236 level = BDT_BOTH;
1237
Zheng Baoc26108f2023-02-17 11:01:07 +08001238 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001239
1240 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1241 if (!(fw_table[i].level & level))
1242 continue;
1243 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301244 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001245 fw_table[i].type != AMD_BIOS_APOB &&
1246 fw_table[i].type != AMD_BIOS_APOB_NV &&
1247 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001248 fw_table[i].type != AMD_BIOS_BIN &&
1249 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001250 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001251
1252 /* BIOS Directory items may have additional requirements */
1253
Ritul Guru9a321f32022-07-29 11:06:40 +05301254 /* SIG needs a size, else no choice but to skip */
1255 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1256 continue;
1257
Martin Roth48dd9fe2020-07-29 16:32:25 -06001258 /* Check APOB_NV requirements */
1259 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1260 if (!fw_table[i].size && !fw_table[i].src)
1261 continue; /* APOB_NV not used */
1262 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001263 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001264 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001265 exit(1);
1266 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001267 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001268 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001269 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1270 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001271 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001272
1273 /* APOB_DATA needs destination */
1274 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001275 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001276 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001277 exit(1);
1278 }
1279
1280 /* BIOS binary must have destination and uncompressed size. If
1281 * no filename given, then user must provide a source address.
1282 */
1283 if (fw_table[i].type == AMD_BIOS_BIN) {
1284 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001285 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001286 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001287 exit(1);
1288 }
1289 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001290 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001291 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001292 exit(1);
1293 }
1294 }
1295
Martin Roth94554742020-04-14 14:59:36 -06001296 /* PSP_SHARED_MEM needs a destination and size */
1297 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1298 (!fw_table[i].dest || !fw_table[i].size))
1299 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001300 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001301
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001302 biosdir->entries[count].type = fw_table[i].type;
1303 biosdir->entries[count].region_type = fw_table[i].region_type;
1304 biosdir->entries[count].dest = fw_table[i].dest ?
1305 fw_table[i].dest : (uint64_t)-1;
1306 biosdir->entries[count].reset = fw_table[i].reset;
1307 biosdir->entries[count].copy = fw_table[i].copy;
1308 biosdir->entries[count].ro = fw_table[i].ro;
1309 biosdir->entries[count].compressed = fw_table[i].zlib;
1310 biosdir->entries[count].inst = fw_table[i].inst;
1311 biosdir->entries[count].subprog = fw_table[i].subpr;
1312
1313 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301314 case AMD_BIOS_SIG:
1315 /* Reserve size bytes within amdfw.rom */
1316 biosdir->entries[count].size = fw_table[i].size;
1317 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1318 biosdir->entries[count].address_mode =
1319 SET_ADDR_MODE_BY_TABLE(biosdir);
1320 memset(BUFF_CURRENT(*ctx), 0xff,
1321 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001322 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301323 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001324 case AMD_BIOS_APOB:
1325 biosdir->entries[count].size = fw_table[i].size;
1326 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001327 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001328 break;
1329 case AMD_BIOS_APOB_NV:
1330 if (fw_table[i].src) {
1331 /* If source is given, use that and its size */
1332 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001333 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001334 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001335 biosdir->entries[count].size = fw_table[i].size;
1336 } else {
1337 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001338 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001339 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001340 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001341 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001342 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001343 fw_table[i].size, ERASE_ALIGNMENT);
1344 memset(BUFF_CURRENT(*ctx), 0xff,
1345 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001346 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001347 }
1348 break;
1349 case AMD_BIOS_BIN:
1350 /* Don't make a 2nd copy, point to the same one */
Martin Rotheca423b2020-09-01 10:54:11 -06001351 if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, &source, &size)) {
1352 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001353 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001354 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001355 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001356 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001357 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001358
1359 /* level 2, or level 1 and no copy found in level 2 */
1360 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001361 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001362 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001363 biosdir->entries[count].dest = fw_table[i].dest;
1364 biosdir->entries[count].size = fw_table[i].size;
1365
1366 if (!fw_table[i].filename)
1367 break;
1368
1369 bytes = copy_blob(BUFF_CURRENT(*ctx),
1370 fw_table[i].filename, BUFF_ROOM(*ctx));
1371 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001372 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001373 exit(1);
1374 }
1375
Zheng Bao6fff2492021-11-15 19:53:21 +08001376 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001377 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001378 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001379 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001380
Zheng Baoc26108f2023-02-17 11:01:07 +08001381 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001382 break;
Martin Roth94554742020-04-14 14:59:36 -06001383 case AMD_BIOS_PSP_SHARED_MEM:
1384 biosdir->entries[count].dest = fw_table[i].dest;
1385 biosdir->entries[count].size = fw_table[i].size;
1386 break;
1387
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001388 default: /* everything else is copied from input */
1389 if (fw_table[i].type == AMD_BIOS_APCB ||
1390 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001391 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001392 bytes = copy_blob(BUFF_CURRENT(*ctx),
1393 fw_table[i].filename, BUFF_ROOM(*ctx));
1394 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001395 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001396 exit(1);
1397 }
1398
1399 biosdir->entries[count].size = (uint32_t)bytes;
1400 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001401 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001402
Zheng Baoc26108f2023-02-17 11:01:07 +08001403 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001404 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1405 size = biosdir->entries[count].size;
1406 source = biosdir->entries[count].source;
1407 count++;
1408 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1409 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001410 break;
1411 }
1412
1413 count++;
1414 }
1415
1416 if (biosdir2) {
Zheng Bao5164e4b2021-10-30 12:09:07 +08001417 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001418 biosdir->entries[count].type = AMD_BIOS_L2_PTR;
Zheng Baoe8e60432021-05-24 16:11:12 +08001419 biosdir->entries[count].region_type = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001420 biosdir->entries[count].size =
1421 + MAX_BIOS_ENTRIES
1422 * sizeof(bios_directory_entry);
1423 biosdir->entries[count].source =
1424 BUFF_TO_RUN(*ctx, biosdir2);
Zheng Bao6fff2492021-11-15 19:53:21 +08001425 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001426 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001427 biosdir->entries[count].subprog = 0;
1428 biosdir->entries[count].inst = 0;
1429 biosdir->entries[count].copy = 0;
1430 biosdir->entries[count].compressed = 0;
1431 biosdir->entries[count].dest = -1;
1432 biosdir->entries[count].reset = 0;
1433 biosdir->entries[count].ro = 0;
1434 count++;
1435 }
1436
Zheng Baobf29a0d2020-12-03 23:00:48 +08001437 fill_dir_header(biosdir, count, cookie, ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001438}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001439
1440enum {
Zheng Bao806892a2021-04-27 17:21:54 +08001441 AMDFW_OPT_CONFIG = 'c',
1442 AMDFW_OPT_DEBUG = 'd',
1443 AMDFW_OPT_HELP = 'h',
Zheng Bao806892a2021-04-27 17:21:54 +08001444
1445 AMDFW_OPT_XHCI = 128,
1446 AMDFW_OPT_IMC,
1447 AMDFW_OPT_GEC,
Zheng Bao990d1542021-09-17 13:24:54 +08001448 AMDFW_OPT_RECOVERY_AB,
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001449 AMDFW_OPT_RECOVERY_AB_SINGLE_COPY,
Zheng Bao993b43f2021-11-10 12:21:46 +08001450 AMDFW_OPT_USE_COMBO,
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001451 AMDFW_OPT_COMBO1_CONFIG,
Zheng Bao806892a2021-04-27 17:21:54 +08001452 AMDFW_OPT_MULTILEVEL,
1453 AMDFW_OPT_NVRAM,
1454
1455 AMDFW_OPT_FUSE,
1456 AMDFW_OPT_UNLOCK,
1457 AMDFW_OPT_WHITELIST,
1458 AMDFW_OPT_USE_PSPSECUREOS,
1459 AMDFW_OPT_LOAD_MP2FW,
1460 AMDFW_OPT_LOAD_S0I3,
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001461 AMDFW_OPT_SPL_TABLE,
Zheng Bao806892a2021-04-27 17:21:54 +08001462 AMDFW_OPT_VERSTAGE,
1463 AMDFW_OPT_VERSTAGE_SIG,
1464
1465 AMDFW_OPT_INSTANCE,
1466 AMDFW_OPT_APCB,
1467 AMDFW_OPT_APOBBASE,
1468 AMDFW_OPT_BIOSBIN,
1469 AMDFW_OPT_BIOSBIN_SOURCE,
1470 AMDFW_OPT_BIOSBIN_DEST,
1471 AMDFW_OPT_BIOS_UNCOMP_SIZE,
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001472 AMDFW_OPT_BIOSBIN_UNCOMP,
Zheng Bao806892a2021-04-27 17:21:54 +08001473 AMDFW_OPT_UCODE,
1474 AMDFW_OPT_APOB_NVBASE,
1475 AMDFW_OPT_APOB_NVSIZE,
1476
1477 AMDFW_OPT_OUTPUT,
1478 AMDFW_OPT_FLASHSIZE,
1479 AMDFW_OPT_LOCATION,
1480 AMDFW_OPT_ANYWHERE,
1481 AMDFW_OPT_SHAREDMEM,
1482 AMDFW_OPT_SHAREDMEM_SIZE,
Kangheui Won3c164e12021-12-03 20:25:05 +11001483 AMDFW_OPT_SIGNED_OUTPUT,
1484 AMDFW_OPT_SIGNED_ADDR,
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001485 AMDFW_OPT_BODY_LOCATION,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001486 /* begin after ASCII characters */
1487 LONGOPT_SPI_READ_MODE = 256,
1488 LONGOPT_SPI_SPEED = 257,
1489 LONGOPT_SPI_MICRON_FLAG = 258,
Ritul Guru9a321f32022-07-29 11:06:40 +05301490 LONGOPT_BIOS_SIG = 259,
Ritul Gurua2cb3402022-08-29 00:51:08 +05301491 LONGOPT_NVRAM_BASE = 260,
1492 LONGOPT_NVRAM_SIZE = 261,
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001493};
1494
Zheng Bao806892a2021-04-27 17:21:54 +08001495static char const optstring[] = {AMDFW_OPT_CONFIG, ':',
Zheng Bao994ff522023-03-09 11:43:55 +08001496 AMDFW_OPT_DEBUG, AMDFW_OPT_HELP
Zheng Bao806892a2021-04-27 17:21:54 +08001497};
Marc Jones90099b62016-09-20 21:05:45 -06001498
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001499static struct option long_options[] = {
Zheng Bao806892a2021-04-27 17:21:54 +08001500 {"xhci", required_argument, 0, AMDFW_OPT_XHCI },
1501 {"imc", required_argument, 0, AMDFW_OPT_IMC },
1502 {"gec", required_argument, 0, AMDFW_OPT_GEC },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001503 /* PSP Directory Table items */
Zheng Bao990d1542021-09-17 13:24:54 +08001504 {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB },
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001505 {"recovery-ab-single-copy", no_argument, 0, AMDFW_OPT_RECOVERY_AB_SINGLE_COPY },
Zheng Bao993b43f2021-11-10 12:21:46 +08001506 {"use-combo", no_argument, 0, AMDFW_OPT_USE_COMBO },
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001507 {"combo-config1", required_argument, 0, AMDFW_OPT_COMBO1_CONFIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001508 {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL },
1509 {"nvram", required_argument, 0, AMDFW_OPT_NVRAM },
Ritul Gurua2cb3402022-08-29 00:51:08 +05301510 {"nvram-base", required_argument, 0, LONGOPT_NVRAM_BASE },
1511 {"nvram-size", required_argument, 0, LONGOPT_NVRAM_SIZE },
Zheng Bao806892a2021-04-27 17:21:54 +08001512 {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE },
1513 {"token-unlock", no_argument, 0, AMDFW_OPT_UNLOCK },
1514 {"whitelist", required_argument, 0, AMDFW_OPT_WHITELIST },
1515 {"use-pspsecureos", no_argument, 0, AMDFW_OPT_USE_PSPSECUREOS },
1516 {"load-mp2-fw", no_argument, 0, AMDFW_OPT_LOAD_MP2FW },
1517 {"load-s0i3", no_argument, 0, AMDFW_OPT_LOAD_S0I3 },
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001518 {"spl-table", required_argument, 0, AMDFW_OPT_SPL_TABLE },
Zheng Bao806892a2021-04-27 17:21:54 +08001519 {"verstage", required_argument, 0, AMDFW_OPT_VERSTAGE },
1520 {"verstage_sig", required_argument, 0, AMDFW_OPT_VERSTAGE_SIG },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001521 /* BIOS Directory Table items */
Zheng Bao806892a2021-04-27 17:21:54 +08001522 {"instance", required_argument, 0, AMDFW_OPT_INSTANCE },
1523 {"apcb", required_argument, 0, AMDFW_OPT_APCB },
1524 {"apob-base", required_argument, 0, AMDFW_OPT_APOBBASE },
1525 {"bios-bin", required_argument, 0, AMDFW_OPT_BIOSBIN },
1526 {"bios-bin-src", required_argument, 0, AMDFW_OPT_BIOSBIN_SOURCE },
1527 {"bios-bin-dest", required_argument, 0, AMDFW_OPT_BIOSBIN_DEST },
1528 {"bios-uncomp-size", required_argument, 0, AMDFW_OPT_BIOS_UNCOMP_SIZE },
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001529 {"bios-bin-uncomp", no_argument, 0, AMDFW_OPT_BIOSBIN_UNCOMP },
Ritul Guru9a321f32022-07-29 11:06:40 +05301530 {"bios-sig-size", required_argument, 0, LONGOPT_BIOS_SIG },
Zheng Bao806892a2021-04-27 17:21:54 +08001531 {"ucode", required_argument, 0, AMDFW_OPT_UCODE },
1532 {"apob-nv-base", required_argument, 0, AMDFW_OPT_APOB_NVBASE },
1533 {"apob-nv-size", required_argument, 0, AMDFW_OPT_APOB_NVSIZE },
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001534 /* Embedded Firmware Structure items*/
1535 {"spi-read-mode", required_argument, 0, LONGOPT_SPI_READ_MODE },
1536 {"spi-speed", required_argument, 0, LONGOPT_SPI_SPEED },
1537 {"spi-micron-flag", required_argument, 0, LONGOPT_SPI_MICRON_FLAG },
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001538 {"body-location", required_argument, 0, AMDFW_OPT_BODY_LOCATION },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001539 /* other */
Zheng Bao806892a2021-04-27 17:21:54 +08001540 {"output", required_argument, 0, AMDFW_OPT_OUTPUT },
1541 {"flashsize", required_argument, 0, AMDFW_OPT_FLASHSIZE },
1542 {"location", required_argument, 0, AMDFW_OPT_LOCATION },
1543 {"anywhere", no_argument, 0, AMDFW_OPT_ANYWHERE },
1544 {"sharedmem", required_argument, 0, AMDFW_OPT_SHAREDMEM },
1545 {"sharedmem-size", required_argument, 0, AMDFW_OPT_SHAREDMEM_SIZE },
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001546
Kangheui Won3c164e12021-12-03 20:25:05 +11001547 {"signed-output", required_argument, 0, AMDFW_OPT_SIGNED_OUTPUT },
1548 {"signed-addr", required_argument, 0, AMDFW_OPT_SIGNED_ADDR },
1549
Zheng Bao806892a2021-04-27 17:21:54 +08001550 {"config", required_argument, 0, AMDFW_OPT_CONFIG },
1551 {"debug", no_argument, 0, AMDFW_OPT_DEBUG },
1552 {"help", no_argument, 0, AMDFW_OPT_HELP },
Marshall Dawsonf4b9b412017-03-17 16:30:51 -06001553 {NULL, 0, 0, 0 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001554};
1555
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001556void register_fw_fuse(char *str)
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001557{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001558 uint32_t i;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001559
1560 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1561 if (amd_psp_fw_table[i].type != AMD_PSP_FUSE_CHAIN)
1562 continue;
1563
1564 amd_psp_fw_table[i].other = strtoull(str, NULL, 16);
1565 return;
1566 }
1567}
1568
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001569static void register_fw_token_unlock(void)
1570{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001571 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001572
1573 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1574 if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK)
1575 continue;
1576
1577 amd_psp_fw_table[i].other = 1;
1578 return;
1579 }
1580}
1581
Marshall Dawsondbae6322019-03-04 10:31:03 -07001582static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[])
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001583{
Martin Roth8806f7f2016-11-08 10:44:18 -07001584 unsigned int i;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001585
Martin Rothcd15bc82016-11-08 11:34:02 -07001586 for (i = 0; i < sizeof(amd_fw_table) / sizeof(amd_fw_entry); i++) {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001587 if (amd_fw_table[i].type == type) {
1588 amd_fw_table[i].filename = filename;
1589 return;
1590 }
1591 }
1592
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001593 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
Marshall Dawsondbae6322019-03-04 10:31:03 -07001594 if (amd_psp_fw_table[i].type != type)
1595 continue;
1596
1597 if (amd_psp_fw_table[i].subprog == sub) {
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001598 amd_psp_fw_table[i].filename = filename;
1599 return;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001600 }
1601 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001602}
1603
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001604static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[])
1605{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001606 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001607
1608 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1609 if (amd_bios_table[i].type == type
1610 && amd_bios_table[i].inst == ins
1611 && amd_bios_table[i].subpr == sub) {
1612 amd_bios_table[i].filename = name;
1613 return;
1614 }
1615 }
1616}
1617
Ritul Gurua2cb3402022-08-29 00:51:08 +05301618static void register_amd_psp_fw_addr(amd_fw_type type, int sub,
1619 char *dst_str, char *size_str)
1620{
1621 unsigned int i;
1622
1623 for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) {
1624 if (amd_psp_fw_table[i].type != type)
1625 continue;
1626
1627 if (amd_psp_fw_table[i].subprog == sub) {
1628 if (dst_str)
1629 amd_psp_fw_table[i].dest = strtoull(dst_str, NULL, 16);
1630 if (size_str)
1631 amd_psp_fw_table[i].size = strtoul(size_str, NULL, 16);
1632 return;
1633 }
1634 }
1635}
1636
1637static void register_bios_fw_addr(amd_bios_type type, char *src_str,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001638 char *dst_str, char *size_str)
1639{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001640 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001641 for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) {
1642 if (amd_bios_table[i].type != type)
1643 continue;
1644
1645 if (src_str)
1646 amd_bios_table[i].src = strtoull(src_str, NULL, 16);
1647 if (dst_str)
1648 amd_bios_table[i].dest = strtoull(dst_str, NULL, 16);
1649 if (size_str)
1650 amd_bios_table[i].size = strtoul(size_str, NULL, 16);
1651
1652 return;
1653 }
1654}
1655
Zheng Baoc3007f32022-04-03 12:53:51 +08001656static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1657 embedded_firmware *amd_romsig, uint8_t efs_spi_readmode,
1658 uint8_t efs_spi_speed, uint8_t efs_spi_micron_flag)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001659{
1660 if ((efs_spi_readmode == 0xFF) || (efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001661 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001662 return 1;
1663 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001664
1665 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1666 * Leave as 0xffffffff for first gen */
1667 if (cb_config->second_gen) {
1668 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1669 amd_romsig->efs_gen.reserved = 0;
1670 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001671 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1672 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001673 }
1674
1675 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001676 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001677 case PLATFORM_STONEYRIDGE:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001678 amd_romsig->spi_readmode_f15_mod_60_6f = efs_spi_readmode;
1679 amd_romsig->fast_speed_new_f15_mod_60_6f = efs_spi_speed;
1680 break;
1681 case PLATFORM_RAVEN:
1682 case PLATFORM_PICASSO:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001683 amd_romsig->spi_readmode_f17_mod_00_2f = efs_spi_readmode;
1684 amd_romsig->spi_fastspeed_f17_mod_00_2f = efs_spi_speed;
1685 switch (efs_spi_micron_flag) {
1686 case 0:
1687 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1688 break;
1689 case 1:
1690 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1691 break;
1692 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001693 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001694 return 1;
1695 }
1696 break;
1697 case PLATFORM_RENOIR:
1698 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001699 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001700 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001701 case PLATFORM_PHOENIX:
1702 case PLATFORM_GLINDA:
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001703 amd_romsig->spi_readmode_f17_mod_30_3f = efs_spi_readmode;
1704 amd_romsig->spi_fastspeed_f17_mod_30_3f = efs_spi_speed;
1705 switch (efs_spi_micron_flag) {
1706 case 0:
1707 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1708 break;
1709 case 1:
1710 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1711 break;
1712 case 2:
1713 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1714 break;
1715 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001716 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001717 return 1;
1718 }
1719 break;
1720 case PLATFORM_UNKNOWN:
1721 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001722 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001723 return 1;
1724 }
1725 return 0;
1726}
1727
Zheng Bao69ea83c2023-01-22 21:08:18 +08001728static ssize_t write_body(char *output, void *body_offset, ssize_t body_size, context *ctx)
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001729{
Zheng Bao69ea83c2023-01-22 21:08:18 +08001730 char body_name[PATH_MAX], body_tmp_name[PATH_MAX];
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001731 int ret;
1732 int fd;
1733 ssize_t bytes = -1;
1734
1735 /* Create a tmp file and rename it at the end so that make does not get confused
1736 if amdfwtool is killed for some unexpected reasons. */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001737 ret = snprintf(body_tmp_name, sizeof(body_tmp_name), "%s%s%s",
1738 output, BODY_FILE_SUFFIX, TMP_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001739 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001740 fprintf(stderr, "Error %s forming BODY tmp file name: %d\n",
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001741 strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001742 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001743 exit(1);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001744 } else if ((unsigned int)ret >= sizeof(body_tmp_name)) {
1745 fprintf(stderr, "BODY File name %d > %zu\n", ret, sizeof(body_tmp_name));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001746 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001747 exit(1);
1748 }
1749
Zheng Bao69ea83c2023-01-22 21:08:18 +08001750 fd = open(body_tmp_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001751 if (fd < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001752 fprintf(stderr, "Error: Opening %s file: %s\n", body_tmp_name, strerror(errno));
Zheng Bao7c5ad882023-02-19 13:02:52 +08001753 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001754 exit(1);
1755 }
1756
Zheng Bao69ea83c2023-01-22 21:08:18 +08001757 bytes = write_from_buf_to_file(fd, body_offset, body_size);
1758 if (bytes != body_size) {
1759 fprintf(stderr, "Error: Writing to file %s failed\n", body_tmp_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001760 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001761 exit(1);
1762 }
1763 close(fd);
1764
1765 /* Rename the tmp file */
Zheng Bao69ea83c2023-01-22 21:08:18 +08001766 ret = snprintf(body_name, sizeof(body_name), "%s%s", output, BODY_FILE_SUFFIX);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001767 if (ret < 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001768 fprintf(stderr, "Error %s forming BODY file name: %d\n", strerror(errno), ret);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001769 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001770 exit(1);
1771 }
1772
Zheng Bao69ea83c2023-01-22 21:08:18 +08001773 if (rename(body_tmp_name, body_name)) {
1774 fprintf(stderr, "Error: renaming file %s to %s\n", body_tmp_name, body_name);
Zheng Bao7c5ad882023-02-19 13:02:52 +08001775 amdfwtool_cleanup(ctx);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001776 exit(1);
1777 }
1778
1779 return bytes;
1780}
1781
Zheng Bao994ff522023-03-09 11:43:55 +08001782void open_process_config(char *config, amd_cb_config *cb_config, int debug)
Zheng Bao39cae562023-03-07 18:37:43 +08001783{
1784 FILE *config_handle;
1785
1786 if (config) {
1787 config_handle = fopen(config, "r");
1788 if (config_handle == NULL) {
1789 fprintf(stderr, "Can not open file %s for reading: %s\n",
1790 config, strerror(errno));
1791 exit(1);
1792 }
Zheng Bao994ff522023-03-09 11:43:55 +08001793 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001794 fprintf(stderr, "Configuration file %s parsing error\n",
1795 config);
1796 fclose(config_handle);
1797 exit(1);
1798 }
1799 fclose(config_handle);
1800 }
1801
1802 /* For debug. */
1803 if (debug) {
1804 dump_psp_firmwares(amd_psp_fw_table);
1805 dump_bdt_firmwares(amd_bios_table);
1806 }
1807}
1808
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001809static bool is_initial_alignment_required(enum platform soc_id)
1810{
1811 switch (soc_id) {
1812 case PLATFORM_MENDOCINO:
1813 case PLATFORM_PHOENIX:
1814 case PLATFORM_GLINDA:
1815 return false;
1816 default:
1817 return true;
1818 }
1819}
1820
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001821int main(int argc, char **argv)
1822{
Marshall Dawson0e02ce82019-03-04 16:50:37 -07001823 int c;
Martin Roth31d95a22016-11-08 11:22:12 -07001824 int retval = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001825 char *tmp;
Marshall Dawson239286c2019-02-23 16:42:46 -07001826 embedded_firmware *amd_romsig;
Zheng Bao990d1542021-09-17 13:24:54 +08001827 psp_directory_table *pspdir = NULL;
1828 psp_directory_table *pspdir2 = NULL;
1829 psp_directory_table *pspdir2_b = NULL;
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001830 psp_combo_directory *psp_combo_dir = NULL, *bhd_combo_dir = NULL;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001831 char *combo_config[MAX_COMBO_ENTRIES] = { 0 };
1832 int combo_index = 0;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001833 int fuse_defined = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001834 int targetfd;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001835 char *output = NULL, *config = NULL;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001836 context ctx = { 0 };
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001837 /* Values cleared after each firmware or parameter, regardless if N/A */
1838 uint8_t sub = 0, instance = 0;
Zheng Bao99945dc2023-01-02 10:55:56 +08001839 uint32_t body_location = 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001840 uint32_t efs_location = 0;
Martin Roth37305e72020-04-07 14:16:39 -06001841 bool any_location = 0;
Martin Roth0d3b1182017-10-03 14:16:04 -06001842 uint32_t romsig_offset;
Martin Roth60f15512016-11-08 09:55:01 -07001843 uint32_t rom_base_address;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001844 uint8_t efs_spi_readmode = 0xff;
1845 uint8_t efs_spi_speed = 0xff;
1846 uint8_t efs_spi_micron_flag = 0xff;
Kangheui Won3c164e12021-12-03 20:25:05 +11001847 const char *signed_output_file = NULL;
1848 uint64_t signed_start_addr = 0x0;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001849
Fred Reitbergerf36b0132022-06-29 13:54:57 -04001850 amd_cb_config cb_config = { 0 };
Zheng Bao9e908072020-10-28 11:39:13 +08001851 int debug = 0;
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001852
Zheng Baoc26108f2023-02-17 11:01:07 +08001853 ctx.current_pointer_saved = 0xFFFFFFFF;
1854
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001855 while (1) {
1856 int optindex = 0;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001857 int bios_tbl_index = -1;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001858
1859 c = getopt_long(argc, argv, optstring, long_options, &optindex);
1860
1861 if (c == -1)
1862 break;
1863
1864 switch (c) {
Zheng Bao806892a2021-04-27 17:21:54 +08001865 case AMDFW_OPT_XHCI:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001866 register_fw_filename(AMD_FW_XHCI, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001867 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001868 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001869 case AMDFW_OPT_IMC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001870 register_fw_filename(AMD_FW_IMC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001871 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001872 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001873 case AMDFW_OPT_GEC:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001874 register_fw_filename(AMD_FW_GEC, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001875 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001876 break;
Zheng Bao990d1542021-09-17 13:24:54 +08001877 case AMDFW_OPT_RECOVERY_AB:
1878 cb_config.recovery_ab = true;
1879 break;
Karthikeyan Ramasubramanianad06bae2022-04-08 14:19:55 -06001880 case AMDFW_OPT_RECOVERY_AB_SINGLE_COPY:
1881 cb_config.recovery_ab = true;
1882 cb_config.recovery_ab_single_copy = true;
1883 break;
Zheng Bao993b43f2021-11-10 12:21:46 +08001884 case AMDFW_OPT_USE_COMBO:
1885 cb_config.use_combo = true;
1886 break;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001887 case AMDFW_OPT_COMBO1_CONFIG:
1888 cb_config.use_combo = true;
Zheng Bao73917222023-03-15 16:14:03 +08001889 assert_fw_entry(1, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001890 combo_config[1] = optarg;
1891 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001892 case AMDFW_OPT_MULTILEVEL:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001893 cb_config.multi_level = true;
Marshall Dawson24f73d42019-04-01 10:48:43 -06001894 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001895 case AMDFW_OPT_UNLOCK:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001896 register_fw_token_unlock();
Zheng Baoba3af5e2021-11-04 18:56:47 +08001897 cb_config.unlock_secure = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001898 sub = instance = 0;
1899 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001900 case AMDFW_OPT_USE_PSPSECUREOS:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001901 cb_config.use_secureos = true;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001902 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001903 case AMDFW_OPT_INSTANCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001904 instance = strtoul(optarg, &tmp, 16);
1905 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001906 case AMDFW_OPT_LOAD_MP2FW:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001907 cb_config.load_mp2_fw = true;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001908 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001909 case AMDFW_OPT_NVRAM:
Marshall Dawsondbae6322019-03-04 10:31:03 -07001910 register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001911 sub = instance = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001912 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001913 case AMDFW_OPT_FUSE:
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001914 register_fw_fuse(optarg);
1915 fuse_defined = 1;
1916 sub = 0;
1917 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001918 case AMDFW_OPT_APCB:
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001919 if ((instance & 0xF0) == 0) {
Zheng Bao5caca942020-12-04 16:39:38 +08001920 register_bdt_data(AMD_BIOS_APCB, sub, instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001921 } else {
Zheng Bao5caca942020-12-04 16:39:38 +08001922 register_bdt_data(AMD_BIOS_APCB_BK, sub,
1923 instance & 0xF, optarg);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001924 cb_config.have_apcb_bk = 1;
1925 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001926 sub = instance = 0;
1927 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001928 case AMDFW_OPT_APOBBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001929 /* APOB destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301930 register_bios_fw_addr(AMD_BIOS_APOB, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001931 sub = instance = 0;
1932 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001933 case AMDFW_OPT_APOB_NVBASE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001934 /* APOB NV source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301935 register_bios_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001936 sub = instance = 0;
1937 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001938 case AMDFW_OPT_APOB_NVSIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001939 /* APOB NV size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301940 register_bios_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001941 sub = instance = 0;
1942 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001943 case AMDFW_OPT_BIOSBIN:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001944 register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg);
1945 sub = instance = 0;
1946 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001947 case AMDFW_OPT_BIOSBIN_SOURCE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001948 /* BIOS source */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301949 register_bios_fw_addr(AMD_BIOS_BIN, optarg, 0, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001950 sub = instance = 0;
1951 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001952 case AMDFW_OPT_BIOSBIN_DEST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001953 /* BIOS destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301954 register_bios_fw_addr(AMD_BIOS_BIN, 0, optarg, 0);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001955 sub = instance = 0;
1956 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001957 case AMDFW_OPT_BIOS_UNCOMP_SIZE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001958 /* BIOS destination size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301959 register_bios_fw_addr(AMD_BIOS_BIN, 0, 0, optarg);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001960 sub = instance = 0;
1961 break;
Karthikeyan Ramasubramanianbd9dd422022-12-22 15:45:56 -07001962 case AMDFW_OPT_BIOSBIN_UNCOMP:
1963 bios_tbl_index = find_bios_entry(AMD_BIOS_BIN);
1964 if (bios_tbl_index != -1)
1965 amd_bios_table[bios_tbl_index].zlib = 0;
1966 break;
Ritul Guru9a321f32022-07-29 11:06:40 +05301967 case LONGOPT_BIOS_SIG:
1968 /* BIOS signature size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05301969 register_bios_fw_addr(AMD_BIOS_SIG, 0, 0, optarg);
Ritul Guru9a321f32022-07-29 11:06:40 +05301970 sub = instance = 0;
1971 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001972 case AMDFW_OPT_UCODE:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001973 register_bdt_data(AMD_BIOS_UCODE, sub,
1974 instance, optarg);
1975 sub = instance = 0;
1976 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001977 case AMDFW_OPT_LOAD_S0I3:
Zheng Baoba3af5e2021-11-04 18:56:47 +08001978 cb_config.s0i3 = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001979 break;
Zheng Bao6c5ec8e2022-02-11 11:51:26 +08001980 case AMDFW_OPT_SPL_TABLE:
1981 register_fw_filename(AMD_FW_SPL, sub, optarg);
1982 sub = instance = 0;
1983 cb_config.have_mb_spl = true;
1984 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001985 case AMDFW_OPT_WHITELIST:
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001986 register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg);
1987 sub = instance = 0;
Zheng Baoba3af5e2021-11-04 18:56:47 +08001988 cb_config.have_whitelist = true;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001989 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001990 case AMDFW_OPT_VERSTAGE:
Martin Rothd3ce8c82019-07-13 20:13:07 -06001991 register_fw_filename(AMD_FW_PSP_VERSTAGE, sub, optarg);
1992 sub = instance = 0;
1993 break;
Zheng Bao806892a2021-04-27 17:21:54 +08001994 case AMDFW_OPT_VERSTAGE_SIG:
Martin Rothb1f648f2020-09-01 09:36:59 -06001995 register_fw_filename(AMD_FW_VERSTAGE_SIG, sub, optarg);
1996 sub = instance = 0;
1997 break;
Kangheui Won3c164e12021-12-03 20:25:05 +11001998 case AMDFW_OPT_SIGNED_OUTPUT:
1999 signed_output_file = optarg;
2000 sub = instance = 0;
2001 break;
2002 case AMDFW_OPT_SIGNED_ADDR:
2003 signed_start_addr = strtoull(optarg, NULL, 10);
2004 sub = instance = 0;
2005 break;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002006 case LONGOPT_SPI_READ_MODE:
2007 efs_spi_readmode = strtoull(optarg, NULL, 16);
2008 sub = instance = 0;
2009 break;
2010 case LONGOPT_SPI_SPEED:
2011 efs_spi_speed = strtoull(optarg, NULL, 16);
2012 sub = instance = 0;
2013 break;
2014 case LONGOPT_SPI_MICRON_FLAG:
2015 efs_spi_micron_flag = strtoull(optarg, NULL, 16);
2016 sub = instance = 0;
2017 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002018 case AMDFW_OPT_OUTPUT:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002019 output = optarg;
2020 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002021 case AMDFW_OPT_FLASHSIZE:
Marshall Dawson2794a862019-03-04 16:53:15 -07002022 ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth60f15512016-11-08 09:55:01 -07002023 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002024 fprintf(stderr, "Error: ROM size specified"
Martin Roth60f15512016-11-08 09:55:01 -07002025 " incorrectly (%s)\n\n", optarg);
Martin Roth31d95a22016-11-08 11:22:12 -07002026 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002027 }
2028 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002029 case AMDFW_OPT_LOCATION:
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002030 efs_location = (uint32_t)strtoul(optarg, &tmp, 16);
Martin Roth0d3b1182017-10-03 14:16:04 -06002031 if (*tmp != '\0') {
Zheng Bao77a2c672020-10-01 17:05:43 +08002032 fprintf(stderr, "Error: Directory Location specified"
Martin Roth0d3b1182017-10-03 14:16:04 -06002033 " incorrectly (%s)\n\n", optarg);
2034 retval = 1;
2035 }
Zheng Bao99945dc2023-01-02 10:55:56 +08002036 if (body_location == 0)
2037 body_location = efs_location;
Martin Roth0d3b1182017-10-03 14:16:04 -06002038 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002039 case AMDFW_OPT_ANYWHERE:
Martin Roth37305e72020-04-07 14:16:39 -06002040 any_location = 1;
2041 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002042 case AMDFW_OPT_SHAREDMEM:
Martin Roth94554742020-04-14 14:59:36 -06002043 /* shared memory destination */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302044 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, 0, optarg, 0);
Martin Roth94554742020-04-14 14:59:36 -06002045 sub = instance = 0;
2046 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002047 case AMDFW_OPT_SHAREDMEM_SIZE:
Martin Roth94554742020-04-14 14:59:36 -06002048 /* shared memory size */
Ritul Gurua2cb3402022-08-29 00:51:08 +05302049 register_bios_fw_addr(AMD_BIOS_PSP_SHARED_MEM, NULL, NULL, optarg);
Martin Roth94554742020-04-14 14:59:36 -06002050 sub = instance = 0;
2051 break;
Ritul Gurua2cb3402022-08-29 00:51:08 +05302052 case LONGOPT_NVRAM_BASE:
2053 /* PSP NV base */
2054 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, optarg, 0);
2055 sub = instance = 0;
2056 break;
2057 case LONGOPT_NVRAM_SIZE:
2058 /* PSP NV size */
2059 register_amd_psp_fw_addr(AMD_FW_PSP_NVRAM, sub, 0, optarg);
2060 sub = instance = 0;
2061 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002062 case AMDFW_OPT_CONFIG:
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002063 config = optarg;
2064 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002065 case AMDFW_OPT_DEBUG:
Zheng Bao9e908072020-10-28 11:39:13 +08002066 debug = 1;
2067 break;
Zheng Bao806892a2021-04-27 17:21:54 +08002068 case AMDFW_OPT_HELP:
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002069 usage();
Martin Roth31d95a22016-11-08 11:22:12 -07002070 return 0;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002071 case AMDFW_OPT_BODY_LOCATION:
Zheng Bao99945dc2023-01-02 10:55:56 +08002072 body_location = (uint32_t)strtoul(optarg, &tmp, 16);
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002073 if (*tmp != '\0') {
2074 fprintf(stderr, "Error: Body Location specified"
2075 " incorrectly (%s)\n\n", optarg);
2076 retval = 1;
2077 }
2078 break;
2079
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002080 default:
2081 break;
2082 }
2083 }
2084
Zheng Bao994ff522023-03-09 11:43:55 +08002085 open_process_config(config, &cb_config, debug);
Zheng Bao9e908072020-10-28 11:39:13 +08002086
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06002087 if (!fuse_defined)
2088 register_fw_fuse(DEFAULT_SOFT_FUSE_CHAIN);
2089
Zheng Bao994ff522023-03-09 11:43:55 +08002090 if (!output) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002091 fprintf(stderr, "Error: Output value is not specified.\n\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002092 retval = 1;
2093 }
2094
Zheng Baoa7731cc2023-03-11 09:27:53 +08002095 if (ctx.rom_size % 1024 != 0) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002096 fprintf(stderr, "Error: ROM Size (%d bytes) should be a multiple of"
Marshall Dawson2794a862019-03-04 16:53:15 -07002097 " 1024 bytes.\n\n", ctx.rom_size);
Martin Roth31d95a22016-11-08 11:22:12 -07002098 retval = 1;
Martin Roth60f15512016-11-08 09:55:01 -07002099 }
2100
Zheng Baoa7731cc2023-03-11 09:27:53 +08002101 if (ctx.rom_size < MIN_ROM_KB * 1024) {
Zheng Baoc5e28ab2020-10-28 11:38:09 +08002102 fprintf(stderr, "Error: ROM Size (%dKB) must be at least %dKB.\n\n",
Marshall Dawson2794a862019-03-04 16:53:15 -07002103 ctx.rom_size / 1024, MIN_ROM_KB);
Martin Roth31d95a22016-11-08 11:22:12 -07002104 retval = 1;
2105 }
2106
2107 if (retval) {
2108 usage();
2109 return retval;
Martin Roth60f15512016-11-08 09:55:01 -07002110 }
2111
Marshall Dawson2794a862019-03-04 16:53:15 -07002112 printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
Martin Roth60f15512016-11-08 09:55:01 -07002113
Marshall Dawson2794a862019-03-04 16:53:15 -07002114 rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
Zheng Bao9770df12023-02-14 13:23:35 +08002115
2116 if (efs_location & 0xFF000000)
2117 efs_location = efs_location - rom_base_address;
2118 if (body_location & 0xFF000000)
2119 body_location = body_location - rom_base_address;
2120
2121 if (efs_location && efs_location > ctx.rom_size) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002122 fprintf(stderr, "Error: EFS/Directory location outside of ROM.\n\n");
2123 return 1;
2124 }
Zheng Bao9770df12023-02-14 13:23:35 +08002125 if (body_location && body_location > ctx.rom_size) {
2126 fprintf(stderr, "Error: Body location outside of ROM.\n\n");
2127 return 1;
2128 }
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002129
Zheng Bao99945dc2023-01-02 10:55:56 +08002130 if (!efs_location && body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002131 fprintf(stderr, "Error AMDFW body location specified without EFS location.\n");
2132 return 1;
2133 }
2134
Zheng Bao99945dc2023-01-02 10:55:56 +08002135 if (body_location != efs_location &&
2136 body_location < ALIGN(efs_location + sizeof(embedded_firmware), BLOB_ALIGNMENT)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002137 fprintf(stderr, "Error: Insufficient space between EFS and Blobs.\n");
2138 fprintf(stderr, " Require safe spacing of 256 bytes\n");
Martin Roth0d3b1182017-10-03 14:16:04 -06002139 return 1;
2140 }
2141
Martin Roth37305e72020-04-07 14:16:39 -06002142 if (any_location) {
Zheng Bao99945dc2023-01-02 10:55:56 +08002143 if ((body_location & 0x3f) || (efs_location & 0x3f)) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002144 fprintf(stderr, "Error: Invalid Directory/EFS location.\n");
Zheng Bao77a2c672020-10-01 17:05:43 +08002145 fprintf(stderr, " Valid locations are 64-byte aligned\n");
Martin Roth37305e72020-04-07 14:16:39 -06002146 return 1;
2147 }
2148 } else {
Zheng Bao4e8fb352022-11-21 21:34:45 +08002149 /* efs_location is relative address now. */
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002150 switch (efs_location) {
Zheng Bao92c920b2022-12-08 13:56:13 +08002151 case 0:
Zheng Bao4e8fb352022-11-21 21:34:45 +08002152 case 0xFA0000:
2153 case 0xF20000:
2154 case 0xE20000:
2155 case 0xC20000:
2156 case 0x820000:
2157 case 0x020000:
2158 break;
2159 case 0x7A0000:
2160 case 0x720000:
2161 case 0x620000:
2162 case 0x420000:
2163 /* Special cases for 8M. */
2164 if (ctx.rom_size != 0x800000) {
2165 fprintf(stderr, "Error: Invalid Directory location.\n");
2166 fprintf(stderr, "%x is only for 8M image size.", efs_location);
2167 return 1;
2168 }
2169 break;
2170 case 0x3A0000:
2171 case 0x320000:
2172 case 0x220000:
2173 /* Special cases for 4M. */
2174 if (ctx.rom_size != 0x400000) {
2175 fprintf(stderr, "Error: Invalid Directory location.\n");
2176 fprintf(stderr, "%x is only for 4M image size.", efs_location);
2177 return 1;
2178 }
Martin Roth37305e72020-04-07 14:16:39 -06002179 break;
2180 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08002181 fprintf(stderr, "Error: Invalid Directory location.\n");
2182 fprintf(stderr, " Valid locations are 0xFFFA0000, 0xFFF20000,\n");
2183 fprintf(stderr, " 0xFFE20000, 0xFFC20000, 0xFF820000, 0xFF020000\n");
Zheng Bao4e8fb352022-11-21 21:34:45 +08002184 fprintf(stderr, " 0xFA0000, 0xF20000, 0xE20000, 0xC20000,\n");
2185 fprintf(stderr, " 0x820000, 0x020000\n");
Martin Roth37305e72020-04-07 14:16:39 -06002186 return 1;
2187 }
Martin Roth0d3b1182017-10-03 14:16:04 -06002188 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002189 ctx.rom = malloc(ctx.rom_size);
2190 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08002191 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07002192 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07002193 }
2194 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07002195
Zheng Bao6095cd12023-02-21 10:52:47 +08002196 romsig_offset = efs_location ? efs_location : AMD_ROMSIG_OFFSET;
2197 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06002198
Marshall Dawson2794a862019-03-04 16:53:15 -07002199 amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
Marshall Dawson239286c2019-02-23 16:42:46 -07002200 amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
2201 amd_romsig->imc_entry = 0;
2202 amd_romsig->gec_entry = 0;
2203 amd_romsig->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07002204
Zheng Bao4bf6f492023-01-25 22:37:29 +08002205 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
2206 retval = set_efs_table(cb_config.soc_id, &cb_config, amd_romsig,
2207 efs_spi_readmode, efs_spi_speed, efs_spi_micron_flag);
Zheng Bao570645d2021-11-03 10:25:03 +08002208 if (retval) {
2209 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
2210 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002211 }
2212 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002213 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05002214 }
2215
Felix Held21a8e382022-03-29 23:10:45 +02002216 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002217 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08002218 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06002219 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08002220 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06002221 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao7c7294f2023-01-04 16:38:28 +08002222 printf(" AMDFWTOOL Using firmware directory location of address: 0x%08x",
2223 efs_location);
2224 if (body_location != efs_location)
2225 printf(" with a split body at: 0x%08x\n", body_location);
2226 else
2227 printf("\n");
Zheng Baoda83d2c2021-06-04 19:03:10 +08002228
Zheng Bao6095cd12023-02-21 10:52:47 +08002229 if (efs_location != body_location)
2230 set_current_pointer(&ctx, body_location);
2231 else
2232 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
2233
Marshall Dawson2794a862019-03-04 16:53:15 -07002234 integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002235
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07002236 if (is_initial_alignment_required(cb_config.soc_id)) {
2237 /* TODO: Check for older platforms. */
2238 adjust_current_pointer(&ctx, 0, 0x10000U);
2239 }
Zheng Bao6fff2492021-11-15 19:53:21 +08002240 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07002241
Kangheui Won3c164e12021-12-03 20:25:05 +11002242 /* If the tool is invoked with command-line options to keep the signed PSP
2243 binaries separate, process the signed binaries first. */
2244 if (signed_output_file && signed_start_addr)
2245 process_signed_psp_firmwares(signed_output_file,
2246 amd_psp_fw_table,
2247 signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08002248 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11002249
Zheng Baob2ae6a52022-08-18 15:45:27 +08002250 if (cb_config.use_combo) {
2251 psp_combo_dir = new_combo_dir(&ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002252
2253 adjust_current_pointer(&ctx, 0, 0x1000U);
2254
2255 bhd_combo_dir = new_combo_dir(&ctx);
Zheng Baob2ae6a52022-08-18 15:45:27 +08002256 }
2257
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002258 combo_index = 0;
2259 if (config)
2260 combo_config[0] = config;
2261
Zheng Bao4b6aa192023-03-09 11:28:47 +08002262 do {
Zheng Bao3e7008d2023-03-15 16:15:13 +08002263 if (cb_config.use_combo && debug)
2264 printf("Processing %dth combo entry\n", combo_index);
2265
Zheng Bao4b6aa192023-03-09 11:28:47 +08002266 /* for non-combo image, combo_config[0] == config, and
2267 * it already is processed. Actually "combo_index >
2268 * 0" is enough. Put both of them here to make sure
2269 * and make it clear this will not affect non-combo
2270 * case.
2271 */
2272 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao73917222023-03-15 16:14:03 +08002273 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08002274 open_process_config(combo_config[combo_index], &cb_config,
Zheng Bao994ff522023-03-09 11:43:55 +08002275 debug);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08002276
Zheng Bao4b6aa192023-03-09 11:28:47 +08002277 /* In most cases, the address modes are same. */
2278 if (cb_config.need_ish)
2279 ctx.address_mode = AMD_ADDR_REL_TAB;
2280 else if (cb_config.second_gen)
2281 ctx.address_mode = AMD_ADDR_REL_BIOS;
2282 else
2283 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Bao990d1542021-09-17 13:24:54 +08002284 }
Marshall Dawson2794a862019-03-04 16:53:15 -07002285
Zheng Bao481661e2021-08-20 14:47:46 +08002286 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002287 /* Do 2nd PSP directory followed by 1st */
2288 pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
2289 integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL,
2290 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
2291 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
2292 /* Create a copy of PSP Directory 2 in the backup slot B.
2293 Related biosdir2_b copy will be created later. */
2294 pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
2295 integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL,
2296 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08002297 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002298 /*
2299 * Either the platform is using only
2300 * one slot or B is same as above
2301 * directories for A. Skip creating
2302 * pspdir2_b here to save flash space.
2303 * Related biosdir2_b will be skipped
2304 * automatically.
2305 */
2306 pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08002307 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002308 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2309 integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b,
2310 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002311 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08002312 /* flat: PSP 1 cookie and no pointer to 2nd table */
2313 pspdir = new_psp_dir(&ctx, cb_config.multi_level);
2314 integrate_psp_firmwares(&ctx, pspdir, NULL, NULL,
2315 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002316 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002317
Zheng Bao4b6aa192023-03-09 11:28:47 +08002318 if (!cb_config.use_combo) {
2319 fill_psp_directory_to_efs(amd_romsig, pspdir, &ctx, &cb_config);
2320 } else {
2321 fill_psp_directory_to_efs(amd_romsig, psp_combo_dir, &ctx, &cb_config);
2322 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
2323 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2324 psp_combo_dir->entries[combo_index].id_sel = 0;
2325 psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
2326 psp_combo_dir->entries[combo_index].lvl2_addr =
2327 BUFF_TO_RUN_MODE(ctx, pspdir, AMD_ADDR_REL_BIOS);
2328
2329 fill_dir_header(psp_combo_dir, combo_index + 1, PSP2_COOKIE, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08002330 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08002331
2332 if (have_bios_tables(amd_bios_table)) {
2333 bios_directory_table *biosdir = NULL;
2334 if (cb_config.multi_level) {
2335 /* Do 2nd level BIOS directory followed by 1st */
2336 bios_directory_table *biosdir2 = NULL;
2337 bios_directory_table *biosdir2_b = NULL;
2338
2339 biosdir2 = new_bios_dir(&ctx, cb_config.multi_level);
2340
2341 integrate_bios_firmwares(&ctx, biosdir2, NULL,
2342 amd_bios_table, BHDL2_COOKIE, &cb_config);
2343 if (cb_config.recovery_ab) {
2344 if (pspdir2_b != NULL) {
2345 biosdir2_b = new_bios_dir(&ctx,
2346 cb_config.multi_level);
2347 integrate_bios_firmwares(&ctx, biosdir2_b, NULL,
2348 amd_bios_table, BHDL2_COOKIE,
2349 &cb_config);
2350 }
2351 add_psp_firmware_entry(&ctx, pspdir2, biosdir2,
2352 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
2353 if (pspdir2_b != NULL)
2354 add_psp_firmware_entry(&ctx, pspdir2_b,
2355 biosdir2_b, AMD_FW_BIOS_TABLE,
2356 TABLE_ALIGNMENT);
2357 } else {
2358 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2359 integrate_bios_firmwares(&ctx, biosdir, biosdir2,
2360 amd_bios_table, BHD_COOKIE, &cb_config);
2361 }
2362 } else {
2363 /* flat: BHD1 cookie and no pointer to 2nd table */
2364 biosdir = new_bios_dir(&ctx, cb_config.multi_level);
2365 integrate_bios_firmwares(&ctx, biosdir, NULL,
2366 amd_bios_table, BHD_COOKIE, &cb_config);
2367 }
2368 if (!cb_config.use_combo) {
2369 fill_bios_directory_to_efs(amd_romsig, biosdir,
2370 &ctx, &cb_config);
2371 } else {
2372 fill_bios_directory_to_efs(amd_romsig, bhd_combo_dir,
2373 &ctx, &cb_config);
2374 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
2375 bhd_combo_dir->entries[combo_index].id_sel = 0;
2376 bhd_combo_dir->entries[combo_index].id =
2377 get_psp_id(cb_config.soc_id);
2378 bhd_combo_dir->entries[combo_index].lvl2_addr =
2379 BUFF_TO_RUN_MODE(ctx, biosdir, AMD_ADDR_REL_BIOS);
2380
2381 fill_dir_header(bhd_combo_dir, combo_index + 1,
2382 BHD2_COOKIE, &ctx);
2383 }
2384 }
Zheng Bao17551ae2023-03-11 10:29:56 +08002385 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
2386 combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06002387
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002388 targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07002389 if (targetfd >= 0) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08002390 uint32_t offset = efs_location;
2391 uint32_t bytes = efs_location == body_location ?
2392 ctx.current - offset : sizeof(*amd_romsig);
2393 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002394
Zheng Bao69ea83c2023-01-22 21:08:18 +08002395 ret_bytes = write(targetfd, BUFF_OFFSET(ctx, offset), bytes);
2396 if (bytes != ret_bytes) {
Zheng Bao47396912020-09-29 17:33:17 +08002397 fprintf(stderr, "Error: Writing to file %s failed\n", output);
2398 retval = 1;
2399 }
Martin Roth31d95a22016-11-08 11:22:12 -07002400 close(targetfd);
2401 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08002402 fprintf(stderr, "Error: could not open file: %s\n", output);
Martin Roth31d95a22016-11-08 11:22:12 -07002403 retval = 1;
2404 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002405
Zheng Bao99945dc2023-01-02 10:55:56 +08002406 if (efs_location != body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002407 ssize_t bytes;
2408
Zheng Bao69ea83c2023-01-22 21:08:18 +08002409 bytes = write_body(output, BUFF_OFFSET(ctx, body_location),
2410 ctx.current - body_location, &ctx);
2411 if (bytes != ctx.current - body_location) {
2412 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06002413 retval = 1;
2414 }
2415 }
2416
Zheng Bao7c5ad882023-02-19 13:02:52 +08002417 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07002418 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08002419}