blob: 0fe3e3f7a7621cb085bc59ef2fda3bff6fc02c96 [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3
Matt Spinlerdf13bdb2019-07-10 16:54:13 -05004#include "log_id.hpp"
5
6#include "paths.hpp"
7
Arya K Padman5bc26532024-04-10 06:19:25 -05008#include <phosphor-logging/lg2.hpp>
Patrick Williams2544b412022-10-04 08:41:06 -05009
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050010#include <chrono>
11#include <filesystem>
12#include <fstream>
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050013
14namespace openpower
15{
16namespace pels
17{
18
19namespace fs = std::filesystem;
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050020
21constexpr uint32_t startingLogID = 1;
22constexpr uint32_t bmcLogIDPrefix = 0x50000000;
23
24namespace detail
25{
26
27uint32_t addLogIDPrefix(uint32_t id)
28{
29 // If redundant BMCs are ever a thing, may need a different prefix.
30 return (id & 0x00FFFFFF) | bmcLogIDPrefix;
31}
32
33uint32_t getTimeBasedLogID()
34{
35 using namespace std::chrono;
36
37 // Use 3 bytes of the nanosecond count since the epoch.
38 uint32_t id =
39 duration_cast<nanoseconds>(system_clock::now().time_since_epoch())
40 .count();
41
42 return addLogIDPrefix(id);
43}
44
45} // namespace detail
46
47uint32_t generatePELID()
48{
49 // Note: there isn't a need to be thread safe.
50
51 static std::string idFilename;
52 if (idFilename.empty())
53 {
54 idFilename = getPELIDFile();
Sumit Kumarf380c512021-11-19 06:07:31 -060055 checkFileForZeroData(idFilename);
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050056 }
57
58 uint32_t id = 0;
59
60 if (!fs::exists(idFilename))
61 {
62 auto path = fs::path(idFilename).parent_path();
63 if (!fs::exists(path))
64 {
65 fs::create_directories(path);
66 }
67
68 id = startingLogID;
69 }
70 else
71 {
72 std::ifstream idFile{idFilename};
73 idFile >> id;
74 if (idFile.fail())
75 {
76 // Just make up an ID
Arya K Padman5bc26532024-04-10 06:19:25 -050077 lg2::error("Unable to read PEL ID File!");
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050078 return detail::getTimeBasedLogID();
79 }
80 }
81
82 // Wrapping shouldn't be a problem, but check anyway
83 if (id == 0x00FFFFFF)
84 {
85 id = startingLogID;
86 }
87
88 std::ofstream idFile{idFilename};
89 idFile << (id + 1);
90 if (idFile.fail())
91 {
92 // Just make up an ID so we don't reuse one next time
Arya K Padman5bc26532024-04-10 06:19:25 -050093 lg2::error("Unable to write PEL ID File!");
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050094 return detail::getTimeBasedLogID();
95 }
96
97 return detail::addLogIDPrefix(id);
98}
99
Sumit Kumarf380c512021-11-19 06:07:31 -0600100void checkFileForZeroData(const std::string& filename)
101{
102 if (fs::exists(filename))
103 {
104 char ch;
105
106 std::ifstream rf{filename, std::ios::binary};
107 rf.read(&ch, sizeof(ch));
108 while (ch == '\0')
109 {
110 if (rf.eof())
111 {
112 fs::remove(filename);
Arya K Padman5bc26532024-04-10 06:19:25 -0500113 lg2::warning("PEL ID file seems corrupted. Deleting it.");
Sumit Kumarf380c512021-11-19 06:07:31 -0600114 break;
115 }
116 rf.read(&ch, sizeof(ch));
117 }
118 }
119}
Matt Spinlerdf13bdb2019-07-10 16:54:13 -0500120} // namespace pels
121} // namespace openpower