1 #include <inttypes.h> 2 #include <libpldm/firmware_update.h> 3 4 #include <cstring> 5 #include <optional> 6 #include <string> 7 #include <vector> 8 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 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 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 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 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