blob: 9af8acee8e27d388da52d2e3c1272229eea0d6e2 [file] [log] [blame]
Patrick Venture030b1a82019-01-18 08:33:02 -08001#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
11namespace host_tool
12{
13
14const std::string DevMemDevice::devMemPath = "/dev/mem";
15
Patrick Ventureac4ff972019-05-03 17:35:00 -070016bool DevMemDevice::read(const std::size_t offset, const std::size_t length,
17 void* const destination)
18{
Patrick Venture18bbe3c2019-05-14 11:40:57 -070019 devMemFd = sys->open(devMemPath.c_str(), O_RDONLY);
20 if (devMemFd < 0)
Patrick Ventureac4ff972019-05-03 17:35:00 -070021 {
Patrick Venture18bbe3c2019-05-14 11:40:57 -070022 return false;
Patrick Ventureac4ff972019-05-03 17:35:00 -070023 }
24
Patrick Venture206097b2019-05-07 13:37:01 -070025 /* 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
Patrick Ventureac4ff972019-05-03 17:35:00 -070030 // addr, length, prot, flags, fd, offset
Patrick Venture206097b2019-05-07 13:37:01 -070031 devMemMapped = sys->mmap(0, alignedSize, PROT_READ, MAP_SHARED, devMemFd,
32 alignedOffset);
Patrick Ventureac4ff972019-05-03 17:35:00 -070033 if (devMemMapped == MAP_FAILED)
34 {
Patrick Venture213f2db2019-05-15 10:47:30 -070035 std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n",
Patrick Venture18bbe3c2019-05-14 11:40:57 -070036 offset, length);
37 sys->close(devMemFd);
38 return false;
Patrick Ventureac4ff972019-05-03 17:35:00 -070039 }
40
Patrick Venture206097b2019-05-07 13:37:01 -070041 void* alignedSource =
42 static_cast<std::uint8_t*>(devMemMapped) + alignedDiff;
43
Patrick Ventureac4ff972019-05-03 17:35:00 -070044 /* Copy the bytes. */
Patrick Venture206097b2019-05-07 13:37:01 -070045 std::memcpy(destination, alignedSource, length);
Patrick Ventureac4ff972019-05-03 17:35:00 -070046
47 /* Close the map between reads for now. */
48 sys->munmap(devMemMapped, length);
Patrick Venture18bbe3c2019-05-14 11:40:57 -070049 sys->close(devMemFd);
Patrick Ventureac4ff972019-05-03 17:35:00 -070050
51 return true;
52}
53
Patrick Venture030b1a82019-01-18 08:33:02 -080054bool DevMemDevice::write(const std::size_t offset, const std::size_t length,
55 const void* const source)
56{
Patrick Venture18bbe3c2019-05-14 11:40:57 -070057 devMemFd = sys->open(devMemPath.c_str(), O_RDWR);
58 if (devMemFd < 0)
Patrick Venture030b1a82019-01-18 08:33:02 -080059 {
Patrick Venture18bbe3c2019-05-14 11:40:57 -070060 std::fprintf(stderr, "Failed to open /dev/mem for writing\n");
61 return false;
Patrick Venture030b1a82019-01-18 08:33:02 -080062 }
63
Patrick Venture206097b2019-05-07 13:37:01 -070064 /* 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
Patrick Venture030b1a82019-01-18 08:33:02 -080069 // addr, length, prot, flags, fd, offset
Patrick Venture206097b2019-05-07 13:37:01 -070070 devMemMapped = sys->mmap(0, alignedSize, PROT_WRITE, MAP_SHARED, devMemFd,
71 alignedOffset);
72
Patrick Venture030b1a82019-01-18 08:33:02 -080073 if (devMemMapped == MAP_FAILED)
74 {
Patrick Venture213f2db2019-05-15 10:47:30 -070075 std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n",
Patrick Venture18bbe3c2019-05-14 11:40:57 -070076 offset, length);
77 sys->close(devMemFd);
78 return false;
Patrick Venture030b1a82019-01-18 08:33:02 -080079 }
80
Patrick Venture206097b2019-05-07 13:37:01 -070081 void* alignedDestination =
82 static_cast<std::uint8_t*>(devMemMapped) + alignedDiff;
83
Patrick Venture030b1a82019-01-18 08:33:02 -080084 /* Copy the bytes. */
Patrick Venture206097b2019-05-07 13:37:01 -070085 std::memcpy(alignedDestination, source, length);
Patrick Venture030b1a82019-01-18 08:33:02 -080086
87 /* Close the map between writes for now. */
88 sys->munmap(devMemMapped, length);
Patrick Venture18bbe3c2019-05-14 11:40:57 -070089 sys->close(devMemFd);
Patrick Venture030b1a82019-01-18 08:33:02 -080090
91 return true;
92}
93
Brandon Kim286cc6a2019-11-05 16:39:47 -080094PpcMemDevice::~PpcMemDevice()
95{
96 // Attempt to close in case reads or writes didn't close themselves
Patrick Ventureea0e4702020-10-05 12:22:59 -070097 close();
98}
99
100void PpcMemDevice::close()
101{
Brandon Kim286cc6a2019-11-05 16:39:47 -0800102 if (ppcMemFd >= 0)
103 {
104 sys->close(ppcMemFd);
Patrick Ventureea0e4702020-10-05 12:22:59 -0700105 ppcMemFd = -1;
Brandon Kim286cc6a2019-11-05 16:39:47 -0800106 }
107}
108
109bool 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);
Patrick Ventureea0e4702020-10-05 12:22:59 -0700125 close();
Brandon Kim286cc6a2019-11-05 16:39:47 -0800126 return false;
127 }
128
Patrick Ventureea0e4702020-10-05 12:22:59 -0700129 close();
Brandon Kim286cc6a2019-11-05 16:39:47 -0800130 return true;
131}
132
133bool 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);
Patrick Ventureea0e4702020-10-05 12:22:59 -0700149 close();
Brandon Kim286cc6a2019-11-05 16:39:47 -0800150 return false;
151 }
152
Patrick Ventureea0e4702020-10-05 12:22:59 -0700153 close();
Brandon Kim286cc6a2019-11-05 16:39:47 -0800154 return true;
155}
156
Patrick Venture030b1a82019-01-18 08:33:02 -0800157} // namespace host_tool