xref: /openbmc/libpldm/include/libpldm++/firmware_update.hpp (revision d6a957481638b00a49aed15d04b60d3d32fede54)
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