GNU Linux-libre 5.19-rc6-gnu
[releases.git] / lib / pldmfw / pldmfw_private.h
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 */
27 static 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
36 struct __pldm_timestamp {
37         u8 b[PLDM_TIMESTAMP_SIZE];
38 } __packed __aligned(1);
39
40 /* Package Header Information */
41 struct __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 */
63 struct __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 */
91 struct __pldmfw_desc_tlv {
92         __le16 type;                    /* DescriptorType */
93         __le16 size;                    /* DescriptorSize */
94         u8 data[];                      /* DescriptorData */
95 } __aligned(1);
96
97 /* Firmware Device Identification Area */
98 struct __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 */
105 struct __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 */
129 struct __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