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 "ascii_string.hpp"
17 
18 #include "pel_types.hpp"
19 
20 #include <phosphor-logging/log.hpp>
21 
22 namespace openpower
23 {
24 namespace pels
25 {
26 namespace src
27 {
28 
29 using namespace phosphor::logging;
30 
31 AsciiString::AsciiString(Stream& stream)
32 {
33     unflatten(stream);
34 }
35 
36 AsciiString::AsciiString(const message::Entry& entry)
37 {
38     // Power Error:  1100RRRR
39     // BMC Error:    BDSSRRRR
40     // where:
41     //  RRRR = reason code
42     //  SS = subsystem ID
43 
44     // First is type, like 'BD'
45     setByte(0, entry.src.type);
46 
47     // Next is '00', or subsystem ID
48     if (entry.src.type == static_cast<uint8_t>(SRCType::powerError))
49     {
50         setByte(2, 0x00);
51     }
52     else // BMC Error
53     {
54         setByte(2, entry.subsystem);
55     }
56 
57     // Then the reason code
58     setByte(4, entry.src.reasonCode >> 8);
59     setByte(6, entry.src.reasonCode & 0xFF);
60 
61     // Padded with spaces
62     for (size_t offset = 8; offset < asciiStringSize; offset++)
63     {
64         _string[offset] = ' ';
65     }
66 }
67 
68 void AsciiString::flatten(Stream& stream) const
69 {
70     stream.write(_string.data(), _string.size());
71 }
72 
73 void AsciiString::unflatten(Stream& stream)
74 {
75     stream.read(_string.data(), _string.size());
76 
77     // Only allow certain ASCII characters as other entities will
78     // eventually want to display this.
79     std::for_each(_string.begin(), _string.end(), [](auto& c) {
80         if (!isalnum(c) && (c != ' ') && (c != '.') && (c != ':') && (c != '/'))
81         {
82             c = ' ';
83         }
84     });
85 }
86 
87 std::string AsciiString::get() const
88 {
89     std::string string{_string.begin(), _string.begin() + _string.size()};
90     return string;
91 }
92 
93 void AsciiString::setByte(size_t byteOffset, uint8_t value)
94 {
95     assert(byteOffset < asciiStringSize);
96 
97     char characters[3];
98     sprintf(characters, "%02X", value);
99 
100     auto writeOffset = byteOffset;
101     _string[writeOffset++] = characters[0];
102     _string[writeOffset] = characters[1];
103 }
104 
105 } // namespace src
106 } // namespace pels
107 } // namespace openpower
108