cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pldmfw_private.h (7898B)


      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