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