blob: 2b847a9a4239c77bc4b7a5d978433c4b2d37f0f4 [file] [log] [blame]
Patrick Venture01123b22019-06-20 13:49:06 -07001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "handler.hpp"
18
Patrick Venture84778b82019-06-26 20:11:09 -070019#include "flags.hpp"
Patrick Venture01123b22019-06-20 13:49:06 -070020#include "helper.hpp"
21#include "status.hpp"
22#include "tool_errors.hpp"
23#include "util.hpp"
24
Patrick Venture9b37b092020-05-28 20:58:57 -070025#include <ipmiblob/blob_errors.hpp>
William A. Kennington III43eeeb32021-10-14 01:49:34 -070026#include <stdplus/handle/managed.hpp>
Patrick Venture9b37b092020-05-28 20:58:57 -070027
Patrick Venture01123b22019-06-20 13:49:06 -070028#include <algorithm>
Patrick Venture01123b22019-06-20 13:49:06 -070029#include <cstdint>
30#include <cstring>
Patrick Venture01123b22019-06-20 13:49:06 -070031#include <string>
32#include <vector>
33
34namespace host_tool
35{
36
William A. Kennington III43eeeb32021-10-14 01:49:34 -070037static void closeBlob(uint16_t&& session, ipmiblob::BlobInterface*& blob)
38{
39 blob->closeBlob(session);
40}
41
42using BlobHandle =
43 stdplus::Managed<uint16_t, ipmiblob::BlobInterface*>::Handle<closeBlob>;
44
45template <typename... Args>
46inline BlobHandle openBlob(ipmiblob::BlobInterface* blob, Args&&... args)
47{
48 return BlobHandle(blob->openBlob(std::forward<Args>(args)...), blob);
49}
50
Patrick Venture01123b22019-06-20 13:49:06 -070051bool UpdateHandler::checkAvailable(const std::string& goalFirmware)
52{
53 std::vector<std::string> blobs = blob->getBlobList();
54
55 auto blobInst = std::find_if(
56 blobs.begin(), blobs.end(), [&goalFirmware](const std::string& iter) {
57 /* Running into weird scenarios where the string comparison doesn't
58 * work. TODO: revisit.
59 */
60 return (0 == std::memcmp(goalFirmware.c_str(), iter.c_str(),
61 goalFirmware.length()));
62 // return (goalFirmware.compare(iter));
63 });
64 if (blobInst == blobs.end())
65 {
66 std::fprintf(stderr, "%s not found\n", goalFirmware.c_str());
67 return false;
68 }
69
Patrick Venture01123b22019-06-20 13:49:06 -070070 return true;
71}
72
73void UpdateHandler::sendFile(const std::string& target, const std::string& path)
74{
Patrick Venture01123b22019-06-20 13:49:06 -070075 auto supported = handler->supportedType();
76
77 try
78 {
William A. Kennington III43eeeb32021-10-14 01:49:34 -070079 auto session = openBlob(
80 blob, target,
81 static_cast<std::uint16_t>(supported) |
82 static_cast<std::uint16_t>(
83 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
84
85 if (!handler->sendContents(path, *session))
86 {
87 throw ToolException("Failed to send contents of " + path);
88 }
Patrick Venture01123b22019-06-20 13:49:06 -070089 }
90 catch (const ipmiblob::BlobException& b)
91 {
92 throw ToolException("blob exception received: " +
93 std::string(b.what()));
94 }
Patrick Venture01123b22019-06-20 13:49:06 -070095}
96
Brandon Kim6749ba12019-09-19 13:31:37 -070097bool UpdateHandler::verifyFile(const std::string& target, bool ignoreStatus)
Patrick Venture01123b22019-06-20 13:49:06 -070098{
Patrick Venture01123b22019-06-20 13:49:06 -070099 try
100 {
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700101 auto session =
102 openBlob(blob, target,
103 static_cast<std::uint16_t>(
104 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
105
106 std::fprintf(stderr, "Committing to %s to trigger service\n",
107 target.c_str());
108 blob->commit(*session, {});
109
110 if (ignoreStatus)
111 {
112 // Skip checking the blob for status if ignoreStatus is enabled
113 return true;
114 }
115
116 std::fprintf(stderr, "Calling stat on %s session to check status\n",
117 target.c_str());
William A. Kennington IIIf88bcf32021-10-14 02:15:10 -0700118 pollStatus(*session, blob);
119 return true;
Patrick Venture01123b22019-06-20 13:49:06 -0700120 }
121 catch (const ipmiblob::BlobException& b)
122 {
123 throw ToolException("blob exception received: " +
124 std::string(b.what()));
125 }
Patrick Venture01123b22019-06-20 13:49:06 -0700126}
127
Jie Yang328f5202021-03-16 00:52:07 -0700128std::vector<uint8_t> UpdateHandler::readVersion(const std::string& versionBlob)
129{
Jie Yang328f5202021-03-16 00:52:07 -0700130 try
131 {
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700132 auto session =
133 openBlob(blob, versionBlob,
134 static_cast<std::uint16_t>(
135 ipmi_flash::FirmwareFlags::UpdateFlags::openRead));
136
137 std::fprintf(stderr, "Calling stat on %s session to check status\n",
138 versionBlob.c_str());
139
140 /* TODO: call readBytes multiple times in case IPMI message length
141 * exceeds IPMI_MAX_MSG_LENGTH.
142 */
William A. Kennington IIIf88bcf32021-10-14 02:15:10 -0700143 auto size = pollReadReady(*session, blob);
144 if (size > 0)
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700145 {
William A. Kennington IIIf88bcf32021-10-14 02:15:10 -0700146 return blob->readBytes(*session, 0, size);
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700147 }
148 return {};
Jie Yang328f5202021-03-16 00:52:07 -0700149 }
150 catch (const ipmiblob::BlobException& b)
151 {
152 throw ToolException("blob exception received: " +
153 std::string(b.what()));
154 }
Jie Yang328f5202021-03-16 00:52:07 -0700155}
156
Patrick Venture01123b22019-06-20 13:49:06 -0700157void UpdateHandler::cleanArtifacts()
158{
Patrick Venture01123b22019-06-20 13:49:06 -0700159 /* Errors aren't important for this call. */
160 try
161 {
William A. Kennington III4b0c2ec2021-10-14 02:04:14 -0700162 std::fprintf(stderr, "Executing cleanup blob\n");
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700163 auto session =
164 openBlob(blob, ipmi_flash::cleanupBlobId,
165 static_cast<std::uint16_t>(
166 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
William A. Kennington III43eeeb32021-10-14 01:49:34 -0700167 blob->commit(*session, {});
Patrick Venture01123b22019-06-20 13:49:06 -0700168 }
William A. Kennington III4b0c2ec2021-10-14 02:04:14 -0700169 catch (const std::exception& e)
170 {
171 std::fprintf(stderr, "Cleanup failed: %s\n", e.what());
172 }
Patrick Venture01123b22019-06-20 13:49:06 -0700173}
174
175} // namespace host_tool