brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 687ef22 Raw
239 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/* Copyright (C) 2018-2019, Intel Corporation. */3 4#ifndef _PLDMFW_PRIVATE_H_5#define _PLDMFW_PRIVATE_H_6 7/* The following data structures define the layout of a firmware binary8 * following the "PLDM For Firmware Update Specification", DMTF standard9 * #DSP0267.10 *11 * pldmfw.c uses these structures to implement a simple engine that will parse12 * a fw binary file in this format and perform a firmware update for a given13 * device.14 *15 * Due to the variable sized data layout, alignment of fields within these16 * structures is not guaranteed when reading. For this reason, all multi-byte17 * field accesses should be done using the unaligned access macros.18 * Additionally, the standard specifies that multi-byte fields are in19 * LittleEndian format.20 *21 * The structure definitions are not made public, in order to keep direct22 * accesses within code that is prepared to deal with the limitation of23 * unaligned access.24 */25 26/* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */27static const uuid_t pldm_firmware_header_id =28	UUID_INIT(0xf018878c, 0xcb7d, 0x4943,29		  0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02);30 31/* Revision number of the PLDM header format this code supports */32#define PACKAGE_HEADER_FORMAT_REVISION 0x0133 34/* timestamp104 structure defined in PLDM Base specification */35#define PLDM_TIMESTAMP_SIZE 1336struct __pldm_timestamp {37	u8 b[PLDM_TIMESTAMP_SIZE];38} __packed __aligned(1);39 40/* Package Header Information */41struct __pldm_header {42	uuid_t id;			    /* PackageHeaderIdentifier */43	u8 revision;			    /* PackageHeaderFormatRevision */44	__le16 size;			    /* PackageHeaderSize */45	struct __pldm_timestamp release_date; /* PackageReleaseDateTime */46	__le16 component_bitmap_len;	    /* ComponentBitmapBitLength */47	u8 version_type;		    /* PackageVersionStringType */48	u8 version_len;			    /* PackageVersionStringLength */49 50	/*51	 * DSP0267 also includes the following variable length fields at the52	 * end of this structure:53	 *54	 * PackageVersionString, length is version_len.55	 *56	 * The total size of this section is57	 *   sizeof(pldm_header) + version_len;58	 */59	u8 version_string[];		/* PackageVersionString */60} __packed __aligned(1);61 62/* Firmware Device ID Record */63struct __pldmfw_record_info {64	__le16 record_len;		/* RecordLength */65	u8 descriptor_count;		/* DescriptorCount */66	__le32 device_update_flags;	/* DeviceUpdateOptionFlags */67	u8 version_type;		/* ComponentImageSetVersionType */68	u8 version_len;			/* ComponentImageSetVersionLength */69	__le16 package_data_len;	/* FirmwareDevicePackageDataLength */70 71	/*72	 * DSP0267 also includes the following variable length fields at the73	 * end of this structure:74	 *75	 * ApplicableComponents, length is component_bitmap_len from header76	 * ComponentImageSetVersionString, length is version_len77	 * RecordDescriptors, a series of TLVs with 16bit type and length78	 * FirmwareDevicePackageData, length is package_data_len79	 *80	 * The total size of each record is81	 *   sizeof(pldmfw_record_info) +82	 *   component_bitmap_len (converted to bytes!) +83	 *   version_len +84	 *   <length of RecordDescriptors> +85	 *   package_data_len86	 */87	u8 variable_record_data[];88} __packed __aligned(1);89 90/* Firmware Descriptor Definition */91struct __pldmfw_desc_tlv {92	__le16 type;			/* DescriptorType */93	__le16 size;			/* DescriptorSize */94	u8 data[];			/* DescriptorData */95} __aligned(1);96 97/* Firmware Device Identification Area */98struct __pldmfw_record_area {99	u8 record_count;		/* DeviceIDRecordCount */100	/* This is not a struct type because the size of each record varies */101	u8 records[];102} __aligned(1);103 104/* Individual Component Image Information */105struct __pldmfw_component_info {106	__le16 classification;		/* ComponentClassfication */107	__le16 identifier;		/* ComponentIdentifier */108	__le32 comparison_stamp;	/* ComponentComparisonStamp */109	__le16 options;			/* componentOptions */110	__le16 activation_method;	/* RequestedComponentActivationMethod */111	__le32 location_offset;		/* ComponentLocationOffset */112	__le32 size;			/* ComponentSize */113	u8 version_type;		/* ComponentVersionStringType */114	u8 version_len;		/* ComponentVersionStringLength */115 116	/*117	 * DSP0267 also includes the following variable length fields at the118	 * end of this structure:119	 *120	 * ComponentVersionString, length is version_len121	 *122	 * The total size of this section is123	 *   sizeof(pldmfw_component_info) + version_len;124	 */125	u8 version_string[];		/* ComponentVersionString */126} __packed __aligned(1);127 128/* Component Image Information Area */129struct __pldmfw_component_area {130	__le16 component_image_count;131	/* This is not a struct type because the component size varies */132	u8 components[];133} __aligned(1);134 135/**136 * pldm_first_desc_tlv137 * @start: byte offset of the start of the descriptor TLVs138 *139 * Converts the starting offset of the descriptor TLVs into a pointer to the140 * first descriptor.141 */142#define pldm_first_desc_tlv(start)					\143	((const struct __pldmfw_desc_tlv *)(start))144 145/**146 * pldm_next_desc_tlv147 * @desc: pointer to a descriptor TLV148 *149 * Finds the pointer to the next descriptor following a given descriptor150 */151#define pldm_next_desc_tlv(desc)						\152	((const struct __pldmfw_desc_tlv *)((desc)->data +			\153					     get_unaligned_le16(&(desc)->size)))154 155/**156 * pldm_for_each_desc_tlv157 * @i: variable to store descriptor index158 * @desc: variable to store descriptor pointer159 * @start: byte offset of the start of the descriptors160 * @count: the number of descriptors161 *162 * for loop macro to iterate over all of the descriptors of a given PLDM163 * record.164 */165#define pldm_for_each_desc_tlv(i, desc, start, count)			\166	for ((i) = 0, (desc) = pldm_first_desc_tlv(start);		\167	     (i) < (count);						\168	     (i)++, (desc) = pldm_next_desc_tlv(desc))169 170/**171 * pldm_first_record172 * @start: byte offset of the start of the PLDM records173 *174 * Converts a starting offset of the PLDM records into a pointer to the first175 * record.176 */177#define pldm_first_record(start)					\178	((const struct __pldmfw_record_info *)(start))179 180/**181 * pldm_next_record182 * @record: pointer to a PLDM record183 *184 * Finds a pointer to the next record following a given record185 */186#define pldm_next_record(record)					\187	((const struct __pldmfw_record_info *)				\188	 ((const u8 *)(record) + get_unaligned_le16(&(record)->record_len)))189 190/**191 * pldm_for_each_record192 * @i: variable to store record index193 * @record: variable to store record pointer194 * @start: byte offset of the start of the records195 * @count: the number of records196 *197 * for loop macro to iterate over all of the records of a PLDM file.198 */199#define pldm_for_each_record(i, record, start, count)			\200	for ((i) = 0, (record) = pldm_first_record(start);		\201	     (i) < (count);						\202	     (i)++, (record) = pldm_next_record(record))203 204/**205 * pldm_first_component206 * @start: byte offset of the start of the PLDM components207 *208 * Convert a starting offset of the PLDM components into a pointer to the209 * first component210 */211#define pldm_first_component(start)					\212	((const struct __pldmfw_component_info *)(start))213 214/**215 * pldm_next_component216 * @component: pointer to a PLDM component217 *218 * Finds a pointer to the next component following a given component219 */220#define pldm_next_component(component)						\221	((const struct __pldmfw_component_info *)((component)->version_string +	\222						  (component)->version_len))223 224/**225 * pldm_for_each_component226 * @i: variable to store component index227 * @component: variable to store component pointer228 * @start: byte offset to the start of the first component229 * @count: the number of components230 *231 * for loop macro to iterate over all of the components of a PLDM file.232 */233#define pldm_for_each_component(i, component, start, count)		\234	for ((i) = 0, (component) = pldm_first_component(start);	\235	     (i) < (count);						\236	     (i)++, (component) = pldm_next_component(component))237 238#endif239