blob: 147a4575e416bcbd96ba98d38f9397333ddfd764 [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
19#include "helper.hpp"
20#include "status.hpp"
21#include "tool_errors.hpp"
22#include "util.hpp"
23
24#include <algorithm>
25#include <blobs-ipmid/blobs.hpp>
26#include <cstdint>
27#include <cstring>
28#include <ipmiblob/blob_errors.hpp>
29#include <string>
30#include <vector>
31
32namespace host_tool
33{
34
35bool UpdateHandler::checkAvailable(const std::string& goalFirmware)
36{
37 std::vector<std::string> blobs = blob->getBlobList();
38
39 auto blobInst = std::find_if(
40 blobs.begin(), blobs.end(), [&goalFirmware](const std::string& iter) {
41 /* Running into weird scenarios where the string comparison doesn't
42 * work. TODO: revisit.
43 */
44 return (0 == std::memcmp(goalFirmware.c_str(), iter.c_str(),
45 goalFirmware.length()));
46 // return (goalFirmware.compare(iter));
47 });
48 if (blobInst == blobs.end())
49 {
50 std::fprintf(stderr, "%s not found\n", goalFirmware.c_str());
51 return false;
52 }
53
54 /* Call stat on /flash/image (or /flash/tarball) and check if data interface
55 * is supported.
56 */
57 ipmiblob::StatResponse stat;
58
59 try
60 {
61 stat = blob->getStat(goalFirmware);
62 }
63 catch (const ipmiblob::BlobException& b)
64 {
65 std::fprintf(stderr, "Received exception '%s' on getStat\n", b.what());
66 return false;
67 }
68
69 auto supported = handler->supportedType();
70 if ((stat.blob_state & supported) == 0)
71 {
72 std::fprintf(stderr, "data interface selected not supported.\n");
73 return false;
74 }
75
76 return true;
77}
78
79void UpdateHandler::sendFile(const std::string& target, const std::string& path)
80{
81 std::uint16_t session;
82 auto supported = handler->supportedType();
83
84 try
85 {
86 session = blob->openBlob(
87 target, static_cast<std::uint16_t>(supported) |
88 static_cast<std::uint16_t>(blobs::OpenFlags::write));
89 }
90 catch (const ipmiblob::BlobException& b)
91 {
92 throw ToolException("blob exception received: " +
93 std::string(b.what()));
94 }
95
96 if (!handler->sendContents(path, session))
97 {
98 /* Need to close the session on failure, or it's stuck open (until the
99 * blob handler timeout is implemented, and even then, why make it wait.
100 */
101 blob->closeBlob(session);
102 throw ToolException("Failed to send contents of " + path);
103 }
104
105 blob->closeBlob(session);
106}
107
108bool UpdateHandler::verifyFile(const std::string& target)
109{
110 std::uint16_t session;
111 bool success = false;
112
113 try
114 {
115 session = blob->openBlob(
116 target, static_cast<std::uint16_t>(blobs::OpenFlags::write));
117 }
118 catch (const ipmiblob::BlobException& b)
119 {
120 throw ToolException("blob exception received: " +
121 std::string(b.what()));
122 }
123
124 std::fprintf(stderr, "Committing to %s to trigger service\n",
125 target.c_str());
126
127 try
128 {
129 blob->commit(session, {});
130 }
131 catch (const ipmiblob::BlobException& b)
132 {
Patrick Venturede73c3b2019-06-20 19:38:17 -0700133 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700134 throw ToolException("blob exception received: " +
135 std::string(b.what()));
136 }
137
138 std::fprintf(stderr, "Calling stat on %s session to check status\n",
139 target.c_str());
140
141 if (pollStatus(session, blob))
142 {
143 std::fprintf(stderr, "Returned success\n");
144 success = true;
145 }
146 else
147 {
148 std::fprintf(stderr, "Returned non-success (could still "
149 "be running (unlikely))\n");
150 }
151
152 blob->closeBlob(session);
153 return (success == true);
154}
155
156void UpdateHandler::cleanArtifacts()
157{
158 /* open(), commit(), close() */
159 std::uint16_t session;
160
161 /* Errors aren't important for this call. */
162 try
163 {
164 std::fprintf(stderr, "Opening the cleanup blob\n");
165 session =
166 blob->openBlob(ipmi_flash::cleanupBlobId,
167 static_cast<std::uint16_t>(blobs::OpenFlags::write));
Patrick Venturede73c3b2019-06-20 19:38:17 -0700168 }
169 catch (...)
170 {
171 return;
172 }
173
174 try
175 {
Patrick Venture01123b22019-06-20 13:49:06 -0700176 std::fprintf(stderr, "Committing to the cleanup blob\n");
177 blob->commit(session, {});
178 std::fprintf(stderr, "Closing cleanup blob\n");
Patrick Venture01123b22019-06-20 13:49:06 -0700179 }
180 catch (...)
181 {
182 }
Patrick Venturede73c3b2019-06-20 19:38:17 -0700183
184 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700185}
186
187} // namespace host_tool