Showing with 86 additions and 8 deletions.
  1. +6 −0 internal/sys.cpp
  2. +2 −0 internal/sys.hpp
  3. +60 −3 lpc_aspeed.cpp
  4. +11 −3 lpc_aspeed.hpp
  5. +6 −2 main.cpp
  6. +1 −0 test/internal_sys_mock.hpp
@@ -17,6 +17,7 @@
#include "sys.hpp"

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>

@@ -53,6 +54,11 @@ int SysImpl::getpagesize() const
return ::getpagesize();
}

int SysImpl::ioctl(int fd, unsigned long request, void* param) const
{
return ::ioctl(fd, request, param);
}

SysImpl sys_impl;

} // namespace internal
@@ -34,6 +34,7 @@ class Sys
off_t offset) const = 0;
virtual int munmap(void* addr, size_t length) const = 0;
virtual int getpagesize() const = 0;
virtual int ioctl(int fd, unsigned long request, void* param) const = 0;
};

/**
@@ -50,6 +51,7 @@ class SysImpl : public Sys
off_t offset) const override;
int munmap(void* addr, size_t length) const override;
int getpagesize() const override;
int ioctl(int fd, unsigned long request, void* param) const override;
};

/** @brief Default instantiation of sys */
@@ -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
@@ -1,5 +1,6 @@
#pragma once

#include "internal/sys.hpp"
#include "lpc_interface.hpp"

#include <memory>
@@ -10,13 +11,20 @@ namespace blobs
class LpcMapperAspeed : public LpcMapperInterface
{
public:
static std::unique_ptr<LpcMapperInterface> createAspeedMapper();
static std::unique_ptr<LpcMapperInterface>
createAspeedMapper(size_t regionSize);

/* TODO: Needs reserved memory region's physical address and size. */
LpcMapperAspeed() = default;
LpcMapperAspeed(size_t regionSize, const flash::internal::Sys* sys =
&flash::internal::sys_impl) :
regionSize(regionSize),
sys(sys){};

std::pair<std::uint32_t, std::uint32_t>
mapWindow(std::uint32_t address, std::uint32_t length) override;

private:
size_t regionSize;
const flash::internal::Sys* sys;
};

} // namespace blobs
@@ -36,10 +36,14 @@ FileHandler hashHandler(HASH_FILENAME);
FileHandler staticLayoutHandler(STATIC_HANDLER_STAGED_NAME);
FileHandler ubitarballHandler(TARBALL_STAGED_NAME);

/* The maximum external buffer size we expect is 64KB. */
static constexpr size_t memoryRegionSize = 64 * 1024UL;

#ifdef ENABLE_LPC_BRIDGE
#if defined(ASPEED_LPC)
LpcDataHandler lpcDataHandler(MAPPED_ADDRESS,
LpcMapperAspeed::createAspeedMapper());
LpcDataHandler
lpcDataHandler(MAPPED_ADDRESS,
LpcMapperAspeed::createAspeedMapper(memoryRegionSize));
#elif defined(NUVOTON_LPC)
LpcDataHandler lpcDataHandler(MAPPED_ADDRESS,
LpcMapperNuvoton::createNuvotonMapper());
@@ -23,6 +23,7 @@ class InternalSysMock : public Sys
MOCK_CONST_METHOD6(mmap, void*(void*, size_t, int, int, int, off_t));
MOCK_CONST_METHOD2(munmap, int(void*, size));
MOCK_CONST_METHOD0(getpagesize, int());
MOCK_CONST_METHOD3(ioctl, int(int, unsigned long, void*));
};

} // namespace internal