blob: 462e8cd4137cfd2bc9b06ff5c197d1b3df9502be [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
Manojkiran Eda84855ab2021-12-05 11:09:02 +053017#include <config.h>
Kuiying Wang3a044402019-02-19 15:00:11 +080018#include <fcntl.h>
19#include <unistd.h>
20
21#include <cereal/access.hpp>
22#include <cereal/archives/json.hpp>
23#include <cereal/cereal.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080024#include <cereal/types/map.hpp>
Manojkiran Eda84a4c192021-02-25 15:23:42 +053025#include <cereal/types/tuple.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080026#include <cereal/types/vector.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080027#include <chrono>
Manojkiran Eda410ba292021-12-05 10:55:56 +053028#include <filesystem>
Kuiying Wang3a044402019-02-19 15:00:11 +080029#include <fstream>
30#include <iostream>
31#include <phosphor-logging/elog-errors.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080032#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080033#include <xyz/openbmc_project/Common/error.hpp>
34#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
35#include <xyz/openbmc_project/State/Host/server.hpp>
36
ZhikuiRen993d4dd2020-01-29 14:25:44 -080037const static constexpr char *CurrentBootCycleCountName =
38 "CurrentBootCycleCount";
Kuiying Wang3a044402019-02-19 15:00:11 +080039const static constexpr char *CurrentBootCycleIndexName =
40 "CurrentBootCycleIndex";
Kumar Thangavelfd45f782020-09-01 22:59:00 +053041
42// Singleton holder to store host/node and other path information
43class PostCodeDataHolder
44{
Kumar Thangavelfd45f782020-09-01 22:59:00 +053045
46 PostCodeDataHolder()
47 {
48 }
49
50 public:
Manojkiran Edabd706d72021-12-21 05:09:47 +053051 static PostCodeDataHolder &getInstance()
Kumar Thangavelfd45f782020-09-01 22:59:00 +053052 {
Manojkiran Edabd706d72021-12-21 05:09:47 +053053 static PostCodeDataHolder instance;
Kumar Thangavelfd45f782020-09-01 22:59:00 +053054 return instance;
55 }
56
57 int node;
58
59 const static constexpr char *PostCodePath =
60 "/xyz/openbmc_project/state/boot/raw";
61 const static constexpr char *PropertiesIntf =
62 "org.freedesktop.DBus.Properties";
63 const static constexpr char *PostCodeListPathPrefix =
64 "/var/lib/phosphor-post-code-manager/host";
65 const static constexpr char *HostStatePathPrefix =
66 "/xyz/openbmc_project/state/host";
67};
Kuiying Wang3a044402019-02-19 15:00:11 +080068
69struct EventDeleter
70{
71 void operator()(sd_event *event) const
72 {
Manojkiran Edade8d3a52021-12-05 12:51:07 +053073 sd_event_unref(event);
Kuiying Wang3a044402019-02-19 15:00:11 +080074 }
75};
76using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
Manojkiran Eda84a4c192021-02-25 15:23:42 +053077using primarycode_t = uint64_t;
78using secondarycode_t = std::vector<uint8_t>;
79using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
Manojkiran Eda410ba292021-12-05 10:55:56 +053080namespace fs = std::filesystem;
Kuiying Wang3a044402019-02-19 15:00:11 +080081namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
82
83using post_code =
84 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
ZhikuiRen993d4dd2020-01-29 14:25:44 -080085using delete_all =
86 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
Kuiying Wang3a044402019-02-19 15:00:11 +080087
ZhikuiRen993d4dd2020-01-29 14:25:44 -080088struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
Kuiying Wang3a044402019-02-19 15:00:11 +080089{
Manojkiran Edabd706d72021-12-21 05:09:47 +053090 PostCodeDataHolder postcodeDataHolderObj =
91 PostCodeDataHolder::getInstance();
Kumar Thangavelfd45f782020-09-01 22:59:00 +053092
Patrick Williamse9feb952022-07-22 19:26:54 -050093 PostCode(sdbusplus::bus_t &bus, const char *path, EventPtr & /*event*/) :
ZhikuiRen993d4dd2020-01-29 14:25:44 -080094 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
Kuiying Wang3a044402019-02-19 15:00:11 +080095 propertiesChangedSignalRaw(
96 bus,
97 sdbusplus::bus::match::rules::type::signal() +
98 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +053099 sdbusplus::bus::match::rules::path(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530100 postcodeDataHolderObj.PostCodePath +
101 std::to_string(postcodeDataHolderObj.node)) +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530102 sdbusplus::bus::match::rules::interface(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530103 postcodeDataHolderObj.PropertiesIntf),
Patrick Williamse9feb952022-07-22 19:26:54 -0500104 [this](sdbusplus::message_t &msg) {
Kuiying Wang3a044402019-02-19 15:00:11 +0800105 std::string objectName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530106 std::map<std::string, std::variant<postcode_t>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800107 msg.read(objectName, msgData);
108 // Check if it was the Value property that changed.
109 auto valPropMap = msgData.find("Value");
110 {
111 if (valPropMap != msgData.end())
112 {
113 this->savePostCodes(
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530114 std::get<postcode_t>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800115 }
116 }
117 }),
118 propertiesChangedSignalCurrentHostState(
119 bus,
120 sdbusplus::bus::match::rules::type::signal() +
121 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530122 sdbusplus::bus::match::rules::path(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530123 postcodeDataHolderObj.HostStatePathPrefix +
124 std::to_string(postcodeDataHolderObj.node)) +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530125 sdbusplus::bus::match::rules::interface(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530126 postcodeDataHolderObj.PropertiesIntf),
Patrick Williamse9feb952022-07-22 19:26:54 -0500127 [this](sdbusplus::message_t &msg) {
Kuiying Wang3a044402019-02-19 15:00:11 +0800128 std::string objectName;
Patrick Williams9d91a392020-05-13 17:59:26 -0500129 std::map<std::string, std::variant<std::string>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800130 msg.read(objectName, msgData);
131 // Check if it was the Value property that changed.
132 auto valPropMap = msgData.find("CurrentHostState");
133 {
134 if (valPropMap != msgData.end())
135 {
136 StateServer::Host::HostState currentHostState =
137 StateServer::Host::convertHostStateFromString(
Patrick Williams23e3bf02020-05-13 11:37:14 -0500138 std::get<std::string>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800139 if (currentHostState ==
140 StateServer::Host::HostState::Off)
141 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800142 if (this->postCodes.empty())
Kuiying Wang3a044402019-02-19 15:00:11 +0800143 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800144 std::cerr << "HostState changed to OFF. Empty "
145 "postcode log, keep boot cycle at "
146 << this->currentBootCycleIndex
147 << std::endl;
Kuiying Wang3a044402019-02-19 15:00:11 +0800148 }
149 else
150 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800151 this->postCodes.clear();
Kuiying Wang3a044402019-02-19 15:00:11 +0800152 }
Kuiying Wang3a044402019-02-19 15:00:11 +0800153 }
154 }
155 }
156 })
157 {
158 phosphor::logging::log<phosphor::logging::level::INFO>(
159 "PostCode is created");
Manojkiran Edabd706d72021-12-21 05:09:47 +0530160 auto dir = fs::path(postcodeDataHolderObj.PostCodeListPathPrefix +
161 std::to_string(postcodeDataHolderObj.node));
Kuiying Wang3a044402019-02-19 15:00:11 +0800162 fs::create_directories(dir);
Manojkiran Edabd706d72021-12-21 05:09:47 +0530163 strPostCodeListPath = postcodeDataHolderObj.PostCodeListPathPrefix +
164 std::to_string(postcodeDataHolderObj.node) + "/";
Kuiying Wang3a044402019-02-19 15:00:11 +0800165 strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
166 uint16_t index = 0;
167 deserialize(
168 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName),
169 index);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800170 currentBootCycleIndex = index;
171 strCurrentBootCycleCountName = CurrentBootCycleCountName;
172 uint16_t count = 0;
173 deserialize(
174 fs::path(strPostCodeListPath + strCurrentBootCycleCountName),
175 count);
176 currentBootCycleCount(count);
Manojkiran Edaaed7b3d2021-06-19 09:39:30 +0530177 maxBootCycleNum(MAX_BOOT_CYCLE_COUNT);
Kuiying Wang3a044402019-02-19 15:00:11 +0800178 }
179 ~PostCode()
180 {
181 }
182
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530183 std::vector<postcode_t> getPostCodes(uint16_t index) override;
184 std::map<uint64_t, postcode_t>
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800185 getPostCodesWithTimeStamp(uint16_t index) override;
186 void deleteAll() override;
Kuiying Wang3a044402019-02-19 15:00:11 +0800187
188 private:
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800189 void incrBootCycle();
190 uint16_t getBootNum(const uint16_t index) const;
191
Patrick Williamse9feb952022-07-22 19:26:54 -0500192 sdbusplus::bus_t &bus;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800193 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
194 uint64_t firstPostCodeUsSinceEpoch;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530195 std::map<uint64_t, postcode_t> postCodes;
Kuiying Wang3a044402019-02-19 15:00:11 +0800196 std::string strPostCodeListPath;
197 std::string strCurrentBootCycleIndexName;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800198 uint16_t currentBootCycleIndex;
199 std::string strCurrentBootCycleCountName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530200 void savePostCodes(postcode_t code);
Kuiying Wang3a044402019-02-19 15:00:11 +0800201 sdbusplus::bus::match_t propertiesChangedSignalRaw;
202 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
203 fs::path serialize(const std::string &path);
204 bool deserialize(const fs::path &path, uint16_t &index);
205 bool deserializePostCodes(const fs::path &path,
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530206 std::map<uint64_t, postcode_t> &codes);
Kuiying Wang3a044402019-02-19 15:00:11 +0800207};