blob: 72f0c5ff348d6ebb14fdbbda6f05f4e3315237d2 [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;
849 ctx->current_table = (char *)pspdir - ctx->rom;
850 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++;
880 pspdir->header.num_entries = count;
881 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 }
906 pspdir->header.num_entries = count;
907 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
908 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
909 if (pspdir2_b != NULL)
910 integrate_psp_ab(ctx, pspdir, pspdir2_b, ctx->ish_b_dir,
911 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
912 cb_config->soc_id);
913 else
914 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
915 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
916 cb_config->soc_id);
917
918 count = pspdir->header.num_entries;
919 } else if (pspdir2 != NULL) {
920 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
921 pspdir->entries[count].type = AMD_FW_L2_PTR;
922 pspdir->entries[count].subprog = 0;
923 pspdir->entries[count].rsvd = 0;
924 pspdir->entries[count].size = sizeof(pspdir2->header)
925 + pspdir2->header.num_entries
926 * sizeof(psp_directory_entry);
927
928 pspdir->entries[count].addr =
929 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
930 pspdir->entries[count].address_mode =
931 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
932 count++;
933 }
Zheng Baob81b7da2024-03-14 13:29:34 +0800934 fill_dir_header(pspdir, count, ctx);
Zheng Baof3600952024-03-14 13:35:38 +0800935 ctx->current_table = current_table_save;
936}
937
Marshall Dawson2794a862019-03-04 16:53:15 -0700938static void integrate_psp_firmwares(context *ctx,
Marshall Dawson24f73d42019-04-01 10:48:43 -0600939 amd_fw_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +0800940 uint32_t cookie,
941 amd_cb_config *cb_config)
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800942{
Richard Spiegel137484d2018-01-17 10:23:19 -0700943 ssize_t bytes;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700944 unsigned int i, count;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600945 int level;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530946 uint32_t size;
Zheng Baoeea834b2024-03-14 13:17:05 +0800947 psp_directory_table *pspdir;
Ritul Gurua2cb3402022-08-29 00:51:08 +0530948 uint64_t addr;
Zheng Bao6fff2492021-11-15 19:53:21 +0800949 uint32_t current_table_save;
Zheng Bao990d1542021-09-17 13:24:54 +0800950 bool recovery_ab = cb_config->recovery_ab;
Marshall Dawson24f73d42019-04-01 10:48:43 -0600951
952 /* This function can create a primary table, a secondary table, or a
953 * flattened table which contains all applicable types. These if-else
954 * statements infer what the caller intended. If a 2nd-level cookie
955 * is passed, clearly a 2nd-level table is intended. However, a
Zheng Baoe0793792024-03-13 23:35:29 +0800956 * 1st-level cookie may indicate level 1 or flattened.
Marshall Dawson24f73d42019-04-01 10:48:43 -0600957 */
Zheng Baob81b7da2024-03-14 13:29:34 +0800958 pspdir = new_psp_dir(ctx, cb_config->multi_level, cookie);
Zheng Baoeea834b2024-03-14 13:17:05 +0800959
960 if (cookie == PSP_COOKIE)
961 ctx->pspdir = pspdir;
962 else if (cookie == PSPL2_COOKIE) {
963 if (ctx->pspdir2 == NULL)
964 ctx->pspdir2 = pspdir;
965 else if (ctx->pspdir2_b == NULL)
966 ctx->pspdir2_b = pspdir;
967 }
968
Zheng Baoba3af5e2021-11-04 18:56:47 +0800969 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +0800970 level = PSP_BOTH;
971 else if (cookie == PSPL2_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600972 level = PSP_LVL2;
Zheng Baoe0793792024-03-13 23:35:29 +0800973 else if (cookie == PSP_COOKIE)
Marshall Dawson24f73d42019-04-01 10:48:43 -0600974 level = PSP_LVL1;
975 else
976 level = PSP_BOTH;
Marshall Dawson2794a862019-03-04 16:53:15 -0700977
Zheng Bao990d1542021-09-17 13:24:54 +0800978 if (recovery_ab) {
979 if (cookie == PSPL2_COOKIE)
980 level = PSP_LVL2_AB;
Zheng Baoe0793792024-03-13 23:35:29 +0800981 else if (cookie == PSP_COOKIE)
Zheng Bao990d1542021-09-17 13:24:54 +0800982 level = PSP_LVL1_AB;
983 else
984 level = PSP_BOTH_AB;
985 }
Zheng Bao6fff2492021-11-15 19:53:21 +0800986 current_table_save = ctx->current_table;
987 ctx->current_table = (char *)pspdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +0800988 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +0800989
Marshall Dawsonc38c0c92019-02-23 16:41:35 -0700990 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
Marshall Dawson24f73d42019-04-01 10:48:43 -0600991 if (!(fw_table[i].level & level))
992 continue;
993
Zheng Bao5164e4b2021-10-30 12:09:07 +0800994 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
995
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -0600996 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
997 if (!fw_table[i].other)
998 continue;
Zheng Baoc26108f2023-02-17 11:01:07 +0800999 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001000 pspdir->entries[count].type = fw_table[i].type;
1001 pspdir->entries[count].size = 4096; /* TODO: doc? */
1002 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001003 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001004 pspdir->entries[count].subprog = fw_table[i].subprog;
1005 pspdir->entries[count].rsvd = 0;
Zheng Baoc26108f2023-02-17 11:01:07 +08001006 adjust_current_pointer(ctx, 4096, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001007 count++;
1008 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
Marshall Dawson239286c2019-02-23 16:42:46 -07001009 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001010 pspdir->entries[count].subprog = fw_table[i].subprog;
1011 pspdir->entries[count].rsvd = 0;
Marshall Dawson239286c2019-02-23 16:42:46 -07001012 pspdir->entries[count].size = 0xFFFFFFFF;
Marshall Dawsonef79fcc2019-04-01 10:16:41 -06001013 pspdir->entries[count].addr = fw_table[i].other;
Zheng Bao6fff2492021-11-15 19:53:21 +08001014 pspdir->entries[count].address_mode = 0;
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001015 count++;
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001016 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301017 if (fw_table[i].filename == NULL) {
1018 if (fw_table[i].size == 0)
1019 continue;
1020 size = fw_table[i].size;
1021 addr = fw_table[i].dest;
Elyes Haouas7d67a192022-10-14 09:58:29 +02001022 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
Ritul Gurua2cb3402022-08-29 00:51:08 +05301023 fprintf(stderr,
1024 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001025 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301026 exit(1);
1027 }
1028 } else {
Zheng Baoc26108f2023-02-17 11:01:07 +08001029 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301030 bytes = copy_blob(BUFF_CURRENT(*ctx),
1031 fw_table[i].filename, BUFF_ROOM(*ctx));
1032 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001033 amdfwtool_cleanup(ctx);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301034 exit(1);
1035 }
1036
Elyes Haouas7d67a192022-10-14 09:58:29 +02001037 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
Ritul Gurua2cb3402022-08-29 00:51:08 +05301038 addr = RUN_CURRENT(*ctx);
Zheng Baoc26108f2023-02-17 11:01:07 +08001039 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001040 }
1041
1042 pspdir->entries[count].type = fw_table[i].type;
1043 pspdir->entries[count].subprog = fw_table[i].subprog;
1044 pspdir->entries[count].rsvd = 0;
Ritul Gurua2cb3402022-08-29 00:51:08 +05301045 pspdir->entries[count].size = size;
1046 pspdir->entries[count].addr = addr;
1047
Zheng Bao6fff2492021-11-15 19:53:21 +08001048 pspdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001049 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001050
Marshall Dawson7c1e1422019-04-11 09:44:43 -06001051 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001052 } else if (fw_table[i].filename != NULL) {
Kangheui Won3c164e12021-12-03 20:25:05 +11001053 if (fw_table[i].addr_signed) {
1054 pspdir->entries[count].addr =
1055 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1056 pspdir->entries[count].address_mode =
1057 SET_ADDR_MODE_BY_TABLE(pspdir);
1058 bytes = fw_table[i].file_size;
1059 } else {
1060 bytes = copy_blob(BUFF_CURRENT(*ctx),
1061 fw_table[i].filename, BUFF_ROOM(*ctx));
1062 if (bytes < 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001063 amdfwtool_cleanup(ctx);
Kangheui Won3c164e12021-12-03 20:25:05 +11001064 exit(1);
1065 }
1066 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1067 pspdir->entries[count].address_mode =
1068 SET_ADDR_MODE_BY_TABLE(pspdir);
Zheng Baoc26108f2023-02-17 11:01:07 +08001069 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001070 }
1071
Marshall Dawson239286c2019-02-23 16:42:46 -07001072 pspdir->entries[count].type = fw_table[i].type;
Marshall Dawsondbae6322019-03-04 10:31:03 -07001073 pspdir->entries[count].subprog = fw_table[i].subprog;
1074 pspdir->entries[count].rsvd = 0;
Fred Reitberger75191be2023-03-07 11:00:49 -05001075 pspdir->entries[count].inst = fw_table[i].inst;
Marshall Dawson8e0dca02019-02-27 18:40:49 -07001076 pspdir->entries[count].size = (uint32_t)bytes;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001077
Marshall Dawsonc38c0c92019-02-23 16:41:35 -07001078 count++;
zbaoc3a08a92016-03-02 14:47:27 +08001079 } else {
1080 /* This APU doesn't have this firmware. */
1081 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001082 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001083
Zheng Baob81b7da2024-03-14 13:29:34 +08001084 fill_dir_header(pspdir, count, ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001085 ctx->current_table = current_table_save;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001086}
1087
Zheng Bao990d1542021-09-17 13:24:54 +08001088static void add_psp_firmware_entry(context *ctx,
1089 psp_directory_table *pspdir,
1090 void *table, amd_fw_type type, uint32_t size)
1091{
1092 uint32_t count = pspdir->header.num_entries;
1093 uint32_t index;
1094 uint32_t current_table_save;
1095
1096 current_table_save = ctx->current_table;
1097 ctx->current_table = (char *)pspdir - ctx->rom;
1098
1099 /* If there is an entry of "type", replace it. */
1100 for (index = 0; index < count; index++) {
1101 if (pspdir->entries[index].type == (uint8_t)type)
1102 break;
1103 }
1104
1105 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1106 pspdir->entries[index].type = (uint8_t)type;
1107 pspdir->entries[index].subprog = 0;
1108 pspdir->entries[index].rsvd = 0;
1109 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1110 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1111 pspdir->entries[index].size = size;
1112 if (index == count)
1113 count++;
1114
Zheng Baob81b7da2024-03-14 13:29:34 +08001115 fill_dir_header(pspdir, count, ctx);
Zheng Bao990d1542021-09-17 13:24:54 +08001116 ctx->current_table = current_table_save;
1117}
1118
Zheng Baob81b7da2024-03-14 13:29:34 +08001119static void *new_bios_dir(context *ctx, bool multi, uint32_t cookie)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001120{
1121 void *ptr;
1122
1123 /*
1124 * Force both onto boundary when multi. Primary table is after
1125 * updatable table, so alignment ensures primary can stay intact
1126 * if secondary is reprogrammed.
1127 */
1128 if (multi)
Zheng Baoc26108f2023-02-17 11:01:07 +08001129 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001130 else
Zheng Baoc26108f2023-02-17 11:01:07 +08001131 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001132 ptr = BUFF_CURRENT(*ctx);
Zheng Baob81b7da2024-03-14 13:29:34 +08001133 ((bios_directory_hdr *) ptr)->cookie = cookie;
Zheng Bao6fff2492021-11-15 19:53:21 +08001134 ((bios_directory_hdr *) ptr)->additional_info = 0;
1135 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
Zheng Baoc26108f2023-02-17 11:01:07 +08001136 adjust_current_pointer(ctx,
1137 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1138 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001139 return ptr;
1140}
1141
1142static int locate_bdt2_bios(bios_directory_table *level2,
1143 uint64_t *source, uint32_t *size)
1144{
Zheng Bao6d402ac2020-10-01 16:16:30 +08001145 uint32_t i;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001146
1147 *source = 0;
1148 *size = 0;
1149 if (!level2)
1150 return 0;
1151
1152 for (i = 0 ; i < level2->header.num_entries ; i++) {
1153 if (level2->entries[i].type == AMD_BIOS_BIN) {
1154 *source = level2->entries[i].source;
1155 *size = level2->entries[i].size;
1156 return 1;
1157 }
1158 }
1159 return 0;
1160}
1161
1162static int have_bios_tables(amd_bios_entry *table)
1163{
1164 int i;
1165
1166 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1167 if (table[i].level & BDT_LVL1 && table[i].filename)
1168 return 1;
1169 }
1170 return 0;
1171}
1172
Zheng Baoe35c5022023-10-11 16:08:44 +08001173int find_bios_entry(amd_bios_type type)
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001174{
1175 int i;
1176
1177 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1178 if (amd_bios_table[i].type == type)
1179 return i;
1180 }
1181 return -1;
1182}
1183
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001184static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1185 int inst, uint32_t size, uint64_t source)
1186{
1187 int i;
1188
1189 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1190 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1191 amd_bios_table[i].inst == inst)
1192 break;
1193 }
1194
1195 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1196 return;
1197
1198 biosdir->entries[idx].type = amd_bios_table[i].type;
1199 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1200 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1201 amd_bios_table[i].dest : (uint64_t)-1;
1202 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1203 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1204 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1205 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1206 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1207 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1208 biosdir->entries[idx].size = size;
1209 biosdir->entries[idx].source = source;
1210 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1211}
1212
Zheng Baof3600952024-03-14 13:35:38 +08001213static void integrate_bios_levels(context *ctx)
1214{
1215 unsigned int count = ctx->biosdir->header.num_entries;
1216 uint32_t current_table_save;
1217
1218 current_table_save = ctx->current_table;
1219 ctx->current_table = (char *)ctx->biosdir - ctx->rom;
1220
1221 if (ctx->biosdir2) {
1222 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1223 ctx->biosdir->entries[count].type = AMD_BIOS_L2_PTR;
1224 ctx->biosdir->entries[count].region_type = 0;
1225 ctx->biosdir->entries[count].size =
1226 + MAX_BIOS_ENTRIES
1227 * sizeof(bios_directory_entry);
1228 ctx->biosdir->entries[count].source =
1229 BUFF_TO_RUN(*ctx, ctx->biosdir2);
1230 ctx->biosdir->entries[count].address_mode =
1231 SET_ADDR_MODE(ctx->biosdir, AMD_ADDR_REL_BIOS);
1232 ctx->biosdir->entries[count].subprog = 0;
1233 ctx->biosdir->entries[count].inst = 0;
1234 ctx->biosdir->entries[count].copy = 0;
1235 ctx->biosdir->entries[count].compressed = 0;
1236 ctx->biosdir->entries[count].dest = -1;
1237 ctx->biosdir->entries[count].reset = 0;
1238 ctx->biosdir->entries[count].ro = 0;
1239 count++;
1240 }
Zheng Baob81b7da2024-03-14 13:29:34 +08001241 fill_dir_header(ctx->biosdir, count, ctx);
Zheng Baof3600952024-03-14 13:35:38 +08001242 ctx->current_table = current_table_save;
1243}
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001244static void integrate_bios_firmwares(context *ctx,
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001245 amd_bios_entry *fw_table,
Zheng Bao20795892021-08-20 14:58:22 +08001246 uint32_t cookie,
1247 amd_cb_config *cb_config)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001248{
1249 ssize_t bytes;
Martin Rothec933132019-07-13 20:03:34 -06001250 unsigned int i, count;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001251 int level;
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001252 int apob_idx;
Martin Rotheca423b2020-09-01 10:54:11 -06001253 uint32_t size;
1254 uint64_t source;
Zheng Baoa640b122023-10-09 17:36:08 +08001255 uint32_t current_table_save;
Zheng Baoeea834b2024-03-14 13:17:05 +08001256 bios_directory_table *biosdir;
1257
Zheng Baob81b7da2024-03-14 13:29:34 +08001258 biosdir = new_bios_dir(ctx, cb_config->multi_level, cookie);
Zheng Baoeea834b2024-03-14 13:17:05 +08001259
1260 if (cookie == BHD_COOKIE)
1261 ctx->biosdir = biosdir;
1262 else if (cookie == BHDL2_COOKIE) {
1263 if (ctx->biosdir2 == NULL)
1264 ctx->biosdir2 = biosdir;
1265 else if (ctx->biosdir2_b == NULL)
1266 ctx->biosdir2_b = biosdir;
1267 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001268
1269 /* This function can create a primary table, a secondary table, or a
1270 * flattened table which contains all applicable types. These if-else
1271 * statements infer what the caller intended. If a 2nd-level cookie
1272 * is passed, clearly a 2nd-level table is intended. However, a
Zheng Baoe0793792024-03-13 23:35:29 +08001273 * 1st-level cookie may indicate level 1 or flattened.
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001274 */
Zheng Baoba3af5e2021-11-04 18:56:47 +08001275 if (!cb_config->multi_level)
Zheng Bao20795892021-08-20 14:58:22 +08001276 level = BDT_BOTH;
Zheng Bao96a33712021-06-11 15:54:40 +08001277 else if (cookie == BHDL2_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001278 level = BDT_LVL2;
Zheng Baoe0793792024-03-13 23:35:29 +08001279 else if (cookie == BHD_COOKIE)
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001280 level = BDT_LVL1;
1281 else
1282 level = BDT_BOTH;
1283
Zheng Baoa640b122023-10-09 17:36:08 +08001284 current_table_save = ctx->current_table;
1285 ctx->current_table = (char *)biosdir - ctx->rom;
Zheng Baoc26108f2023-02-17 11:01:07 +08001286 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001287
1288 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1289 if (!(fw_table[i].level & level))
1290 continue;
1291 if (fw_table[i].filename == NULL && (
Ritul Guru9a321f32022-07-29 11:06:40 +05301292 fw_table[i].type != AMD_BIOS_SIG &&
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001293 fw_table[i].type != AMD_BIOS_APOB &&
1294 fw_table[i].type != AMD_BIOS_APOB_NV &&
1295 fw_table[i].type != AMD_BIOS_L2_PTR &&
Martin Roth94554742020-04-14 14:59:36 -06001296 fw_table[i].type != AMD_BIOS_BIN &&
1297 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001298 continue;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001299
1300 /* BIOS Directory items may have additional requirements */
1301
Ritul Guru9a321f32022-07-29 11:06:40 +05301302 /* SIG needs a size, else no choice but to skip */
1303 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1304 continue;
1305
Martin Roth48dd9fe2020-07-29 16:32:25 -06001306 /* Check APOB_NV requirements */
1307 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1308 if (!fw_table[i].size && !fw_table[i].src)
1309 continue; /* APOB_NV not used */
1310 if (fw_table[i].src && !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001311 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001312 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001313 exit(1);
1314 }
Martin Roth48dd9fe2020-07-29 16:32:25 -06001315 /* If the APOB isn't used, APOB_NV isn't used either */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001316 apob_idx = find_bios_entry(AMD_BIOS_APOB);
Martin Roth48dd9fe2020-07-29 16:32:25 -06001317 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1318 continue; /* APOV NV not supported */
Marshall Dawsonc4a8c482020-01-21 17:17:59 -07001319 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001320
1321 /* APOB_DATA needs destination */
1322 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001323 fprintf(stderr, "Error: APOB destination not provided\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001324 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001325 exit(1);
1326 }
1327
1328 /* BIOS binary must have destination and uncompressed size. If
1329 * no filename given, then user must provide a source address.
1330 */
1331 if (fw_table[i].type == AMD_BIOS_BIN) {
1332 if (!fw_table[i].dest || !fw_table[i].size) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001333 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001334 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001335 exit(1);
1336 }
1337 if (!fw_table[i].filename && !fw_table[i].src) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001338 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
Zheng Bao7c5ad882023-02-19 13:02:52 +08001339 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001340 exit(1);
1341 }
1342 }
1343
Martin Roth94554742020-04-14 14:59:36 -06001344 /* PSP_SHARED_MEM needs a destination and size */
1345 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1346 (!fw_table[i].dest || !fw_table[i].size))
1347 continue;
Zheng Bao5164e4b2021-10-30 12:09:07 +08001348 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
Martin Roth94554742020-04-14 14:59:36 -06001349
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001350 biosdir->entries[count].type = fw_table[i].type;
1351 biosdir->entries[count].region_type = fw_table[i].region_type;
1352 biosdir->entries[count].dest = fw_table[i].dest ?
1353 fw_table[i].dest : (uint64_t)-1;
1354 biosdir->entries[count].reset = fw_table[i].reset;
1355 biosdir->entries[count].copy = fw_table[i].copy;
1356 biosdir->entries[count].ro = fw_table[i].ro;
1357 biosdir->entries[count].compressed = fw_table[i].zlib;
1358 biosdir->entries[count].inst = fw_table[i].inst;
1359 biosdir->entries[count].subprog = fw_table[i].subpr;
1360
1361 switch (fw_table[i].type) {
Ritul Guru9a321f32022-07-29 11:06:40 +05301362 case AMD_BIOS_SIG:
1363 /* Reserve size bytes within amdfw.rom */
1364 biosdir->entries[count].size = fw_table[i].size;
1365 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1366 biosdir->entries[count].address_mode =
1367 SET_ADDR_MODE_BY_TABLE(biosdir);
1368 memset(BUFF_CURRENT(*ctx), 0xff,
1369 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001370 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
Ritul Guru9a321f32022-07-29 11:06:40 +05301371 break;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001372 case AMD_BIOS_APOB:
1373 biosdir->entries[count].size = fw_table[i].size;
1374 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001375 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001376 break;
1377 case AMD_BIOS_APOB_NV:
1378 if (fw_table[i].src) {
1379 /* If source is given, use that and its size */
1380 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001381 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001382 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001383 biosdir->entries[count].size = fw_table[i].size;
1384 } else {
1385 /* Else reserve size bytes within amdfw.rom */
Zheng Baoc26108f2023-02-17 11:01:07 +08001386 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001387 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001388 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001389 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Elyes Haouas7d67a192022-10-14 09:58:29 +02001390 biosdir->entries[count].size = ALIGN_UP(
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001391 fw_table[i].size, ERASE_ALIGNMENT);
1392 memset(BUFF_CURRENT(*ctx), 0xff,
1393 biosdir->entries[count].size);
Zheng Baoc26108f2023-02-17 11:01:07 +08001394 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001395 }
1396 break;
1397 case AMD_BIOS_BIN:
1398 /* Don't make a 2nd copy, point to the same one */
Zheng Baoeea834b2024-03-14 13:17:05 +08001399 if (level == BDT_LVL1 && locate_bdt2_bios(ctx->biosdir2, &source, &size)) {
Martin Rotheca423b2020-09-01 10:54:11 -06001400 biosdir->entries[count].source = source;
Zheng Bao6fff2492021-11-15 19:53:21 +08001401 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001402 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Martin Rotheca423b2020-09-01 10:54:11 -06001403 biosdir->entries[count].size = size;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001404 break;
Martin Rotheca423b2020-09-01 10:54:11 -06001405 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001406
1407 /* level 2, or level 1 and no copy found in level 2 */
1408 biosdir->entries[count].source = fw_table[i].src;
Zheng Bao6fff2492021-11-15 19:53:21 +08001409 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001410 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001411 biosdir->entries[count].dest = fw_table[i].dest;
1412 biosdir->entries[count].size = fw_table[i].size;
1413
1414 if (!fw_table[i].filename)
1415 break;
1416
1417 bytes = copy_blob(BUFF_CURRENT(*ctx),
1418 fw_table[i].filename, BUFF_ROOM(*ctx));
1419 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001420 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001421 exit(1);
1422 }
1423
Zheng Bao6fff2492021-11-15 19:53:21 +08001424 biosdir->entries[count].source =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001425 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
Zheng Bao6fff2492021-11-15 19:53:21 +08001426 biosdir->entries[count].address_mode =
Robert Zieba29bc79f2022-03-14 15:59:12 -06001427 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001428
Zheng Baoc26108f2023-02-17 11:01:07 +08001429 adjust_current_pointer(ctx, bytes, 0x100U);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001430 break;
Martin Roth94554742020-04-14 14:59:36 -06001431 case AMD_BIOS_PSP_SHARED_MEM:
1432 biosdir->entries[count].dest = fw_table[i].dest;
1433 biosdir->entries[count].size = fw_table[i].size;
1434 break;
1435
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001436 default: /* everything else is copied from input */
1437 if (fw_table[i].type == AMD_BIOS_APCB ||
1438 fw_table[i].type == AMD_BIOS_APCB_BK)
Zheng Baoc26108f2023-02-17 11:01:07 +08001439 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001440 bytes = copy_blob(BUFF_CURRENT(*ctx),
1441 fw_table[i].filename, BUFF_ROOM(*ctx));
1442 if (bytes <= 0) {
Zheng Bao7c5ad882023-02-19 13:02:52 +08001443 amdfwtool_cleanup(ctx);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001444 exit(1);
1445 }
1446
1447 biosdir->entries[count].size = (uint32_t)bytes;
1448 biosdir->entries[count].source = RUN_CURRENT(*ctx);
Zheng Bao6fff2492021-11-15 19:53:21 +08001449 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001450
Zheng Baoc26108f2023-02-17 11:01:07 +08001451 adjust_current_pointer(ctx, bytes, 0x100U);
Karthikeyan Ramasubramanian8d885612023-03-09 17:39:31 -07001452 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1453 size = biosdir->entries[count].size;
1454 source = biosdir->entries[count].source;
1455 count++;
1456 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1457 }
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001458 break;
1459 }
1460
1461 count++;
1462 }
1463
Zheng Baob81b7da2024-03-14 13:29:34 +08001464 fill_dir_header(biosdir, count, ctx);
Zheng Baoa640b122023-10-09 17:36:08 +08001465 ctx->current_table = current_table_save;
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001466}
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001467
Zheng Baoc3007f32022-04-03 12:53:51 +08001468static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
Zheng Baoe35c5022023-10-11 16:08:44 +08001469 embedded_firmware *amd_romsig)
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001470{
Zheng Baoe35c5022023-10-11 16:08:44 +08001471 if ((cb_config->efs_spi_readmode == 0xFF) || (cb_config->efs_spi_speed == 0xFF)) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001472 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001473 return 1;
1474 }
Zheng Baoc3007f32022-04-03 12:53:51 +08001475
1476 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1477 * Leave as 0xffffffff for first gen */
1478 if (cb_config->second_gen) {
1479 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1480 amd_romsig->efs_gen.reserved = 0;
1481 } else {
Zheng Bao487d0452022-04-03 12:50:07 +08001482 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1483 amd_romsig->efs_gen.reserved = ~0;
Zheng Baoc3007f32022-04-03 12:53:51 +08001484 }
1485
1486 switch (soc_id) {
Zheng Bao3d7623f2022-08-17 11:52:30 +08001487 case PLATFORM_CARRIZO:
Zheng Baoc3007f32022-04-03 12:53:51 +08001488 case PLATFORM_STONEYRIDGE:
Zheng Baoe35c5022023-10-11 16:08:44 +08001489 amd_romsig->spi_readmode_f15_mod_60_6f = cb_config->efs_spi_readmode;
1490 amd_romsig->fast_speed_new_f15_mod_60_6f = cb_config->efs_spi_speed;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001491 break;
1492 case PLATFORM_RAVEN:
1493 case PLATFORM_PICASSO:
Zheng Baoe35c5022023-10-11 16:08:44 +08001494 amd_romsig->spi_readmode_f17_mod_00_2f = cb_config->efs_spi_readmode;
1495 amd_romsig->spi_fastspeed_f17_mod_00_2f = cb_config->efs_spi_speed;
1496 switch (cb_config->efs_spi_micron_flag) {
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001497 case 0:
1498 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1499 break;
1500 case 1:
1501 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1502 break;
1503 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001504 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001505 return 1;
1506 }
1507 break;
1508 case PLATFORM_RENOIR:
1509 case PLATFORM_LUCIENNE:
Zheng Baobf29a0d2020-12-03 23:00:48 +08001510 case PLATFORM_CEZANNE:
Zheng Bao535ec532021-08-12 16:30:19 +08001511 case PLATFORM_MENDOCINO:
Zheng Baode6f1982022-10-16 20:32:43 +08001512 case PLATFORM_PHOENIX:
1513 case PLATFORM_GLINDA:
Arthur Heymans563f7af2023-07-13 11:40:08 +02001514 case PLATFORM_GENOA:
Zheng Baoe35c5022023-10-11 16:08:44 +08001515 amd_romsig->spi_readmode_f17_mod_30_3f = cb_config->efs_spi_readmode;
1516 amd_romsig->spi_fastspeed_f17_mod_30_3f = cb_config->efs_spi_speed;
1517 switch (cb_config->efs_spi_micron_flag) {
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001518 case 0:
1519 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1520 break;
1521 case 1:
1522 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1523 break;
1524 case 2:
1525 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1526 break;
1527 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001528 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001529 return 1;
1530 }
1531 break;
1532 case PLATFORM_UNKNOWN:
1533 default:
Zheng Bao77a2c672020-10-01 17:05:43 +08001534 fprintf(stderr, "Error: Invalid SOC name.\n\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001535 return 1;
1536 }
1537 return 0;
1538}
1539
Zheng Bao18cf3f72024-03-09 12:38:16 +08001540void open_process_config(char *config, amd_cb_config *cb_config)
Zheng Bao39cae562023-03-07 18:37:43 +08001541{
1542 FILE *config_handle;
1543
1544 if (config) {
1545 config_handle = fopen(config, "r");
1546 if (config_handle == NULL) {
1547 fprintf(stderr, "Can not open file %s for reading: %s\n",
1548 config, strerror(errno));
1549 exit(1);
1550 }
Zheng Bao994ff522023-03-09 11:43:55 +08001551 if (process_config(config_handle, cb_config) == 0) {
Zheng Bao39cae562023-03-07 18:37:43 +08001552 fprintf(stderr, "Configuration file %s parsing error\n",
1553 config);
1554 fclose(config_handle);
1555 exit(1);
1556 }
1557 fclose(config_handle);
1558 }
1559
1560 /* For debug. */
Zheng Bao18cf3f72024-03-09 12:38:16 +08001561 if (cb_config->debug) {
Zheng Bao39cae562023-03-07 18:37:43 +08001562 dump_psp_firmwares(amd_psp_fw_table);
1563 dump_bdt_firmwares(amd_bios_table);
1564 }
1565}
1566
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001567static bool is_initial_alignment_required(enum platform soc_id)
1568{
1569 switch (soc_id) {
1570 case PLATFORM_MENDOCINO:
1571 case PLATFORM_PHOENIX:
1572 case PLATFORM_GLINDA:
1573 return false;
1574 default:
1575 return true;
1576 }
1577}
1578
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001579int main(int argc, char **argv)
1580{
Martin Roth31d95a22016-11-08 11:22:12 -07001581 int retval = 0;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001582 int combo_index = 0;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001583 int targetfd;
Zheng Bao9c8ce3e2020-09-28 10:36:29 +08001584 context ctx = { 0 };
Martin Roth0d3b1182017-10-03 14:16:04 -06001585 uint32_t romsig_offset;
Zheng Baoe35c5022023-10-11 16:08:44 +08001586 amd_cb_config cb_config = {
1587 .efs_spi_readmode = 0xff, .efs_spi_speed = 0xff, .efs_spi_micron_flag = 0xff
1588 };
Zheng Baoc5e28ab2020-10-28 11:38:09 +08001589
Zheng Baoc26108f2023-02-17 11:01:07 +08001590 ctx.current_pointer_saved = 0xFFFFFFFF;
1591
Zheng Baoe35c5022023-10-11 16:08:44 +08001592 retval = amdfwtool_getopt(argc, argv, &cb_config, &ctx);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001593
Zheng Baoe35c5022023-10-11 16:08:44 +08001594 if (retval) {
1595 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001596 }
1597
Zheng Bao8dd34bd2023-03-09 21:09:58 +08001598 if (cb_config.use_combo) {
1599 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
1600 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
1601 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
1602 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
1603 }
1604
Zheng Bao18cf3f72024-03-09 12:38:16 +08001605 open_process_config(cb_config.config, &cb_config);
Zheng Bao9e908072020-10-28 11:39:13 +08001606
Marshall Dawson2794a862019-03-04 16:53:15 -07001607 ctx.rom = malloc(ctx.rom_size);
1608 if (!ctx.rom) {
Zheng Bao77a2c672020-10-01 17:05:43 +08001609 fprintf(stderr, "Error: Failed to allocate memory\n");
Martin Roth31d95a22016-11-08 11:22:12 -07001610 return 1;
Marshall Dawson2794a862019-03-04 16:53:15 -07001611 }
1612 memset(ctx.rom, 0xFF, ctx.rom_size);
Martin Roth60f15512016-11-08 09:55:01 -07001613
Zheng Baoe35c5022023-10-11 16:08:44 +08001614 romsig_offset = cb_config.efs_location ? cb_config.efs_location : AMD_ROMSIG_OFFSET;
Zheng Bao6095cd12023-02-21 10:52:47 +08001615 set_current_pointer(&ctx, romsig_offset);
Martin Roth0d3b1182017-10-03 14:16:04 -06001616
Zheng Baoe4214b72024-03-13 22:51:24 +08001617 ctx.amd_romsig_ptr = BUFF_OFFSET(ctx, romsig_offset);
1618 ctx.amd_romsig_ptr->signature = EMBEDDED_FW_SIGNATURE;
1619 ctx.amd_romsig_ptr->imc_entry = 0;
1620 ctx.amd_romsig_ptr->gec_entry = 0;
1621 ctx.amd_romsig_ptr->xhci_entry = 0;
Martin Roth60f15512016-11-08 09:55:01 -07001622
Zheng Bao4bf6f492023-01-25 22:37:29 +08001623 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001624 retval = set_efs_table(cb_config.soc_id, &cb_config, ctx.amd_romsig_ptr);
Zheng Bao570645d2021-11-03 10:25:03 +08001625 if (retval) {
1626 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
1627 return retval;
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001628 }
1629 } else {
Zheng Bao77a2c672020-10-01 17:05:43 +08001630 fprintf(stderr, "WARNING: No SOC name specified.\n");
Matt Papageorgebe4376c2020-06-15 11:18:15 -05001631 }
1632
Felix Held21a8e382022-03-29 23:10:45 +02001633 if (cb_config.need_ish)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001634 ctx.address_mode = AMD_ADDR_REL_TAB;
Zheng Baoc3007f32022-04-03 12:53:51 +08001635 else if (cb_config.second_gen)
Robert Zieba29bc79f2022-03-14 15:59:12 -06001636 ctx.address_mode = AMD_ADDR_REL_BIOS;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001637 else
Robert Zieba29bc79f2022-03-14 15:59:12 -06001638 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baoda83d2c2021-06-04 19:03:10 +08001639
Zheng Baoe35c5022023-10-11 16:08:44 +08001640 if (cb_config.efs_location != cb_config.body_location)
1641 set_current_pointer(&ctx, cb_config.body_location);
Zheng Bao6095cd12023-02-21 10:52:47 +08001642 else
1643 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
1644
Zheng Baoe4214b72024-03-13 22:51:24 +08001645 integrate_firmwares(&ctx, ctx.amd_romsig_ptr, amd_fw_table);
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001646
Karthikeyan Ramasubramanian225b4b32023-03-08 10:24:50 -07001647 if (is_initial_alignment_required(cb_config.soc_id)) {
1648 /* TODO: Check for older platforms. */
1649 adjust_current_pointer(&ctx, 0, 0x10000U);
1650 }
Zheng Bao6fff2492021-11-15 19:53:21 +08001651 ctx.current_table = 0;
Marshall Dawson2794a862019-03-04 16:53:15 -07001652
Kangheui Won3c164e12021-12-03 20:25:05 +11001653 /* If the tool is invoked with command-line options to keep the signed PSP
1654 binaries separate, process the signed binaries first. */
Zheng Baoe35c5022023-10-11 16:08:44 +08001655 if (cb_config.signed_output_file && cb_config.signed_start_addr)
1656 process_signed_psp_firmwares(cb_config.signed_output_file,
Kangheui Won3c164e12021-12-03 20:25:05 +11001657 amd_psp_fw_table,
Zheng Baoe35c5022023-10-11 16:08:44 +08001658 cb_config.signed_start_addr,
Zheng Bao4bf6f492023-01-25 22:37:29 +08001659 cb_config.soc_id);
Kangheui Won3c164e12021-12-03 20:25:05 +11001660
Zheng Baob2ae6a52022-08-18 15:45:27 +08001661 if (cb_config.use_combo) {
Zheng Baob81b7da2024-03-14 13:29:34 +08001662 ctx.psp_combo_dir = new_combo_dir(&ctx, PSP2_COOKIE);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001663
1664 adjust_current_pointer(&ctx, 0, 0x1000U);
1665
Zheng Baod22c2c82024-03-09 10:56:06 +08001666 if (!cb_config.recovery_ab)
Zheng Baob81b7da2024-03-14 13:29:34 +08001667 ctx.bhd_combo_dir = new_combo_dir(&ctx, BHD2_COOKIE);
Zheng Baob2ae6a52022-08-18 15:45:27 +08001668 }
1669
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001670 combo_index = 0;
Zheng Baoe35c5022023-10-11 16:08:44 +08001671 if (cb_config.config)
1672 cb_config.combo_config[0] = cb_config.config;
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001673
Zheng Bao4b6aa192023-03-09 11:28:47 +08001674 do {
Zheng Baoe35c5022023-10-11 16:08:44 +08001675 if (cb_config.use_combo && cb_config.debug)
Zheng Bao3e7008d2023-03-15 16:15:13 +08001676 printf("Processing %dth combo entry\n", combo_index);
1677
Zheng Baoe4214b72024-03-13 22:51:24 +08001678 ctx.pspdir = NULL;
1679 ctx.pspdir2 = NULL;
1680 ctx.pspdir2_b = NULL;
1681 ctx.biosdir = NULL;
1682 ctx.biosdir2 = NULL;
1683 ctx.biosdir2_b = NULL;
1684 ctx.ish_a_dir = NULL;
1685 ctx.ish_b_dir = NULL;
Zheng Bao4b6aa192023-03-09 11:28:47 +08001686 /* for non-combo image, combo_config[0] == config, and
1687 * it already is processed. Actually "combo_index >
1688 * 0" is enough. Put both of them here to make sure
1689 * and make it clear this will not affect non-combo
1690 * case.
1691 */
1692 if (cb_config.use_combo && combo_index > 0) {
Zheng Bao8dd34bd2023-03-09 21:09:58 +08001693 /* Restore the table as clean data. */
1694 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
1695 sizeof(amd_psp_fw_table));
1696 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
1697 sizeof(amd_bios_table));
Zheng Bao73917222023-03-15 16:14:03 +08001698 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Bao18cf3f72024-03-09 12:38:16 +08001699 open_process_config(cb_config.combo_config[combo_index], &cb_config);
Zheng Bao0e3d18b2023-03-07 15:28:57 +08001700
Zheng Bao4b6aa192023-03-09 11:28:47 +08001701 /* In most cases, the address modes are same. */
1702 if (cb_config.need_ish)
1703 ctx.address_mode = AMD_ADDR_REL_TAB;
1704 else if (cb_config.second_gen)
1705 ctx.address_mode = AMD_ADDR_REL_BIOS;
1706 else
1707 ctx.address_mode = AMD_ADDR_PHYSICAL;
Zheng Baofa259542021-10-26 19:46:55 +08001708
Zheng Baoe35c5022023-10-11 16:08:44 +08001709 register_apcb_combo(&cb_config, combo_index, &ctx);
Zheng Bao990d1542021-09-17 13:24:54 +08001710 }
Marshall Dawson2794a862019-03-04 16:53:15 -07001711
Zheng Bao481661e2021-08-20 14:47:46 +08001712 if (cb_config.multi_level) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001713 /* Do 2nd PSP directory followed by 1st */
Zheng Baoeea834b2024-03-14 13:17:05 +08001714 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001715 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1716 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
1717 /* Create a copy of PSP Directory 2 in the backup slot B.
1718 Related biosdir2_b copy will be created later. */
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);
Zheng Bao990d1542021-09-17 13:24:54 +08001721 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001722 /*
1723 * Either the platform is using only
1724 * one slot or B is same as above
1725 * directories for A. Skip creating
1726 * pspdir2_b here to save flash space.
1727 * Related biosdir2_b will be skipped
1728 * automatically.
1729 */
Zheng Baoe4214b72024-03-13 22:51:24 +08001730 ctx.pspdir2_b = NULL; /* More explicitly */
Zheng Bao990d1542021-09-17 13:24:54 +08001731 }
Zheng Baoeea834b2024-03-14 13:17:05 +08001732 integrate_psp_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001733 amd_psp_fw_table, PSP_COOKIE, &cb_config);
Zheng Baof3600952024-03-14 13:35:38 +08001734 integrate_psp_levels(&ctx, &cb_config);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001735 } else {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001736 /* flat: PSP 1 cookie and no pointer to 2nd table */
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);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001739 }
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001740
Zheng Bao4b6aa192023-03-09 11:28:47 +08001741 if (!cb_config.use_combo) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001742 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.pspdir, &ctx, &cb_config);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001743 } else {
Zheng Baoe4214b72024-03-13 22:51:24 +08001744 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.psp_combo_dir, &ctx, &cb_config);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001745 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
1746 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Baoe4214b72024-03-13 22:51:24 +08001747 ctx.psp_combo_dir->entries[combo_index].id_sel = 0;
1748 ctx.psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
1749 ctx.psp_combo_dir->entries[combo_index].lvl2_addr =
1750 BUFF_TO_RUN_MODE(ctx, ctx.pspdir, AMD_ADDR_REL_BIOS);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001751
Zheng Baob81b7da2024-03-14 13:29:34 +08001752 fill_dir_header(ctx.psp_combo_dir, combo_index + 1, &ctx);
Zheng Bao84fb9ea2022-08-18 15:54:47 +08001753 }
Zheng Bao4b6aa192023-03-09 11:28:47 +08001754
1755 if (have_bios_tables(amd_bios_table)) {
Zheng Bao4b6aa192023-03-09 11:28:47 +08001756 if (cb_config.multi_level) {
1757 /* Do 2nd level BIOS directory followed by 1st */
Zheng Baoeea834b2024-03-14 13:17:05 +08001758 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001759 amd_bios_table, BHDL2_COOKIE, &cb_config);
1760 if (cb_config.recovery_ab) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001761 if (ctx.pspdir2_b != NULL) {
Zheng Baoeea834b2024-03-14 13:17:05 +08001762 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001763 amd_bios_table, BHDL2_COOKIE,
1764 &cb_config);
1765 }
Zheng Baoe4214b72024-03-13 22:51:24 +08001766 add_psp_firmware_entry(&ctx, ctx.pspdir2, ctx.biosdir2,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001767 AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
Zheng Baoe4214b72024-03-13 22:51:24 +08001768 if (ctx.pspdir2_b != NULL)
1769 add_psp_firmware_entry(&ctx, ctx.pspdir2_b,
1770 ctx.biosdir2_b, AMD_FW_BIOS_TABLE,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001771 TABLE_ALIGNMENT);
1772 } else {
Zheng Baoeea834b2024-03-14 13:17:05 +08001773 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001774 amd_bios_table, BHD_COOKIE, &cb_config);
Zheng Baof3600952024-03-14 13:35:38 +08001775 integrate_bios_levels(&ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001776 }
1777 } else {
1778 /* flat: BHD1 cookie and no pointer to 2nd table */
Zheng Baoeea834b2024-03-14 13:17:05 +08001779 integrate_bios_firmwares(&ctx,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001780 amd_bios_table, BHD_COOKIE, &cb_config);
1781 }
1782 if (!cb_config.use_combo) {
Zheng Baoe4214b72024-03-13 22:51:24 +08001783 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.biosdir,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001784 &ctx, &cb_config);
Zheng Baoe4214b72024-03-13 22:51:24 +08001785 } else if (ctx.bhd_combo_dir != NULL) {
Zheng Baod22c2c82024-03-09 10:56:06 +08001786 /* In recovery A/B mode, there isn't a BHD combo directory.
1787 * Instead, the BIOS tables level 2 are linked by PSP tables.
1788 */
Zheng Baoe4214b72024-03-13 22:51:24 +08001789 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.bhd_combo_dir,
Zheng Bao4b6aa192023-03-09 11:28:47 +08001790 &ctx, &cb_config);
1791 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
Zheng Baoe4214b72024-03-13 22:51:24 +08001792 ctx.bhd_combo_dir->entries[combo_index].id_sel = 0;
1793 ctx.bhd_combo_dir->entries[combo_index].id =
Zheng Bao4b6aa192023-03-09 11:28:47 +08001794 get_psp_id(cb_config.soc_id);
Zheng Baoe4214b72024-03-13 22:51:24 +08001795 ctx.bhd_combo_dir->entries[combo_index].lvl2_addr =
1796 BUFF_TO_RUN_MODE(ctx, ctx.biosdir, AMD_ADDR_REL_BIOS);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001797
Zheng Baob81b7da2024-03-14 13:29:34 +08001798 fill_dir_header(ctx.bhd_combo_dir, combo_index + 1, &ctx);
Zheng Bao4b6aa192023-03-09 11:28:47 +08001799 }
1800 }
Zheng Baoe4214b72024-03-13 22:51:24 +08001801 if (cb_config.debug)
1802 dump_image_addresses(&ctx);
Zheng Bao17551ae2023-03-11 10:29:56 +08001803 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
Zheng Baoe35c5022023-10-11 16:08:44 +08001804 cb_config.combo_config[combo_index] != NULL);
Marshall Dawsonce2b2ba2019-03-19 14:45:31 -06001805
Zheng Baoe35c5022023-10-11 16:08:44 +08001806 targetfd = open(cb_config.output, O_RDWR | O_CREAT | O_TRUNC, 0666);
Martin Roth31d95a22016-11-08 11:22:12 -07001807 if (targetfd >= 0) {
Zheng Baoe35c5022023-10-11 16:08:44 +08001808 uint32_t offset = cb_config.efs_location;
1809 uint32_t bytes = cb_config.efs_location == cb_config.body_location ?
Zheng Baoe4214b72024-03-13 22:51:24 +08001810 ctx.current - offset : sizeof(embedded_firmware);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001811 uint32_t ret_bytes;
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001812
Zheng Baoc25d5932023-03-22 12:51:47 +08001813 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
Zheng Bao69ea83c2023-01-22 21:08:18 +08001814 if (bytes != ret_bytes) {
Zheng Baoe35c5022023-10-11 16:08:44 +08001815 fprintf(stderr, "Error: Writing to file %s failed\n", cb_config.output);
Zheng Bao47396912020-09-29 17:33:17 +08001816 retval = 1;
1817 }
Martin Roth31d95a22016-11-08 11:22:12 -07001818 close(targetfd);
1819 } else {
Zheng Baoe35c5022023-10-11 16:08:44 +08001820 fprintf(stderr, "Error: could not open file: %s\n", cb_config.output);
Martin Roth31d95a22016-11-08 11:22:12 -07001821 retval = 1;
1822 }
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001823
Zheng Baoe35c5022023-10-11 16:08:44 +08001824 if (cb_config.efs_location != cb_config.body_location) {
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001825 ssize_t bytes;
1826
Zheng Baoe35c5022023-10-11 16:08:44 +08001827 bytes = write_body(cb_config.output, BUFF_OFFSET(ctx, cb_config.body_location),
1828 ctx.current - cb_config.body_location);
1829 if (bytes != ctx.current - cb_config.body_location) {
Zheng Bao69ea83c2023-01-22 21:08:18 +08001830 fprintf(stderr, "Error: Writing body\n");
Karthikeyan Ramasubramanianecb4e312022-11-02 16:53:54 -06001831 retval = 1;
1832 }
1833 }
1834
Zheng Baoe35c5022023-10-11 16:08:44 +08001835 if (cb_config.manifest_file) {
1836 dump_blob_version(cb_config.manifest_file, amd_psp_fw_table);
Grzegorz Bernackidfdf81c2023-04-05 09:35:42 +00001837 }
1838
Zheng Bao7c5ad882023-02-19 13:02:52 +08001839 amdfwtool_cleanup(&ctx);
Martin Roth31d95a22016-11-08 11:22:12 -07001840 return retval;
Zheng Bao9c7ff7b2015-11-17 22:57:39 +08001841}