1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for AMD network controllers and boards
4 * Copyright (C) 2025, Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation, incorporated herein by reference.
9 */
10
11 #include <linux/crc32.h>
12 #include <net/devlink.h>
13 #include "efx_reflash.h"
14 #include "net_driver.h"
15 #include "fw_formats.h"
16 #include "mcdi_pcol.h"
17 #include "mcdi.h"
18
19 /* Try to parse a Reflash header at the specified offset */
efx_reflash_parse_reflash_header(const struct firmware * fw,size_t header_offset,u32 * type,u32 * subtype,const u8 ** data,size_t * data_size)20 static bool efx_reflash_parse_reflash_header(const struct firmware *fw,
21 size_t header_offset, u32 *type,
22 u32 *subtype, const u8 **data,
23 size_t *data_size)
24 {
25 size_t header_end, trailer_offset, trailer_end;
26 u32 magic, version, payload_size, header_len;
27 const u8 *header, *trailer;
28 u32 expected_crc, crc;
29
30 if (check_add_overflow(header_offset, EFX_REFLASH_HEADER_LENGTH_OFST +
31 EFX_REFLASH_HEADER_LENGTH_LEN,
32 &header_end))
33 return false;
34 if (fw->size < header_end)
35 return false;
36
37 header = fw->data + header_offset;
38 magic = get_unaligned_le32(header + EFX_REFLASH_HEADER_MAGIC_OFST);
39 if (magic != EFX_REFLASH_HEADER_MAGIC_VALUE)
40 return false;
41
42 version = get_unaligned_le32(header + EFX_REFLASH_HEADER_VERSION_OFST);
43 if (version != EFX_REFLASH_HEADER_VERSION_VALUE)
44 return false;
45
46 payload_size = get_unaligned_le32(header + EFX_REFLASH_HEADER_PAYLOAD_SIZE_OFST);
47 header_len = get_unaligned_le32(header + EFX_REFLASH_HEADER_LENGTH_OFST);
48 if (check_add_overflow(header_offset, header_len, &trailer_offset) ||
49 check_add_overflow(trailer_offset, payload_size, &trailer_offset) ||
50 check_add_overflow(trailer_offset, EFX_REFLASH_TRAILER_LEN,
51 &trailer_end))
52 return false;
53 if (fw->size < trailer_end)
54 return false;
55
56 trailer = fw->data + trailer_offset;
57 expected_crc = get_unaligned_le32(trailer + EFX_REFLASH_TRAILER_CRC_OFST);
58 /* Addition could overflow u32, but not size_t since we already
59 * checked trailer_offset didn't overflow. So cast to size_t first.
60 */
61 crc = crc32_le(0, header, (size_t)header_len + payload_size);
62 if (crc != expected_crc)
63 return false;
64
65 *type = get_unaligned_le32(header + EFX_REFLASH_HEADER_FIRMWARE_TYPE_OFST);
66 *subtype = get_unaligned_le32(header + EFX_REFLASH_HEADER_FIRMWARE_SUBTYPE_OFST);
67 if (*type == EFX_REFLASH_FIRMWARE_TYPE_BUNDLE) {
68 /* All the bundle data is written verbatim to NVRAM */
69 *data = fw->data;
70 *data_size = fw->size;
71 } else {
72 /* Other payload types strip the reflash header and trailer
73 * from the data written to NVRAM
74 */
75 *data = header + header_len;
76 *data_size = payload_size;
77 }
78
79 return true;
80 }
81
82 /* Map from FIRMWARE_TYPE to NVRAM_PARTITION_TYPE */
efx_reflash_partition_type(u32 type,u32 subtype,u32 * partition_type,u32 * partition_subtype)83 static int efx_reflash_partition_type(u32 type, u32 subtype,
84 u32 *partition_type,
85 u32 *partition_subtype)
86 {
87 int rc = 0;
88
89 switch (type) {
90 case EFX_REFLASH_FIRMWARE_TYPE_BOOTROM:
91 *partition_type = NVRAM_PARTITION_TYPE_EXPANSION_ROM;
92 *partition_subtype = subtype;
93 break;
94 case EFX_REFLASH_FIRMWARE_TYPE_BUNDLE:
95 *partition_type = NVRAM_PARTITION_TYPE_BUNDLE;
96 *partition_subtype = subtype;
97 break;
98 default:
99 /* Not supported */
100 rc = -EINVAL;
101 }
102
103 return rc;
104 }
105
106 /* Try to parse a SmartNIC image header at the specified offset */
efx_reflash_parse_snic_header(const struct firmware * fw,size_t header_offset,u32 * partition_type,u32 * partition_subtype,const u8 ** data,size_t * data_size)107 static bool efx_reflash_parse_snic_header(const struct firmware *fw,
108 size_t header_offset,
109 u32 *partition_type,
110 u32 *partition_subtype,
111 const u8 **data, size_t *data_size)
112 {
113 u32 magic, version, payload_size, header_len, expected_crc, crc;
114 size_t header_end, payload_end;
115 const u8 *header;
116
117 if (check_add_overflow(header_offset, EFX_SNICIMAGE_HEADER_MINLEN,
118 &header_end) ||
119 fw->size < header_end)
120 return false;
121
122 header = fw->data + header_offset;
123 magic = get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_MAGIC_OFST);
124 if (magic != EFX_SNICIMAGE_HEADER_MAGIC_VALUE)
125 return false;
126
127 version = get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_VERSION_OFST);
128 if (version != EFX_SNICIMAGE_HEADER_VERSION_VALUE)
129 return false;
130
131 header_len = get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_LENGTH_OFST);
132 if (check_add_overflow(header_offset, header_len, &header_end))
133 return false;
134 payload_size = get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_PAYLOAD_SIZE_OFST);
135 if (check_add_overflow(header_end, payload_size, &payload_end) ||
136 fw->size < payload_end)
137 return false;
138
139 expected_crc = get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_CRC_OFST);
140
141 /* Calculate CRC omitting the expected CRC field itself */
142 crc = crc32_le(~0, header, EFX_SNICIMAGE_HEADER_CRC_OFST);
143 crc = ~crc32_le(crc,
144 header + EFX_SNICIMAGE_HEADER_CRC_OFST +
145 EFX_SNICIMAGE_HEADER_CRC_LEN,
146 header_len + payload_size - EFX_SNICIMAGE_HEADER_CRC_OFST -
147 EFX_SNICIMAGE_HEADER_CRC_LEN);
148 if (crc != expected_crc)
149 return false;
150
151 *partition_type =
152 get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_PARTITION_TYPE_OFST);
153 *partition_subtype =
154 get_unaligned_le32(header + EFX_SNICIMAGE_HEADER_PARTITION_SUBTYPE_OFST);
155 *data = fw->data;
156 *data_size = fw->size;
157 return true;
158 }
159
160 /* Try to parse a SmartNIC bundle header at the specified offset */
efx_reflash_parse_snic_bundle_header(const struct firmware * fw,size_t header_offset,u32 * partition_type,u32 * partition_subtype,const u8 ** data,size_t * data_size)161 static bool efx_reflash_parse_snic_bundle_header(const struct firmware *fw,
162 size_t header_offset,
163 u32 *partition_type,
164 u32 *partition_subtype,
165 const u8 **data,
166 size_t *data_size)
167 {
168 u32 magic, version, bundle_type, header_len, expected_crc, crc;
169 size_t header_end;
170 const u8 *header;
171
172 if (check_add_overflow(header_offset, EFX_SNICBUNDLE_HEADER_LEN,
173 &header_end))
174 return false;
175 if (fw->size < header_end)
176 return false;
177
178 header = fw->data + header_offset;
179 magic = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_MAGIC_OFST);
180 if (magic != EFX_SNICBUNDLE_HEADER_MAGIC_VALUE)
181 return false;
182
183 version = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_VERSION_OFST);
184 if (version != EFX_SNICBUNDLE_HEADER_VERSION_VALUE)
185 return false;
186
187 bundle_type = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_BUNDLE_TYPE_OFST);
188 if (bundle_type != NVRAM_PARTITION_TYPE_BUNDLE)
189 return false;
190
191 header_len = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_LENGTH_OFST);
192 if (header_len != EFX_SNICBUNDLE_HEADER_LEN)
193 return false;
194
195 expected_crc = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_CRC_OFST);
196 crc = ~crc32_le(~0, header, EFX_SNICBUNDLE_HEADER_CRC_OFST);
197 if (crc != expected_crc)
198 return false;
199
200 *partition_type = NVRAM_PARTITION_TYPE_BUNDLE;
201 *partition_subtype = get_unaligned_le32(header + EFX_SNICBUNDLE_HEADER_BUNDLE_SUBTYPE_OFST);
202 *data = fw->data;
203 *data_size = fw->size;
204 return true;
205 }
206
207 /* Try to find a valid firmware payload in the firmware data.
208 * When we recognise a valid header, we parse it for the partition type
209 * (so we know where to ask the MC to write it to) and the location of
210 * the data blob to write.
211 */
efx_reflash_parse_firmware_data(const struct firmware * fw,u32 * partition_type,u32 * partition_subtype,const u8 ** data,size_t * data_size)212 static int efx_reflash_parse_firmware_data(const struct firmware *fw,
213 u32 *partition_type,
214 u32 *partition_subtype,
215 const u8 **data, size_t *data_size)
216 {
217 size_t header_offset;
218 u32 type, subtype;
219
220 /* Some packaging formats (such as CMS/PKCS#7 signed images)
221 * prepend a header for which finding the size is a non-trivial
222 * task, so step through the firmware data until we find a valid
223 * header.
224 *
225 * The checks are intended to reject firmware data that is clearly not
226 * in the expected format. They do not need to be exhaustive as the
227 * running firmware will perform its own comprehensive validity and
228 * compatibility checks during the update procedure.
229 *
230 * Firmware packages may contain multiple reflash images, e.g. a
231 * bundle containing one or more other images. Only check the
232 * outermost container by stopping after the first candidate image
233 * found even it is for an unsupported partition type.
234 */
235 for (header_offset = 0; header_offset < fw->size; header_offset++) {
236 if (efx_reflash_parse_snic_bundle_header(fw, header_offset,
237 partition_type,
238 partition_subtype,
239 data, data_size))
240 return 0;
241
242 if (efx_reflash_parse_snic_header(fw, header_offset,
243 partition_type,
244 partition_subtype, data,
245 data_size))
246 return 0;
247
248 if (efx_reflash_parse_reflash_header(fw, header_offset, &type,
249 &subtype, data, data_size))
250 return efx_reflash_partition_type(type, subtype,
251 partition_type,
252 partition_subtype);
253 }
254
255 return -EINVAL;
256 }
257
258 /* Limit the number of status updates during the erase or write phases */
259 #define EFX_DEVLINK_STATUS_UPDATE_COUNT 50
260
261 /* Expected timeout for the efx_mcdi_nvram_update_finish_polled() */
262 #define EFX_DEVLINK_UPDATE_FINISH_TIMEOUT 900
263
264 /* Ideal erase chunk size. This is a balance between minimising the number of
265 * MCDI requests to erase an entire partition whilst avoiding tripping the MCDI
266 * RPC timeout.
267 */
268 #define EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE (64 * 1024)
269
efx_reflash_erase_partition(struct efx_nic * efx,struct netlink_ext_ack * extack,struct devlink * devlink,u32 type,size_t partition_size,size_t align)270 static int efx_reflash_erase_partition(struct efx_nic *efx,
271 struct netlink_ext_ack *extack,
272 struct devlink *devlink, u32 type,
273 size_t partition_size,
274 size_t align)
275 {
276 size_t chunk, offset, next_update;
277 int rc;
278
279 /* Partitions that cannot be erased or do not require erase before
280 * write are advertised with a erase alignment/sector size of zero.
281 */
282 if (align == 0)
283 /* Nothing to do */
284 return 0;
285
286 if (partition_size % align)
287 return -EINVAL;
288
289 /* Erase the entire NVRAM partition a chunk at a time to avoid
290 * potentially tripping the MCDI RPC timeout.
291 */
292 if (align >= EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE)
293 chunk = align;
294 else
295 chunk = rounddown(EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE, align);
296
297 for (offset = 0, next_update = 0; offset < partition_size; offset += chunk) {
298 if (offset >= next_update) {
299 devlink_flash_update_status_notify(devlink, "Erasing",
300 NULL, offset,
301 partition_size);
302 next_update += partition_size / EFX_DEVLINK_STATUS_UPDATE_COUNT;
303 }
304
305 chunk = min_t(size_t, partition_size - offset, chunk);
306 rc = efx_mcdi_nvram_erase(efx, type, offset, chunk);
307 if (rc) {
308 NL_SET_ERR_MSG_FMT_MOD(extack,
309 "Erase failed for NVRAM partition %#x at %#zx-%#zx",
310 type, offset, offset + chunk - 1);
311 return rc;
312 }
313 }
314
315 devlink_flash_update_status_notify(devlink, "Erasing", NULL,
316 partition_size, partition_size);
317
318 return 0;
319 }
320
efx_reflash_write_partition(struct efx_nic * efx,struct netlink_ext_ack * extack,struct devlink * devlink,u32 type,const u8 * data,size_t data_size,size_t align)321 static int efx_reflash_write_partition(struct efx_nic *efx,
322 struct netlink_ext_ack *extack,
323 struct devlink *devlink, u32 type,
324 const u8 *data, size_t data_size,
325 size_t align)
326 {
327 size_t write_max, chunk, offset, next_update;
328 int rc;
329
330 if (align == 0)
331 return -EINVAL;
332
333 /* Write the NVRAM partition in chunks that are the largest multiple
334 * of the partition's required write alignment that will fit into the
335 * MCDI NVRAM_WRITE RPC payload.
336 */
337 if (efx->type->mcdi_max_ver < 2)
338 write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
339 MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM;
340 else
341 write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
342 MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM_MCDI2;
343 chunk = rounddown(write_max, align);
344
345 for (offset = 0, next_update = 0; offset + chunk <= data_size; offset += chunk) {
346 if (offset >= next_update) {
347 devlink_flash_update_status_notify(devlink, "Writing",
348 NULL, offset,
349 data_size);
350 next_update += data_size / EFX_DEVLINK_STATUS_UPDATE_COUNT;
351 }
352
353 rc = efx_mcdi_nvram_write(efx, type, offset, data + offset, chunk);
354 if (rc) {
355 NL_SET_ERR_MSG_FMT_MOD(extack,
356 "Write failed for NVRAM partition %#x at %#zx-%#zx",
357 type, offset, offset + chunk - 1);
358 return rc;
359 }
360 }
361
362 /* Round up left over data to satisfy write alignment */
363 if (offset < data_size) {
364 size_t remaining = data_size - offset;
365 u8 *buf;
366
367 if (offset >= next_update)
368 devlink_flash_update_status_notify(devlink, "Writing",
369 NULL, offset,
370 data_size);
371
372 chunk = roundup(remaining, align);
373 buf = kmalloc(chunk, GFP_KERNEL);
374 if (!buf)
375 return -ENOMEM;
376
377 memcpy(buf, data + offset, remaining);
378 memset(buf + remaining, 0xFF, chunk - remaining);
379 rc = efx_mcdi_nvram_write(efx, type, offset, buf, chunk);
380 kfree(buf);
381 if (rc) {
382 NL_SET_ERR_MSG_FMT_MOD(extack,
383 "Write failed for NVRAM partition %#x at %#zx-%#zx",
384 type, offset, offset + chunk - 1);
385 return rc;
386 }
387 }
388
389 devlink_flash_update_status_notify(devlink, "Writing", NULL, data_size,
390 data_size);
391
392 return 0;
393 }
394
efx_reflash_flash_firmware(struct efx_nic * efx,const struct firmware * fw,struct netlink_ext_ack * extack)395 int efx_reflash_flash_firmware(struct efx_nic *efx, const struct firmware *fw,
396 struct netlink_ext_ack *extack)
397 {
398 size_t data_size, size, erase_align, write_align;
399 struct devlink *devlink = efx->devlink;
400 u32 type, data_subtype, subtype;
401 const u8 *data;
402 bool protected;
403 int rc;
404
405 if (!efx_has_cap(efx, BUNDLE_UPDATE)) {
406 NL_SET_ERR_MSG_MOD(extack, "NVRAM bundle updates are not supported by the firmware");
407 return -EOPNOTSUPP;
408 }
409
410 mutex_lock(&efx->reflash_mutex);
411
412 devlink_flash_update_status_notify(devlink, "Checking update", NULL, 0, 0);
413
414 if (efx->type->flash_auto_partition) {
415 /* NIC wants entire FW file including headers;
416 * FW will validate 'subtype' if there is one
417 */
418 type = NVRAM_PARTITION_TYPE_AUTO;
419 data = fw->data;
420 data_size = fw->size;
421 } else {
422 rc = efx_reflash_parse_firmware_data(fw, &type, &data_subtype, &data,
423 &data_size);
424 if (rc) {
425 NL_SET_ERR_MSG_MOD(extack,
426 "Firmware image validation check failed");
427 goto out_unlock;
428 }
429
430 rc = efx_mcdi_nvram_metadata(efx, type, &subtype, NULL, NULL, 0);
431 if (rc) {
432 NL_SET_ERR_MSG_FMT_MOD(extack,
433 "Metadata query for NVRAM partition %#x failed",
434 type);
435 goto out_unlock;
436 }
437
438 if (subtype != data_subtype) {
439 NL_SET_ERR_MSG_MOD(extack,
440 "Firmware image is not appropriate for this adapter");
441 rc = -EINVAL;
442 goto out_unlock;
443 }
444 }
445
446 rc = efx_mcdi_nvram_info(efx, type, &size, &erase_align, &write_align,
447 &protected);
448 if (rc) {
449 NL_SET_ERR_MSG_FMT_MOD(extack,
450 "Info query for NVRAM partition %#x failed",
451 type);
452 goto out_unlock;
453 }
454
455 if (protected) {
456 NL_SET_ERR_MSG_FMT_MOD(extack,
457 "NVRAM partition %#x is protected",
458 type);
459 rc = -EPERM;
460 goto out_unlock;
461 }
462
463 if (write_align == 0) {
464 NL_SET_ERR_MSG_FMT_MOD(extack,
465 "NVRAM partition %#x is not writable",
466 type);
467 rc = -EACCES;
468 goto out_unlock;
469 }
470
471 if (erase_align != 0 && size % erase_align) {
472 NL_SET_ERR_MSG_FMT_MOD(extack,
473 "NVRAM partition %#x has a bad partition table entry, can't erase it",
474 type);
475 rc = -EACCES;
476 goto out_unlock;
477 }
478
479 if (data_size > size) {
480 NL_SET_ERR_MSG_FMT_MOD(extack,
481 "Firmware image is too big for NVRAM partition %#x",
482 type);
483 rc = -EFBIG;
484 goto out_unlock;
485 }
486
487 devlink_flash_update_status_notify(devlink, "Starting update", NULL, 0, 0);
488
489 rc = efx_mcdi_nvram_update_start(efx, type);
490 if (rc) {
491 NL_SET_ERR_MSG_FMT_MOD(extack,
492 "Update start request for NVRAM partition %#x failed",
493 type);
494 goto out_unlock;
495 }
496
497 rc = efx_reflash_erase_partition(efx, extack, devlink, type, size,
498 erase_align);
499 if (rc)
500 goto out_update_finish;
501
502 rc = efx_reflash_write_partition(efx, extack, devlink, type, data,
503 data_size, write_align);
504 if (rc)
505 goto out_update_finish;
506
507 devlink_flash_update_timeout_notify(devlink, "Finishing update", NULL,
508 EFX_DEVLINK_UPDATE_FINISH_TIMEOUT);
509
510 out_update_finish:
511 if (rc)
512 /* Don't obscure the return code from an earlier failure */
513 efx_mcdi_nvram_update_finish(efx, type, EFX_UPDATE_FINISH_ABORT);
514 else
515 rc = efx_mcdi_nvram_update_finish_polled(efx, type);
516 out_unlock:
517 mutex_unlock(&efx->reflash_mutex);
518 devlink_flash_update_status_notify(devlink, rc ? "Update failed" :
519 "Update complete",
520 NULL, 0, 0);
521 return rc;
522 }
523