Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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 binary
  8 * following the "PLDM For Firmware Update Specification", DMTF standard
  9 * #DSP0267.
 10 *
 11 * pldmfw.c uses these structures to implement a simple engine that will parse
 12 * a fw binary file in this format and perform a firmware update for a given
 13 * device.
 14 *
 15 * Due to the variable sized data layout, alignment of fields within these
 16 * structures is not guaranteed when reading. For this reason, all multi-byte
 17 * field accesses should be done using the unaligned access macros.
 18 * Additionally, the standard specifies that multi-byte fields are in
 19 * LittleEndian format.
 20 *
 21 * The structure definitions are not made public, in order to keep direct
 22 * accesses within code that is prepared to deal with the limitation of
 23 * 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 0x01
 33
 34/* timestamp104 structure defined in PLDM Base specification */
 35#define PLDM_TIMESTAMP_SIZE 13
 36struct __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 the
 52	 * end of this structure:
 53	 *
 54	 * PackageVersionString, length is version_len.
 55	 *
 56	 * The total size of this section is
 57	 *   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 the
 73	 * end of this structure:
 74	 *
 75	 * ApplicableComponents, length is component_bitmap_len from header
 76	 * ComponentImageSetVersionString, length is version_len
 77	 * RecordDescriptors, a series of TLVs with 16bit type and length
 78	 * FirmwareDevicePackageData, length is package_data_len
 79	 *
 80	 * The total size of each record is
 81	 *   sizeof(pldmfw_record_info) +
 82	 *   component_bitmap_len (converted to bytes!) +
 83	 *   version_len +
 84	 *   <length of RecordDescriptors> +
 85	 *   package_data_len
 86	 */
 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 the
118	 * end of this structure:
119	 *
120	 * ComponentVersionString, length is version_len
121	 *
122	 * The total size of this section is
123	 *   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_tlv
137 * @start: byte offset of the start of the descriptor TLVs
138 *
139 * Converts the starting offset of the descriptor TLVs into a pointer to the
140 * first descriptor.
141 */
142#define pldm_first_desc_tlv(start)					\
143	((const struct __pldmfw_desc_tlv *)(start))
144
145/**
146 * pldm_next_desc_tlv
147 * @desc: pointer to a descriptor TLV
148 *
149 * Finds the pointer to the next descriptor following a given descriptor
150 */
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_tlv
157 * @i: variable to store descriptor index
158 * @desc: variable to store descriptor pointer
159 * @start: byte offset of the start of the descriptors
160 * @count: the number of descriptors
161 *
162 * for loop macro to iterate over all of the descriptors of a given PLDM
163 * 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_record
172 * @start: byte offset of the start of the PLDM records
173 *
174 * Converts a starting offset of the PLDM records into a pointer to the first
175 * record.
176 */
177#define pldm_first_record(start)					\
178	((const struct __pldmfw_record_info *)(start))
179
180/**
181 * pldm_next_record
182 * @record: pointer to a PLDM record
183 *
184 * Finds a pointer to the next record following a given record
185 */
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_record
192 * @i: variable to store record index
193 * @record: variable to store record pointer
194 * @start: byte offset of the start of the records
195 * @count: the number of records
196 *
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_component
206 * @start: byte offset of the start of the PLDM components
207 *
208 * Convert a starting offset of the PLDM components into a pointer to the
209 * first component
210 */
211#define pldm_first_component(start)					\
212	((const struct __pldmfw_component_info *)(start))
213
214/**
215 * pldm_next_component
216 * @component: pointer to a PLDM component
217 *
218 * Finds a pointer to the next component following a given component
219 */
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_component
226 * @i: variable to store component index
227 * @component: variable to store component pointer
228 * @start: byte offset to the start of the first component
229 * @count: the number of components
230 *
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#endif