blob: d6346b1bddf39ee235160d1fa93ae2059e7bcf3c [file] [log] [blame]
Andrew Jeffery4fe996c2018-02-27 12:16:48 +10301/* SPDX-License-Identifier: Apache-2.0 */
2/* Copyright (C) 2018 IBM Corp. */
Ratan Guptac0ef9872017-06-06 14:31:37 +05303#pragma once
4
Andrew Jefferyad343102018-02-28 00:35:50 +10305extern "C" {
Evan Lojewskif1e547c2019-03-14 14:34:33 +10306#include "backend.h"
Andrew Jefferyf4bc3352019-03-18 12:09:48 +10307#include "vpnor/backend.h"
Andrew Jefferyad343102018-02-28 00:35:50 +10308};
9
Andrew Jefferyde08ca22019-03-18 13:23:46 +103010#include "vpnor/table.hpp"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070011
Ratan Guptac0ef9872017-06-06 14:31:37 +053012#include <fcntl.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053013#include <unistd.h>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070014
Ratan Guptac0ef9872017-06-06 14:31:37 +053015#include <experimental/filesystem>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070016#include <string>
17
Ratan Guptac0ef9872017-06-06 14:31:37 +053018namespace openpower
19{
Ratan Guptac0ef9872017-06-06 14:31:37 +053020namespace virtual_pnor
21{
22
23namespace fs = std::experimental::filesystem;
24
Ratan Guptac0ef9872017-06-06 14:31:37 +053025class Request
26{
Andrew Jefferyf34db312018-03-09 15:27:03 +103027 public:
Andrew Jefferyad343102018-02-28 00:35:50 +103028 /** @brief Construct a flash access request
29 *
Evan Lojewskif1e547c2019-03-14 14:34:33 +103030 * @param[in] backend - The backend context used to process the request
Andrew Jefferyad343102018-02-28 00:35:50 +103031 * @param[in] offset - The absolute offset into the flash device as
32 * provided by the mbox message associated with the
33 * request
34 *
35 * The class does not take ownership of the ctx pointer. The lifetime of
36 * the ctx pointer must strictly exceed the lifetime of the class
37 * instance.
38 */
Evan Lojewskif1e547c2019-03-14 14:34:33 +103039 Request(struct backend* backend, size_t offset) :
40 backend(backend), partition(((struct vpnor_data*)backend->priv)
41 ->vpnor->table->partition(offset)),
42 base(partition.data.base << backend->block_size_shift),
Andrew Jefferyad343102018-02-28 00:35:50 +103043 offset(offset - base)
44 {
45 }
Andrew Jefferyf34db312018-03-09 15:27:03 +103046 Request(const Request&) = delete;
47 Request& operator=(const Request&) = delete;
48 Request(Request&&) = default;
49 Request& operator=(Request&&) = default;
50 ~Request() = default;
Ratan Guptac0ef9872017-06-06 14:31:37 +053051
Andrew Jefferyad343102018-02-28 00:35:50 +103052 ssize_t read(void* dst, size_t len)
53 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103054 len = clamp(len);
55 constexpr auto flags = O_RDONLY;
56 fs::path path = getPartitionFilePath(flags);
57 return fulfil(path, flags, dst, len);
Andrew Jefferyad343102018-02-28 00:35:50 +103058 }
Ratan Guptac0ef9872017-06-06 14:31:37 +053059
Andrew Jefferyad343102018-02-28 00:35:50 +103060 ssize_t write(void* dst, size_t len)
61 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103062 if (len != clamp(len))
63 {
64 std::stringstream err;
65 err << "Request size 0x" << std::hex << len << " from offset 0x"
66 << std::hex << offset << " exceeds the partition size 0x"
Evan Lojewskif1e547c2019-03-14 14:34:33 +103067 << std::hex
68 << (partition.data.size << backend->block_size_shift);
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103069 throw OutOfBoundsOffset(err.str());
70 }
71 constexpr auto flags = O_RDWR;
72 /* Ensure file is at least the size of the maximum access */
73 fs::path path = getPartitionFilePath(flags);
74 resize(path, len);
75 return fulfil(path, flags, dst, len);
Andrew Jefferyad343102018-02-28 00:35:50 +103076 }
77
78 private:
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103079 /** @brief Clamp the access length to the maximum supported by the ToC */
80 size_t clamp(size_t len);
81
82 /** @brief Ensure the backing file is sized appropriately for the access
83 *
84 * We need to ensure the file is big enough to satisfy the request so that
85 * mmap() will succeed for the required size.
86 *
87 * @return The valid access length
88 *
89 * Throws: std::system_error
90 */
91 void resize(const std::experimental::filesystem::path& path, size_t len);
92
Andrew Jefferyad343102018-02-28 00:35:50 +103093 /** @brief Returns the partition file path associated with the offset.
Andrew Jefferyf34db312018-03-09 15:27:03 +103094 *
Andrew Jefferyad343102018-02-28 00:35:50 +103095 * The search strategy for the partition file depends on the value of the
96 * flags parameter.
Andrew Jefferyf34db312018-03-09 15:27:03 +103097 *
Andrew Jefferyad343102018-02-28 00:35:50 +103098 * For the O_RDONLY case:
Andrew Jefferyf34db312018-03-09 15:27:03 +103099 *
100 * 1. Depending on the partition type,tries to open the file
101 * from the associated partition(RW/PRSV/RO).
102 * 1a. if file not found in the corresponding
103 * partition(RW/PRSV/RO) then tries to read the file from
104 * the read only partition.
105 * 1b. if the file not found in the read only partition then
106 * throw exception.
107 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030108 * For the O_RDWR case:
Andrew Jefferyf34db312018-03-09 15:27:03 +1030109 *
110 * 1. Depending on the partition type tries to open the file
111 * from the associated partition.
112 * 1a. if file not found in the corresponding partition(RW/PRSV)
113 * then copy the file from the read only partition to the (RW/PRSV)
114 * partition depending on the partition type.
115 * 1b. if the file not found in the read only partition then throw
Andrew Jefferyad343102018-02-28 00:35:50 +1030116 * exception.
Andrew Jefferyf34db312018-03-09 15:27:03 +1030117 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030118 * @param[in] flags - The flags that will be used to open the file. Must
119 * be one of O_RDONLY or O_RDWR.
120 *
121 * Post-condition: The file described by the returned path exists
122 *
123 * Throws: std::filesystem_error, std::bad_alloc
Andrew Jefferyf34db312018-03-09 15:27:03 +1030124 */
Andrew Jefferyad343102018-02-28 00:35:50 +1030125 std::experimental::filesystem::path getPartitionFilePath(int flags);
126
127 /** @brief Fill dst with the content of the partition relative to offset.
128 *
129 * @param[in] offset - The pnor offset(bytes).
130 * @param[out] dst - The buffer to fill with partition data
131 * @param[in] len - The length of the destination buffer
132 */
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030133 size_t fulfil(const std::experimental::filesystem::path& path, int flags,
134 void* dst, size_t len);
Andrew Jefferyad343102018-02-28 00:35:50 +1030135
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030136 struct backend* backend;
Andrew Jefferyad343102018-02-28 00:35:50 +1030137 const pnor_partition& partition;
138 size_t base;
139 size_t offset;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530140};
141
Andrew Jefferyf34db312018-03-09 15:27:03 +1030142} // namespace virtual_pnor
143} // namespace openpower