1b5bf0fc2SPatrick Venture /* 2b5bf0fc2SPatrick Venture * Copyright 2019 Google Inc. 3b5bf0fc2SPatrick Venture * 4b5bf0fc2SPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License"); 5b5bf0fc2SPatrick Venture * you may not use this file except in compliance with the License. 6b5bf0fc2SPatrick Venture * You may obtain a copy of the License at 7b5bf0fc2SPatrick Venture * 8b5bf0fc2SPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0 9b5bf0fc2SPatrick Venture * 10b5bf0fc2SPatrick Venture * Unless required by applicable law or agreed to in writing, software 11b5bf0fc2SPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS, 12b5bf0fc2SPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b5bf0fc2SPatrick Venture * See the License for the specific language governing permissions and 14b5bf0fc2SPatrick Venture * limitations under the License. 15b5bf0fc2SPatrick Venture */ 16b5bf0fc2SPatrick Venture 17b5bf0fc2SPatrick Venture #include "p2a.hpp" 18b5bf0fc2SPatrick Venture 1984778b8dSPatrick Venture #include "data.hpp" 2084778b8dSPatrick Venture #include "flags.hpp" 21b5bf0fc2SPatrick Venture #include "pci.hpp" 22e5aafa5bSBenjamin Fair #include "tool_errors.hpp" 23e5aafa5bSBenjamin Fair 24e5aafa5bSBenjamin Fair #include <fmt/format.h> 25c73dce91SPatrick Venture 269b37b095SPatrick Venture #include <ipmiblob/blob_errors.hpp> 27e5aafa5bSBenjamin Fair #include <stdplus/handle/managed.hpp> 289b37b095SPatrick Venture 2984778b8dSPatrick Venture #include <cstdint> 30c73dce91SPatrick Venture #include <cstring> 3184778b8dSPatrick Venture #include <memory> 32*28c00d6eSPatrick Williams #include <span> 3384778b8dSPatrick Venture #include <string> 34b5bf0fc2SPatrick Venture 35b5bf0fc2SPatrick Venture namespace host_tool 36b5bf0fc2SPatrick Venture { 37b5bf0fc2SPatrick Venture 38cf0e5de3SPatrick Venture namespace 39cf0e5de3SPatrick Venture { 40cf0e5de3SPatrick Venture 41e5aafa5bSBenjamin Fair /** @brief RAII wrapper and its destructor for opening a file descriptor */ 42e5aafa5bSBenjamin Fair static void closeFd(int&& fd, const internal::Sys* const& sys) 43e5aafa5bSBenjamin Fair { 44e5aafa5bSBenjamin Fair sys->close(fd); 45cf0e5de3SPatrick Venture } 46e5aafa5bSBenjamin Fair using Fd = stdplus::Managed<int, const internal::Sys* const>::Handle<closeFd>; 47cf0e5de3SPatrick Venture 48cf0e5de3SPatrick Venture } // namespace 49cf0e5de3SPatrick Venture 50b5bf0fc2SPatrick Venture bool P2aDataHandler::sendContents(const std::string& input, 51b5bf0fc2SPatrick Venture std::uint16_t session) 52b5bf0fc2SPatrick Venture { 53e5aafa5bSBenjamin Fair std::unique_ptr<PciBridgeIntf> bridge; 54cf0e5de3SPatrick Venture ipmi_flash::PciConfigResponse pciResp; 55cf0e5de3SPatrick Venture std::int64_t fileSize; 56b5bf0fc2SPatrick Venture 57e5aafa5bSBenjamin Fair try 58c8445aaaSMedad CChien { 598a9de245SWilly Tu bridge = std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable); 60b5bf0fc2SPatrick Venture } 61665905ffSPatrick Williams catch (const NotFoundException& e) 62e5aafa5bSBenjamin Fair {} 63b5bf0fc2SPatrick Venture 64e5aafa5bSBenjamin Fair try 65c8445aaaSMedad CChien { 668a9de245SWilly Tu bridge = std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable); 67c8445aaaSMedad CChien } 68665905ffSPatrick Williams catch (const NotFoundException& e) 69e5aafa5bSBenjamin Fair {} 70c8445aaaSMedad CChien 71e5aafa5bSBenjamin Fair if (!bridge) 7236bb4670SPatrick Venture { 73e5aafa5bSBenjamin Fair throw NotFoundException("supported PCI device"); 74c8445aaaSMedad CChien } 7524141611SPatrick Venture 7624141611SPatrick Venture /* Read the configuration via blobs metadata (stat). */ 77c73dce91SPatrick Venture ipmiblob::StatResponse stat = blob->getStat(session); 781d5a31c9SPatrick Venture if (stat.metadata.size() != sizeof(ipmi_flash::PciConfigResponse)) 79c73dce91SPatrick Venture { 80e5aafa5bSBenjamin Fair throw ToolException("Didn't receive expected size of metadata for " 81e5aafa5bSBenjamin Fair "PCI Configuration response"); 82c73dce91SPatrick Venture } 83c73dce91SPatrick Venture 84c73dce91SPatrick Venture std::memcpy(&pciResp, stat.metadata.data(), sizeof(pciResp)); 85e5aafa5bSBenjamin Fair bridge->configure(pciResp); 8624141611SPatrick Venture 8718bbe3c6SPatrick Venture /* For data blocks in 64kb, stage data, and send blob write command. */ 88e5aafa5bSBenjamin Fair Fd inputFd(sys->open(input.c_str(), 0), sys); 89e5aafa5bSBenjamin Fair if (*inputFd < 0) 9018bbe3c6SPatrick Venture { 91e5aafa5bSBenjamin Fair (void)inputFd.release(); 92e5aafa5bSBenjamin Fair throw internal::errnoException( 93e5aafa5bSBenjamin Fair fmt::format("Error opening file '{}'", input)); 94b5bf0fc2SPatrick Venture } 95b5bf0fc2SPatrick Venture 96cf0e5de3SPatrick Venture fileSize = sys->getSize(input.c_str()); 97cf9b2195SPatrick Venture progress->start(fileSize); 98cf9b2195SPatrick Venture 99e5aafa5bSBenjamin Fair std::vector<std::uint8_t> readBuffer(bridge->getDataLength()); 10018bbe3c6SPatrick Venture 10163528046SPatrick Venture int bytesRead = 0; 10263528046SPatrick Venture std::uint32_t offset = 0; 10363528046SPatrick Venture 10418bbe3c6SPatrick Venture do 10518bbe3c6SPatrick Venture { 106e5aafa5bSBenjamin Fair bytesRead = sys->read(*inputFd, readBuffer.data(), readBuffer.size()); 10718bbe3c6SPatrick Venture if (bytesRead > 0) 10818bbe3c6SPatrick Venture { 109*28c00d6eSPatrick Williams bridge->write( 110*28c00d6eSPatrick Williams std::span<const std::uint8_t>(readBuffer.data(), bytesRead)); 11118bbe3c6SPatrick Venture 112c8445aaaSMedad CChien /* Ok, so the data is staged, now send the blob write with the 113c8445aaaSMedad CChien * details. 11418bbe3c6SPatrick Venture */ 1151d5a31c9SPatrick Venture struct ipmi_flash::ExtChunkHdr chunk; 11618bbe3c6SPatrick Venture chunk.length = bytesRead; 11718bbe3c6SPatrick Venture std::vector<std::uint8_t> chunkBytes(sizeof(chunk)); 11818bbe3c6SPatrick Venture std::memcpy(chunkBytes.data(), &chunk, sizeof(chunk)); 11918bbe3c6SPatrick Venture 12018bbe3c6SPatrick Venture /* This doesn't return anything on success. */ 12118bbe3c6SPatrick Venture blob->writeBytes(session, offset, chunkBytes); 12218bbe3c6SPatrick Venture offset += bytesRead; 123cf9b2195SPatrick Venture progress->updateProgress(bytesRead); 12418bbe3c6SPatrick Venture } 12518bbe3c6SPatrick Venture } while (bytesRead > 0); 12618bbe3c6SPatrick Venture 1270d5bb784SWilliam A. Kennington III progress->finish(); 128e5aafa5bSBenjamin Fair return true; 12918bbe3c6SPatrick Venture } 13018bbe3c6SPatrick Venture 131b5bf0fc2SPatrick Venture } // namespace host_tool 132