blob: 3c4ac4ae91d1395ee003a9cfcfd9bb7c78ba71c2 [file] [log] [blame]
Kuiying Wang3a044402019-02-19 15:00:11 +08001/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17#include <fcntl.h>
18#include <unistd.h>
19
20#include <cereal/access.hpp>
21#include <cereal/archives/json.hpp>
22#include <cereal/cereal.hpp>
23#include <cereal/types/vector.hpp>
24#include <experimental/filesystem>
25#include <fstream>
26#include <iostream>
27#include <phosphor-logging/elog-errors.hpp>
28#include <xyz/openbmc_project/Common/error.hpp>
29#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
30#include <xyz/openbmc_project/State/Host/server.hpp>
31
32#define MaxPostCodeCycles 100
33
34const static constexpr char *PostCodePath =
35 "/xyz/openbmc_project/state/boot/raw";
36const static constexpr char *PropertiesIntf = "org.freedesktop.DBus.Properties";
37const static constexpr char *PostCodeListPath =
38 "/var/lib/phosphor-post-code-manager/";
39const static constexpr char *CurrentBootCycleIndexName =
40 "CurrentBootCycleIndex";
41const static constexpr char *HostStatePath = "/xyz/openbmc_project/state/host0";
42
43struct EventDeleter
44{
45 void operator()(sd_event *event) const
46 {
47 event = sd_event_unref(event);
48 }
49};
50using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
51namespace fs = std::experimental::filesystem;
52namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
53
54using post_code =
55 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
56
57struct PostCode : sdbusplus::server::object_t<post_code>
58{
59 PostCode(sdbusplus::bus::bus &bus, const char *path, EventPtr &event) :
60 sdbusplus::server::object_t<post_code>(bus, path), bus(bus),
61 propertiesChangedSignalRaw(
62 bus,
63 sdbusplus::bus::match::rules::type::signal() +
64 sdbusplus::bus::match::rules::member("PropertiesChanged") +
65 sdbusplus::bus::match::rules::path(PostCodePath) +
66 sdbusplus::bus::match::rules::interface(PropertiesIntf),
67 [this](sdbusplus::message::message &msg) {
68 std::string objectName;
69 std::map<std::string, sdbusplus::message::variant<uint64_t>>
70 msgData;
71 msg.read(objectName, msgData);
72 // Check if it was the Value property that changed.
73 auto valPropMap = msgData.find("Value");
74 {
75 if (valPropMap != msgData.end())
76 {
77 this->savePostCodes(
78 sdbusplus::message::variant_ns::get<uint64_t>(
79 valPropMap->second));
80 }
81 }
82 }),
83 propertiesChangedSignalCurrentHostState(
84 bus,
85 sdbusplus::bus::match::rules::type::signal() +
86 sdbusplus::bus::match::rules::member("PropertiesChanged") +
87 sdbusplus::bus::match::rules::path(HostStatePath) +
88 sdbusplus::bus::match::rules::interface(PropertiesIntf),
89 [this](sdbusplus::message::message &msg) {
90 std::string objectName;
91 std::map<std::string, sdbusplus::message::variant<std::string>>
92 msgData;
93 msg.read(objectName, msgData);
94 // Check if it was the Value property that changed.
95 auto valPropMap = msgData.find("CurrentHostState");
96 {
97 if (valPropMap != msgData.end())
98 {
99 StateServer::Host::HostState currentHostState =
100 StateServer::Host::convertHostStateFromString(
101 sdbusplus::message::variant_ns::get<
102 std::string>(valPropMap->second));
103 if (currentHostState ==
104 StateServer::Host::HostState::Off)
105 {
106 if (this->currentBootCycleIndex() >=
107 this->maxBootCycleNum())
108 {
109 this->currentBootCycleIndex(1);
110 }
111 else
112 {
113 this->currentBootCycleIndex(
114 this->currentBootCycleIndex() + 1);
115 }
116 this->postCodes.clear();
117 }
118 }
119 }
120 })
121 {
122 phosphor::logging::log<phosphor::logging::level::INFO>(
123 "PostCode is created");
124 auto dir = fs::path(PostCodeListPath);
125 fs::create_directories(dir);
126 strPostCodeListPath = PostCodeListPath;
127 strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
128 uint16_t index = 0;
129 deserialize(
130 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName),
131 index);
132 currentBootCycleIndex(index);
133 maxBootCycleNum(MaxPostCodeCycles);
134 if (currentBootCycleIndex() >= maxBootCycleNum())
135 {
136 currentBootCycleIndex(1);
137 }
138 else
139 {
140 currentBootCycleIndex(currentBootCycleIndex() + 1);
141 }
142 }
143 ~PostCode()
144 {
145 }
146
147 std::vector<uint64_t> getPostCodes(uint16_t index) override;
148
149 private:
150 sdbusplus::bus::bus &bus;
151 std::vector<uint64_t> postCodes;
152 std::string strPostCodeListPath;
153 std::string strCurrentBootCycleIndexName;
154 void savePostCodes(uint64_t code);
155 sdbusplus::bus::match_t propertiesChangedSignalRaw;
156 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
157 fs::path serialize(const std::string &path);
158 bool deserialize(const fs::path &path, uint16_t &index);
159 bool deserializePostCodes(const fs::path &path,
160 std::vector<uint64_t> &codes);
161};