summaryrefslogtreecommitdiffstats
path: root/firmware_handler.hpp
blob: bfae52941ec3bc256387abd70ae6ec784f572d46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#pragma once

#include "config.h"

#include "data_handler.hpp"
#include "image_handler.hpp"
#include "update.hpp"
#include "util.hpp"
#include "verify.hpp"

#include <algorithm>
#include <blobs-ipmid/blobs.hpp>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace ipmi_flash
{

/**
 * Representation of a session, includes how to read/write data.
 */
struct Session
{
    /**
     * Built a session object.
     *
     * @param[in] the active path to which this corresponds.
     */
    explicit Session(const std::string& path) :
        dataHandler(nullptr), imageHandler(nullptr), flags(0),
        state(State::closed), activePath(path)
    {
    }

    /**
     * Pointer to the correct Data handler interface. (nullptr on BT (or KCS))
     */
    DataInterface* dataHandler;

    /**
     * Pointer to the correct image handler interface.  (nullptr on hash
     * blob_id)
     */
    ImageHandlerInterface* imageHandler;

    /** The flags used to open the session. */
    std::uint16_t flags;

    /** A sesion can be for an image (or tarball) or the hash. */
    enum class State
    {
        open = 0,
        closed = 1,
    };

    /** The current state of this session. */
    State state;

    /** The active path. */
    std::string activePath;
};

struct ExtChunkHdr
{
    std::uint32_t length; /* Length of the data queued (little endian). */
} __attribute__((packed));

/**
 * Register only one firmware blob handler that will manage all sessions.
 */
class FirmwareBlobHandler : public blobs::GenericBlobInterface
{
  public:
    enum UpdateFlags : std::uint16_t
    {
        openRead = (1 << 0),  /* Flag for reading. */
        openWrite = (1 << 1), /* Flag for writing. */
        ipmi = (1 << 8), /* Expect to send contents over IPMI BlockTransfer. */
        p2a = (1 << 9),  /* Expect to send contents over P2A bridge. */
        lpc = (1 << 10), /* Expect to send contents over LPC bridge. */
    };

    /* TODO: All of the states may not be required - if we add abort() commands
     * appropriately.
     */
    /** The state of the firmware update process. */
    enum class UpdateState
    {
        /** The initial state. */
        notYetStarted = 0,
        /** The BMC is expecting to receive bytes. */
        uploadInProgress,
        /** The BMC is ready for verification or more bytes. */
        verificationPending,
        /** The verification process has started, no more writes allowed. */
        verificationStarted,
        /** The verification process has completed. */
        verificationCompleted,
        /** The update process is pending. */
        updatePending,
        /** The update process has started. */
        updateStarted,
        /** The update has completed (optional state to reach) */
        updatedCompleted,
    };

    /**
     * Create a FirmwareBlobHandler.
     *
     * @param[in] firmwares - list of firmware blob_ids to support.
     * @param[in] transports - list of transports to support.
     * @param[in] verification - pointer to object for triggering verification
     * @param[in] update - point to object for triggering the update
     */
    static std::unique_ptr<GenericBlobInterface> CreateFirmwareBlobHandler(
        const std::vector<HandlerPack>& firmwares,
        const std::vector<DataHandlerPack>& transports,
        std::unique_ptr<VerificationInterface> verification,
        std::unique_ptr<UpdateInterface> update);

    /**
     * Create a FirmwareBlobHandler.
     *
     * @param[in] firmwares - list of firmware types and their handlers
     * @param[in] blobs - list of blobs_ids to support
     * @param[in] transports - list of transport types and their handlers
     * @param[in] bitmask - bitmask of transports to support
     * @param[in] verification - pointer to object for triggering verification
     * @param[in] update - point to object for triggering the update
     */
    FirmwareBlobHandler(const std::vector<HandlerPack>& firmwares,
                        const std::vector<std::string>& blobs,
                        const std::vector<DataHandlerPack>& transports,
                        std::uint16_t bitmask,
                        std::unique_ptr<VerificationInterface> verification,
                        std::unique_ptr<UpdateInterface> update) :
        handlers(firmwares),
        blobIDs(blobs), transports(transports), bitmask(bitmask),
        activeImage(activeImageBlobId), activeHash(activeHashBlobId),
        verifyImage(verifyBlobId), updateImage(updateBlobId), lookup(),
        state(UpdateState::notYetStarted),
        verification(std::move(verification)), update(std::move(update))
    {
    }
    ~FirmwareBlobHandler() = default;
    FirmwareBlobHandler(const FirmwareBlobHandler&) = delete;
    FirmwareBlobHandler& operator=(const FirmwareBlobHandler&) = delete;
    FirmwareBlobHandler(FirmwareBlobHandler&&) = default;
    FirmwareBlobHandler& operator=(FirmwareBlobHandler&&) = default;

    bool canHandleBlob(const std::string& path) override;
    std::vector<std::string> getBlobIds() override;
    bool deleteBlob(const std::string& path) override;
    bool stat(const std::string& path, struct blobs::BlobMeta* meta) override;
    bool open(uint16_t session, uint16_t flags,
              const std::string& path) override;
    std::vector<uint8_t> read(uint16_t session, uint32_t offset,
                              uint32_t requestedSize) override;
    bool write(uint16_t session, uint32_t offset,
               const std::vector<uint8_t>& data) override;
    bool writeMeta(uint16_t session, uint32_t offset,
                   const std::vector<uint8_t>& data) override;
    bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
    bool close(uint16_t session) override;
    bool stat(uint16_t session, struct blobs::BlobMeta* meta) override;
    bool expire(uint16_t session) override;

    bool triggerVerification();

    /** Allow grabbing the current state. */
    UpdateState getCurrentState() const
    {
        return state;
    };

  private:
    void addBlobId(const std::string& blob)
    {
        auto blobIdMatch =
            std::find_if(blobIDs.begin(), blobIDs.end(),
                         [&blob](const auto& iter) { return (iter == blob); });
        if (blobIdMatch == blobIDs.end())
        {
            blobIDs.push_back(blob);
        }
    }

    void removeBlobId(const std::string& blob)
    {
        blobIDs.erase(std::remove(blobIDs.begin(), blobIDs.end(), blob),
                      blobIDs.end());
    }

    /** List of handlers by type. */
    std::vector<HandlerPack> handlers;

    /** Active list of blobIDs. */
    std::vector<std::string> blobIDs;

    /** List of handlers by transport type. */
    std::vector<DataHandlerPack> transports;

    /** The bits set indicate what transport mechanisms are supported. */
    std::uint16_t bitmask;

    /** Active image session. */
    Session activeImage;

    /** Active hash session. */
    Session activeHash;

    /** Session for verification. */
    Session verifyImage;

    /** Session for update. */
    Session updateImage;

    /** A quick method for looking up a session's mechanisms and details. */
    std::map<std::uint16_t, Session*> lookup;

    /** The firmware update state. */
    UpdateState state;

    std::unique_ptr<VerificationInterface> verification;

    std::unique_ptr<UpdateInterface> update;

    /** Temporary variable to track whether a blob is open. */
    bool fileOpen = false;

    VerifyCheckResponses lastVerificationResponse = VerifyCheckResponses::other;
};

} // namespace ipmi_flash
OpenPOWER on IntegriCloud