summaryrefslogtreecommitdiffstats
path: root/ubi/serialize.cpp
blob: a40925a6a8dd3fff9b48f05483734510e09b5af5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "config.h"

#include "serialize.hpp"

#include <cereal/archives/json.hpp>
#include <experimental/filesystem>
#include <fstream>
#include <sdbusplus/server.hpp>

namespace openpower
{
namespace software
{
namespace updater
{

namespace fs = std::experimental::filesystem;

void storeToFile(const std::string& versionId, uint8_t priority)
{
    auto bus = sdbusplus::bus::new_default();

    if (!fs::is_directory(PERSIST_DIR))
    {
        fs::create_directories(PERSIST_DIR);
    }

    // store one copy in /var/lib/obmc/openpower-pnor-code-mgmt/[versionId]
    auto varPath = PERSIST_DIR + versionId;
    std::ofstream varOutput(varPath.c_str());
    cereal::JSONOutputArchive varArchive(varOutput);
    varArchive(cereal::make_nvp("priority", priority));

    if (fs::is_directory(PNOR_RW_PREFIX + versionId))
    {
        // store another copy in /media/pnor-rw-[versionId]/[versionId]
        auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
        std::ofstream rwOutput(rwPath.c_str());
        cereal::JSONOutputArchive rwArchive(rwOutput);
        rwArchive(cereal::make_nvp("priority", priority));
    }

    // lastly, store the priority as an environment variable pnor-[versionId]
    std::string serviceFile = "obmc-flash-bmc-setenv@pnor\\x2d" + versionId +
                              "\\x3d" + std::to_string(priority) + ".service";
    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append(serviceFile, "replace");
    bus.call_noreply(method);
}

bool restoreFromFile(const std::string& versionId, uint8_t& priority)
{
    auto varPath = PERSIST_DIR + versionId;
    if (fs::exists(varPath))
    {
        std::ifstream varInput(varPath.c_str(), std::ios::in);
        try
        {
            cereal::JSONInputArchive varArchive(varInput);
            varArchive(cereal::make_nvp("priority", priority));
            return true;
        }
        catch (cereal::RapidJSONException& e)
        {
            fs::remove(varPath);
        }
    }

    auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
    if (fs::exists(rwPath))
    {
        std::ifstream rwInput(rwPath.c_str(), std::ios::in);
        try
        {
            cereal::JSONInputArchive rwArchive(rwInput);
            rwArchive(cereal::make_nvp("priority", priority));
            return true;
        }
        catch (cereal::RapidJSONException& e)
        {
            fs::remove(rwPath);
        }
    }

    try
    {
        std::string devicePath = "/dev/mtd/u-boot-env";

        if (fs::exists(devicePath) && !devicePath.empty())
        {
            std::ifstream input(devicePath.c_str());
            std::string envVars;
            std::getline(input, envVars);

            std::string versionVar = "pnor-" + versionId + "=";
            auto varPosition = envVars.find(versionVar);

            if (varPosition != std::string::npos)
            {
                // Grab the environment variable for this versionId. These
                // variables follow the format "pnor-[versionId]=[priority]\0"
                auto var = envVars.substr(varPosition);
                priority = std::stoi(var.substr(versionVar.length()));
                return true;
            }
        }
    }
    catch (const std::exception& e)
    {
    }

    return false;
}

void removeFile(const std::string& versionId)
{
    auto bus = sdbusplus::bus::new_default();

    // Clear the environment variable pnor-[versionId].
    std::string serviceFile =
        "obmc-flash-bmc-setenv@pnor\\x2d" + versionId + ".service";
    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append(serviceFile, "replace");
    bus.call_noreply(method);

    // Delete the file /var/lib/obmc/openpower-pnor-code-mgmt/[versionId].
    // Note that removeFile() is called in the case of a version being deleted,
    // so the file /media/pnor-rw-[versionId]/[versionId] will also be deleted
    // along with its surrounding directory.
    std::string path = PERSIST_DIR + versionId;
    if (fs::exists(path))
    {
        fs::remove(path);
    }
}

} // namespace updater
} // namespace software
} // namespace openpower
OpenPOWER on IntegriCloud