diff options
| author | Patrick Venture <venture@google.com> | 2019-05-15 15:58:06 -0700 |
|---|---|---|
| committer | Patrick Venture <venture@google.com> | 2019-05-15 16:07:52 -0700 |
| commit | d61b0ff8d1dbc2ea4688b74a9836a000339902cf (patch) | |
| tree | a0dc0c4b5eda4883cc54242759f3088f05724c34 /tools | |
| parent | 9420ad20777cb28acd5c66c3c4dd75a17b8364e2 (diff) | |
| download | phosphor-ipmi-flash-d61b0ff8d1dbc2ea4688b74a9836a000339902cf.tar.gz phosphor-ipmi-flash-d61b0ff8d1dbc2ea4688b74a9836a000339902cf.zip | |
tools: implement firmware verification polling
The verification process is asynchronous, therefore poll the BMC
firmware state.
Tested: Verified it behaves as intended, before moving it into a
sub-routine:
Opening the verification file
Committing to verification file to trigger verification service
Calling stat on verification session to check status
stat received:
blob_state: 0x206
size: 0x0
metadata(1): 0x3
other
stat received:
blob_state: 0x206
size: 0x0
metadata(1): 0x0
running
stat received:
blob_state: 0x206
size: 0x0
metadata(1): 0x0
running
stat received:
blob_state: 0x206
size: 0x0
metadata(1): 0x1
success
stat received:
blob_state: 0x206
size: 0x0
metadata(1): 0x1
success
Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I3cb13d1a966c2c833fd4fee5654332f34e80355a
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/updater.cpp | 102 | ||||
| -rw-r--r-- | tools/updater.hpp | 10 |
2 files changed, 110 insertions, 2 deletions
diff --git a/tools/updater.cpp b/tools/updater.cpp index fd72136..7c78765 100644 --- a/tools/updater.cpp +++ b/tools/updater.cpp @@ -16,6 +16,7 @@ #include "updater.hpp" +#include "firmware_handler.hpp" #include "tool_errors.hpp" #include <algorithm> @@ -24,10 +25,92 @@ #include <ipmiblob/blob_errors.hpp> #include <memory> #include <string> +#include <thread> namespace host_tool { +/* Poll an open verification session. Handling closing the session is not yet + * owned by this method. */ +bool pollVerificationStatus(std::uint16_t session, + ipmiblob::BlobInterface* blob) +{ + using namespace std::chrono_literals; + + static constexpr auto verificationSleep = 5s; + static constexpr int commandAttempts = 20; + int attempts = 0; + bool exitLoop = false; + blobs::FirmwareBlobHandler::VerifyCheckResponses result = + blobs::FirmwareBlobHandler::VerifyCheckResponses::other; + + try + { + /* Reach back the current status from the verification service output. + */ + while (attempts++ < commandAttempts) + { + ipmiblob::StatResponse resp = blob->getStat(session); + + if (resp.metadata.size() != sizeof(std::uint8_t)) + { + /* TODO: How do we want to handle the verification failures, + * because closing the session to the verify blob has a special + * as-of-yet not fully defined behavior. + */ + std::fprintf(stderr, "Received invalid metadata response!!!\n"); + } + + result = + static_cast<blobs::FirmwareBlobHandler::VerifyCheckResponses>( + resp.metadata[0]); + + switch (result) + { + case blobs::FirmwareBlobHandler::VerifyCheckResponses::failed: + std::fprintf(stderr, "failed\n"); + exitLoop = true; + break; + case blobs::FirmwareBlobHandler::VerifyCheckResponses::other: + std::fprintf(stderr, "other\n"); + break; + case blobs::FirmwareBlobHandler::VerifyCheckResponses::running: + std::fprintf(stderr, "running\n"); + break; + case blobs::FirmwareBlobHandler::VerifyCheckResponses::success: + std::fprintf(stderr, "success\n"); + exitLoop = true; + break; + default: + std::fprintf(stderr, "wat\n"); + } + + if (exitLoop) + { + break; + } + std::this_thread::sleep_for(verificationSleep); + } + } + catch (const ipmiblob::BlobException& b) + { + throw ToolException("blob exception received: " + + std::string(b.what())); + } + + /* TODO: If this is reached and it's not success, it may be worth just + * throwing a ToolException with a timeout message specifying the final + * read's value. + * + * TODO: Given that excepting from certain points leaves the BMC update + * state machine in an inconsistent state, we need to carefully evaluate + * which exceptions from the lower layers allow one to try and delete the + * blobs to rollback the state and progress. + */ + return (result == + blobs::FirmwareBlobHandler::VerifyCheckResponses::success); +} + void updaterMain(ipmiblob::BlobInterface* blob, DataInterface* handler, const std::string& imagePath, const std::string& signaturePath) { @@ -162,9 +245,24 @@ void updaterMain(ipmiblob::BlobInterface* blob, DataInterface* handler, std::string(b.what())); } - /* TODO: Check the verification via stat(session). */ + std::fprintf(stderr, + "Calling stat on verification session to check status\n"); - /* DO NOT CLOSE the verification session until it's done. */ + if (pollVerificationStatus(session, blob)) + { + std::fprintf(stderr, "Verification returned success\n"); + } + else + { + std::fprintf(stderr, "Verification returned non-success (could still " + "be running (unlikely))\n"); + } + + /* DO NOT CLOSE the verification session until it's done. + * TODO: Evaluate what closing verification should do? If the process is + * complete, nothing bad, maybe reset the entire state machine? This will + * benefit from a diagram. + */ blob->closeBlob(session); return; diff --git a/tools/updater.hpp b/tools/updater.hpp index 0a66f34..062f704 100644 --- a/tools/updater.hpp +++ b/tools/updater.hpp @@ -9,6 +9,16 @@ namespace host_tool { /** + * Poll an open verification session. + * + * @param[in] session - the open verification session + * @param[in] blob - pointer to blob interface implementation object. + * @return true if the verification was successul. + */ +bool pollVerificationStatus(std::uint16_t session, + ipmiblob::BlobInterface* blob); + +/** * Attempt to update the BMC's firmware using the interface provided. * * @param[in] blob - pointer to blob interface implementation object. |

