pldmfw_private.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* Copyright (C) 2018-2019, Intel Corporation. */
  3. #ifndef _PLDMFW_PRIVATE_H_
  4. #define _PLDMFW_PRIVATE_H_
  5. /* The following data structures define the layout of a firmware binary
  6. * following the "PLDM For Firmware Update Specification", DMTF standard
  7. * #DSP0267.
  8. *
  9. * pldmfw.c uses these structures to implement a simple engine that will parse
  10. * a fw binary file in this format and perform a firmware update for a given
  11. * device.
  12. *
  13. * Due to the variable sized data layout, alignment of fields within these
  14. * structures is not guaranteed when reading. For this reason, all multi-byte
  15. * field accesses should be done using the unaligned access macros.
  16. * Additionally, the standard specifies that multi-byte fields are in
  17. * LittleEndian format.
  18. *
  19. * The structure definitions are not made public, in order to keep direct
  20. * accesses within code that is prepared to deal with the limitation of
  21. * unaligned access.
  22. */
  23. /* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */
  24. static const uuid_t pldm_firmware_header_id =
  25. UUID_INIT(0xf018878c, 0xcb7d, 0x4943,
  26. 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02);
  27. /* Revision number of the PLDM header format this code supports */
  28. #define PACKAGE_HEADER_FORMAT_REVISION 0x01
  29. /* timestamp104 structure defined in PLDM Base specification */
  30. #define PLDM_TIMESTAMP_SIZE 13
  31. struct __pldm_timestamp {
  32. u8 b[PLDM_TIMESTAMP_SIZE];
  33. } __packed __aligned(1);
  34. /* Package Header Information */
  35. struct __pldm_header {
  36. uuid_t id; /* PackageHeaderIdentifier */
  37. u8 revision; /* PackageHeaderFormatRevision */
  38. __le16 size; /* PackageHeaderSize */
  39. struct __pldm_timestamp release_date; /* PackageReleaseDateTime */
  40. __le16 component_bitmap_len; /* ComponentBitmapBitLength */
  41. u8 version_type; /* PackageVersionStringType */
  42. u8 version_len; /* PackageVersionStringLength */
  43. /*
  44. * DSP0267 also includes the following variable length fields at the
  45. * end of this structure:
  46. *
  47. * PackageVersionString, length is version_len.
  48. *
  49. * The total size of this section is
  50. * sizeof(pldm_header) + version_len;
  51. */
  52. u8 version_string[]; /* PackageVersionString */
  53. } __packed __aligned(1);
  54. /* Firmware Device ID Record */
  55. struct __pldmfw_record_info {
  56. __le16 record_len; /* RecordLength */
  57. u8 descriptor_count; /* DescriptorCount */
  58. __le32 device_update_flags; /* DeviceUpdateOptionFlags */
  59. u8 version_type; /* ComponentImageSetVersionType */
  60. u8 version_len; /* ComponentImageSetVersionLength */
  61. __le16 package_data_len; /* FirmwareDevicePackageDataLength */
  62. /*
  63. * DSP0267 also includes the following variable length fields at the
  64. * end of this structure:
  65. *
  66. * ApplicableComponents, length is component_bitmap_len from header
  67. * ComponentImageSetVersionString, length is version_len
  68. * RecordDescriptors, a series of TLVs with 16bit type and length
  69. * FirmwareDevicePackageData, length is package_data_len
  70. *
  71. * The total size of each record is
  72. * sizeof(pldmfw_record_info) +
  73. * component_bitmap_len (converted to bytes!) +
  74. * version_len +
  75. * <length of RecordDescriptors> +
  76. * package_data_len
  77. */
  78. u8 variable_record_data[];
  79. } __packed __aligned(1);
  80. /* Firmware Descriptor Definition */
  81. struct __pldmfw_desc_tlv {
  82. __le16 type; /* DescriptorType */
  83. __le16 size; /* DescriptorSize */
  84. u8 data[]; /* DescriptorData */
  85. } __aligned(1);
  86. /* Firmware Device Identification Area */
  87. struct __pldmfw_record_area {
  88. u8 record_count; /* DeviceIDRecordCount */
  89. /* This is not a struct type because the size of each record varies */
  90. u8 records[];
  91. } __aligned(1);
  92. /* Individual Component Image Information */
  93. struct __pldmfw_component_info {
  94. __le16 classification; /* ComponentClassfication */
  95. __le16 identifier; /* ComponentIdentifier */
  96. __le32 comparison_stamp; /* ComponentComparisonStamp */
  97. __le16 options; /* componentOptions */
  98. __le16 activation_method; /* RequestedComponentActivationMethod */
  99. __le32 location_offset; /* ComponentLocationOffset */
  100. __le32 size; /* ComponentSize */
  101. u8 version_type; /* ComponentVersionStringType */
  102. u8 version_len; /* ComponentVersionStringLength */
  103. /*
  104. * DSP0267 also includes the following variable length fields at the
  105. * end of this structure:
  106. *
  107. * ComponentVersionString, length is version_len
  108. *
  109. * The total size of this section is
  110. * sizeof(pldmfw_component_info) + version_len;
  111. */
  112. u8 version_string[]; /* ComponentVersionString */
  113. } __packed __aligned(1);
  114. /* Component Image Information Area */
  115. struct __pldmfw_component_area {
  116. __le16 component_image_count;
  117. /* This is not a struct type because the component size varies */
  118. u8 components[];
  119. } __aligned(1);
  120. /**
  121. * pldm_first_desc_tlv
  122. * @start: byte offset of the start of the descriptor TLVs
  123. *
  124. * Converts the starting offset of the descriptor TLVs into a pointer to the
  125. * first descriptor.
  126. */
  127. #define pldm_first_desc_tlv(start) \
  128. ((const struct __pldmfw_desc_tlv *)(start))
  129. /**
  130. * pldm_next_desc_tlv
  131. * @desc: pointer to a descriptor TLV
  132. *
  133. * Finds the pointer to the next descriptor following a given descriptor
  134. */
  135. #define pldm_next_desc_tlv(desc) \
  136. ((const struct __pldmfw_desc_tlv *)((desc)->data + \
  137. get_unaligned_le16(&(desc)->size)))
  138. /**
  139. * pldm_for_each_desc_tlv
  140. * @i: variable to store descriptor index
  141. * @desc: variable to store descriptor pointer
  142. * @start: byte offset of the start of the descriptors
  143. * @count: the number of descriptors
  144. *
  145. * for loop macro to iterate over all of the descriptors of a given PLDM
  146. * record.
  147. */
  148. #define pldm_for_each_desc_tlv(i, desc, start, count) \
  149. for ((i) = 0, (desc) = pldm_first_desc_tlv(start); \
  150. (i) < (count); \
  151. (i)++, (desc) = pldm_next_desc_tlv(desc))
  152. /**
  153. * pldm_first_record
  154. * @start: byte offset of the start of the PLDM records
  155. *
  156. * Converts a starting offset of the PLDM records into a pointer to the first
  157. * record.
  158. */
  159. #define pldm_first_record(start) \
  160. ((const struct __pldmfw_record_info *)(start))
  161. /**
  162. * pldm_next_record
  163. * @record: pointer to a PLDM record
  164. *
  165. * Finds a pointer to the next record following a given record
  166. */
  167. #define pldm_next_record(record) \
  168. ((const struct __pldmfw_record_info *) \
  169. ((const u8 *)(record) + get_unaligned_le16(&(record)->record_len)))
  170. /**
  171. * pldm_for_each_record
  172. * @i: variable to store record index
  173. * @record: variable to store record pointer
  174. * @start: byte offset of the start of the records
  175. * @count: the number of records
  176. *
  177. * for loop macro to iterate over all of the records of a PLDM file.
  178. */
  179. #define pldm_for_each_record(i, record, start, count) \
  180. for ((i) = 0, (record) = pldm_first_record(start); \
  181. (i) < (count); \
  182. (i)++, (record) = pldm_next_record(record))
  183. /**
  184. * pldm_first_component
  185. * @start: byte offset of the start of the PLDM components
  186. *
  187. * Convert a starting offset of the PLDM components into a pointer to the
  188. * first component
  189. */
  190. #define pldm_first_component(start) \
  191. ((const struct __pldmfw_component_info *)(start))
  192. /**
  193. * pldm_next_component
  194. * @component: pointer to a PLDM component
  195. *
  196. * Finds a pointer to the next component following a given component
  197. */
  198. #define pldm_next_component(component) \
  199. ((const struct __pldmfw_component_info *)((component)->version_string + \
  200. (component)->version_len))
  201. /**
  202. * pldm_for_each_component
  203. * @i: variable to store component index
  204. * @component: variable to store component pointer
  205. * @start: byte offset to the start of the first component
  206. * @count: the number of components
  207. *
  208. * for loop macro to iterate over all of the components of a PLDM file.
  209. */
  210. #define pldm_for_each_component(i, component, start, count) \
  211. for ((i) = 0, (component) = pldm_first_component(start); \
  212. (i) < (count); \
  213. (i)++, (component) = pldm_next_component(component))
  214. #endif