1 #pragma once 2 3 #include <libpldm++/types.hpp> 4 5 #include <libpldm/firmware_update.h> 6 7 #include <cstdint> 8 #include <stdexcept> 9 #include <vector> 10 #include <expected> 11 #include <span> 12 #include <memory> 13 14 // namespace pldm is for things which are (in)directly defined by PLDM specifications 15 namespace pldm 16 { 17 18 namespace fw_update 19 { 20 // forward declare structs and classes for our 'friend' declarations 21 class PackageParser; 22 struct DescriptorData; 23 struct FirmwareDeviceIDRecord; 24 struct ComponentImageInfo; 25 26 struct DescriptorData : libpldm::GrowableStruct<struct DescriptorData>, 27 private libpldm::NonCopyableNonMoveable { 28 private: 29 friend pldm::fw_update::PackageParser; 30 31 // since it is holding a map of descriptors, it needs to construct 32 // for the private copy constructor 33 friend struct pldm::fw_update::FirmwareDeviceIDRecord; 34 35 DescriptorData(const struct DescriptorData &ref); 36 DescriptorData(const std::vector<uint8_t> &data); 37 DescriptorData(const std::string &title, 38 const std::vector<uint8_t> &data); 39 40 public: 41 LIBPLDM_ABI_TESTING 42 ~DescriptorData(); 43 44 bool operator==(const DescriptorData &other) const; 45 46 // data members 47 const std::optional<std::string> vendorDefinedDescriptorTitle; 48 const std::vector<uint8_t> data; 49 }; 50 51 struct ComponentImageInfo 52 : libpldm::GrowableStruct<struct ComponentImageInfo>, 53 private libpldm::NonCopyableNonMoveable { 54 private: 55 friend pldm::fw_update::PackageParser; 56 57 ComponentImageInfo( 58 uint16_t componentClassification, 59 uint16_t componentIdentifier, 60 uint32_t componentComparisonStamp, 61 std::bitset<16> componentOptions, 62 std::bitset<16> requestedComponentActivationMethod, 63 const variable_field &componentLocation, 64 const std::string &componentVersion); 65 66 public: 67 LIBPLDM_ABI_TESTING 68 ComponentImageInfo(const ComponentImageInfo &ref); 69 70 LIBPLDM_ABI_TESTING 71 ~ComponentImageInfo(); 72 73 // note: this function compares all members besides the 74 // component image itself 75 LIBPLDM_ABI_TESTING 76 bool operator==(const ComponentImageInfo &other) const; 77 78 // data members 79 const uint16_t componentClassification; 80 const uint16_t componentIdentifier; 81 const uint32_t compComparisonStamp; 82 const std::bitset<16> componentOptions; 83 const std::bitset<16> requestedComponentActivationMethod; 84 85 // pointer to, and length of the component image. 86 // The pointer becomes dangling when the 87 // lifetime of the parsed buffer ends. 88 const variable_field componentLocation; 89 90 const std::string componentVersion; 91 }; 92 93 struct FirmwareDeviceIDRecord 94 : libpldm::GrowableStruct<struct FirmwareDeviceIDRecord>, 95 private libpldm::NonCopyableNonMoveable { 96 private: 97 friend pldm::fw_update::PackageParser; 98 99 FirmwareDeviceIDRecord( 100 const std::bitset<32> &deviceUpdateOptionFlags, 101 const std::vector<size_t> &applicableComponents, 102 const std::string &componentImageSetVersionString, 103 const std::map<uint16_t, std::unique_ptr<DescriptorData> > 104 &descriptors, 105 const std::vector<uint8_t> &firmwareDevicePackageData); 106 107 public: 108 LIBPLDM_ABI_TESTING 109 ~FirmwareDeviceIDRecord(); 110 111 LIBPLDM_ABI_TESTING 112 FirmwareDeviceIDRecord(const FirmwareDeviceIDRecord &ref); 113 114 LIBPLDM_ABI_TESTING 115 bool operator==(const FirmwareDeviceIDRecord &other) const; 116 117 // data members 118 LIBPLDM_ABI_TESTING 119 const std::vector<uint16_t> getDescriptorTypes() const; 120 121 const std::bitset<32> deviceUpdateOptionFlags; 122 123 const std::vector<size_t> applicableComponents; 124 125 const std::string componentImageSetVersionString; 126 127 // map descriptor type to descriptor data 128 // 129 // We cannot have a value-map since 'DescriptorData' is a growable struct 130 // which cannot be (move) constructed by the library user or 131 // anyone who is not a friend (including STL templates like construct_at). 132 // To avoid any mismatch in usage due to layout difference of a value map 133 // on struct growth, we store a unique_ptr. 134 const std::map<uint16_t, std::unique_ptr<DescriptorData> > 135 recordDescriptors; 136 137 const std::vector<uint8_t> firmwareDevicePackageData; 138 }; 139 140 struct Package : libpldm::GrowableStruct<struct Package>, 141 private libpldm::NonCopyableNonMoveable { 142 private: 143 friend pldm::fw_update::PackageParser; 144 145 Package(const std::vector<FirmwareDeviceIDRecord> 146 &firmwareDeviceIdRecords, 147 const std::vector<ComponentImageInfo> 148 &componentImageInformation); 149 150 public: 151 LIBPLDM_ABI_TESTING 152 ~Package(); 153 154 LIBPLDM_ABI_TESTING 155 Package(const Package &ref); 156 157 LIBPLDM_ABI_TESTING 158 bool operator==(const Package &other) const; 159 160 // data members 161 const std::vector<FirmwareDeviceIDRecord> 162 firmwareDeviceIdRecords; 163 const std::vector<ComponentImageInfo> componentImageInformation; 164 }; 165 166 // To avoid issues like "ERROR: no symbols info in the ABI dump" 167 // with the ABI tooling, expose a do-nothing stable symbol. 168 // Which ensures we always have a non-empty stable ABI. 169 LIBPLDM_ABI_STABLE 170 void stable_nop(); 171 172 class PackageParserError { 173 public: 174 explicit PackageParserError(std::string s); 175 PackageParserError(std::string s, int rc); 176 177 std::string msg; 178 179 // error codes from libpldm 180 std::optional<int> rc; 181 }; 182 183 class PackageParser : private libpldm::NonCopyableNonMoveable { 184 public: 185 PackageParser() = delete; 186 ~PackageParser(); 187 188 /** @brief Parse the firmware update package 189 * 190 * @param[in] pkg - vector with the pldm fw update package 191 * @param[in] pin - pldm package format support 192 * 193 * @returns an error value if parsing fails 194 * @returns a unique_ptr to Package struct on success 195 */ 196 LIBPLDM_ABI_TESTING 197 static std::expected<std::unique_ptr<Package>, 198 PackageParserError> 199 parse(const std::span<const uint8_t> &pkg, 200 struct pldm_package_format_pin &pin) noexcept; 201 202 private: 203 static std::expected<void, std::string> helperParseFDDescriptor( 204 struct pldm_descriptor *desc, 205 std::map<uint16_t, 206 std::unique_ptr<pldm::fw_update::DescriptorData> > 207 &descriptors) noexcept; 208 }; 209 210 } // namespace fw_update 211 212 } // namespace pldm 213