xref: /openbmc/smbios-mdr/src/cpu.cpp (revision a30229e1)
1 /*
2 // Copyright (c) 2018 Intel 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 
17 #include "cpu.hpp"
18 
19 #include <bitset>
20 #include <map>
21 
22 namespace phosphor
23 {
24 namespace smbios
25 {
26 
27 void Cpu::socket(const uint8_t positionNum, const uint8_t structLen,
28                  uint8_t* dataIn)
29 {
30     std::string result = positionToString(positionNum, structLen, dataIn);
31 
32     processor::socket(result);
33 
34     location::locationCode(result);
35 }
36 
37 static constexpr uint8_t processorFamily2Indicator = 0xfe;
38 void Cpu::family(const uint8_t family, const uint16_t family2)
39 {
40     std::map<uint8_t, const char*>::const_iterator it =
41         familyTable.find(family);
42     if (it == familyTable.end())
43     {
44         processor::family("Unknown Processor Family");
45     }
46     else if (it->first == processorFamily2Indicator)
47     {
48         std::map<uint16_t, const char*>::const_iterator it2 =
49             family2Table.find(family2);
50         if (it2 == family2Table.end())
51         {
52             processor::family("Unknown Processor Family");
53         }
54         else
55         {
56             processor::family(it2->second);
57         }
58     }
59     else
60     {
61         processor::family(it->second);
62     }
63 }
64 
65 void Cpu::manufacturer(const uint8_t positionNum, const uint8_t structLen,
66                        uint8_t* dataIn)
67 {
68     std::string result = positionToString(positionNum, structLen, dataIn);
69 
70     asset::manufacturer(result);
71 }
72 
73 void Cpu::partNumber(const uint8_t positionNum, const uint8_t structLen,
74                      uint8_t* dataIn)
75 {
76     std::string result = positionToString(positionNum, structLen, dataIn);
77 
78     asset::partNumber(result);
79 }
80 
81 void Cpu::serialNumber(const uint8_t positionNum, const uint8_t structLen,
82                        uint8_t* dataIn)
83 {
84     std::string result = positionToString(positionNum, structLen, dataIn);
85 
86     asset::serialNumber(result);
87 }
88 
89 void Cpu::version(const uint8_t positionNum, const uint8_t structLen,
90                   uint8_t* dataIn)
91 {
92     std::string result;
93 
94     result = positionToString(positionNum, structLen, dataIn);
95 
96     rev::version(result);
97 }
98 
99 void Cpu::characteristics(uint16_t value)
100 {
101     std::vector<processor::Capability> result;
102     std::optional<processor::Capability> cap;
103 
104     std::bitset<16> charBits = value;
105     for (uint8_t index = 0; index < charBits.size(); index++)
106     {
107         if (charBits.test(index))
108         {
109             if (cap = characteristicsTable[index])
110             {
111                 result.emplace_back(*cap);
112             }
113         }
114     }
115 
116     processor::characteristics(result);
117 }
118 
119 static constexpr uint8_t maxOldVersionCount = 0xff;
120 void Cpu::infoUpdate(void)
121 {
122     uint8_t* dataIn = storage;
123 
124     dataIn = getSMBIOSTypePtr(dataIn, processorsType);
125     if (dataIn == nullptr)
126     {
127         return;
128     }
129 
130     for (uint8_t index = 0; index < cpuNum; index++)
131     {
132         dataIn = smbiosNextPtr(dataIn);
133         if (dataIn == nullptr)
134         {
135             return;
136         }
137         dataIn = getSMBIOSTypePtr(dataIn, processorsType);
138         if (dataIn == nullptr)
139         {
140             return;
141         }
142     }
143 
144     auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn);
145 
146     socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h
147 
148     constexpr uint32_t socketPopulatedMask = 1 << 6;
149     if ((cpuInfo->status & socketPopulatedMask) == 0)
150     {
151         // Don't attempt to fill in any other details if the CPU is not present.
152         present(false);
153         return;
154     }
155     present(true);
156 
157     // this class is for type CPU  //offset 5h
158     family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h
159     manufacturer(cpuInfo->manufacturer, cpuInfo->length,
160                  dataIn);                               // offset 7h
161     id(cpuInfo->id);                                    // offset 8h
162     version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
163     maxSpeedInMhz(cpuInfo->maxSpeed);                   // offset 14h
164     serialNumber(cpuInfo->serialNum, cpuInfo->length,
165                  dataIn); // offset 20h
166     partNumber(cpuInfo->partNum, cpuInfo->length,
167                dataIn);                          // offset 22h
168     if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah
169     {
170         coreCount(cpuInfo->coreCount);
171     }
172     else
173     {
174         coreCount(cpuInfo->coreCount2);
175     }
176 
177     if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
178     {
179         threadCount(cpuInfo->threadCount);
180     }
181     else
182     {
183         threadCount(cpuInfo->threadCount2);
184     }
185 
186     characteristics(cpuInfo->characteristics); // offset 26h
187 
188     if (!motherboardPath.empty())
189     {
190         std::vector<std::tuple<std::string, std::string, std::string>> assocs;
191         assocs.emplace_back("chassis", "processors", motherboardPath);
192         association::associations(assocs);
193     }
194 }
195 
196 } // namespace smbios
197 } // namespace phosphor
198