xref: /openbmc/phosphor-bmc-code-mgmt/test/create_package/firmware_device_id_area.cpp (revision 4a053c8e069133436d490aaff12471ee6c9d0677)
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