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