xref: /openbmc/hiomapd/vpnor/test/tmpd.hpp (revision a042978b03c91ca3a716e99f313ef5cda42820ba)
1 /* SPDX-License-Identifier: Apache-2.0 */
2 /* Copyright (C) 2018 IBM Corp. */
3 
4 #include "config.h"
5 
6 extern "C" {
7 #include "backend.h"
8 #include "mboxd.h"
9 }
10 
11 #include "vpnor/pnor_partition_table.hpp"
12 
13 #include <cassert>
14 #include <cstring>
15 #include <experimental/filesystem>
16 #include <fstream>
17 #include <vector>
18 
19 namespace openpower
20 {
21 namespace virtual_pnor
22 {
23 namespace test
24 {
25 
26 namespace fs = std::experimental::filesystem;
27 
28 class VpnorRoot
29 {
30   public:
31     template <std::size_t N>
32     VpnorRoot(struct backend* backend, const std::string (&toc)[N],
33               size_t blockSize) :
34         backend(backend)
35     {
36         char tmplt[] = "/tmp/vpnor_root.XXXXXX";
37         char* tmpdir = mkdtemp(tmplt);
38         root = fs::path{tmpdir};
39 
40         for (const auto& attr : attributes)
41         {
42             fs::create_directory(root / attr);
43         }
44 
45         fs::path tocFilePath = root / "ro" / PARTITION_TOC_FILE;
46 
47         for (const std::string& line : toc)
48         {
49             pnor_partition part;
50 
51             openpower::virtual_pnor::parseTocLine(line, blockSize, part);
52 
53             /* Populate the partition in the tree */
54             std::vector<char> zeroed(part.data.actual, 0);
55             fs::path partitionFilePath = root / "ro" / part.data.name;
56             std::ofstream(partitionFilePath)
57                 .write(zeroed.data(), zeroed.size());
58 
59             /* Update the ToC if the partition file was created */
60             std::ofstream(tocFilePath, std::ofstream::app) << line << "\n";
61         }
62 
63         vpnor_partition_paths paths{};
64 
65         snprintf(paths.ro_loc, PATH_MAX - 1, "%s/ro", root.c_str());
66         paths.ro_loc[PATH_MAX - 1] = '\0';
67         snprintf(paths.rw_loc, PATH_MAX - 1, "%s/rw", root.c_str());
68         paths.rw_loc[PATH_MAX - 1] = '\0';
69         snprintf(paths.prsv_loc, PATH_MAX - 1, "%s/prsv", root.c_str());
70         paths.prsv_loc[PATH_MAX - 1] = '\0';
71         snprintf(paths.patch_loc, PATH_MAX - 1, "%s/patch", root.c_str());
72         paths.patch_loc[PATH_MAX - 1] = '\0';
73 
74         if (backend_probe_vpnor(backend, &paths))
75         {
76             throw std::system_error(errno, std::system_category());
77         }
78     }
79 
80     VpnorRoot(const VpnorRoot&) = delete;
81     VpnorRoot& operator=(const VpnorRoot&) = delete;
82     VpnorRoot(VpnorRoot&&) = delete;
83     VpnorRoot& operator=(VpnorRoot&&) = delete;
84 
85     ~VpnorRoot()
86     {
87         backend_free(backend);
88         fs::remove_all(root);
89     }
90     fs::path ro()
91     {
92         return fs::path{root} / "ro";
93     }
94     fs::path rw()
95     {
96         return fs::path{root} / "rw";
97     }
98     fs::path prsv()
99     {
100         return fs::path{root} / "prsv";
101     }
102     fs::path patch()
103     {
104         return fs::path{root} / "patch";
105     }
106     size_t write(const std::string& name, const void* data, size_t len);
107     size_t patch(const std::string& name, const void* data, size_t len);
108 
109   private:
110     struct backend* backend;
111     fs::path root;
112     const std::string attributes[4] = {"ro", "rw", "prsv", "patch"};
113 };
114 
115 } // namespace test
116 } // namespace virtual_pnor
117 } // namespace openpower
118