blob: 440e56f15e14869e1c94273678bbf66a395898b4 [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>
Kuiying Wang3a044402019-02-19 15:00:11 +080027#include <phosphor-logging/elog-errors.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080028#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080029#include <xyz/openbmc_project/Common/error.hpp>
30#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
31#include <xyz/openbmc_project/State/Host/server.hpp>
32
Jonathan Domaneddf9602022-11-23 09:29:41 -080033#include <chrono>
34#include <filesystem>
35#include <fstream>
36#include <iostream>
37
38const static constexpr char* CurrentBootCycleCountName =
ZhikuiRen993d4dd2020-01-29 14:25:44 -080039 "CurrentBootCycleCount";
Jonathan Domaneddf9602022-11-23 09:29:41 -080040const static constexpr char* CurrentBootCycleIndexName =
Kuiying Wang3a044402019-02-19 15:00:11 +080041 "CurrentBootCycleIndex";
Kumar Thangavelfd45f782020-09-01 22:59:00 +053042
43// Singleton holder to store host/node and other path information
44class PostCodeDataHolder
45{
Jonathan Domaneddf9602022-11-23 09:29:41 -080046 PostCodeDataHolder() {}
Kumar Thangavelfd45f782020-09-01 22:59:00 +053047
48 public:
Jonathan Domaneddf9602022-11-23 09:29:41 -080049 static PostCodeDataHolder& getInstance()
Kumar Thangavelfd45f782020-09-01 22:59:00 +053050 {
Manojkiran Edabd706d72021-12-21 05:09:47 +053051 static PostCodeDataHolder instance;
Kumar Thangavelfd45f782020-09-01 22:59:00 +053052 return instance;
53 }
54
55 int node;
56
Jonathan Domaneddf9602022-11-23 09:29:41 -080057 const static constexpr char* PostCodePath =
Kumar Thangavelfd45f782020-09-01 22:59:00 +053058 "/xyz/openbmc_project/state/boot/raw";
Jonathan Domaneddf9602022-11-23 09:29:41 -080059 const static constexpr char* PropertiesIntf =
Kumar Thangavelfd45f782020-09-01 22:59:00 +053060 "org.freedesktop.DBus.Properties";
Jonathan Domaneddf9602022-11-23 09:29:41 -080061 const static constexpr char* PostCodeListPathPrefix =
Kumar Thangavelfd45f782020-09-01 22:59:00 +053062 "/var/lib/phosphor-post-code-manager/host";
Jonathan Domaneddf9602022-11-23 09:29:41 -080063 const static constexpr char* HostStatePathPrefix =
Kumar Thangavelfd45f782020-09-01 22:59:00 +053064 "/xyz/openbmc_project/state/host";
65};
Kuiying Wang3a044402019-02-19 15:00:11 +080066
67struct EventDeleter
68{
Jonathan Domaneddf9602022-11-23 09:29:41 -080069 void operator()(sd_event* event) const
Kuiying Wang3a044402019-02-19 15:00:11 +080070 {
Manojkiran Edade8d3a52021-12-05 12:51:07 +053071 sd_event_unref(event);
Kuiying Wang3a044402019-02-19 15:00:11 +080072 }
73};
74using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
Manojkiran Eda84a4c192021-02-25 15:23:42 +053075using primarycode_t = uint64_t;
76using secondarycode_t = std::vector<uint8_t>;
77using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
Manojkiran Eda410ba292021-12-05 10:55:56 +053078namespace fs = std::filesystem;
Kuiying Wang3a044402019-02-19 15:00:11 +080079namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
80
81using post_code =
82 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
ZhikuiRen993d4dd2020-01-29 14:25:44 -080083using delete_all =
84 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
Kuiying Wang3a044402019-02-19 15:00:11 +080085
ZhikuiRen993d4dd2020-01-29 14:25:44 -080086struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
Kuiying Wang3a044402019-02-19 15:00:11 +080087{
Bonnie Lo20189642022-11-10 13:32:42 +080088 PostCodeDataHolder& postcodeDataHolderObj =
Manojkiran Edabd706d72021-12-21 05:09:47 +053089 PostCodeDataHolder::getInstance();
Kumar Thangavelfd45f782020-09-01 22:59:00 +053090
Jonathan Domaneddf9602022-11-23 09:29:41 -080091 PostCode(sdbusplus::bus_t& bus, const char* path, EventPtr& /*event*/) :
ZhikuiRen993d4dd2020-01-29 14:25:44 -080092 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
Kuiying Wang3a044402019-02-19 15:00:11 +080093 propertiesChangedSignalRaw(
94 bus,
95 sdbusplus::bus::match::rules::type::signal() +
96 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +053097 sdbusplus::bus::match::rules::path(
Manojkiran Edabd706d72021-12-21 05:09:47 +053098 postcodeDataHolderObj.PostCodePath +
99 std::to_string(postcodeDataHolderObj.node)) +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530100 sdbusplus::bus::match::rules::interface(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530101 postcodeDataHolderObj.PropertiesIntf),
Jonathan Domaneddf9602022-11-23 09:29:41 -0800102 [this](sdbusplus::message_t& msg) {
Kuiying Wang3a044402019-02-19 15:00:11 +0800103 std::string objectName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530104 std::map<std::string, std::variant<postcode_t>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800105 msg.read(objectName, msgData);
106 // Check if it was the Value property that changed.
107 auto valPropMap = msgData.find("Value");
108 {
109 if (valPropMap != msgData.end())
110 {
111 this->savePostCodes(
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530112 std::get<postcode_t>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800113 }
114 }
115 }),
116 propertiesChangedSignalCurrentHostState(
117 bus,
118 sdbusplus::bus::match::rules::type::signal() +
119 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530120 sdbusplus::bus::match::rules::path(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530121 postcodeDataHolderObj.HostStatePathPrefix +
122 std::to_string(postcodeDataHolderObj.node)) +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530123 sdbusplus::bus::match::rules::interface(
Manojkiran Edabd706d72021-12-21 05:09:47 +0530124 postcodeDataHolderObj.PropertiesIntf),
Jonathan Domaneddf9602022-11-23 09:29:41 -0800125 [this](sdbusplus::message_t& msg) {
Kuiying Wang3a044402019-02-19 15:00:11 +0800126 std::string objectName;
Patrick Williams9d91a392020-05-13 17:59:26 -0500127 std::map<std::string, std::variant<std::string>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800128 msg.read(objectName, msgData);
129 // Check if it was the Value property that changed.
130 auto valPropMap = msgData.find("CurrentHostState");
131 {
132 if (valPropMap != msgData.end())
133 {
134 StateServer::Host::HostState currentHostState =
135 StateServer::Host::convertHostStateFromString(
Patrick Williams23e3bf02020-05-13 11:37:14 -0500136 std::get<std::string>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800137 if (currentHostState ==
138 StateServer::Host::HostState::Off)
139 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800140 if (this->postCodes.empty())
Kuiying Wang3a044402019-02-19 15:00:11 +0800141 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800142 std::cerr << "HostState changed to OFF. Empty "
143 "postcode log, keep boot cycle at "
144 << this->currentBootCycleIndex
145 << std::endl;
Kuiying Wang3a044402019-02-19 15:00:11 +0800146 }
147 else
148 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800149 this->postCodes.clear();
Kuiying Wang3a044402019-02-19 15:00:11 +0800150 }
Kuiying Wang3a044402019-02-19 15:00:11 +0800151 }
152 }
153 }
154 })
155 {
156 phosphor::logging::log<phosphor::logging::level::INFO>(
157 "PostCode is created");
Manojkiran Edabd706d72021-12-21 05:09:47 +0530158 auto dir = fs::path(postcodeDataHolderObj.PostCodeListPathPrefix +
159 std::to_string(postcodeDataHolderObj.node));
Kuiying Wang3a044402019-02-19 15:00:11 +0800160 fs::create_directories(dir);
Manojkiran Edabd706d72021-12-21 05:09:47 +0530161 strPostCodeListPath = postcodeDataHolderObj.PostCodeListPathPrefix +
162 std::to_string(postcodeDataHolderObj.node) + "/";
Kuiying Wang3a044402019-02-19 15:00:11 +0800163 strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
164 uint16_t index = 0;
165 deserialize(
166 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName),
167 index);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800168 currentBootCycleIndex = index;
169 strCurrentBootCycleCountName = CurrentBootCycleCountName;
170 uint16_t count = 0;
171 deserialize(
172 fs::path(strPostCodeListPath + strCurrentBootCycleCountName),
173 count);
174 currentBootCycleCount(count);
Manojkiran Edaaed7b3d2021-06-19 09:39:30 +0530175 maxBootCycleNum(MAX_BOOT_CYCLE_COUNT);
Kuiying Wang3a044402019-02-19 15:00:11 +0800176 }
Jonathan Domaneddf9602022-11-23 09:29:41 -0800177 ~PostCode() {}
Kuiying Wang3a044402019-02-19 15:00:11 +0800178
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530179 std::vector<postcode_t> getPostCodes(uint16_t index) override;
180 std::map<uint64_t, postcode_t>
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800181 getPostCodesWithTimeStamp(uint16_t index) override;
182 void deleteAll() override;
Kuiying Wang3a044402019-02-19 15:00:11 +0800183
184 private:
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800185 void incrBootCycle();
186 uint16_t getBootNum(const uint16_t index) const;
187
Jonathan Domaneddf9602022-11-23 09:29:41 -0800188 sdbusplus::bus_t& bus;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800189 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
190 uint64_t firstPostCodeUsSinceEpoch;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530191 std::map<uint64_t, postcode_t> postCodes;
Kuiying Wang3a044402019-02-19 15:00:11 +0800192 std::string strPostCodeListPath;
193 std::string strCurrentBootCycleIndexName;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800194 uint16_t currentBootCycleIndex;
195 std::string strCurrentBootCycleCountName;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530196 void savePostCodes(postcode_t code);
Kuiying Wang3a044402019-02-19 15:00:11 +0800197 sdbusplus::bus::match_t propertiesChangedSignalRaw;
198 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
Jonathan Domaneddf9602022-11-23 09:29:41 -0800199 fs::path serialize(const std::string& path);
200 bool deserialize(const fs::path& path, uint16_t& index);
201 bool deserializePostCodes(const fs::path& path,
202 std::map<uint64_t, postcode_t>& codes);
Kuiying Wang3a044402019-02-19 15:00:11 +0800203};