// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for AMD network controllers and boards * Copyright (C) 2025, Advanced Micro Devices, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, incorporated herein by reference.
*/
trailer = fw->data + trailer_offset;
expected_crc = get_unaligned_le32(trailer + EFX_REFLASH_TRAILER_CRC_OFST); /* Addition could overflow u32, but not size_t since we already * checked trailer_offset didn't overflow. So cast to size_t first.
*/
crc = crc32_le(0, header, (size_t)header_len + payload_size); if (crc != expected_crc) returnfalse;
*type = get_unaligned_le32(header + EFX_REFLASH_HEADER_FIRMWARE_TYPE_OFST);
*subtype = get_unaligned_le32(header + EFX_REFLASH_HEADER_FIRMWARE_SUBTYPE_OFST); if (*type == EFX_REFLASH_FIRMWARE_TYPE_BUNDLE) { /* All the bundle data is written verbatim to NVRAM */
*data = fw->data;
*data_size = fw->size;
} else { /* Other payload types strip the reflash header and trailer * from the data written to NVRAM
*/
*data = header + header_len;
*data_size = payload_size;
}
returntrue;
}
/* Map from FIRMWARE_TYPE to NVRAM_PARTITION_TYPE */ staticint efx_reflash_partition_type(u32 type, u32 subtype,
u32 *partition_type,
u32 *partition_subtype)
{ int rc = 0;
switch (type) { case EFX_REFLASH_FIRMWARE_TYPE_BOOTROM:
*partition_type = NVRAM_PARTITION_TYPE_EXPANSION_ROM;
*partition_subtype = subtype; break; case EFX_REFLASH_FIRMWARE_TYPE_BUNDLE:
*partition_type = NVRAM_PARTITION_TYPE_BUNDLE;
*partition_subtype = subtype; break; default: /* Not supported */
rc = -EINVAL;
}
/* Try to find a valid firmware payload in the firmware data. * When we recognise a valid header, we parse it for the partition type * (so we know where to ask the MC to write it to) and the location of * the data blob to write.
*/ staticint efx_reflash_parse_firmware_data(conststruct firmware *fw,
u32 *partition_type,
u32 *partition_subtype, const u8 **data, size_t *data_size)
{
size_t header_offset;
u32 type, subtype;
/* Some packaging formats (such as CMS/PKCS#7 signed images) * prepend a header for which finding the size is a non-trivial * task, so step through the firmware data until we find a valid * header. * * The checks are intended to reject firmware data that is clearly not * in the expected format. They do not need to be exhaustive as the * running firmware will perform its own comprehensive validity and * compatibility checks during the update procedure. * * Firmware packages may contain multiple reflash images, e.g. a * bundle containing one or more other images. Only check the * outermost container by stopping after the first candidate image * found even it is for an unsupported partition type.
*/ for (header_offset = 0; header_offset < fw->size; header_offset++) { if (efx_reflash_parse_snic_bundle_header(fw, header_offset,
partition_type,
partition_subtype,
data, data_size)) return 0;
if (efx_reflash_parse_snic_header(fw, header_offset,
partition_type,
partition_subtype, data,
data_size)) return 0;
/* Limit the number of status updates during the erase or write phases */ #define EFX_DEVLINK_STATUS_UPDATE_COUNT 50
/* Expected timeout for the efx_mcdi_nvram_update_finish_polled() */ #define EFX_DEVLINK_UPDATE_FINISH_TIMEOUT 900
/* Ideal erase chunk size. This is a balance between minimising the number of * MCDI requests to erase an entire partition whilst avoiding tripping the MCDI * RPC timeout.
*/ #define EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE (64 * 1024)
/* Partitions that cannot be erased or do not require erase before * write are advertised with a erase alignment/sector size of zero.
*/ if (align == 0) /* Nothing to do */ return 0;
if (partition_size % align) return -EINVAL;
/* Erase the entire NVRAM partition a chunk at a time to avoid * potentially tripping the MCDI RPC timeout.
*/ if (align >= EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE)
chunk = align; else
chunk = rounddown(EFX_NVRAM_ERASE_IDEAL_CHUNK_SIZE, align);
/* Write the NVRAM partition in chunks that are the largest multiple * of the partition's required write alignment that will fit into the * MCDI NVRAM_WRITE RPC payload.
*/ if (efx->type->mcdi_max_ver < 2)
write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM; else
write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM_MCDI2;
chunk = rounddown(write_max, align);
if (efx->type->flash_auto_partition) { /* NIC wants entire FW file including headers; * FW will validate 'subtype' if there is one
*/
type = NVRAM_PARTITION_TYPE_AUTO;
data = fw->data;
data_size = fw->size;
} else {
rc = efx_reflash_parse_firmware_data(fw, &type, &data_subtype, &data,
&data_size); if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Firmware image validation check failed"); goto out_unlock;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.