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 "callout.hpp"
17 
18 #include <phosphor-logging/log.hpp>
19 
20 namespace openpower
21 {
22 namespace pels
23 {
24 namespace src
25 {
26 
27 using namespace phosphor::logging;
28 
29 Callout::Callout(Stream& pel)
30 {
31     pel >> _size >> _flags >> _priority >> _locationCodeSize;
32 
33     if (_locationCodeSize)
34     {
35         _locationCode.resize(_locationCodeSize);
36         pel >> _locationCode;
37     }
38 
39     size_t currentSize = 4 + _locationCodeSize;
40 
41     // Read in the substructures until the end of this structure.
42     // Any stream overflows will throw an exception up to the SRC constructor
43     while (_size > currentSize)
44     {
45         // Peek the type
46         uint16_t type = 0;
47         pel >> type;
48         pel.offset(pel.offset() - 2);
49 
50         switch (type)
51         {
52             case FRUIdentity::substructureType:
53             {
54                 _fruIdentity = std::make_unique<FRUIdentity>(pel);
55                 currentSize += _fruIdentity->flattenedSize();
56                 break;
57             }
58             case PCEIdentity::substructureType:
59             {
60                 _pceIdentity = std::make_unique<PCEIdentity>(pel);
61                 currentSize += _pceIdentity->flattenedSize();
62                 break;
63             }
64             case MRU::substructureType:
65             {
66                 _mru = std::make_unique<MRU>(pel);
67                 currentSize += _mru->flattenedSize();
68                 break;
69             }
70             default:
71                 log<level::ERR>("Invalid Callout subsection type",
72                                 entry("CALLOUT_TYPE=0x%X", type));
73                 throw std::runtime_error("Invalid Callout subsection type");
74                 break;
75         }
76     }
77 }
78 
79 size_t Callout::flattenedSize()
80 {
81     size_t size = sizeof(_size) + sizeof(_flags) + sizeof(_priority) +
82                   sizeof(_locationCodeSize) + _locationCodeSize;
83 
84     size += _fruIdentity ? _fruIdentity->flattenedSize() : 0;
85     size += _pceIdentity ? _pceIdentity->flattenedSize() : 0;
86     size += _mru ? _mru->flattenedSize() : 0;
87 
88     return size;
89 }
90 
91 void Callout::flatten(Stream& pel) const
92 {
93     pel << _size << _flags << _priority << _locationCodeSize;
94 
95     if (_locationCodeSize)
96     {
97         pel << _locationCode;
98     }
99 
100     if (_fruIdentity)
101     {
102         _fruIdentity->flatten(pel);
103     }
104 
105     if (_pceIdentity)
106     {
107         _pceIdentity->flatten(pel);
108     }
109     if (_mru)
110     {
111         _mru->flatten(pel);
112     }
113 }
114 
115 } // namespace src
116 } // namespace pels
117 } // namespace openpower
118