1 #include "io.hpp" 2 3 #include "internal/sys.hpp" 4 5 #include <fcntl.h> 6 7 #include <cstdint> 8 #include <cstring> 9 #include <string> 10 11 namespace host_tool 12 { 13 14 const std::string DevMemDevice::devMemPath = "/dev/mem"; 15 16 bool DevMemDevice::read(const std::size_t offset, const std::size_t length, 17 void* const destination) 18 { 19 devMemFd = sys->open(devMemPath.c_str(), O_RDONLY); 20 if (devMemFd < 0) 21 { 22 return false; 23 } 24 25 /* Map based on aligned addresses - behind the scenes. */ 26 const std::size_t alignedDiff = offset % sys->getpagesize(); 27 const std::size_t alignedOffset = offset - alignedDiff; 28 const std::size_t alignedSize = length + alignedDiff; 29 30 // addr, length, prot, flags, fd, offset 31 devMemMapped = sys->mmap(0, alignedSize, PROT_READ, MAP_SHARED, devMemFd, 32 alignedOffset); 33 if (devMemMapped == MAP_FAILED) 34 { 35 std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n", 36 offset, length); 37 sys->close(devMemFd); 38 return false; 39 } 40 41 void* alignedSource = 42 static_cast<std::uint8_t*>(devMemMapped) + alignedDiff; 43 44 /* Copy the bytes. */ 45 std::memcpy(destination, alignedSource, length); 46 47 /* Close the map between reads for now. */ 48 sys->munmap(devMemMapped, length); 49 sys->close(devMemFd); 50 51 return true; 52 } 53 54 bool DevMemDevice::write(const std::size_t offset, const std::size_t length, 55 const void* const source) 56 { 57 devMemFd = sys->open(devMemPath.c_str(), O_RDWR); 58 if (devMemFd < 0) 59 { 60 std::fprintf(stderr, "Failed to open /dev/mem for writing\n"); 61 return false; 62 } 63 64 /* Map based on aligned addresses - behind the scenes. */ 65 const std::size_t alignedDiff = offset % sys->getpagesize(); 66 const std::size_t alignedOffset = offset - alignedDiff; 67 const std::size_t alignedSize = length + alignedDiff; 68 69 // addr, length, prot, flags, fd, offset 70 devMemMapped = sys->mmap(0, alignedSize, PROT_WRITE, MAP_SHARED, devMemFd, 71 alignedOffset); 72 73 if (devMemMapped == MAP_FAILED) 74 { 75 std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n", 76 offset, length); 77 sys->close(devMemFd); 78 return false; 79 } 80 81 void* alignedDestination = 82 static_cast<std::uint8_t*>(devMemMapped) + alignedDiff; 83 84 /* Copy the bytes. */ 85 std::memcpy(alignedDestination, source, length); 86 87 /* Close the map between writes for now. */ 88 sys->munmap(devMemMapped, length); 89 sys->close(devMemFd); 90 91 return true; 92 } 93 94 PpcMemDevice::~PpcMemDevice() 95 { 96 // Attempt to close in case reads or writes didn't close themselves 97 close(); 98 } 99 100 void PpcMemDevice::close() 101 { 102 if (ppcMemFd >= 0) 103 { 104 sys->close(ppcMemFd); 105 ppcMemFd = -1; 106 } 107 } 108 109 bool PpcMemDevice::read(const std::size_t offset, const std::size_t length, 110 void* const destination) 111 { 112 ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR); 113 if (ppcMemFd < 0) 114 { 115 std::fprintf(stderr, "Failed to open PPC LPC access path: %s", 116 ppcMemPath.c_str()); 117 return false; 118 } 119 120 int ret = sys->pread(ppcMemFd, destination, length, offset); 121 if (ret < 0) 122 { 123 std::fprintf(stderr, "IO read failed at offset: 0x%zx, length: %zu\n", 124 offset, length); 125 close(); 126 return false; 127 } 128 129 close(); 130 return true; 131 } 132 133 bool PpcMemDevice::write(const std::size_t offset, const std::size_t length, 134 const void* const source) 135 { 136 ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR); 137 if (ppcMemFd < 0) 138 { 139 std::fprintf(stderr, "Failed to open PPC LPC access path: %s", 140 ppcMemPath.c_str()); 141 return false; 142 } 143 144 ssize_t ret = sys->pwrite(ppcMemFd, source, length, offset); 145 if (ret < 0) 146 { 147 std::fprintf(stderr, "IO write failed at offset: 0x%zx, length: %zu\n", 148 offset, length); 149 close(); 150 return false; 151 } 152 153 close(); 154 return true; 155 } 156 157 } // namespace host_tool 158