1711d51d8SMatt Spinler /** 2711d51d8SMatt Spinler * Copyright © 2019 IBM Corporation 3711d51d8SMatt Spinler * 4711d51d8SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5711d51d8SMatt Spinler * you may not use this file except in compliance with the License. 6711d51d8SMatt Spinler * You may obtain a copy of the License at 7711d51d8SMatt Spinler * 8711d51d8SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9711d51d8SMatt Spinler * 10711d51d8SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11711d51d8SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12711d51d8SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13711d51d8SMatt Spinler * See the License for the specific language governing permissions and 14711d51d8SMatt Spinler * limitations under the License. 15711d51d8SMatt Spinler */ 16a906c940SMatt Spinler #include "fru_identity.hpp" 17a906c940SMatt Spinler 18ba0ee002SMatt Spinler #include "pel_values.hpp" 19ba0ee002SMatt Spinler 20a27e2e50SMatt Spinler #include <phosphor-logging/log.hpp> 21a27e2e50SMatt Spinler 22a27e2e50SMatt Spinler using namespace phosphor::logging; 23a27e2e50SMatt Spinler 24a906c940SMatt Spinler namespace openpower 25a906c940SMatt Spinler { 26a906c940SMatt Spinler namespace pels 27a906c940SMatt Spinler { 28a906c940SMatt Spinler namespace src 29a906c940SMatt Spinler { 30a906c940SMatt Spinler 31a906c940SMatt Spinler FRUIdentity::FRUIdentity(Stream& pel) 32a906c940SMatt Spinler { 33a906c940SMatt Spinler pel >> _type >> _size >> _flags; 34a906c940SMatt Spinler 35ba0ee002SMatt Spinler if (hasPN() || hasMP()) 36a906c940SMatt Spinler { 37a906c940SMatt Spinler pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size()); 38a906c940SMatt Spinler } 39a906c940SMatt Spinler 40ba0ee002SMatt Spinler if (hasCCIN()) 41a906c940SMatt Spinler { 42a906c940SMatt Spinler pel.read(_ccin.data(), _ccin.size()); 43a906c940SMatt Spinler } 44a906c940SMatt Spinler 45ba0ee002SMatt Spinler if (hasSN()) 46a906c940SMatt Spinler { 47a906c940SMatt Spinler pel.read(_sn.data(), _sn.size()); 48a906c940SMatt Spinler } 49a906c940SMatt Spinler } 50a906c940SMatt Spinler 51a09354b7SMatt Spinler size_t FRUIdentity::flattenedSize() const 52a09354b7SMatt Spinler { 53a09354b7SMatt Spinler size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags); 54a09354b7SMatt Spinler 55a09354b7SMatt Spinler if (hasPN() || hasMP()) 56a09354b7SMatt Spinler { 57a09354b7SMatt Spinler size += _pnOrProcedureID.size(); 58a09354b7SMatt Spinler } 59a09354b7SMatt Spinler 60a09354b7SMatt Spinler if (hasCCIN()) 61a09354b7SMatt Spinler { 62a09354b7SMatt Spinler size += _ccin.size(); 63a09354b7SMatt Spinler } 64a09354b7SMatt Spinler 65a09354b7SMatt Spinler if (hasSN()) 66a09354b7SMatt Spinler { 67a09354b7SMatt Spinler size += _sn.size(); 68a09354b7SMatt Spinler } 69a09354b7SMatt Spinler 70a09354b7SMatt Spinler return size; 71a09354b7SMatt Spinler } 72a09354b7SMatt Spinler 73ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin, 74ba0ee002SMatt Spinler const std::string& serialNumber) 75ba0ee002SMatt Spinler { 76ba0ee002SMatt Spinler _type = substructureType; 77ba0ee002SMatt Spinler _flags = hardwareFRU; 78ba0ee002SMatt Spinler 79ba0ee002SMatt Spinler setPartNumber(partNumber); 80ba0ee002SMatt Spinler setCCIN(ccin); 81ba0ee002SMatt Spinler setSerialNumber(serialNumber); 82ba0ee002SMatt Spinler 83ba0ee002SMatt Spinler _size = flattenedSize(); 84ba0ee002SMatt Spinler } 85ba0ee002SMatt Spinler 86a27e2e50SMatt Spinler FRUIdentity::FRUIdentity(const std::string& procedureFromRegistry) 87ba0ee002SMatt Spinler { 88ba0ee002SMatt Spinler _type = substructureType; 89ba0ee002SMatt Spinler _flags = maintenanceProc; 90ba0ee002SMatt Spinler 91a27e2e50SMatt Spinler setMaintenanceProcedure(procedureFromRegistry); 92ba0ee002SMatt Spinler 93ba0ee002SMatt Spinler _size = flattenedSize(); 94ba0ee002SMatt Spinler } 95ba0ee002SMatt Spinler 96*2b6dfa00SMatt Spinler FRUIdentity::FRUIdentity(const std::string& symbolicFRUFromRegistry, 97*2b6dfa00SMatt Spinler bool trustedLocationCode) 98*2b6dfa00SMatt Spinler { 99*2b6dfa00SMatt Spinler _type = substructureType; 100*2b6dfa00SMatt Spinler _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU; 101*2b6dfa00SMatt Spinler 102*2b6dfa00SMatt Spinler setSymbolicFRU(symbolicFRUFromRegistry); 103*2b6dfa00SMatt Spinler 104*2b6dfa00SMatt Spinler _size = flattenedSize(); 105*2b6dfa00SMatt Spinler } 106*2b6dfa00SMatt Spinler 107a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getPN() const 108a906c940SMatt Spinler { 109a906c940SMatt Spinler if (hasPN()) 110a906c940SMatt Spinler { 111a906c940SMatt Spinler // NULL terminated 112a906c940SMatt Spinler std::string pn{_pnOrProcedureID.data()}; 113a906c940SMatt Spinler return pn; 114a906c940SMatt Spinler } 115a906c940SMatt Spinler 116a906c940SMatt Spinler return std::nullopt; 117a906c940SMatt Spinler } 118a906c940SMatt Spinler 119a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getMaintProc() const 120a906c940SMatt Spinler { 121a906c940SMatt Spinler if (hasMP()) 122a906c940SMatt Spinler { 123a906c940SMatt Spinler // NULL terminated 124a906c940SMatt Spinler std::string mp{_pnOrProcedureID.data()}; 125a906c940SMatt Spinler return mp; 126a906c940SMatt Spinler } 127a906c940SMatt Spinler 128a906c940SMatt Spinler return std::nullopt; 129a906c940SMatt Spinler } 130a906c940SMatt Spinler 131a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getCCIN() const 132a906c940SMatt Spinler { 133a906c940SMatt Spinler if (hasCCIN()) 134a906c940SMatt Spinler { 135a906c940SMatt Spinler std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()}; 136ba0ee002SMatt Spinler 137ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually) 138ba0ee002SMatt Spinler if (auto pos = ccin.find('\0'); pos != std::string::npos) 139ba0ee002SMatt Spinler { 140ba0ee002SMatt Spinler ccin.resize(pos); 141ba0ee002SMatt Spinler } 142a906c940SMatt Spinler return ccin; 143a906c940SMatt Spinler } 144a906c940SMatt Spinler 145a906c940SMatt Spinler return std::nullopt; 146a906c940SMatt Spinler } 147a906c940SMatt Spinler 148a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getSN() const 149a906c940SMatt Spinler { 150a906c940SMatt Spinler if (hasSN()) 151a906c940SMatt Spinler { 152a906c940SMatt Spinler std::string sn{_sn.begin(), _sn.begin() + _sn.size()}; 153ba0ee002SMatt Spinler 154ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually) 155ba0ee002SMatt Spinler if (auto pos = sn.find('\0'); pos != std::string::npos) 156ba0ee002SMatt Spinler { 157ba0ee002SMatt Spinler sn.resize(pos); 158ba0ee002SMatt Spinler } 159a906c940SMatt Spinler return sn; 160a906c940SMatt Spinler } 161a906c940SMatt Spinler 162a906c940SMatt Spinler return std::nullopt; 163a906c940SMatt Spinler } 164a906c940SMatt Spinler 165724d0d8cSMatt Spinler void FRUIdentity::flatten(Stream& pel) const 166a906c940SMatt Spinler { 167a906c940SMatt Spinler pel << _type << _size << _flags; 168a906c940SMatt Spinler 169a906c940SMatt Spinler if (hasPN() || hasMP()) 170a906c940SMatt Spinler { 171a906c940SMatt Spinler pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size()); 172a906c940SMatt Spinler } 173a906c940SMatt Spinler 174a906c940SMatt Spinler if (hasCCIN()) 175a906c940SMatt Spinler { 176a906c940SMatt Spinler pel.write(_ccin.data(), _ccin.size()); 177a906c940SMatt Spinler } 178a906c940SMatt Spinler 179a906c940SMatt Spinler if (hasSN()) 180a906c940SMatt Spinler { 181a906c940SMatt Spinler pel.write(_sn.data(), _sn.size()); 182a906c940SMatt Spinler } 183a906c940SMatt Spinler } 184a906c940SMatt Spinler 185ba0ee002SMatt Spinler void FRUIdentity::setPartNumber(const std::string& partNumber) 186ba0ee002SMatt Spinler { 187ba0ee002SMatt Spinler _flags |= pnSupplied; 188ba0ee002SMatt Spinler _flags &= ~maintProcSupplied; 189ba0ee002SMatt Spinler 190ba0ee002SMatt Spinler auto pn = partNumber; 191ba0ee002SMatt Spinler 192ba0ee002SMatt Spinler // Strip leading whitespace on this one. 193ba0ee002SMatt Spinler while (' ' == pn.front()) 194ba0ee002SMatt Spinler { 195ba0ee002SMatt Spinler pn = pn.substr(1); 196ba0ee002SMatt Spinler } 197ba0ee002SMatt Spinler 198ba0ee002SMatt Spinler // Note: strncpy only writes NULLs if pn short 199ba0ee002SMatt Spinler strncpy(_pnOrProcedureID.data(), pn.c_str(), _pnOrProcedureID.size()); 200ba0ee002SMatt Spinler 201ba0ee002SMatt Spinler // ensure null terminated 202ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0; 203ba0ee002SMatt Spinler } 204ba0ee002SMatt Spinler 205ba0ee002SMatt Spinler void FRUIdentity::setCCIN(const std::string& ccin) 206ba0ee002SMatt Spinler { 207ba0ee002SMatt Spinler _flags |= ccinSupplied; 208ba0ee002SMatt Spinler 209ba0ee002SMatt Spinler // Note: _ccin not null terminated, though strncpy writes NULLs if short 210ba0ee002SMatt Spinler strncpy(_ccin.data(), ccin.c_str(), _ccin.size()); 211ba0ee002SMatt Spinler } 212ba0ee002SMatt Spinler 213ba0ee002SMatt Spinler void FRUIdentity::setSerialNumber(const std::string& serialNumber) 214ba0ee002SMatt Spinler { 215ba0ee002SMatt Spinler _flags |= snSupplied; 216ba0ee002SMatt Spinler 217ba0ee002SMatt Spinler // Note: _sn not null terminated, though strncpy writes NULLs if short 218ba0ee002SMatt Spinler strncpy(_sn.data(), serialNumber.c_str(), _sn.size()); 219ba0ee002SMatt Spinler } 220ba0ee002SMatt Spinler 221a27e2e50SMatt Spinler void FRUIdentity::setMaintenanceProcedure( 222a27e2e50SMatt Spinler const std::string& procedureFromRegistry) 223ba0ee002SMatt Spinler { 224ba0ee002SMatt Spinler _flags |= maintProcSupplied; 225ba0ee002SMatt Spinler _flags &= ~pnSupplied; 226ba0ee002SMatt Spinler 227a27e2e50SMatt Spinler if (pel_values::maintenanceProcedures.count(procedureFromRegistry)) 228a27e2e50SMatt Spinler { 229a27e2e50SMatt Spinler strncpy( 230a27e2e50SMatt Spinler _pnOrProcedureID.data(), 231a27e2e50SMatt Spinler pel_values::maintenanceProcedures.at(procedureFromRegistry).c_str(), 232ba0ee002SMatt Spinler _pnOrProcedureID.size()); 233a27e2e50SMatt Spinler } 234a27e2e50SMatt Spinler else 235a27e2e50SMatt Spinler { 236a27e2e50SMatt Spinler log<level::ERR>("Invalid maintenance procedure", 237a27e2e50SMatt Spinler entry("PROCEDURE=%s", procedureFromRegistry.c_str())); 238a27e2e50SMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size()); 239a27e2e50SMatt Spinler } 240ba0ee002SMatt Spinler 241ba0ee002SMatt Spinler // ensure null terminated 242ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0; 243ba0ee002SMatt Spinler } 244ba0ee002SMatt Spinler 245*2b6dfa00SMatt Spinler void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRUFromRegistry) 246*2b6dfa00SMatt Spinler { 247*2b6dfa00SMatt Spinler 248*2b6dfa00SMatt Spinler // Treat this has a HW callout. 249*2b6dfa00SMatt Spinler _flags |= pnSupplied; 250*2b6dfa00SMatt Spinler _flags &= ~maintProcSupplied; 251*2b6dfa00SMatt Spinler 252*2b6dfa00SMatt Spinler if (pel_values::symbolicFRUs.count(symbolicFRUFromRegistry)) 253*2b6dfa00SMatt Spinler { 254*2b6dfa00SMatt Spinler strncpy(_pnOrProcedureID.data(), 255*2b6dfa00SMatt Spinler pel_values::symbolicFRUs.at(symbolicFRUFromRegistry).c_str(), 256*2b6dfa00SMatt Spinler _pnOrProcedureID.size()); 257*2b6dfa00SMatt Spinler } 258*2b6dfa00SMatt Spinler else 259*2b6dfa00SMatt Spinler { 260*2b6dfa00SMatt Spinler log<level::ERR>("Invalid symbolic FRU", 261*2b6dfa00SMatt Spinler entry("FRU=%s", symbolicFRUFromRegistry.c_str())); 262*2b6dfa00SMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size()); 263*2b6dfa00SMatt Spinler } 264*2b6dfa00SMatt Spinler 265*2b6dfa00SMatt Spinler // ensure null terminated 266*2b6dfa00SMatt Spinler _pnOrProcedureID.back() = 0; 267*2b6dfa00SMatt Spinler } 268*2b6dfa00SMatt Spinler 269a906c940SMatt Spinler } // namespace src 270a906c940SMatt Spinler } // namespace pels 271a906c940SMatt Spinler } // namespace openpower 272