blob: e77abf4a2b3fadd3779930d606bf579286d428bf [file] [log] [blame]
/*
// 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 <phosphor-logging/elog-errors.hpp>
#include <array>
static constexpr const char* mdrType2File = "/var/lib/smbios/smbios2";
static constexpr const char* smbiosPath = "/var/lib/smbios";
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 = 20000;
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* cpuPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu";
static constexpr const char* dimmPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm";
static constexpr const char* pciePath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot";
static constexpr const char* systemPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/bios";
constexpr std::array<SMBIOSVersion, 3> supportedSMBIOSVersions{
SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3}, SMBIOSVersion{3, 5}};
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<char*>(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<phosphor::logging::level::ERR>(
"Record size mismatch!");
return nullptr;
}
return reinterpret_cast<uint8_t*>(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<char*>(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;
}