diff options
author | Andrew Jeffery <andrew@aj.id.au> | 2018-03-26 11:56:16 +1030 |
---|---|---|
committer | Andrew Jeffery <andrew@aj.id.au> | 2018-04-04 17:27:31 +0930 |
commit | 53c21aaa803e148c9c79cb3f5e0252d911506b10 (patch) | |
tree | 2c8e7482711617bc12a58022dd5839234a17f6a7 /vpnor/pnor_partition.cpp | |
parent | 8b9102389718f639434253be3fa99f8f6d38d9a6 (diff) | |
download | phosphor-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.cpp | 163 |
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 |