UiApp: Dynamically generated firmware configuration information page
Signed-off-by: Jeremy Soller <jeremy@system76.com> Signed-off-by: Tim Crawford <tcrawford@system76.com>
This commit is contained in:
committed by
Tim Crawford
parent
90e04a7e31
commit
cb870a1ce9
@ -7,6 +7,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/PciRootBridgeIo.h>
|
||||
#include <Protocol/UsbIo.h>
|
||||
#include <Register/Amd/Cpuid.h>
|
||||
#include <Register/Intel/Cpuid.h>
|
||||
#include <Register/Intel/Msr.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user