/* // Copyright (c) 2018 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #pragma once #include #include #include static constexpr const char* mdrDefaultFile = "/var/lib/smbios/smbios2"; static constexpr uint16_t mdrSMBIOSSize = 32 * 1024; constexpr uint16_t smbiosAgentId = 0x0101; constexpr int firstAgentIndex = 1; constexpr uint8_t maxDirEntries = 4; constexpr uint32_t mdr2SMSize = 0x00100000; constexpr uint32_t mdr2SMBaseAddress = 0x9FF00000; constexpr uint8_t mdrDirVersion = 1; constexpr uint8_t mdrTypeII = 2; constexpr uint8_t mdr2Version = 2; constexpr uint8_t smbiosAgentVersion = 1; constexpr uint8_t smbiosDirVersion = 1; constexpr uint32_t pageMask = 0xf000; constexpr int smbiosDirIndex = 0; constexpr uint32_t smbiosTableVersion = 15; constexpr uint32_t smbiosTableTimestamp = 0x45464748; constexpr uint32_t smbiosSMMemoryOffset = 0; constexpr uint32_t smbiosSMMemorySize = 1024 * 1024; constexpr uint32_t smbiosTableStorageSize = 64 * 1024; constexpr uint32_t defaultTimeout = 2'000'000; // 2-seconds. enum class MDR2SMBIOSStatusEnum { mdr2Init = 0, mdr2Loaded = 1, mdr2Updated = 2, mdr2Updating = 3 }; enum class MDR2DirLockEnum { mdr2DirUnlock = 0, mdr2DirLock = 1 }; enum class DirDataRequestEnum { dirDataNotRequested = 0x00, dirDataRequested = 0x01 }; enum class FlagStatus { flagIsInvalid = 0, flagIsValid = 1, flagIsLocked = 2 }; typedef struct { uint8_t dataInfo[16]; } DataIdStruct; typedef struct { DataIdStruct id; uint32_t size; uint32_t dataSetSize; uint8_t dataVersion; uint32_t timestamp; } Mdr2DirEntry; typedef struct { Mdr2DirEntry common; MDR2SMBIOSStatusEnum stage; MDR2DirLockEnum lock; uint16_t lockHandle; uint32_t xferBuff; uint32_t xferSize; uint32_t maxDataSize; uint8_t* dataStorage; } Mdr2DirLocalStruct; typedef struct { uint8_t agentVersion; uint8_t dirVersion; uint8_t dirEntries; uint8_t status; // valid / locked / etc uint8_t remoteDirVersion; uint16_t sessionHandle; Mdr2DirLocalStruct dir[maxDirEntries]; } Mdr2DirStruct; struct MDRSMBIOSHeader { uint8_t dirVer; uint8_t mdrType; uint32_t timestamp; uint32_t dataSize; } __attribute__((packed)); typedef struct { uint8_t majorVersion; uint8_t minorVersion; } SMBIOSVersion; struct EntryPointStructure21 { uint32_t anchorString; uint8_t epChecksum; uint8_t epLength; SMBIOSVersion smbiosVersion; uint16_t maxStructSize; uint8_t epRevision; uint8_t formattedArea[5]; uint8_t intermediateAnchorString[5]; uint8_t intermediateChecksum; uint16_t structTableLength; uint32_t structTableAddress; uint16_t noOfSmbiosStruct; uint8_t smbiosBDCRevision; } __attribute__((packed)); struct EntryPointStructure30 { uint8_t anchorString[5]; uint8_t epChecksum; uint8_t epLength; SMBIOSVersion smbiosVersion; uint8_t smbiosDocRev; uint8_t epRevision; uint8_t reserved; uint32_t structTableMaxSize; uint64_t structTableAddr; } __attribute__((packed)); static constexpr const char* cpuSuffix = "/chassis/motherboard/cpu"; static constexpr const char* dimmSuffix = "/chassis/motherboard/dimm"; static constexpr const char* pcieSuffix = "/chassis/motherboard/pcieslot"; static constexpr const char* systemSuffix = "/chassis/motherboard/bios"; constexpr std::array supportedSMBIOSVersions{ SMBIOSVersion{3, 0}, SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3}, SMBIOSVersion{3, 4}, SMBIOSVersion{3, 5}, SMBIOSVersion{3, 6}, SMBIOSVersion{3, 7}}; typedef enum { biosType = 0, systemType = 1, baseboardType = 2, chassisType = 3, processorsType = 4, memoryControllerType = 5, memoryModuleInformationType = 6, cacheType = 7, portConnectorType = 8, systemSlots = 9, onBoardDevicesType = 10, oemStringsType = 11, systemCconfigurationOptionsType = 12, biosLanguageType = 13, groupAssociatonsType = 14, systemEventLogType = 15, physicalMemoryArrayType = 16, memoryDeviceType = 17, } SmbiosType; static constexpr uint8_t separateLen = 2; static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn) { if (smbiosDataIn == nullptr) { return nullptr; } uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1); int len = 0; while ((*smbiosData | *(smbiosData + 1)) != 0) { smbiosData++; len++; if (len >= mdrSMBIOSSize) // To avoid endless loop { return nullptr; } } return smbiosData + separateLen; } // When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData // to smbiosDataIn static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId, size_t size = 0) { if (smbiosDataIn == nullptr) { return nullptr; } char* smbiosData = reinterpret_cast(smbiosDataIn); while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) { uint32_t len = *(smbiosData + 1); if (*smbiosData != typeId) { smbiosData += len; while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) { smbiosData++; len++; if (len >= mdrSMBIOSSize) // To avoid endless loop { return nullptr; } } smbiosData += separateLen; continue; } if (len < size) { phosphor::logging::log( "Record size mismatch!"); return nullptr; } return reinterpret_cast(smbiosData); } return nullptr; } static inline std::string positionToString(uint8_t positionNum, uint8_t structLen, uint8_t* dataIn) { if (dataIn == nullptr || positionNum == 0) { return ""; } uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop char* target = reinterpret_cast(dataIn + structLen); if (target == nullptr) { return ""; } for (uint8_t index = 1; index < positionNum; index++) { for (; *target != '\0'; target++) { limit--; // When target = dataIn + structLen + limit, // following target++ will be nullptr if (limit < 1 || target == nullptr) { return ""; } } target++; if (target == nullptr || *target == '\0') { return ""; // 0x00 0x00 means end of the entry. } } std::string result = target; return result; }