blob: dbaa53f72097f5eaa00ab6cf8051c53f8c7e203a [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
25#include <algorithm>
Patrick Venture01123b22019-06-20 13:49:06 -070026#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
Patrick Venture01123b22019-06-20 13:49:06 -070054 return true;
55}
56
57void UpdateHandler::sendFile(const std::string& target, const std::string& path)
58{
59 std::uint16_t session;
60 auto supported = handler->supportedType();
61
62 try
63 {
64 session = blob->openBlob(
65 target, static_cast<std::uint16_t>(supported) |
Patrick Venture84778b82019-06-26 20:11:09 -070066 static_cast<std::uint16_t>(
67 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venture01123b22019-06-20 13:49:06 -070068 }
69 catch (const ipmiblob::BlobException& b)
70 {
71 throw ToolException("blob exception received: " +
72 std::string(b.what()));
73 }
74
75 if (!handler->sendContents(path, session))
76 {
77 /* Need to close the session on failure, or it's stuck open (until the
78 * blob handler timeout is implemented, and even then, why make it wait.
79 */
80 blob->closeBlob(session);
81 throw ToolException("Failed to send contents of " + path);
82 }
83
84 blob->closeBlob(session);
85}
86
Brandon Kim6749ba12019-09-19 13:31:37 -070087bool UpdateHandler::verifyFile(const std::string& target, bool ignoreStatus)
Patrick Venture01123b22019-06-20 13:49:06 -070088{
89 std::uint16_t session;
90 bool success = false;
91
92 try
93 {
94 session = blob->openBlob(
Patrick Venture84778b82019-06-26 20:11:09 -070095 target, static_cast<std::uint16_t>(
96 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venture01123b22019-06-20 13:49:06 -070097 }
98 catch (const ipmiblob::BlobException& b)
99 {
100 throw ToolException("blob exception received: " +
101 std::string(b.what()));
102 }
103
104 std::fprintf(stderr, "Committing to %s to trigger service\n",
105 target.c_str());
106
107 try
108 {
109 blob->commit(session, {});
110 }
111 catch (const ipmiblob::BlobException& b)
112 {
Patrick Venturede73c3b2019-06-20 19:38:17 -0700113 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700114 throw ToolException("blob exception received: " +
115 std::string(b.what()));
116 }
117
Brandon Kim6749ba12019-09-19 13:31:37 -0700118 if (ignoreStatus)
119 {
120 // Skip checking the blob for status if ignoreStatus is enabled
121 blob->closeBlob(session);
122 return true;
123 }
124
Patrick Venture01123b22019-06-20 13:49:06 -0700125 std::fprintf(stderr, "Calling stat on %s session to check status\n",
126 target.c_str());
127
128 if (pollStatus(session, blob))
129 {
130 std::fprintf(stderr, "Returned success\n");
131 success = true;
132 }
133 else
134 {
135 std::fprintf(stderr, "Returned non-success (could still "
136 "be running (unlikely))\n");
137 }
138
139 blob->closeBlob(session);
140 return (success == true);
141}
142
143void UpdateHandler::cleanArtifacts()
144{
145 /* open(), commit(), close() */
146 std::uint16_t session;
147
148 /* Errors aren't important for this call. */
149 try
150 {
151 std::fprintf(stderr, "Opening the cleanup blob\n");
Patrick Venture84778b82019-06-26 20:11:09 -0700152 session = blob->openBlob(
153 ipmi_flash::cleanupBlobId,
154 static_cast<std::uint16_t>(
155 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite));
Patrick Venturede73c3b2019-06-20 19:38:17 -0700156 }
157 catch (...)
158 {
159 return;
160 }
161
162 try
163 {
Patrick Venture01123b22019-06-20 13:49:06 -0700164 std::fprintf(stderr, "Committing to the cleanup blob\n");
165 blob->commit(session, {});
166 std::fprintf(stderr, "Closing cleanup blob\n");
Patrick Venture01123b22019-06-20 13:49:06 -0700167 }
168 catch (...)
169 {
170 }
Patrick Venturede73c3b2019-06-20 19:38:17 -0700171
172 blob->closeBlob(session);
Patrick Venture01123b22019-06-20 13:49:06 -0700173}
174
175} // namespace host_tool