xref: /openbmc/phosphor-mboxd/vpnor/pnor_partition.hpp (revision 53c21aaa803e148c9c79cb3f5e0252d911506b10)
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