blob: 5e2a7b95a103278989610fcbf19067303fd126cd [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>
Kuiying Wang3a044402019-02-19 15:00:11 +080024#include <cereal/types/vector.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080025#include <chrono>
Kuiying Wang3a044402019-02-19 15:00:11 +080026#include <experimental/filesystem>
27#include <fstream>
28#include <iostream>
29#include <phosphor-logging/elog-errors.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080030#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080031#include <xyz/openbmc_project/Common/error.hpp>
32#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
33#include <xyz/openbmc_project/State/Host/server.hpp>
34
35#define MaxPostCodeCycles 100
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{
45 static PostCodeDataHolder *instance;
46
47 PostCodeDataHolder()
48 {
49 }
50
51 public:
52 static PostCodeDataHolder *getInstance()
53 {
54 if (!instance)
55 instance = new PostCodeDataHolder;
56 return instance;
57 }
58
59 int node;
60
61 const static constexpr char *PostCodePath =
62 "/xyz/openbmc_project/state/boot/raw";
63 const static constexpr char *PropertiesIntf =
64 "org.freedesktop.DBus.Properties";
65 const static constexpr char *PostCodeListPathPrefix =
66 "/var/lib/phosphor-post-code-manager/host";
67 const static constexpr char *HostStatePathPrefix =
68 "/xyz/openbmc_project/state/host";
69};
Kuiying Wang3a044402019-02-19 15:00:11 +080070
71struct EventDeleter
72{
73 void operator()(sd_event *event) const
74 {
75 event = sd_event_unref(event);
76 }
77};
78using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
79namespace fs = std::experimental::filesystem;
80namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
81
82using post_code =
83 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
ZhikuiRen993d4dd2020-01-29 14:25:44 -080084using delete_all =
85 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
Kuiying Wang3a044402019-02-19 15:00:11 +080086
ZhikuiRen993d4dd2020-01-29 14:25:44 -080087struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
Kuiying Wang3a044402019-02-19 15:00:11 +080088{
Kumar Thangavelfd45f782020-09-01 22:59:00 +053089 PostCodeDataHolder *postcodeDataHolderObj =
90 postcodeDataHolderObj->getInstance();
91
Kuiying Wang3a044402019-02-19 15:00:11 +080092 PostCode(sdbusplus::bus::bus &bus, const char *path, EventPtr &event) :
ZhikuiRen993d4dd2020-01-29 14:25:44 -080093 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
Kuiying Wang3a044402019-02-19 15:00:11 +080094 propertiesChangedSignalRaw(
95 bus,
96 sdbusplus::bus::match::rules::type::signal() +
97 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +053098 sdbusplus::bus::match::rules::path(
99 postcodeDataHolderObj->PostCodePath +
100 std::to_string(postcodeDataHolderObj->node)) +
101 sdbusplus::bus::match::rules::interface(
102 postcodeDataHolderObj->PropertiesIntf),
Kuiying Wang3a044402019-02-19 15:00:11 +0800103 [this](sdbusplus::message::message &msg) {
104 std::string objectName;
Patrick Williams9d91a392020-05-13 17:59:26 -0500105 std::map<std::string, std::variant<uint64_t>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800106 msg.read(objectName, msgData);
107 // Check if it was the Value property that changed.
108 auto valPropMap = msgData.find("Value");
109 {
110 if (valPropMap != msgData.end())
111 {
112 this->savePostCodes(
Patrick Williams23e3bf02020-05-13 11:37:14 -0500113 std::get<uint64_t>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800114 }
115 }
116 }),
117 propertiesChangedSignalCurrentHostState(
118 bus,
119 sdbusplus::bus::match::rules::type::signal() +
120 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530121 sdbusplus::bus::match::rules::path(
122 postcodeDataHolderObj->HostStatePathPrefix +
123 std::to_string(postcodeDataHolderObj->node)) +
124 sdbusplus::bus::match::rules::interface(
125 postcodeDataHolderObj->PropertiesIntf),
Kuiying Wang3a044402019-02-19 15:00:11 +0800126 [this](sdbusplus::message::message &msg) {
127 std::string objectName;
Patrick Williams9d91a392020-05-13 17:59:26 -0500128 std::map<std::string, std::variant<std::string>> msgData;
Kuiying Wang3a044402019-02-19 15:00:11 +0800129 msg.read(objectName, msgData);
130 // Check if it was the Value property that changed.
131 auto valPropMap = msgData.find("CurrentHostState");
132 {
133 if (valPropMap != msgData.end())
134 {
135 StateServer::Host::HostState currentHostState =
136 StateServer::Host::convertHostStateFromString(
Patrick Williams23e3bf02020-05-13 11:37:14 -0500137 std::get<std::string>(valPropMap->second));
Kuiying Wang3a044402019-02-19 15:00:11 +0800138 if (currentHostState ==
139 StateServer::Host::HostState::Off)
140 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800141 if (this->postCodes.empty())
Kuiying Wang3a044402019-02-19 15:00:11 +0800142 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800143 std::cerr << "HostState changed to OFF. Empty "
144 "postcode log, keep boot cycle at "
145 << this->currentBootCycleIndex
146 << std::endl;
Kuiying Wang3a044402019-02-19 15:00:11 +0800147 }
148 else
149 {
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800150 this->postCodes.clear();
Kuiying Wang3a044402019-02-19 15:00:11 +0800151 }
Kuiying Wang3a044402019-02-19 15:00:11 +0800152 }
153 }
154 }
155 })
156 {
157 phosphor::logging::log<phosphor::logging::level::INFO>(
158 "PostCode is created");
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530159 auto dir = fs::path(postcodeDataHolderObj->PostCodeListPathPrefix +
160 std::to_string(postcodeDataHolderObj->node));
Kuiying Wang3a044402019-02-19 15:00:11 +0800161 fs::create_directories(dir);
Kumar Thangavelfd45f782020-09-01 22:59:00 +0530162 strPostCodeListPath = postcodeDataHolderObj->PostCodeListPathPrefix +
163 std::to_string(postcodeDataHolderObj->node) + "/";
Kuiying Wang3a044402019-02-19 15:00:11 +0800164 strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
165 uint16_t index = 0;
166 deserialize(
167 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName),
168 index);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800169 currentBootCycleIndex = index;
170 strCurrentBootCycleCountName = CurrentBootCycleCountName;
171 uint16_t count = 0;
172 deserialize(
173 fs::path(strPostCodeListPath + strCurrentBootCycleCountName),
174 count);
175 currentBootCycleCount(count);
Kuiying Wang3a044402019-02-19 15:00:11 +0800176 maxBootCycleNum(MaxPostCodeCycles);
Kuiying Wang3a044402019-02-19 15:00:11 +0800177 }
178 ~PostCode()
179 {
180 }
181
182 std::vector<uint64_t> getPostCodes(uint16_t index) override;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800183 std::map<uint64_t, uint64_t>
184 getPostCodesWithTimeStamp(uint16_t index) override;
185 void deleteAll() override;
Kuiying Wang3a044402019-02-19 15:00:11 +0800186
187 private:
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800188 void incrBootCycle();
189 uint16_t getBootNum(const uint16_t index) const;
190
Kuiying Wang3a044402019-02-19 15:00:11 +0800191 sdbusplus::bus::bus &bus;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800192 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
193 uint64_t firstPostCodeUsSinceEpoch;
194 std::map<uint64_t, uint64_t> postCodes;
Kuiying Wang3a044402019-02-19 15:00:11 +0800195 std::string strPostCodeListPath;
196 std::string strCurrentBootCycleIndexName;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800197 uint16_t currentBootCycleIndex;
198 std::string strCurrentBootCycleCountName;
Kuiying Wang3a044402019-02-19 15:00:11 +0800199 void savePostCodes(uint64_t code);
200 sdbusplus::bus::match_t propertiesChangedSignalRaw;
201 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
202 fs::path serialize(const std::string &path);
203 bool deserialize(const fs::path &path, uint16_t &index);
204 bool deserializePostCodes(const fs::path &path,
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800205 std::map<uint64_t, uint64_t> &codes);
Kuiying Wang3a044402019-02-19 15:00:11 +0800206};