1 #include <inttypes.h>
2 #include <libpldm/firmware_update.h>
3
4 #include <cstring>
5 #include <optional>
6 #include <string>
7 #include <vector>
8
create_pldm_firmware_device_descriptor_v1_0_0(uint8_t * b,ssize_t i,uint16_t descType,std::vector<uint8_t> & data)9 static ssize_t create_pldm_firmware_device_descriptor_v1_0_0(
10 uint8_t* b, ssize_t i, uint16_t descType, std::vector<uint8_t>& data)
11 {
12 // DescriptorType, Table 7. (0x0001 == IANA Enterprise ID, 4 bytes)
13 b[i++] = (descType >> 0) & 0xff;
14 b[i++] = (descType >> 8) & 0xff;
15
16 // DescriptorLength
17 b[i++] = (data.size() >> 0) & 0xff;
18 b[i++] = (data.size() >> 8) & 0xff;
19
20 // DescriptorData
21 for (uint8_t v : data)
22 {
23 b[i++] = v;
24 }
25
26 return i;
27 }
28
create_pldm_firmware_device_vendor_defined_descriptor_v1_0_0(uint8_t * b,ssize_t i,std::vector<uint8_t> & data)29 static ssize_t create_pldm_firmware_device_vendor_defined_descriptor_v1_0_0(
30 uint8_t* b, ssize_t i, std::vector<uint8_t>& data)
31 {
32 const uint16_t descType = 0xffff; // vendor defined
33
34 // DescriptorType, Table 7.
35 b[i++] = (descType >> 0) & 0xff;
36 b[i++] = (descType >> 8) & 0xff;
37
38 // DescriptorLength
39 const uint16_t length = data.size() + 3; // data and the additional fields
40 b[i++] = (length >> 0) & 0xff;
41 b[i++] = (length >> 8) & 0xff;
42
43 // VendorDefinedDescriptorTitleStringType
44 b[i++] = 0x1; // type 1 = ascii
45
46 // VendorDefinedDescriptorTitleStringLength
47 b[i++] = data.size();
48
49 // VendorDefinedDescriptorTitleString
50 for (uint8_t v : data)
51 {
52 b[i++] = v;
53 }
54
55 // VendorDefinedDescriptorData
56 b[i++] = 0x00;
57
58 return i;
59 }
60
create_pldm_firmware_device_descriptors_v1_0_0(uint8_t * b,ssize_t i,const std::optional<uint32_t> & optVendorIANA,const std::optional<std::string> & optCompatible,size_t * actual_count)61 static ssize_t create_pldm_firmware_device_descriptors_v1_0_0(
62 uint8_t* b, ssize_t i, const std::optional<uint32_t>& optVendorIANA,
63 const std::optional<std::string>& optCompatible, size_t* actual_count)
64 {
65 // RecordDescriptiors. The initial descriptor is restricted.
66 // In our case we use iana for the first descriptor.
67
68 std::vector<uint8_t> descriptorData = {0xaf, 0xaf, 0xaf, 0xaf};
69
70 if (optVendorIANA.has_value())
71 {
72 uint32_t v = optVendorIANA.value();
73 descriptorData[0] = (v >> 0) & 0xff;
74 descriptorData[1] = (v >> 8) & 0xff;
75 descriptorData[2] = (v >> 16) & 0xff;
76 descriptorData[3] = (v >> 24) & 0xff;
77 }
78
79 i = create_pldm_firmware_device_descriptor_v1_0_0(b, i, 0x1,
80 descriptorData);
81
82 *actual_count = 1;
83
84 if (optCompatible.has_value())
85 {
86 std::string comp = optCompatible.value();
87 std::vector<uint8_t> compatible = {};
88 for (char c : comp)
89 {
90 compatible.push_back((uint8_t)c);
91 }
92 i = create_pldm_firmware_device_vendor_defined_descriptor_v1_0_0(
93 b, i, compatible);
94
95 *actual_count = 2;
96 }
97
98 return i;
99 }
100
create_pldm_firmware_device_identification_record(uint8_t * b,ssize_t i,const std::optional<uint32_t> & optVendorIANA,const std::optional<std::string> & optCompatible,uint16_t componentBitmapBitLength)101 ssize_t create_pldm_firmware_device_identification_record(
102 uint8_t* b, ssize_t i, const std::optional<uint32_t>& optVendorIANA,
103 const std::optional<std::string>& optCompatible,
104 uint16_t componentBitmapBitLength)
105 {
106 const ssize_t startIndex = i;
107 // RecordLength, backfill later
108 const size_t recordLengthOffset = i;
109 b[i++] = 0;
110 b[i++] = 0;
111
112 // DescriptorCount (backfill later)
113 const size_t descriptorCountOffset = i;
114 b[i++] = 0;
115
116 // DeviceUpdateOptionFlags
117 b[i++] = 0;
118 b[i++] = 0;
119 b[i++] = 0;
120 b[i++] = 0;
121
122 // ComponentImageSetVersionStringType
123 b[i++] = 1; // type = Ascii
124
125 const char* str = (const char*)"compimagesetversion1";
126 // ComponentImageSetVersionStringLength
127 b[i++] = strlen(str);
128
129 // FirmwareDevicePackageDataLength
130 b[i++] = 0x0;
131 b[i++] = 0x0;
132
133 // ApplicableComponents
134 for (int j = 0; j < (componentBitmapBitLength / 8); j++)
135 {
136 b[i++] = 0x1;
137 // the first and only component image does apply to this device
138 }
139
140 // ComponentSetVersionString
141 for (size_t j = 0; j < strlen(str); j++)
142 {
143 b[i++] = str[j];
144 }
145
146 // RecordDescriptiors. The initial descriptor is restricted.
147 size_t actual_count = 0;
148 i = create_pldm_firmware_device_descriptors_v1_0_0(
149 b, i, optVendorIANA, optCompatible, &actual_count);
150
151 // backfill DescriptorCount
152 b[descriptorCountOffset] = actual_count;
153
154 // FirmwareDevicePackageData (optional, we make it empty)
155
156 // backfill RecordLength
157 const ssize_t recordLength = i - startIndex;
158 b[recordLengthOffset + 0] = (recordLength >> 0) & 0xff;
159 b[recordLengthOffset + 1] = (recordLength >> 8) & 0xff;
160
161 return i;
162 }
163
create_pldm_firmware_device_identification_area_v1_0_0(uint8_t * b,ssize_t i,const std::optional<uint32_t> & optVendorIANA,const std::optional<std::string> & optCompatible,uint16_t componentBitmapBitLength)164 ssize_t create_pldm_firmware_device_identification_area_v1_0_0(
165 uint8_t* b, ssize_t i, const std::optional<uint32_t>& optVendorIANA,
166 const std::optional<std::string>& optCompatible,
167 uint16_t componentBitmapBitLength)
168 {
169 // Device ID Record Count
170 b[i++] = 1;
171
172 return create_pldm_firmware_device_identification_record(
173 b, i, optVendorIANA, optCompatible, componentBitmapBitLength);
174 }
175