1711d51d8SMatt Spinler /** 2711d51d8SMatt Spinler * Copyright © 2019 IBM Corporation 3711d51d8SMatt Spinler * 4711d51d8SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5711d51d8SMatt Spinler * you may not use this file except in compliance with the License. 6711d51d8SMatt Spinler * You may obtain a copy of the License at 7711d51d8SMatt Spinler * 8711d51d8SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9711d51d8SMatt Spinler * 10711d51d8SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11711d51d8SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12711d51d8SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13711d51d8SMatt Spinler * See the License for the specific language governing permissions and 14711d51d8SMatt Spinler * limitations under the License. 15711d51d8SMatt Spinler */ 16df13bdb6SMatt Spinler #include "log_id.hpp" 17df13bdb6SMatt Spinler 18df13bdb6SMatt Spinler #include "paths.hpp" 19df13bdb6SMatt Spinler 20*5bc26533SArya K Padman #include <phosphor-logging/lg2.hpp> 212544b419SPatrick Williams 22df13bdb6SMatt Spinler #include <chrono> 23df13bdb6SMatt Spinler #include <filesystem> 24df13bdb6SMatt Spinler #include <fstream> 25df13bdb6SMatt Spinler 26df13bdb6SMatt Spinler namespace openpower 27df13bdb6SMatt Spinler { 28df13bdb6SMatt Spinler namespace pels 29df13bdb6SMatt Spinler { 30df13bdb6SMatt Spinler 31df13bdb6SMatt Spinler namespace fs = std::filesystem; 32df13bdb6SMatt Spinler 33df13bdb6SMatt Spinler constexpr uint32_t startingLogID = 1; 34df13bdb6SMatt Spinler constexpr uint32_t bmcLogIDPrefix = 0x50000000; 35df13bdb6SMatt Spinler 36df13bdb6SMatt Spinler namespace detail 37df13bdb6SMatt Spinler { 38df13bdb6SMatt Spinler addLogIDPrefix(uint32_t id)39df13bdb6SMatt Spinleruint32_t addLogIDPrefix(uint32_t id) 40df13bdb6SMatt Spinler { 41df13bdb6SMatt Spinler // If redundant BMCs are ever a thing, may need a different prefix. 42df13bdb6SMatt Spinler return (id & 0x00FFFFFF) | bmcLogIDPrefix; 43df13bdb6SMatt Spinler } 44df13bdb6SMatt Spinler getTimeBasedLogID()45df13bdb6SMatt Spinleruint32_t getTimeBasedLogID() 46df13bdb6SMatt Spinler { 47df13bdb6SMatt Spinler using namespace std::chrono; 48df13bdb6SMatt Spinler 49df13bdb6SMatt Spinler // Use 3 bytes of the nanosecond count since the epoch. 50df13bdb6SMatt Spinler uint32_t id = 51df13bdb6SMatt Spinler duration_cast<nanoseconds>(system_clock::now().time_since_epoch()) 52df13bdb6SMatt Spinler .count(); 53df13bdb6SMatt Spinler 54df13bdb6SMatt Spinler return addLogIDPrefix(id); 55df13bdb6SMatt Spinler } 56df13bdb6SMatt Spinler 57df13bdb6SMatt Spinler } // namespace detail 58df13bdb6SMatt Spinler generatePELID()59df13bdb6SMatt Spinleruint32_t generatePELID() 60df13bdb6SMatt Spinler { 61df13bdb6SMatt Spinler // Note: there isn't a need to be thread safe. 62df13bdb6SMatt Spinler 63df13bdb6SMatt Spinler static std::string idFilename; 64df13bdb6SMatt Spinler if (idFilename.empty()) 65df13bdb6SMatt Spinler { 66df13bdb6SMatt Spinler idFilename = getPELIDFile(); 67f380c516SSumit Kumar checkFileForZeroData(idFilename); 68df13bdb6SMatt Spinler } 69df13bdb6SMatt Spinler 70df13bdb6SMatt Spinler uint32_t id = 0; 71df13bdb6SMatt Spinler 72df13bdb6SMatt Spinler if (!fs::exists(idFilename)) 73df13bdb6SMatt Spinler { 74df13bdb6SMatt Spinler auto path = fs::path(idFilename).parent_path(); 75df13bdb6SMatt Spinler if (!fs::exists(path)) 76df13bdb6SMatt Spinler { 77df13bdb6SMatt Spinler fs::create_directories(path); 78df13bdb6SMatt Spinler } 79df13bdb6SMatt Spinler 80df13bdb6SMatt Spinler id = startingLogID; 81df13bdb6SMatt Spinler } 82df13bdb6SMatt Spinler else 83df13bdb6SMatt Spinler { 84df13bdb6SMatt Spinler std::ifstream idFile{idFilename}; 85df13bdb6SMatt Spinler idFile >> id; 86df13bdb6SMatt Spinler if (idFile.fail()) 87df13bdb6SMatt Spinler { 88df13bdb6SMatt Spinler // Just make up an ID 89*5bc26533SArya K Padman lg2::error("Unable to read PEL ID File!"); 90df13bdb6SMatt Spinler return detail::getTimeBasedLogID(); 91df13bdb6SMatt Spinler } 92df13bdb6SMatt Spinler } 93df13bdb6SMatt Spinler 94df13bdb6SMatt Spinler // Wrapping shouldn't be a problem, but check anyway 95df13bdb6SMatt Spinler if (id == 0x00FFFFFF) 96df13bdb6SMatt Spinler { 97df13bdb6SMatt Spinler id = startingLogID; 98df13bdb6SMatt Spinler } 99df13bdb6SMatt Spinler 100df13bdb6SMatt Spinler std::ofstream idFile{idFilename}; 101df13bdb6SMatt Spinler idFile << (id + 1); 102df13bdb6SMatt Spinler if (idFile.fail()) 103df13bdb6SMatt Spinler { 104df13bdb6SMatt Spinler // Just make up an ID so we don't reuse one next time 105*5bc26533SArya K Padman lg2::error("Unable to write PEL ID File!"); 106df13bdb6SMatt Spinler return detail::getTimeBasedLogID(); 107df13bdb6SMatt Spinler } 108df13bdb6SMatt Spinler 109df13bdb6SMatt Spinler return detail::addLogIDPrefix(id); 110df13bdb6SMatt Spinler } 111df13bdb6SMatt Spinler checkFileForZeroData(const std::string & filename)112f380c516SSumit Kumarvoid checkFileForZeroData(const std::string& filename) 113f380c516SSumit Kumar { 114f380c516SSumit Kumar if (fs::exists(filename)) 115f380c516SSumit Kumar { 116f380c516SSumit Kumar char ch; 117f380c516SSumit Kumar 118f380c516SSumit Kumar std::ifstream rf{filename, std::ios::binary}; 119f380c516SSumit Kumar rf.read(&ch, sizeof(ch)); 120f380c516SSumit Kumar while (ch == '\0') 121f380c516SSumit Kumar { 122f380c516SSumit Kumar if (rf.eof()) 123f380c516SSumit Kumar { 124f380c516SSumit Kumar fs::remove(filename); 125*5bc26533SArya K Padman lg2::warning("PEL ID file seems corrupted. Deleting it."); 126f380c516SSumit Kumar break; 127f380c516SSumit Kumar } 128f380c516SSumit Kumar rf.read(&ch, sizeof(ch)); 129f380c516SSumit Kumar } 130f380c516SSumit Kumar } 131f380c516SSumit Kumar } 132df13bdb6SMatt Spinler } // namespace pels 133df13bdb6SMatt Spinler } // namespace openpower 134