xref: /openbmc/phosphor-ipmi-flash/tools/io.cpp (revision 2950c258)
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