+/** @file\r
+\r
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>\r
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>\r
+ Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include "SmbiosMisc.h"\r
+\r
+\r
+typedef struct {\r
+ CONST CHAR8* MonthStr;\r
+ UINT32 MonthInt;\r
+} MONTH_DESCRIPTION;\r
+\r
+STATIC CONST\r
+MONTH_DESCRIPTION mMonthDescription[] = {\r
+ { "Jan", 1 },\r
+ { "Feb", 2 },\r
+ { "Mar", 3 },\r
+ { "Apr", 4 },\r
+ { "May", 5 },\r
+ { "Jun", 6 },\r
+ { "Jul", 7 },\r
+ { "Aug", 8 },\r
+ { "Sep", 9 },\r
+ { "Oct", 10 },\r
+ { "Nov", 11 },\r
+ { "Dec", 12 },\r
+ { "???", 1 }, // Use 1 as default month\r
+};\r
+\r
+/**\r
+ Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'\r
+ as the unit.\r
+\r
+ @param Value Pointer to Base2_Data\r
+\r
+ @retval\r
+\r
+**/\r
+UINT8\r
+Base2ToByteWith64KUnit (\r
+ IN UINTN Value\r
+ )\r
+{\r
+ UINT8 Size;\r
+\r
+ Size = ((Value + (SIZE_64KB - 1)) >> 16);\r
+\r
+ return Size;\r
+}\r
+\r
+/**\r
+ Returns the date and time this file (and firmware) was built.\r
+\r
+ @param[out] *Time Pointer to the EFI_TIME structure to fill in.\r
+**/\r
+VOID\r
+GetReleaseTime (\r
+ OUT EFI_TIME *Time\r
+ )\r
+{\r
+ CONST CHAR8 *ReleaseDate = __DATE__;\r
+ CONST CHAR8 *ReleaseTime = __TIME__;\r
+ UINTN i;\r
+\r
+ for (i = 0; i < 12; i++) {\r
+ if (AsciiStrnCmp (ReleaseDate, mMonthDescription[i].MonthStr, 3) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ Time->Month = mMonthDescription[i].MonthInt;\r
+ Time->Day = AsciiStrDecimalToUintn (ReleaseDate + 4);\r
+ Time->Year = AsciiStrDecimalToUintn (ReleaseDate + 7);\r
+ Time->Hour = AsciiStrDecimalToUintn (ReleaseTime);\r
+ Time->Minute = AsciiStrDecimalToUintn (ReleaseTime + 3);\r
+ Time->Second = AsciiStrDecimalToUintn (ReleaseTime + 6);\r
+}\r
+\r
+/**\r
+ Fetches the firmware ('BIOS') release date from the\r
+ FirmwareVersionInfo HOB.\r
+\r
+ @return The release date as a UTF-16 string\r
+**/\r
+CHAR16 *\r
+GetBiosReleaseDate (\r
+ VOID\r
+ )\r
+{\r
+ CHAR16 *ReleaseDate;\r
+ EFI_TIME BuildTime;\r
+\r
+ ReleaseDate = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);\r
+ if (ReleaseDate == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ GetReleaseTime (&BuildTime);\r
+\r
+ (VOID)UnicodeSPrintAsciiFormat (ReleaseDate,\r
+ (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH,\r
+ "%02d/%02d/%4d",\r
+ BuildTime.Month,\r
+ BuildTime.Day,\r
+ BuildTime.Year\r
+ );\r
+\r
+ return ReleaseDate;\r
+}\r
+\r
+/**\r
+ Fetches the firmware ('BIOS') version from the\r
+ FirmwareVersionInfo HOB.\r
+\r
+ @return The version as a UTF-16 string\r
+**/\r
+CHAR16 *\r
+GetBiosVersion (\r
+ VOID\r
+ )\r
+{\r
+ CHAR16 *ReleaseString;\r
+\r
+ ReleaseString = (CHAR16 *)FixedPcdGetPtr (PcdFirmwareVersionString);\r
+\r
+ return ReleaseString;\r
+}\r
+\r
+\r
+/**\r
+ This function makes boot time changes to the contents of the\r
+ MiscBiosVendor (Type 0) record.\r
+\r
+ @param RecordData Pointer to SMBIOS table with default values.\r
+ @param Smbios SMBIOS protocol.\r
+\r
+ @retval EFI_SUCCESS The SMBIOS table was successfully added.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate required memory.\r
+\r
+**/\r
+SMBIOS_MISC_TABLE_FUNCTION (MiscBiosVendor)\r
+{\r
+ CHAR8 *OptionalStrStart;\r
+ CHAR8 *StrStart;\r
+ UINTN VendorStrLen;\r
+ UINTN VerStrLen;\r
+ UINTN DateStrLen;\r
+ UINTN BiosPhysicalSize;\r
+ CHAR16 *Vendor;\r
+ CHAR16 *Version;\r
+ CHAR16 *ReleaseDate;\r
+ CHAR16 *Char16String;\r
+ EFI_STATUS Status;\r
+ EFI_STRING_ID TokenToUpdate;\r
+ EFI_STRING_ID TokenToGet;\r
+ SMBIOS_TABLE_TYPE0 *SmbiosRecord;\r
+ SMBIOS_TABLE_TYPE0 *InputData;\r
+\r
+ //\r
+ // First check for invalid parameters.\r
+ //\r
+ if (RecordData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ InputData = (SMBIOS_TABLE_TYPE0 *)RecordData;\r
+\r
+ Vendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);\r
+\r
+ if (StrLen (Vendor) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VENDOR);\r
+ HiiSetString (mSmbiosMiscHiiHandle, TokenToUpdate, Vendor, NULL);\r
+ }\r
+\r
+ Version = GetBiosVersion();\r
+\r
+ if (StrLen (Version) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);\r
+ HiiSetString (mSmbiosMiscHiiHandle, TokenToUpdate, Version, NULL);\r
+ } else {\r
+ Version = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);\r
+ if (StrLen (Version) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);\r
+ HiiSetString (mSmbiosMiscHiiHandle, TokenToUpdate, Version, NULL);\r
+ }\r
+ }\r
+\r
+ Char16String = GetBiosReleaseDate ();\r
+ if (StrLen(Char16String) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);\r
+ HiiSetString (mSmbiosMiscHiiHandle, TokenToUpdate, Char16String, NULL);\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);\r
+ Vendor = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);\r
+ VendorStrLen = StrLen (Vendor);\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);\r
+ Version = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);\r
+ VerStrLen = StrLen (Version);\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);\r
+ ReleaseDate = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);\r
+ DateStrLen = StrLen (ReleaseDate);\r
+\r
+ //\r
+ // Now update the BiosPhysicalSize\r
+ //\r
+ BiosPhysicalSize = FixedPcdGet32 (PcdFdSize);\r
+\r
+ //\r
+ // Two zeros following the last string.\r
+ //\r
+ SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 +\r
+ VerStrLen + 1 +\r
+ DateStrLen + 1 + 1);\r
+ if (SmbiosRecord == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE0));\r
+\r
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);\r
+ SmbiosRecord->BiosSegment = (UINT16)(FixedPcdGet32 (PcdFdBaseAddress) / SIZE_64KB);\r
+ if (BiosPhysicalSize < SIZE_16MB) {\r
+ SmbiosRecord->BiosSize = Base2ToByteWith64KUnit (BiosPhysicalSize) - 1;\r
+ SmbiosRecord->ExtendedBiosSize.Size = BiosPhysicalSize / SIZE_1MB;\r
+ SmbiosRecord->ExtendedBiosSize.Unit = 0; // Size is in MB\r
+ } else {\r
+ SmbiosRecord->BiosSize = 0xFF;\r
+ if (BiosPhysicalSize > 0x3FFF) {\r
+ SmbiosRecord->ExtendedBiosSize.Size = BiosPhysicalSize / SIZE_1GB;\r
+ SmbiosRecord->ExtendedBiosSize.Unit = 1; // Size is in GB\r
+ }\r
+ }\r
+\r
+ SmbiosRecord->SystemBiosMajorRelease = (UINT8) (PcdGet16 (PcdSystemBiosRelease) >> 8);\r
+ SmbiosRecord->SystemBiosMinorRelease = (UINT8) (PcdGet16 (PcdSystemBiosRelease) & 0xFF);\r
+\r
+ SmbiosRecord->EmbeddedControllerFirmwareMajorRelease = (UINT16)\r
+ (PcdGet16 (PcdEmbeddedControllerFirmwareRelease) >> 8);\r
+ SmbiosRecord->EmbeddedControllerFirmwareMinorRelease = (UINT16)\r
+ (PcdGet16 (PcdEmbeddedControllerFirmwareRelease) & 0xFF);\r
+\r
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
+ UnicodeStrToAsciiStrS (Vendor, OptionalStrStart, VendorStrLen + 1);\r
+ StrStart = OptionalStrStart + VendorStrLen + 1;\r
+ UnicodeStrToAsciiStrS (Version, StrStart, VerStrLen + 1);\r
+ StrStart += VerStrLen + 1;\r
+ UnicodeStrToAsciiStrS (ReleaseDate, StrStart, DateStrLen + 1);\r
+ //\r
+ // Now we have got the full smbios record, call smbios protocol to add this record.\r
+ //\r
+ Status = SmbiosMiscAddRecord ((UINT8*)SmbiosRecord, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type00 Table Log Failed! %r \n",\r
+ __FUNCTION__, __LINE__, Status));\r
+ }\r
+\r
+ FreePool (SmbiosRecord);\r
+\r
+Exit:\r
+ if (Vendor != NULL) {\r
+ FreePool (Vendor);\r
+ }\r
+\r
+ if (Version != NULL) {\r
+ FreePool (Version);\r
+ }\r
+\r
+ if (ReleaseDate != NULL) {\r
+ FreePool (ReleaseDate);\r
+ }\r
+\r
+ if (Char16String != NULL) {\r
+ FreePool (Char16String);\r
+ }\r
+\r
+ return Status;\r
+}\r