xref: /aosp_15_r20/external/coreboot/util/amdfwtool/amdfwtool.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
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
14  *
15  *  EC ROM should be 64K aligned.
16  *
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
54  *
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
70  */
71 
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>
85 
86 #include "amdfwtool.h"
87 
88 #define AMD_ROMSIG_OFFSET	0x20000
89 
90 #define _MAX(A, B) (((A) > (B)) ? (A) : (B))
91 
92 static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry);
93 
94 /*
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.
101  *
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.
106  *
107  * TODO: Future work may require fully implementing the PSP_COMBO feature.
108  */
109 
110 /*
111  * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
112  * The checksum field of the passed PDU does not need to be reset to zero.
113  *
114  * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
115  * Lawrence Livermore Labs.  The Fletcher Checksum was proposed as an
116  * alternative to cyclical redundancy checks because it provides error-
117  * detection properties similar to cyclical redundancy checks but at the
118  * cost of a simple summation technique.  Its characteristics were first
119  * published in IEEE Transactions on Communications in January 1982.  One
120  * version has been adopted by ISO for use in the class-4 transport layer
121  * of the network protocol.
122  *
123  * This program expects:
124  *    stdin:    The input file to compute a checksum for.  The input file
125  *              not be longer than 256 bytes.
126  *    stdout:   Copied from the input file with the Fletcher's Checksum
127  *              inserted 8 bytes after the beginning of the file.
128  *    stderr:   Used to print out error messages.
129  */
fletcher32(const void * data,int length)130 static uint32_t fletcher32(const void *data, int length)
131 {
132 	uint32_t c0;
133 	uint32_t c1;
134 	uint32_t checksum;
135 	int index;
136 	const uint16_t *pptr = data;
137 
138 	length /= 2;
139 
140 	c0 = 0xFFFF;
141 	c1 = 0xFFFF;
142 
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);
152 	}
153 
154 	/* Sums[0,1] mod 64K + overflow */
155 	c0 = (c0 & 0xFFFF) + (c0 >> 16);
156 	c1 = (c1 & 0xFFFF) + (c1 >> 16);
157 	checksum = (c1 << 16) | c0;
158 
159 	return checksum;
160 }
161 
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 },
258 };
259 
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 },
265 };
266 
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 },
364 };
365 
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)
391 
392 
free_psp_firmware_filenames(amd_fw_entry * fw_table)393 static void free_psp_firmware_filenames(amd_fw_entry *fw_table)
394 {
395 	amd_fw_entry *index;
396 
397 	for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
398 		if (index->filename &&
399 				index->type != AMD_FW_VERSTAGE_SIG &&
400 				index->type != AMD_FW_PSP_VERSTAGE &&
401 				index->type != AMD_FW_SPL &&
402 				index->type != AMD_FW_PSP_WHITELIST) {
403 			free(index->filename);
404 			index->filename = NULL;
405 		}
406 	}
407 }
408 
free_bdt_firmware_filenames(amd_bios_entry * fw_table)409 static void free_bdt_firmware_filenames(amd_bios_entry *fw_table)
410 {
411 	amd_bios_entry *index;
412 
413 	for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
414 		if (index->filename &&
415 				index->type != AMD_BIOS_APCB &&
416 				index->type != AMD_BIOS_BIN &&
417 				index->type != AMD_BIOS_APCB_BK &&
418 				index->type != AMD_BIOS_UCODE) {
419 			free(index->filename);
420 			index->filename = NULL;
421 		}
422 	}
423 }
424 
amdfwtool_cleanup(context * ctx)425 static void amdfwtool_cleanup(context *ctx)
426 {
427 	free(ctx->rom);
428 	ctx->rom = NULL;
429 
430 	/* Free the filename. */
431 	free_psp_firmware_filenames(amd_psp_fw_table);
432 	free_bdt_firmware_filenames(amd_bios_table);
433 
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;
438 }
439 
assert_fw_entry(uint32_t count,uint32_t max,context * ctx)440 void assert_fw_entry(uint32_t count, uint32_t max, context *ctx)
441 {
442 	if (count >= max) {
443 		fprintf(stderr, "Error: BIOS entries (%d) exceeds max allowed items "
444 			"(%d)\n", count, max);
445 		amdfwtool_cleanup(ctx);
446 		exit(1);
447 	}
448 }
449 
set_current_pointer(context * ctx,uint32_t value)450 static void set_current_pointer(context *ctx, uint32_t value)
451 {
452 	if (ctx->current_pointer_saved != 0xFFFFFFFF &&
453 			ctx->current_pointer_saved != ctx->current) {
454 		fprintf(stderr, "Error: The pointer is changed elsewhere\n");
455 		amdfwtool_cleanup(ctx);
456 		exit(1);
457 	}
458 
459 	ctx->current = value;
460 
461 	if (ctx->current > ctx->rom_size) {
462 		fprintf(stderr, "Error: Packing data causes overflow\n");
463 		amdfwtool_cleanup(ctx);
464 		exit(1);
465 	}
466 
467 	ctx->current_pointer_saved = ctx->current;
468 }
469 
adjust_current_pointer(context * ctx,uint32_t add,uint32_t align)470 static void adjust_current_pointer(context *ctx, uint32_t add, uint32_t align)
471 {
472 	/* Get */
473 	set_current_pointer(ctx, ALIGN_UP(ctx->current + add, align));
474 }
475 
new_psp_dir(context * ctx,int multi,uint32_t cookie)476 static void *new_psp_dir(context *ctx, int multi, uint32_t cookie)
477 {
478 	void *ptr;
479 
480 	/*
481 	 * Force both onto boundary when multi.  Primary table is after
482 	 * updatable table, so alignment ensures primary can stay intact
483 	 * if secondary is reprogrammed.
484 	 */
485 	if (multi)
486 		adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
487 	else
488 		adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
489 
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 	adjust_current_pointer(ctx,
496 		sizeof(psp_directory_header) + MAX_PSP_ENTRIES * sizeof(psp_directory_entry),
497 		1);
498 	return ptr;
499 }
500 
new_ish_dir(context * ctx)501 static void *new_ish_dir(context *ctx)
502 {
503 	void *ptr;
504 	adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
505 	ptr = BUFF_CURRENT(*ctx);
506 	adjust_current_pointer(ctx, TABLE_ALIGNMENT, 1);
507 
508 	return ptr;
509 }
510 
new_combo_dir(context * ctx,uint32_t cookie)511 static void *new_combo_dir(context *ctx, uint32_t cookie)
512 {
513 	void *ptr;
514 
515 	adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
516 	ptr = BUFF_CURRENT(*ctx);
517 	((psp_combo_header *)ptr)->cookie = cookie;
518 	adjust_current_pointer(ctx,
519 		sizeof(psp_combo_header) + MAX_COMBO_ENTRIES * sizeof(psp_combo_entry),
520 		1);
521 	return ptr;
522 }
523 
fill_dir_header(void * directory,uint32_t count,context * ctx)524 static void fill_dir_header(void *directory, uint32_t count, context *ctx)
525 {
526 	psp_combo_directory *cdir = directory;
527 	psp_directory_table *dir = directory;
528 	bios_directory_table *bdir = directory;
529 	/* The cookies have same offsets. */
530 	uint32_t cookie = ((psp_directory_table *)directory)->header.cookie;
531 	uint32_t table_size = 0;
532 
533 	if (ctx == NULL || directory == NULL) {
534 		fprintf(stderr, "Calling %s with NULL pointers\n", __func__);
535 		return;
536 	}
537 
538 	/* The table size needs to be 0x1000 aligned. So align the end of table. */
539 	adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
540 
541 	switch (cookie) {
542 	case PSP2_COOKIE:
543 	case BHD2_COOKIE:
544 		/* lookup mode is hardcoded for now. */
545 		cdir->header.lookup = 1;
546 		cdir->header.num_entries = count;
547 		cdir->header.reserved[0] = 0;
548 		cdir->header.reserved[1] = 0;
549 		/* checksum everything that comes after the Checksum field */
550 		cdir->header.checksum = fletcher32(&cdir->header.num_entries,
551 					count * sizeof(psp_combo_entry)
552 					+ sizeof(cdir->header.num_entries)
553 					+ sizeof(cdir->header.lookup)
554 					+ 2 * sizeof(cdir->header.reserved[0]));
555 		break;
556 	case PSP_COOKIE:
557 	case PSPL2_COOKIE:
558 		/* The table size is only set once. Later calls only update
559 		 * the count and fletcher. So does the BIOS table. */
560 		if (dir->header.additional_info_fields.dir_size == 0) {
561 			table_size = ctx->current - ctx->current_table;
562 			if ((table_size % TABLE_ALIGNMENT) != 0 &&
563 				(table_size / TABLE_ALIGNMENT) != 0) {
564 				fprintf(stderr, "The PSP table size should be 4K aligned\n");
565 				amdfwtool_cleanup(ctx);
566 				exit(1);
567 			}
568 			dir->header.additional_info_fields.dir_size =
569 					table_size / TABLE_ALIGNMENT;
570 		}
571 		dir->header.num_entries = count;
572 		dir->header.additional_info_fields.spi_block_size = 1;
573 		dir->header.additional_info_fields.base_addr = 0;
574 		/* checksum everything that comes after the Checksum field */
575 		dir->header.checksum = fletcher32(&dir->header.num_entries,
576 					count * sizeof(psp_directory_entry)
577 					+ sizeof(dir->header.num_entries)
578 					+ sizeof(dir->header.additional_info));
579 		break;
580 	case BHD_COOKIE:
581 	case BHDL2_COOKIE:
582 		if (bdir->header.additional_info_fields.dir_size == 0) {
583 			table_size = ctx->current - ctx->current_table;
584 			if ((table_size % TABLE_ALIGNMENT) != 0 &&
585 				table_size / TABLE_ALIGNMENT != 0) {
586 				fprintf(stderr, "The BIOS table size should be 4K aligned\n");
587 				amdfwtool_cleanup(ctx);
588 				exit(1);
589 			}
590 			bdir->header.additional_info_fields.dir_size =
591 				table_size / TABLE_ALIGNMENT;
592 		}
593 		bdir->header.num_entries = count;
594 		bdir->header.additional_info_fields.spi_block_size = 1;
595 		bdir->header.additional_info_fields.base_addr = 0;
596 		/* checksum everything that comes after the Checksum field */
597 		bdir->header.checksum = fletcher32(&bdir->header.num_entries,
598 					count * sizeof(bios_directory_entry)
599 					+ sizeof(bdir->header.num_entries)
600 					+ sizeof(bdir->header.additional_info));
601 		break;
602 	}
603 
604 }
605 
fill_psp_directory_to_efs(embedded_firmware * amd_romsig,void * pspdir,context * ctx,amd_cb_config * cb_config)606 static void fill_psp_directory_to_efs(embedded_firmware *amd_romsig, void *pspdir,
607 	context *ctx, amd_cb_config *cb_config)
608 {
609 	switch (cb_config->soc_id) {
610 	case PLATFORM_UNKNOWN:
611 		amd_romsig->psp_directory =
612 			BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
613 		break;
614 	case PLATFORM_CEZANNE:
615 	case PLATFORM_MENDOCINO:
616 	case PLATFORM_PHOENIX:
617 	case PLATFORM_GLINDA:
618 	case PLATFORM_CARRIZO:
619 	case PLATFORM_STONEYRIDGE:
620 	case PLATFORM_RAVEN:
621 	case PLATFORM_PICASSO:
622 	case PLATFORM_LUCIENNE:
623 	case PLATFORM_RENOIR:
624 	case PLATFORM_GENOA:
625 	default:
626 		/* for combo, it is also combo_psp_directory */
627 		amd_romsig->new_psp_directory =
628 			BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
629 		break;
630 	}
631 }
632 
fill_bios_directory_to_efs(embedded_firmware * amd_romsig,void * biosdir,context * ctx,amd_cb_config * cb_config)633 static void fill_bios_directory_to_efs(embedded_firmware *amd_romsig, void *biosdir,
634 	context *ctx, amd_cb_config *cb_config)
635 {
636 	switch (cb_config->soc_id) {
637 	case PLATFORM_RENOIR:
638 	case PLATFORM_LUCIENNE:
639 	case PLATFORM_CEZANNE:
640 	case PLATFORM_GENOA:
641 		if (!cb_config->recovery_ab)
642 			amd_romsig->bios3_entry =
643 				BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
644 		break;
645 	case PLATFORM_MENDOCINO:
646 	case PLATFORM_PHOENIX:
647 	case PLATFORM_GLINDA:
648 		break;
649 	case PLATFORM_CARRIZO:
650 	case PLATFORM_STONEYRIDGE:
651 	case PLATFORM_RAVEN:
652 	case PLATFORM_PICASSO:
653 	default:
654 		amd_romsig->bios1_entry =
655 			BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
656 		break;
657 	}
658 }
659 
get_psp_id(enum platform soc_id)660 static uint32_t get_psp_id(enum platform soc_id)
661 {
662 	uint32_t psp_id;
663 	switch (soc_id) {
664 	case PLATFORM_RAVEN:
665 	case PLATFORM_PICASSO:
666 		psp_id = 0xBC0A0000;
667 		break;
668 	case PLATFORM_RENOIR:
669 	case PLATFORM_LUCIENNE:
670 		psp_id = 0xBC0C0000;
671 		break;
672 	case PLATFORM_CEZANNE:
673 		psp_id = 0xBC0C0140;
674 		break;
675 	case PLATFORM_MENDOCINO:
676 		psp_id = 0xBC0D0900;
677 		break;
678 	case PLATFORM_STONEYRIDGE:
679 		psp_id = 0x10220B00;
680 		break;
681 	case PLATFORM_GLINDA:
682 		psp_id = 0xBC0E0200;
683 		break;
684 	case PLATFORM_PHOENIX:
685 		psp_id = 0xBC0D0400;
686 		break;
687 	case PLATFORM_GENOA:
688 		psp_id = 0xBC0C0111;
689 		break;
690 	case PLATFORM_CARRIZO:
691 	default:
692 		psp_id = 0;
693 		break;
694 	}
695 	return psp_id;
696 }
697 
integrate_firmwares(context * ctx,embedded_firmware * romsig,amd_fw_entry * fw_table)698 static void integrate_firmwares(context *ctx,
699 				embedded_firmware *romsig,
700 				amd_fw_entry *fw_table)
701 {
702 	ssize_t bytes;
703 	uint32_t i;
704 
705 	adjust_current_pointer(ctx, 0, BLOB_ALIGNMENT);
706 
707 	for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
708 		if (fw_table[i].filename != NULL) {
709 			switch (fw_table[i].type) {
710 			case AMD_FW_IMC:
711 				adjust_current_pointer(ctx, 0, 0x10000U);
712 				romsig->imc_entry = RUN_CURRENT(*ctx);
713 				break;
714 			case AMD_FW_GEC:
715 				romsig->gec_entry = RUN_CURRENT(*ctx);
716 				break;
717 			case AMD_FW_XHCI:
718 				romsig->xhci_entry = RUN_CURRENT(*ctx);
719 				break;
720 			default:
721 				/* Error */
722 				break;
723 			}
724 
725 			bytes = copy_blob(BUFF_CURRENT(*ctx),
726 					fw_table[i].filename, BUFF_ROOM(*ctx));
727 			if (bytes < 0) {
728 				amdfwtool_cleanup(ctx);
729 				exit(1);
730 			}
731 
732 			adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
733 		}
734 	}
735 }
736 
output_manifest(int manifest_fd,amd_fw_entry * fw_entry)737 static void output_manifest(int manifest_fd, amd_fw_entry *fw_entry)
738 {
739 	struct amd_fw_header hdr;
740 	int blob_fd;
741 	ssize_t bytes;
742 
743 	blob_fd = open(fw_entry->filename, O_RDONLY);
744 	if (blob_fd < 0) {
745 		fprintf(stderr, "Error opening file: %s: %s\n",
746 		       fw_entry->filename, strerror(errno));
747 		return;
748 	}
749 
750 	bytes = read(blob_fd, &hdr, sizeof(hdr));
751 	if (bytes != sizeof(hdr)) {
752 		close(blob_fd);
753 		fprintf(stderr, "Error while reading %s\n", fw_entry->filename);
754 		return;
755 	}
756 
757 	dprintf(manifest_fd, "type: 0x%02x ver:%02x.%02x.%02x.%02x\n",
758 	    fw_entry->type, hdr.version[3], hdr.version[2],
759 	    hdr.version[1], hdr.version[0]);
760 
761 	close(blob_fd);
762 
763 }
764 
dump_blob_version(char * manifest_file,amd_fw_entry * fw_table)765 static void dump_blob_version(char *manifest_file, amd_fw_entry *fw_table)
766 {
767 	amd_fw_entry *index;
768 	int manifest_fd;
769 
770 	manifest_fd = open(manifest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
771 	if (manifest_fd < 0) {
772 		fprintf(stderr, "Error opening file: %s: %s\n",
773 		       manifest_file, strerror(errno));
774 		return;
775 	}
776 
777 	for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
778 		if (!(index->filename))
779 			continue;
780 
781 		if (index->generate_manifest == true)
782 			output_manifest(manifest_fd, index);
783 	}
784 
785 	close(manifest_fd);
786 }
787 
788 /* For debugging */
dump_psp_firmwares(amd_fw_entry * fw_table)789 static void dump_psp_firmwares(amd_fw_entry *fw_table)
790 {
791 	amd_fw_entry *index;
792 
793 	printf("PSP firmware components:\n");
794 	for (index = fw_table; index->type != AMD_FW_INVALID; index++) {
795 		if (index->type == AMD_PSP_FUSE_CHAIN)
796 			printf("  %2x: level=%x, subprog=%x, inst=%x\n",
797 				index->type, index->level, index->subprog, index->inst);
798 		else if (index->filename)
799 			printf("  %2x: level=%x, subprog=%x, inst=%x, %s\n",
800 				index->type, index->level, index->subprog, index->inst,
801 				index->filename);
802 	}
803 }
804 
dump_bdt_firmwares(amd_bios_entry * fw_table)805 static void dump_bdt_firmwares(amd_bios_entry *fw_table)
806 {
807 	amd_bios_entry *index;
808 
809 	printf("BIOS Directory Table (BDT) components:\n");
810 	for (index = fw_table; index->type != AMD_BIOS_INVALID; index++) {
811 		if (index->filename)
812 			printf("  %2x: level=%x, %s\n",
813 				index->type, index->level, index->filename);
814 	}
815 }
816 
dump_image_addresses(context * ctx)817 static void dump_image_addresses(context *ctx)
818 {
819 	printf("romsig offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->amd_romsig_ptr));
820 	printf("PSP L1 offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir));
821 	if (ctx->pspdir2 != NULL)
822 		printf("PSP L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2));
823 	if (ctx->ish_a_dir != NULL)
824 		printf("ISHA offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_a_dir));
825 	if (ctx->ish_b_dir != NULL)
826 		printf("ISHB offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->ish_b_dir));
827 	if (ctx->pspdir2_b != NULL)
828 		printf("PSP L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->pspdir2_b));
829 	if (ctx->biosdir != NULL)
830 		printf("BHD offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir));
831 	if (ctx->biosdir2 != NULL)
832 		printf("BHD L2(A) offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2));
833 	if (ctx->biosdir2_b != NULL)
834 		printf("BHD L2B offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->biosdir2_b));
835 	if (ctx->psp_combo_dir != NULL)
836 		printf("PSP combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->psp_combo_dir));
837 	if (ctx->bhd_combo_dir != NULL)
838 		printf("BHD combo offset:%lx\n", BUFF_TO_RUN(*ctx, ctx->bhd_combo_dir));
839 }
840 
integrate_psp_ab(context * ctx,psp_directory_table * pspdir,psp_directory_table * pspdir2,ish_directory_table * ish,amd_fw_type ab,enum platform soc_id)841 static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
842 		psp_directory_table *pspdir2, ish_directory_table *ish,
843 		amd_fw_type ab, enum platform soc_id)
844 {
845 	uint32_t count;
846 	uint32_t current_table_save;
847 
848 	current_table_save = ctx->current_table;
849 	ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
850 	count = pspdir->header.num_entries;
851 	assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
852 	pspdir->entries[count].type = (uint8_t)ab;
853 	pspdir->entries[count].subprog = 0;
854 	pspdir->entries[count].rsvd = 0;
855 	if (ish != NULL) {
856 		ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
857 		ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1;
858 		ish->update_retry_count = 2;
859 		ish->glitch_retry_count = 0;
860 		ish->psp_id = get_psp_id(soc_id);
861 		ish->checksum = fletcher32(&ish->boot_priority,
862 				sizeof(ish_directory_table) - sizeof(uint32_t));
863 		pspdir->entries[count].addr =
864 				BUFF_TO_RUN_MODE(*ctx, ish, AMD_ADDR_REL_BIOS);
865 		pspdir->entries[count].address_mode =
866 				SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
867 		pspdir->entries[count].size = TABLE_ALIGNMENT;
868 	} else {
869 		pspdir->entries[count].addr =
870 				BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
871 		pspdir->entries[count].address_mode =
872 				SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
873 		pspdir->entries[count].size = _MAX(TABLE_ALIGNMENT,
874 				pspdir2->header.num_entries *
875 				sizeof(psp_directory_entry) +
876 				sizeof(psp_directory_header));
877 	}
878 
879 	count++;
880 	fill_dir_header(pspdir, count, ctx);
881 	ctx->current_table = current_table_save;
882 }
883 
integrate_psp_levels(context * ctx,amd_cb_config * cb_config)884 static void integrate_psp_levels(context *ctx,
885 				amd_cb_config *cb_config)
886 {
887 	uint32_t current_table_save;
888 	bool recovery_ab = cb_config->recovery_ab;
889 	unsigned int count;
890 	psp_directory_table *pspdir, *pspdir2, *pspdir2_b;
891 	bool use_only_a = (cb_config->soc_id == PLATFORM_PHOENIX); /* TODO: b:285390041 */
892 
893 	pspdir = ctx->pspdir;
894 	pspdir2 = ctx->pspdir2;
895 	pspdir2_b = ctx->pspdir2_b;
896 	count = pspdir->header.num_entries;
897 
898 	current_table_save = ctx->current_table;
899 	ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
900 	if (recovery_ab && (pspdir2 != NULL)) {
901 		if (cb_config->need_ish) {	/* Need ISH */
902 			ctx->ish_a_dir = new_ish_dir(ctx);
903 			if (pspdir2_b != NULL)
904 				ctx->ish_b_dir = new_ish_dir(ctx);
905 		}
906 		integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
907 			AMD_FW_RECOVERYAB_A, cb_config->soc_id);
908 		if (pspdir2_b != NULL)
909 			integrate_psp_ab(ctx, pspdir, pspdir2_b, ctx->ish_b_dir,
910 				use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
911 				cb_config->soc_id);
912 		else
913 			integrate_psp_ab(ctx, pspdir, pspdir2, ctx->ish_a_dir,
914 				use_only_a ? AMD_FW_RECOVERYAB_A : AMD_FW_RECOVERYAB_B,
915 				cb_config->soc_id);
916 
917 	} else if (pspdir2 != NULL) {
918 		assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
919 		pspdir->entries[count].type = AMD_FW_L2_PTR;
920 		pspdir->entries[count].subprog = 0;
921 		pspdir->entries[count].rsvd = 0;
922 		pspdir->entries[count].size = sizeof(pspdir2->header)
923 					+ pspdir2->header.num_entries
924 					* sizeof(psp_directory_entry);
925 
926 		pspdir->entries[count].addr =
927 				BUFF_TO_RUN_MODE(*ctx, pspdir2, AMD_ADDR_REL_BIOS);
928 		pspdir->entries[count].address_mode =
929 				SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
930 		count++;
931 		fill_dir_header(pspdir, count, ctx);
932 	}
933 	ctx->current_table = current_table_save;
934 }
935 
integrate_psp_firmwares(context * ctx,amd_fw_entry * fw_table,uint32_t cookie,amd_cb_config * cb_config)936 static void integrate_psp_firmwares(context *ctx,
937 					amd_fw_entry *fw_table,
938 					uint32_t cookie,
939 					amd_cb_config *cb_config)
940 {
941 	ssize_t bytes;
942 	unsigned int i, count;
943 	int level;
944 	uint32_t size;
945 	psp_directory_table *pspdir;
946 	uint64_t addr;
947 	uint32_t current_table_save;
948 	bool recovery_ab = cb_config->recovery_ab;
949 
950 	/* This function can create a primary table, a secondary table, or a
951 	 * flattened table which contains all applicable types.  These if-else
952 	 * statements infer what the caller intended.  If a 2nd-level cookie
953 	 * is passed, clearly a 2nd-level table is intended.  However, a
954 	 * 1st-level cookie may indicate level 1 or flattened.
955 	 */
956 	pspdir = new_psp_dir(ctx, cb_config->multi_level, cookie);
957 
958 	if (cookie == PSP_COOKIE)
959 		ctx->pspdir = pspdir;
960 	else if (cookie == PSPL2_COOKIE) {
961 		if (ctx->pspdir2 == NULL)
962 			ctx->pspdir2 = pspdir;
963 		else if (ctx->pspdir2_b == NULL)
964 			ctx->pspdir2_b = pspdir;
965 	}
966 
967 	if (!cb_config->multi_level)
968 		level = PSP_BOTH;
969 	else if (cookie == PSPL2_COOKIE)
970 		level = PSP_LVL2;
971 	else if (cookie == PSP_COOKIE)
972 		level = PSP_LVL1;
973 	else
974 		level = PSP_BOTH;
975 
976 	if (recovery_ab) {
977 		if (cookie == PSPL2_COOKIE)
978 			level = PSP_LVL2_AB;
979 		else if (cookie == PSP_COOKIE)
980 			level = PSP_LVL1_AB;
981 		else
982 			level = PSP_BOTH_AB;
983 	}
984 	current_table_save = ctx->current_table;
985 	ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
986 	adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
987 
988 	for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
989 		if (!(fw_table[i].level & level))
990 			continue;
991 
992 		assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
993 
994 		if (fw_table[i].type == AMD_TOKEN_UNLOCK) {
995 			if (!fw_table[i].other)
996 				continue;
997 			adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
998 			pspdir->entries[count].type = fw_table[i].type;
999 			pspdir->entries[count].size = 4096; /* TODO: doc? */
1000 			pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1001 			pspdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1002 			pspdir->entries[count].subprog = fw_table[i].subprog;
1003 			pspdir->entries[count].rsvd = 0;
1004 			adjust_current_pointer(ctx, 4096, 0x100U);
1005 			count++;
1006 		} else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
1007 			pspdir->entries[count].type = fw_table[i].type;
1008 			pspdir->entries[count].subprog = fw_table[i].subprog;
1009 			pspdir->entries[count].rsvd = 0;
1010 			pspdir->entries[count].size = 0xFFFFFFFF;
1011 			pspdir->entries[count].addr = fw_table[i].other;
1012 			pspdir->entries[count].address_mode = 0;
1013 			count++;
1014 		} else if (fw_table[i].type == AMD_FW_PSP_NVRAM) {
1015 			if (fw_table[i].filename == NULL) {
1016 				if (fw_table[i].size == 0)
1017 					continue;
1018 				size = fw_table[i].size;
1019 				addr = fw_table[i].dest;
1020 				if (addr != ALIGN_UP(addr, ERASE_ALIGNMENT)) {
1021 					fprintf(stderr,
1022 						"Error: PSP NVRAM section not aligned with erase block size.\n\n");
1023 					amdfwtool_cleanup(ctx);
1024 					exit(1);
1025 				}
1026 			} else {
1027 				adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1028 				bytes = copy_blob(BUFF_CURRENT(*ctx),
1029 						fw_table[i].filename, BUFF_ROOM(*ctx));
1030 				if (bytes <= 0) {
1031 					amdfwtool_cleanup(ctx);
1032 					exit(1);
1033 				}
1034 
1035 				size = ALIGN_UP(bytes, ERASE_ALIGNMENT);
1036 				addr = RUN_CURRENT(*ctx);
1037 				adjust_current_pointer(ctx, bytes, BLOB_ERASE_ALIGNMENT);
1038 			}
1039 
1040 			pspdir->entries[count].type = fw_table[i].type;
1041 			pspdir->entries[count].subprog = fw_table[i].subprog;
1042 			pspdir->entries[count].rsvd = 0;
1043 			pspdir->entries[count].size = size;
1044 			pspdir->entries[count].addr = addr;
1045 
1046 			pspdir->entries[count].address_mode =
1047 				SET_ADDR_MODE(pspdir, AMD_ADDR_REL_BIOS);
1048 
1049 			count++;
1050 		} else if (fw_table[i].filename != NULL) {
1051 			if (fw_table[i].addr_signed) {
1052 				pspdir->entries[count].addr =
1053 					RUN_OFFSET(*ctx, fw_table[i].addr_signed);
1054 				pspdir->entries[count].address_mode =
1055 							SET_ADDR_MODE_BY_TABLE(pspdir);
1056 				bytes = fw_table[i].file_size;
1057 			} else {
1058 				bytes = copy_blob(BUFF_CURRENT(*ctx),
1059 						fw_table[i].filename, BUFF_ROOM(*ctx));
1060 				if (bytes < 0) {
1061 					amdfwtool_cleanup(ctx);
1062 					exit(1);
1063 				}
1064 				pspdir->entries[count].addr = RUN_CURRENT(*ctx);
1065 				pspdir->entries[count].address_mode =
1066 							SET_ADDR_MODE_BY_TABLE(pspdir);
1067 				adjust_current_pointer(ctx, bytes, BLOB_ALIGNMENT);
1068 			}
1069 
1070 			pspdir->entries[count].type = fw_table[i].type;
1071 			pspdir->entries[count].subprog = fw_table[i].subprog;
1072 			pspdir->entries[count].rsvd = 0;
1073 			pspdir->entries[count].inst = fw_table[i].inst;
1074 			pspdir->entries[count].size = (uint32_t)bytes;
1075 
1076 			count++;
1077 		} else {
1078 			/* This APU doesn't have this firmware. */
1079 		}
1080 	}
1081 
1082 	fill_dir_header(pspdir, count, ctx);
1083 	ctx->current_table = current_table_save;
1084 }
1085 
add_psp_firmware_entry(context * ctx,psp_directory_table * pspdir,void * table,amd_fw_type type,uint32_t size)1086 static void add_psp_firmware_entry(context *ctx,
1087 					psp_directory_table *pspdir,
1088 					void *table, amd_fw_type type, uint32_t size)
1089 {
1090 	uint32_t count = pspdir->header.num_entries;
1091 	uint32_t index;
1092 	uint32_t current_table_save;
1093 
1094 	current_table_save = ctx->current_table;
1095 	ctx->current_table = BUFF_TO_RUN_MODE(*ctx, pspdir, AMD_ADDR_REL_BIOS);
1096 
1097 	/* If there is an entry of "type", replace it. */
1098 	for (index = 0; index < count; index++) {
1099 		if (pspdir->entries[index].type == (uint8_t)type)
1100 			break;
1101 	}
1102 
1103 	assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
1104 	pspdir->entries[index].type = (uint8_t)type;
1105 	pspdir->entries[index].subprog = 0;
1106 	pspdir->entries[index].rsvd = 0;
1107 	pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table);
1108 	pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir);
1109 	pspdir->entries[index].size = size;
1110 	if (index == count)
1111 		count++;
1112 
1113 	fill_dir_header(pspdir, count, ctx);
1114 	ctx->current_table = current_table_save;
1115 }
1116 
new_bios_dir(context * ctx,bool multi,uint32_t cookie)1117 static void *new_bios_dir(context *ctx, bool multi, uint32_t cookie)
1118 {
1119 	void *ptr;
1120 
1121 	/*
1122 	 * Force both onto boundary when multi.  Primary table is after
1123 	 * updatable table, so alignment ensures primary can stay intact
1124 	 * if secondary is reprogrammed.
1125 	 */
1126 	if (multi)
1127 		adjust_current_pointer(ctx, 0, TABLE_ERASE_ALIGNMENT);
1128 	else
1129 		adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
1130 	ptr = BUFF_CURRENT(*ctx);
1131 	((bios_directory_hdr *) ptr)->cookie = cookie;
1132 	((bios_directory_hdr *) ptr)->additional_info = 0;
1133 	((bios_directory_hdr *) ptr)->additional_info_fields.address_mode = ctx->address_mode;
1134 	adjust_current_pointer(ctx,
1135 		sizeof(bios_directory_hdr) + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry),
1136 		1);
1137 	return ptr;
1138 }
1139 
locate_bdt2_bios(bios_directory_table * level2,uint64_t * source,uint32_t * size)1140 static int locate_bdt2_bios(bios_directory_table *level2,
1141 					uint64_t *source, uint32_t *size)
1142 {
1143 	uint32_t i;
1144 
1145 	*source = 0;
1146 	*size = 0;
1147 	if (!level2)
1148 		return 0;
1149 
1150 	for (i = 0 ; i < level2->header.num_entries ; i++) {
1151 		if (level2->entries[i].type == AMD_BIOS_BIN) {
1152 			*source = level2->entries[i].source;
1153 			*size = level2->entries[i].size;
1154 			return 1;
1155 		}
1156 	}
1157 	return 0;
1158 }
1159 
have_bios_tables(amd_bios_entry * table)1160 static int have_bios_tables(amd_bios_entry *table)
1161 {
1162 	int i;
1163 
1164 	for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) {
1165 		if (table[i].level & BDT_LVL1 && table[i].filename)
1166 			return 1;
1167 	}
1168 	return 0;
1169 }
1170 
find_bios_entry(amd_bios_type type)1171 int find_bios_entry(amd_bios_type type)
1172 {
1173 	int i;
1174 
1175 	for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1176 		if (amd_bios_table[i].type == type)
1177 			return i;
1178 	}
1179 	return -1;
1180 }
1181 
add_bios_apcb_bk_entry(bios_directory_table * biosdir,unsigned int idx,int inst,uint32_t size,uint64_t source)1182 static void add_bios_apcb_bk_entry(bios_directory_table *biosdir, unsigned int idx,
1183 						int inst, uint32_t size, uint64_t source)
1184 {
1185 	int i;
1186 
1187 	for (i = 0; amd_bios_table[i].type != AMD_BIOS_INVALID; i++) {
1188 		if (amd_bios_table[i].type == AMD_BIOS_APCB_BK &&
1189 					amd_bios_table[i].inst == inst)
1190 			break;
1191 	}
1192 
1193 	if (amd_bios_table[i].type != AMD_BIOS_APCB_BK)
1194 		return;
1195 
1196 	biosdir->entries[idx].type = amd_bios_table[i].type;
1197 	biosdir->entries[idx].region_type = amd_bios_table[i].region_type;
1198 	biosdir->entries[idx].dest = amd_bios_table[i].dest ?
1199 					amd_bios_table[i].dest : (uint64_t)-1;
1200 	biosdir->entries[idx].reset = amd_bios_table[i].reset;
1201 	biosdir->entries[idx].copy = amd_bios_table[i].copy;
1202 	biosdir->entries[idx].ro = amd_bios_table[i].ro;
1203 	biosdir->entries[idx].compressed = amd_bios_table[i].zlib;
1204 	biosdir->entries[idx].inst = amd_bios_table[i].inst;
1205 	biosdir->entries[idx].subprog = amd_bios_table[i].subpr;
1206 	biosdir->entries[idx].size = size;
1207 	biosdir->entries[idx].source = source;
1208 	biosdir->entries[idx].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1209 }
1210 
integrate_bios_levels(context * ctx,amd_cb_config * cb_config)1211 static void integrate_bios_levels(context *ctx, amd_cb_config *cb_config)
1212 {
1213 	unsigned int count;
1214 	uint32_t current_table_save;
1215 
1216 	if (cb_config->recovery_ab) {
1217 		add_psp_firmware_entry(ctx, ctx->pspdir2, ctx->biosdir2,
1218 			AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT);
1219 		if (ctx->pspdir2_b != NULL)
1220 			add_psp_firmware_entry(ctx, ctx->pspdir2_b,
1221 				ctx->biosdir2_b, AMD_FW_BIOS_TABLE,
1222 				TABLE_ALIGNMENT);
1223 	} else if (ctx->biosdir2) {
1224 		current_table_save = ctx->current_table;
1225 		ctx->current_table = BUFF_TO_RUN_MODE(*ctx, ctx->biosdir, AMD_ADDR_REL_BIOS);
1226 		count = ctx->biosdir->header.num_entries;
1227 		assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1228 		ctx->biosdir->entries[count].type = AMD_BIOS_L2_PTR;
1229 		ctx->biosdir->entries[count].region_type = 0;
1230 		ctx->biosdir->entries[count].size =
1231 					+ MAX_BIOS_ENTRIES
1232 					* sizeof(bios_directory_entry);
1233 		ctx->biosdir->entries[count].source =
1234 					BUFF_TO_RUN(*ctx, ctx->biosdir2);
1235 		ctx->biosdir->entries[count].address_mode =
1236 					SET_ADDR_MODE(ctx->biosdir, AMD_ADDR_REL_BIOS);
1237 		ctx->biosdir->entries[count].subprog = 0;
1238 		ctx->biosdir->entries[count].inst = 0;
1239 		ctx->biosdir->entries[count].copy = 0;
1240 		ctx->biosdir->entries[count].compressed = 0;
1241 		ctx->biosdir->entries[count].dest = -1;
1242 		ctx->biosdir->entries[count].reset = 0;
1243 		ctx->biosdir->entries[count].ro = 0;
1244 		count++;
1245 		fill_dir_header(ctx->biosdir, count, ctx);
1246 		ctx->current_table = current_table_save;
1247 	}
1248 }
integrate_bios_firmwares(context * ctx,amd_bios_entry * fw_table,uint32_t cookie,amd_cb_config * cb_config)1249 static void integrate_bios_firmwares(context *ctx,
1250 					amd_bios_entry *fw_table,
1251 					uint32_t cookie,
1252 					amd_cb_config *cb_config)
1253 {
1254 	ssize_t bytes;
1255 	unsigned int i, count;
1256 	int level;
1257 	int apob_idx;
1258 	uint32_t size;
1259 	uint64_t source;
1260 	uint32_t current_table_save;
1261 	bios_directory_table *biosdir;
1262 
1263 	biosdir = new_bios_dir(ctx, cb_config->multi_level, cookie);
1264 
1265 	if (cookie == BHD_COOKIE)
1266 		ctx->biosdir = biosdir;
1267 	else if (cookie == BHDL2_COOKIE) {
1268 		if (ctx->biosdir2 == NULL)
1269 			ctx->biosdir2 = biosdir;
1270 		else if (ctx->biosdir2_b == NULL)
1271 			ctx->biosdir2_b = biosdir;
1272 	}
1273 
1274 	/* This function can create a primary table, a secondary table, or a
1275 	 * flattened table which contains all applicable types.  These if-else
1276 	 * statements infer what the caller intended.  If a 2nd-level cookie
1277 	 * is passed, clearly a 2nd-level table is intended.  However, a
1278 	 * 1st-level cookie may indicate level 1 or flattened.
1279 	 */
1280 	if (!cb_config->multi_level)
1281 		level = BDT_BOTH;
1282 	else if (cookie == BHDL2_COOKIE)
1283 		level = BDT_LVL2;
1284 	else if (cookie == BHD_COOKIE)
1285 		level = BDT_LVL1;
1286 	else
1287 		level = BDT_BOTH;
1288 
1289 	current_table_save = ctx->current_table;
1290 	ctx->current_table = BUFF_TO_RUN_MODE(*ctx, biosdir, AMD_ADDR_REL_BIOS);
1291 	adjust_current_pointer(ctx, 0, TABLE_ALIGNMENT);
1292 
1293 	for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) {
1294 		if (!(fw_table[i].level & level))
1295 			continue;
1296 		if (fw_table[i].filename == NULL && (
1297 				fw_table[i].type != AMD_BIOS_SIG &&
1298 				fw_table[i].type != AMD_BIOS_APOB &&
1299 				fw_table[i].type != AMD_BIOS_APOB_NV &&
1300 				fw_table[i].type != AMD_BIOS_L2_PTR &&
1301 				fw_table[i].type != AMD_BIOS_BIN &&
1302 				fw_table[i].type != AMD_BIOS_PSP_SHARED_MEM))
1303 			continue;
1304 
1305 		/* BIOS Directory items may have additional requirements */
1306 
1307 		/* SIG needs a size, else no choice but to skip */
1308 		if (fw_table[i].type == AMD_BIOS_SIG && !fw_table[i].size)
1309 			continue;
1310 
1311 		/* Check APOB_NV requirements */
1312 		if (fw_table[i].type == AMD_BIOS_APOB_NV) {
1313 			if (!fw_table[i].size && !fw_table[i].src)
1314 				continue; /* APOB_NV not used */
1315 			if (fw_table[i].src && !fw_table[i].size) {
1316 				fprintf(stderr, "Error: APOB NV address provided, but no size\n");
1317 				amdfwtool_cleanup(ctx);
1318 				exit(1);
1319 			}
1320 			/* If the APOB isn't used, APOB_NV isn't used either */
1321 			apob_idx = find_bios_entry(AMD_BIOS_APOB);
1322 			if (apob_idx < 0 || !fw_table[apob_idx].dest)
1323 				continue; /* APOV NV not supported */
1324 		}
1325 
1326 		/* APOB_DATA needs destination */
1327 		if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) {
1328 			fprintf(stderr, "Error: APOB destination not provided\n");
1329 			amdfwtool_cleanup(ctx);
1330 			exit(1);
1331 		}
1332 
1333 		/* BIOS binary must have destination and uncompressed size.  If
1334 		 * no filename given, then user must provide a source address.
1335 		 */
1336 		if (fw_table[i].type == AMD_BIOS_BIN) {
1337 			if (!fw_table[i].dest || !fw_table[i].size) {
1338 				fprintf(stderr, "Error: BIOS binary destination and uncompressed size are required\n");
1339 				amdfwtool_cleanup(ctx);
1340 				exit(1);
1341 			}
1342 			if (!fw_table[i].filename && !fw_table[i].src) {
1343 				fprintf(stderr, "Error: BIOS binary assumed outside amdfw.rom but no source address given\n");
1344 				amdfwtool_cleanup(ctx);
1345 				exit(1);
1346 			}
1347 		}
1348 
1349 		/* PSP_SHARED_MEM needs a destination and size */
1350 		if (fw_table[i].type == AMD_BIOS_PSP_SHARED_MEM &&
1351 				(!fw_table[i].dest || !fw_table[i].size))
1352 			continue;
1353 		assert_fw_entry(count, MAX_BIOS_ENTRIES, ctx);
1354 
1355 		biosdir->entries[count].type = fw_table[i].type;
1356 		biosdir->entries[count].region_type = fw_table[i].region_type;
1357 		biosdir->entries[count].dest = fw_table[i].dest ?
1358 					fw_table[i].dest : (uint64_t)-1;
1359 		biosdir->entries[count].reset = fw_table[i].reset;
1360 		biosdir->entries[count].copy = fw_table[i].copy;
1361 		biosdir->entries[count].ro = fw_table[i].ro;
1362 		biosdir->entries[count].compressed = fw_table[i].zlib;
1363 		biosdir->entries[count].inst = fw_table[i].inst;
1364 		biosdir->entries[count].subprog = fw_table[i].subpr;
1365 
1366 		switch (fw_table[i].type) {
1367 		case AMD_BIOS_SIG:
1368 			/* Reserve size bytes within amdfw.rom */
1369 			biosdir->entries[count].size = fw_table[i].size;
1370 			biosdir->entries[count].source = RUN_CURRENT(*ctx);
1371 			biosdir->entries[count].address_mode =
1372 					SET_ADDR_MODE_BY_TABLE(biosdir);
1373 			memset(BUFF_CURRENT(*ctx), 0xff,
1374 							biosdir->entries[count].size);
1375 			adjust_current_pointer(ctx, biosdir->entries[count].size, 0x100U);
1376 			break;
1377 		case AMD_BIOS_APOB:
1378 			biosdir->entries[count].size = fw_table[i].size;
1379 			biosdir->entries[count].source = fw_table[i].src;
1380 			biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1381 			break;
1382 		case AMD_BIOS_APOB_NV:
1383 			if (fw_table[i].src) {
1384 				/* If source is given, use that and its size */
1385 				biosdir->entries[count].source = fw_table[i].src;
1386 				biosdir->entries[count].address_mode =
1387 						SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1388 				biosdir->entries[count].size = fw_table[i].size;
1389 			} else {
1390 				/* Else reserve size bytes within amdfw.rom */
1391 				adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1392 				biosdir->entries[count].source = RUN_CURRENT(*ctx);
1393 				biosdir->entries[count].address_mode =
1394 						SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1395 				biosdir->entries[count].size = ALIGN_UP(
1396 						fw_table[i].size, ERASE_ALIGNMENT);
1397 				memset(BUFF_CURRENT(*ctx), 0xff,
1398 						biosdir->entries[count].size);
1399 				adjust_current_pointer(ctx, biosdir->entries[count].size, 1);
1400 			}
1401 			break;
1402 		case AMD_BIOS_BIN:
1403 			/* Don't make a 2nd copy, point to the same one */
1404 			if (level == BDT_LVL1 && locate_bdt2_bios(ctx->biosdir2, &source, &size)) {
1405 				biosdir->entries[count].source = source;
1406 				biosdir->entries[count].address_mode =
1407 						SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1408 				biosdir->entries[count].size = size;
1409 				break;
1410 			}
1411 
1412 			/* level 2, or level 1 and no copy found in level 2 */
1413 			biosdir->entries[count].source = fw_table[i].src;
1414 			biosdir->entries[count].address_mode =
1415 						SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1416 			biosdir->entries[count].dest = fw_table[i].dest;
1417 			biosdir->entries[count].size = fw_table[i].size;
1418 
1419 			if (!fw_table[i].filename)
1420 				break;
1421 
1422 			bytes = copy_blob(BUFF_CURRENT(*ctx),
1423 					fw_table[i].filename, BUFF_ROOM(*ctx));
1424 			if (bytes <= 0) {
1425 				amdfwtool_cleanup(ctx);
1426 				exit(1);
1427 			}
1428 
1429 			biosdir->entries[count].source =
1430 				RUN_CURRENT_MODE(*ctx, AMD_ADDR_REL_BIOS);
1431 			biosdir->entries[count].address_mode =
1432 				SET_ADDR_MODE(biosdir, AMD_ADDR_REL_BIOS);
1433 
1434 			adjust_current_pointer(ctx, bytes, 0x100U);
1435 			break;
1436 		case AMD_BIOS_PSP_SHARED_MEM:
1437 			biosdir->entries[count].dest = fw_table[i].dest;
1438 			biosdir->entries[count].size = fw_table[i].size;
1439 			break;
1440 
1441 		default: /* everything else is copied from input */
1442 			if (fw_table[i].type == AMD_BIOS_APCB ||
1443 					fw_table[i].type == AMD_BIOS_APCB_BK)
1444 				adjust_current_pointer(ctx, 0, ERASE_ALIGNMENT);
1445 			bytes = copy_blob(BUFF_CURRENT(*ctx),
1446 					fw_table[i].filename, BUFF_ROOM(*ctx));
1447 			if (bytes <= 0) {
1448 				amdfwtool_cleanup(ctx);
1449 				exit(1);
1450 			}
1451 
1452 			biosdir->entries[count].size = (uint32_t)bytes;
1453 			biosdir->entries[count].source = RUN_CURRENT(*ctx);
1454 			biosdir->entries[count].address_mode = SET_ADDR_MODE_BY_TABLE(biosdir);
1455 
1456 			adjust_current_pointer(ctx, bytes, 0x100U);
1457 			if (fw_table[i].type == AMD_BIOS_APCB && !cb_config->have_apcb_bk) {
1458 				size = biosdir->entries[count].size;
1459 				source = biosdir->entries[count].source;
1460 				count++;
1461 				add_bios_apcb_bk_entry(biosdir, count, fw_table[i].inst, size, source);
1462 			}
1463 			break;
1464 		}
1465 
1466 		count++;
1467 	}
1468 
1469 	fill_dir_header(biosdir, count, ctx);
1470 	ctx->current_table = current_table_save;
1471 }
1472 
set_efs_table(uint8_t soc_id,amd_cb_config * cb_config,embedded_firmware * amd_romsig)1473 static int set_efs_table(uint8_t soc_id, amd_cb_config *cb_config,
1474 			 embedded_firmware *amd_romsig)
1475 {
1476 	if ((cb_config->efs_spi_readmode == 0xFF) || (cb_config->efs_spi_speed == 0xFF)) {
1477 		fprintf(stderr, "Error: EFS read mode and SPI speed must be set\n");
1478 		return 1;
1479 	}
1480 
1481 	/* amd_romsig->efs_gen introduced after RAVEN/PICASSO.
1482 	 * Leave as 0xffffffff for first gen */
1483 	if (cb_config->second_gen) {
1484 		amd_romsig->efs_gen.gen = EFS_SECOND_GEN;
1485 		amd_romsig->efs_gen.reserved = 0;
1486 	} else {
1487 		amd_romsig->efs_gen.gen = EFS_BEFORE_SECOND_GEN;
1488 		amd_romsig->efs_gen.reserved = ~0;
1489 	}
1490 
1491 	switch (soc_id) {
1492 	case PLATFORM_CARRIZO:
1493 	case PLATFORM_STONEYRIDGE:
1494 		amd_romsig->spi_readmode_f15_mod_60_6f = cb_config->efs_spi_readmode;
1495 		amd_romsig->fast_speed_new_f15_mod_60_6f = cb_config->efs_spi_speed;
1496 		break;
1497 	case PLATFORM_RAVEN:
1498 	case PLATFORM_PICASSO:
1499 		amd_romsig->spi_readmode_f17_mod_00_2f = cb_config->efs_spi_readmode;
1500 		amd_romsig->spi_fastspeed_f17_mod_00_2f = cb_config->efs_spi_speed;
1501 		switch (cb_config->efs_spi_micron_flag) {
1502 		case 0:
1503 			amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xff;
1504 			break;
1505 		case 1:
1506 			amd_romsig->qpr_dummy_cycle_f17_mod_00_2f = 0xa;
1507 			break;
1508 		default:
1509 			fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
1510 			return 1;
1511 		}
1512 		break;
1513 	case PLATFORM_RENOIR:
1514 	case PLATFORM_LUCIENNE:
1515 	case PLATFORM_CEZANNE:
1516 	case PLATFORM_MENDOCINO:
1517 	case PLATFORM_PHOENIX:
1518 	case PLATFORM_GLINDA:
1519 	case PLATFORM_GENOA:
1520 		amd_romsig->spi_readmode_f17_mod_30_3f = cb_config->efs_spi_readmode;
1521 		amd_romsig->spi_fastspeed_f17_mod_30_3f = cb_config->efs_spi_speed;
1522 		switch (cb_config->efs_spi_micron_flag) {
1523 		case 0:
1524 			amd_romsig->micron_detect_f17_mod_30_3f = 0xff;
1525 			break;
1526 		case 1:
1527 			amd_romsig->micron_detect_f17_mod_30_3f = 0xaa;
1528 			break;
1529 		case 2:
1530 			amd_romsig->micron_detect_f17_mod_30_3f = 0x55;
1531 			break;
1532 		default:
1533 			fprintf(stderr, "Error: EFS Micron flag must be correctly set.\n\n");
1534 			return 1;
1535 		}
1536 		break;
1537 	case PLATFORM_UNKNOWN:
1538 	default:
1539 		fprintf(stderr, "Error: Invalid SOC name.\n\n");
1540 		return 1;
1541 	}
1542 	return 0;
1543 }
1544 
open_process_config(char * config,amd_cb_config * cb_config)1545 void open_process_config(char *config, amd_cb_config *cb_config)
1546 {
1547 	FILE *config_handle;
1548 
1549 	if (config) {
1550 		config_handle = fopen(config, "r");
1551 		if (config_handle == NULL) {
1552 			fprintf(stderr, "Can not open file %s for reading: %s\n",
1553 				config, strerror(errno));
1554 			exit(1);
1555 		}
1556 		if (process_config(config_handle, cb_config) == 0) {
1557 			fprintf(stderr, "Configuration file %s parsing error\n",
1558 					config);
1559 			fclose(config_handle);
1560 			exit(1);
1561 		}
1562 		fclose(config_handle);
1563 	}
1564 
1565 	/* For debug. */
1566 	if (cb_config->debug) {
1567 		dump_psp_firmwares(amd_psp_fw_table);
1568 		dump_bdt_firmwares(amd_bios_table);
1569 	}
1570 }
1571 
is_initial_alignment_required(enum platform soc_id)1572 static bool is_initial_alignment_required(enum platform soc_id)
1573 {
1574 	switch (soc_id) {
1575 	case PLATFORM_MENDOCINO:
1576 	case PLATFORM_PHOENIX:
1577 	case PLATFORM_GLINDA:
1578 		return false;
1579 	default:
1580 		return true;
1581 	}
1582 }
1583 
main(int argc,char ** argv)1584 int main(int argc, char **argv)
1585 {
1586 	int retval = 0;
1587 	int combo_index = 0;
1588 	int targetfd;
1589 	context ctx = { 0 };
1590 	uint32_t romsig_offset;
1591 	amd_cb_config cb_config = {
1592 		.efs_spi_readmode = 0xff, .efs_spi_speed = 0xff, .efs_spi_micron_flag = 0xff
1593 	};
1594 
1595 	ctx.current_pointer_saved = 0xFFFFFFFF;
1596 
1597 	retval = amdfwtool_getopt(argc, argv, &cb_config, &ctx);
1598 
1599 	if (retval) {
1600 		return retval;
1601 	}
1602 
1603 	if (cb_config.use_combo) {
1604 		ctx.amd_psp_fw_table_clean = malloc(sizeof(amd_psp_fw_table));
1605 		ctx.amd_bios_table_clean = malloc(sizeof(amd_bios_table));
1606 		memcpy(ctx.amd_psp_fw_table_clean, amd_psp_fw_table, sizeof(amd_psp_fw_table));
1607 		memcpy(ctx.amd_bios_table_clean, amd_bios_table, sizeof(amd_bios_table));
1608 	}
1609 
1610 	open_process_config(cb_config.config, &cb_config);
1611 
1612 	ctx.rom = malloc(ctx.rom_size);
1613 	if (!ctx.rom) {
1614 		fprintf(stderr, "Error: Failed to allocate memory\n");
1615 		return 1;
1616 	}
1617 	memset(ctx.rom, 0xFF, ctx.rom_size);
1618 
1619 	romsig_offset = cb_config.efs_location ? cb_config.efs_location : AMD_ROMSIG_OFFSET;
1620 	set_current_pointer(&ctx, romsig_offset);
1621 
1622 	ctx.amd_romsig_ptr = BUFF_OFFSET(ctx, romsig_offset);
1623 	ctx.amd_romsig_ptr->signature = EMBEDDED_FW_SIGNATURE;
1624 	ctx.amd_romsig_ptr->imc_entry = 0;
1625 	ctx.amd_romsig_ptr->gec_entry = 0;
1626 	ctx.amd_romsig_ptr->xhci_entry = 0;
1627 
1628 	if (cb_config.soc_id != PLATFORM_UNKNOWN) {
1629 		retval = set_efs_table(cb_config.soc_id, &cb_config, ctx.amd_romsig_ptr);
1630 		if (retval) {
1631 			fprintf(stderr, "ERROR: Failed to initialize EFS table!\n");
1632 			return retval;
1633 		}
1634 	} else {
1635 		fprintf(stderr, "WARNING: No SOC name specified.\n");
1636 	}
1637 
1638 	if (cb_config.need_ish)
1639 		ctx.address_mode = AMD_ADDR_REL_TAB;
1640 	else if (cb_config.second_gen)
1641 		ctx.address_mode = AMD_ADDR_REL_BIOS;
1642 	else
1643 		ctx.address_mode = AMD_ADDR_PHYSICAL;
1644 
1645 	if (cb_config.efs_location != cb_config.body_location)
1646 		set_current_pointer(&ctx, cb_config.body_location);
1647 	else
1648 		set_current_pointer(&ctx, romsig_offset + sizeof(embedded_firmware));
1649 
1650 	integrate_firmwares(&ctx, ctx.amd_romsig_ptr, amd_fw_table);
1651 
1652 	if (is_initial_alignment_required(cb_config.soc_id)) {
1653 		/* TODO: Check for older platforms. */
1654 		adjust_current_pointer(&ctx, 0, 0x10000U);
1655 	}
1656 	ctx.current_table = 0;
1657 
1658 	/* If the tool is invoked with command-line options to keep the signed PSP
1659 	   binaries separate, process the signed binaries first. */
1660 	if (cb_config.signed_output_file && cb_config.signed_start_addr)
1661 		process_signed_psp_firmwares(cb_config.signed_output_file,
1662 				amd_psp_fw_table,
1663 				cb_config.signed_start_addr,
1664 				cb_config.soc_id);
1665 
1666 	if (cb_config.use_combo) {
1667 		ctx.psp_combo_dir = new_combo_dir(&ctx, PSP2_COOKIE);
1668 
1669 		adjust_current_pointer(&ctx, 0, 0x1000U);
1670 
1671 		if (!cb_config.recovery_ab)
1672 			ctx.bhd_combo_dir = new_combo_dir(&ctx, BHD2_COOKIE);
1673 	}
1674 
1675 	combo_index = 0;
1676 	if (cb_config.config)
1677 		cb_config.combo_config[0] = cb_config.config;
1678 
1679 	do {
1680 		if (cb_config.use_combo && cb_config.debug)
1681 			printf("Processing %dth combo entry\n", combo_index);
1682 
1683 		ctx.pspdir = NULL;
1684 		ctx.pspdir2 = NULL;
1685 		ctx.pspdir2_b = NULL;
1686 		ctx.biosdir = NULL;
1687 		ctx.biosdir2 = NULL;
1688 		ctx.biosdir2_b = NULL;
1689 		ctx.ish_a_dir = NULL;
1690 		ctx.ish_b_dir = NULL;
1691 		/* for non-combo image, combo_config[0] == config, and
1692 		 *  it already is processed.  Actually "combo_index >
1693 		 *  0" is enough. Put both of them here to make sure
1694 		 *  and make it clear this will not affect non-combo
1695 		 *  case.
1696 		 */
1697 		if (cb_config.use_combo && combo_index > 0) {
1698 			/* Restore the table as clean data. */
1699 			memcpy(amd_psp_fw_table, ctx.amd_psp_fw_table_clean,
1700 				sizeof(amd_psp_fw_table));
1701 			memcpy(amd_bios_table, ctx.amd_bios_table_clean,
1702 				sizeof(amd_bios_table));
1703 			assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
1704 			open_process_config(cb_config.combo_config[combo_index], &cb_config);
1705 
1706 			/* In most cases, the address modes are same. */
1707 			if (cb_config.need_ish)
1708 				ctx.address_mode = AMD_ADDR_REL_TAB;
1709 			else if (cb_config.second_gen)
1710 				ctx.address_mode = AMD_ADDR_REL_BIOS;
1711 			else
1712 				ctx.address_mode = AMD_ADDR_PHYSICAL;
1713 
1714 			register_apcb_combo(&cb_config, combo_index, &ctx);
1715 		}
1716 
1717 		if (cb_config.multi_level) {
1718 			/* Do 2nd PSP directory followed by 1st */
1719 			integrate_psp_firmwares(&ctx,
1720 						amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1721 			if (cb_config.recovery_ab && !cb_config.recovery_ab_single_copy) {
1722 				/* Create a copy of PSP Directory 2 in the backup slot B.
1723 				   Related biosdir2_b copy will be created later. */
1724 				integrate_psp_firmwares(&ctx,
1725 						amd_psp_fw_table, PSPL2_COOKIE, &cb_config);
1726 			} else {
1727 				/*
1728 				 * Either the platform is using only
1729 				 * one slot or B is same as above
1730 				 * directories for A. Skip creating
1731 				 * pspdir2_b here to save flash space.
1732 				 * Related biosdir2_b will be skipped
1733 				 * automatically.
1734 				 */
1735 				ctx.pspdir2_b = NULL; /* More explicitly */
1736 			}
1737 			integrate_psp_firmwares(&ctx,
1738 					amd_psp_fw_table, PSP_COOKIE, &cb_config);
1739 			integrate_psp_levels(&ctx, &cb_config);
1740 		} else {
1741 			/* flat: PSP 1 cookie and no pointer to 2nd table */
1742 			integrate_psp_firmwares(&ctx,
1743 					amd_psp_fw_table, PSP_COOKIE, &cb_config);
1744 		}
1745 
1746 		if (!cb_config.use_combo) {
1747 			fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.pspdir, &ctx, &cb_config);
1748 		} else {
1749 			fill_psp_directory_to_efs(ctx.amd_romsig_ptr, ctx.psp_combo_dir, &ctx, &cb_config);
1750 			/* 0 -Compare PSP ID, 1 -Compare chip family ID */
1751 			assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
1752 			ctx.psp_combo_dir->entries[combo_index].id_sel = 0;
1753 			ctx.psp_combo_dir->entries[combo_index].id = get_psp_id(cb_config.soc_id);
1754 			ctx.psp_combo_dir->entries[combo_index].lvl2_addr =
1755 				BUFF_TO_RUN_MODE(ctx, ctx.pspdir, AMD_ADDR_REL_BIOS);
1756 
1757 			fill_dir_header(ctx.psp_combo_dir, combo_index + 1, &ctx);
1758 		}
1759 
1760 		if (have_bios_tables(amd_bios_table)) {
1761 			if (cb_config.multi_level) {
1762 				/* Do 2nd level BIOS directory followed by 1st */
1763 				integrate_bios_firmwares(&ctx,
1764 						amd_bios_table, BHDL2_COOKIE, &cb_config);
1765 				if (cb_config.recovery_ab) {
1766 					if (ctx.pspdir2_b != NULL) {
1767 						integrate_bios_firmwares(&ctx,
1768 								amd_bios_table, BHDL2_COOKIE,
1769 								&cb_config);
1770 					}
1771 				} else {
1772 					integrate_bios_firmwares(&ctx,
1773 							amd_bios_table, BHD_COOKIE, &cb_config);
1774 				}
1775 				integrate_bios_levels(&ctx, &cb_config);
1776 			} else {
1777 				/* flat: BHD1 cookie and no pointer to 2nd table */
1778 				integrate_bios_firmwares(&ctx,
1779 							amd_bios_table, BHD_COOKIE, &cb_config);
1780 			}
1781 			if (!cb_config.use_combo) {
1782 				fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.biosdir,
1783 					&ctx, &cb_config);
1784 			} else if (ctx.bhd_combo_dir != NULL) {
1785 				/* In recovery A/B mode, there isn't a BHD combo directory.
1786 				 * Instead, the BIOS tables level 2 are linked by PSP tables.
1787 				 */
1788 				fill_bios_directory_to_efs(ctx.amd_romsig_ptr, ctx.bhd_combo_dir,
1789 					&ctx, &cb_config);
1790 				assert_fw_entry(combo_index, MAX_COMBO_ENTRIES, &ctx);
1791 				ctx.bhd_combo_dir->entries[combo_index].id_sel = 0;
1792 				ctx.bhd_combo_dir->entries[combo_index].id =
1793 					get_psp_id(cb_config.soc_id);
1794 				ctx.bhd_combo_dir->entries[combo_index].lvl2_addr =
1795 					BUFF_TO_RUN_MODE(ctx, ctx.biosdir, AMD_ADDR_REL_BIOS);
1796 
1797 				fill_dir_header(ctx.bhd_combo_dir, combo_index + 1, &ctx);
1798 			}
1799 		}
1800 		if (cb_config.debug)
1801 			dump_image_addresses(&ctx);
1802 	} while (cb_config.use_combo && ++combo_index < MAX_COMBO_ENTRIES &&
1803 					cb_config.combo_config[combo_index] != NULL);
1804 
1805 	targetfd = open(cb_config.output, O_RDWR | O_CREAT | O_TRUNC, 0666);
1806 	if (targetfd >= 0) {
1807 		uint32_t offset = cb_config.efs_location;
1808 		uint32_t bytes = cb_config.efs_location == cb_config.body_location ?
1809 				ctx.current - offset : sizeof(embedded_firmware);
1810 		uint32_t ret_bytes;
1811 
1812 		ret_bytes = write_from_buf_to_file(targetfd, BUFF_OFFSET(ctx, offset), bytes);
1813 		if (bytes != ret_bytes) {
1814 			fprintf(stderr, "Error: Writing to file %s failed\n", cb_config.output);
1815 			retval = 1;
1816 		}
1817 		close(targetfd);
1818 	} else {
1819 		fprintf(stderr, "Error: could not open file: %s\n", cb_config.output);
1820 		retval = 1;
1821 	}
1822 
1823 	if (cb_config.efs_location != cb_config.body_location) {
1824 		ssize_t bytes;
1825 
1826 		bytes = write_body(cb_config.output, BUFF_OFFSET(ctx, cb_config.body_location),
1827 			ctx.current - cb_config.body_location);
1828 		if (bytes != ctx.current - cb_config.body_location) {
1829 			fprintf(stderr, "Error: Writing body\n");
1830 			retval = 1;
1831 		}
1832 	}
1833 
1834 	if (cb_config.manifest_file) {
1835 		dump_blob_version(cb_config.manifest_file, amd_psp_fw_table);
1836 	}
1837 
1838 	amdfwtool_cleanup(&ctx);
1839 	return retval;
1840 }
1841