diff --git a/MdeModulePkg/Application/UiApp/FrontPage.c b/MdeModulePkg/Application/UiApp/FrontPage.c index abb19dcdd2..36cbee7428 100644 --- a/MdeModulePkg/Application/UiApp/FrontPage.c +++ b/MdeModulePkg/Application/UiApp/FrontPage.c @@ -7,6 +7,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ +#include +#include +#include +#include +#include +#include +#include + #include "FrontPage.h" #include "FrontPageCustomizedUi.h" @@ -33,6 +41,8 @@ UINT32 mSetupTextModeRow = 0; UINT32 mSetupHorizontalResolution = 0; UINT32 mSetupVerticalResolution = 0; +EFI_SYSTEM_TABLE * gSystemTable = NULL; + FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = { FRONT_PAGE_CALLBACK_DATA_SIGNATURE, NULL, @@ -563,6 +573,386 @@ WarnNoBootableMedia ( FreePool(String); } +BOOLEAN +StandardSignatureIsAuthenticAMD ( + VOID + ) +{ + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; + + AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx); + return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_AMD_EBX && + RegEcx == CPUID_SIGNATURE_AUTHENTIC_AMD_ECX && + RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX); +} + +BOOLEAN +StandardSignatureIsGenuineIntel ( + VOID + ) +{ + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; + + AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx); + return (RegEbx == CPUID_SIGNATURE_GENUINE_INTEL_EBX && + RegEcx == CPUID_SIGNATURE_GENUINE_INTEL_ECX && + RegEdx == CPUID_SIGNATURE_GENUINE_INTEL_EDX); +} + +typedef struct { + CHAR8 Signature[8]; + UINT8 Checksum; + CHAR8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; +} ACPI_RSDP; + +CHAR8 RSDP_SIGNATURE[8] = {'R', 'S', 'D', ' ', 'P', 'T', 'R', ' '}; + +typedef struct { + CHAR8 Signature[4]; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + CHAR8 OemId[6]; + CHAR8 OemTableId[8]; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} ACPI_SDT_HEADER; + +CHAR8 RSDT_SIGNATURE[4] = {'R', 'S', 'D', 'T'}; + +STATIC ACPI_SDT_HEADER* FindAcpiTable(CHAR8 Name[4]) { + UINTN Index; + EFI_CONFIGURATION_TABLE* ConfigurationTable; + UINTN RsdpPtr; + ACPI_RSDP* Rsdp; + UINTN RsdtPtr; + ACPI_SDT_HEADER* Rsdt; + UINTN TablePtr; + ACPI_SDT_HEADER* Table; + + DEBUG ((EFI_D_INFO, "FindAcpiTable: '%c%c%c%c'\n", + Name[0], + Name[1], + Name[2], + Name[3] + )); + + if (gSystemTable == NULL) { + DEBUG ((EFI_D_INFO, " System Table missing\n")); + return NULL; + } + + // Search the table for an entry that matches the ACPI Table Guid + for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) { + if (CompareGuid (&gEfiAcpiTableGuid, &(gSystemTable->ConfigurationTable[Index].VendorGuid))) { + ConfigurationTable = &gSystemTable->ConfigurationTable[Index]; + break; + } + } + + if (ConfigurationTable == NULL) { + DEBUG ((EFI_D_INFO, " ACPI Configuration Table missing\n")); + return NULL; + } + + RsdpPtr = (UINTN)ConfigurationTable->VendorTable; + DEBUG ((EFI_D_INFO, " RSDP 0x%x\n", RsdpPtr)); + Rsdp = (ACPI_RSDP*)RsdpPtr; + DEBUG ((EFI_D_INFO, " Signature: '%c%c%c%c%c%c%c%c'\n", + Rsdp->Signature[0], + Rsdp->Signature[1], + Rsdp->Signature[2], + Rsdp->Signature[3], + Rsdp->Signature[4], + Rsdp->Signature[5], + Rsdp->Signature[6], + Rsdp->Signature[7] + )); + if (CompareMem(Rsdp->Signature, RSDP_SIGNATURE, 8) != 0) { + DEBUG ((EFI_D_INFO, " RSDP invalid signature\n")); + return NULL; + } + DEBUG ((EFI_D_INFO, " Revision: 0x%x\n", Rsdp->Revision)); + + RsdtPtr = (UINTN)Rsdp->RsdtAddress; + DEBUG ((EFI_D_INFO, " RSDT 0x%x\n", RsdpPtr)); + Rsdt = (ACPI_SDT_HEADER*)RsdtPtr; + DEBUG ((EFI_D_INFO, " Signature: '%c%c%c%c'\n", + Rsdt->Signature[0], + Rsdt->Signature[1], + Rsdt->Signature[2], + Rsdt->Signature[3] + )); + if (CompareMem(Rsdt->Signature, RSDT_SIGNATURE, 4) != 0) { + DEBUG ((EFI_D_INFO, " RSDT invalid signature\n")); + return NULL; + } + DEBUG ((EFI_D_INFO, " Revision: 0x%x\n", Rsdt->Revision)); + DEBUG ((EFI_D_INFO, " Length: 0x%x\n", Rsdt->Length)); + + for (Index = sizeof(ACPI_SDT_HEADER); Index < Rsdt->Length; Index += 4) { + TablePtr = (UINTN)(*(UINT32*)(RsdtPtr + Index)); + DEBUG ((EFI_D_INFO, " Table %d: 0x%x\n", Index, TablePtr)); + Table = (ACPI_SDT_HEADER*)TablePtr; + DEBUG ((EFI_D_INFO, " Signature: '%c%c%c%c'\n", + Table->Signature[0], + Table->Signature[1], + Table->Signature[2], + Table->Signature[3] + )); + DEBUG ((EFI_D_INFO, " Revision: 0x%x\n", Table->Revision)); + DEBUG ((EFI_D_INFO, " Length: 0x%x\n", Table->Length)); + + if (CompareMem(Table->Signature, Name, 4) == 0) { + DEBUG ((EFI_D_INFO, " Match found\n")); + return Table; + } + } + + DEBUG ((EFI_D_INFO, " No match found\n")); + return NULL; +} + +// From PciBusDxe +STATIC +EFI_STATUS +PciDevicePresent( + OUT PCI_TYPE00 *Pci, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func + ) +{ + UINT64 Address = EFI_PCI_ADDRESS(Bus, Device, Func, 0); + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_STATUS Status; + EFI_HANDLE *PciIoBuffer; + UINTN PciIoHandleCount = 0; + + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &PciIoHandleCount, + &PciIoBuffer + ); + + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_INFO, "%a: Failed to get PciRootBridgeIo handles: %r\n", __FUNCTION__, Status)); + return Status; + } + + for (UINTN Index = 0; Index < PciIoHandleCount; Index++) { + Status = gBS->OpenProtocol( + PciIoBuffer[Index], + &gEfiPciRootBridgeIoProtocolGuid, + (VOID *)&PciRootBridgeIo, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_INFO, "%a: Failed to open PciRootBridgeIo protocol: %r\n", __FUNCTION__, Status)); + continue; + } + + // Read the Vendor ID register + Status = PciRootBridgeIo->Pci.Read( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + Pci + ); + + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_INFO, "%a: Failed to read vendor ID: %r\n", __FUNCTION__, Status)); + continue; + } + + // Read the entire config header for the device + Status = PciRootBridgeIo->Pci.Read( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + sizeof(PCI_TYPE00) / sizeof(UINT32), + Pci + ); + + FreePool(PciIoBuffer); + return Status; + } + + FreePool(PciIoBuffer); + return EFI_NOT_FOUND; +} + +/* + * Check for Intel device with class [0780] at 00:16.0. + */ +STATIC +BOOLEAN +HasCsmeDevice(VOID) +{ + PCI_TYPE00 Pci; + + if (!EFI_ERROR(PciDevicePresent(&Pci, 0x00, 0x16, 0x00))) { + DEBUG((EFI_D_INFO, "%a: vid=0x%04X, class=[%02X,%02X,%02X]\n", __FUNCTION__, + Pci.Hdr.VendorId, Pci.Hdr.ClassCode[0], Pci.Hdr.ClassCode[1], Pci.Hdr.ClassCode[2])); + return Pci.Hdr.VendorId == 0x8086 && + Pci.Hdr.ClassCode[2] == PCI_CLASS_SCC && + Pci.Hdr.ClassCode[1] == PCI_SUBCLASS_SCC_OTHER; + } + + return FALSE; +} + +STATIC VOID FirmwareConfigurationInformation(VOID) { + EFI_STRING_ID Token; + + Token = STRING_TOKEN (STR_VIRTUALIZATION); + if (StandardSignatureIsGenuineIntel()) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"Intel Virtualization", NULL); + + Token = STRING_TOKEN (STR_VIRTUALIZATION_STATUS); + CPUID_VERSION_INFO_ECX VersionInfoEcx; + AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL); + if (VersionInfoEcx.Bits.VMX) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"VT-x: Active", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"VT-x: Deactivated", NULL); + } + + Token = STRING_TOKEN (STR_IOMMU_STATUS); + CHAR8 TableName[4] = {'D', 'M', 'A', 'R'}; + if (FindAcpiTable(TableName)) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"VT-d: Active", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"VT-d: Deactivated", NULL); + } + + Token = STRING_TOKEN(STR_ME_STATUS); + if (HasCsmeDevice()) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"The Intel Management Engine is enabled.", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"The Intel Management Engine is disabled at runtime to increase security.", NULL); + } + } else if (StandardSignatureIsAuthenticAMD()) { + //TODO: verify AMD tests + + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"AMD Virtualization", NULL); + + Token = STRING_TOKEN (STR_VIRTUALIZATION_STATUS); + CPUID_AMD_EXTENDED_CPU_SIG_ECX AmdExtendedCpuSigEcx; + AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, &AmdExtendedCpuSigEcx.Uint32, NULL); + if (AmdExtendedCpuSigEcx.Bits.SVM) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"AMD-V: Active", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"AMD-V: Deactivated", NULL); + } + + Token = STRING_TOKEN (STR_IOMMU_STATUS); + //TODO: proper test for AMD IOMMU + BOOLEAN iommu_active = FALSE; + if (iommu_active) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"AMD-Vi: Active", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"AMD-Vi: Deactivated", NULL); + } + } + + Token = STRING_TOKEN (STR_TPM_STATUS); + CHAR8 TableName[4] = {'T', 'P', 'M', '2'}; + if (FindAcpiTable(TableName)) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"Trusted Platform Module: Active", NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"Trusted Platform Module: Deactivated", NULL); + } +} + +VOID WebcamStatus(VOID) { + EFI_STATUS Status; + UINTN UsbIoHandleCount; + EFI_HANDLE *UsbIoBuffer; + UINTN Index; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_DEVICE_DESCRIPTOR DevDesc; + EFI_USB_INTERFACE_DESCRIPTOR IntfDesc; + UINTN Webcams; + EFI_STRING_ID Token; + + // + // Get all Usb IO handles in system + // + UsbIoHandleCount = 0; + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "Failed to read UsbIo handles: 0x%x\n", Status)); + return; + } + + Webcams = 0; + for (Index = 0; Index < UsbIoHandleCount; Index++) { + DEBUG ((EFI_D_INFO, "UsbIo Handle %d\n", Index)); + + // + // Get the child Usb IO interface + // + Status = gBS->HandleProtocol( + UsbIoBuffer[Index], + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " Failed to find UsbIo protocol\n")); + continue; + } + + Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " Failed to get device descriptor\n")); + continue; + } + + DEBUG ((EFI_D_INFO, " ID: 0x%04X:0x%04X\n", DevDesc.IdVendor, DevDesc.IdProduct)); + DEBUG ((EFI_D_INFO, " DeviceClass: %d\n", DevDesc.DeviceClass)); + DEBUG ((EFI_D_INFO, " DeviceSubClass: %d\n", DevDesc.DeviceSubClass)); + DEBUG ((EFI_D_INFO, " DeviceProtocol: %d\n", DevDesc.DeviceProtocol)); + + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IntfDesc); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " Failed to get interface descriptor\n")); + continue; + } + + DEBUG ((EFI_D_INFO, " Interface: %d\n", IntfDesc.InterfaceNumber)); + DEBUG ((EFI_D_INFO, " InterfaceClass: %d\n", IntfDesc.InterfaceClass)); + DEBUG ((EFI_D_INFO, " InterfaceSubClass: %d\n", IntfDesc.InterfaceSubClass)); + DEBUG ((EFI_D_INFO, " InterfaceProtocol: %d\n", IntfDesc.InterfaceProtocol)); + + if (IntfDesc.InterfaceClass == 14 && IntfDesc.InterfaceSubClass == 1) { + DEBUG ((EFI_D_INFO, " Detected Video Control interface\n")); + Webcams++; + } + } + + FreePool (UsbIoBuffer); + + //TODO: logic for not showing the warning on desktops + Token = STRING_TOKEN (STR_WEBCAM_STATUS); + if (Webcams == 0) { + HiiSetString (gFrontPagePrivate.HiiHandle, Token, L"Info: Webcam Module Disconnected", NULL); + } +} + /** Update the banner information for the Front Page based on Smbios information. @@ -579,7 +969,9 @@ UpdateFrontPageBannerStrings ( SMBIOS_TABLE_ENTRY_POINT *EntryPoint; SMBIOS_STRUCTURE_POINTER SmbiosTable; + FirmwareConfigurationInformation(); WarnNoBootableMedia (); + WebcamStatus(); Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &Table); if (EFI_ERROR (Status) || Table == NULL) { @@ -892,6 +1284,8 @@ InitializeUserInterface ( UINTN BootTextColumn; UINTN BootTextRow; + gSystemTable = SystemTable; + if (!mModeInitialized) { // // After the console is ready, get current video resolution @@ -1097,4 +1491,3 @@ SetupResetReminder ( gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } } - diff --git a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni index 1ca0a21729..8370ecb1d4 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni +++ b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni @@ -14,8 +14,15 @@ #string STR_FRONT_PAGE_TITLE #language en-US "Front Page" #string STR_FRONT_PAGE_COMPUTER_MODEL #language en-US "" #string STR_FRONT_PAGE_BIOS_VERSION #language en-US "" +#string STR_FIRMWARE_INFO #language en-US "Firmware Configuration Information" #string STR_BOOT_DEFAULT_PROMPT #language en-US "Boot Default" #string STR_BOOT_DEFAULT_HELP #language en-US "Boot the default entry" #string STR_MISSING_STRING #language en-US "Missing String" #string STR_NO_BOOTABLE_MEDIA #language en-US "" +#string STR_WEBCAM_STATUS #language en-US "" #string STR_EMPTY_STRING #language en-US "" +#string STR_VIRTUALIZATION #language en-US "" +#string STR_VIRTUALIZATION_STATUS #language en-US "" +#string STR_IOMMU_STATUS #language en-US "" +#string STR_TPM_STATUS #language en-US "" +#string STR_ME_STATUS #language en-US "" diff --git a/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr index dc3fd383fb..39fd87f135 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr +++ b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr @@ -10,6 +10,7 @@ #define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } #define FRONT_PAGE_FORM_ID 0x7600 +#define FIRMWARE_INFO_FORM_ID 0x7601 #define LABEL_FRONTPAGE_INFORMATION 0x1000 #define LABEL_END 0xffff @@ -34,9 +35,27 @@ formset // label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + goto FIRMWARE_INFO_FORM_ID, + prompt = STRING_TOKEN(STR_FIRMWARE_INFO), + help = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); subtitle text = STRING_TOKEN(STR_NO_BOOTABLE_MEDIA); + subtitle text = STRING_TOKEN(STR_WEBCAM_STATUS); endform; + form formid = FIRMWARE_INFO_FORM_ID, + title = STRING_TOKEN(STR_FIRMWARE_INFO); + + subtitle text = STRING_TOKEN(STR_VIRTUALIZATION); + subtitle text = STRING_TOKEN(STR_VIRTUALIZATION_STATUS); + subtitle text = STRING_TOKEN(STR_IOMMU_STATUS); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_TPM_STATUS); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_ME_STATUS); + endform; + endformset; diff --git a/MdeModulePkg/Application/UiApp/UiApp.inf b/MdeModulePkg/Application/UiApp/UiApp.inf index ff394bf36c..af7803aa96 100644 --- a/MdeModulePkg/Application/UiApp/UiApp.inf +++ b/MdeModulePkg/Application/UiApp/UiApp.inf @@ -56,6 +56,7 @@ UefiBootManagerLib [Guids] + gEfiAcpiTableGuid ## CONSUMES ## GUID gEfiIfrTianoGuid ## CONSUMES ## GUID (Extended IFR Guid Opcode) gEfiIfrFrontPageGuid ## CONSUMES ## GUID gEfiSmbiosTableGuid ## CONSUMES ## GUID diff --git a/MdePkg/Include/Register/Intel/ArchitecturalMsr.h b/MdePkg/Include/Register/Intel/ArchitecturalMsr.h index 28e71cf713..eeb13fb489 100644 --- a/MdePkg/Include/Register/Intel/ArchitecturalMsr.h +++ b/MdePkg/Include/Register/Intel/ArchitecturalMsr.h @@ -6378,7 +6378,11 @@ typedef union { /// [Bit 11] Execute Disable Bit Enable: IA32_EFER.NXE (R/W). /// UINT32 NXE:1; - UINT32 Reserved3:20; + /// + /// [ Bit 12] Secure Virtual Machine Enable (AMD only) + /// + UINT32 SVME:1; + UINT32 Reserved3:19; UINT32 Reserved4:32; } Bits; ///