blob: 6275843ab8e611197d31b815324864f22da1a66e [file] [log] [blame]
Patrick Venturec7ca2912018-11-02 11:38:33 -07001#pragma once
2
Patrick Ventureac11ae92019-01-16 12:43:00 -08003#include "config.h"
4
Patrick Venture1cde5f92018-11-07 08:26:47 -08005#include "data_handler.hpp"
Patrick Venturea78e39f2018-11-06 18:37:06 -08006#include "image_handler.hpp"
Patrick Venture1d66fe62019-06-03 14:57:27 -07007#include "status.hpp"
Patrick Venture7dad86f2019-05-17 08:52:20 -07008#include "util.hpp"
Patrick Venturea78e39f2018-11-06 18:37:06 -08009
Patrick Ventureefba42d2019-05-24 10:48:16 -070010#include <algorithm>
Patrick Venturec7ca2912018-11-02 11:38:33 -070011#include <blobs-ipmid/blobs.hpp>
Patrick Venture192d60f2018-11-06 11:11:59 -080012#include <cstdint>
Patrick Ventured9fb6132018-11-08 09:56:10 -080013#include <map>
Patrick Venture68cf64f2018-11-06 10:46:51 -080014#include <memory>
Patrick Venture148cd652018-11-06 10:59:47 -080015#include <string>
Patrick Venturefa06a5f2019-07-01 09:22:38 -070016#include <unordered_map>
Patrick Venture148cd652018-11-06 10:59:47 -080017#include <vector>
Patrick Venturec7ca2912018-11-02 11:38:33 -070018
Patrick Venture1d5a31c2019-05-20 11:38:22 -070019namespace ipmi_flash
Patrick Venturec7ca2912018-11-02 11:38:33 -070020{
21
Patrick Venturec7ca2912018-11-02 11:38:33 -070022/**
Patrick Venturefa06a5f2019-07-01 09:22:38 -070023 * Given a firmware name, provide a set of triggerable action interfaces
24 * associated with that firmware type.
25 */
26struct ActionPack
27{
28 /** The name of the action pack, something like image, or tarball, or bios.
29 * The firmware blob id is parsed to pull the "filename" portion from the
30 * path, and matched against the key to a map of these.
31 */
32 std::unique_ptr<TriggerableActionInterface> preparation;
33 std::unique_ptr<TriggerableActionInterface> verification;
34 std::unique_ptr<TriggerableActionInterface> update;
35};
36
37using ActionMap =
38 std::unordered_map<std::string, std::unique_ptr<ipmi_flash::ActionPack>>;
39
40/**
Patrick Venture2d3a2542018-11-08 09:23:24 -080041 * Representation of a session, includes how to read/write data.
42 */
43struct Session
44{
Patrick Ventured6461d62018-11-09 17:30:25 -080045 /**
Patrick Ventureedd55b52018-11-15 11:05:13 -080046 * Built a session object.
47 *
48 * @param[in] the active path to which this corresponds.
49 */
50 explicit Session(const std::string& path) :
Patrick Ventured816b232019-06-05 13:30:32 -070051 dataHandler(nullptr), imageHandler(nullptr), flags(0), activePath(path)
Patrick Ventureedd55b52018-11-15 11:05:13 -080052 {
53 }
54
55 /**
Patrick Ventured6461d62018-11-09 17:30:25 -080056 * Pointer to the correct Data handler interface. (nullptr on BT (or KCS))
Patrick Venture2d3a2542018-11-08 09:23:24 -080057 */
58 DataInterface* dataHandler;
59
Patrick Ventured6461d62018-11-09 17:30:25 -080060 /**
61 * Pointer to the correct image handler interface. (nullptr on hash
62 * blob_id)
63 */
Patrick Venture2d3a2542018-11-08 09:23:24 -080064 ImageHandlerInterface* imageHandler;
Patrick Venture18235e62018-11-08 10:21:09 -080065
66 /** The flags used to open the session. */
67 std::uint16_t flags;
Patrick Venture32ba9dd2018-11-09 16:22:53 -080068
Patrick Ventureedd55b52018-11-15 11:05:13 -080069 /** The active path. */
70 std::string activePath;
Patrick Venture2d3a2542018-11-08 09:23:24 -080071};
72
73/**
Patrick Venturec7ca2912018-11-02 11:38:33 -070074 * Register only one firmware blob handler that will manage all sessions.
75 */
Patrick Venture1d5a31c2019-05-20 11:38:22 -070076class FirmwareBlobHandler : public blobs::GenericBlobInterface
Patrick Venturec7ca2912018-11-02 11:38:33 -070077{
78 public:
Patrick Venture92106df2018-11-09 09:26:30 -080079 /** The state of the firmware update process. */
Patrick Venture88bc26e2019-05-15 12:02:05 -070080 enum class UpdateState
Patrick Venture92106df2018-11-09 09:26:30 -080081 {
82 /** The initial state. */
83 notYetStarted = 0,
Patrick Venture12233c52019-05-16 09:26:59 -070084 /** The BMC is expecting to receive bytes. */
85 uploadInProgress,
86 /** The BMC is ready for verification or more bytes. */
87 verificationPending,
Patrick Venture92106df2018-11-09 09:26:30 -080088 /** The verification process has started, no more writes allowed. */
Patrick Venture12233c52019-05-16 09:26:59 -070089 verificationStarted,
Patrick Venture92106df2018-11-09 09:26:30 -080090 /** The verification process has completed. */
Patrick Venture12233c52019-05-16 09:26:59 -070091 verificationCompleted,
Patrick Venture02922e42019-05-22 09:49:31 -070092 /** The update process is pending. */
93 updatePending,
94 /** The update process has started. */
95 updateStarted,
96 /** The update has completed (optional state to reach) */
Patrick Venturef1f0f652019-06-03 09:10:19 -070097 updateCompleted,
Patrick Venture92106df2018-11-09 09:26:30 -080098 };
99
Patrick Venture137ad2c2018-11-06 11:30:43 -0800100 /**
101 * Create a FirmwareBlobHandler.
102 *
Patrick Venture4cceb8e2018-11-06 11:56:48 -0800103 * @param[in] firmwares - list of firmware blob_ids to support.
Patrick Venture1cde5f92018-11-07 08:26:47 -0800104 * @param[in] transports - list of transports to support.
Patrick Venture3ecb3502019-05-17 11:03:51 -0700105 * @param[in] verification - pointer to object for triggering verification
Patrick Venture27ac5822019-05-20 17:39:31 -0700106 * @param[in] update - point to object for triggering the update
Patrick Venture137ad2c2018-11-06 11:30:43 -0800107 */
Patrick Venture9efef5d2019-06-19 08:45:44 -0700108 static std::unique_ptr<blobs::GenericBlobInterface>
109 CreateFirmwareBlobHandler(
Patrick Ventured4e20de2019-07-18 12:48:05 -0700110 std::vector<HandlerPack>&& firmwares,
Patrick Venture9efef5d2019-06-19 08:45:44 -0700111 const std::vector<DataHandlerPack>& transports,
Patrick Venturefa06a5f2019-07-01 09:22:38 -0700112 ActionMap&& actionPacks);
Patrick Venture68cf64f2018-11-06 10:46:51 -0800113
Patrick Venture137ad2c2018-11-06 11:30:43 -0800114 /**
115 * Create a FirmwareBlobHandler.
116 *
Patrick Venture1cde5f92018-11-07 08:26:47 -0800117 * @param[in] firmwares - list of firmware types and their handlers
118 * @param[in] blobs - list of blobs_ids to support
119 * @param[in] transports - list of transport types and their handlers
Patrick Venture3ecb3502019-05-17 11:03:51 -0700120 * @param[in] verification - pointer to object for triggering verification
Patrick Venture27ac5822019-05-20 17:39:31 -0700121 * @param[in] update - point to object for triggering the update
Patrick Venture137ad2c2018-11-06 11:30:43 -0800122 */
Patrick Ventured4e20de2019-07-18 12:48:05 -0700123 FirmwareBlobHandler(std::vector<HandlerPack>&& firmwares,
Patrick Venturefa06a5f2019-07-01 09:22:38 -0700124 const std::vector<std::string>& blobs,
125 const std::vector<DataHandlerPack>& transports,
Benjamin Fair12901982019-11-12 13:55:46 -0800126 ActionMap&& actionPacks) :
Patrick Ventured4e20de2019-07-18 12:48:05 -0700127 handlers(std::move(firmwares)),
Benjamin Fair12901982019-11-12 13:55:46 -0800128 blobIDs(blobs), transports(transports), activeImage(activeImageBlobId),
129 activeHash(activeHashBlobId), verifyImage(verifyBlobId),
130 updateImage(updateBlobId), lookup(), state(UpdateState::notYetStarted),
131 actionPacks(std::move(actionPacks))
Patrick Venture148cd652018-11-06 10:59:47 -0800132 {
133 }
Patrick Venturec7ca2912018-11-02 11:38:33 -0700134 ~FirmwareBlobHandler() = default;
Patrick Venture4eb55952018-11-16 15:36:24 -0800135 FirmwareBlobHandler(const FirmwareBlobHandler&) = delete;
136 FirmwareBlobHandler& operator=(const FirmwareBlobHandler&) = delete;
Patrick Venturec7ca2912018-11-02 11:38:33 -0700137 FirmwareBlobHandler(FirmwareBlobHandler&&) = default;
138 FirmwareBlobHandler& operator=(FirmwareBlobHandler&&) = default;
139
140 bool canHandleBlob(const std::string& path) override;
141 std::vector<std::string> getBlobIds() override;
142 bool deleteBlob(const std::string& path) override;
Patrick Venturee312f392019-06-04 07:44:37 -0700143 bool stat(const std::string& path, blobs::BlobMeta* meta) override;
Patrick Venturec7ca2912018-11-02 11:38:33 -0700144 bool open(uint16_t session, uint16_t flags,
145 const std::string& path) override;
146 std::vector<uint8_t> read(uint16_t session, uint32_t offset,
147 uint32_t requestedSize) override;
148 bool write(uint16_t session, uint32_t offset,
149 const std::vector<uint8_t>& data) override;
150 bool writeMeta(uint16_t session, uint32_t offset,
151 const std::vector<uint8_t>& data) override;
152 bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
153 bool close(uint16_t session) override;
Patrick Venturee312f392019-06-04 07:44:37 -0700154 bool stat(uint16_t session, blobs::BlobMeta* meta) override;
Patrick Venturec7ca2912018-11-02 11:38:33 -0700155 bool expire(uint16_t session) override;
Patrick Venture148cd652018-11-06 10:59:47 -0800156
Patrick Ventured5741022019-06-17 09:08:35 -0700157 void abortProcess();
158
159 void abortVerification();
Patrick Ventureffcc5502018-11-16 12:32:38 -0800160 bool triggerVerification();
Patrick Venture49731712019-06-17 10:04:02 -0700161 void abortUpdate();
Patrick Venture1a406fe2019-05-31 07:29:56 -0700162 bool triggerUpdate();
Patrick Ventureffcc5502018-11-16 12:32:38 -0800163
Patrick Venture92106df2018-11-09 09:26:30 -0800164 /** Allow grabbing the current state. */
165 UpdateState getCurrentState() const
166 {
167 return state;
168 };
169
Patrick Venture75c0c272019-06-21 09:15:08 -0700170 /** Provide for any state change triggers in convenience handler. */
171 void changeState(UpdateState next);
172
Patrick Venture148cd652018-11-06 10:59:47 -0800173 private:
Patrick Venturefa06a5f2019-07-01 09:22:38 -0700174 /**
175 * Given the current session type, grab the ActionPack (likely will be
176 * worked into the Session for lookup).
177 */
178 ActionPack* getActionPack()
179 {
180 if (openedFirmwareType.empty())
181 {
182 /* No firmware type has been opened, but we're triggering
183 * verification, or preparing. This can happen if they open the hash
184 * before the image, which is possible.
185 */
186 return nullptr;
187 }
188
189 /* TODO: Once the actionPacks and supportedFirmwares are merged this'll
190 * be less dangerous
191 */
192 return actionPacks[openedFirmwareType].get();
193 }
194
Patrick Ventureefba42d2019-05-24 10:48:16 -0700195 void addBlobId(const std::string& blob)
196 {
Patrick Venturef8119952019-06-06 13:47:34 -0700197 auto blobIdMatch = std::find_if(
198 blobIDs.begin(), blobIDs.end(),
199 [&blob](const std::string& iter) { return (iter == blob); });
Patrick Ventureefba42d2019-05-24 10:48:16 -0700200 if (blobIdMatch == blobIDs.end())
201 {
202 blobIDs.push_back(blob);
203 }
204 }
205
Patrick Venture930c7b72019-05-24 11:11:08 -0700206 void removeBlobId(const std::string& blob)
207 {
208 blobIDs.erase(std::remove(blobIDs.begin(), blobIDs.end(), blob),
209 blobIDs.end());
210 }
211
Brandon Kim8fc60872019-10-18 15:15:50 -0700212 inline bool fileOpen()
213 {
214 return !lookup.empty();
215 }
216
Patrick Ventureda66fd82019-06-03 11:11:24 -0700217 ActionStatus getVerifyStatus();
218 ActionStatus getActionStatus();
Patrick Venturea2d82392019-06-03 10:55:17 -0700219
Patrick Venturea78e39f2018-11-06 18:37:06 -0800220 /** List of handlers by type. */
221 std::vector<HandlerPack> handlers;
222
Patrick Venturec02849b2018-11-06 17:31:15 -0800223 /** Active list of blobIDs. */
Patrick Venture4cceb8e2018-11-06 11:56:48 -0800224 std::vector<std::string> blobIDs;
Patrick Venturec02849b2018-11-06 17:31:15 -0800225
Patrick Venture1cde5f92018-11-07 08:26:47 -0800226 /** List of handlers by transport type. */
227 std::vector<DataHandlerPack> transports;
228
Patrick Ventured9fb6132018-11-08 09:56:10 -0800229 /** Active image session. */
230 Session activeImage;
231
232 /** Active hash session. */
233 Session activeHash;
234
Patrick Ventureffcc5502018-11-16 12:32:38 -0800235 /** Session for verification. */
236 Session verifyImage;
237
Patrick Venture26e241d2019-05-20 18:39:01 -0700238 /** Session for update. */
239 Session updateImage;
240
Patrick Ventured9fb6132018-11-08 09:56:10 -0800241 /** A quick method for looking up a session's mechanisms and details. */
242 std::map<std::uint16_t, Session*> lookup;
243
Patrick Venture92106df2018-11-09 09:26:30 -0800244 /** The firmware update state. */
245 UpdateState state;
246
Patrick Venturefa06a5f2019-07-01 09:22:38 -0700247 /** Track what firmware blobid they opened to start this sequence. */
248 std::string openedFirmwareType;
249
Patrick Venture6d7735d2019-06-21 10:03:19 -0700250 /* preparation is triggered once we go into uploadInProgress(), but only
251 * once per full cycle, going back to notYetStarted resets this.
252 */
253 bool preparationTriggered = false;
Patrick Venturefa06a5f2019-07-01 09:22:38 -0700254 ActionMap actionPacks;
Patrick Venture27ac5822019-05-20 17:39:31 -0700255
Patrick Ventureda66fd82019-06-03 11:11:24 -0700256 ActionStatus lastVerificationStatus = ActionStatus::unknown;
Patrick Venturea2d82392019-06-03 10:55:17 -0700257
Patrick Ventureda66fd82019-06-03 11:11:24 -0700258 ActionStatus lastUpdateStatus = ActionStatus::unknown;
Benjamin Fair12901982019-11-12 13:55:46 -0800259
260 /** Portion of "flags" argument to open() which specifies the desired
261 * transport type
262 */
263 static constexpr std::uint16_t transportMask = 0xff00;
Patrick Venturec7ca2912018-11-02 11:38:33 -0700264};
265
Patrick Venture1d5a31c2019-05-20 11:38:22 -0700266} // namespace ipmi_flash