acpi: Add IORT helper functions
[coreboot2.git] / util / amdfwtool / amdfwtool.c
blob7f17b71361751941d3aa9d4d361809962757ca8d
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /*
4 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
5 * 0 4 8 C
6 * +------------+---------------+----------------+------------+
7 * | 0x55AA55AA |EC ROM Address |GEC ROM Address |USB3 ROM |
8 * +------------+---------------+----------------+------------+
9 * | 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
15 * EC ROM should be 64K aligned.
17 * PSP directory (Where "PSPDIR ADDR" points)
18 * +------------+---------------+----------------+------------+
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 * | |
31 * | Other PSP Firmware |
32 * | |
33 * +------------+---------------+----------------+------------+
34 * | 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
55 * PSP Combo directory
56 * +------------+---------------+----------------+------------+
57 * | 'PSP2' | Fletcher | Count |Look up mode|
58 * +------------+---------------+----------------+------------+
59 * | R e s e r v e d |
60 * +------------+---------------+----------------+------------+
61 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
62 * +------------+---------------+----------------+------------+
63 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
64 * +------------+---------------+----------------+------------+
65 * | |
66 * | Other PSP |
67 * | |
68 * +------------+---------------+----------------+------------+
69 * BDT Combo is similar
72 #include <commonlib/bsd/helpers.h>
73 #include <fcntl.h>
74 #include <errno.h>
75 #include <limits.h>
76 #include <stdbool.h>
77 #include <stdio.h>
78 #include <sys/stat.h>
79 #include <sys/types.h>
80 #include <unistd.h>
81 #include <string.h>
82 #include <stdlib.h>
83 #include <libgen.h>
84 #include <stdint.h>
86 #include "amdfwtool.h"
88 #define AMD_ROMSIG_OFFSET 0x20000
90 #define _MAX(A, B) (((A) > (B)) ? (A) : (B))
92 static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry);
95 * 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.
102 * Modern generations supporting the combo directories require the
103 * pointer to be at offset 0x14 of the Embedded Firmware Structure,
104 * regardless of the type of directory used. The --use-combo
105 * argument enforces this placement.
107 * TODO: Future work may require fully implementing the PSP_COMBO feature.
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.
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.
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.
130 static uint32_t fletcher32(const void *data, int length)
132 uint32_t c0;
133 uint32_t c1;
134 uint32_t checksum;
135 int index;
136 const uint16_t *pptr = data;
138 length /= 2;
140 c0 = 0xFFFF;
141 c1 = 0xFFFF;
143 while (length) {
144 index = length >= 359 ? 359 : length;
145 length -= index;
146 do {
147 c0 += *(pptr++);
148 c1 += c0;
149 } while (--index);
150 c0 = (c0 & 0xFFFF) + (c0 >> 16);
151 c1 = (c1 & 0xFFFF) + (c1 >> 16);
154 /* Sums[0,1] mod 64K + overflow */
155 c0 = (c0 & 0xFFFF) + (c0 >> 16);
156 c1 = (c1 & 0xFFFF) + (c1 >> 16);
157 checksum = (c1 << 16) | c0;
159 return checksum;
162 amd_fw_entry amd_psp_fw_table[] = {
163 { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
164 { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL2_AB,
165 .generate_manifest = true },
166 { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB },
167 { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 },
168 { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
169 { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH },
170 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB,
171 .generate_manifest = true },
172 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
173 { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
174 { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB,
175 .skip_hashing = true },
176 { .type = AMD_FW_ABL_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB },
177 { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB },
178 { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB },
179 { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB },
180 { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB },
181 { .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 },
183 { .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 },
187 { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB },
188 { .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 },
190 { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
191 { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB },
192 { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB },
193 { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB },
194 { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB },
195 { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
196 { .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 },
198 { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB },
199 { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB },
200 { .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 },
203 { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB },
204 { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB,
205 .generate_manifest = true },
206 { .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 },
213 { .type = AMD_SEV_DATA, .level = PSP_LVL2 | PSP_LVL2_AB },
214 { .type = AMD_SEV_CODE, .level = PSP_LVL2 | PSP_LVL2_AB },
215 { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 | PSP_LVL2_AB },
216 { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB },
217 { .type = AMD_FW_DXIO, .level = PSP_BOTH | PSP_BOTH_AB },
218 { .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 },
223 { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_LVL2_AB },
224 { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_LVL2_AB },
225 { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB },
226 { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB },
227 { .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 },
231 { .type = AMD_FW_MPIO, .level = PSP_LVL2 | PSP_LVL2_AB },
232 { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH | PSP_LVL2_AB },
233 { .type = AMD_FW_DMCUB, .level = PSP_LVL2 | PSP_LVL2_AB },
234 { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB,
235 .generate_manifest = true },
236 { .type = AMD_RIB, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB },
237 { .type = AMD_RIB, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB },
238 { .type = AMD_FW_MPDMA_TF, .level = PSP_BOTH | PSP_BOTH_AB },
239 { .type = AMD_TA_IKEK, .level = PSP_BOTH | PSP_LVL2_AB, .skip_hashing = true },
240 { .type = AMD_FW_GMI3_PHY, .level = PSP_BOTH | PSP_BOTH_AB },
241 { .type = AMD_FW_MPDMA_PM, .level = PSP_BOTH | PSP_BOTH_AB },
242 { .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 },
256 { .type = AMD_FW_UMSMU, .level = PSP_LVL2 | PSP_LVL2_AB },
257 { .type = AMD_FW_INVALID },
260 amd_fw_entry amd_fw_table[] = {
261 { .type = AMD_FW_XHCI },
262 { .type = AMD_FW_IMC },
263 { .type = AMD_FW_GEC },
264 { .type = AMD_FW_INVALID },
267 amd_bios_entry amd_bios_table[] = {
268 { .type = AMD_BIOS_RTM_PUBKEY, .inst = 0, .level = BDT_BOTH },
269 { .type = AMD_BIOS_SIG, .inst = 0, .level = BDT_BOTH },
270 { .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 },
275 { .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 },
286 { .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 },
291 { .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 },
302 { .type = AMD_BIOS_APOB, .level = BDT_BOTH },
303 { .type = AMD_BIOS_BIN,
304 .reset = 1, .copy = 1, .zlib = 1, .inst = 0, .level = BDT_BOTH },
305 { .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 },
308 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 0, .level = BDT_BOTH },
309 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 0, .level = BDT_BOTH },
310 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 0, .level = BDT_BOTH },
311 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 0, .level = BDT_BOTH },
312 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH },
313 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH },
314 { .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 },
320 { .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 },
324 { .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 },
330 { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH },
331 { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH },
332 { .type = AMD_BIOS_PMUI, .inst = 2, .subpr = 1, .level = BDT_BOTH },
333 { .type = AMD_BIOS_PMUD, .inst = 2, .subpr = 1, .level = BDT_BOTH },
334 { .type = AMD_BIOS_PMUI, .inst = 3, .subpr = 1, .level = BDT_BOTH },
335 { .type = AMD_BIOS_PMUD, .inst = 3, .subpr = 1, .level = BDT_BOTH },
336 { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH },
337 { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH },
338 { .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 },
344 { .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 },
348 { .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 },
354 { .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 },
357 { .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 },
361 { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 },
362 { .type = AMD_BIOS_PSP_SHARED_MEM, .inst = 0, .level = BDT_BOTH },
363 { .type = AMD_BIOS_INVALID },
366 #define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
367 #define RUN_OFFSET_MODE(ctx, offset, mode) \
368 ((mode) == AMD_ADDR_PHYSICAL ? RUN_BASE(ctx) + (offset) : \
369 ((mode) == AMD_ADDR_REL_BIOS ? (offset) : \
370 ((mode) == AMD_ADDR_REL_TAB ? (offset) - (ctx).current_table : (offset))))
371 #define RUN_OFFSET(ctx, offset) RUN_OFFSET_MODE((ctx), (offset), (ctx).address_mode)
372 #define RUN_TO_OFFSET(ctx, run) ((ctx).address_mode == AMD_ADDR_PHYSICAL ? \
373 (run) - RUN_BASE(ctx) : (run)) /* TODO: */
374 #define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
375 /* 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))
379 #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))
382 #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))
384 #define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
385 /* 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 == \
388 AMD_ADDR_REL_TAB ? (mode) : 0)
389 #define SET_ADDR_MODE_BY_TABLE(table) \
390 SET_ADDR_MODE((table), (table)->header.additional_info_fields.address_mode)
393 static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
395 amd_fw_entry *index;
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;
409 static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
411 amd_bios_entry *index;
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;
425 static void amdfwtool_cleanup(context *ctx)
427 free(ctx->rom);
428 ctx->rom = NULL;
430 /* Free the filename. */
431 free_psp_firmware_filenames(amd_psp_fw_table);
432 free_bdt_firmware_filenames(amd_bios_table);
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;
440 void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
442 if (count >= max) {
443 fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
444 "(%d)\n", count, max);
445 amdfwtool_cleanup(ctx);
446 exit(1);
450 static void set_current_pointer(context *ctx, uint32_t value)
452 if (ctx->current_pointer_saved != 0xFFFFFFFF &&
453 ctx->current_pointer_saved != ctx->current) {
454 fprintf(stderr, "Error: The pointer is changed elsewhere\n");
455 amdfwtool_cleanup(ctx);
456 exit(1);
459 ctx->current = value;
461 if (ctx->current > ctx->rom_size) {
462 fprintf(stderr, "Error: Packing data causes overflow\n");
463 amdfwtool_cleanup(ctx);
464 exit(1);
467 ctx->current_pointer_saved = ctx->current;
470 static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
472 /* Get */
473 set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
476 static void *new_psp_dir(context *ctx, int multi, uint32_t cookie)
478 void *ptr;
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.
485 if (multi)
486 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
487 else
488 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
490 ptr = BUFF_CURRENT(*ctx);
491 ((psp_directory_header *)ptr)->cookie = cookie;
492 ((psp_directory_header *)ptr)->num_entries = 0;
493 ((psp_directory_header *)ptr)->additional_info = 0;
494 ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode;
495 ((psp_directory_header *)ptr)->additional_info_fields.spi_block_size = 1;
496 ((psp_directory_header *)ptr)->additional_info_fields.base_addr = 0;
497 adjust_current_pointer(ctx,
498 sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
500 return ptr;
503 static void *new_ish_dir(context *ctx)
505 void *ptr;
506 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
507 ptr = BUFF_CURRENT(*ctx);
508 adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
510 return ptr;
513 static void *new_combo_dir(context *ctx, uint32_t cookie)
515 void *ptr;
517 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
518 ptr = BUFF_CURRENT(*ctx);
519 ((psp_combo_header *)ptr)->cookie = cookie;
520 /* lookup mode is hardcoded for now. */
521 ((psp_combo_header *)ptr)->lookup = 1;
522 ((psp_combo_header *)ptr)->reserved[0] = 0;
523 ((psp_combo_header *)ptr)->reserved[1] = 0;
525 adjust_current_pointer(ctx,
526 sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
528 return ptr;
531 static void copy_psp_header(void *bak, void *orig)
533 uint32_t count = ((psp_directory_header *)orig)->num_entries;
534 memcpy(bak, orig, count * sizeof(bios_directory_entry) + sizeof(psp_directory_table));
537 static void fill_dir_header(void *directory, uint32_t count, context *ctx)
539 psp_combo_directory *cdir = directory;
540 psp_directory_table *dir = directory;
541 bios_directory_table *bdir = directory;
542 /* The cookies have same offsets. */
543 uint32_t cookie = ((psp_directory_table *)directory)->header.cookie;
544 uint32_t table_size = 0;
546 if (ctx == NULL || directory == NULL) {
547 fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
548 return;
551 /* The table size needs to be 0x1000 aligned. So align the end of table. */
552 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
554 switch (cookie) {
555 case PSP2_COOKIE:
556 case BHD2_COOKIE:
557 cdir->header.num_entries = count;
558 /* checksum everything that comes after the Checksum field */
559 cdir->header.checksum = fletcher32(&cdir->header.num_entries,
560 count * sizeof(psp_combo_entry)
561 + sizeof(cdir->header.num_entries)
562 + sizeof(cdir->header.lookup)
563 + 2 * sizeof(cdir->header.reserved[0]));
564 break;
565 case PSP_COOKIE:
566 case PSPL2_COOKIE:
567 /* The table size is only set once. Later calls only update
568 * the count and fletcher. So does the BIOS table. */
569 if (dir->header.additional_info_fields.dir_size == 0) {
570 table_size = ctx->current - ctx->current_table;
571 if ((table_size % TABLE_ALIGNMENT) != 0 &&
572 (table_size / TABLE_ALIGNMENT) != 0) {
573 fprintf(stderr, "The PSP table size should be 4K aligned\n");
574 amdfwtool_cleanup(ctx);
575 exit(1);
577 dir->header.additional_info_fields.dir_size =
578 table_size / TABLE_ALIGNMENT;
580 dir->header.num_entries = count;
581 /* checksum everything that comes after the Checksum field */
582 dir->header.checksum = fletcher32(&dir->header.num_entries,
583 count * sizeof(psp_directory_entry)
584 + sizeof(dir->header.num_entries)
585 + sizeof(dir->header.additional_info));
586 break;
587 case BHD_COOKIE:
588 case BHDL2_COOKIE:
589 if (bdir->header.additional_info_fields.dir_size == 0) {
590 table_size = ctx->current - ctx->current_table;
591 if ((table_size % TABLE_ALIGNMENT) != 0 &&
592 table_size / TABLE_ALIGNMENT != 0) {
593 fprintf(stderr, "The BIOS table size should be 4K aligned\n");
594 amdfwtool_cleanup(ctx);
595 exit(1);
597 bdir->header.additional_info_fields.dir_size =
598 table_size / TABLE_ALIGNMENT;
600 bdir->header.num_entries = count;
601 /* checksum everything that comes after the Checksum field */
602 bdir->header.checksum = fletcher32(&bdir->header.num_entries,
603 count * sizeof(bios_directory_entry)
604 + sizeof(bdir->header.num_entries)
605 + sizeof(bdir->header.additional_info));
606 break;
610 static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
611 context *ctx, amd_cb_config *cb_config)
613 switch (cb_config->soc_id) {
614 case PLATFORM_UNKNOWN:
615 amd_romsig->psp_directory =
616 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
617 break;
618 case PLATFORM_CEZANNE:
619 case PLATFORM_MENDOCINO:
620 case PLATFORM_PHOENIX:
621 case PLATFORM_GLINDA:
622 case PLATFORM_CARRIZO:
623 case PLATFORM_STONEYRIDGE:
624 case PLATFORM_RAVEN:
625 case PLATFORM_PICASSO:
626 case PLATFORM_LUCIENNE:
627 case PLATFORM_RENOIR:
628 case PLATFORM_GENOA:
629 default:
630 /* for combo, it is also combo_psp_directory */
631 amd_romsig->new_psp_directory =
632 BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
633 break;
637 static void fill_psp_bak_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir_bak,
638 context *ctx, amd_cb_config *cb_config)
640 if (cb_config->recovery_ab)
641 amd_romsig->psp_bak_directory =
642 BUFF_TO_RUN_MODE(*ctx, pspdir_bak, AMD_ADDR_REL_BIOS);
645 static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
646 context *ctx, amd_cb_config *cb_config)
648 switch (cb_config->soc_id) {
649 case PLATFORM_RENOIR:
650 case PLATFORM_LUCIENNE:
651 case PLATFORM_CEZANNE:
652 case PLATFORM_GENOA:
653 if (!cb_config->recovery_ab)
654 amd_romsig->bios3_entry =
655 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
656 break;
657 case PLATFORM_MENDOCINO:
658 case PLATFORM_PHOENIX:
659 case PLATFORM_GLINDA:
660 break;
661 case PLATFORM_CARRIZO:
662 case PLATFORM_STONEYRIDGE:
663 case PLATFORM_RAVEN:
664 case PLATFORM_PICASSO:
665 default:
666 amd_romsig->bios1_entry =
667 BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
668 break;
672 static uint32_t get_psp_id(enum platform soc_id)
674 uint32_t psp_id;
675 switch (soc_id) {
676 case PLATFORM_RAVEN:
677 case PLATFORM_PICASSO:
678 psp_id = 0xBC0A0000;
679 break;
680 case PLATFORM_RENOIR:
681 case PLATFORM_LUCIENNE:
682 psp_id = 0xBC0C0000;
683 break;
684 case PLATFORM_CEZANNE:
685 psp_id = 0xBC0C0140;
686 break;
687 case PLATFORM_MENDOCINO:
688 psp_id = 0xBC0D0900;
689 break;
690 case PLATFORM_STONEYRIDGE:
691 psp_id = 0x10220B00;
692 break;
693 case PLATFORM_GLINDA:
694 psp_id = 0xBC0E0200;
695 break;
696 case PLATFORM_PHOENIX:
697 psp_id = 0xBC0D0400;
698 break;
699 case PLATFORM_GENOA:
700 psp_id = 0xBC0C0111;
701 break;
702 case PLATFORM_CARRIZO:
703 default:
704 psp_id = 0;
705 break;
707 return psp_id;
710 static void integrate_firmwares(context *ctx,
711 embedded_firmware *romsig,
712 amd_fw_entry *fw_table)
714 ssize_t bytes;
715 uint32_t i;
717 adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
719 for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
720 if (fw_table[i].filename != NULL) {
721 switch (fw_table[i].type) {
722 case AMD_FW_IMC:
723 adjust_current_pointer(ctx, 0, 0x10000U);
724 romsig->imc_entry = RUN_CURRENT(*ctx);
725 break;
726 case AMD_FW_GEC:
727 romsig->gec_entry = RUN_CURRENT(*ctx);
728 break;
729 case AMD_FW_XHCI:
730 romsig->xhci_entry = RUN_CURRENT(*ctx);
731 break;
732 default:
733 /* Error */
734 break;
737 bytes = copy_blob(BUFF_CURRENT(*ctx),
738 fw_table[i].filename, BUFF_ROOM(*ctx));
739 if (bytes < 0) {
740 amdfwtool_cleanup(ctx);
741 exit(1);
744 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
749 static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
751 struct amd_fw_header hdr;
752 int blob_fd;
753 ssize_t bytes;
755 blob_fd = open(fw_entry->filename, O_RDONLY);
756 if (blob_fd < 0) {
757 fprintf(stderr, "Error opening file: %s: %s\n",
758 fw_entry->filename, strerror(errno));
759 return;
762 bytes = read(blob_fd, &hdr, sizeof(hdr));
763 if (bytes != sizeof(hdr)) {
764 close(blob_fd);
765 fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
766 return;
769 dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
770 fw_entry->type, hdr.version[3], hdr.version[2],
771 hdr.version[1], hdr.version[0]);
773 close(blob_fd);
777 static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
779 amd_fw_entry *index;
780 int manifest_fd;
782 manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
783 if (manifest_fd < 0) {
784 fprintf(stderr, "Error opening file: %s: %s\n",
785 manifest_file, strerror(errno));
786 return;
789 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
790 if (!(index->filename))
791 continue;
793 if (index->generate_manifest == true)
794 output_manifest(manifest_fd, index);
797 close(manifest_fd);
800 /* For debugging */
801 static void dump_psp_firmwares(amd_fw_entry *fw_table)
803 amd_fw_entry *index;
805 printf("PSP firmware components:\n");
806 for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
807 if (index->type == AMD_PSP_FUSE_CHAIN)
808 printf(" %2x: level=%x, subprog=%x, inst=%x\n",
809 index->type, index->level, index->subprog, index->inst);
810 else if (index->filename)
811 printf(" %2x: level=%x, subprog=%x, inst=%x, %s\n",
812 index->type, index->level, index->subprog, index->inst,
813 index->filename);
817 static void dump_bdt_firmwares(amd_bios_entry *fw_table)
819 amd_bios_entry *index;
821 printf("BIOS Directory Table (BDT) components:\n");
822 for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
823 if (index->filename)
824 printf(" %2x: level=%x, %s\n",
825 index->type, index->level, index->filename);
829 static void dump_image_addresses(context *ctx)
831 printf("romsig offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->amd_romsig_ptr));
832 printf("PSP L1 offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir));
833 if (ctx->pspdir_bak != NULL)
834 printf("PSP L1 backup offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir_bak));
835 if (ctx->pspdir2 != NULL)
836 printf("PSP L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2));
837 if (ctx->ish_a_dir != NULL)
838 printf("ISHA offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_a_dir));
839 if (ctx->ish_b_dir != NULL)
840 printf("ISHB offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_b_dir));
841 if (ctx->pspdir2_b != NULL)
842 printf("PSP L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2_b));
843 if (ctx->biosdir != NULL)
844 printf("BHD offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir));
845 if (ctx->biosdir2 != NULL)
846 printf("BHD L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2));
847 if (ctx->biosdir2_b != NULL)
848 printf("BHD L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2_b));
849 if (ctx->psp_combo_dir != NULL)
850 printf("PSP combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->psp_combo_dir));
851 if (ctx->bhd_combo_dir != NULL)
852 printf("BHD combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->bhd_combo_dir));
855 static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
856 psp_directory_table *pspdir2, ish_directory_table *ish,
857 amd_fw_type ab, enum platform soc_id)
859 uint32_t count;
860 uint32_t current_table_save;
862 current_table_save = ctx->current_table;
863 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
864 count = pspdir->header.num_entries;
865 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
866 pspdir->entries[count].type = (uint8_t)ab;
867 pspdir->entries[count].subprog = 0;
868 pspdir->entries[count].rsvd = 0;
869 if (ish != NULL) {
870 ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
871 ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
872 ish->update_retry_count = 2;
873 ish->glitch_retry_count = 0;
874 ish->psp_id = get_psp_id(soc_id);
875 ish->checksum = fletcher32(&ish->boot_priority,
876 sizeof(ish_directory_table) - sizeof(uint32_t));
877 pspdir->entries[count].addr =
878 BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
879 pspdir->entries[count].address_mode =
880 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
881 pspdir->entries[count].size = TABLE_ALIGNMENT;
882 } else {
883 pspdir->entries[count].addr =
884 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
885 pspdir->entries[count].address_mode =
886 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
887 pspdir->entries[count].size = _MAX(TABLE_L2_SIZE_MAX,
888 pspdir2->header.num_entries *
889 sizeof(psp_directory_entry) +
890 sizeof(psp_directory_header));
893 count++;
894 fill_dir_header(pspdir, count, ctx);
895 ctx->current_table = current_table_save;
898 static void integrate_psp_levels(context *ctx,
899 amd_cb_config *cb_config)
901 uint32_t current_table_save;
902 bool recovery_ab = cb_config->recovery_ab;
903 unsigned int count;
904 psp_directory_table *pspdir, *pspdir2, *pspdir2_b;
905 bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
907 pspdir = ctx->pspdir;
908 pspdir2 = ctx->pspdir2;
909 pspdir2_b = ctx->pspdir2_b;
910 count = pspdir->header.num_entries;
912 current_table_save = ctx->current_table;
913 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
914 if (recovery_ab && (pspdir2 != NULL)) {
915 if (cb_config->need_ish) { /* Need ISH */
916 ctx->ish_a_dir = new_ish_dir(ctx);
917 if (pspdir2_b != NULL)
918 ctx->ish_b_dir = new_ish_dir(ctx);
920 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
921 AMD_FW_RECOVERYAB_A, cb_config->soc_id);
922 if (pspdir2_b != NULL)
923 integrate_psp_ab(ctx, pspdir, pspdir2_b, ctx->ish_b_dir,
924 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
925 cb_config->soc_id);
926 else
927 integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
928 use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
929 cb_config->soc_id);
931 copy_psp_header(ctx->pspdir_bak, ctx->pspdir);
932 } else if (pspdir2 != NULL) {
933 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
934 pspdir->entries[count].type = AMD_FW_L2_PTR;
935 pspdir->entries[count].subprog = 0;
936 pspdir->entries[count].rsvd = 0;
937 pspdir->entries[count].size = sizeof(pspdir2->header)
938 + pspdir2->header.num_entries
939 * sizeof(psp_directory_entry);
941 pspdir->entries[count].addr =
942 BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
943 pspdir->entries[count].address_mode =
944 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
945 count++;
946 fill_dir_header(pspdir, count, ctx);
948 ctx->current_table = current_table_save;
951 static void integrate_psp_firmwares(context *ctx,
952 amd_fw_entry *fw_table,
953 uint32_t cookie,
954 amd_cb_config *cb_config)
956 ssize_t bytes;
957 unsigned int i, count;
958 int level;
959 uint32_t size;
960 psp_directory_table *pspdir;
961 uint64_t addr;
962 uint32_t current_table_save;
963 bool recovery_ab = cb_config->recovery_ab;
965 /* This function can create a primary table, a secondary table, or a
966 * flattened table which contains all applicable types. These if-else
967 * statements infer what the caller intended. If a 2nd-level cookie
968 * is passed, clearly a 2nd-level table is intended. However, a
969 * 1st-level cookie may indicate level 1 or flattened.
971 pspdir = new_psp_dir(ctx, cb_config->multi_level, cookie);
973 if (cookie == PSP_COOKIE) {
974 ctx->pspdir = pspdir;
975 if (recovery_ab)
976 ctx->pspdir_bak = new_psp_dir(ctx, cb_config->multi_level, cookie);
977 } else if (cookie == PSPL2_COOKIE) {
978 if (ctx->pspdir2 == NULL)
979 ctx->pspdir2 = pspdir;
980 else if (ctx->pspdir2_b == NULL)
981 ctx->pspdir2_b = pspdir;
984 if (!cb_config->multi_level)
985 level = PSP_BOTH;
986 else if (cookie == PSPL2_COOKIE)
987 level = PSP_LVL2;
988 else if (cookie == PSP_COOKIE)
989 level = PSP_LVL1;
990 else
991 level = PSP_BOTH;
993 if (recovery_ab) {
994 if (cookie == PSPL2_COOKIE)
995 level = PSP_LVL2_AB;
996 else if (cookie == PSP_COOKIE)
997 level = PSP_LVL1_AB;
998 else
999 level = PSP_BOTH_AB;
1001 current_table_save = ctx->current_table;
1002 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
1003 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
1005 for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
1006 if (!(fw_table[i].level & level))
1007 continue;
1009 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1011 if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
1012 if (!fw_table[i].other)
1013 continue;
1014 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1015 pspdir->entries[count].type = fw_table[i].type;
1016 pspdir->entries[count].size = 4096; /* TODO: doc? */
1017 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1018 pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1019 pspdir->entries[count].subprog = fw_table[i].subprog;
1020 pspdir->entries[count].rsvd = 0;
1021 adjust_current_pointer(ctx, 4096, 0x100U);
1022 count++;
1023 } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
1024 pspdir->entries[count].type = fw_table[i].type;
1025 pspdir->entries[count].subprog = fw_table[i].subprog;
1026 pspdir->entries[count].rsvd = 0;
1027 pspdir->entries[count].size = 0xFFFFFFFF;
1028 pspdir->entries[count].addr = fw_table[i].other;
1029 pspdir->entries[count].address_mode = 0;
1030 count++;
1031 } else if (fw_table[i].type == AMD_FW_PSP_NVRAM ||
1032 fw_table[i].type == AMD_RPMC_NVRAM) {
1033 if (fw_table[i].filename == NULL) {
1034 if (fw_table[i].size == 0)
1035 continue;
1036 size = fw_table[i].size;
1037 addr = fw_table[i].dest;
1038 if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
1039 fprintf(stderr,
1040 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1041 amdfwtool_cleanup(ctx);
1042 exit(1);
1044 } else {
1045 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1046 bytes = copy_blob(BUFF_CURRENT(*ctx),
1047 fw_table[i].filename, BUFF_ROOM(*ctx));
1048 if (bytes <= 0) {
1049 amdfwtool_cleanup(ctx);
1050 exit(1);
1053 size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
1054 addr = RUN_CURRENT(*ctx);
1055 adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
1058 pspdir->entries[count].type = fw_table[i].type;
1059 pspdir->entries[count].subprog = fw_table[i].subprog;
1060 pspdir->entries[count].rsvd = 0;
1061 pspdir->entries[count].size = size;
1062 pspdir->entries[count].addr = addr;
1064 pspdir->entries[count].address_mode =
1065 SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
1067 count++;
1068 } else if (fw_table[i].filename != NULL) {
1069 if (fw_table[i].addr_signed) {
1070 pspdir->entries[count].addr =
1071 RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1072 pspdir->entries[count].address_mode =
1073 SET_ADDR_MODE_BY_TABLE(pspdir);
1074 bytes = fw_table[i].file_size;
1075 } else {
1076 bytes = copy_blob(BUFF_CURRENT(*ctx),
1077 fw_table[i].filename, BUFF_ROOM(*ctx));
1078 if (bytes < 0) {
1079 amdfwtool_cleanup(ctx);
1080 exit(1);
1082 pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1083 pspdir->entries[count].address_mode =
1084 SET_ADDR_MODE_BY_TABLE(pspdir);
1085 adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
1088 pspdir->entries[count].type = fw_table[i].type;
1089 pspdir->entries[count].subprog = fw_table[i].subprog;
1090 pspdir->entries[count].rsvd = 0;
1091 pspdir->entries[count].inst = fw_table[i].inst;
1092 pspdir->entries[count].size = (uint32_t)bytes;
1094 count++;
1095 } else {
1096 /* This APU doesn't have this firmware. */
1100 fill_dir_header(pspdir, count, ctx);
1101 ctx->current_table = current_table_save;
1104 static void add_psp_firmware_entry(context *ctx,
1105 psp_directory_table *pspdir,
1106 void *table, amd_fw_type type, uint32_t size)
1108 uint32_t count = pspdir->header.num_entries;
1109 uint32_t index;
1110 uint32_t current_table_save;
1112 current_table_save = ctx->current_table;
1113 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
1115 /* If there is an entry of "type", replace it. */
1116 for (index = 0; index < count; index++) {
1117 if (pspdir->entries[index].type == (uint8_t)type)
1118 break;
1121 assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1122 pspdir->entries[index].type = (uint8_t)type;
1123 pspdir->entries[index].subprog = 0;
1124 pspdir->entries[index].rsvd = 0;
1125 pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1126 pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1127 pspdir->entries[index].size = size;
1128 if (index == count)
1129 count++;
1131 fill_dir_header(pspdir, count, ctx);
1132 ctx->current_table = current_table_save;
1135 static void *new_bios_dir(context *ctx, bool multi, uint32_t cookie)
1137 void *ptr;
1140 * Force both onto boundary when multi. Primary table is after
1141 * updatable table, so alignment ensures primary can stay intact
1142 * if secondary is reprogrammed.
1144 if (multi)
1145 adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
1146 else
1147 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
1148 ptr = BUFF_CURRENT(*ctx);
1149 ((bios_directory_hdr *) ptr)->cookie = cookie;
1150 ((bios_directory_hdr *) ptr)->additional_info = 0;
1151 ((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1152 ((bios_directory_hdr *) ptr)->additional_info_fields.spi_block_size = 1;
1153 ((bios_directory_hdr *) ptr)->additional_info_fields.base_addr = 0;
1154 adjust_current_pointer(ctx,
1155 sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1157 return ptr;
1160 static int locate_bdt2_bios(bios_directory_table *level2,
1161 uint64_t *source, uint32_t *size)
1163 uint32_t i;
1165 *source = 0;
1166 *size = 0;
1167 if (!level2)
1168 return 0;
1170 for (i = 0 ; i < level2->header.num_entries ; i++) {
1171 if (level2->entries[i].type == AMD_BIOS_BIN) {
1172 *source = level2->entries[i].source;
1173 *size = level2->entries[i].size;
1174 return 1;
1177 return 0;
1180 static int have_bios_tables(amd_bios_entry *table)
1182 int i;
1184 for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1185 if (table[i].level & BDT_LVL1 && table[i].filename)
1186 return 1;
1188 return 0;
1191 int find_bios_entry(amd_bios_type type)
1193 int i;
1195 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1196 if (amd_bios_table[i].type == type)
1197 return i;
1199 return -1;
1202 static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1203 int inst, uint32_t size, uint64_t source)
1205 int i;
1207 for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1208 if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1209 amd_bios_table[i].inst == inst)
1210 break;
1213 if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1214 return;
1216 biosdir->entries[idx].type = amd_bios_table[i].type;
1217 biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1218 biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1219 amd_bios_table[i].dest : (uint64_t)-1;
1220 biosdir->entries[idx].reset = amd_bios_table[i].reset;
1221 biosdir->entries[idx].copy = amd_bios_table[i].copy;
1222 biosdir->entries[idx].ro = amd_bios_table[i].ro;
1223 biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1224 biosdir->entries[idx].inst = amd_bios_table[i].inst;
1225 biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1226 biosdir->entries[idx].size = size;
1227 biosdir->entries[idx].source = source;
1228 biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1231 static void integrate_bios_levels(context *ctx, amd_cb_config *cb_config)
1233 unsigned int count;
1234 uint32_t current_table_save;
1236 if (cb_config->recovery_ab) {
1237 add_psp_firmware_entry(ctx, ctx->pspdir2, ctx->biosdir2,
1238 AMD_FW_BIOS_TABLE, TABLE_L2_SIZE_MAX);
1239 if (ctx->pspdir2_b != NULL)
1240 add_psp_firmware_entry(ctx, ctx->pspdir2_b,
1241 ctx->biosdir2_b, AMD_FW_BIOS_TABLE,
1242 TABLE_L2_SIZE_MAX);
1243 } else if (ctx->biosdir2) {
1244 current_table_save = ctx->current_table;
1245 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, ctx->biosdir, AMD_ADDR_REL_BIOS);
1246 count = ctx->biosdir->header.num_entries;
1247 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1248 ctx->biosdir->entries[count].type = AMD_BIOS_L2_PTR;
1249 ctx->biosdir->entries[count].region_type = 0;
1250 ctx->biosdir->entries[count].size =
1251 + MAX_BIOS_ENTRIES
1252 * sizeof(bios_directory_entry);
1253 ctx->biosdir->entries[count].source =
1254 BUFF_TO_RUN(*ctx, ctx->biosdir2);
1255 ctx->biosdir->entries[count].address_mode =
1256 SET_ADDR_MODE(ctx->biosdir, AMD_ADDR_REL_BIOS);
1257 ctx->biosdir->entries[count].subprog = 0;
1258 ctx->biosdir->entries[count].inst = 0;
1259 ctx->biosdir->entries[count].copy = 0;
1260 ctx->biosdir->entries[count].compressed = 0;
1261 ctx->biosdir->entries[count].dest = -1;
1262 ctx->biosdir->entries[count].reset = 0;
1263 ctx->biosdir->entries[count].ro = 0;
1264 count++;
1265 fill_dir_header(ctx->biosdir, count, ctx);
1266 ctx->current_table = current_table_save;
1269 static void integrate_bios_firmwares(context *ctx,
1270 amd_bios_entry *fw_table,
1271 uint32_t cookie,
1272 amd_cb_config *cb_config)
1274 ssize_t bytes;
1275 unsigned int i, count;
1276 int level;
1277 int apob_idx;
1278 uint32_t size;
1279 uint64_t source;
1280 uint32_t current_table_save;
1281 bios_directory_table *biosdir;
1283 biosdir = new_bios_dir(ctx, cb_config->multi_level, cookie);
1285 if (cookie == BHD_COOKIE)
1286 ctx->biosdir = biosdir;
1287 else if (cookie == BHDL2_COOKIE) {
1288 if (ctx->biosdir2 == NULL)
1289 ctx->biosdir2 = biosdir;
1290 else if (ctx->biosdir2_b == NULL)
1291 ctx->biosdir2_b = biosdir;
1294 /* This function can create a primary table, a secondary table, or a
1295 * flattened table which contains all applicable types. These if-else
1296 * statements infer what the caller intended. If a 2nd-level cookie
1297 * is passed, clearly a 2nd-level table is intended. However, a
1298 * 1st-level cookie may indicate level 1 or flattened.
1300 if (!cb_config->multi_level)
1301 level = BDT_BOTH;
1302 else if (cookie == BHDL2_COOKIE)
1303 level = BDT_LVL2;
1304 else if (cookie == BHD_COOKIE)
1305 level = BDT_LVL1;
1306 else
1307 level = BDT_BOTH;
1309 current_table_save = ctx->current_table;
1310 ctx->current_table = BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
1311 adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
1313 for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1314 if (!(fw_table[i].level & level))
1315 continue;
1316 if (fw_table[i].filename == NULL && (
1317 fw_table[i].type != AMD_BIOS_SIG &&
1318 fw_table[i].type != AMD_BIOS_APOB &&
1319 fw_table[i].type != AMD_BIOS_APOB_NV &&
1320 fw_table[i].type != AMD_BIOS_L2_PTR &&
1321 fw_table[i].type != AMD_BIOS_BIN &&
1322 fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
1323 continue;
1325 /* BIOS Directory items may have additional requirements */
1327 /* SIG needs a size, else no choice but to skip */
1328 if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1329 continue;
1331 /* Check APOB_NV requirements */
1332 if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1333 if (!fw_table[i].size && !fw_table[i].src)
1334 continue; /* APOB_NV not used */
1335 if (fw_table[i].src && !fw_table[i].size) {
1336 fprintf(stderr, "Error: APOB NV address provided, but no size\n");
1337 amdfwtool_cleanup(ctx);
1338 exit(1);
1340 /* If the APOB isn't used, APOB_NV isn't used either */
1341 apob_idx = find_bios_entry(AMD_BIOS_APOB);
1342 if (apob_idx < 0 || !fw_table[apob_idx].dest)
1343 continue; /* APOV NV not supported */
1346 /* APOB_DATA needs destination */
1347 if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
1348 fprintf(stderr, "Error: APOB destination not provided\n");
1349 amdfwtool_cleanup(ctx);
1350 exit(1);
1353 /* BIOS binary must have destination and uncompressed size. If
1354 * no filename given, then user must provide a source address.
1356 if (fw_table[i].type == AMD_BIOS_BIN) {
1357 if (!fw_table[i].dest || !fw_table[i].size) {
1358 fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
1359 amdfwtool_cleanup(ctx);
1360 exit(1);
1362 if (!fw_table[i].filename && !fw_table[i].src) {
1363 fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
1364 amdfwtool_cleanup(ctx);
1365 exit(1);
1369 /* PSP_SHARED_MEM needs a destination and size */
1370 if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1371 (!fw_table[i].dest || !fw_table[i].size))
1372 continue;
1373 assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1375 biosdir->entries[count].type = fw_table[i].type;
1376 biosdir->entries[count].region_type = fw_table[i].region_type;
1377 biosdir->entries[count].dest = fw_table[i].dest ?
1378 fw_table[i].dest : (uint64_t)-1;
1379 biosdir->entries[count].reset = fw_table[i].reset;
1380 biosdir->entries[count].copy = fw_table[i].copy;
1381 biosdir->entries[count].ro = fw_table[i].ro;
1382 biosdir->entries[count].compressed = fw_table[i].zlib;
1383 biosdir->entries[count].inst = fw_table[i].inst;
1384 biosdir->entries[count].subprog = fw_table[i].subpr;
1386 switch (fw_table[i].type) {
1387 case AMD_BIOS_SIG:
1388 /* Reserve size bytes within amdfw.rom */
1389 biosdir->entries[count].size = fw_table[i].size;
1390 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1391 biosdir->entries[count].address_mode =
1392 SET_ADDR_MODE_BY_TABLE(biosdir);
1393 memset(BUFF_CURRENT(*ctx), 0xff,
1394 biosdir->entries[count].size);
1395 adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
1396 break;
1397 case AMD_BIOS_APOB:
1398 biosdir->entries[count].size = fw_table[i].size;
1399 biosdir->entries[count].source = fw_table[i].src;
1400 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1401 break;
1402 case AMD_BIOS_APOB_NV:
1403 if (fw_table[i].src) {
1404 /* If source is given, use that and its size */
1405 biosdir->entries[count].source = fw_table[i].src;
1406 biosdir->entries[count].address_mode =
1407 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1408 biosdir->entries[count].size = fw_table[i].size;
1409 } else {
1410 /* Else reserve size bytes within amdfw.rom */
1411 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1412 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1413 biosdir->entries[count].address_mode =
1414 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1415 biosdir->entries[count].size = ALIGN_UP(
1416 fw_table[i].size, ERASE_ALIGNMENT);
1417 memset(BUFF_CURRENT(*ctx), 0xff,
1418 biosdir->entries[count].size);
1419 adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
1421 break;
1422 case AMD_BIOS_BIN:
1423 /* Don't make a 2nd copy, point to the same one */
1424 if (level == BDT_LVL1 && locate_bdt2_bios(ctx->biosdir2, &source, &size)) {
1425 biosdir->entries[count].source = source;
1426 biosdir->entries[count].address_mode =
1427 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1428 biosdir->entries[count].size = size;
1429 break;
1432 /* level 2, or level 1 and no copy found in level 2 */
1433 biosdir->entries[count].source = fw_table[i].src;
1434 biosdir->entries[count].address_mode =
1435 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1436 biosdir->entries[count].dest = fw_table[i].dest;
1437 biosdir->entries[count].size = fw_table[i].size;
1439 if (!fw_table[i].filename)
1440 break;
1442 bytes = copy_blob(BUFF_CURRENT(*ctx),
1443 fw_table[i].filename, BUFF_ROOM(*ctx));
1444 if (bytes <= 0) {
1445 amdfwtool_cleanup(ctx);
1446 exit(1);
1449 biosdir->entries[count].source =
1450 RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
1451 biosdir->entries[count].address_mode =
1452 SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1454 adjust_current_pointer(ctx, bytes, 0x100U);
1455 break;
1456 case AMD_BIOS_PSP_SHARED_MEM:
1457 biosdir->entries[count].dest = fw_table[i].dest;
1458 biosdir->entries[count].size = fw_table[i].size;
1459 break;
1461 default: /* everything else is copied from input */
1462 if (fw_table[i].type == AMD_BIOS_APCB ||
1463 fw_table[i].type == AMD_BIOS_APCB_BK)
1464 adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1465 bytes = copy_blob(BUFF_CURRENT(*ctx),
1466 fw_table[i].filename, BUFF_ROOM(*ctx));
1467 if (bytes <= 0) {
1468 amdfwtool_cleanup(ctx);
1469 exit(1);
1472 biosdir->entries[count].size = (uint32_t)bytes;
1473 biosdir->entries[count].source = RUN_CURRENT(*ctx);
1474 biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1476 adjust_current_pointer(ctx, bytes, 0x100U);
1477 if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1478 size = biosdir->entries[count].size;
1479 source = biosdir->entries[count].source;
1480 count++;
1481 add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1483 break;
1486 count++;
1489 fill_dir_header(biosdir, count, ctx);
1490 ctx->current_table = current_table_save;
1493 static void add_combo_entry(void *combo_dir, void *dir, uint32_t combo_index,
1494 context *ctx, amd_cb_config *cb_config)
1496 psp_combo_directory *cdir = combo_dir;
1497 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, ctx);
1498 /* 0 -Compare PSP ID, 1 -Compare chip family ID */
1499 cdir->entries[combo_index].id_sel = 0;
1500 cdir->entries[combo_index].id = get_psp_id(cb_config->soc_id);
1501 cdir->entries[combo_index].lvl2_addr =
1502 BUFF_TO_RUN_MODE(*ctx, dir, AMD_ADDR_REL_BIOS);
1504 fill_dir_header(combo_dir, combo_index + 1, ctx);
1507 static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1508 embedded_firmware *amd_romsig)
1510 if ((cb_config->efs_spi_readmode == 0xFF) || (cb_config->efs_spi_speed == 0xFF)) {
1511 fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
1512 return 1;
1515 /* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1516 * Leave as 0xffffffff for first gen */
1517 if (cb_config->second_gen) {
1518 amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1519 amd_romsig->efs_gen.reserved = 0;
1520 } else {
1521 amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1522 amd_romsig->efs_gen.reserved = ~0;
1525 switch (soc_id) {
1526 case PLATFORM_CARRIZO:
1527 case PLATFORM_STONEYRIDGE:
1528 amd_romsig->spi_readmode_f15_mod_60_6f = cb_config->efs_spi_readmode;
1529 amd_romsig->fast_speed_new_f15_mod_60_6f = cb_config->efs_spi_speed;
1530 break;
1531 case PLATFORM_RAVEN:
1532 case PLATFORM_PICASSO:
1533 amd_romsig->spi_readmode_f17_mod_00_2f = cb_config->efs_spi_readmode;
1534 amd_romsig->spi_fastspeed_f17_mod_00_2f = cb_config->efs_spi_speed;
1535 switch (cb_config->efs_spi_micron_flag) {
1536 case 0:
1537 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1538 break;
1539 case 1:
1540 amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1541 break;
1542 default:
1543 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
1544 return 1;
1546 break;
1547 case PLATFORM_RENOIR:
1548 case PLATFORM_LUCIENNE:
1549 case PLATFORM_CEZANNE:
1550 case PLATFORM_MENDOCINO:
1551 case PLATFORM_PHOENIX:
1552 case PLATFORM_GLINDA:
1553 case PLATFORM_GENOA:
1554 amd_romsig->spi_readmode_f17_mod_30_3f = cb_config->efs_spi_readmode;
1555 amd_romsig->spi_fastspeed_f17_mod_30_3f = cb_config->efs_spi_speed;
1556 switch (cb_config->efs_spi_micron_flag) {
1557 case 0:
1558 amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1559 break;
1560 case 1:
1561 amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1562 break;
1563 case 2:
1564 amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1565 break;
1566 default:
1567 fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
1568 return 1;
1570 break;
1571 case PLATFORM_UNKNOWN:
1572 default:
1573 fprintf(stderr, "Error: Invalid SOC name.\n\n");
1574 return 1;
1576 return 0;
1579 void open_process_config(char *config, amd_cb_config *cb_config)
1581 FILE *config_handle;
1583 if (config) {
1584 config_handle = fopen(config, "r");
1585 if (config_handle == NULL) {
1586 fprintf(stderr, "Can not open file %s for reading: %s\n",
1587 config, strerror(errno));
1588 exit(1);
1590 if (process_config(config_handle, cb_config) == 0) {
1591 fprintf(stderr, "Configuration file %s parsing error\n",
1592 config);
1593 fclose(config_handle);
1594 exit(1);
1596 fclose(config_handle);
1599 /* For debug. */
1600 if (cb_config->debug) {
1601 dump_psp_firmwares(amd_psp_fw_table);
1602 dump_bdt_firmwares(amd_bios_table);
1606 static bool is_initial_alignment_required(enum platform soc_id)
1608 switch (soc_id) {
1609 case PLATFORM_MENDOCINO:
1610 case PLATFORM_PHOENIX:
1611 case PLATFORM_GLINDA:
1612 return false;
1613 default:
1614 return true;
1618 static bool needs_new_combo_layout(enum platform soc_id)
1620 return needs_ish(soc_id);
1623 int main(int argc, char **argv)
1625 int retval = 0;
1626 int combo_index = 0;
1627 int targetfd;
1628 context ctx = { 0 };
1629 uint32_t romsig_offset;
1630 amd_cb_config cb_config = {
1631 .efs_spi_readmode = 0xff, .efs_spi_speed = 0xff, .efs_spi_micron_flag = 0xff
1634 ctx.current_pointer_saved = 0xFFFFFFFF;
1636 retval = amdfwtool_getopt(argc, argv, &cb_config, &ctx);
1638 if (retval) {
1639 return retval;
1642 if (cb_config.use_combo) {
1643 ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
1644 ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
1645 memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
1646 memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
1649 open_process_config(cb_config.config, &cb_config);
1651 if (cb_config.use_combo && needs_new_combo_layout(cb_config.soc_id))
1652 cb_config.combo_new_rab = true;
1654 ctx.rom = malloc(ctx.rom_size);
1655 if (!ctx.rom) {
1656 fprintf(stderr, "Error: Failed to allocate memory\n");
1657 return 1;
1659 memset(ctx.rom, 0xFF, ctx.rom_size);
1661 romsig_offset = cb_config.efs_location ? cb_config.efs_location : AMD_ROMSIG_OFFSET;
1662 set_current_pointer(&ctx, romsig_offset);
1664 ctx.amd_romsig_ptr = BUFF_OFFSET(ctx, romsig_offset);
1665 ctx.amd_romsig_ptr->signature = EMBEDDED_FW_SIGNATURE;
1666 ctx.amd_romsig_ptr->imc_entry = 0;
1667 ctx.amd_romsig_ptr->gec_entry = 0;
1668 ctx.amd_romsig_ptr->xhci_entry = 0;
1670 if (cb_config.soc_id != PLATFORM_UNKNOWN) {
1671 retval = set_efs_table(cb_config.soc_id, &cb_config, ctx.amd_romsig_ptr);
1672 if (retval) {
1673 fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
1674 return retval;
1676 } else {
1677 fprintf(stderr, "WARNING: No SOC name specified.\n");
1680 if (cb_config.need_ish)
1681 ctx.address_mode = AMD_ADDR_REL_TAB;
1682 else if (cb_config.second_gen)
1683 ctx.address_mode = AMD_ADDR_REL_BIOS;
1684 else
1685 ctx.address_mode = AMD_ADDR_PHYSICAL;
1687 if (cb_config.efs_location != cb_config.body_location)
1688 set_current_pointer(&ctx, cb_config.body_location);
1689 else
1690 set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
1692 integrate_firmwares(&ctx, ctx.amd_romsig_ptr, amd_fw_table);
1694 if (is_initial_alignment_required(cb_config.soc_id)) {
1695 /* TODO: Check for older platforms. */
1696 adjust_current_pointer(&ctx, 0, 0x10000U);
1698 ctx.current_table = 0;
1700 /* If the tool is invoked with command-line options to keep the signed PSP
1701 binaries separate, process the signed binaries first. */
1702 if (cb_config.signed_output_file && cb_config.signed_start_addr)
1703 process_signed_psp_firmwares(cb_config.signed_output_file,
1704 amd_psp_fw_table,
1705 cb_config.signed_start_addr,
1706 cb_config.soc_id);
1708 if (cb_config.use_combo && !cb_config.combo_new_rab) {
1709 ctx.psp_combo_dir = new_combo_dir(&ctx, PSP2_COOKIE);
1711 adjust_current_pointer(&ctx, 0, 0x1000U);
1713 if (!cb_config.recovery_ab)
1714 ctx.bhd_combo_dir = new_combo_dir(&ctx, BHD2_COOKIE);
1717 combo_index = 0;
1718 if (cb_config.config)
1719 cb_config.combo_config[0] = cb_config.config;
1721 do {
1722 if (cb_config.use_combo && cb_config.debug)
1723 printf("Processing %dth combo entry\n", combo_index);
1725 /* The pspdir level 1 is special. For new combo layout, all the combo entries
1726 share one pspdir L1. It should not be cleared at each iteration. */
1727 if (!cb_config.combo_new_rab || combo_index == 0) {
1728 ctx.pspdir = NULL;
1729 ctx.pspdir_bak = NULL;
1731 ctx.pspdir2 = NULL;
1732 ctx.pspdir2_b = NULL;
1733 ctx.biosdir = NULL;
1734 ctx.biosdir2 = NULL;
1735 ctx.biosdir2_b = NULL;
1736 ctx.ish_a_dir = NULL;
1737 ctx.ish_b_dir = NULL;
1738 /* for non-combo image, combo_config[0] == config, and
1739 * it already is processed. Actually "combo_index >
1740 * 0" is enough. Put both of them here to make sure
1741 * and make it clear this will not affect non-combo
1742 * case.
1744 if (cb_config.use_combo && combo_index > 0) {
1745 /* Restore the table as clean data. */
1746 memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
1747 sizeof(amd_psp_fw_table));
1748 memcpy(amd_bios_table, ctx.amd_bios_table_clean,
1749 sizeof(amd_bios_table));
1750 assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
1751 open_process_config(cb_config.combo_config[combo_index], &cb_config);
1753 /* In most cases, the address modes are same. */
1754 if (cb_config.need_ish)
1755 ctx.address_mode = AMD_ADDR_REL_TAB;
1756 else if (cb_config.second_gen)
1757 ctx.address_mode = AMD_ADDR_REL_BIOS;
1758 else
1759 ctx.address_mode = AMD_ADDR_PHYSICAL;
1761 register_apcb_combo(&cb_config, combo_index, &ctx);
1764 if (cb_config.multi_level) {
1765 /* Do 2nd PSP directory followed by 1st */
1766 integrate_psp_firmwares(&ctx,
1767 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1768 if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
1769 /* Create a copy of PSP Directory 2 in the backup slot B.
1770 Related biosdir2_b copy will be created later. */
1771 integrate_psp_firmwares(&ctx,
1772 amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1773 } else {
1775 * Either the platform is using only
1776 * one slot or B is same as above
1777 * directories for A. Skip creating
1778 * pspdir2_b here to save flash space.
1779 * Related biosdir2_b will be skipped
1780 * automatically.
1782 ctx.pspdir2_b = NULL; /* More explicitly */
1784 if (!cb_config.combo_new_rab || combo_index == 0)
1785 integrate_psp_firmwares(&ctx,
1786 amd_psp_fw_table, PSP_COOKIE, &cb_config);
1787 integrate_psp_levels(&ctx, &cb_config);
1788 } else {
1789 /* flat: PSP 1 cookie and no pointer to 2nd table */
1790 integrate_psp_firmwares(&ctx,
1791 amd_psp_fw_table, PSP_COOKIE, &cb_config);
1794 if (!cb_config.use_combo || (cb_config.combo_new_rab && combo_index == 0)) {
1795 /* For new combo layout, there is only 1 PSP level 1 directory. */
1796 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.pspdir, &ctx, &cb_config);
1797 fill_psp_bak_directory_to_efs(ctx.amd_romsig_ptr, ctx.pspdir_bak, &ctx, &cb_config);
1798 } else if (cb_config.use_combo && !cb_config.combo_new_rab) {
1799 fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.psp_combo_dir, &ctx, &cb_config);
1800 add_combo_entry(ctx.psp_combo_dir, ctx.pspdir, combo_index, &ctx, &cb_config);
1803 if (have_bios_tables(amd_bios_table)) {
1804 if (cb_config.multi_level) {
1805 /* Do 2nd level BIOS directory followed by 1st */
1806 integrate_bios_firmwares(&ctx,
1807 amd_bios_table, BHDL2_COOKIE, &cb_config);
1808 if (cb_config.recovery_ab) {
1809 if (ctx.pspdir2_b != NULL) {
1810 integrate_bios_firmwares(&ctx,
1811 amd_bios_table, BHDL2_COOKIE,
1812 &cb_config);
1814 } else {
1815 integrate_bios_firmwares(&ctx,
1816 amd_bios_table, BHD_COOKIE, &cb_config);
1818 integrate_bios_levels(&ctx, &cb_config);
1819 } else {
1820 /* flat: BHD1 cookie and no pointer to 2nd table */
1821 integrate_bios_firmwares(&ctx,
1822 amd_bios_table, BHD_COOKIE, &cb_config);
1824 if (!cb_config.use_combo) {
1825 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.biosdir,
1826 &ctx, &cb_config);
1827 } else if (ctx.bhd_combo_dir != NULL) {
1828 /* In recovery A/B mode, there isn't a BHD combo directory.
1829 * Instead, the BIOS tables level 2 are linked by PSP tables.
1831 fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.bhd_combo_dir,
1832 &ctx, &cb_config);
1833 add_combo_entry(ctx.bhd_combo_dir, ctx.biosdir, combo_index, &ctx, &cb_config);
1836 if (cb_config.debug)
1837 dump_image_addresses(&ctx);
1838 } while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
1839 cb_config.combo_config[combo_index] != NULL);
1841 targetfd = open(cb_config.output, O_RDWR | O_CREAT | O_TRUNC, 0666);
1842 if (targetfd >= 0) {
1843 uint32_t offset = cb_config.efs_location;
1844 uint32_t bytes = cb_config.efs_location == cb_config.body_location ?
1845 ctx.current - offset : sizeof(embedded_firmware);
1846 uint32_t ret_bytes;
1848 ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
1849 if (bytes != ret_bytes) {
1850 fprintf(stderr, "Error: Writing to file %s failed\n", cb_config.output);
1851 retval = 1;
1853 close(targetfd);
1854 } else {
1855 fprintf(stderr, "Error: could not open file: %s\n", cb_config.output);
1856 retval = 1;
1859 if (cb_config.efs_location != cb_config.body_location) {
1860 ssize_t bytes;
1862 bytes = write_body(cb_config.output, BUFF_OFFSET(ctx, cb_config.body_location),
1863 ctx.current - cb_config.body_location);
1864 if (bytes != ctx.current - cb_config.body_location) {
1865 fprintf(stderr, "Error: Writing body\n");
1866 retval = 1;
1870 if (cb_config.manifest_file) {
1871 dump_blob_version(cb_config.manifest_file, amd_psp_fw_table);
1874 amdfwtool_cleanup(&ctx);
1875 return retval;