123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /* Copyright (C) 2018-2019, Intel Corporation. */
- #ifndef _PLDMFW_PRIVATE_H_
- #define _PLDMFW_PRIVATE_H_
- /* The following data structures define the layout of a firmware binary
- * following the "PLDM For Firmware Update Specification", DMTF standard
- * #DSP0267.
- *
- * pldmfw.c uses these structures to implement a simple engine that will parse
- * a fw binary file in this format and perform a firmware update for a given
- * device.
- *
- * Due to the variable sized data layout, alignment of fields within these
- * structures is not guaranteed when reading. For this reason, all multi-byte
- * field accesses should be done using the unaligned access macros.
- * Additionally, the standard specifies that multi-byte fields are in
- * LittleEndian format.
- *
- * The structure definitions are not made public, in order to keep direct
- * accesses within code that is prepared to deal with the limitation of
- * unaligned access.
- */
- /* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */
- static const uuid_t pldm_firmware_header_id =
- UUID_INIT(0xf018878c, 0xcb7d, 0x4943,
- 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02);
- /* Revision number of the PLDM header format this code supports */
- #define PACKAGE_HEADER_FORMAT_REVISION 0x01
- /* timestamp104 structure defined in PLDM Base specification */
- #define PLDM_TIMESTAMP_SIZE 13
- struct __pldm_timestamp {
- u8 b[PLDM_TIMESTAMP_SIZE];
- } __packed __aligned(1);
- /* Package Header Information */
- struct __pldm_header {
- uuid_t id; /* PackageHeaderIdentifier */
- u8 revision; /* PackageHeaderFormatRevision */
- __le16 size; /* PackageHeaderSize */
- struct __pldm_timestamp release_date; /* PackageReleaseDateTime */
- __le16 component_bitmap_len; /* ComponentBitmapBitLength */
- u8 version_type; /* PackageVersionStringType */
- u8 version_len; /* PackageVersionStringLength */
- /*
- * DSP0267 also includes the following variable length fields at the
- * end of this structure:
- *
- * PackageVersionString, length is version_len.
- *
- * The total size of this section is
- * sizeof(pldm_header) + version_len;
- */
- u8 version_string[]; /* PackageVersionString */
- } __packed __aligned(1);
- /* Firmware Device ID Record */
- struct __pldmfw_record_info {
- __le16 record_len; /* RecordLength */
- u8 descriptor_count; /* DescriptorCount */
- __le32 device_update_flags; /* DeviceUpdateOptionFlags */
- u8 version_type; /* ComponentImageSetVersionType */
- u8 version_len; /* ComponentImageSetVersionLength */
- __le16 package_data_len; /* FirmwareDevicePackageDataLength */
- /*
- * DSP0267 also includes the following variable length fields at the
- * end of this structure:
- *
- * ApplicableComponents, length is component_bitmap_len from header
- * ComponentImageSetVersionString, length is version_len
- * RecordDescriptors, a series of TLVs with 16bit type and length
- * FirmwareDevicePackageData, length is package_data_len
- *
- * The total size of each record is
- * sizeof(pldmfw_record_info) +
- * component_bitmap_len (converted to bytes!) +
- * version_len +
- * <length of RecordDescriptors> +
- * package_data_len
- */
- u8 variable_record_data[];
- } __packed __aligned(1);
- /* Firmware Descriptor Definition */
- struct __pldmfw_desc_tlv {
- __le16 type; /* DescriptorType */
- __le16 size; /* DescriptorSize */
- u8 data[]; /* DescriptorData */
- } __aligned(1);
- /* Firmware Device Identification Area */
- struct __pldmfw_record_area {
- u8 record_count; /* DeviceIDRecordCount */
- /* This is not a struct type because the size of each record varies */
- u8 records[];
- } __aligned(1);
- /* Individual Component Image Information */
- struct __pldmfw_component_info {
- __le16 classification; /* ComponentClassfication */
- __le16 identifier; /* ComponentIdentifier */
- __le32 comparison_stamp; /* ComponentComparisonStamp */
- __le16 options; /* componentOptions */
- __le16 activation_method; /* RequestedComponentActivationMethod */
- __le32 location_offset; /* ComponentLocationOffset */
- __le32 size; /* ComponentSize */
- u8 version_type; /* ComponentVersionStringType */
- u8 version_len; /* ComponentVersionStringLength */
- /*
- * DSP0267 also includes the following variable length fields at the
- * end of this structure:
- *
- * ComponentVersionString, length is version_len
- *
- * The total size of this section is
- * sizeof(pldmfw_component_info) + version_len;
- */
- u8 version_string[]; /* ComponentVersionString */
- } __packed __aligned(1);
- /* Component Image Information Area */
- struct __pldmfw_component_area {
- __le16 component_image_count;
- /* This is not a struct type because the component size varies */
- u8 components[];
- } __aligned(1);
- /**
- * pldm_first_desc_tlv
- * @start: byte offset of the start of the descriptor TLVs
- *
- * Converts the starting offset of the descriptor TLVs into a pointer to the
- * first descriptor.
- */
- #define pldm_first_desc_tlv(start) \
- ((const struct __pldmfw_desc_tlv *)(start))
- /**
- * pldm_next_desc_tlv
- * @desc: pointer to a descriptor TLV
- *
- * Finds the pointer to the next descriptor following a given descriptor
- */
- #define pldm_next_desc_tlv(desc) \
- ((const struct __pldmfw_desc_tlv *)((desc)->data + \
- get_unaligned_le16(&(desc)->size)))
- /**
- * pldm_for_each_desc_tlv
- * @i: variable to store descriptor index
- * @desc: variable to store descriptor pointer
- * @start: byte offset of the start of the descriptors
- * @count: the number of descriptors
- *
- * for loop macro to iterate over all of the descriptors of a given PLDM
- * record.
- */
- #define pldm_for_each_desc_tlv(i, desc, start, count) \
- for ((i) = 0, (desc) = pldm_first_desc_tlv(start); \
- (i) < (count); \
- (i)++, (desc) = pldm_next_desc_tlv(desc))
- /**
- * pldm_first_record
- * @start: byte offset of the start of the PLDM records
- *
- * Converts a starting offset of the PLDM records into a pointer to the first
- * record.
- */
- #define pldm_first_record(start) \
- ((const struct __pldmfw_record_info *)(start))
- /**
- * pldm_next_record
- * @record: pointer to a PLDM record
- *
- * Finds a pointer to the next record following a given record
- */
- #define pldm_next_record(record) \
- ((const struct __pldmfw_record_info *) \
- ((const u8 *)(record) + get_unaligned_le16(&(record)->record_len)))
- /**
- * pldm_for_each_record
- * @i: variable to store record index
- * @record: variable to store record pointer
- * @start: byte offset of the start of the records
- * @count: the number of records
- *
- * for loop macro to iterate over all of the records of a PLDM file.
- */
- #define pldm_for_each_record(i, record, start, count) \
- for ((i) = 0, (record) = pldm_first_record(start); \
- (i) < (count); \
- (i)++, (record) = pldm_next_record(record))
- /**
- * pldm_first_component
- * @start: byte offset of the start of the PLDM components
- *
- * Convert a starting offset of the PLDM components into a pointer to the
- * first component
- */
- #define pldm_first_component(start) \
- ((const struct __pldmfw_component_info *)(start))
- /**
- * pldm_next_component
- * @component: pointer to a PLDM component
- *
- * Finds a pointer to the next component following a given component
- */
- #define pldm_next_component(component) \
- ((const struct __pldmfw_component_info *)((component)->version_string + \
- (component)->version_len))
- /**
- * pldm_for_each_component
- * @i: variable to store component index
- * @component: variable to store component pointer
- * @start: byte offset to the start of the first component
- * @count: the number of components
- *
- * for loop macro to iterate over all of the components of a PLDM file.
- */
- #define pldm_for_each_component(i, component, start, count) \
- for ((i) = 0, (component) = pldm_first_component(start); \
- (i) < (count); \
- (i)++, (component) = pldm_next_component(component))
- #endif
|