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 if (ppcMemFd >= 0) 98 { 99 sys->close(ppcMemFd); 100 } 101 } 102 103 bool PpcMemDevice::read(const std::size_t offset, const std::size_t length, 104 void* const destination) 105 { 106 ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR); 107 if (ppcMemFd < 0) 108 { 109 std::fprintf(stderr, "Failed to open PPC LPC access path: %s", 110 ppcMemPath.c_str()); 111 return false; 112 } 113 114 int ret = sys->pread(ppcMemFd, destination, length, offset); 115 if (ret < 0) 116 { 117 std::fprintf(stderr, "IO read failed at offset: 0x%zx, length: %zu\n", 118 offset, length); 119 sys->close(ppcMemFd); 120 return false; 121 } 122 123 sys->close(ppcMemFd); 124 return true; 125 } 126 127 bool PpcMemDevice::write(const std::size_t offset, const std::size_t length, 128 const void* const source) 129 { 130 ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR); 131 if (ppcMemFd < 0) 132 { 133 std::fprintf(stderr, "Failed to open PPC LPC access path: %s", 134 ppcMemPath.c_str()); 135 return false; 136 } 137 138 ssize_t ret = sys->pwrite(ppcMemFd, source, length, offset); 139 if (ret < 0) 140 { 141 std::fprintf(stderr, "IO write failed at offset: 0x%zx, length: %zu\n", 142 offset, length); 143 sys->close(ppcMemFd); 144 return false; 145 } 146 147 sys->close(ppcMemFd); 148 return true; 149 } 150 151 } // namespace host_tool 152