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