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 } // namespace host_tool 95