Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* Copyright (C) 2018-2019, Intel Corporation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/pldmfw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "pldmfw_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /* Internal structure used to store details about the PLDM image file as it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * being validated and processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) struct pldmfw_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	struct pldmfw *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	/* current offset of firmware image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	size_t offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct list_head records;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct list_head components;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	/* PLDM Firmware Package Header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	const struct __pldm_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	u16 total_header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	/* length of the component bitmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u16 component_bitmap_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	u16 bitmap_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	/* Start of the component image information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	u16 component_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	const u8 *component_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	/* Start pf the firmware device id records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	const u8 *record_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	u8 record_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	/* The CRC at the end of the package header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	u32 header_crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct pldmfw_record *matching_record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * pldm_check_fw_space - Verify that the firmware image has space left
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * @offset: offset to start from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * @length: length to check for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * Verify that the firmware data can hold a chunk of bytes with the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * offset and length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * Returns: zero on success, or -EFAULT if the image does not have enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * space left to fit the expected length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) pldm_check_fw_space(struct pldmfw_priv *data, size_t offset, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	size_t expected_size = offset + length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct device *dev = data->context->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if (data->fw->size < expected_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		dev_dbg(dev, "Firmware file size smaller than expected. Got %zu bytes, needed %zu bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			data->fw->size, expected_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * pldm_move_fw_offset - Move the current firmware offset forward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @bytes_to_move: number of bytes to move the offset forward by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * Check that there is enough space past the current offset, and then move the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * offset forward by this ammount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * Returns: zero on success, or -EFAULT if the image is too small to fit the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * expected length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) pldm_move_fw_offset(struct pldmfw_priv *data, size_t bytes_to_move)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	err = pldm_check_fw_space(data, data->offset, bytes_to_move);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	data->offset += bytes_to_move;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * pldm_parse_header - Validate and extract details about the PLDM header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * Performs initial basic verification of the PLDM image, up to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * firmware record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * This includes the following checks and extractions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  *   * Verify that the UUID at the start of the header matches the expected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *     value as defined in the DSP0267 PLDM specification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  *   * Check that the revision is 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  *   * Extract the total header_size and verify that the image is large enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  *     to contain at least the length of this header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  *   * Extract the size of the component bitmap length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  *   * Extract a pointer to the start of the record area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int pldm_parse_header(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	const struct __pldmfw_record_area *record_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	struct device *dev = data->context->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	const struct __pldm_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	size_t header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	err = pldm_move_fw_offset(data, sizeof(*header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	header = (const struct __pldm_header *)data->fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	data->header = header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (!uuid_equal(&header->id, &pldm_firmware_header_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		dev_dbg(dev, "Invalid package header identifier. Expected UUID %pUB, but got %pUB\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			&pldm_firmware_header_id, &header->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (header->revision != PACKAGE_HEADER_FORMAT_REVISION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		dev_dbg(dev, "Invalid package header revision. Expected revision %u but got %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			PACKAGE_HEADER_FORMAT_REVISION, header->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	data->total_header_size = get_unaligned_le16(&header->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	header_size = data->total_header_size - sizeof(*header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	err = pldm_check_fw_space(data, data->offset, header_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	data->component_bitmap_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		get_unaligned_le16(&header->component_bitmap_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	if (data->component_bitmap_len % 8 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		dev_dbg(dev, "Invalid component bitmap length. The length is %u, which is not a multiple of 8\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			data->component_bitmap_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	data->bitmap_size = data->component_bitmap_len / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	err = pldm_move_fw_offset(data, header->version_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	/* extract a pointer to the record area, which just follows the main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	 * PLDM header data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	record_area = (const struct __pldmfw_record_area *)(data->fw->data +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 							 data->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	err = pldm_move_fw_offset(data, sizeof(*record_area));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	data->record_count = record_area->record_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	data->record_start = record_area->records;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * pldm_check_desc_tlv_len - Check that the length matches expectation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * @data: pointer to image details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * @type: the descriptor type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * @size: the length from the descriptor header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * If the descriptor type is one of the documented descriptor types according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * to the standard, verify that the provided length matches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * If the type is not recognized or is VENDOR_DEFINED, return zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  * Returns: zero on success, or -EINVAL if the specified size of a standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * TLV does not match the expected value defined for that TLV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pldm_check_desc_tlv_len(struct pldmfw_priv *data, u16 type, u16 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	struct device *dev = data->context->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	u16 expected_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	case PLDM_DESC_ID_PCI_VENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	case PLDM_DESC_ID_PCI_DEVICE_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	case PLDM_DESC_ID_PCI_SUBVENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	case PLDM_DESC_ID_PCI_SUBDEV_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		expected_size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	case PLDM_DESC_ID_PCI_REVISION_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		expected_size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	case PLDM_DESC_ID_PNP_VENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		expected_size = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	case PLDM_DESC_ID_IANA_ENTERPRISE_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	case PLDM_DESC_ID_ACPI_VENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	case PLDM_DESC_ID_PNP_PRODUCT_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	case PLDM_DESC_ID_ACPI_PRODUCT_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		expected_size = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	case PLDM_DESC_ID_UUID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		expected_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	case PLDM_DESC_ID_VENDOR_DEFINED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		/* Do not report an error on an unexpected TLV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		dev_dbg(dev, "Found unrecognized TLV type 0x%04x\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	if (size != expected_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		dev_dbg(dev, "Found TLV type 0x%04x with unexpected length. Got %u bytes, but expected %u bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			type, size, expected_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  * pldm_parse_desc_tlvs - Check and skip past a number of TLVs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  * @record: pointer to the record this TLV belongs too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * @desc_count: descriptor count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * From the current offset, read and extract the descriptor TLVs, updating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * current offset each time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) pldm_parse_desc_tlvs(struct pldmfw_priv *data, struct pldmfw_record *record, u8 desc_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	const struct __pldmfw_desc_tlv *__desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	const u8 *desc_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	desc_start = data->fw->data + data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	pldm_for_each_desc_tlv(i, __desc, desc_start, desc_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		struct pldmfw_desc_tlv *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		u16 type, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		err = pldm_move_fw_offset(data, sizeof(*__desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		type = get_unaligned_le16(&__desc->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		/* According to DSP0267, this only includes the data field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		size = get_unaligned_le16(&__desc->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		err = pldm_check_desc_tlv_len(data, type, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		/* check that we have space and move the offset forward */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		err = pldm_move_fw_offset(data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		desc->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		desc->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		desc->data = __desc->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		list_add_tail(&desc->entry, &record->descs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)  * pldm_parse_one_record - Verify size of one PLDM record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)  * @data: pointer to image details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * @__record: pointer to the record to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * This function checks that the record size does not exceed either the size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  * of the firmware file or the total length specified in the header section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)  * It also verifies that the recorded length of the start of the record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)  * matches the size calculated by adding the static structure length, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)  * component bitmap length, the version string length, the length of all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  * descriptor TLVs, and the length of the package data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pldm_parse_one_record(struct pldmfw_priv *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		      const struct __pldmfw_record_info *__record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	struct pldmfw_record *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	size_t measured_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	const u8 *bitmap_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	u16 record_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	/* Make a copy and insert it into the record list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	record = kzalloc(sizeof(*record), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (!record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	INIT_LIST_HEAD(&record->descs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	list_add_tail(&record->entry, &data->records);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	/* Then check that we have space and move the offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	err = pldm_move_fw_offset(data, sizeof(*__record));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	record_len = get_unaligned_le16(&__record->record_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	record->package_data_len = get_unaligned_le16(&__record->package_data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	record->version_len = __record->version_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	record->version_type = __record->version_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	bitmap_ptr = data->fw->data + data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	/* check that we have space for the component bitmap length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	err = pldm_move_fw_offset(data, data->bitmap_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	record->component_bitmap_len = data->component_bitmap_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	record->component_bitmap = bitmap_zalloc(record->component_bitmap_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 						 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	if (!record->component_bitmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	for (i = 0; i < data->bitmap_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		bitmap_set_value8(record->component_bitmap, bitmap_ptr[i], i * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	record->version_string = data->fw->data + data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	err = pldm_move_fw_offset(data, record->version_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	/* Scan through the descriptor TLVs and find the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	err = pldm_parse_desc_tlvs(data, record, __record->descriptor_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	record->package_data = data->fw->data + data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	err = pldm_move_fw_offset(data, record->package_data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	measured_length = data->offset - ((const u8 *)__record - data->fw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	if (measured_length != record_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		dev_dbg(data->context->dev, "Unexpected record length. Measured record length is %zu bytes, expected length is %u bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 			measured_length, record_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)  * pldm_parse_records - Locate the start of the component area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  * Extract the record count, and loop through each record, searching for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  * component area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int pldm_parse_records(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	const struct __pldmfw_component_area *component_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	const struct __pldmfw_record_info *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	pldm_for_each_record(i, record, data->record_start, data->record_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		err = pldm_parse_one_record(data, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	/* Extract a pointer to the component area, which just follows the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	 * PLDM device record data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	component_area = (const struct __pldmfw_component_area *)(data->fw->data + data->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	err = pldm_move_fw_offset(data, sizeof(*component_area));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	data->component_count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		get_unaligned_le16(&component_area->component_image_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	data->component_start = component_area->components;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  * pldm_parse_components - Locate the CRC header checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)  * Extract the component count, and find the pointer to the component area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)  * Scan through each component searching for the end, which should point to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)  * the package header checksum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)  * Extract the package header CRC and save it for verification.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static int pldm_parse_components(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	const struct __pldmfw_component_info *__component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	struct device *dev = data->context->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	const u8 *header_crc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	pldm_for_each_component(i, __component, data->component_start, data->component_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		struct pldmfw_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		u32 offset, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		err = pldm_move_fw_offset(data, sizeof(*__component));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		err = pldm_move_fw_offset(data, __component->version_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		offset = get_unaligned_le32(&__component->location_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		size = get_unaligned_le32(&__component->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		err = pldm_check_fw_space(data, offset, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		component = kzalloc(sizeof(*component), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (!component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		component->index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		component->classification = get_unaligned_le16(&__component->classification);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		component->identifier = get_unaligned_le16(&__component->identifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		component->comparison_stamp = get_unaligned_le32(&__component->comparison_stamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		component->options = get_unaligned_le16(&__component->options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		component->activation_method = get_unaligned_le16(&__component->activation_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		component->version_type = __component->version_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		component->version_len = __component->version_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		component->version_string = __component->version_string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		component->component_data = data->fw->data + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		component->component_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		list_add_tail(&component->entry, &data->components);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	header_crc_ptr = data->fw->data + data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	err = pldm_move_fw_offset(data, sizeof(data->header_crc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	/* Make sure that we reached the expected offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (data->offset != data->total_header_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		dev_dbg(dev, "Invalid firmware header size. Expected %u but got %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 			data->total_header_size, data->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	data->header_crc = get_unaligned_le32(header_crc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  * pldm_verify_header_crc - Verify that the CRC in the header matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  * Calculates the 32-bit CRC using the standard IEEE 802.3 CRC polynomial and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)  * compares it to the value stored in the header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * Returns: zero on success if the CRC matches, or -EBADMSG on an invalid CRC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int pldm_verify_header_crc(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	struct device *dev = data->context->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	u32 calculated_crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	size_t length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	/* Calculate the 32-bit CRC of the header header contents up to but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	 * not including the checksum. Note that the Linux crc32_le function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	 * does not perform an expected final XOR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	length = data->offset - sizeof(data->header_crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	calculated_crc = crc32_le(~0, data->fw->data, length) ^ ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	if (calculated_crc != data->header_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		dev_dbg(dev, "Invalid CRC in firmware header. Got 0x%08x but expected 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 			calculated_crc, data->header_crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		return -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  * pldmfw_free_priv - Free memory allocated while parsing the PLDM image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)  * @data: pointer to the PLDM data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  * Loops through and clears all allocated memory associated with each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)  * allocated descriptor, record, and component.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void pldmfw_free_priv(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	struct pldmfw_component *component, *c_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	struct pldmfw_record *record, *r_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	struct pldmfw_desc_tlv *desc, *d_safe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	list_for_each_entry_safe(component, c_safe, &data->components, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		list_del(&component->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		kfree(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	list_for_each_entry_safe(record, r_safe, &data->records, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		list_for_each_entry_safe(desc, d_safe, &record->descs, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 			list_del(&desc->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			kfree(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		if (record->component_bitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			bitmap_free(record->component_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 			record->component_bitmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		list_del(&record->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		kfree(record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)  * pldm_parse_image - parse and extract details from PLDM image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)  * Verify that the firmware file contains valid data for a PLDM firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)  * file. Extract useful pointers and data from the firmware file and store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)  * them in the data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)  * The PLDM firmware file format is defined in DMTF DSP0267 1.0.0. Care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)  * should be taken to use get_unaligned_le* when accessing data from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)  * pointers in data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static int pldm_parse_image(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	if (WARN_ON(!(data->context->dev && data->fw->data && data->fw->size)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	err = pldm_parse_header(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	err = pldm_parse_records(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	err = pldm_parse_components(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	return pldm_verify_header_crc(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* these are u32 so that we can store PCI_ANY_ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct pldm_pci_record_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	int vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	int device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	int subsystem_vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	int subsystem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)  * pldmfw_op_pci_match_record - Check if a PCI device matches the record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)  * @context: PLDM fw update structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)  * @record: list of records extracted from the PLDM image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)  * Determine of the PCI device associated with this device matches the record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)  * data provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)  * Searches the descriptor TLVs and extracts the relevant descriptor data into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)  * a pldm_pci_record_id. This is then compared against the PCI device ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)  * information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)  * Returns: true if the device matches the record, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	struct pci_dev *pdev = to_pci_dev(context->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	struct pldm_pci_record_id id = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		.vendor = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		.device = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		.subsystem_vendor = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		.subsystem_device = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	struct pldmfw_desc_tlv *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	list_for_each_entry(desc, &record->descs, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 		u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		int *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 		switch (desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		case PLDM_DESC_ID_PCI_VENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 			ptr = &id.vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		case PLDM_DESC_ID_PCI_DEVICE_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 			ptr = &id.device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		case PLDM_DESC_ID_PCI_SUBVENDOR_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 			ptr = &id.subsystem_vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		case PLDM_DESC_ID_PCI_SUBDEV_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 			ptr = &id.subsystem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 			/* Skip unrelated TLVs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		value = get_unaligned_le16(desc->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 		/* A value of zero for one of the descriptors is sometimes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		 * used when the record should ignore this field when matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		 * device. For example if the record applies to any subsystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		 * device or vendor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 		if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 			*ptr = (int)value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 			*ptr = PCI_ANY_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	if ((id.vendor == PCI_ANY_ID || id.vendor == pdev->vendor) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	    (id.device == PCI_ANY_ID || id.device == pdev->device) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	    (id.subsystem_vendor == PCI_ANY_ID || id.subsystem_vendor == pdev->subsystem_vendor) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	    (id.subsystem_device == PCI_ANY_ID || id.subsystem_device == pdev->subsystem_device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) EXPORT_SYMBOL(pldmfw_op_pci_match_record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)  * pldm_find_matching_record - Find the first matching PLDM record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)  * Search through PLDM records and find the first matching entry. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)  * expected that only one entry matches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)  * Store a pointer to the matching record, if found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)  * Returns: zero on success, or -ENOENT if no matching record is found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int pldm_find_matching_record(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	struct pldmfw_record *record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	list_for_each_entry(record, &data->records, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		if (data->context->ops->match_record(data->context, record)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			data->matching_record = record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)  * pldm_send_package_data - Send firmware the package data for the record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)  * Send the package data associated with the matching record to the firmware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)  * using the send_pkg_data operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) pldm_send_package_data(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	struct pldmfw_record *record = data->matching_record;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	const struct pldmfw_ops *ops = data->context->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	return ops->send_package_data(data->context, record->package_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 				      record->package_data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)  * pldm_send_component_tables - Send component table information to firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)  * Loop over each component, sending the applicable components to the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)  * via the send_component_table operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) pldm_send_component_tables(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	unsigned long *bitmap = data->matching_record->component_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	struct pldmfw_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	list_for_each_entry(component, &data->components, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 		u8 index = component->index, transfer_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		/* Skip components which are not intended for this device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		if (!test_bit(index, bitmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		/* determine whether this is the start, middle, end, or both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 		 * the start and end of the component tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 		if (index == find_first_bit(bitmap, data->component_bitmap_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 			transfer_flag |= PLDM_TRANSFER_FLAG_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 		if (index == find_last_bit(bitmap, data->component_bitmap_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 			transfer_flag |= PLDM_TRANSFER_FLAG_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 		if (!transfer_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 			transfer_flag = PLDM_TRANSFER_FLAG_MIDDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 		err = data->context->ops->send_component_table(data->context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 							       component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 							       transfer_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)  * pldm_flash_components - Program each component to device flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)  * Loop through each component that is active for the matching device record,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)  * and send it to the device driver for flashing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static int pldm_flash_components(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	unsigned long *bitmap = data->matching_record->component_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	struct pldmfw_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	list_for_each_entry(component, &data->components, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 		u8 index = component->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		/* Skip components which are not intended for this device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 		if (!test_bit(index, bitmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 		err = data->context->ops->flash_component(data->context, component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)  * pldm_finalize_update - Finalize the device flash update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)  * @data: pointer to private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)  * Tell the device driver to perform any remaining logic to complete the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)  * device update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)  * Returns: zero on success, or a PLFM_FWU error indicating the reason for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)  * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static int pldm_finalize_update(struct pldmfw_priv *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	if (data->context->ops->finalize_update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		return data->context->ops->finalize_update(data->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)  * pldmfw_flash_image - Write a PLDM-formatted firmware image to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)  * @context: ops and data for firmware update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)  * @fw: firmware object pointing to the relevant firmware file to program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)  * Parse the data for a given firmware file, verifying that it is a valid PLDM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)  * formatted image that matches this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)  * Extract the device record Package Data and Component Tables and send them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)  * to the device firmware. Extract and write the flash data for each of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)  * components indicated in the firmware file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)  * Returns: zero on success, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	struct pldmfw_priv *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 	data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	INIT_LIST_HEAD(&data->records);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	INIT_LIST_HEAD(&data->components);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	data->fw = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	data->context = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	err = pldm_parse_image(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 		goto out_release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	err = pldm_find_matching_record(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		goto out_release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	err = pldm_send_package_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 		goto out_release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 	err = pldm_send_component_tables(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 		goto out_release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	err = pldm_flash_components(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 		goto out_release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 	err = pldm_finalize_update(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) out_release_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	pldmfw_free_priv(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) EXPORT_SYMBOL(pldmfw_flash_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) MODULE_AUTHOR("Jacob Keller <jacob.e.keller@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) MODULE_DESCRIPTION("PLDM firmware flash update library");