1ded66d0fSJason Ling #pragma once 2ded66d0fSJason Ling 3ded66d0fSJason Ling #include "config.h" 4ded66d0fSJason Ling 5ded66d0fSJason Ling #include "data_handler.hpp" 6ded66d0fSJason Ling #include "image_handler.hpp" 7ded66d0fSJason Ling #include "status.hpp" 8ded66d0fSJason Ling #include "util.hpp" 9ded66d0fSJason Ling 10ded66d0fSJason Ling #include <blobs-ipmid/blobs.hpp> 11ded66d0fSJason Ling 12ded66d0fSJason Ling #include <algorithm> 13ded66d0fSJason Ling #include <cstdint> 14ded66d0fSJason Ling #include <map> 15ded66d0fSJason Ling #include <memory> 16ded66d0fSJason Ling #include <string> 17ded66d0fSJason Ling #include <unordered_map> 18ded66d0fSJason Ling #include <vector> 19ded66d0fSJason Ling 20ded66d0fSJason Ling namespace ipmi_flash 21ded66d0fSJason Ling { 22ded66d0fSJason Ling 23ded66d0fSJason Ling /** 24ded66d0fSJason Ling * Given a firmware name, provide a set of triggerable action interfaces 25ded66d0fSJason Ling * associated with that firmware type. 26ded66d0fSJason Ling */ 27ded66d0fSJason Ling struct ActionPack 28ded66d0fSJason Ling { 29ded66d0fSJason Ling /** The name of the action pack, something like image, or tarball, or bios. 30ded66d0fSJason Ling * The firmware blob id is parsed to pull the "filename" portion from the 31ded66d0fSJason Ling * path, and matched against the key to a map of these. 32ded66d0fSJason Ling */ 33ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> preparation; 34ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> verification; 35ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> update; 36ded66d0fSJason Ling }; 37ded66d0fSJason Ling 38ded66d0fSJason Ling using ActionMap = 39ded66d0fSJason Ling std::unordered_map<std::string, std::unique_ptr<ipmi_flash::ActionPack>>; 40ded66d0fSJason Ling 41ded66d0fSJason Ling /** 42ded66d0fSJason Ling * Representation of a session, includes how to read/write data. 43ded66d0fSJason Ling */ 44ded66d0fSJason Ling struct Session 45ded66d0fSJason Ling { 46ded66d0fSJason Ling /** 47ded66d0fSJason Ling * Built a session object. 48ded66d0fSJason Ling * 49ded66d0fSJason Ling * @param[in] the active path to which this corresponds. 50ded66d0fSJason Ling */ Sessionipmi_flash::Session51ded66d0fSJason Ling explicit Session(const std::string& path) : 52ded66d0fSJason Ling dataHandler(nullptr), imageHandler(nullptr), flags(0), activePath(path) 53ded66d0fSJason Ling {} 54ded66d0fSJason Ling 55ded66d0fSJason Ling /** 56ded66d0fSJason Ling * Pointer to the correct Data handler interface. (nullptr on BT (or KCS)) 57ded66d0fSJason Ling */ 58ded66d0fSJason Ling DataInterface* dataHandler; 59ded66d0fSJason Ling 60ded66d0fSJason Ling /** 61ded66d0fSJason Ling * Pointer to the correct image handler interface. (nullptr on hash 62ded66d0fSJason Ling * blob_id) 63ded66d0fSJason Ling */ 64ded66d0fSJason Ling ipmi_flash::ImageHandlerInterface* imageHandler; 65ded66d0fSJason Ling 66ded66d0fSJason Ling /** The flags used to open the session. */ 67ded66d0fSJason Ling std::uint16_t flags; 68ded66d0fSJason Ling 69ded66d0fSJason Ling /** The active path. */ 70ded66d0fSJason Ling std::string activePath; 71ded66d0fSJason Ling }; 72ded66d0fSJason Ling 73ded66d0fSJason Ling /** 74ded66d0fSJason Ling * Register only one firmware blob handler that will manage all sessions. 75ded66d0fSJason Ling */ 76ded66d0fSJason Ling class FirmwareBlobHandler : public blobs::GenericBlobInterface 77ded66d0fSJason Ling { 78ded66d0fSJason Ling public: 79ded66d0fSJason Ling /** The state of the firmware update process. */ 80ded66d0fSJason Ling enum class UpdateState 81ded66d0fSJason Ling { 82ded66d0fSJason Ling /** The initial state. */ 83ded66d0fSJason Ling notYetStarted = 0, 84ded66d0fSJason Ling /** The BMC is expecting to receive bytes. */ 85ded66d0fSJason Ling uploadInProgress, 86ded66d0fSJason Ling /** The BMC is ready for verification or more bytes. */ 87ded66d0fSJason Ling verificationPending, 88ded66d0fSJason Ling /** The verification process has started, no more writes allowed. */ 89ded66d0fSJason Ling verificationStarted, 90ded66d0fSJason Ling /** The verification process has completed. */ 91ded66d0fSJason Ling verificationCompleted, 92ded66d0fSJason Ling /** The update process is pending. */ 93ded66d0fSJason Ling updatePending, 94ded66d0fSJason Ling /** The update process has started. */ 95ded66d0fSJason Ling updateStarted, 96ded66d0fSJason Ling /** The update has completed (optional state to reach) */ 97ded66d0fSJason Ling updateCompleted, 98ded66d0fSJason Ling }; 99ded66d0fSJason Ling 100ded66d0fSJason Ling /** 101ded66d0fSJason Ling * Create a FirmwareBlobHandler. 102ded66d0fSJason Ling * 103ded66d0fSJason Ling * @param[in] firmwares - list of firmware blob_ids to support. 104ded66d0fSJason Ling * @param[in] transports - list of transports to support. 105ded66d0fSJason Ling * @param[in] verification - pointer to object for triggering verification 106ded66d0fSJason Ling * @param[in] update - point to object for triggering the update 107ded66d0fSJason Ling */ 108ded66d0fSJason Ling static std::unique_ptr<blobs::GenericBlobInterface> 109ded66d0fSJason Ling CreateFirmwareBlobHandler(std::vector<HandlerPack>&& firmwares, 110ded66d0fSJason Ling std::vector<DataHandlerPack>&& transports, 111ded66d0fSJason Ling ActionMap&& actionPacks); 112ded66d0fSJason Ling 113ded66d0fSJason Ling /** 114ded66d0fSJason Ling * Create a FirmwareBlobHandler. 115ded66d0fSJason Ling * 116ded66d0fSJason Ling * @param[in] firmwares - list of firmware types and their handlers 117ded66d0fSJason Ling * @param[in] blobs - list of blobs_ids to support 118ded66d0fSJason Ling * @param[in] transports - list of transport types and their handlers 119ded66d0fSJason Ling * @param[in] verification - pointer to object for triggering verification 120ded66d0fSJason Ling * @param[in] update - point to object for triggering the update 121ded66d0fSJason Ling */ FirmwareBlobHandler(std::vector<HandlerPack> && firmwares,const std::vector<std::string> & blobs,std::vector<DataHandlerPack> && transports,ActionMap && actionPacks)122ded66d0fSJason Ling FirmwareBlobHandler(std::vector<HandlerPack>&& firmwares, 123ded66d0fSJason Ling const std::vector<std::string>& blobs, 124ded66d0fSJason Ling std::vector<DataHandlerPack>&& transports, 125ded66d0fSJason Ling ActionMap&& actionPacks) : 126*42a44c28SPatrick Williams handlers(std::move(firmwares)), blobIDs(blobs), 127*42a44c28SPatrick Williams transports(std::move(transports)), activeImage(activeImageBlobId), 128*42a44c28SPatrick Williams activeHash(activeHashBlobId), verifyImage(verifyBlobId), 129*42a44c28SPatrick Williams updateImage(updateBlobId), lookup(), state(UpdateState::notYetStarted), 130*42a44c28SPatrick Williams actionPacks(std::move(actionPacks)) 131ded66d0fSJason Ling {} 132ded66d0fSJason Ling ~FirmwareBlobHandler() = default; 133ded66d0fSJason Ling FirmwareBlobHandler(const FirmwareBlobHandler&) = delete; 134ded66d0fSJason Ling FirmwareBlobHandler& operator=(const FirmwareBlobHandler&) = delete; 135ded66d0fSJason Ling FirmwareBlobHandler(FirmwareBlobHandler&&) = default; 136ded66d0fSJason Ling FirmwareBlobHandler& operator=(FirmwareBlobHandler&&) = default; 137ded66d0fSJason Ling 138ded66d0fSJason Ling bool canHandleBlob(const std::string& path) override; 139ded66d0fSJason Ling std::vector<std::string> getBlobIds() override; 140ded66d0fSJason Ling bool deleteBlob(const std::string& path) override; 141ded66d0fSJason Ling bool stat(const std::string& path, blobs::BlobMeta* meta) override; 142ded66d0fSJason Ling bool open(uint16_t session, uint16_t flags, 143ded66d0fSJason Ling const std::string& path) override; 144ded66d0fSJason Ling std::vector<uint8_t> read(uint16_t session, uint32_t offset, 145ded66d0fSJason Ling uint32_t requestedSize) override; 146ded66d0fSJason Ling bool write(uint16_t session, uint32_t offset, 147ded66d0fSJason Ling const std::vector<uint8_t>& data) override; 148ded66d0fSJason Ling bool writeMeta(uint16_t session, uint32_t offset, 149ded66d0fSJason Ling const std::vector<uint8_t>& data) override; 150ded66d0fSJason Ling bool commit(uint16_t session, const std::vector<uint8_t>& data) override; 151ded66d0fSJason Ling bool close(uint16_t session) override; 152ded66d0fSJason Ling bool stat(uint16_t session, blobs::BlobMeta* meta) override; 153ded66d0fSJason Ling bool expire(uint16_t session) override; 154ded66d0fSJason Ling 155ded66d0fSJason Ling void abortProcess(); 156ded66d0fSJason Ling 157ded66d0fSJason Ling void abortVerification(); 158ded66d0fSJason Ling bool triggerVerification(); 159ded66d0fSJason Ling void abortUpdate(); 160ded66d0fSJason Ling bool triggerUpdate(); 161ded66d0fSJason Ling 162ded66d0fSJason Ling /** Allow grabbing the current state. */ getCurrentState() const163ded66d0fSJason Ling UpdateState getCurrentState() const 164ded66d0fSJason Ling { 165ded66d0fSJason Ling return state; 166ded66d0fSJason Ling }; 167ded66d0fSJason Ling 168ded66d0fSJason Ling /** Provide for any state change triggers in convenience handler. */ 169ded66d0fSJason Ling void changeState(UpdateState next); 170ded66d0fSJason Ling 171ded66d0fSJason Ling private: 172ded66d0fSJason Ling /** 173ded66d0fSJason Ling * Given the current session type, grab the ActionPack (likely will be 174ded66d0fSJason Ling * worked into the Session for lookup). 175ded66d0fSJason Ling */ getActionPack()176ded66d0fSJason Ling ActionPack* getActionPack() 177ded66d0fSJason Ling { 178ded66d0fSJason Ling if (openedFirmwareType.empty()) 179ded66d0fSJason Ling { 180ded66d0fSJason Ling /* No firmware type has been opened, but we're triggering 181ded66d0fSJason Ling * verification, or preparing. This can happen if they open the hash 182ded66d0fSJason Ling * before the image, which is possible. 183ded66d0fSJason Ling */ 184ded66d0fSJason Ling return nullptr; 185ded66d0fSJason Ling } 186ded66d0fSJason Ling 187ded66d0fSJason Ling /* TODO: Once the actionPacks and supportedFirmwares are merged this'll 188ded66d0fSJason Ling * be less dangerous 189ded66d0fSJason Ling */ 190ded66d0fSJason Ling return actionPacks[openedFirmwareType].get(); 191ded66d0fSJason Ling } 192ded66d0fSJason Ling addBlobId(const std::string & blob)193ded66d0fSJason Ling void addBlobId(const std::string& blob) 194ded66d0fSJason Ling { 195a9423469SPatrick Williams auto blobIdMatch = std::find_if( 196a9423469SPatrick Williams blobIDs.begin(), blobIDs.end(), 197a9423469SPatrick Williams [&blob](const std::string& iter) { return (iter == blob); }); 198ded66d0fSJason Ling if (blobIdMatch == blobIDs.end()) 199ded66d0fSJason Ling { 200ded66d0fSJason Ling blobIDs.push_back(blob); 201ded66d0fSJason Ling } 202ded66d0fSJason Ling } 203ded66d0fSJason Ling removeBlobId(const std::string & blob)204ded66d0fSJason Ling void removeBlobId(const std::string& blob) 205ded66d0fSJason Ling { 206ded66d0fSJason Ling blobIDs.erase(std::remove(blobIDs.begin(), blobIDs.end(), blob), 207ded66d0fSJason Ling blobIDs.end()); 208ded66d0fSJason Ling } 209ded66d0fSJason Ling fileOpen()210ded66d0fSJason Ling inline bool fileOpen() 211ded66d0fSJason Ling { 212ded66d0fSJason Ling return !lookup.empty(); 213ded66d0fSJason Ling } 214ded66d0fSJason Ling 215ded66d0fSJason Ling ActionStatus getVerifyStatus(); 216ded66d0fSJason Ling ActionStatus getActionStatus(); 217ded66d0fSJason Ling 218ded66d0fSJason Ling /** List of handlers by type. */ 219ded66d0fSJason Ling std::vector<HandlerPack> handlers; 220ded66d0fSJason Ling 221ded66d0fSJason Ling /** Active list of blobIDs. */ 222ded66d0fSJason Ling std::vector<std::string> blobIDs; 223ded66d0fSJason Ling 224ded66d0fSJason Ling /** List of handlers by transport type. */ 225ded66d0fSJason Ling std::vector<DataHandlerPack> transports; 226ded66d0fSJason Ling 227ded66d0fSJason Ling /** Active image session. */ 228ded66d0fSJason Ling Session activeImage; 229ded66d0fSJason Ling 230ded66d0fSJason Ling /** Active hash session. */ 231ded66d0fSJason Ling Session activeHash; 232ded66d0fSJason Ling 233ded66d0fSJason Ling /** Session for verification. */ 234ded66d0fSJason Ling Session verifyImage; 235ded66d0fSJason Ling 236ded66d0fSJason Ling /** Session for update. */ 237ded66d0fSJason Ling Session updateImage; 238ded66d0fSJason Ling 239ded66d0fSJason Ling /** A quick method for looking up a session's mechanisms and details. */ 240ded66d0fSJason Ling std::map<std::uint16_t, Session*> lookup; 241ded66d0fSJason Ling 242ded66d0fSJason Ling /** The firmware update state. */ 243ded66d0fSJason Ling UpdateState state; 244ded66d0fSJason Ling 245ded66d0fSJason Ling /** Track what firmware blobid they opened to start this sequence. */ 246ded66d0fSJason Ling std::string openedFirmwareType; 247ded66d0fSJason Ling 248ded66d0fSJason Ling /* preparation is triggered once we go into uploadInProgress(), but only 249ded66d0fSJason Ling * once per full cycle, going back to notYetStarted resets this. 250ded66d0fSJason Ling */ 251ded66d0fSJason Ling bool preparationTriggered = false; 252ded66d0fSJason Ling ActionMap actionPacks; 253ded66d0fSJason Ling 254ded66d0fSJason Ling ActionStatus lastVerificationStatus = ActionStatus::unknown; 255ded66d0fSJason Ling 256ded66d0fSJason Ling ActionStatus lastUpdateStatus = ActionStatus::unknown; 257ded66d0fSJason Ling 258ded66d0fSJason Ling /** Portion of "flags" argument to open() which specifies the desired 259ded66d0fSJason Ling * transport type 260ded66d0fSJason Ling */ 261ded66d0fSJason Ling static constexpr std::uint16_t transportMask = 0xff00; 262ded66d0fSJason Ling }; 263ded66d0fSJason Ling 264ded66d0fSJason Ling } // namespace ipmi_flash 265