1*53c21aaaSAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 */ 2*53c21aaaSAndrew Jeffery /* Copyright (C) 2018 IBM Corp. */ 3*53c21aaaSAndrew Jeffery #pragma once 4*53c21aaaSAndrew Jeffery 5*53c21aaaSAndrew Jeffery extern "C" { 6*53c21aaaSAndrew Jeffery #include "mbox.h" 7*53c21aaaSAndrew Jeffery }; 8*53c21aaaSAndrew Jeffery 9*53c21aaaSAndrew Jeffery #include "mboxd_pnor_partition_table.h" 10*53c21aaaSAndrew Jeffery #include "pnor_partition_table.hpp" 11*53c21aaaSAndrew Jeffery #include <fcntl.h> 12*53c21aaaSAndrew Jeffery #include <string> 13*53c21aaaSAndrew Jeffery #include <unistd.h> 14*53c21aaaSAndrew Jeffery #include <experimental/filesystem> 15*53c21aaaSAndrew Jeffery 16*53c21aaaSAndrew Jeffery namespace openpower 17*53c21aaaSAndrew Jeffery { 18*53c21aaaSAndrew Jeffery namespace virtual_pnor 19*53c21aaaSAndrew Jeffery { 20*53c21aaaSAndrew Jeffery 21*53c21aaaSAndrew Jeffery namespace fs = std::experimental::filesystem; 22*53c21aaaSAndrew Jeffery 23*53c21aaaSAndrew Jeffery class Request 24*53c21aaaSAndrew Jeffery { 25*53c21aaaSAndrew Jeffery public: 26*53c21aaaSAndrew Jeffery /** @brief Construct a flash access request 27*53c21aaaSAndrew Jeffery * 28*53c21aaaSAndrew Jeffery * @param[in] ctx - The mbox context used to process the request 29*53c21aaaSAndrew Jeffery * @param[in] offset - The absolute offset into the flash device as 30*53c21aaaSAndrew Jeffery * provided by the mbox message associated with the 31*53c21aaaSAndrew Jeffery * request 32*53c21aaaSAndrew Jeffery * 33*53c21aaaSAndrew Jeffery * The class does not take ownership of the ctx pointer. The lifetime of 34*53c21aaaSAndrew Jeffery * the ctx pointer must strictly exceed the lifetime of the class 35*53c21aaaSAndrew Jeffery * instance. 36*53c21aaaSAndrew Jeffery */ Request(struct mbox_context * ctx,size_t offset)37*53c21aaaSAndrew Jeffery Request(struct mbox_context* ctx, size_t offset) : 38*53c21aaaSAndrew Jeffery ctx(ctx), partition(ctx->vpnor->table->partition(offset)), 39*53c21aaaSAndrew Jeffery base(partition.data.base << ctx->block_size_shift), 40*53c21aaaSAndrew Jeffery offset(offset - base) 41*53c21aaaSAndrew Jeffery { 42*53c21aaaSAndrew Jeffery } 43*53c21aaaSAndrew Jeffery Request(const Request&) = delete; 44*53c21aaaSAndrew Jeffery Request& operator=(const Request&) = delete; 45*53c21aaaSAndrew Jeffery Request(Request&&) = default; 46*53c21aaaSAndrew Jeffery Request& operator=(Request&&) = default; 47*53c21aaaSAndrew Jeffery ~Request() = default; 48*53c21aaaSAndrew Jeffery read(void * dst,size_t len)49*53c21aaaSAndrew Jeffery ssize_t read(void* dst, size_t len) 50*53c21aaaSAndrew Jeffery { 51*53c21aaaSAndrew Jeffery len = clamp(len); 52*53c21aaaSAndrew Jeffery constexpr auto flags = O_RDONLY; 53*53c21aaaSAndrew Jeffery fs::path path = getPartitionFilePath(flags); 54*53c21aaaSAndrew Jeffery return fulfil(path, flags, dst, len); 55*53c21aaaSAndrew Jeffery } 56*53c21aaaSAndrew Jeffery write(void * dst,size_t len)57*53c21aaaSAndrew Jeffery ssize_t write(void* dst, size_t len) 58*53c21aaaSAndrew Jeffery { 59*53c21aaaSAndrew Jeffery if (len != clamp(len)) 60*53c21aaaSAndrew Jeffery { 61*53c21aaaSAndrew Jeffery std::stringstream err; 62*53c21aaaSAndrew Jeffery err << "Request size 0x" << std::hex << len << " from offset 0x" 63*53c21aaaSAndrew Jeffery << std::hex << offset << " exceeds the partition size 0x" 64*53c21aaaSAndrew Jeffery << std::hex << (partition.data.size << ctx->block_size_shift); 65*53c21aaaSAndrew Jeffery throw OutOfBoundsOffset(err.str()); 66*53c21aaaSAndrew Jeffery } 67*53c21aaaSAndrew Jeffery constexpr auto flags = O_RDWR; 68*53c21aaaSAndrew Jeffery /* Ensure file is at least the size of the maximum access */ 69*53c21aaaSAndrew Jeffery fs::path path = getPartitionFilePath(flags); 70*53c21aaaSAndrew Jeffery resize(path, len); 71*53c21aaaSAndrew Jeffery return fulfil(path, flags, dst, len); 72*53c21aaaSAndrew Jeffery } 73*53c21aaaSAndrew Jeffery 74*53c21aaaSAndrew Jeffery private: 75*53c21aaaSAndrew Jeffery /** @brief Clamp the access length to the maximum supported by the ToC */ 76*53c21aaaSAndrew Jeffery size_t clamp(size_t len); 77*53c21aaaSAndrew Jeffery 78*53c21aaaSAndrew Jeffery /** @brief Ensure the backing file is sized appropriately for the access 79*53c21aaaSAndrew Jeffery * 80*53c21aaaSAndrew Jeffery * We need to ensure the file is big enough to satisfy the request so that 81*53c21aaaSAndrew Jeffery * mmap() will succeed for the required size. 82*53c21aaaSAndrew Jeffery * 83*53c21aaaSAndrew Jeffery * @return The valid access length 84*53c21aaaSAndrew Jeffery * 85*53c21aaaSAndrew Jeffery * Throws: std::system_error 86*53c21aaaSAndrew Jeffery */ 87*53c21aaaSAndrew Jeffery void resize(const std::experimental::filesystem::path& path, size_t len); 88*53c21aaaSAndrew Jeffery 89*53c21aaaSAndrew Jeffery /** @brief Returns the partition file path associated with the offset. 90*53c21aaaSAndrew Jeffery * 91*53c21aaaSAndrew Jeffery * The search strategy for the partition file depends on the value of the 92*53c21aaaSAndrew Jeffery * flags parameter. 93*53c21aaaSAndrew Jeffery * 94*53c21aaaSAndrew Jeffery * For the O_RDONLY case: 95*53c21aaaSAndrew Jeffery * 96*53c21aaaSAndrew Jeffery * 1. Depending on the partition type,tries to open the file 97*53c21aaaSAndrew Jeffery * from the associated partition(RW/PRSV/RO). 98*53c21aaaSAndrew Jeffery * 1a. if file not found in the corresponding 99*53c21aaaSAndrew Jeffery * partition(RW/PRSV/RO) then tries to read the file from 100*53c21aaaSAndrew Jeffery * the read only partition. 101*53c21aaaSAndrew Jeffery * 1b. if the file not found in the read only partition then 102*53c21aaaSAndrew Jeffery * throw exception. 103*53c21aaaSAndrew Jeffery * 104*53c21aaaSAndrew Jeffery * For the O_RDWR case: 105*53c21aaaSAndrew Jeffery * 106*53c21aaaSAndrew Jeffery * 1. Depending on the partition type tries to open the file 107*53c21aaaSAndrew Jeffery * from the associated partition. 108*53c21aaaSAndrew Jeffery * 1a. if file not found in the corresponding partition(RW/PRSV) 109*53c21aaaSAndrew Jeffery * then copy the file from the read only partition to the (RW/PRSV) 110*53c21aaaSAndrew Jeffery * partition depending on the partition type. 111*53c21aaaSAndrew Jeffery * 1b. if the file not found in the read only partition then throw 112*53c21aaaSAndrew Jeffery * exception. 113*53c21aaaSAndrew Jeffery * 114*53c21aaaSAndrew Jeffery * @param[in] flags - The flags that will be used to open the file. Must 115*53c21aaaSAndrew Jeffery * be one of O_RDONLY or O_RDWR. 116*53c21aaaSAndrew Jeffery * 117*53c21aaaSAndrew Jeffery * Post-condition: The file described by the returned path exists 118*53c21aaaSAndrew Jeffery * 119*53c21aaaSAndrew Jeffery * Throws: std::filesystem_error, std::bad_alloc 120*53c21aaaSAndrew Jeffery */ 121*53c21aaaSAndrew Jeffery std::experimental::filesystem::path getPartitionFilePath(int flags); 122*53c21aaaSAndrew Jeffery 123*53c21aaaSAndrew Jeffery /** @brief Fill dst with the content of the partition relative to offset. 124*53c21aaaSAndrew Jeffery * 125*53c21aaaSAndrew Jeffery * @param[in] offset - The pnor offset(bytes). 126*53c21aaaSAndrew Jeffery * @param[out] dst - The buffer to fill with partition data 127*53c21aaaSAndrew Jeffery * @param[in] len - The length of the destination buffer 128*53c21aaaSAndrew Jeffery */ 129*53c21aaaSAndrew Jeffery size_t fulfil(const std::experimental::filesystem::path& path, int flags, 130*53c21aaaSAndrew Jeffery void* dst, size_t len); 131*53c21aaaSAndrew Jeffery 132*53c21aaaSAndrew Jeffery struct mbox_context* ctx; 133*53c21aaaSAndrew Jeffery const pnor_partition& partition; 134*53c21aaaSAndrew Jeffery size_t base; 135*53c21aaaSAndrew Jeffery size_t offset; 136*53c21aaaSAndrew Jeffery }; 137*53c21aaaSAndrew Jeffery 138*53c21aaaSAndrew Jeffery } // namespace virtual_pnor 139*53c21aaaSAndrew Jeffery } // namespace openpower 140