1 /* 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 "flags.hpp" 20 #include "helper.hpp" 21 #include "status.hpp" 22 #include "tool_errors.hpp" 23 #include "util.hpp" 24 25 #include <ipmiblob/blob_errors.hpp> 26 27 #include <algorithm> 28 #include <cstdint> 29 #include <cstring> 30 #include <string> 31 #include <vector> 32 33 namespace host_tool 34 { 35 36 bool 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 55 return true; 56 } 57 58 void 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) | 67 static_cast<std::uint16_t>( 68 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite)); 69 } 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 88 bool UpdateHandler::verifyFile(const std::string& target, bool ignoreStatus) 89 { 90 std::uint16_t session; 91 bool success = false; 92 93 try 94 { 95 session = blob->openBlob( 96 target, static_cast<std::uint16_t>( 97 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite)); 98 } 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 { 114 blob->closeBlob(session); 115 throw ToolException("blob exception received: " + 116 std::string(b.what())); 117 } 118 119 if (ignoreStatus) 120 { 121 // Skip checking the blob for status if ignoreStatus is enabled 122 blob->closeBlob(session); 123 return true; 124 } 125 126 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 144 void UpdateHandler::cleanArtifacts() 145 { 146 /* open(), commit(), close() */ 147 std::uint16_t session; 148 149 /* Errors aren't important for this call. */ 150 try 151 { 152 std::fprintf(stderr, "Opening the cleanup blob\n"); 153 session = blob->openBlob( 154 ipmi_flash::cleanupBlobId, 155 static_cast<std::uint16_t>( 156 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite)); 157 } 158 catch (...) 159 { 160 return; 161 } 162 163 try 164 { 165 std::fprintf(stderr, "Committing to the cleanup blob\n"); 166 blob->commit(session, {}); 167 std::fprintf(stderr, "Closing cleanup blob\n"); 168 } 169 catch (...) 170 {} 171 172 blob->closeBlob(session); 173 } 174 175 } // namespace host_tool 176