blob: eb63a3922c58bf94d898e9e79933dfbcce569c29 [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" {
6#include "mbox.h"
7};
8
Ratan Guptac0ef9872017-06-06 14:31:37 +05309#include "mboxd_pnor_partition_table.h"
Andrew Jefferyad343102018-02-28 00:35:50 +103010#include "pnor_partition_table.hpp"
Ratan Guptac0ef9872017-06-06 14:31:37 +053011#include <fcntl.h>
12#include <string>
13#include <unistd.h>
14#include <experimental/filesystem>
15
16namespace openpower
17{
Ratan Guptac0ef9872017-06-06 14:31:37 +053018namespace virtual_pnor
19{
20
21namespace fs = std::experimental::filesystem;
22
Ratan Guptac0ef9872017-06-06 14:31:37 +053023class Request
24{
Andrew Jefferyf34db312018-03-09 15:27:03 +103025 public:
Andrew Jefferyad343102018-02-28 00:35:50 +103026 /** @brief Construct a flash access request
27 *
28 * @param[in] ctx - The mbox context used to process the request
29 * @param[in] offset - The absolute offset into the flash device as
30 * provided by the mbox message associated with the
31 * request
32 *
33 * The class does not take ownership of the ctx pointer. The lifetime of
34 * the ctx pointer must strictly exceed the lifetime of the class
35 * instance.
36 */
37 Request(struct mbox_context* ctx, size_t offset) :
38 ctx(ctx), partition(ctx->vpnor->table->partition(offset)),
39 base(partition.data.base << ctx->block_size_shift),
40 offset(offset - base)
41 {
42 }
Andrew Jefferyf34db312018-03-09 15:27:03 +103043 Request(const Request&) = delete;
44 Request& operator=(const Request&) = delete;
45 Request(Request&&) = default;
46 Request& operator=(Request&&) = default;
47 ~Request() = default;
Ratan Guptac0ef9872017-06-06 14:31:37 +053048
Andrew Jefferyad343102018-02-28 00:35:50 +103049 ssize_t read(void* dst, size_t len)
50 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103051 len = clamp(len);
52 constexpr auto flags = O_RDONLY;
53 fs::path path = getPartitionFilePath(flags);
54 return fulfil(path, flags, dst, len);
Andrew Jefferyad343102018-02-28 00:35:50 +103055 }
Ratan Guptac0ef9872017-06-06 14:31:37 +053056
Andrew Jefferyad343102018-02-28 00:35:50 +103057 ssize_t write(void* dst, size_t len)
58 {
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103059 if (len != clamp(len))
60 {
61 std::stringstream err;
62 err << "Request size 0x" << std::hex << len << " from offset 0x"
63 << std::hex << offset << " exceeds the partition size 0x"
64 << std::hex << (partition.data.size << ctx->block_size_shift);
65 throw OutOfBoundsOffset(err.str());
66 }
67 constexpr auto flags = O_RDWR;
68 /* Ensure file is at least the size of the maximum access */
69 fs::path path = getPartitionFilePath(flags);
70 resize(path, len);
71 return fulfil(path, flags, dst, len);
Andrew Jefferyad343102018-02-28 00:35:50 +103072 }
73
74 private:
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103075 /** @brief Clamp the access length to the maximum supported by the ToC */
76 size_t clamp(size_t len);
77
78 /** @brief Ensure the backing file is sized appropriately for the access
79 *
80 * We need to ensure the file is big enough to satisfy the request so that
81 * mmap() will succeed for the required size.
82 *
83 * @return The valid access length
84 *
85 * Throws: std::system_error
86 */
87 void resize(const std::experimental::filesystem::path& path, size_t len);
88
Andrew Jefferyad343102018-02-28 00:35:50 +103089 /** @brief Returns the partition file path associated with the offset.
Andrew Jefferyf34db312018-03-09 15:27:03 +103090 *
Andrew Jefferyad343102018-02-28 00:35:50 +103091 * The search strategy for the partition file depends on the value of the
92 * flags parameter.
Andrew Jefferyf34db312018-03-09 15:27:03 +103093 *
Andrew Jefferyad343102018-02-28 00:35:50 +103094 * For the O_RDONLY case:
Andrew Jefferyf34db312018-03-09 15:27:03 +103095 *
96 * 1. Depending on the partition type,tries to open the file
97 * from the associated partition(RW/PRSV/RO).
98 * 1a. if file not found in the corresponding
99 * partition(RW/PRSV/RO) then tries to read the file from
100 * the read only partition.
101 * 1b. if the file not found in the read only partition then
102 * throw exception.
103 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030104 * For the O_RDWR case:
Andrew Jefferyf34db312018-03-09 15:27:03 +1030105 *
106 * 1. Depending on the partition type tries to open the file
107 * from the associated partition.
108 * 1a. if file not found in the corresponding partition(RW/PRSV)
109 * then copy the file from the read only partition to the (RW/PRSV)
110 * partition depending on the partition type.
111 * 1b. if the file not found in the read only partition then throw
Andrew Jefferyad343102018-02-28 00:35:50 +1030112 * exception.
Andrew Jefferyf34db312018-03-09 15:27:03 +1030113 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030114 * @param[in] flags - The flags that will be used to open the file. Must
115 * be one of O_RDONLY or O_RDWR.
116 *
117 * Post-condition: The file described by the returned path exists
118 *
119 * Throws: std::filesystem_error, std::bad_alloc
Andrew Jefferyf34db312018-03-09 15:27:03 +1030120 */
Andrew Jefferyad343102018-02-28 00:35:50 +1030121 std::experimental::filesystem::path getPartitionFilePath(int flags);
122
123 /** @brief Fill dst with the content of the partition relative to offset.
124 *
125 * @param[in] offset - The pnor offset(bytes).
126 * @param[out] dst - The buffer to fill with partition data
127 * @param[in] len - The length of the destination buffer
128 */
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030129 size_t fulfil(const std::experimental::filesystem::path& path, int flags,
130 void* dst, size_t len);
Andrew Jefferyad343102018-02-28 00:35:50 +1030131
132 struct mbox_context* ctx;
133 const pnor_partition& partition;
134 size_t base;
135 size_t offset;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530136};
137
Andrew Jefferyf34db312018-03-09 15:27:03 +1030138} // namespace virtual_pnor
139} // namespace openpower