blob: 262a7735fd9e756cee518e0c56bd6469d3de9087 [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
Amithash Prasadb6616cd2025-05-29 15:56:51 -070021#include <nlohmann/json.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080022#include <phosphor-logging/elog-errors.hpp>
Bonnie Lo13cb8532022-12-15 17:00:40 +080023#include <sdbusplus/timer.hpp>
ZhikuiRen993d4dd2020-01-29 14:25:44 -080024#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Kuiying Wang3a044402019-02-19 15:00:11 +080025#include <xyz/openbmc_project/Common/error.hpp>
26#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
27#include <xyz/openbmc_project/State/Host/server.hpp>
28
Jonathan Domaneddf9602022-11-23 09:29:41 -080029#include <chrono>
30#include <filesystem>
31#include <fstream>
32#include <iostream>
33
34const static constexpr char* CurrentBootCycleCountName =
ZhikuiRen993d4dd2020-01-29 14:25:44 -080035 "CurrentBootCycleCount";
Jonathan Domaneddf9602022-11-23 09:29:41 -080036const static constexpr char* CurrentBootCycleIndexName =
Kuiying Wang3a044402019-02-19 15:00:11 +080037 "CurrentBootCycleIndex";
Kumar Thangavelfd45f782020-09-01 22:59:00 +053038
Jonathan Domanc7fed5c2022-11-23 11:14:42 -080039const static constexpr char* PostCodePath =
40 "/xyz/openbmc_project/state/boot/raw";
41const static constexpr char* PostCodeListPathPrefix =
42 "/var/lib/phosphor-post-code-manager/host";
43const static constexpr char* HostStatePathPrefix =
44 "/xyz/openbmc_project/state/host";
Kuiying Wang3a044402019-02-19 15:00:11 +080045
46struct EventDeleter
47{
Jonathan Domaneddf9602022-11-23 09:29:41 -080048 void operator()(sd_event* event) const
Kuiying Wang3a044402019-02-19 15:00:11 +080049 {
Manojkiran Edade8d3a52021-12-05 12:51:07 +053050 sd_event_unref(event);
Kuiying Wang3a044402019-02-19 15:00:11 +080051 }
52};
53using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
Potin Lai06b1dbe2024-09-16 15:09:06 +080054using primarycode_t = std::vector<uint8_t>;
Manojkiran Eda84a4c192021-02-25 15:23:42 +053055using secondarycode_t = std::vector<uint8_t>;
56using postcode_t = std::tuple<primarycode_t, secondarycode_t>;
Manojkiran Eda410ba292021-12-05 10:55:56 +053057namespace fs = std::filesystem;
Kuiying Wang3a044402019-02-19 15:00:11 +080058namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
59
60using post_code =
61 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
ZhikuiRen993d4dd2020-01-29 14:25:44 -080062using delete_all =
63 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
Kuiying Wang3a044402019-02-19 15:00:11 +080064
Amithash Prasadb6616cd2025-05-29 15:56:51 -070065struct PostCodeEvent
66{
67 std::string name;
68 nlohmann::json args;
69 void raise() const;
70};
71
72struct PostCodeHandler
73{
74 primarycode_t primary;
75 std::optional<secondarycode_t> secondary;
76 std::vector<std::string> targets;
77 std::optional<PostCodeEvent> event;
78};
79
80struct PostCodeHandlers
81{
82 std::vector<PostCodeHandler> handlers;
83 void handle(postcode_t code);
84 const PostCodeHandler* find(postcode_t code);
85 void load(const std::string& path);
86};
87
ZhikuiRen993d4dd2020-01-29 14:25:44 -080088struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
Kuiying Wang3a044402019-02-19 15:00:11 +080089{
Bonnie Lo13cb8532022-12-15 17:00:40 +080090 PostCode(sdbusplus::bus_t& bus, const char* path, EventPtr& event,
Amithash Prasadb6616cd2025-05-29 15:56:51 -070091 int nodeIndex, PostCodeHandlers& handlers) :
Patrick Williams9c2e8712024-08-16 15:20:36 -040092 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
93 event(event), node(nodeIndex),
Jonathan Domanc7fed5c2022-11-23 11:14:42 -080094 postCodeListPath(PostCodeListPathPrefix + std::to_string(node)),
Kuiying Wang3a044402019-02-19 15:00:11 +080095 propertiesChangedSignalRaw(
96 bus,
Jonathan Domanc7fed5c2022-11-23 11:14:42 -080097 sdbusplus::bus::match::rules::propertiesChanged(
98 PostCodePath + std::to_string(node),
99 "xyz.openbmc_project.State.Boot.Raw"),
Jonathan Domaneddf9602022-11-23 09:29:41 -0800100 [this](sdbusplus::message_t& msg) {
Patrick Williams9c2e8712024-08-16 15:20:36 -0400101 std::string intfName;
102 std::map<std::string, std::variant<postcode_t>> msgData;
103 msg.read(intfName, msgData);
104 // Check if it was the Value property that changed.
105 auto valPropMap = msgData.find("Value");
106 if (valPropMap != msgData.end())
107 {
108 this->savePostCodes(
109 std::get<postcode_t>(valPropMap->second));
110 }
111 }),
Patrick Williams608a3922023-10-20 11:18:57 -0500112 propertiesChangedSignalCurrentHostState(
113 bus,
114 sdbusplus::bus::match::rules::propertiesChanged(
115 HostStatePathPrefix + std::to_string(node),
116 "xyz.openbmc_project.State.Host"),
117 [this](sdbusplus::message_t& msg) {
Patrick Williams9c2e8712024-08-16 15:20:36 -0400118 std::string intfName;
119 std::map<std::string, std::variant<std::string>> msgData;
120 msg.read(intfName, msgData);
121 // Check if it was the Value property that changed.
122 auto valPropMap = msgData.find("CurrentHostState");
123 if (valPropMap != msgData.end())
Kuiying Wang3a044402019-02-19 15:00:11 +0800124 {
Patrick Williams9c2e8712024-08-16 15:20:36 -0400125 StateServer::Host::HostState currentHostState =
126 StateServer::Host::convertHostStateFromString(
127 std::get<std::string>(valPropMap->second));
128 if (currentHostState == StateServer::Host::HostState::Off)
129 {
130 if (this->postCodes.empty())
131 {
132 std::cerr
133 << "HostState changed to OFF. Empty "
134 "postcode log, keep boot cycle at "
135 << this->currentBootCycleIndex << std::endl;
136 }
137 else
138 {
139 this->postCodes.clear();
140 }
141 }
Kuiying Wang3a044402019-02-19 15:00:11 +0800142 }
Amithash Prasadb6616cd2025-05-29 15:56:51 -0700143 }),
144 postCodeHandlers(std::move(handlers))
Kuiying Wang3a044402019-02-19 15:00:11 +0800145 {
146 phosphor::logging::log<phosphor::logging::level::INFO>(
147 "PostCode is created");
Jonathan Domanc7fed5c2022-11-23 11:14:42 -0800148 fs::create_directories(postCodeListPath);
149 deserialize(postCodeListPath / CurrentBootCycleIndexName,
150 currentBootCycleIndex);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800151 uint16_t count = 0;
Jonathan Domanc7fed5c2022-11-23 11:14:42 -0800152 deserialize(postCodeListPath / CurrentBootCycleCountName, count);
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800153 currentBootCycleCount(count);
Manojkiran Edaaed7b3d2021-06-19 09:39:30 +0530154 maxBootCycleNum(MAX_BOOT_CYCLE_COUNT);
Kuiying Wang3a044402019-02-19 15:00:11 +0800155 }
Jonathan Domaneddf9602022-11-23 09:29:41 -0800156 ~PostCode() {}
Kuiying Wang3a044402019-02-19 15:00:11 +0800157
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530158 std::vector<postcode_t> getPostCodes(uint16_t index) override;
Patrick Williams4e1910b2025-02-01 08:22:19 -0500159 std::map<uint64_t, postcode_t> getPostCodesWithTimeStamp(
160 uint16_t index) override;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800161 void deleteAll() override;
Kuiying Wang3a044402019-02-19 15:00:11 +0800162
163 private:
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800164 void incrBootCycle();
165 uint16_t getBootNum(const uint16_t index) const;
166
Patrick Williams2d74ceb2023-12-05 12:45:02 -0600167 std::unique_ptr<sdbusplus::Timer> timer;
Jonathan Domaneddf9602022-11-23 09:29:41 -0800168 sdbusplus::bus_t& bus;
Bonnie Lo13cb8532022-12-15 17:00:40 +0800169 EventPtr& event;
Jonathan Domanc7fed5c2022-11-23 11:14:42 -0800170 int node;
ZhikuiRen993d4dd2020-01-29 14:25:44 -0800171 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
172 uint64_t firstPostCodeUsSinceEpoch;
Manojkiran Eda84a4c192021-02-25 15:23:42 +0530173 std::map<uint64_t, postcode_t> postCodes;
Jonathan Domanc7fed5c2022-11-23 11:14:42 -0800174 fs::path postCodeListPath;
175 uint16_t currentBootCycleIndex = 0;
Kuiying Wang3a044402019-02-19 15:00:11 +0800176 sdbusplus::bus::match_t propertiesChangedSignalRaw;
177 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
Jonathan Domanc7fed5c2022-11-23 11:14:42 -0800178
179 void savePostCodes(postcode_t code);
180 fs::path serialize(const fs::path& path);
Jonathan Domaneddf9602022-11-23 09:29:41 -0800181 bool deserialize(const fs::path& path, uint16_t& index);
182 bool deserializePostCodes(const fs::path& path,
183 std::map<uint64_t, postcode_t>& codes);
Amithash Prasadb6616cd2025-05-29 15:56:51 -0700184 PostCodeHandlers postCodeHandlers;
Kuiying Wang3a044402019-02-19 15:00:11 +0800185};