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 20468aab5fSMatt Spinler #include <fmt/format.h> 21468aab5fSMatt Spinler 22a27e2e50SMatt Spinler #include <phosphor-logging/log.hpp> 23a27e2e50SMatt Spinler 24a27e2e50SMatt Spinler using namespace phosphor::logging; 25a27e2e50SMatt Spinler 26a906c940SMatt Spinler namespace openpower 27a906c940SMatt Spinler { 28a906c940SMatt Spinler namespace pels 29a906c940SMatt Spinler { 30a906c940SMatt Spinler namespace src 31a906c940SMatt Spinler { 32a906c940SMatt Spinler 3318f4b6e8SMatt Spinler namespace 3418f4b6e8SMatt Spinler { 3518f4b6e8SMatt Spinler 3618f4b6e8SMatt Spinler /** 3718f4b6e8SMatt Spinler * @brief Fills in the std::array from the string value 3818f4b6e8SMatt Spinler * 3918f4b6e8SMatt Spinler * If the string is shorter than the array, it will be padded with 4018f4b6e8SMatt Spinler * '\0's. 4118f4b6e8SMatt Spinler * 4218f4b6e8SMatt Spinler * @param[in] source - The string to fill in the array with 4318f4b6e8SMatt Spinler * @param[out] target - The input object that supports [] and size() 4418f4b6e8SMatt Spinler */ 4518f4b6e8SMatt Spinler template <typename T> 4618f4b6e8SMatt Spinler void fillArray(const std::string& source, T& target) 4718f4b6e8SMatt Spinler { 4818f4b6e8SMatt Spinler for (size_t i = 0; i < target.size(); i++) 4918f4b6e8SMatt Spinler { 5018f4b6e8SMatt Spinler target[i] = (source.size() > i) ? source[i] : '\0'; 5118f4b6e8SMatt Spinler } 5218f4b6e8SMatt Spinler } 5318f4b6e8SMatt Spinler 54*d26fa3e7SPatrick Williams } // namespace 5518f4b6e8SMatt Spinler 56a906c940SMatt Spinler FRUIdentity::FRUIdentity(Stream& pel) 57a906c940SMatt Spinler { 58a906c940SMatt Spinler pel >> _type >> _size >> _flags; 59a906c940SMatt Spinler 60ba0ee002SMatt Spinler if (hasPN() || hasMP()) 61a906c940SMatt Spinler { 62a906c940SMatt Spinler pel.read(_pnOrProcedureID.data(), _pnOrProcedureID.size()); 63a906c940SMatt Spinler } 64a906c940SMatt Spinler 65ba0ee002SMatt Spinler if (hasCCIN()) 66a906c940SMatt Spinler { 67a906c940SMatt Spinler pel.read(_ccin.data(), _ccin.size()); 68a906c940SMatt Spinler } 69a906c940SMatt Spinler 70ba0ee002SMatt Spinler if (hasSN()) 71a906c940SMatt Spinler { 72a906c940SMatt Spinler pel.read(_sn.data(), _sn.size()); 73a906c940SMatt Spinler } 74a906c940SMatt Spinler } 75a906c940SMatt Spinler 76a09354b7SMatt Spinler size_t FRUIdentity::flattenedSize() const 77a09354b7SMatt Spinler { 78a09354b7SMatt Spinler size_t size = sizeof(_type) + sizeof(_size) + sizeof(_flags); 79a09354b7SMatt Spinler 80a09354b7SMatt Spinler if (hasPN() || hasMP()) 81a09354b7SMatt Spinler { 82a09354b7SMatt Spinler size += _pnOrProcedureID.size(); 83a09354b7SMatt Spinler } 84a09354b7SMatt Spinler 85a09354b7SMatt Spinler if (hasCCIN()) 86a09354b7SMatt Spinler { 87a09354b7SMatt Spinler size += _ccin.size(); 88a09354b7SMatt Spinler } 89a09354b7SMatt Spinler 90a09354b7SMatt Spinler if (hasSN()) 91a09354b7SMatt Spinler { 92a09354b7SMatt Spinler size += _sn.size(); 93a09354b7SMatt Spinler } 94a09354b7SMatt Spinler 95a09354b7SMatt Spinler return size; 96a09354b7SMatt Spinler } 97a09354b7SMatt Spinler 98ba0ee002SMatt Spinler FRUIdentity::FRUIdentity(const std::string& partNumber, const std::string& ccin, 99ba0ee002SMatt Spinler const std::string& serialNumber) 100ba0ee002SMatt Spinler { 101ba0ee002SMatt Spinler _type = substructureType; 102ba0ee002SMatt Spinler _flags = hardwareFRU; 103ba0ee002SMatt Spinler 104ba0ee002SMatt Spinler setPartNumber(partNumber); 105ba0ee002SMatt Spinler setCCIN(ccin); 106ba0ee002SMatt Spinler setSerialNumber(serialNumber); 107ba0ee002SMatt Spinler 108ba0ee002SMatt Spinler _size = flattenedSize(); 109ba0ee002SMatt Spinler } 110ba0ee002SMatt Spinler 111468aab5fSMatt Spinler FRUIdentity::FRUIdentity(const std::string& procedure, CalloutValueType type) 112ba0ee002SMatt Spinler { 113ba0ee002SMatt Spinler _type = substructureType; 114ba0ee002SMatt Spinler _flags = maintenanceProc; 115ba0ee002SMatt Spinler 116468aab5fSMatt Spinler setMaintenanceProcedure(procedure, type); 117ba0ee002SMatt Spinler 118ba0ee002SMatt Spinler _size = flattenedSize(); 119ba0ee002SMatt Spinler } 120ba0ee002SMatt Spinler 121468aab5fSMatt Spinler FRUIdentity::FRUIdentity(const std::string& fru, CalloutValueType type, 1222b6dfa00SMatt Spinler bool trustedLocationCode) 1232b6dfa00SMatt Spinler { 1242b6dfa00SMatt Spinler _type = substructureType; 1252b6dfa00SMatt Spinler _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU; 1262b6dfa00SMatt Spinler 127468aab5fSMatt Spinler setSymbolicFRU(fru, type); 1282b6dfa00SMatt Spinler 1292b6dfa00SMatt Spinler _size = flattenedSize(); 1302b6dfa00SMatt Spinler } 1312b6dfa00SMatt Spinler 132a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getPN() const 133a906c940SMatt Spinler { 134a906c940SMatt Spinler if (hasPN()) 135a906c940SMatt Spinler { 136a906c940SMatt Spinler // NULL terminated 137a906c940SMatt Spinler std::string pn{_pnOrProcedureID.data()}; 138a906c940SMatt Spinler return pn; 139a906c940SMatt Spinler } 140a906c940SMatt Spinler 141a906c940SMatt Spinler return std::nullopt; 142a906c940SMatt Spinler } 143a906c940SMatt Spinler 144a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getMaintProc() const 145a906c940SMatt Spinler { 146a906c940SMatt Spinler if (hasMP()) 147a906c940SMatt Spinler { 148a906c940SMatt Spinler // NULL terminated 149a906c940SMatt Spinler std::string mp{_pnOrProcedureID.data()}; 150a906c940SMatt Spinler return mp; 151a906c940SMatt Spinler } 152a906c940SMatt Spinler 153a906c940SMatt Spinler return std::nullopt; 154a906c940SMatt Spinler } 155a906c940SMatt Spinler 156a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getCCIN() const 157a906c940SMatt Spinler { 158a906c940SMatt Spinler if (hasCCIN()) 159a906c940SMatt Spinler { 160a906c940SMatt Spinler std::string ccin{_ccin.begin(), _ccin.begin() + _ccin.size()}; 161ba0ee002SMatt Spinler 162ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually) 163ba0ee002SMatt Spinler if (auto pos = ccin.find('\0'); pos != std::string::npos) 164ba0ee002SMatt Spinler { 165ba0ee002SMatt Spinler ccin.resize(pos); 166ba0ee002SMatt Spinler } 167a906c940SMatt Spinler return ccin; 168a906c940SMatt Spinler } 169a906c940SMatt Spinler 170a906c940SMatt Spinler return std::nullopt; 171a906c940SMatt Spinler } 172a906c940SMatt Spinler 173a906c940SMatt Spinler std::optional<std::string> FRUIdentity::getSN() const 174a906c940SMatt Spinler { 175a906c940SMatt Spinler if (hasSN()) 176a906c940SMatt Spinler { 177a906c940SMatt Spinler std::string sn{_sn.begin(), _sn.begin() + _sn.size()}; 178ba0ee002SMatt Spinler 179ba0ee002SMatt Spinler // Don't leave any NULLs in the string (not there usually) 180ba0ee002SMatt Spinler if (auto pos = sn.find('\0'); pos != std::string::npos) 181ba0ee002SMatt Spinler { 182ba0ee002SMatt Spinler sn.resize(pos); 183ba0ee002SMatt Spinler } 184a906c940SMatt Spinler return sn; 185a906c940SMatt Spinler } 186a906c940SMatt Spinler 187a906c940SMatt Spinler return std::nullopt; 188a906c940SMatt Spinler } 189a906c940SMatt Spinler 190724d0d8cSMatt Spinler void FRUIdentity::flatten(Stream& pel) const 191a906c940SMatt Spinler { 192a906c940SMatt Spinler pel << _type << _size << _flags; 193a906c940SMatt Spinler 194a906c940SMatt Spinler if (hasPN() || hasMP()) 195a906c940SMatt Spinler { 196a906c940SMatt Spinler pel.write(_pnOrProcedureID.data(), _pnOrProcedureID.size()); 197a906c940SMatt Spinler } 198a906c940SMatt Spinler 199a906c940SMatt Spinler if (hasCCIN()) 200a906c940SMatt Spinler { 201a906c940SMatt Spinler pel.write(_ccin.data(), _ccin.size()); 202a906c940SMatt Spinler } 203a906c940SMatt Spinler 204a906c940SMatt Spinler if (hasSN()) 205a906c940SMatt Spinler { 206a906c940SMatt Spinler pel.write(_sn.data(), _sn.size()); 207a906c940SMatt Spinler } 208a906c940SMatt Spinler } 209a906c940SMatt Spinler 210ba0ee002SMatt Spinler void FRUIdentity::setPartNumber(const std::string& partNumber) 211ba0ee002SMatt Spinler { 212ba0ee002SMatt Spinler _flags |= pnSupplied; 213ba0ee002SMatt Spinler _flags &= ~maintProcSupplied; 214ba0ee002SMatt Spinler 215ba0ee002SMatt Spinler auto pn = partNumber; 216ba0ee002SMatt Spinler 217ba0ee002SMatt Spinler // Strip leading whitespace on this one. 218ba0ee002SMatt Spinler while (' ' == pn.front()) 219ba0ee002SMatt Spinler { 220ba0ee002SMatt Spinler pn = pn.substr(1); 221ba0ee002SMatt Spinler } 222ba0ee002SMatt Spinler 22318f4b6e8SMatt Spinler fillArray(pn, _pnOrProcedureID); 224ba0ee002SMatt Spinler 225ba0ee002SMatt Spinler // ensure null terminated 226ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0; 227ba0ee002SMatt Spinler } 228ba0ee002SMatt Spinler 229ba0ee002SMatt Spinler void FRUIdentity::setCCIN(const std::string& ccin) 230ba0ee002SMatt Spinler { 231ba0ee002SMatt Spinler _flags |= ccinSupplied; 232ba0ee002SMatt Spinler 23318f4b6e8SMatt Spinler fillArray(ccin, _ccin); 234ba0ee002SMatt Spinler } 235ba0ee002SMatt Spinler 236ba0ee002SMatt Spinler void FRUIdentity::setSerialNumber(const std::string& serialNumber) 237ba0ee002SMatt Spinler { 238ba0ee002SMatt Spinler _flags |= snSupplied; 239ba0ee002SMatt Spinler 24018f4b6e8SMatt Spinler fillArray(serialNumber, _sn); 241ba0ee002SMatt Spinler } 242ba0ee002SMatt Spinler 243468aab5fSMatt Spinler void FRUIdentity::setMaintenanceProcedure(const std::string& procedure, 244468aab5fSMatt Spinler CalloutValueType type) 245ba0ee002SMatt Spinler { 246ba0ee002SMatt Spinler _flags |= maintProcSupplied; 247ba0ee002SMatt Spinler _flags &= ~pnSupplied; 248ba0ee002SMatt Spinler 249468aab5fSMatt Spinler if (type == CalloutValueType::registryName) 250a27e2e50SMatt Spinler { 251468aab5fSMatt Spinler if (pel_values::maintenanceProcedures.count(procedure)) 252468aab5fSMatt Spinler { 253468aab5fSMatt Spinler fillArray(pel_values::maintenanceProcedures.at(procedure), 25418f4b6e8SMatt Spinler _pnOrProcedureID); 255a27e2e50SMatt Spinler } 256a27e2e50SMatt Spinler else 257a27e2e50SMatt Spinler { 258468aab5fSMatt Spinler log<level::ERR>( 259468aab5fSMatt Spinler fmt::format("Invalid maintenance procedure {}", procedure) 260468aab5fSMatt Spinler .c_str()); 261468aab5fSMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID", 262468aab5fSMatt Spinler _pnOrProcedureID.size()); 263468aab5fSMatt Spinler } 264468aab5fSMatt Spinler } 265468aab5fSMatt Spinler else 266468aab5fSMatt Spinler { 267468aab5fSMatt Spinler fillArray(procedure, _pnOrProcedureID); 268a27e2e50SMatt Spinler } 269ba0ee002SMatt Spinler 270ba0ee002SMatt Spinler // ensure null terminated 271ba0ee002SMatt Spinler _pnOrProcedureID.back() = 0; 272ba0ee002SMatt Spinler } 273ba0ee002SMatt Spinler 274468aab5fSMatt Spinler void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRU, 275468aab5fSMatt Spinler CalloutValueType type) 2762b6dfa00SMatt Spinler { 2772b6dfa00SMatt Spinler 2782b6dfa00SMatt Spinler // Treat this has a HW callout. 2792b6dfa00SMatt Spinler _flags |= pnSupplied; 2802b6dfa00SMatt Spinler _flags &= ~maintProcSupplied; 2812b6dfa00SMatt Spinler 282468aab5fSMatt Spinler if (type == CalloutValueType::registryName) 2832b6dfa00SMatt Spinler { 284468aab5fSMatt Spinler if (pel_values::symbolicFRUs.count(symbolicFRU)) 285468aab5fSMatt Spinler { 286468aab5fSMatt Spinler fillArray(pel_values::symbolicFRUs.at(symbolicFRU), 28718f4b6e8SMatt Spinler _pnOrProcedureID); 2882b6dfa00SMatt Spinler } 2892b6dfa00SMatt Spinler else 2902b6dfa00SMatt Spinler { 2912b6dfa00SMatt Spinler log<level::ERR>("Invalid symbolic FRU", 292468aab5fSMatt Spinler entry("FRU=%s", symbolicFRU.c_str())); 293468aab5fSMatt Spinler strncpy(_pnOrProcedureID.data(), "INVALID", 294468aab5fSMatt Spinler _pnOrProcedureID.size()); 295468aab5fSMatt Spinler } 296468aab5fSMatt Spinler } 297468aab5fSMatt Spinler else 298468aab5fSMatt Spinler { 299468aab5fSMatt Spinler fillArray(symbolicFRU, _pnOrProcedureID); 3002b6dfa00SMatt Spinler } 3012b6dfa00SMatt Spinler 3022b6dfa00SMatt Spinler // ensure null terminated 3032b6dfa00SMatt Spinler _pnOrProcedureID.back() = 0; 3042b6dfa00SMatt Spinler } 3052b6dfa00SMatt Spinler 306a906c940SMatt Spinler } // namespace src 307a906c940SMatt Spinler } // namespace pels 308a906c940SMatt Spinler } // namespace openpower 309