xref: /openbmc/phosphor-logging/extensions/openpower-pels/log_id.cpp (revision 5bc265338cfeb7def47f45b4eef0efdc1cf1e751)
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 Spinler uint32_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 Spinler uint32_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 Spinler uint32_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 Kumar void 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