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 "data.hpp" 18 #include "pci_handler.hpp" 19 20 #include <fcntl.h> 21 22 #include <cstdint> 23 #include <cstring> 24 #include <string> 25 #include <vector> 26 27 namespace ipmi_flash 28 { 29 30 bool PciDataHandler::open() 31 { 32 static constexpr auto devmem = "/dev/mem"; 33 34 mappedFd = sys->open(devmem, O_RDWR | O_SYNC); 35 if (mappedFd == -1) 36 { 37 std::fprintf(stderr, "PciDataHandler::Unable to open /dev/mem"); 38 return false; 39 } 40 41 mapped = reinterpret_cast<uint8_t*>(sys->mmap( 42 0, memoryRegionSize, PROT_READ, MAP_SHARED, mappedFd, regionAddress)); 43 if (mapped == MAP_FAILED) 44 { 45 sys->close(mappedFd); 46 mappedFd = -1; 47 mapped = nullptr; 48 49 std::fprintf(stderr, "PciDataHandler::Unable to map region"); 50 return false; 51 } 52 53 return true; 54 } 55 56 bool PciDataHandler::close() 57 { 58 /* TODO: Turn off the P2A bridge and region to disable host-side access. 59 */ 60 if (mapped) 61 { 62 sys->munmap(mapped, memoryRegionSize); 63 mapped = nullptr; 64 } 65 66 if (mappedFd != -1) 67 { 68 sys->close(mappedFd); 69 mappedFd = -1; 70 } 71 72 return true; 73 } 74 75 std::vector<std::uint8_t> PciDataHandler::copyFrom(std::uint32_t length) 76 { 77 std::vector<std::uint8_t> results(length); 78 std::memcpy(results.data(), mapped, length); 79 80 return results; 81 } 82 83 bool PciDataHandler::writeMeta(const std::vector<std::uint8_t>&) 84 { 85 /* PCI handler doesn't require configuration write, only read. */ 86 return false; 87 } 88 89 std::vector<std::uint8_t> PciDataHandler::readMeta() 90 { 91 /* PCI handler does require returning a configuration from read. */ 92 struct PciConfigResponse reply; 93 reply.address = regionAddress; 94 95 std::vector<std::uint8_t> bytes; 96 bytes.resize(sizeof(reply)); 97 std::memcpy(bytes.data(), &reply, sizeof(reply)); 98 99 return bytes; 100 } 101 102 } // namespace ipmi_flash 103