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
read(const std::size_t offset,const std::size_t length,void * const destination)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
write(const std::size_t offset,const std::size_t length,const void * const source)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
~PpcMemDevice()94 PpcMemDevice::~PpcMemDevice()
95 {
96 // Attempt to close in case reads or writes didn't close themselves
97 close();
98 }
99
close()100 void PpcMemDevice::close()
101 {
102 if (ppcMemFd >= 0)
103 {
104 sys->close(ppcMemFd);
105 ppcMemFd = -1;
106 }
107 }
108
read(const std::size_t offset,const std::size_t length,void * const destination)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
write(const std::size_t offset,const std::size_t length,const void * const source)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