1 /* 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> 23 #include <cereal/types/map.hpp> 24 #include <cereal/types/vector.hpp> 25 #include <chrono> 26 #include <experimental/filesystem> 27 #include <fstream> 28 #include <iostream> 29 #include <phosphor-logging/elog-errors.hpp> 30 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp> 31 #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 37 const static constexpr char *PostCodePath = 38 "/xyz/openbmc_project/state/boot/raw"; 39 const static constexpr char *PropertiesIntf = "org.freedesktop.DBus.Properties"; 40 const static constexpr char *PostCodeListPath = 41 "/var/lib/phosphor-post-code-manager/"; 42 const static constexpr char *CurrentBootCycleCountName = 43 "CurrentBootCycleCount"; 44 const static constexpr char *CurrentBootCycleIndexName = 45 "CurrentBootCycleIndex"; 46 const static constexpr char *HostStatePath = "/xyz/openbmc_project/state/host0"; 47 48 struct EventDeleter 49 { 50 void operator()(sd_event *event) const 51 { 52 event = sd_event_unref(event); 53 } 54 }; 55 using EventPtr = std::unique_ptr<sd_event, EventDeleter>; 56 namespace fs = std::experimental::filesystem; 57 namespace StateServer = sdbusplus::xyz::openbmc_project::State::server; 58 59 using post_code = 60 sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode; 61 using delete_all = 62 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll; 63 64 struct PostCode : sdbusplus::server::object_t<post_code, delete_all> 65 { 66 PostCode(sdbusplus::bus::bus &bus, const char *path, EventPtr &event) : 67 sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus), 68 propertiesChangedSignalRaw( 69 bus, 70 sdbusplus::bus::match::rules::type::signal() + 71 sdbusplus::bus::match::rules::member("PropertiesChanged") + 72 sdbusplus::bus::match::rules::path(PostCodePath) + 73 sdbusplus::bus::match::rules::interface(PropertiesIntf), 74 [this](sdbusplus::message::message &msg) { 75 std::string objectName; 76 std::map<std::string, sdbusplus::message::variant<uint64_t>> 77 msgData; 78 msg.read(objectName, msgData); 79 // Check if it was the Value property that changed. 80 auto valPropMap = msgData.find("Value"); 81 { 82 if (valPropMap != msgData.end()) 83 { 84 this->savePostCodes( 85 sdbusplus::message::variant_ns::get<uint64_t>( 86 valPropMap->second)); 87 } 88 } 89 }), 90 propertiesChangedSignalCurrentHostState( 91 bus, 92 sdbusplus::bus::match::rules::type::signal() + 93 sdbusplus::bus::match::rules::member("PropertiesChanged") + 94 sdbusplus::bus::match::rules::path(HostStatePath) + 95 sdbusplus::bus::match::rules::interface(PropertiesIntf), 96 [this](sdbusplus::message::message &msg) { 97 std::string objectName; 98 std::map<std::string, sdbusplus::message::variant<std::string>> 99 msgData; 100 msg.read(objectName, msgData); 101 // Check if it was the Value property that changed. 102 auto valPropMap = msgData.find("CurrentHostState"); 103 { 104 if (valPropMap != msgData.end()) 105 { 106 StateServer::Host::HostState currentHostState = 107 StateServer::Host::convertHostStateFromString( 108 sdbusplus::message::variant_ns::get< 109 std::string>(valPropMap->second)); 110 if (currentHostState == 111 StateServer::Host::HostState::Off) 112 { 113 if (this->postCodes.empty()) 114 { 115 std::cerr << "HostState changed to OFF. Empty " 116 "postcode log, keep boot cycle at " 117 << this->currentBootCycleIndex 118 << std::endl; 119 } 120 else 121 { 122 this->postCodes.clear(); 123 } 124 } 125 } 126 } 127 }) 128 { 129 phosphor::logging::log<phosphor::logging::level::INFO>( 130 "PostCode is created"); 131 auto dir = fs::path(PostCodeListPath); 132 fs::create_directories(dir); 133 strPostCodeListPath = PostCodeListPath; 134 strCurrentBootCycleIndexName = CurrentBootCycleIndexName; 135 uint16_t index = 0; 136 deserialize( 137 fs::path(strPostCodeListPath + strCurrentBootCycleIndexName), 138 index); 139 currentBootCycleIndex = index; 140 strCurrentBootCycleCountName = CurrentBootCycleCountName; 141 uint16_t count = 0; 142 deserialize( 143 fs::path(strPostCodeListPath + strCurrentBootCycleCountName), 144 count); 145 currentBootCycleCount(count); 146 maxBootCycleNum(MaxPostCodeCycles); 147 } 148 ~PostCode() 149 { 150 } 151 152 std::vector<uint64_t> getPostCodes(uint16_t index) override; 153 std::map<uint64_t, uint64_t> 154 getPostCodesWithTimeStamp(uint16_t index) override; 155 void deleteAll() override; 156 157 private: 158 void incrBootCycle(); 159 uint16_t getBootNum(const uint16_t index) const; 160 161 sdbusplus::bus::bus &bus; 162 std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady; 163 uint64_t firstPostCodeUsSinceEpoch; 164 std::map<uint64_t, uint64_t> postCodes; 165 std::string strPostCodeListPath; 166 std::string strCurrentBootCycleIndexName; 167 uint16_t currentBootCycleIndex; 168 std::string strCurrentBootCycleCountName; 169 void savePostCodes(uint64_t code); 170 sdbusplus::bus::match_t propertiesChangedSignalRaw; 171 sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState; 172 fs::path serialize(const std::string &path); 173 bool deserialize(const fs::path &path, uint16_t &index); 174 bool deserializePostCodes(const fs::path &path, 175 std::map<uint64_t, uint64_t> &codes); 176 }; 177