| /* | 
 |  * Copyright 2018 Google Inc. | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include "updater.hpp" | 
 |  | 
 | #include "tool_errors.hpp" | 
 |  | 
 | #include <algorithm> | 
 | #include <blobs-ipmid/blobs.hpp> | 
 | #include <cstring> | 
 | #include <ipmiblob/blob_errors.hpp> | 
 | #include <memory> | 
 | #include <string> | 
 |  | 
 | namespace host_tool | 
 | { | 
 |  | 
 | void updaterMain(ipmiblob::BlobInterface* blob, DataInterface* handler, | 
 |                  const std::string& imagePath, const std::string& signaturePath) | 
 | { | 
 |     /* TODO(venture): Add optional parameter to specify the flash type, default | 
 |      * to legacy for now. | 
 |      */ | 
 |     std::string goalFirmware = "/flash/image"; | 
 |  | 
 |     /* Get list of blob_ids, check for /flash/image, or /flash/tarball. | 
 |      * TODO(venture) the mechanism doesn't care, but the caller of burn_my_bmc | 
 |      * will have in mind which they're sending and we need to verify it's | 
 |      * available and use it. | 
 |      */ | 
 |     std::vector<std::string> blobs = blob->getBlobList(); | 
 |     auto blobInst = std::find_if( | 
 |         blobs.begin(), blobs.end(), [&goalFirmware](const std::string& iter) { | 
 |             /* Running into weird scenarios where the string comparison doesn't | 
 |              * work.  TODO: revisit. | 
 |              */ | 
 |             return (0 == std::memcmp(goalFirmware.c_str(), iter.c_str(), | 
 |                                      goalFirmware.length())); | 
 |             // return (goalFirmware.compare(iter)); | 
 |         }); | 
 |     if (blobInst == blobs.end()) | 
 |     { | 
 |         throw ToolException(goalFirmware + " not found"); | 
 |     } | 
 |  | 
 |     /* Call stat on /flash/image (or /flash/tarball) and check if data interface | 
 |      * is supported. | 
 |      */ | 
 |     ipmiblob::StatResponse stat; | 
 |     try | 
 |     { | 
 |         stat = blob->getStat(goalFirmware); | 
 |     } | 
 |     catch (const ipmiblob::BlobException& b) | 
 |     { | 
 |         throw ToolException("blob exception received: " + | 
 |                             std::string(b.what())); | 
 |     } | 
 |  | 
 |     auto supported = handler->supportedType(); | 
 |     if ((stat.blob_state & supported) == 0) | 
 |     { | 
 |         throw ToolException("data interface selected not supported."); | 
 |     } | 
 |  | 
 |     /* Yay, our data handler is supported. */ | 
 |     std::uint16_t session; | 
 |     try | 
 |     { | 
 |         session = blob->openBlob( | 
 |             goalFirmware, | 
 |             static_cast<std::uint16_t>(supported) | | 
 |                 static_cast<std::uint16_t>(blobs::OpenFlags::write)); | 
 |     } | 
 |     catch (const ipmiblob::BlobException& b) | 
 |     { | 
 |         throw ToolException("blob exception received: " + | 
 |                             std::string(b.what())); | 
 |     } | 
 |  | 
 |     /* Send over the firmware image. */ | 
 |     if (!handler->sendContents(imagePath, session)) | 
 |     { | 
 |         /* Need to close the session on failure, or it's stuck open (until the | 
 |          * blob handler timeout is implemented, and even then, why make it wait. | 
 |          */ | 
 |         blob->closeBlob(session); | 
 |         throw ToolException("Failed to send contents of " + imagePath); | 
 |     } | 
 |  | 
 |     blob->closeBlob(session); | 
 |  | 
 |     /* Send over the hash contents. */ | 
 |     /* Trigger the verification. */ | 
 |     /* Check the verification. */ | 
 |  | 
 |     return; | 
 | } | 
 |  | 
 | } // namespace host_tool |