1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * ROMSIG At ROMBASE + 0x[0,2,4,8]20000:
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 * +------------+---------------+----------------+------------+
31 * | Other PSP Firmware |
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 |
44 * +------------+---------------+----------------+------------+ |
45 * | '2LP$' | Fletcher | Count | Reserved |<--+
46 * +------------+---------------+----------------+------------+
50 * | (2nd-level is not required on all families) |
52 * +------------+---------------+----------------+------------+
53 * BIOS Directory Table (BDT) is similar
56 * +------------+---------------+----------------+------------+
57 * | 'PSP2' | Fletcher | Count |Look up mode|
58 * +------------+---------------+----------------+------------+
60 * +------------+---------------+----------------+------------+
61 * | ID-Sel | PSP ID | PSPDIR ADDR | | 1st PSP directory
62 * +------------+---------------+----------------+------------+
63 * | ID-Sel | PSP ID | PSPDIR ADDR | | 2nd PSP directory
64 * +------------+---------------+----------------+------------+
68 * +------------+---------------+----------------+------------+
69 * BDT Combo is similar
72 #include <commonlib/bsd/helpers.h>
79 #include <sys/types.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
)
136 const uint16_t *pptr
= data
;
144 index
= length
>= 359 ? 359 : length
;
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
;
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
)
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
)
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
)
443 fprintf(stderr
, "Error: BIOS entries (%d) exceeds max allowed items "
444 "(%d)\n", count
, max
);
445 amdfwtool_cleanup(ctx
);
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
);
459 ctx
->current
= value
;
461 if (ctx
->current
> ctx
->rom_size
) {
462 fprintf(stderr
, "Error: Packing data causes overflow\n");
463 amdfwtool_cleanup(ctx
);
467 ctx
->current_pointer_saved
= ctx
->current
;
470 static void adjust_current_pointer(context
*ctx
, uint32_t add
, uint32_t align
)
473 set_current_pointer(ctx
, ALIGN_UP(ctx
->current
+ add
, align
));
476 static void *new_psp_dir(context
*ctx
, int multi
, uint32_t cookie
)
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.
486 adjust_current_pointer(ctx
, 0, TABLE_ERASE_ALIGNMENT
);
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
),
503 static void *new_ish_dir(context
*ctx
)
506 adjust_current_pointer(ctx
, 0, TABLE_ALIGNMENT
);
507 ptr
= BUFF_CURRENT(*ctx
);
508 adjust_current_pointer(ctx
, TABLE_ALIGNMENT
, 1);
513 static void *new_combo_dir(context
*ctx
, uint32_t cookie
)
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
),
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__
);
551 /* The table size needs to be 0x1000 aligned. So align the end of table. */
552 adjust_current_pointer(ctx
, 0, TABLE_ALIGNMENT
);
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]));
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
);
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
));
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
);
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
));
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
);
618 case PLATFORM_CEZANNE
:
619 case PLATFORM_MENDOCINO
:
620 case PLATFORM_PHOENIX
:
621 case PLATFORM_GLINDA
:
622 case PLATFORM_CARRIZO
:
623 case PLATFORM_STONEYRIDGE
:
625 case PLATFORM_PICASSO
:
626 case PLATFORM_LUCIENNE
:
627 case PLATFORM_RENOIR
:
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
);
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
:
653 if (!cb_config
->recovery_ab
)
654 amd_romsig
->bios3_entry
=
655 BUFF_TO_RUN_MODE(*ctx
, biosdir
, AMD_ADDR_REL_BIOS
);
657 case PLATFORM_MENDOCINO
:
658 case PLATFORM_PHOENIX
:
659 case PLATFORM_GLINDA
:
661 case PLATFORM_CARRIZO
:
662 case PLATFORM_STONEYRIDGE
:
664 case PLATFORM_PICASSO
:
666 amd_romsig
->bios1_entry
=
667 BUFF_TO_RUN_MODE(*ctx
, biosdir
, AMD_ADDR_REL_BIOS
);
672 static uint32_t get_psp_id(enum platform soc_id
)
677 case PLATFORM_PICASSO
:
680 case PLATFORM_RENOIR
:
681 case PLATFORM_LUCIENNE
:
684 case PLATFORM_CEZANNE
:
687 case PLATFORM_MENDOCINO
:
690 case PLATFORM_STONEYRIDGE
:
693 case PLATFORM_GLINDA
:
696 case PLATFORM_PHOENIX
:
702 case PLATFORM_CARRIZO
:
710 static void integrate_firmwares(context
*ctx
,
711 embedded_firmware
*romsig
,
712 amd_fw_entry
*fw_table
)
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
) {
723 adjust_current_pointer(ctx
, 0, 0x10000U
);
724 romsig
->imc_entry
= RUN_CURRENT(*ctx
);
727 romsig
->gec_entry
= RUN_CURRENT(*ctx
);
730 romsig
->xhci_entry
= RUN_CURRENT(*ctx
);
737 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
738 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
740 amdfwtool_cleanup(ctx
);
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
;
755 blob_fd
= open(fw_entry
->filename
, O_RDONLY
);
757 fprintf(stderr
, "Error opening file: %s: %s\n",
758 fw_entry
->filename
, strerror(errno
));
762 bytes
= read(blob_fd
, &hdr
, sizeof(hdr
));
763 if (bytes
!= sizeof(hdr
)) {
765 fprintf(stderr
, "Error while reading %s\n", fw_entry
->filename
);
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]);
777 static void dump_blob_version(char *manifest_file
, amd_fw_entry
*fw_table
)
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
));
789 for (index
= fw_table
; index
->type
!= AMD_FW_INVALID
; index
++) {
790 if (!(index
->filename
))
793 if (index
->generate_manifest
== true)
794 output_manifest(manifest_fd
, index
);
801 static void dump_psp_firmwares(amd_fw_entry
*fw_table
)
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
,
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
++) {
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
)
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;
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
;
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
));
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
;
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
,
927 integrate_psp_ab(ctx
, pspdir
, pspdir2
, ctx
->ish_a_dir
,
928 use_only_a
? AMD_FW_RECOVERYAB_A
: AMD_FW_RECOVERYAB_B
,
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
);
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
,
954 amd_cb_config
*cb_config
)
957 unsigned int i
, count
;
960 psp_directory_table
*pspdir
;
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
;
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
)
986 else if (cookie
== PSPL2_COOKIE
)
988 else if (cookie
== PSP_COOKIE
)
994 if (cookie
== PSPL2_COOKIE
)
996 else if (cookie
== PSP_COOKIE
)
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
))
1009 assert_fw_entry(count
, MAX_PSP_ENTRIES
, ctx
);
1011 if (fw_table
[i
].type
== AMD_TOKEN_UNLOCK
) {
1012 if (!fw_table
[i
].other
)
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
);
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;
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)
1036 size
= fw_table
[i
].size
;
1037 addr
= fw_table
[i
].dest
;
1038 if (addr
!= ALIGN_UP(addr
, ERASE_ALIGNMENT
)) {
1040 "Error: PSP NVRAM section not aligned with erase block size.\n\n");
1041 amdfwtool_cleanup(ctx
);
1045 adjust_current_pointer(ctx
, 0, ERASE_ALIGNMENT
);
1046 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
1047 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
1049 amdfwtool_cleanup(ctx
);
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
);
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
;
1076 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
1077 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
1079 amdfwtool_cleanup(ctx
);
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
;
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
;
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
)
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
;
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
)
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.
1145 adjust_current_pointer(ctx
, 0, TABLE_ERASE_ALIGNMENT
);
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
),
1160 static int locate_bdt2_bios(bios_directory_table
*level2
,
1161 uint64_t *source
, uint32_t *size
)
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
;
1180 static int have_bios_tables(amd_bios_entry
*table
)
1184 for (i
= 0 ; table
[i
].type
!= AMD_BIOS_INVALID
; i
++) {
1185 if (table
[i
].level
& BDT_LVL1
&& table
[i
].filename
)
1191 int find_bios_entry(amd_bios_type type
)
1195 for (i
= 0; amd_bios_table
[i
].type
!= AMD_BIOS_INVALID
; i
++) {
1196 if (amd_bios_table
[i
].type
== type
)
1202 static void add_bios_apcb_bk_entry(bios_directory_table
*biosdir
, unsigned int idx
,
1203 int inst
, uint32_t size
, uint64_t source
)
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
)
1213 if (amd_bios_table
[i
].type
!= AMD_BIOS_APCB_BK
)
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
)
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
,
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
=
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;
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
,
1272 amd_cb_config
*cb_config
)
1275 unsigned int i
, count
;
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
)
1302 else if (cookie
== BHDL2_COOKIE
)
1304 else if (cookie
== BHD_COOKIE
)
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
))
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
))
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
)
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
);
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
);
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
);
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
);
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
))
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
) {
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
);
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
);
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
;
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);
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
;
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
)
1442 bytes
= copy_blob(BUFF_CURRENT(*ctx
),
1443 fw_table
[i
].filename
, BUFF_ROOM(*ctx
));
1445 amdfwtool_cleanup(ctx
);
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
);
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
;
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
));
1468 amdfwtool_cleanup(ctx
);
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
;
1481 add_bios_apcb_bk_entry(biosdir
, count
, fw_table
[i
].inst
, size
, source
);
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");
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;
1521 amd_romsig
->efs_gen
.gen
= EFS_BEFORE_SECOND_GEN
;
1522 amd_romsig
->efs_gen
.reserved
= ~0;
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
;
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
) {
1537 amd_romsig
->qpr_dummy_cycle_f17_mod_00_2f
= 0xff;
1540 amd_romsig
->qpr_dummy_cycle_f17_mod_00_2f
= 0xa;
1543 fprintf(stderr
, "Error: EFS Micron flag must be correctly set.\n\n");
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
) {
1558 amd_romsig
->micron_detect_f17_mod_30_3f
= 0xff;
1561 amd_romsig
->micron_detect_f17_mod_30_3f
= 0xaa;
1564 amd_romsig
->micron_detect_f17_mod_30_3f
= 0x55;
1567 fprintf(stderr
, "Error: EFS Micron flag must be correctly set.\n\n");
1571 case PLATFORM_UNKNOWN
:
1573 fprintf(stderr
, "Error: Invalid SOC name.\n\n");
1579 void open_process_config(char *config
, amd_cb_config
*cb_config
)
1581 FILE *config_handle
;
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
));
1590 if (process_config(config_handle
, cb_config
) == 0) {
1591 fprintf(stderr
, "Configuration file %s parsing error\n",
1593 fclose(config_handle
);
1596 fclose(config_handle
);
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
)
1609 case PLATFORM_MENDOCINO
:
1610 case PLATFORM_PHOENIX
:
1611 case PLATFORM_GLINDA
:
1618 static bool needs_new_combo_layout(enum platform soc_id
)
1620 return needs_ish(soc_id
);
1623 int main(int argc
, char **argv
)
1626 int combo_index
= 0;
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
);
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
);
1656 fprintf(stderr
, "Error: Failed to allocate memory\n");
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
);
1673 fprintf(stderr
, "ERROR: Failed to initialize EFS table!\n");
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
;
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
);
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
,
1705 cb_config
.signed_start_addr
,
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
);
1718 if (cb_config
.config
)
1719 cb_config
.combo_config
[0] = cb_config
.config
;
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) {
1729 ctx
.pspdir_bak
= NULL
;
1732 ctx
.pspdir2_b
= 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
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
;
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
);
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
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
);
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
,
1815 integrate_bios_firmwares(&ctx
,
1816 amd_bios_table
, BHD_COOKIE
, &cb_config
);
1818 integrate_bios_levels(&ctx
, &cb_config
);
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
,
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
,
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
);
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
);
1855 fprintf(stderr
, "Error: could not open file: %s\n", cb_config
.output
);
1859 if (cb_config
.efs_location
!= cb_config
.body_location
) {
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");
1870 if (cb_config
.manifest_file
) {
1871 dump_blob_version(cb_config
.manifest_file
, amd_psp_fw_table
);
1874 amdfwtool_cleanup(&ctx
);