blob: 95d430985daab16a12a9652af581b48a1ba5eb1b [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" {
Andrew Jeffery26558db2018-08-10 00:22:38 +09306#include "mboxd.h"
Andrew Jefferyad343102018-02-28 00:35:50 +10307};
8
Andrew Jefferyad343102018-02-28 00:35:50 +10309#include "pnor_partition_table.hpp"
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070010
Ratan Guptac0ef9872017-06-06 14:31:37 +053011#include <fcntl.h>
Ratan Guptac0ef9872017-06-06 14:31:37 +053012#include <unistd.h>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070013
Ratan Guptac0ef9872017-06-06 14:31:37 +053014#include <experimental/filesystem>
William A. Kennington IIId5f1d402018-10-11 13:55:04 -070015#include <string>
16
17#include "mboxd_pnor_partition_table.h"
Ratan Guptac0ef9872017-06-06 14:31:37 +053018
19namespace openpower
20{
Ratan Guptac0ef9872017-06-06 14:31:37 +053021namespace virtual_pnor
22{
23
24namespace fs = std::experimental::filesystem;
25
Ratan Guptac0ef9872017-06-06 14:31:37 +053026class Request
27{
Andrew Jefferyf34db312018-03-09 15:27:03 +103028 public:
Andrew Jefferyad343102018-02-28 00:35:50 +103029 /** @brief Construct a flash access request
30 *
31 * @param[in] ctx - The mbox context used to process the request
32 * @param[in] offset - The absolute offset into the flash device as
33 * provided by the mbox message associated with the
34 * request
35 *
36 * The class does not take ownership of the ctx pointer. The lifetime of
37 * the ctx pointer must strictly exceed the lifetime of the class
38 * instance.
39 */
40 Request(struct mbox_context* ctx, size_t offset) :
41 ctx(ctx), partition(ctx->vpnor->table->partition(offset)),
42 base(partition.data.base << ctx->block_size_shift),
43 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"
67 << std::hex << (partition.data.size << ctx->block_size_shift);
68 throw OutOfBoundsOffset(err.str());
69 }
70 constexpr auto flags = O_RDWR;
71 /* Ensure file is at least the size of the maximum access */
72 fs::path path = getPartitionFilePath(flags);
73 resize(path, len);
74 return fulfil(path, flags, dst, len);
Andrew Jefferyad343102018-02-28 00:35:50 +103075 }
76
77 private:
Andrew Jeffery1a3f8432018-03-02 10:18:02 +103078 /** @brief Clamp the access length to the maximum supported by the ToC */
79 size_t clamp(size_t len);
80
81 /** @brief Ensure the backing file is sized appropriately for the access
82 *
83 * We need to ensure the file is big enough to satisfy the request so that
84 * mmap() will succeed for the required size.
85 *
86 * @return The valid access length
87 *
88 * Throws: std::system_error
89 */
90 void resize(const std::experimental::filesystem::path& path, size_t len);
91
Andrew Jefferyad343102018-02-28 00:35:50 +103092 /** @brief Returns the partition file path associated with the offset.
Andrew Jefferyf34db312018-03-09 15:27:03 +103093 *
Andrew Jefferyad343102018-02-28 00:35:50 +103094 * The search strategy for the partition file depends on the value of the
95 * flags parameter.
Andrew Jefferyf34db312018-03-09 15:27:03 +103096 *
Andrew Jefferyad343102018-02-28 00:35:50 +103097 * For the O_RDONLY case:
Andrew Jefferyf34db312018-03-09 15:27:03 +103098 *
99 * 1. Depending on the partition type,tries to open the file
100 * from the associated partition(RW/PRSV/RO).
101 * 1a. if file not found in the corresponding
102 * partition(RW/PRSV/RO) then tries to read the file from
103 * the read only partition.
104 * 1b. if the file not found in the read only partition then
105 * throw exception.
106 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030107 * For the O_RDWR case:
Andrew Jefferyf34db312018-03-09 15:27:03 +1030108 *
109 * 1. Depending on the partition type tries to open the file
110 * from the associated partition.
111 * 1a. if file not found in the corresponding partition(RW/PRSV)
112 * then copy the file from the read only partition to the (RW/PRSV)
113 * partition depending on the partition type.
114 * 1b. if the file not found in the read only partition then throw
Andrew Jefferyad343102018-02-28 00:35:50 +1030115 * exception.
Andrew Jefferyf34db312018-03-09 15:27:03 +1030116 *
Andrew Jefferyad343102018-02-28 00:35:50 +1030117 * @param[in] flags - The flags that will be used to open the file. Must
118 * be one of O_RDONLY or O_RDWR.
119 *
120 * Post-condition: The file described by the returned path exists
121 *
122 * Throws: std::filesystem_error, std::bad_alloc
Andrew Jefferyf34db312018-03-09 15:27:03 +1030123 */
Andrew Jefferyad343102018-02-28 00:35:50 +1030124 std::experimental::filesystem::path getPartitionFilePath(int flags);
125
126 /** @brief Fill dst with the content of the partition relative to offset.
127 *
128 * @param[in] offset - The pnor offset(bytes).
129 * @param[out] dst - The buffer to fill with partition data
130 * @param[in] len - The length of the destination buffer
131 */
Andrew Jeffery1a3f8432018-03-02 10:18:02 +1030132 size_t fulfil(const std::experimental::filesystem::path& path, int flags,
133 void* dst, size_t len);
Andrew Jefferyad343102018-02-28 00:35:50 +1030134
135 struct mbox_context* ctx;
136 const pnor_partition& partition;
137 size_t base;
138 size_t offset;
Ratan Guptac0ef9872017-06-06 14:31:37 +0530139};
140
Andrew Jefferyf34db312018-03-09 15:27:03 +1030141} // namespace virtual_pnor
142} // namespace openpower