xref: /openbmc/phosphor-bmc-code-mgmt/common/pldm/package_parser.hpp (revision 994a77ff25aeb28b2cce7142d081af767f9eb542)
1 #pragma once
2 
3 #include "types.hpp"
4 
5 #include <libpldm/firmware_update.h>
6 
7 #include <array>
8 #include <cstdint>
9 #include <memory>
10 #include <tuple>
11 #include <vector>
12 
13 // NOLINTBEGIN
14 
15 namespace pldm
16 {
17 
18 namespace fw_update
19 {
20 
21 /** @class PackageParser
22  *
23  *  PackageParser is the abstract base class for parsing the PLDM firmware
24  *  update package. The PLDM firmware update contains two major sections; the
25  *  firmware package header, and the firmware package payload. Each package
26  *  header version will have a concrete implementation of the PackageParser.
27  *  The concrete implementation understands the format of the package header and
28  *  will implement the parse API.
29  */
30 class PackageParser
31 {
32   public:
33     PackageParser() = delete;
34     PackageParser(const PackageParser&) = delete;
35     PackageParser(PackageParser&&) = default;
36     PackageParser& operator=(const PackageParser&) = delete;
37     PackageParser& operator=(PackageParser&&) = delete;
38     virtual ~PackageParser() = default;
39 
40     /** @brief Constructor
41      *
42      *  @param[in] pkgHeaderSize - Size of package header section
43      *  @param[in] pkgVersion - Package version
44      *  @param[in] componentBitmapBitLength - The number of bits used to
45      *                                        represent the bitmap in the
46      *                                        ApplicableComponents field for a
47      *                                        matching device.
48      */
49     explicit PackageParser(PackageHeaderSize pkgHeaderSize,
50                            const PackageVersion& pkgVersion,
51                            ComponentBitmapBitLength componentBitmapBitLength) :
52         pkgHeaderSize(pkgHeaderSize), pkgVersion(pkgVersion),
53         componentBitmapBitLength(componentBitmapBitLength)
54     {}
55 
56     /** @brief Parse the firmware update package header
57      *
58      *  @param[in] pkgHdr - Package header
59      *  @param[in] pkgSize - Size of the firmware update package
60      *
61      *  @note Throws exception is parsing fails
62      */
63     virtual void parse(const std::vector<uint8_t>& pkgHdr,
64                        uintmax_t pkgSize) = 0;
65 
66     /** @brief Get firmware device ID records from the package
67      *
68      *  @return if parsing the package is successful, return firmware device ID
69      *          records
70      */
71     const FirmwareDeviceIDRecords& getFwDeviceIDRecords() const
72     {
73         return fwDeviceIDRecords;
74     }
75 
76     /** @brief Get component image information from the package
77      *
78      *  @return if parsing the package is successful, return component image
79      *          information
80      */
81     const ComponentImageInfos& getComponentImageInfos() const
82     {
83         return componentImageInfos;
84     }
85 
86     /** @brief Device identifiers of the managed FDs */
87     const PackageHeaderSize pkgHeaderSize;
88 
89     /** @brief Package version string */
90     const PackageVersion pkgVersion;
91 
92   protected:
93     /** @brief Parse the firmware device identification area
94      *
95      *  @param[in] deviceIdRecCount - count of firmware device ID records
96      *  @param[in] pkgHdr - firmware package header
97      *  @param[in] offset - offset in package header which is the start of the
98      *                      firmware device identification area
99      *
100      *  @return On success return the offset which is the end of the firmware
101      *          device identification area, on error throw exception.
102      */
103     size_t parseFDIdentificationArea(DeviceIDRecordCount deviceIdRecCount,
104                                      const std::vector<uint8_t>& pkgHdr,
105                                      size_t offset);
106 
107     /** @brief Parse the component image information area
108      *
109      *  @param[in] compImageCount - component image count
110      *  @param[in] pkgHdr - firmware package header
111      *  @param[in] offset - offset in package header which is the start of the
112      *                      component image information area
113      *
114      *  @return On success return the offset which is the end of the component
115      *          image information area, on error throw exception.
116      */
117     size_t parseCompImageInfoArea(ComponentImageCount compImageCount,
118                                   const std::vector<uint8_t>& pkgHdr,
119                                   size_t offset);
120 
121     /** @brief Validate the total size of the package
122      *
123      *  Verify the total size of the package is the sum of package header and
124      *  the size of each component.
125      *
126      *  @param[in] pkgSize - firmware update package size
127      *
128      *  @note Throws exception if validation fails
129      */
130     void validatePkgTotalSize(uintmax_t pkgSize);
131 
132     /** @brief Firmware Device ID Records in the package */
133     FirmwareDeviceIDRecords fwDeviceIDRecords;
134 
135     /** @brief Component Image Information in the package */
136     ComponentImageInfos componentImageInfos;
137 
138     /** @brief The number of bits that will be used to represent the bitmap in
139      *         the ApplicableComponents field for matching device. The value
140      *         shall be a multiple of 8 and be large enough to contain a bit
141      *         for each component in the package.
142      */
143     const ComponentBitmapBitLength componentBitmapBitLength;
144 };
145 
146 /** @class PackageParserV1
147  *
148  *  This class implements the package parser for the header format version 0x01
149  */
150 class PackageParserV1 final : public PackageParser
151 {
152   public:
153     PackageParserV1() = delete;
154     PackageParserV1(const PackageParserV1&) = delete;
155     PackageParserV1(PackageParserV1&&) = default;
156     PackageParserV1& operator=(const PackageParserV1&) = delete;
157     PackageParserV1& operator=(PackageParserV1&&) = delete;
158     ~PackageParserV1() = default;
159 
160     /** @brief Constructor
161      *
162      *  @param[in] pkgHeaderSize - Size of package header section
163      *  @param[in] pkgVersion - Package version
164      *  @param[in] componentBitmapBitLength - The number of bits used to
165      *                                        represent the bitmap in the
166      *                                        ApplicableComponents field for a
167      *                                        matching device.
168      */
169     explicit PackageParserV1(
170         PackageHeaderSize pkgHeaderSize, const PackageVersion& pkgVersion,
171         ComponentBitmapBitLength componentBitmapBitLength) :
172         PackageParser(pkgHeaderSize, pkgVersion, componentBitmapBitLength)
173     {}
174 
175     virtual void parse(const std::vector<uint8_t>& pkgHdr, uintmax_t pkgSize);
176 };
177 
178 /** @brief Parse the package header information
179  *
180  *  @param[in] pkgHdrInfo - package header information section in the package
181  *
182  *  @return On success return the PackageParser for the header format version
183  *          on failure return nullptr
184  */
185 std::unique_ptr<PackageParser> parsePackageHeader(
186     std::vector<uint8_t>& pkgHdrInfo);
187 
188 } // namespace fw_update
189 
190 } // namespace pldm
191 
192 // NOLINTEND
193