blob: 8cd7a999460ac443a933f0d6b57537a9cd415576 [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>
26
Patrick Venture01123b22019-06-20 13:49:06 -070027#include <algorithm>
Patrick Venture01123b22019-06-20 13:49:06 -070028#include <cstdint>
29#include <cstring>
Patrick Venture01123b22019-06-20 13:49:06 -070030#include <string>
31#include <vector>
32
33namespace host_tool
34{
35
36bool UpdateHandler::checkAvailable(const std::string& goalFirmware)
37{
38 std::vector<std::string> blobs = blob->getBlobList();
39
40 auto blobInst = std::find_if(
41 blobs.begin(), blobs.end(), [&goalFirmware](const std::string& iter) {
42 /* Running into weird scenarios where the string comparison doesn't
43 * work. TODO: revisit.
44 */
45 return (0 == std::memcmp(goalFirmware.c_str(), iter.c_str(),
46 goalFirmware.length()));
47 // return (goalFirmware.compare(iter));
48 });
49 if (blobInst == blobs.end())
50 {
51 std::fprintf(stderr, "%s not found\n", goalFirmware.c_str());
52 return false;
53 }
54
Patrick Venture01123b22019-06-20 13:49:06 -070055 return true;
56}
57
58void UpdateHandler::sendFile(const std::string& target, const std::string& path)
59{
60 std::uint16_t session;
61 auto supported = handler->supportedType();
62
63 try
64 {
65 session = blob->openBlob(
66 target, static_cast<std::uint16_t>(supported) |
Patrick Venture84778b82019-06-26 20:11:09 -070067 static_cast<std::uint16_t>(
68 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venture01123b22019-06-20 13:49:06 -070069 }
70 catch (const ipmiblob::BlobException& b)
71 {
72 throw ToolException("blob exception received: " +
73 std::string(b.what()));
74 }
75
76 if (!handler->sendContents(path, session))
77 {
78 /* Need to close the session on failure, or it's stuck open (until the
79 * blob handler timeout is implemented, and even then, why make it wait.
80 */
81 blob->closeBlob(session);
82 throw ToolException("Failed to send contents of " + path);
83 }
84
85 blob->closeBlob(session);
86}
87
Brandon Kim6749ba12019-09-19 13:31:37 -070088bool UpdateHandler::verifyFile(const std::string& target, bool ignoreStatus)
Patrick Venture01123b22019-06-20 13:49:06 -070089{
90 std::uint16_t session;
91 bool success = false;
92
93 try
94 {
95 session = blob->openBlob(
Patrick Venture84778b82019-06-26 20:11:09 -070096 target, static_cast<std::uint16_t>(
97 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venture01123b22019-06-20 13:49:06 -070098 }
99 catch (const ipmiblob::BlobException& b)
100 {
101 throw ToolException("blob exception received: " +
102 std::string(b.what()));
103 }
104
105 std::fprintf(stderr, "Committing to %s to trigger service\n",
106 target.c_str());
107
108 try
109 {
110 blob->commit(session, {});
111 }
112 catch (const ipmiblob::BlobException& b)
113 {
Patrick Venturede73c3b2019-06-20 19:38:17 -0700114 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700115 throw ToolException("blob exception received: " +
116 std::string(b.what()));
117 }
118
Brandon Kim6749ba12019-09-19 13:31:37 -0700119 if (ignoreStatus)
120 {
121 // Skip checking the blob for status if ignoreStatus is enabled
122 blob->closeBlob(session);
123 return true;
124 }
125
Patrick Venture01123b22019-06-20 13:49:06 -0700126 std::fprintf(stderr, "Calling stat on %s session to check status\n",
127 target.c_str());
128
129 if (pollStatus(session, blob))
130 {
131 std::fprintf(stderr, "Returned success\n");
132 success = true;
133 }
134 else
135 {
136 std::fprintf(stderr, "Returned non-success (could still "
137 "be running (unlikely))\n");
138 }
139
140 blob->closeBlob(session);
141 return (success == true);
142}
143
Jie Yang328f5202021-03-16 00:52:07 -0700144std::vector<uint8_t> UpdateHandler::readVersion(const std::string& versionBlob)
145{
146 std::uint16_t session;
147
148 try
149 {
150 session = blob->openBlob(
151 versionBlob, static_cast<std::uint16_t>(
152 ipmi_flash::FirmwareFlags::UpdateFlags::openRead));
153 }
154 catch (const ipmiblob::BlobException& b)
155 {
156 throw ToolException("blob exception received: " +
157 std::string(b.what()));
158 }
159
160 std::fprintf(stderr, "Calling stat on %s session to check status\n",
161 versionBlob.c_str());
162 std::vector<uint8_t> data;
163
164 /* TODO: call readBytes multiple times in case IPMI message length exceeds
165 * IPMI_MAX_MSG_LENGTH.
166 */
167 auto pollResp = pollReadReady(session, blob);
168 if (pollResp.first)
169 {
170 std::fprintf(stderr, "Returned success\n");
171 if (pollResp.second > 0)
172 {
173 try
174 {
175 data = blob->readBytes(session, 0, pollResp.second);
176 }
177 catch (const ipmiblob::BlobException& b)
178 {
179 blob->closeBlob(session);
180 throw ToolException("blob exception received: " +
181 std::string(b.what()));
182 }
183 }
184 }
185 else
186 {
187 std::fprintf(stderr, "Returned non-success (could still "
188 "be running (unlikely))\n");
189 }
190
191 blob->closeBlob(session);
192 return data;
193}
194
Patrick Venture01123b22019-06-20 13:49:06 -0700195void UpdateHandler::cleanArtifacts()
196{
197 /* open(), commit(), close() */
198 std::uint16_t session;
199
200 /* Errors aren't important for this call. */
201 try
202 {
203 std::fprintf(stderr, "Opening the cleanup blob\n");
Patrick Venture84778b82019-06-26 20:11:09 -0700204 session = blob->openBlob(
205 ipmi_flash::cleanupBlobId,
206 static_cast<std::uint16_t>(
207 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venturede73c3b2019-06-20 19:38:17 -0700208 }
209 catch (...)
210 {
211 return;
212 }
213
214 try
215 {
Patrick Venture01123b22019-06-20 13:49:06 -0700216 std::fprintf(stderr, "Committing to the cleanup blob\n");
217 blob->commit(session, {});
218 std::fprintf(stderr, "Closing cleanup blob\n");
Patrick Venture01123b22019-06-20 13:49:06 -0700219 }
220 catch (...)
Patrick Venture9b37b092020-05-28 20:58:57 -0700221 {}
Patrick Venturede73c3b2019-06-20 19:38:17 -0700222
223 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700224}
225
226} // namespace host_tool