![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 */ 0002 /* Copyright (C) 2018-2019, Intel Corporation. */ 0003 0004 #ifndef _PLDMFW_PRIVATE_H_ 0005 #define _PLDMFW_PRIVATE_H_ 0006 0007 /* The following data structures define the layout of a firmware binary 0008 * following the "PLDM For Firmware Update Specification", DMTF standard 0009 * #DSP0267. 0010 * 0011 * pldmfw.c uses these structures to implement a simple engine that will parse 0012 * a fw binary file in this format and perform a firmware update for a given 0013 * device. 0014 * 0015 * Due to the variable sized data layout, alignment of fields within these 0016 * structures is not guaranteed when reading. For this reason, all multi-byte 0017 * field accesses should be done using the unaligned access macros. 0018 * Additionally, the standard specifies that multi-byte fields are in 0019 * LittleEndian format. 0020 * 0021 * The structure definitions are not made public, in order to keep direct 0022 * accesses within code that is prepared to deal with the limitation of 0023 * unaligned access. 0024 */ 0025 0026 /* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */ 0027 static const uuid_t pldm_firmware_header_id = 0028 UUID_INIT(0xf018878c, 0xcb7d, 0x4943, 0029 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02); 0030 0031 /* Revision number of the PLDM header format this code supports */ 0032 #define PACKAGE_HEADER_FORMAT_REVISION 0x01 0033 0034 /* timestamp104 structure defined in PLDM Base specification */ 0035 #define PLDM_TIMESTAMP_SIZE 13 0036 struct __pldm_timestamp { 0037 u8 b[PLDM_TIMESTAMP_SIZE]; 0038 } __packed __aligned(1); 0039 0040 /* Package Header Information */ 0041 struct __pldm_header { 0042 uuid_t id; /* PackageHeaderIdentifier */ 0043 u8 revision; /* PackageHeaderFormatRevision */ 0044 __le16 size; /* PackageHeaderSize */ 0045 struct __pldm_timestamp release_date; /* PackageReleaseDateTime */ 0046 __le16 component_bitmap_len; /* ComponentBitmapBitLength */ 0047 u8 version_type; /* PackageVersionStringType */ 0048 u8 version_len; /* PackageVersionStringLength */ 0049 0050 /* 0051 * DSP0267 also includes the following variable length fields at the 0052 * end of this structure: 0053 * 0054 * PackageVersionString, length is version_len. 0055 * 0056 * The total size of this section is 0057 * sizeof(pldm_header) + version_len; 0058 */ 0059 u8 version_string[]; /* PackageVersionString */ 0060 } __packed __aligned(1); 0061 0062 /* Firmware Device ID Record */ 0063 struct __pldmfw_record_info { 0064 __le16 record_len; /* RecordLength */ 0065 u8 descriptor_count; /* DescriptorCount */ 0066 __le32 device_update_flags; /* DeviceUpdateOptionFlags */ 0067 u8 version_type; /* ComponentImageSetVersionType */ 0068 u8 version_len; /* ComponentImageSetVersionLength */ 0069 __le16 package_data_len; /* FirmwareDevicePackageDataLength */ 0070 0071 /* 0072 * DSP0267 also includes the following variable length fields at the 0073 * end of this structure: 0074 * 0075 * ApplicableComponents, length is component_bitmap_len from header 0076 * ComponentImageSetVersionString, length is version_len 0077 * RecordDescriptors, a series of TLVs with 16bit type and length 0078 * FirmwareDevicePackageData, length is package_data_len 0079 * 0080 * The total size of each record is 0081 * sizeof(pldmfw_record_info) + 0082 * component_bitmap_len (converted to bytes!) + 0083 * version_len + 0084 * <length of RecordDescriptors> + 0085 * package_data_len 0086 */ 0087 u8 variable_record_data[]; 0088 } __packed __aligned(1); 0089 0090 /* Firmware Descriptor Definition */ 0091 struct __pldmfw_desc_tlv { 0092 __le16 type; /* DescriptorType */ 0093 __le16 size; /* DescriptorSize */ 0094 u8 data[]; /* DescriptorData */ 0095 } __aligned(1); 0096 0097 /* Firmware Device Identification Area */ 0098 struct __pldmfw_record_area { 0099 u8 record_count; /* DeviceIDRecordCount */ 0100 /* This is not a struct type because the size of each record varies */ 0101 u8 records[]; 0102 } __aligned(1); 0103 0104 /* Individual Component Image Information */ 0105 struct __pldmfw_component_info { 0106 __le16 classification; /* ComponentClassfication */ 0107 __le16 identifier; /* ComponentIdentifier */ 0108 __le32 comparison_stamp; /* ComponentComparisonStamp */ 0109 __le16 options; /* componentOptions */ 0110 __le16 activation_method; /* RequestedComponentActivationMethod */ 0111 __le32 location_offset; /* ComponentLocationOffset */ 0112 __le32 size; /* ComponentSize */ 0113 u8 version_type; /* ComponentVersionStringType */ 0114 u8 version_len; /* ComponentVersionStringLength */ 0115 0116 /* 0117 * DSP0267 also includes the following variable length fields at the 0118 * end of this structure: 0119 * 0120 * ComponentVersionString, length is version_len 0121 * 0122 * The total size of this section is 0123 * sizeof(pldmfw_component_info) + version_len; 0124 */ 0125 u8 version_string[]; /* ComponentVersionString */ 0126 } __packed __aligned(1); 0127 0128 /* Component Image Information Area */ 0129 struct __pldmfw_component_area { 0130 __le16 component_image_count; 0131 /* This is not a struct type because the component size varies */ 0132 u8 components[]; 0133 } __aligned(1); 0134 0135 /** 0136 * pldm_first_desc_tlv 0137 * @start: byte offset of the start of the descriptor TLVs 0138 * 0139 * Converts the starting offset of the descriptor TLVs into a pointer to the 0140 * first descriptor. 0141 */ 0142 #define pldm_first_desc_tlv(start) \ 0143 ((const struct __pldmfw_desc_tlv *)(start)) 0144 0145 /** 0146 * pldm_next_desc_tlv 0147 * @desc: pointer to a descriptor TLV 0148 * 0149 * Finds the pointer to the next descriptor following a given descriptor 0150 */ 0151 #define pldm_next_desc_tlv(desc) \ 0152 ((const struct __pldmfw_desc_tlv *)((desc)->data + \ 0153 get_unaligned_le16(&(desc)->size))) 0154 0155 /** 0156 * pldm_for_each_desc_tlv 0157 * @i: variable to store descriptor index 0158 * @desc: variable to store descriptor pointer 0159 * @start: byte offset of the start of the descriptors 0160 * @count: the number of descriptors 0161 * 0162 * for loop macro to iterate over all of the descriptors of a given PLDM 0163 * record. 0164 */ 0165 #define pldm_for_each_desc_tlv(i, desc, start, count) \ 0166 for ((i) = 0, (desc) = pldm_first_desc_tlv(start); \ 0167 (i) < (count); \ 0168 (i)++, (desc) = pldm_next_desc_tlv(desc)) 0169 0170 /** 0171 * pldm_first_record 0172 * @start: byte offset of the start of the PLDM records 0173 * 0174 * Converts a starting offset of the PLDM records into a pointer to the first 0175 * record. 0176 */ 0177 #define pldm_first_record(start) \ 0178 ((const struct __pldmfw_record_info *)(start)) 0179 0180 /** 0181 * pldm_next_record 0182 * @record: pointer to a PLDM record 0183 * 0184 * Finds a pointer to the next record following a given record 0185 */ 0186 #define pldm_next_record(record) \ 0187 ((const struct __pldmfw_record_info *) \ 0188 ((const u8 *)(record) + get_unaligned_le16(&(record)->record_len))) 0189 0190 /** 0191 * pldm_for_each_record 0192 * @i: variable to store record index 0193 * @record: variable to store record pointer 0194 * @start: byte offset of the start of the records 0195 * @count: the number of records 0196 * 0197 * for loop macro to iterate over all of the records of a PLDM file. 0198 */ 0199 #define pldm_for_each_record(i, record, start, count) \ 0200 for ((i) = 0, (record) = pldm_first_record(start); \ 0201 (i) < (count); \ 0202 (i)++, (record) = pldm_next_record(record)) 0203 0204 /** 0205 * pldm_first_component 0206 * @start: byte offset of the start of the PLDM components 0207 * 0208 * Convert a starting offset of the PLDM components into a pointer to the 0209 * first component 0210 */ 0211 #define pldm_first_component(start) \ 0212 ((const struct __pldmfw_component_info *)(start)) 0213 0214 /** 0215 * pldm_next_component 0216 * @component: pointer to a PLDM component 0217 * 0218 * Finds a pointer to the next component following a given component 0219 */ 0220 #define pldm_next_component(component) \ 0221 ((const struct __pldmfw_component_info *)((component)->version_string + \ 0222 (component)->version_len)) 0223 0224 /** 0225 * pldm_for_each_component 0226 * @i: variable to store component index 0227 * @component: variable to store component pointer 0228 * @start: byte offset to the start of the first component 0229 * @count: the number of components 0230 * 0231 * for loop macro to iterate over all of the components of a PLDM file. 0232 */ 0233 #define pldm_for_each_component(i, component, start, count) \ 0234 for ((i) = 0, (component) = pldm_first_component(start); \ 0235 (i) < (count); \ 0236 (i)++, (component) = pldm_next_component(component)) 0237 0238 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |