summaryrefslogtreecommitdiffstats
path: root/vpnor/pnor_partition.cpp
diff options
context:
space:
mode:
authorAndrew Jeffery <andrew@aj.id.au>2018-03-26 11:56:16 +1030
committerAndrew Jeffery <andrew@aj.id.au>2018-04-04 17:27:31 +0930
commit53c21aaa803e148c9c79cb3f5e0252d911506b10 (patch)
tree2c8e7482711617bc12a58022dd5839234a17f6a7 /vpnor/pnor_partition.cpp
parent8b9102389718f639434253be3fa99f8f6d38d9a6 (diff)
downloadphosphor-mboxd-53c21aaa803e148c9c79cb3f5e0252d911506b10.tar.gz
phosphor-mboxd-53c21aaa803e148c9c79cb3f5e0252d911506b10.zip
vpnor: Isolate relevant code in vpnor directory
This is prepatory work for introducing more vpnor-specific behaviours to window handling. We will be introducing more objects to link, in order to hook some of the window command handlers. This change takes the opportunity to revert back to the upstream names for some of the original C files. Change-Id: I6b67ae466a2695054035e65ba752881be9c32d1a Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Diffstat (limited to 'vpnor/pnor_partition.cpp')
-rw-r--r--vpnor/pnor_partition.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/vpnor/pnor_partition.cpp b/vpnor/pnor_partition.cpp
new file mode 100644
index 0000000..84aeb3f
--- /dev/null
+++ b/vpnor/pnor_partition.cpp
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+#include "pnor_partition.hpp"
+#include "pnor_partition_table.hpp"
+#include "config.h"
+#include "mboxd_flash.h"
+#include "mboxd_pnor_partition_table.h"
+#include "xyz/openbmc_project/Common/error.hpp"
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "common.h"
+
+#include <string>
+#include <exception>
+#include <stdexcept>
+#include <iostream>
+
+namespace openpower
+{
+namespace virtual_pnor
+{
+
+namespace fs = std::experimental::filesystem;
+
+fs::path Request::getPartitionFilePath(int flags)
+{
+ // Check if partition exists in patch location
+ auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
+ if (fs::is_regular_file(dst))
+ {
+ return dst;
+ }
+
+ switch (partition.data.user.data[1] &
+ (PARTITION_PRESERVED | PARTITION_READONLY))
+ {
+ case PARTITION_PRESERVED:
+ dst = ctx->paths.prsv_loc;
+ break;
+
+ case PARTITION_READONLY:
+ dst = ctx->paths.ro_loc;
+ break;
+
+ default:
+ dst = ctx->paths.rw_loc;
+ }
+ dst /= partition.data.name;
+
+ if (fs::exists(dst))
+ {
+ return dst;
+ }
+
+ if (flags == O_RDONLY)
+ {
+ dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
+ assert(fs::exists(dst));
+ return dst;
+ }
+
+ assert(flags == O_RDWR);
+ auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
+ assert(fs::exists(src));
+
+ MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
+ partition.data.name, dst.c_str(), src.c_str());
+
+ dst = ctx->paths.rw_loc;
+ if (partition.data.user.data[1] & PARTITION_PRESERVED)
+ {
+ dst = ctx->paths.prsv_loc;
+ }
+
+ dst /= partition.data.name;
+ fs::copy_file(src, dst);
+
+ return dst;
+}
+
+size_t Request::clamp(size_t len)
+{
+ size_t maxAccess = offset + len;
+ size_t partSize = partition.data.size << ctx->block_size_shift;
+ return std::min(maxAccess, partSize) - offset;
+}
+
+void Request::resize(const fs::path &path, size_t len)
+{
+ size_t maxAccess = offset + len;
+ size_t fileSize = fs::file_size(path);
+ if (maxAccess < fileSize)
+ {
+ return;
+ }
+ MSG_DBG("Resizing %s to %zu bytes\n", path.c_str(), maxAccess);
+ int rc = truncate(path.c_str(), maxAccess);
+ if (rc == -1)
+ {
+ MSG_ERR("Failed to resize %s: %d\n", path.c_str(), errno);
+ throw std::system_error(errno, std::system_category());
+ }
+}
+
+size_t Request::fulfil(const fs::path &path, int flags, void *buf, size_t len)
+{
+ if (!(flags == O_RDONLY || flags == O_RDWR))
+ {
+ std::stringstream err;
+ err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
+ << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
+ throw std::invalid_argument(err.str());
+ }
+
+ int fd = ::open(path.c_str(), flags);
+ if (fd == -1)
+ {
+ MSG_ERR("Failed to open backing file at '%s': %d\n",
+ path.c_str(), errno);
+ throw std::system_error(errno, std::system_category());
+ }
+
+ size_t fileSize = fs::file_size(path);
+ int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
+ auto map = mmap(NULL, fileSize, mprot, MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED)
+ {
+ close(fd);
+ MSG_ERR("Failed to map backing file '%s' for %zd bytes: %d\n",
+ path.c_str(), fileSize, errno);
+ throw std::system_error(errno, std::system_category());
+ }
+
+ // copy to the reserved memory area
+ if (flags == O_RDONLY)
+ {
+ memset(buf, 0xff, len);
+ memcpy(buf, (char *)map + offset, std::min(len, fileSize));
+ }
+ else
+ {
+ memcpy((char *)map + offset, buf, len);
+ set_flash_bytemap(ctx, base + offset, len, FLASH_DIRTY);
+ }
+ munmap(map, fileSize);
+ close(fd);
+
+ return len;
+}
+
+} // namespace virtual_pnor
+} // namespace openpower
OpenPOWER on IntegriCloud