1 /**
2  * Copyright © 2019 IBM 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 #include "private_header.hpp"
17 
18 #include "json_utils.hpp"
19 #include "log_id.hpp"
20 #include "pel_types.hpp"
21 #include "pel_values.hpp"
22 
23 #include <fmt/format.h>
24 
25 #include <phosphor-logging/log.hpp>
26 
27 namespace openpower
28 {
29 namespace pels
30 {
31 
32 namespace pv = openpower::pels::pel_values;
33 using namespace phosphor::logging;
34 
35 PrivateHeader::PrivateHeader(uint16_t componentID, uint32_t obmcLogID,
36                              uint64_t timestamp)
37 {
38     _header.id = static_cast<uint16_t>(SectionID::privateHeader);
39     _header.size = PrivateHeader::flattenedSize();
40     _header.version = privateHeaderVersion;
41     _header.subType = 0;
42     _header.componentID = componentID;
43 
44     _createTimestamp = getBCDTime(timestamp);
45 
46     auto now = std::chrono::system_clock::now();
47     _commitTimestamp = getBCDTime(now);
48 
49     _creatorID = static_cast<uint8_t>(CreatorID::openBMC);
50 
51     // Add support for reminder and telemetry log types here if
52     // ever necessary.
53     _logType = 0;
54 
55     _reservedByte = 0;
56 
57     // the final section count will be updated later
58     _sectionCount = 1;
59 
60     _obmcLogID = obmcLogID;
61 
62     _id = generatePELID();
63 
64     _plid = _id;
65 
66     // Leave _creatorVersion at 0
67 
68     _valid = true;
69 }
70 
71 PrivateHeader::PrivateHeader(Stream& pel) :
72     _creatorID(0), _logType(0), _reservedByte(0), _sectionCount(0),
73     _obmcLogID(0), _plid(0), _id(0)
74 {
75     try
76     {
77         unflatten(pel);
78         validate();
79     }
80     catch (const std::exception& e)
81     {
82         log<level::ERR>(
83             fmt::format("Cannot unflatten privatej header: {}", e.what())
84                 .c_str());
85         _valid = false;
86     }
87 }
88 std::optional<std::string> PrivateHeader::getJSON() const
89 {
90     char tmpPhVal[50];
91     sprintf(tmpPhVal, "%02X/%02X/%02X%02X %02X:%02X:%02X",
92             _createTimestamp.month, _createTimestamp.day,
93             _createTimestamp.yearMSB, _createTimestamp.yearLSB,
94             _createTimestamp.hour, _createTimestamp.minutes,
95             _createTimestamp.seconds);
96     std::string phCreateTStr(tmpPhVal);
97     sprintf(tmpPhVal, "%02X/%02X/%02X%02X %02X:%02X:%02X",
98             _commitTimestamp.month, _commitTimestamp.day,
99             _commitTimestamp.yearMSB, _commitTimestamp.yearLSB,
100             _commitTimestamp.hour, _commitTimestamp.minutes,
101             _commitTimestamp.seconds);
102     std::string phCommitTStr(tmpPhVal);
103     std::string creator = getNumberString("%c", _creatorID);
104     creator = pv::creatorIDs.count(creator) ? pv::creatorIDs.at(creator)
105                                             : "Unknown CreatorID";
106     std::string phCreatorVersionStr =
107         std::string(reinterpret_cast<const char*>(_creatorVersion.version));
108 
109     std::string ph;
110     jsonInsert(ph, pv::sectionVer, getNumberString("%d", privateHeaderVersion),
111                1);
112     jsonInsert(ph, pv::subSection, getNumberString("%d", _header.subType), 1);
113     jsonInsert(ph, pv::createdBy, getNumberString("0x%X", _header.componentID),
114                1);
115     jsonInsert(ph, "Created at", phCreateTStr, 1);
116     jsonInsert(ph, "Committed at", phCommitTStr, 1);
117     jsonInsert(ph, "Creator Subsystem", creator, 1);
118     jsonInsert(ph, "CSSVER", phCreatorVersionStr, 1);
119     jsonInsert(ph, "Platform Log Id", getNumberString("0x%X", _plid), 1);
120     jsonInsert(ph, "Entry Id", getNumberString("0x%X", _id), 1);
121     jsonInsert(ph, "BMC Event Log Id", std::to_string(_obmcLogID), 1);
122     ph.erase(ph.size() - 2);
123 
124     return ph;
125 }
126 void PrivateHeader::validate()
127 {
128     bool failed = false;
129 
130     if (header().id != static_cast<uint16_t>(SectionID::privateHeader))
131     {
132         log<level::ERR>(fmt::format("Invalid private header section ID: {0:#x}",
133                                     header().id)
134                             .c_str());
135         failed = true;
136     }
137 
138     if (header().version != privateHeaderVersion)
139     {
140         log<level::ERR>(fmt::format("Invalid private header version: {0:#x}",
141                                     header().version)
142                             .c_str());
143         failed = true;
144     }
145 
146     if (_sectionCount < minSectionCount)
147     {
148         log<level::ERR>(
149             fmt::format("Invalid section count in private header: {0:#x}",
150                         _sectionCount)
151                 .c_str());
152         failed = true;
153     }
154 
155     _valid = (failed) ? false : true;
156 }
157 
158 void PrivateHeader::unflatten(Stream& stream)
159 {
160     stream >> _header >> _createTimestamp >> _commitTimestamp >> _creatorID >>
161         _logType >> _reservedByte >> _sectionCount >> _obmcLogID >>
162         _creatorVersion >> _plid >> _id;
163 }
164 
165 void PrivateHeader::flatten(Stream& stream) const
166 {
167     stream << _header << _createTimestamp << _commitTimestamp << _creatorID
168            << _logType << _reservedByte << _sectionCount << _obmcLogID
169            << _creatorVersion << _plid << _id;
170 }
171 
172 Stream& operator>>(Stream& s, CreatorVersion& cv)
173 {
174     for (size_t i = 0; i < sizeof(CreatorVersion); i++)
175     {
176         s >> cv.version[i];
177     }
178     return s;
179 }
180 
181 Stream& operator<<(Stream& s, const CreatorVersion& cv)
182 {
183     for (size_t i = 0; i < sizeof(CreatorVersion); i++)
184     {
185         s << cv.version[i];
186     }
187     return s;
188 }
189 
190 } // namespace pels
191 } // namespace openpower
192