lpc_aspeed: add mapping implementation
Add mapper implementation for Aspeed.
Change-Id: I4bc1cbaaa6c0bf57424b0c881cb087153d63597c
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/lpc_aspeed.cpp b/lpc_aspeed.cpp
index df2b13c..63147c4 100644
--- a/lpc_aspeed.cpp
+++ b/lpc_aspeed.cpp
@@ -18,25 +18,82 @@
#include "lpc_interface.hpp"
+#include <fcntl.h>
+#include <linux/aspeed-lpc-ctrl.h>
+#include <linux/kernel.h>
+
#include <cstdint>
+#include <cstring>
#include <memory>
#include <utility>
namespace blobs
{
-std::unique_ptr<LpcMapperInterface> LpcMapperAspeed::createAspeedMapper()
+std::unique_ptr<LpcMapperInterface>
+ LpcMapperAspeed::createAspeedMapper(size_t regionSize)
{
/* NOTE: considered using a joint factory to create one or the other, for
* now, separate factories.
*/
- return std::make_unique<LpcMapperAspeed>();
+ return std::make_unique<LpcMapperAspeed>(regionSize);
}
std::pair<std::uint32_t, std::uint32_t>
LpcMapperAspeed::mapWindow(std::uint32_t address, std::uint32_t length)
{
- return std::make_pair(0, 0);
+ static const std::uint32_t MASK_64K = 0xFFFFU;
+ const std::uint32_t offset = address & MASK_64K;
+
+ if (offset + length > regionSize)
+ {
+ std::fprintf(stderr,
+ "requested window size %" PRIu32 ", offset %#" PRIx32
+ " is too large for mem region"
+ " of size %zu\n",
+ length, offset, regionSize);
+ /* TODO: need to throw an exception at this point to store the data to
+ * provide an EBIG response later.
+ */
+ /* *windowSize = regionSize - offset; */
+ return std::make_pair(0, 0);
+ }
+
+ struct aspeed_lpc_ctrl_mapping map = {
+ .window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
+ .window_id = 0,
+ .flags = 0,
+ .addr = address & ~MASK_64K,
+ .offset = 0,
+ .size = __ALIGN_KERNEL_MASK(offset + length, MASK_64K),
+ };
+
+ std::fprintf(stderr,
+ "requesting Aspeed LPC window at %#" PRIx32 " of size %" PRIu32
+ "\n",
+ map.addr, map.size);
+
+ static const char lpcControlPath[] = "/dev/aspeed-lpc-ctrl";
+
+ const auto lpcControlFd = sys->open(lpcControlPath, O_RDWR);
+ if (lpcControlFd == -1)
+ {
+ std::fprintf(stderr,
+ "cannot open Aspeed LPC kernel control dev \"%s\"\n",
+ lpcControlPath);
+ return std::make_pair(0, 0);
+ }
+
+ if (sys->ioctl(lpcControlFd, ASPEED_LPC_CTRL_IOCTL_MAP, &map) == -1)
+ {
+ std::fprintf(stderr, "Failed to ioctl Aspeed LPC map with error %s\n",
+ std::strerror(errno));
+ sys->close(lpcControlFd);
+ return std::make_pair(0, 0);
+ }
+
+ sys->close(lpcControlFd);
+ return std::make_pair(offset, length);
}
} // namespace blobs