blob: 1dac476a2ae613e1faca22d9d4da879e43ecb860 [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>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080083#include <libgen.h>
Idwer Vollering93df1d92020-12-30 00:01:59 +010084#include <stdint.h>
Zheng Baoc5e28ab2020-10-28 11:38:09 +080085
86#include "amdfwtool.h"
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080087
Martin Roth60f15512016-11-08 09:55:01 -070088#define AMD_ROMSIG_OFFSET 0x20000
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080089
Marshall Dawson7c1e1422019-04-11 09:44:43 -060090#define _MAX(A, B) (((A) > (B)) ? (A) : (B))
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080091
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +000092static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry);
93
Zheng Bao9c7ff7b2015-11-17 22:57:39 +080094/*
Marshall Dawson0e02ce82019-03-04 16:50:37 -070095 * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP
96 * can support an optional "combo" implementation. If the PSP sees the
97 * PSP2 cookie, it interprets the table as a roadmap to additional PSP
98 * tables. Using this, support for multiple product generations may be
99 * built into one image. If the PSP$ cookie is found, the table is a
100 * normal directory table.
101 *
102 * Modern generations supporting the combo directories require the
103 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
Zheng Baoc91867a2023-02-26 12:31:31 +0800104 * regardless of the type of directory used. The --use-combo
Marshall Dawson0e02ce82019-03-04 16:50:37 -0700105 * argument enforces this placement.
106 *
107 * TODO: Future work may require fully implementing the PSP_COMBO feature.
zbaoc3b0b722016-02-19 13:47:31 +0800108 */
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800109
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800110/*
111 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
112 * The checksum field of the passed PDU does not need to be reset to zero.
113 *
114 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
115 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
116 * alternative to cyclical redundancy checks because it provides error-
117 * detection properties similar to cyclical redundancy checks but at the
118 * cost of a simple summation technique. Its characteristics were first
119 * published in IEEE Transactions on Communications in January 1982. One
120 * version has been adopted by ISO for use in the class-4 transport layer
121 * of the network protocol.
122 *
123 * This program expects:
124 * stdin: The input file to compute a checksum for. The input file
125 * not be longer than 256 bytes.
126 * stdout: Copied from the input file with the Fletcher's Checksum
127 * inserted 8 bytes after the beginning of the file.
128 * stderr: Used to print out error messages.
129 */
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700130static uint32_t fletcher32(const void *data, int length)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800131{
132 uint32_t c0;
133 uint32_t c1;
134 uint32_t checksum;
135 int index;
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700136 const uint16_t *pptr = data;
137
138 length /= 2;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800139
140 c0 = 0xFFFF;
141 c1 = 0xFFFF;
142
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600143 while (length) {
144 index = length >= 359 ? 359 : length;
145 length -= index;
Zheng Baoc88f2b52021-10-14 16:15:11 +0800146 do {
147 c0 += *(pptr++);
148 c1 += c0;
149 } while (--index);
Marshall Dawsonb85ddc52019-07-23 07:24:30 -0600150 c0 = (c0 & 0xFFFF) + (c0 >> 16);
151 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800152 }
153
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700154 /* Sums[0,1] mod 64K + overflow */
155 c0 = (c0 & 0xFFFF) + (c0 >> 16);
156 c1 = (c1 & 0xFFFF) + (c1 >> 16);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800157 checksum = (c1 << 16) | c0;
158
159 return checksum;
160}
161
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800162amd_fw_entry amd_psp_fw_table[] = {
Kangheui Won3c164e12021-12-03 20:25:05 +1100163 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000164 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB,
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000165 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800166 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200167 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
Zheng Bao990d1542021-09-17 13:24:54 +0800168 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200169 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000170 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB,
171 .generate_manifest = true },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200172 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800173 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100174 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
175 .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200176 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000177 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800178 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
179 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000180 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200181 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
182 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800183 { .type = AMD_BOOT_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
184 { .type = AMD_SOC_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
185 { .type = AMD_DEBUG_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
186 { .type = AMD_INTERFACE_DRIVER, .level = PSP_BOTH | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000187 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao9bb62cb2023-03-07 19:48:11 +0800188 { .type = AMD_HW_IPCFG, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
189 { .type = AMD_HW_IPCFG, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Kangheui Won3c164e12021-12-03 20:25:05 +1100190 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800191 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
192 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800193 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200194 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800195 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200196 { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
197 { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800198 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
199 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200200 { .type = AMD_FW_MP5, .subprog = 0, .level = PSP_BOTH | PSP_BOTH_AB },
201 { .type = AMD_FW_MP5, .subprog = 1, .level = PSP_BOTH | PSP_BOTH_AB },
202 { .type = AMD_FW_MP5, .subprog = 2, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao990d1542021-09-17 13:24:54 +0800203 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000204 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB,
205 .generate_manifest = true },
Zheng Bao990d1542021-09-17 13:24:54 +0800206 { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB },
207 { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB },
208 { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB },
209 { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB },
210 { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB },
211 { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB },
212 { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200213 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
214 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian51f914d2022-07-28 16:42:12 -0600215 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200216 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200217 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200218 { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB },
219 { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB },
220 { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB },
221 { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB },
222 { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB },
Karthikeyan Ramasubramanian234e3702022-07-25 09:49:24 -0600223 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
224 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200225 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
Matt DeVillierfdb45032023-07-31 20:08:43 +0000226 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200227 { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB },
228 { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB },
229 { .type = AMD_FW_MSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
230 { .type = AMD_FW_SPIROM_CFG, .level = PSP_LVL2 | PSP_LVL2_AB },
Nikolai Vyssotskibfc9ca72023-03-07 15:09:09 -0600231 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800232 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200233 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000234 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB,
235 .generate_manifest = true },
Zheng Bao85ee1fd2023-01-30 13:52:30 +0800236 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
237 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200238 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
Arthur Heymansaafbe132022-09-30 08:33:28 +0200239 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
Arthur Heymans1f05c802022-10-04 17:50:21 +0200240 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
241 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
Zheng Bao8eba6622022-10-16 20:29:03 +0800242 { .type = AMD_FW_AMF_SRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
243 { .type = AMD_FW_AMF_DRAM, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
244 { .type = AMD_FW_AMF_DRAM, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
245 { .type = AMD_FW_FCFG_TABLE, .level = PSP_LVL2 | PSP_LVL2_AB },
246 { .type = AMD_FW_AMF_WLAN, .inst = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
247 { .type = AMD_FW_AMF_WLAN, .inst = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
248 { .type = AMD_FW_AMF_MFD, .level = PSP_LVL2 | PSP_LVL2_AB },
249 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
250 { .type = AMD_FW_MPCCX, .level = PSP_LVL2 | PSP_LVL2_AB },
251 { .type = AMD_FW_LSDMA, .level = PSP_LVL2 | PSP_LVL2_AB },
252 { .type = AMD_FW_C20_MP, .level = PSP_BOTH | PSP_LVL2_AB },
253 { .type = AMD_FW_MINIMSMU, .inst = 0, .level = PSP_BOTH | PSP_LVL2_AB },
254 { .type = AMD_FW_MINIMSMU, .inst = 1, .level = PSP_BOTH | PSP_LVL2_AB },
255 { .type = AMD_FW_SRAM_FW_EXT, .level = PSP_LVL2 | PSP_LVL2_AB },
Fred Reitbergerc4f3a332023-02-07 12:12:40 -0500256 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
zbaoc3a08a92016-03-02 14:47:27 +0800257 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800258};
259
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800260amd_fw_entry amd_fw_table[] = {
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800261 { .type = AMD_FW_XHCI },
262 { .type = AMD_FW_IMC },
263 { .type = AMD_FW_GEC },
zbaoc3a08a92016-03-02 14:47:27 +0800264 { .type = AMD_FW_INVALID },
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800265};
266
Zheng Baoc5e28ab2020-10-28 11:38:09 +0800267amd_bios_entry amd_bios_table[] = {
Zheng Baobf29a0d2020-12-03 23:00:48 +0800268 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
Ritul Guru9a321f32022-07-29 11:06:40 +0530269 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
Marshall Dawson0581bf62019-09-25 11:03:53 -0600270 { .type = AMD_BIOS_APCB, .inst = 0, .level = BDT_BOTH },
271 { .type = AMD_BIOS_APCB, .inst = 1, .level = BDT_BOTH },
272 { .type = AMD_BIOS_APCB, .inst = 2, .level = BDT_BOTH },
273 { .type = AMD_BIOS_APCB, .inst = 3, .level = BDT_BOTH },
274 { .type = AMD_BIOS_APCB, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700275 { .type = AMD_BIOS_APCB, .inst = 5, .level = BDT_BOTH },
276 { .type = AMD_BIOS_APCB, .inst = 6, .level = BDT_BOTH },
277 { .type = AMD_BIOS_APCB, .inst = 7, .level = BDT_BOTH },
278 { .type = AMD_BIOS_APCB, .inst = 8, .level = BDT_BOTH },
279 { .type = AMD_BIOS_APCB, .inst = 9, .level = BDT_BOTH },
280 { .type = AMD_BIOS_APCB, .inst = 10, .level = BDT_BOTH },
281 { .type = AMD_BIOS_APCB, .inst = 11, .level = BDT_BOTH },
282 { .type = AMD_BIOS_APCB, .inst = 12, .level = BDT_BOTH },
283 { .type = AMD_BIOS_APCB, .inst = 13, .level = BDT_BOTH },
284 { .type = AMD_BIOS_APCB, .inst = 14, .level = BDT_BOTH },
285 { .type = AMD_BIOS_APCB, .inst = 15, .level = BDT_BOTH },
Marshall Dawson2dd3b5c2020-01-03 17:57:48 -0700286 { .type = AMD_BIOS_APCB_BK, .inst = 0, .level = BDT_BOTH },
287 { .type = AMD_BIOS_APCB_BK, .inst = 1, .level = BDT_BOTH },
288 { .type = AMD_BIOS_APCB_BK, .inst = 2, .level = BDT_BOTH },
289 { .type = AMD_BIOS_APCB_BK, .inst = 3, .level = BDT_BOTH },
290 { .type = AMD_BIOS_APCB_BK, .inst = 4, .level = BDT_BOTH },
Rob Barnes18fd26c2020-03-03 10:35:02 -0700291 { .type = AMD_BIOS_APCB_BK, .inst = 5, .level = BDT_BOTH },
292 { .type = AMD_BIOS_APCB_BK, .inst = 6, .level = BDT_BOTH },
293 { .type = AMD_BIOS_APCB_BK, .inst = 7, .level = BDT_BOTH },
294 { .type = AMD_BIOS_APCB_BK, .inst = 8, .level = BDT_BOTH },
295 { .type = AMD_BIOS_APCB_BK, .inst = 9, .level = BDT_BOTH },
296 { .type = AMD_BIOS_APCB_BK, .inst = 10, .level = BDT_BOTH },
297 { .type = AMD_BIOS_APCB_BK, .inst = 11, .level = BDT_BOTH },
298 { .type = AMD_BIOS_APCB_BK, .inst = 12, .level = BDT_BOTH },
299 { .type = AMD_BIOS_APCB_BK, .inst = 13, .level = BDT_BOTH },
300 { .type = AMD_BIOS_APCB_BK, .inst = 14, .level = BDT_BOTH },
301 { .type = AMD_BIOS_APCB_BK, .inst = 15, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600302 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
303 { .type = AMD_BIOS_BIN,
Zheng Bao3d426f32022-10-16 20:34:57 +0800304 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600305 { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 },
306 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH },
307 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800308 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
309 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200310 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
311 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600312 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
313 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800314 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 0, .level = BDT_BOTH },
315 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 0, .level = BDT_BOTH },
316 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 0, .level = BDT_BOTH },
317 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 0, .level = BDT_BOTH },
318 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 0, .level = BDT_BOTH },
319 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 0, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200320 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 0, .level = BDT_BOTH },
321 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 0, .level = BDT_BOTH },
322 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 0, .level = BDT_BOTH },
323 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 0, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800324 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 0, .level = BDT_BOTH },
325 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 0, .level = BDT_BOTH },
326 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 0, .level = BDT_BOTH },
327 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 0, .level = BDT_BOTH },
328 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 0, .level = BDT_BOTH },
329 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600330 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
331 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
Zheng Baoe220faa2022-02-17 17:22:15 +0800332 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
333 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200334 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
335 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600336 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
337 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800338 { .type = AMD_BIOS_PMUI, .inst = 5, .subpr = 1, .level = BDT_BOTH },
339 { .type = AMD_BIOS_PMUD, .inst = 5, .subpr = 1, .level = BDT_BOTH },
340 { .type = AMD_BIOS_PMUI, .inst = 6, .subpr = 1, .level = BDT_BOTH },
341 { .type = AMD_BIOS_PMUD, .inst = 6, .subpr = 1, .level = BDT_BOTH },
342 { .type = AMD_BIOS_PMUI, .inst = 7, .subpr = 1, .level = BDT_BOTH },
343 { .type = AMD_BIOS_PMUD, .inst = 7, .subpr = 1, .level = BDT_BOTH },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200344 { .type = AMD_BIOS_PMUI, .inst = 9, .subpr = 1, .level = BDT_BOTH },
345 { .type = AMD_BIOS_PMUD, .inst = 9, .subpr = 1, .level = BDT_BOTH },
346 { .type = AMD_BIOS_PMUI, .inst = 10, .subpr = 1, .level = BDT_BOTH },
347 { .type = AMD_BIOS_PMUD, .inst = 10, .subpr = 1, .level = BDT_BOTH },
Zheng Bao8eba6622022-10-16 20:29:03 +0800348 { .type = AMD_BIOS_PMUI, .inst = 11, .subpr = 1, .level = BDT_BOTH },
349 { .type = AMD_BIOS_PMUD, .inst = 11, .subpr = 1, .level = BDT_BOTH },
350 { .type = AMD_BIOS_PMUI, .inst = 12, .subpr = 1, .level = BDT_BOTH },
351 { .type = AMD_BIOS_PMUD, .inst = 12, .subpr = 1, .level = BDT_BOTH },
352 { .type = AMD_BIOS_PMUI, .inst = 13, .subpr = 1, .level = BDT_BOTH },
353 { .type = AMD_BIOS_PMUD, .inst = 13, .subpr = 1, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600354 { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 },
355 { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 },
356 { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 },
Arthur Heymansa83c5022022-10-04 20:37:10 +0200357 { .type = AMD_BIOS_UCODE, .inst = 3, .level = BDT_LVL2 },
358 { .type = AMD_BIOS_UCODE, .inst = 4, .level = BDT_LVL2 },
359 { .type = AMD_BIOS_UCODE, .inst = 5, .level = BDT_LVL2 },
360 { .type = AMD_BIOS_UCODE, .inst = 6, .level = BDT_LVL2 },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600361 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
Martin Roth94554742020-04-14 14:59:36 -0600362 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600363 { .type = AMD_BIOS_INVALID },
364};
365
Marshall Dawson2794a862019-03-04 16:53:15 -0700366#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
Zheng Bao6fff2492021-11-15 19:53:21 +0800367#define RUN_OFFSET_MODE(ctx, offset, mode) \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600368 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
369 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
Zheng Baoc38f7642023-02-21 10:43:08 +0800370 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
Zheng Bao6fff2492021-11-15 19:53:21 +0800371#define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
Robert Zieba29bc79f2022-03-14 15:59:12 -0600372#define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
Zheng Bao6fff2492021-11-15 19:53:21 +0800373 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
Marshall Dawson2794a862019-03-04 16:53:15 -0700374#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800375/* The mode in entry can not be higher than the header's.
376 For example, if table mode is 0, all the entry mode will be 0. */
377#define RUN_CURRENT_MODE(ctx, mode) RUN_OFFSET_MODE((ctx), (ctx).current, \
378 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700379#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
380#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
381#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
Zheng Bao6fff2492021-11-15 19:53:21 +0800382#define BUFF_TO_RUN_MODE(ctx, ptr, mode) RUN_OFFSET_MODE((ctx), ((char *)(ptr) - (ctx).rom), \
383 (ctx).address_mode < (mode) ? (ctx).address_mode : (mode))
Marshall Dawson2794a862019-03-04 16:53:15 -0700384#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
Zheng Bao6fff2492021-11-15 19:53:21 +0800385/* Only set the address mode in entry if the table is mode 2. */
386#define SET_ADDR_MODE(table, mode) \
387 ((table)->header.additional_info_fields.address_mode == \
Robert Zieba29bc79f2022-03-14 15:59:12 -0600388 AMD_ADDR_REL_TAB ? (mode) : 0)
Zheng Bao6fff2492021-11-15 19:53:21 +0800389#define SET_ADDR_MODE_BY_TABLE(table) \
390 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
Marshall Dawson2794a862019-03-04 16:53:15 -0700391
Zheng Bao7c5ad882023-02-19 13:02:52 +0800392
393static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
394{
395 amd_fw_entry *index;
396
397 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
398 if (index->filename &&
399 index->type != AMD_FW_VERSTAGE_SIG &&
400 index->type != AMD_FW_PSP_VERSTAGE &&
401 index->type != AMD_FW_SPL &&
402 index->type != AMD_FW_PSP_WHITELIST) {
403 free(index->filename);
404 index->filename = NULL;
405 }
406 }
407}
408
409static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
410{
411 amd_bios_entry *index;
412
413 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
414 if (index->filename &&
415 index->type != AMD_BIOS_APCB &&
416 index->type != AMD_BIOS_BIN &&
417 index->type != AMD_BIOS_APCB_BK &&
418 index->type != AMD_BIOS_UCODE) {
419 free(index->filename);
420 index->filename = NULL;
421 }
422 }
423}
424
425static void amdfwtool_cleanup(context *ctx)
426{
427 free(ctx->rom);
428 ctx->rom = NULL;
429
430 /* Free the filename. */
431 free_psp_firmware_filenames(amd_psp_fw_table);
432 free_bdt_firmware_filenames(amd_bios_table);
Zheng Bao8dd34bd2023-03-09 21:09:58 +0800433
434 free(ctx->amd_psp_fw_table_clean);
435 ctx->amd_psp_fw_table_clean = NULL;
436 free(ctx->amd_bios_table_clean);
437 ctx->amd_bios_table_clean = NULL;
Zheng Bao7c5ad882023-02-19 13:02:52 +0800438}
439
Zheng Bao5164e4b2021-10-30 12:09:07 +0800440void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
441{
442 if (count >= max) {
443 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
444 "(%d)\n", count, max);
Zheng Bao7c5ad882023-02-19 13:02:52 +0800445 amdfwtool_cleanup(ctx);
Zheng Bao5164e4b2021-10-30 12:09:07 +0800446 exit(1);
447 }
448}
449
Zheng Baoc26108f2023-02-17 11:01:07 +0800450static void set_current_pointer(context *ctx, uint32_t value)
451{
452 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
453 ctx->current_pointer_saved != ctx->current) {
454 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800455 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800456 exit(1);
457 }
458
459 ctx->current = value;
460
461 if (ctx->current > ctx->rom_size) {
462 fprintf(stderr, "Error: Packing data causes overflow\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +0800463 amdfwtool_cleanup(ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800464 exit(1);
465 }
466
467 ctx->current_pointer_saved = ctx->current;
468}
469
470static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
471{
472 /* Get */
473 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
474}
475
Zheng Baob81b7da2024-03-14 13:29:34 +0800476static void *new_psp_dir(context *ctx, int multi, uint32_t cookie)
Marshall Dawson2794a862019-03-04 16:53:15 -0700477{
478 void *ptr;
479
Marshall Dawson24f73d42019-04-01 10:48:43 -0600480 /*
481 * Force both onto boundary when multi. Primary table is after
482 * updatable table, so alignment ensures primary can stay intact
483 * if secondary is reprogrammed.
484 */
Zheng Bao07e05082024-03-15 13:46:51 +0800485 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +0800486 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600487 else
Zheng Baoc26108f2023-02-17 11:01:07 +0800488 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson24f73d42019-04-01 10:48:43 -0600489
Marshall Dawson2794a862019-03-04 16:53:15 -0700490 ptr = BUFF_CURRENT(*ctx);
Zheng Baob81b7da2024-03-14 13:29:34 +0800491 ((psp_directory_header *)ptr)->cookie = cookie;
Zheng Bao990d1542021-09-17 13:24:54 +0800492 ((psp_directory_header *)ptr)->num_entries = 0;
Zheng Bao6fff2492021-11-15 19:53:21 +0800493 ((psp_directory_header *)ptr)->additional_info = 0;
494 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +0800495 adjust_current_pointer(ctx,
496 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
Zheng Bao07e05082024-03-15 13:46:51 +0800497 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700498 return ptr;
499}
500
Zheng Baofdd47ef2021-09-17 13:30:08 +0800501static void *new_ish_dir(context *ctx)
502{
503 void *ptr;
Zheng Baoc26108f2023-02-17 11:01:07 +0800504 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800505 ptr = BUFF_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +0800506 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
507
Zheng Baofdd47ef2021-09-17 13:30:08 +0800508 return ptr;
509}
510
Zheng Baob81b7da2024-03-14 13:29:34 +0800511static void *new_combo_dir(context *ctx, uint32_t cookie)
Marshall Dawson2794a862019-03-04 16:53:15 -0700512{
513 void *ptr;
514
Zheng Baoc26108f2023-02-17 11:01:07 +0800515 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawson2794a862019-03-04 16:53:15 -0700516 ptr = BUFF_CURRENT(*ctx);
Zheng Baob81b7da2024-03-14 13:29:34 +0800517 ((psp_combo_header *)ptr)->cookie = cookie;
Zheng Baoc26108f2023-02-17 11:01:07 +0800518 adjust_current_pointer(ctx,
519 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
520 1);
Marshall Dawson2794a862019-03-04 16:53:15 -0700521 return ptr;
522}
523
Zheng Baob81b7da2024-03-14 13:29:34 +0800524static void fill_dir_header(void *directory, uint32_t count, context *ctx)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800525{
Marshall Dawson24f73d42019-04-01 10:48:43 -0600526 psp_combo_directory *cdir = directory;
527 psp_directory_table *dir = directory;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600528 bios_directory_table *bdir = directory;
Zheng Baob81b7da2024-03-14 13:29:34 +0800529 /* The cookies have same offsets. */
530 uint32_t cookie = ((psp_directory_table *)directory)->header.cookie;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800531 uint32_t table_size = 0;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600532
Zheng Baob035f582021-05-27 11:26:12 +0800533 if (ctx == NULL || directory == NULL) {
534 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
535 return;
536 }
Marshall Dawson24f73d42019-04-01 10:48:43 -0600537
Zheng Baobf29a0d2020-12-03 23:00:48 +0800538 /* The table size needs to be 0x1000 aligned. So align the end of table. */
Zheng Baoc26108f2023-02-17 11:01:07 +0800539 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Baobf29a0d2020-12-03 23:00:48 +0800540
Marshall Dawson24f73d42019-04-01 10:48:43 -0600541 switch (cookie) {
542 case PSP2_COOKIE:
Zheng Bao84fb9ea2022-08-18 15:54:47 +0800543 case BHD2_COOKIE:
Zheng Baofd51af62022-08-18 15:26:39 +0800544 /* lookup mode is hardcoded for now. */
545 cdir->header.lookup = 1;
Marshall Dawsona378c222019-03-04 16:52:07 -0700546 cdir->header.num_entries = count;
547 cdir->header.reserved[0] = 0;
548 cdir->header.reserved[1] = 0;
549 /* checksum everything that comes after the Checksum field */
550 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
551 count * sizeof(psp_combo_entry)
552 + sizeof(cdir->header.num_entries)
553 + sizeof(cdir->header.lookup)
554 + 2 * sizeof(cdir->header.reserved[0]));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600555 break;
556 case PSP_COOKIE:
557 case PSPL2_COOKIE:
Zheng Bao07e05082024-03-15 13:46:51 +0800558 /* The table size is only set once. Later calls only update
559 * the count and fletcher. So does the BIOS table. */
560 if (dir->header.additional_info_fields.dir_size == 0) {
Zheng Baofc3fcf22023-10-12 11:28:05 +0800561 table_size = ctx->current - ctx->current_table;
Zheng Bao07e05082024-03-15 13:46:51 +0800562 if ((table_size % TABLE_ALIGNMENT) != 0 &&
563 (table_size / TABLE_ALIGNMENT) != 0) {
564 fprintf(stderr, "The PSP table size should be 4K aligned\n");
565 amdfwtool_cleanup(ctx);
566 exit(1);
567 }
568 dir->header.additional_info_fields.dir_size =
569 table_size / TABLE_ALIGNMENT;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800570 }
Marshall Dawsona378c222019-03-04 16:52:07 -0700571 dir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800572 dir->header.additional_info_fields.spi_block_size = 1;
573 dir->header.additional_info_fields.base_addr = 0;
Marshall Dawsona378c222019-03-04 16:52:07 -0700574 /* checksum everything that comes after the Checksum field */
575 dir->header.checksum = fletcher32(&dir->header.num_entries,
Marshall Dawson8a45a4d2019-02-24 07:18:44 -0700576 count * sizeof(psp_directory_entry)
Marshall Dawsona378c222019-03-04 16:52:07 -0700577 + sizeof(dir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800578 + sizeof(dir->header.additional_info));
Marshall Dawson24f73d42019-04-01 10:48:43 -0600579 break;
Zheng Bao96a33712021-06-11 15:54:40 +0800580 case BHD_COOKIE:
581 case BHDL2_COOKIE:
Zheng Bao07e05082024-03-15 13:46:51 +0800582 if (bdir->header.additional_info_fields.dir_size == 0) {
583 table_size = ctx->current - ctx->current_table;
584 if ((table_size % TABLE_ALIGNMENT) != 0 &&
585 table_size / TABLE_ALIGNMENT != 0) {
586 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
587 amdfwtool_cleanup(ctx);
588 exit(1);
589 }
590 bdir->header.additional_info_fields.dir_size =
591 table_size / TABLE_ALIGNMENT;
Zheng Baobf29a0d2020-12-03 23:00:48 +0800592 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600593 bdir->header.num_entries = count;
Zheng Bao6fff2492021-11-15 19:53:21 +0800594 bdir->header.additional_info_fields.spi_block_size = 1;
595 bdir->header.additional_info_fields.base_addr = 0;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600596 /* checksum everything that comes after the Checksum field */
597 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
598 count * sizeof(bios_directory_entry)
599 + sizeof(bdir->header.num_entries)
Zheng Baobf29a0d2020-12-03 23:00:48 +0800600 + sizeof(bdir->header.additional_info));
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600601 break;
Marshall Dawsona378c222019-03-04 16:52:07 -0700602 }
Zheng Baobf29a0d2020-12-03 23:00:48 +0800603
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800604}
605
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800606static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
607 context *ctx, amd_cb_config *cb_config)
608{
609 switch (cb_config->soc_id) {
610 case PLATFORM_UNKNOWN:
611 amd_romsig->psp_directory =
612 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
613 break;
614 case PLATFORM_CEZANNE:
615 case PLATFORM_MENDOCINO:
616 case PLATFORM_PHOENIX:
617 case PLATFORM_GLINDA:
618 case PLATFORM_CARRIZO:
619 case PLATFORM_STONEYRIDGE:
620 case PLATFORM_RAVEN:
621 case PLATFORM_PICASSO:
622 case PLATFORM_LUCIENNE:
623 case PLATFORM_RENOIR:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200624 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800625 default:
626 /* for combo, it is also combo_psp_directory */
627 amd_romsig->new_psp_directory =
628 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
629 break;
630 }
631}
632
633static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
634 context *ctx, amd_cb_config *cb_config)
635{
636 switch (cb_config->soc_id) {
637 case PLATFORM_RENOIR:
638 case PLATFORM_LUCIENNE:
639 case PLATFORM_CEZANNE:
Arthur Heymans563f7af2023-07-13 11:40:08 +0200640 case PLATFORM_GENOA:
Zheng Bao2f6b7d52023-02-11 22:27:49 +0800641 if (!cb_config->recovery_ab)
642 amd_romsig->bios3_entry =
643 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
644 break;
645 case PLATFORM_MENDOCINO:
646 case PLATFORM_PHOENIX:
647 case PLATFORM_GLINDA:
648 break;
649 case PLATFORM_CARRIZO:
650 case PLATFORM_STONEYRIDGE:
651 case PLATFORM_RAVEN:
652 case PLATFORM_PICASSO:
653 default:
654 amd_romsig->bios1_entry =
655 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
656 break;
657 }
658}
659
Zheng Baoeb0404e2021-10-14 15:09:09 +0800660static uint32_t get_psp_id(enum platform soc_id)
661{
662 uint32_t psp_id;
663 switch (soc_id) {
664 case PLATFORM_RAVEN:
665 case PLATFORM_PICASSO:
666 psp_id = 0xBC0A0000;
667 break;
668 case PLATFORM_RENOIR:
669 case PLATFORM_LUCIENNE:
670 psp_id = 0xBC0C0000;
671 break;
672 case PLATFORM_CEZANNE:
673 psp_id = 0xBC0C0140;
674 break;
675 case PLATFORM_MENDOCINO:
676 psp_id = 0xBC0D0900;
677 break;
678 case PLATFORM_STONEYRIDGE:
679 psp_id = 0x10220B00;
680 break;
Zheng Baode6f1982022-10-16 20:32:43 +0800681 case PLATFORM_GLINDA:
682 psp_id = 0xBC0E0200;
683 break;
684 case PLATFORM_PHOENIX:
685 psp_id = 0xBC0D0400;
686 break;
Arthur Heymans563f7af2023-07-13 11:40:08 +0200687 case PLATFORM_GENOA:
688 psp_id = 0xBC0C0111;
689 break;
Zheng Bao3d7623f2022-08-17 11:52:30 +0800690 case PLATFORM_CARRIZO:
Zheng Baoeb0404e2021-10-14 15:09:09 +0800691 default:
692 psp_id = 0;
693 break;
694 }
695 return psp_id;
696}
697
Marshall Dawson2794a862019-03-04 16:53:15 -0700698static void integrate_firmwares(context *ctx,
Marshall Dawson239286c2019-02-23 16:42:46 -0700699 embedded_firmware *romsig,
Marshall Dawson2794a862019-03-04 16:53:15 -0700700 amd_fw_entry *fw_table)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800701{
Richard Spiegel137484d2018-01-17 10:23:19 -0700702 ssize_t bytes;
Zheng Bao6d402ac2020-10-01 16:16:30 +0800703 uint32_t i;
Marshall Dawson2794a862019-03-04 16:53:15 -0700704
Zheng Baoc26108f2023-02-17 11:01:07 +0800705 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800706
Martin Rothcd15bc82016-11-08 11:34:02 -0700707 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
zbaoc3a08a92016-03-02 14:47:27 +0800708 if (fw_table[i].filename != NULL) {
zbaoc3a08a92016-03-02 14:47:27 +0800709 switch (fw_table[i].type) {
710 case AMD_FW_IMC:
Zheng Baoc26108f2023-02-17 11:01:07 +0800711 adjust_current_pointer(ctx, 0, 0x10000U);
Marshall Dawson2794a862019-03-04 16:53:15 -0700712 romsig->imc_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800713 break;
714 case AMD_FW_GEC:
Marshall Dawson2794a862019-03-04 16:53:15 -0700715 romsig->gec_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800716 break;
717 case AMD_FW_XHCI:
Marshall Dawson2794a862019-03-04 16:53:15 -0700718 romsig->xhci_entry = RUN_CURRENT(*ctx);
zbaoc3a08a92016-03-02 14:47:27 +0800719 break;
720 default:
721 /* Error */
722 break;
723 }
724
Marshall Dawson2794a862019-03-04 16:53:15 -0700725 bytes = copy_blob(BUFF_CURRENT(*ctx),
726 fw_table[i].filename, BUFF_ROOM(*ctx));
Marshall Dawson02bd7732019-03-13 14:43:17 -0600727 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +0800728 amdfwtool_cleanup(ctx);
Martin Roth60f15512016-11-08 09:55:01 -0700729 exit(1);
730 }
731
Zheng Baoc26108f2023-02-17 11:01:07 +0800732 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800733 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800734 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800735}
736
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +0000737static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
738{
739 struct amd_fw_header hdr;
740 int blob_fd;
741 ssize_t bytes;
742
743 blob_fd = open(fw_entry->filename, O_RDONLY);
744 if (blob_fd < 0) {
745 fprintf(stderr, "Error opening file: %s: %s\n",
746 fw_entry->filename, strerror(errno));
747 return;
748 }
749
750 bytes = read(blob_fd, &hdr, sizeof(hdr));
751 if (bytes != sizeof(hdr)) {
752 close(blob_fd);
753 fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
754 return;
755 }
756
757 dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
758 fw_entry->type, hdr.version[3], hdr.version[2],
759 hdr.version[1], hdr.version[0]);
760
761 close(blob_fd);
762
763}
764
765static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
766{
767 amd_fw_entry *index;
768 int manifest_fd;
769
770 manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
771 if (manifest_fd < 0) {
772 fprintf(stderr, "Error opening file: %s: %s\n",
773 manifest_file, strerror(errno));
774 return;
775 }
776
777 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
778 if (!(index->filename))
779 continue;
780
781 if (index->generate_manifest == true)
782 output_manifest(manifest_fd, index);
783 }
784
785 close(manifest_fd);
786}
787
Zheng Bao9e908072020-10-28 11:39:13 +0800788/* For debugging */
789static void dump_psp_firmwares(amd_fw_entry *fw_table)
790{
791 amd_fw_entry *index;
792
Zheng Bao29514472023-08-25 19:12:47 +0800793 printf("PSP firmware components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800794 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
Zheng Bao730c3ba2023-08-25 19:20:37 +0800795 if (index->type == AMD_PSP_FUSE_CHAIN)
796 printf(" %2x: level=%x, subprog=%x, inst=%x\n",
797 index->type, index->level, index->subprog, index->inst);
798 else if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800799 printf(" %2x: level=%x, subprog=%x, inst=%x, %s\n",
800 index->type, index->level, index->subprog, index->inst,
801 index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800802 }
803}
804
805static void dump_bdt_firmwares(amd_bios_entry *fw_table)
806{
807 amd_bios_entry *index;
808
Zheng Bao29514472023-08-25 19:12:47 +0800809 printf("BIOS Directory Table (BDT) components:\n");
Zheng Bao9e908072020-10-28 11:39:13 +0800810 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
811 if (index->filename)
Zheng Bao29514472023-08-25 19:12:47 +0800812 printf(" %2x: level=%x, %s\n",
813 index->type, index->level, index->filename);
Zheng Bao9e908072020-10-28 11:39:13 +0800814 }
815}
816
Zheng Baoe4214b72024-03-13 22:51:24 +0800817static void dump_image_addresses(context *ctx)
818{
819 printf("romsig offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->amd_romsig_ptr));
820 printf("PSP L1 offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir));
821 if (ctx->pspdir2 != NULL)
822 printf("PSP L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2));
823 if (ctx->ish_a_dir != NULL)
824 printf("ISHA offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_a_dir));
825 if (ctx->ish_b_dir != NULL)
826 printf("ISHB offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_b_dir));
827 if (ctx->pspdir2_b != NULL)
828 printf("PSP L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2_b));
829 if (ctx->biosdir != NULL)
830 printf("BHD offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir));
831 if (ctx->biosdir2 != NULL)
832 printf("BHD L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2));
833 if (ctx->biosdir2_b != NULL)
834 printf("BHD L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2_b));
835 if (ctx->psp_combo_dir != NULL)
836 printf("PSP combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->psp_combo_dir));
837 if (ctx->bhd_combo_dir != NULL)
838 printf("BHD combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->bhd_combo_dir));
839}
840
Zheng Bao990d1542021-09-17 13:24:54 +0800841static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
Zheng Baofdd47ef2021-09-17 13:30:08 +0800842 psp_directory_table *pspdir2, ish_directory_table *ish,
843 amd_fw_type ab, enum platform soc_id)
Zheng Bao990d1542021-09-17 13:24:54 +0800844{
845 uint32_t count;
846 uint32_t current_table_save;
847
848 current_table_save = ctx->current_table;
Zheng Bao75758002023-10-09 18:35:27 +0800849 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao990d1542021-09-17 13:24:54 +0800850 count = pspdir->header.num_entries;
851 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
852 pspdir->entries[count].type = (uint8_t)ab;
853 pspdir->entries[count].subprog = 0;
854 pspdir->entries[count].rsvd = 0;
Zheng Baofdd47ef2021-09-17 13:30:08 +0800855 if (ish != NULL) {
Robert Zieba29bc79f2022-03-14 15:59:12 -0600856 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800857 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
858 ish->update_retry_count = 2;
859 ish->glitch_retry_count = 0;
860 ish->psp_id = get_psp_id(soc_id);
861 ish->checksum = fletcher32(&ish->boot_priority,
862 sizeof(ish_directory_table) - sizeof(uint32_t));
863 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600864 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800865 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600866 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800867 pspdir->entries[count].size = TABLE_ALIGNMENT;
868 } else {
869 pspdir->entries[count].addr =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600870 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
Zheng Baofdd47ef2021-09-17 13:30:08 +0800871 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -0600872 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao948c0b72023-05-11 10:03:46 +0800873 pspdir->entries[count].size = _MAX(TABLE_ALIGNMENT,
874 pspdir2->header.num_entries *
Zheng Bao990d1542021-09-17 13:24:54 +0800875 sizeof(psp_directory_entry) +
Zheng Bao948c0b72023-05-11 10:03:46 +0800876 sizeof(psp_directory_header));
Zheng Baofdd47ef2021-09-17 13:30:08 +0800877 }
Zheng Bao990d1542021-09-17 13:24:54 +0800878
879 count++;
Zheng Baoe8f9d182024-03-21 11:33:52 +0800880 fill_dir_header(pspdir, count, ctx);
Zheng Bao990d1542021-09-17 13:24:54 +0800881 ctx->current_table = current_table_save;
882}
883
Zheng Baof3600952024-03-14 13:35:38 +0800884static void integrate_psp_levels(context *ctx,
885 amd_cb_config *cb_config)
886{
887 uint32_t current_table_save;
888 bool recovery_ab = cb_config->recovery_ab;
889 unsigned int count;
890 psp_directory_table *pspdir, *pspdir2, *pspdir2_b;
891 bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
892
893 pspdir = ctx->pspdir;
894 pspdir2 = ctx->pspdir2;
895 pspdir2_b = ctx->pspdir2_b;
896 count = pspdir->header.num_entries;
897
898 current_table_save = ctx->current_table;
899 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
900 if (recovery_ab && (pspdir2 != NULL)) {
901 if (cb_config->need_ish) { /* Need ISH */
902 ctx->ish_a_dir = new_ish_dir(ctx);
903 if (pspdir2_b != NULL)
904 ctx->ish_b_dir = new_ish_dir(ctx);
905 }
Zheng Baof3600952024-03-14 13:35:38 +0800906 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
907 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
908 if (pspdir2_b != NULL)
909 integrate_psp_ab(ctx, pspdir, pspdir2_b, ctx->ish_b_dir,
910 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
911 cb_config->soc_id);
912 else
913 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
914 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
915 cb_config->soc_id);
916
Zheng Baof3600952024-03-14 13:35:38 +0800917 } else if (pspdir2 != NULL) {
918 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
919 pspdir->entries[count].type = AMD_FW_L2_PTR;
920 pspdir->entries[count].subprog = 0;
921 pspdir->entries[count].rsvd = 0;
922 pspdir->entries[count].size = sizeof(pspdir2->header)
923 + pspdir2->header.num_entries
924 * sizeof(psp_directory_entry);
925
926 pspdir->entries[count].addr =
927 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
928 pspdir->entries[count].address_mode =
929 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
930 count++;
Zheng Baoe8f9d182024-03-21 11:33:52 +0800931 fill_dir_header(pspdir, count, ctx);
Zheng Baof3600952024-03-14 13:35:38 +0800932 }
Zheng Baof3600952024-03-14 13:35:38 +0800933 ctx->current_table = current_table_save;
934}
935
Marshall Dawson2794a862019-03-04 16:53:15 -0700936static void integrate_psp_firmwares(context *ctx,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600937 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800938 uint32_t cookie,
939 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800940{
Richard Spiegel137484d2018-01-17 10:23:19 -0700941 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700942 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600943 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530944 uint32_t size;
Zheng Baoeea834b2024-03-14 13:17:05 +0800945 psp_directory_table *pspdir;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530946 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800947 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800948 bool recovery_ab = cb_config->recovery_ab;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600949
950 /* This function can create a primary table, a secondary table, or a
951 * flattened table which contains all applicable types. These if-else
952 * statements infer what the caller intended. If a 2nd-level cookie
953 * is passed, clearly a 2nd-level table is intended. However, a
Zheng Baoe0793792024-03-13 23:35:29 +0800954 * 1st-level cookie may indicate level 1 or flattened.
Marshall Dawson24f73d42019-04-01 10:48:43 -0600955 */
Zheng Baob81b7da2024-03-14 13:29:34 +0800956 pspdir = new_psp_dir(ctx, cb_config->multi_level, cookie);
Zheng Baoeea834b2024-03-14 13:17:05 +0800957
958 if (cookie == PSP_COOKIE)
959 ctx->pspdir = pspdir;
960 else if (cookie == PSPL2_COOKIE) {
961 if (ctx->pspdir2 == NULL)
962 ctx->pspdir2 = pspdir;
963 else if (ctx->pspdir2_b == NULL)
964 ctx->pspdir2_b = pspdir;
965 }
966
Zheng Baoba3af5e2021-11-04 18:56:47 +0800967 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800968 level = PSP_BOTH;
969 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600970 level = PSP_LVL2;
Zheng Baoe0793792024-03-13 23:35:29 +0800971 else if (cookie == PSP_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600972 level = PSP_LVL1;
973 else
974 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -0700975
Zheng Bao990d1542021-09-17 13:24:54 +0800976 if (recovery_ab) {
977 if (cookie == PSPL2_COOKIE)
978 level = PSP_LVL2_AB;
Zheng Baoe0793792024-03-13 23:35:29 +0800979 else if (cookie == PSP_COOKIE)
Zheng Bao990d1542021-09-17 13:24:54 +0800980 level = PSP_LVL1_AB;
981 else
982 level = PSP_BOTH_AB;
983 }
Zheng Bao6fff2492021-11-15 19:53:21 +0800984 current_table_save = ctx->current_table;
Zheng Bao75758002023-10-09 18:35:27 +0800985 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
Zheng Baoc26108f2023-02-17 11:01:07 +0800986 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800987
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700988 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -0600989 if (!(fw_table[i].level & level))
990 continue;
991
Zheng Bao5164e4b2021-10-30 12:09:07 +0800992 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
993
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600994 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
995 if (!fw_table[i].other)
996 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +0800997 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600998 pspdir->entries[count].type = fw_table[i].type;
999 pspdir->entries[count].size = 4096; /* TODO: doc? */
1000 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001001 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001002 pspdir->entries[count].subprog = fw_table[i].subprog;
1003 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +08001004 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001005 count++;
1006 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001007 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001008 pspdir->entries[count].subprog = fw_table[i].subprog;
1009 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001010 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001011 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001012 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001013 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001014 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301015 if (fw_table[i].filename == NULL) {
1016 if (fw_table[i].size == 0)
1017 continue;
1018 size = fw_table[i].size;
1019 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001020 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301021 fprintf(stderr,
1022 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001023 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301024 exit(1);
1025 }
1026 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +08001027 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301028 bytes = copy_blob(BUFF_CURRENT(*ctx),
1029 fw_table[i].filename, BUFF_ROOM(*ctx));
1030 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001031 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301032 exit(1);
1033 }
1034
Elyes Haouas7d67a192022-10-14 09:58:29 +02001035 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301036 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001037 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001038 }
1039
1040 pspdir->entries[count].type = fw_table[i].type;
1041 pspdir->entries[count].subprog = fw_table[i].subprog;
1042 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301043 pspdir->entries[count].size = size;
1044 pspdir->entries[count].addr = addr;
1045
Zheng Bao6fff2492021-11-15 19:53:21 +08001046 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001047 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001048
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001049 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001050 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001051 if (fw_table[i].addr_signed) {
1052 pspdir->entries[count].addr =
1053 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1054 pspdir->entries[count].address_mode =
1055 SET_ADDR_MODE_BY_TABLE(pspdir);
1056 bytes = fw_table[i].file_size;
1057 } else {
1058 bytes = copy_blob(BUFF_CURRENT(*ctx),
1059 fw_table[i].filename, BUFF_ROOM(*ctx));
1060 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001061 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001062 exit(1);
1063 }
1064 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1065 pspdir->entries[count].address_mode =
1066 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001067 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001068 }
1069
Marshall Dawson239286c2019-02-23 16:42:46 -07001070 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001071 pspdir->entries[count].subprog = fw_table[i].subprog;
1072 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001073 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001074 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001075
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001076 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001077 } else {
1078 /* This APU doesn't have this firmware. */
1079 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001080 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001081
Zheng Baob81b7da2024-03-14 13:29:34 +08001082 fill_dir_header(pspdir, count, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001083 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001084}
1085
Zheng Bao990d1542021-09-17 13:24:54 +08001086static void add_psp_firmware_entry(context *ctx,
1087 psp_directory_table *pspdir,
1088 void *table, amd_fw_type type, uint32_t size)
1089{
1090 uint32_t count = pspdir->header.num_entries;
1091 uint32_t index;
1092 uint32_t current_table_save;
1093
1094 current_table_save = ctx->current_table;
Zheng Bao75758002023-10-09 18:35:27 +08001095 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao990d1542021-09-17 13:24:54 +08001096
1097 /* If there is an entry of "type", replace it. */
1098 for (index = 0; index < count; index++) {
1099 if (pspdir->entries[index].type == (uint8_t)type)
1100 break;
1101 }
1102
1103 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1104 pspdir->entries[index].type = (uint8_t)type;
1105 pspdir->entries[index].subprog = 0;
1106 pspdir->entries[index].rsvd = 0;
1107 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1108 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1109 pspdir->entries[index].size = size;
1110 if (index == count)
1111 count++;
1112
Zheng Baob81b7da2024-03-14 13:29:34 +08001113 fill_dir_header(pspdir, count, ctx);
Zheng Bao990d1542021-09-17 13:24:54 +08001114 ctx->current_table = current_table_save;
1115}
1116
Zheng Baob81b7da2024-03-14 13:29:34 +08001117static void *new_bios_dir(context *ctx, bool multi, uint32_t cookie)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001118{
1119 void *ptr;
1120
1121 /*
1122 * Force both onto boundary when multi. Primary table is after
1123 * updatable table, so alignment ensures primary can stay intact
1124 * if secondary is reprogrammed.
1125 */
1126 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001127 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001128 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001129 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001130 ptr = BUFF_CURRENT(*ctx);
Zheng Baob81b7da2024-03-14 13:29:34 +08001131 ((bios_directory_hdr *) ptr)->cookie = cookie;
Zheng Bao6fff2492021-11-15 19:53:21 +08001132 ((bios_directory_hdr *) ptr)->additional_info = 0;
1133 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +08001134 adjust_current_pointer(ctx,
1135 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1136 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001137 return ptr;
1138}
1139
1140static int locate_bdt2_bios(bios_directory_table *level2,
1141 uint64_t *source, uint32_t *size)
1142{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001143 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001144
1145 *source = 0;
1146 *size = 0;
1147 if (!level2)
1148 return 0;
1149
1150 for (i = 0 ; i < level2->header.num_entries ; i++) {
1151 if (level2->entries[i].type == AMD_BIOS_BIN) {
1152 *source = level2->entries[i].source;
1153 *size = level2->entries[i].size;
1154 return 1;
1155 }
1156 }
1157 return 0;
1158}
1159
1160static int have_bios_tables(amd_bios_entry *table)
1161{
1162 int i;
1163
1164 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1165 if (table[i].level & BDT_LVL1 && table[i].filename)
1166 return 1;
1167 }
1168 return 0;
1169}
1170
Zheng Baoe35c5022023-10-11 16:08:44 +08001171int find_bios_entry(amd_bios_type type)
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001172{
1173 int i;
1174
1175 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1176 if (amd_bios_table[i].type == type)
1177 return i;
1178 }
1179 return -1;
1180}
1181
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001182static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1183 int inst, uint32_t size, uint64_t source)
1184{
1185 int i;
1186
1187 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1188 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1189 amd_bios_table[i].inst == inst)
1190 break;
1191 }
1192
1193 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1194 return;
1195
1196 biosdir->entries[idx].type = amd_bios_table[i].type;
1197 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1198 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1199 amd_bios_table[i].dest : (uint64_t)-1;
1200 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1201 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1202 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1203 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1204 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1205 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1206 biosdir->entries[idx].size = size;
1207 biosdir->entries[idx].source = source;
1208 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1209}
1210
Zheng Baoe80d0622024-03-16 17:12:30 +08001211static void integrate_bios_levels(context *ctx, amd_cb_config *cb_config)
Zheng Baof3600952024-03-14 13:35:38 +08001212{
Zheng Baoe80d0622024-03-16 17:12:30 +08001213 unsigned int count;
Zheng Baof3600952024-03-14 13:35:38 +08001214 uint32_t current_table_save;
1215
Zheng Baoe80d0622024-03-16 17:12:30 +08001216 if (cb_config->recovery_ab) {
1217 add_psp_firmware_entry(ctx, ctx->pspdir2, ctx->biosdir2,
1218 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
1219 if (ctx->pspdir2_b != NULL)
1220 add_psp_firmware_entry(ctx, ctx->pspdir2_b,
1221 ctx->biosdir2_b, AMD_FW_BIOS_TABLE,
1222 TABLE_ALIGNMENT);
1223 } else if (ctx->biosdir2) {
1224 current_table_save = ctx->current_table;
Zheng Bao75758002023-10-09 18:35:27 +08001225 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, ctx->biosdir, AMD_ADDR_REL_BIOS);
Zheng Baoe80d0622024-03-16 17:12:30 +08001226 count = ctx->biosdir->header.num_entries;
Zheng Baof3600952024-03-14 13:35:38 +08001227 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1228 ctx->biosdir->entries[count].type = AMD_BIOS_L2_PTR;
1229 ctx->biosdir->entries[count].region_type = 0;
1230 ctx->biosdir->entries[count].size =
1231 + MAX_BIOS_ENTRIES
1232 * sizeof(bios_directory_entry);
1233 ctx->biosdir->entries[count].source =
1234 BUFF_TO_RUN(*ctx, ctx->biosdir2);
1235 ctx->biosdir->entries[count].address_mode =
1236 SET_ADDR_MODE(ctx->biosdir, AMD_ADDR_REL_BIOS);
1237 ctx->biosdir->entries[count].subprog = 0;
1238 ctx->biosdir->entries[count].inst = 0;
1239 ctx->biosdir->entries[count].copy = 0;
1240 ctx->biosdir->entries[count].compressed = 0;
1241 ctx->biosdir->entries[count].dest = -1;
1242 ctx->biosdir->entries[count].reset = 0;
1243 ctx->biosdir->entries[count].ro = 0;
1244 count++;
Zheng Baoe80d0622024-03-16 17:12:30 +08001245 fill_dir_header(ctx->biosdir, count, ctx);
1246 ctx->current_table = current_table_save;
Zheng Baof3600952024-03-14 13:35:38 +08001247 }
Zheng Baof3600952024-03-14 13:35:38 +08001248}
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001249static void integrate_bios_firmwares(context *ctx,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001250 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001251 uint32_t cookie,
1252 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001253{
1254 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001255 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001256 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001257 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001258 uint32_t size;
1259 uint64_t source;
Zheng Baoa640b122023-10-09 17:36:08 +08001260 uint32_t current_table_save;
Zheng Baoeea834b2024-03-14 13:17:05 +08001261 bios_directory_table *biosdir;
1262
Zheng Baob81b7da2024-03-14 13:29:34 +08001263 biosdir = new_bios_dir(ctx, cb_config->multi_level, cookie);
Zheng Baoeea834b2024-03-14 13:17:05 +08001264
1265 if (cookie == BHD_COOKIE)
1266 ctx->biosdir = biosdir;
1267 else if (cookie == BHDL2_COOKIE) {
1268 if (ctx->biosdir2 == NULL)
1269 ctx->biosdir2 = biosdir;
1270 else if (ctx->biosdir2_b == NULL)
1271 ctx->biosdir2_b = biosdir;
1272 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001273
1274 /* This function can create a primary table, a secondary table, or a
1275 * flattened table which contains all applicable types. These if-else
1276 * statements infer what the caller intended. If a 2nd-level cookie
1277 * is passed, clearly a 2nd-level table is intended. However, a
Zheng Baoe0793792024-03-13 23:35:29 +08001278 * 1st-level cookie may indicate level 1 or flattened.
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001279 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001280 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001281 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001282 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001283 level = BDT_LVL2;
Zheng Baoe0793792024-03-13 23:35:29 +08001284 else if (cookie == BHD_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001285 level = BDT_LVL1;
1286 else
1287 level = BDT_BOTH;
1288
Zheng Baoa640b122023-10-09 17:36:08 +08001289 current_table_save = ctx->current_table;
Zheng Bao75758002023-10-09 18:35:27 +08001290 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
Zheng Baoc26108f2023-02-17 11:01:07 +08001291 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001292
1293 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1294 if (!(fw_table[i].level & level))
1295 continue;
1296 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301297 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001298 fw_table[i].type != AMD_BIOS_APOB &&
1299 fw_table[i].type != AMD_BIOS_APOB_NV &&
1300 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001301 fw_table[i].type != AMD_BIOS_BIN &&
1302 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001303 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001304
1305 /* BIOS Directory items may have additional requirements */
1306
Ritul Guru9a321f32022-07-29 11:06:40 +05301307 /* SIG needs a size, else no choice but to skip */
1308 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1309 continue;
1310
Martin Roth48dd9fe2020-07-29 16:32:25 -06001311 /* Check APOB_NV requirements */
1312 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1313 if (!fw_table[i].size && !fw_table[i].src)
1314 continue; /* APOB_NV not used */
1315 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001316 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001317 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001318 exit(1);
1319 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001320 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001321 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001322 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1323 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001324 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001325
1326 /* APOB_DATA needs destination */
1327 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001328 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001329 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001330 exit(1);
1331 }
1332
1333 /* BIOS binary must have destination and uncompressed size. If
1334 * no filename given, then user must provide a source address.
1335 */
1336 if (fw_table[i].type == AMD_BIOS_BIN) {
1337 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001338 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001339 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001340 exit(1);
1341 }
1342 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001343 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001344 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001345 exit(1);
1346 }
1347 }
1348
Martin Roth94554742020-04-14 14:59:36 -06001349 /* PSP_SHARED_MEM needs a destination and size */
1350 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1351 (!fw_table[i].dest || !fw_table[i].size))
1352 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001353 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001354
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001355 biosdir->entries[count].type = fw_table[i].type;
1356 biosdir->entries[count].region_type = fw_table[i].region_type;
1357 biosdir->entries[count].dest = fw_table[i].dest ?
1358 fw_table[i].dest : (uint64_t)-1;
1359 biosdir->entries[count].reset = fw_table[i].reset;
1360 biosdir->entries[count].copy = fw_table[i].copy;
1361 biosdir->entries[count].ro = fw_table[i].ro;
1362 biosdir->entries[count].compressed = fw_table[i].zlib;
1363 biosdir->entries[count].inst = fw_table[i].inst;
1364 biosdir->entries[count].subprog = fw_table[i].subpr;
1365
1366 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301367 case AMD_BIOS_SIG:
1368 /* Reserve size bytes within amdfw.rom */
1369 biosdir->entries[count].size = fw_table[i].size;
1370 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1371 biosdir->entries[count].address_mode =
1372 SET_ADDR_MODE_BY_TABLE(biosdir);
1373 memset(BUFF_CURRENT(*ctx), 0xff,
1374 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001375 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301376 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001377 case AMD_BIOS_APOB:
1378 biosdir->entries[count].size = fw_table[i].size;
1379 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001380 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001381 break;
1382 case AMD_BIOS_APOB_NV:
1383 if (fw_table[i].src) {
1384 /* If source is given, use that and its size */
1385 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001386 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001387 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001388 biosdir->entries[count].size = fw_table[i].size;
1389 } else {
1390 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001391 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001392 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001393 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001394 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001395 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001396 fw_table[i].size, ERASE_ALIGNMENT);
1397 memset(BUFF_CURRENT(*ctx), 0xff,
1398 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001399 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001400 }
1401 break;
1402 case AMD_BIOS_BIN:
1403 /* Don't make a 2nd copy, point to the same one */
Zheng Baoeea834b2024-03-14 13:17:05 +08001404 if (level == BDT_LVL1 && locate_bdt2_bios(ctx->biosdir2, &source, &size)) {
Martin Rotheca423b2020-09-01 10:54:11 -06001405 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001406 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001407 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001408 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001409 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001410 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001411
1412 /* level 2, or level 1 and no copy found in level 2 */
1413 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001414 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001415 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001416 biosdir->entries[count].dest = fw_table[i].dest;
1417 biosdir->entries[count].size = fw_table[i].size;
1418
1419 if (!fw_table[i].filename)
1420 break;
1421
1422 bytes = copy_blob(BUFF_CURRENT(*ctx),
1423 fw_table[i].filename, BUFF_ROOM(*ctx));
1424 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001425 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001426 exit(1);
1427 }
1428
Zheng Bao6fff2492021-11-15 19:53:21 +08001429 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001430 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001431 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001432 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001433
Zheng Baoc26108f2023-02-17 11:01:07 +08001434 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001435 break;
Martin Roth94554742020-04-14 14:59:36 -06001436 case AMD_BIOS_PSP_SHARED_MEM:
1437 biosdir->entries[count].dest = fw_table[i].dest;
1438 biosdir->entries[count].size = fw_table[i].size;
1439 break;
1440
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001441 default: /* everything else is copied from input */
1442 if (fw_table[i].type == AMD_BIOS_APCB ||
1443 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001444 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001445 bytes = copy_blob(BUFF_CURRENT(*ctx),
1446 fw_table[i].filename, BUFF_ROOM(*ctx));
1447 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001448 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001449 exit(1);
1450 }
1451
1452 biosdir->entries[count].size = (uint32_t)bytes;
1453 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001454 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001455
Zheng Baoc26108f2023-02-17 11:01:07 +08001456 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001457 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1458 size = biosdir->entries[count].size;
1459 source = biosdir->entries[count].source;
1460 count++;
1461 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1462 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001463 break;
1464 }
1465
1466 count++;
1467 }
1468
Zheng Baob81b7da2024-03-14 13:29:34 +08001469 fill_dir_header(biosdir, count, ctx);
Zheng Baoa640b122023-10-09 17:36:08 +08001470 ctx->current_table = current_table_save;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001471}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001472
Zheng Baoc3007f32022-04-03 12:53:51 +08001473static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
Zheng Baoe35c5022023-10-11 16:08:44 +08001474 embedded_firmware *amd_romsig)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001475{
Zheng Baoe35c5022023-10-11 16:08:44 +08001476 if ((cb_config->efs_spi_readmode == 0xFF) || (cb_config->efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001477 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001478 return 1;
1479 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001480
1481 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1482 * Leave as 0xffffffff for first gen */
1483 if (cb_config->second_gen) {
1484 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1485 amd_romsig->efs_gen.reserved = 0;
1486 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001487 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1488 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001489 }
1490
1491 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001492 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001493 case PLATFORM_STONEYRIDGE:
Zheng Baoe35c5022023-10-11 16:08:44 +08001494 amd_romsig->spi_readmode_f15_mod_60_6f = cb_config->efs_spi_readmode;
1495 amd_romsig->fast_speed_new_f15_mod_60_6f = cb_config->efs_spi_speed;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001496 break;
1497 case PLATFORM_RAVEN:
1498 case PLATFORM_PICASSO:
Zheng Baoe35c5022023-10-11 16:08:44 +08001499 amd_romsig->spi_readmode_f17_mod_00_2f = cb_config->efs_spi_readmode;
1500 amd_romsig->spi_fastspeed_f17_mod_00_2f = cb_config->efs_spi_speed;
1501 switch (cb_config->efs_spi_micron_flag) {
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001502 case 0:
1503 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1504 break;
1505 case 1:
1506 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1507 break;
1508 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001509 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001510 return 1;
1511 }
1512 break;
1513 case PLATFORM_RENOIR:
1514 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001515 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001516 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001517 case PLATFORM_PHOENIX:
1518 case PLATFORM_GLINDA:
Arthur Heymans563f7af2023-07-13 11:40:08 +02001519 case PLATFORM_GENOA:
Zheng Baoe35c5022023-10-11 16:08:44 +08001520 amd_romsig->spi_readmode_f17_mod_30_3f = cb_config->efs_spi_readmode;
1521 amd_romsig->spi_fastspeed_f17_mod_30_3f = cb_config->efs_spi_speed;
1522 switch (cb_config->efs_spi_micron_flag) {
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001523 case 0:
1524 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1525 break;
1526 case 1:
1527 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1528 break;
1529 case 2:
1530 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1531 break;
1532 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001533 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001534 return 1;
1535 }
1536 break;
1537 case PLATFORM_UNKNOWN:
1538 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001539 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001540 return 1;
1541 }
1542 return 0;
1543}
1544
Zheng Bao18cf3f72024-03-09 12:38:16 +08001545void open_process_config(char *config, amd_cb_config *cb_config)
Zheng Bao39cae562023-03-07 18:37:43 +08001546{
1547 FILE *config_handle;
1548
1549 if (config) {
1550 config_handle = fopen(config, "r");
1551 if (config_handle == NULL) {
1552 fprintf(stderr, "Can not open file %s for reading: %s\n",
1553 config, strerror(errno));
1554 exit(1);
1555 }
Zheng Bao994ff522023-03-09 11:43:55 +08001556 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001557 fprintf(stderr, "Configuration file %s parsing error\n",
1558 config);
1559 fclose(config_handle);
1560 exit(1);
1561 }
1562 fclose(config_handle);
1563 }
1564
1565 /* For debug. */
Zheng Bao18cf3f72024-03-09 12:38:16 +08001566 if (cb_config->debug) {
Zheng Bao39cae562023-03-07 18:37:43 +08001567 dump_psp_firmwares(amd_psp_fw_table);
1568 dump_bdt_firmwares(amd_bios_table);
1569 }
1570}
1571
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001572static bool is_initial_alignment_required(enum platform soc_id)
1573{
1574 switch (soc_id) {
1575 case PLATFORM_MENDOCINO:
1576 case PLATFORM_PHOENIX:
1577 case PLATFORM_GLINDA:
1578 return false;
1579 default:
1580 return true;
1581 }
1582}
1583
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001584int main(int argc, char **argv)
1585{
Martin Roth31d95a22016-11-08 11:22:12 -07001586 int retval = 0;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001587 int combo_index = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001588 int targetfd;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001589 context ctx = { 0 };
Martin Roth0d3b1182017-10-03 14:16:04 -06001590 uint32_t romsig_offset;
Zheng Baoe35c5022023-10-11 16:08:44 +08001591 amd_cb_config cb_config = {
1592 .efs_spi_readmode = 0xff, .efs_spi_speed = 0xff, .efs_spi_micron_flag = 0xff
1593 };
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001594
Zheng Baoc26108f2023-02-17 11:01:07 +08001595 ctx.current_pointer_saved = 0xFFFFFFFF;
1596
Zheng Baoe35c5022023-10-11 16:08:44 +08001597 retval = amdfwtool_getopt(argc, argv, &cb_config, &ctx);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001598
Zheng Baoe35c5022023-10-11 16:08:44 +08001599 if (retval) {
1600 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001601 }
1602
Zheng Bao8dd34bd2023-03-09 21:09:58 +08001603 if (cb_config.use_combo) {
1604 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
1605 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
1606 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
1607 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
1608 }
1609
Zheng Bao18cf3f72024-03-09 12:38:16 +08001610 open_process_config(cb_config.config, &cb_config);
Zheng Bao9e908072020-10-28 11:39:13 +08001611
Marshall Dawson2794a862019-03-04 16:53:15 -07001612 ctx.rom = malloc(ctx.rom_size);
1613 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001614 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07001615 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07001616 }
1617 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07001618
Zheng Baoe35c5022023-10-11 16:08:44 +08001619 romsig_offset = cb_config.efs_location ? cb_config.efs_location : AMD_ROMSIG_OFFSET;
Zheng Bao6095cd12023-02-21 10:52:47 +08001620 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06001621
Zheng Baoe4214b72024-03-13 22:51:24 +08001622 ctx.amd_romsig_ptr = BUFF_OFFSET(ctx, romsig_offset);
1623 ctx.amd_romsig_ptr->signature = EMBEDDED_FW_SIGNATURE;
1624 ctx.amd_romsig_ptr->imc_entry = 0;
1625 ctx.amd_romsig_ptr->gec_entry = 0;
1626 ctx.amd_romsig_ptr->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001627
Zheng Bao4bf6f492023-01-25 22:37:29 +08001628 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001629 retval = set_efs_table(cb_config.soc_id, &cb_config, ctx.amd_romsig_ptr);
Zheng Bao570645d2021-11-03 10:25:03 +08001630 if (retval) {
1631 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
1632 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001633 }
1634 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08001635 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001636 }
1637
Felix Held21a8e382022-03-29 23:10:45 +02001638 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001639 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08001640 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001641 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001642 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06001643 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001644
Zheng Baoe35c5022023-10-11 16:08:44 +08001645 if (cb_config.efs_location != cb_config.body_location)
1646 set_current_pointer(&ctx, cb_config.body_location);
Zheng Bao6095cd12023-02-21 10:52:47 +08001647 else
1648 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
1649
Zheng Baoe4214b72024-03-13 22:51:24 +08001650 integrate_firmwares(&ctx, ctx.amd_romsig_ptr, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001651
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001652 if (is_initial_alignment_required(cb_config.soc_id)) {
1653 /* TODO: Check for older platforms. */
1654 adjust_current_pointer(&ctx, 0, 0x10000U);
1655 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001656 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07001657
Kangheui Won3c164e12021-12-03 20:25:05 +11001658 /* If the tool is invoked with command-line options to keep the signed PSP
1659 binaries separate, process the signed binaries first. */
Zheng Baoe35c5022023-10-11 16:08:44 +08001660 if (cb_config.signed_output_file && cb_config.signed_start_addr)
1661 process_signed_psp_firmwares(cb_config.signed_output_file,
Kangheui Won3c164e12021-12-03 20:25:05 +11001662 amd_psp_fw_table,
Zheng Baoe35c5022023-10-11 16:08:44 +08001663 cb_config.signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001664 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11001665
Zheng Baob2ae6a52022-08-18 15:45:27 +08001666 if (cb_config.use_combo) {
Zheng Baob81b7da2024-03-14 13:29:34 +08001667 ctx.psp_combo_dir = new_combo_dir(&ctx, PSP2_COOKIE);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001668
1669 adjust_current_pointer(&ctx, 0, 0x1000U);
1670
Zheng Baod22c2c82024-03-09 10:56:06 +08001671 if (!cb_config.recovery_ab)
Zheng Baob81b7da2024-03-14 13:29:34 +08001672 ctx.bhd_combo_dir = new_combo_dir(&ctx, BHD2_COOKIE);
Zheng Baob2ae6a52022-08-18 15:45:27 +08001673 }
1674
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001675 combo_index = 0;
Zheng Baoe35c5022023-10-11 16:08:44 +08001676 if (cb_config.config)
1677 cb_config.combo_config[0] = cb_config.config;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001678
Zheng Bao4b6aa192023-03-09 11:28:47 +08001679 do {
Zheng Baoe35c5022023-10-11 16:08:44 +08001680 if (cb_config.use_combo && cb_config.debug)
Zheng Bao3e7008d2023-03-15 16:15:13 +08001681 printf("Processing %dth combo entry\n", combo_index);
1682
Zheng Baoe4214b72024-03-13 22:51:24 +08001683 ctx.pspdir = NULL;
1684 ctx.pspdir2 = NULL;
1685 ctx.pspdir2_b = NULL;
1686 ctx.biosdir = NULL;
1687 ctx.biosdir2 = NULL;
1688 ctx.biosdir2_b = NULL;
1689 ctx.ish_a_dir = NULL;
1690 ctx.ish_b_dir = NULL;
Zheng Bao4b6aa192023-03-09 11:28:47 +08001691 /* for non-combo image, combo_config[0] == config, and
1692 * it already is processed. Actually "combo_index >
1693 * 0" is enough. Put both of them here to make sure
1694 * and make it clear this will not affect non-combo
1695 * case.
1696 */
1697 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08001698 /* Restore the table as clean data. */
1699 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
1700 sizeof(amd_psp_fw_table));
1701 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
1702 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08001703 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao18cf3f72024-03-09 12:38:16 +08001704 open_process_config(cb_config.combo_config[combo_index], &cb_config);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001705
Zheng Bao4b6aa192023-03-09 11:28:47 +08001706 /* In most cases, the address modes are same. */
1707 if (cb_config.need_ish)
1708 ctx.address_mode = AMD_ADDR_REL_TAB;
1709 else if (cb_config.second_gen)
1710 ctx.address_mode = AMD_ADDR_REL_BIOS;
1711 else
1712 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baofa259542021-10-26 19:46:55 +08001713
Zheng Baoe35c5022023-10-11 16:08:44 +08001714 register_apcb_combo(&cb_config, combo_index, &ctx);
Zheng Bao990d1542021-09-17 13:24:54 +08001715 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001716
Zheng Bao481661e2021-08-20 14:47:46 +08001717 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001718 /* Do 2nd PSP directory followed by 1st */
Zheng Baoeea834b2024-03-14 13:17:05 +08001719 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001720 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1721 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
1722 /* Create a copy of PSP Directory 2 in the backup slot B.
1723 Related biosdir2_b copy will be created later. */
Zheng Baoeea834b2024-03-14 13:17:05 +08001724 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001725 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
Zheng Bao990d1542021-09-17 13:24:54 +08001726 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001727 /*
1728 * Either the platform is using only
1729 * one slot or B is same as above
1730 * directories for A. Skip creating
1731 * pspdir2_b here to save flash space.
1732 * Related biosdir2_b will be skipped
1733 * automatically.
1734 */
Zheng Baoe4214b72024-03-13 22:51:24 +08001735 ctx.pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08001736 }
Zheng Baoeea834b2024-03-14 13:17:05 +08001737 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001738 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Zheng Baof3600952024-03-14 13:35:38 +08001739 integrate_psp_levels(&ctx, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001740 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001741 /* flat: PSP 1 cookie and no pointer to 2nd table */
Zheng Baoeea834b2024-03-14 13:17:05 +08001742 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001743 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001744 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001745
Zheng Bao4b6aa192023-03-09 11:28:47 +08001746 if (!cb_config.use_combo) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001747 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.pspdir, &ctx, &cb_config);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001748 } else {
Zheng Baoe4214b72024-03-13 22:51:24 +08001749 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.psp_combo_dir, &ctx, &cb_config);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001750 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
1751 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Baoe4214b72024-03-13 22:51:24 +08001752 ctx.psp_combo_dir->entries[combo_index].id_sel = 0;
1753 ctx.psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
1754 ctx.psp_combo_dir->entries[combo_index].lvl2_addr =
1755 BUFF_TO_RUN_MODE(ctx, ctx.pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001756
Zheng Baob81b7da2024-03-14 13:29:34 +08001757 fill_dir_header(ctx.psp_combo_dir, combo_index + 1, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001758 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08001759
1760 if (have_bios_tables(amd_bios_table)) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001761 if (cb_config.multi_level) {
1762 /* Do 2nd level BIOS directory followed by 1st */
Zheng Baoeea834b2024-03-14 13:17:05 +08001763 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001764 amd_bios_table, BHDL2_COOKIE, &cb_config);
1765 if (cb_config.recovery_ab) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001766 if (ctx.pspdir2_b != NULL) {
Zheng Baoeea834b2024-03-14 13:17:05 +08001767 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001768 amd_bios_table, BHDL2_COOKIE,
1769 &cb_config);
1770 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08001771 } else {
Zheng Baoeea834b2024-03-14 13:17:05 +08001772 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001773 amd_bios_table, BHD_COOKIE, &cb_config);
1774 }
Zheng Baoe80d0622024-03-16 17:12:30 +08001775 integrate_bios_levels(&ctx, &cb_config);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001776 } else {
1777 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Baoeea834b2024-03-14 13:17:05 +08001778 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001779 amd_bios_table, BHD_COOKIE, &cb_config);
1780 }
1781 if (!cb_config.use_combo) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001782 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.biosdir,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001783 &ctx, &cb_config);
Zheng Baoe4214b72024-03-13 22:51:24 +08001784 } else if (ctx.bhd_combo_dir != NULL) {
Zheng Baod22c2c82024-03-09 10:56:06 +08001785 /* In recovery A/B mode, there isn't a BHD combo directory.
1786 * Instead, the BIOS tables level 2 are linked by PSP tables.
1787 */
Zheng Baoe4214b72024-03-13 22:51:24 +08001788 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.bhd_combo_dir,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001789 &ctx, &cb_config);
1790 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Baoe4214b72024-03-13 22:51:24 +08001791 ctx.bhd_combo_dir->entries[combo_index].id_sel = 0;
1792 ctx.bhd_combo_dir->entries[combo_index].id =
Zheng Bao4b6aa192023-03-09 11:28:47 +08001793 get_psp_id(cb_config.soc_id);
Zheng Baoe4214b72024-03-13 22:51:24 +08001794 ctx.bhd_combo_dir->entries[combo_index].lvl2_addr =
1795 BUFF_TO_RUN_MODE(ctx, ctx.biosdir, AMD_ADDR_REL_BIOS);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001796
Zheng Baob81b7da2024-03-14 13:29:34 +08001797 fill_dir_header(ctx.bhd_combo_dir, combo_index + 1, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001798 }
1799 }
Zheng Baoe4214b72024-03-13 22:51:24 +08001800 if (cb_config.debug)
1801 dump_image_addresses(&ctx);
Zheng Bao17551ae2023-03-11 10:29:56 +08001802 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
Zheng Baoe35c5022023-10-11 16:08:44 +08001803 cb_config.combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001804
Zheng Baoe35c5022023-10-11 16:08:44 +08001805 targetfd = open(cb_config.output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07001806 if (targetfd >= 0) {
Zheng Baoe35c5022023-10-11 16:08:44 +08001807 uint32_t offset = cb_config.efs_location;
1808 uint32_t bytes = cb_config.efs_location == cb_config.body_location ?
Zheng Baoe4214b72024-03-13 22:51:24 +08001809 ctx.current - offset : sizeof(embedded_firmware);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001810 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001811
Zheng Baoc25d5932023-03-22 12:51:47 +08001812 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001813 if (bytes != ret_bytes) {
Zheng Baoe35c5022023-10-11 16:08:44 +08001814 fprintf(stderr, "Error: Writing to file %s failed\n", cb_config.output);
Zheng Bao47396912020-09-29 17:33:17 +08001815 retval = 1;
1816 }
Martin Roth31d95a22016-11-08 11:22:12 -07001817 close(targetfd);
1818 } else {
Zheng Baoe35c5022023-10-11 16:08:44 +08001819 fprintf(stderr, "Error: could not open file: %s\n", cb_config.output);
Martin Roth31d95a22016-11-08 11:22:12 -07001820 retval = 1;
1821 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001822
Zheng Baoe35c5022023-10-11 16:08:44 +08001823 if (cb_config.efs_location != cb_config.body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001824 ssize_t bytes;
1825
Zheng Baoe35c5022023-10-11 16:08:44 +08001826 bytes = write_body(cb_config.output, BUFF_OFFSET(ctx, cb_config.body_location),
1827 ctx.current - cb_config.body_location);
1828 if (bytes != ctx.current - cb_config.body_location) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001829 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001830 retval = 1;
1831 }
1832 }
1833
Zheng Baoe35c5022023-10-11 16:08:44 +08001834 if (cb_config.manifest_file) {
1835 dump_blob_version(cb_config.manifest_file, amd_psp_fw_table);
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001836 }
1837
Zheng Bao7c5ad882023-02-19 13:02:52 +08001838 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07001839 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001840}