blob: 05ce2843ea1159cf0c3f3a972f83cac177a57e0f [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>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080023#include <cereal/types/map.hpp>
Manojkiran Eda84a4c192021-02-25 15:23:42 +053024#include <cereal/types/tuple.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080025#include <cereal/types/vector.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080026#include <chrono>
Kuiying Wang3a044402019-02-19 15:00:11 +080027#include <experimental/filesystem>
28#include <fstream>
29#include <iostream>
30#include <phosphor-logging/elog-errors.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080031#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080032#include <xyz/openbmc_project/Common/error.hpp>
33#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
34#include <xyz/openbmc_project/State/Host/server.hpp>
35
36#define MaxPostCodeCycles 100
37
ZhikuiRen993d4dd2020-01-29 14:25:44 -080038const static constexpr char *CurrentBootCycleCountName =
39 "CurrentBootCycleCount";
Kuiying Wang3a044402019-02-19 15:00:11 +080040const static constexpr char *CurrentBootCycleIndexName =
41 "CurrentBootCycleIndex";
Kumar Thangavelfd45f782020-09-01 22:59:00 +053042
43// Singleton holder to store host/node and other path information
44class PostCodeDataHolder
45{
46 static PostCodeDataHolder *instance;
47
48 PostCodeDataHolder()
49 {
50 }
51
52 public:
53 static PostCodeDataHolder *getInstance()
54 {
55 if (!instance)
56 instance = new PostCodeDataHolder;
57 return instance;
58 }
59
60 int node;
61
62 const static constexpr char *PostCodePath =
63 "/xyz/openbmc_project/state/boot/raw";
64 const static constexpr char *PropertiesIntf =
65 "org.freedesktop.DBus.Properties";
66 const static constexpr char *PostCodeListPathPrefix =
67 "/var/lib/phosphor-post-code-manager/host";
68 const static constexpr char *HostStatePathPrefix =
69 "/xyz/openbmc_project/state/host";
70};
Kuiying Wang3a044402019-02-19 15:00:11 +080071
72struct EventDeleter
73{
74 void operator()(sd_event *event) const
75 {
76 event = sd_event_unref(event);
77 }
78};
79using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
Manojkiran Eda84a4c192021-02-25 15:23:42 +053080using primarycode_t = uint64_t;
81using secondarycode_t = std::vector<uint8_t>;
82using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
Kuiying Wang3a044402019-02-19 15:00:11 +080083namespace fs = std::experimental::filesystem;
84namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
85
86using post_code =
87 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
ZhikuiRen993d4dd2020-01-29 14:25:44 -080088using delete_all =
89 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
Kuiying Wang3a044402019-02-19 15:00:11 +080090
ZhikuiRen993d4dd2020-01-29 14:25:44 -080091struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
Kuiying Wang3a044402019-02-19 15:00:11 +080092{
Kumar Thangavelfd45f782020-09-01 22:59:00 +053093 PostCodeDataHolder *postcodeDataHolderObj =
94 postcodeDataHolderObj->getInstance();
95
Kuiying Wang3a044402019-02-19 15:00:11 +080096 PostCode(sdbusplus::bus::bus &bus, const char *path, EventPtr &event) :
ZhikuiRen993d4dd2020-01-29 14:25:44 -080097 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
Kuiying Wang3a044402019-02-19 15:00:11 +080098 propertiesChangedSignalRaw(
99 bus,
100 sdbusplus::bus::match::rules::type::signal() +
101 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530102 sdbusplus::bus::match::rules::path(
103 postcodeDataHolderObj->PostCodePath +
104 std::to_string(postcodeDataHolderObj->node)) +
105 sdbusplus::bus::match::rules::interface(
106 postcodeDataHolderObj->PropertiesIntf),
Kuiying Wang3a044402019-02-19 15:00:11 +0800107 [this](sdbusplus::message::message &msg) {
108 std::string objectName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530109 std::map<std::string, std::variant<postcode_t>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800110 msg.read(objectName, msgData);
111 // Check if it was the Value property that changed.
112 auto valPropMap = msgData.find("Value");
113 {
114 if (valPropMap != msgData.end())
115 {
116 this->savePostCodes(
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530117 std::get<postcode_t>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800118 }
119 }
120 }),
121 propertiesChangedSignalCurrentHostState(
122 bus,
123 sdbusplus::bus::match::rules::type::signal() +
124 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530125 sdbusplus::bus::match::rules::path(
126 postcodeDataHolderObj->HostStatePathPrefix +
127 std::to_string(postcodeDataHolderObj->node)) +
128 sdbusplus::bus::match::rules::interface(
129 postcodeDataHolderObj->PropertiesIntf),
Kuiying Wang3a044402019-02-19 15:00:11 +0800130 [this](sdbusplus::message::message &msg) {
131 std::string objectName;
Patrick Williams9d91a392020-05-13 17:59:26 -0500132 std::map<std::string, std::variant<std::string>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800133 msg.read(objectName, msgData);
134 // Check if it was the Value property that changed.
135 auto valPropMap = msgData.find("CurrentHostState");
136 {
137 if (valPropMap != msgData.end())
138 {
139 StateServer::Host::HostState currentHostState =
140 StateServer::Host::convertHostStateFromString(
Patrick Williams23e3bf02020-05-13 11:37:14 -0500141 std::get<std::string>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800142 if (currentHostState ==
143 StateServer::Host::HostState::Off)
144 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800145 if (this->postCodes.empty())
Kuiying Wang3a044402019-02-19 15:00:11 +0800146 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800147 std::cerr << "HostState changed to OFF. Empty "
148 "postcode log, keep boot cycle at "
149 << this->currentBootCycleIndex
150 << std::endl;
Kuiying Wang3a044402019-02-19 15:00:11 +0800151 }
152 else
153 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800154 this->postCodes.clear();
Kuiying Wang3a044402019-02-19 15:00:11 +0800155 }
Kuiying Wang3a044402019-02-19 15:00:11 +0800156 }
157 }
158 }
159 })
160 {
161 phosphor::logging::log<phosphor::logging::level::INFO>(
162 "PostCode is created");
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530163 auto dir = fs::path(postcodeDataHolderObj->PostCodeListPathPrefix +
164 std::to_string(postcodeDataHolderObj->node));
Kuiying Wang3a044402019-02-19 15:00:11 +0800165 fs::create_directories(dir);
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530166 strPostCodeListPath = postcodeDataHolderObj->PostCodeListPathPrefix +
167 std::to_string(postcodeDataHolderObj->node) + "/";
Kuiying Wang3a044402019-02-19 15:00:11 +0800168 strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
169 uint16_t index = 0;
170 deserialize(
171 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName),
172 index);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800173 currentBootCycleIndex = index;
174 strCurrentBootCycleCountName = CurrentBootCycleCountName;
175 uint16_t count = 0;
176 deserialize(
177 fs::path(strPostCodeListPath + strCurrentBootCycleCountName),
178 count);
179 currentBootCycleCount(count);
Kuiying Wang3a044402019-02-19 15:00:11 +0800180 maxBootCycleNum(MaxPostCodeCycles);
Kuiying Wang3a044402019-02-19 15:00:11 +0800181 }
182 ~PostCode()
183 {
184 }
185
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530186 std::vector<postcode_t> getPostCodes(uint16_t index) override;
187 std::map<uint64_t, postcode_t>
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800188 getPostCodesWithTimeStamp(uint16_t index) override;
189 void deleteAll() override;
Kuiying Wang3a044402019-02-19 15:00:11 +0800190
191 private:
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800192 void incrBootCycle();
193 uint16_t getBootNum(const uint16_t index) const;
194
Kuiying Wang3a044402019-02-19 15:00:11 +0800195 sdbusplus::bus::bus &bus;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800196 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
197 uint64_t firstPostCodeUsSinceEpoch;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530198 std::map<uint64_t, postcode_t> postCodes;
Kuiying Wang3a044402019-02-19 15:00:11 +0800199 std::string strPostCodeListPath;
200 std::string strCurrentBootCycleIndexName;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800201 uint16_t currentBootCycleIndex;
202 std::string strCurrentBootCycleCountName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530203 void savePostCodes(postcode_t code);
Kuiying Wang3a044402019-02-19 15:00:11 +0800204 sdbusplus::bus::match_t propertiesChangedSignalRaw;
205 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
206 fs::path serialize(const std::string &path);
207 bool deserialize(const fs::path &path, uint16_t &index);
208 bool deserializePostCodes(const fs::path &path,
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530209 std::map<uint64_t, postcode_t> &codes);
Kuiying Wang3a044402019-02-19 15:00:11 +0800210};