Implement BlActivateSerialControllerIO() routine for activating I/O space access on PCI(E) serial controllers
All checks were successful
ci/woodpecker/push/build Pipeline was successful

This commit is contained in:
Rafal Kupiec 2023-01-03 00:10:24 +01:00
parent d8f2135ac6
commit bb95223501
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
2 changed files with 121 additions and 0 deletions

View File

@ -9,6 +9,108 @@
#include <xtbl.h>
/**
* Enables I/O space access to all serial controllers found on the PCI(E) root bridge.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTCDECL
EFI_STATUS
BlActivateSerialControllerIO()
{
EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev;
USHORT Bus, Device, Function, Command;
UINT_PTR Index, PciHandleSize;
PEFI_HANDLE PciHandle = NULL;
PCI_COMMON_HEADER PciHeader;
EFI_STATUS Status;
UINT64 Address;
/* Allocate memory for single EFI_HANDLE, what should be enough in most cases */
PciHandleSize = sizeof(EFI_HANDLE);
Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory allocation failure */
return Status;
}
/* Get all instances of PciRootBridgeIo */
Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle);
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
{
/* Reallocate more memory as requested by UEFI */
BlEfiMemoryFreePool(PciHandle);
Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory reallocation failure */
return Status;
}
/* Second attempt to get instances of PciRootBridgeIo */
Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle);
}
/* Make sure successfully obtained PciRootBridgeIo instances */
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to get PciRootBridgeIo instances */
return Status;
}
/* Enumerate all devices for each handle, which decides a segment and a bus number range */
for(Index = 0; Index < (PciHandleSize / sizeof(EFI_HANDLE)); Index++)
{
/* Get inferface from the protocol */
Status = EfiSystemTable->BootServices->HandleProtocol(PciHandle[Index], &PciGuid, (PVOID*)&PciDev);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to get interface */
return Status;
}
/* Enumerate whole PCI bridge */
for(Bus = 0; Bus <= PCI_MAX_BRIDGE_NUMBER; Bus++)
{
/* Enumerate all devices for each bus */
for(Device = 0; Device < PCI_MAX_DEVICES; Device++)
{
/* Enumerate all functions for each devices */
for(Function = 0; Function < PCI_MAX_FUNCTION; Function++)
{
/* Read configuration space */
Address = ((UINT64)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) +
(((UINT_PTR) Function) << 8) + ((UINT_PTR) 0)));
PciDev->Pci.Read(PciDev, 2, Address, sizeof (PciHeader) / sizeof (UINT32), &PciHeader);
/* Check if device exists */
if(PciHeader.VendorId == PCI_INVALID_VENDORID)
{
/* Skip non-existen device */
continue;
}
/* Check if device is serial controller or multiport serial controller */
if(PciHeader.BaseClass == 0x07 && (PciHeader.SubClass == 0x00 || PciHeader.SubClass == 0x02))
{
/* Enable I/O space access */
Address |= 0x4;
Command = PCI_ENABLE_IO_SPACE;
Status = PciDev->Pci.Write(PciDev, 1, Address, 1, &Command);
}
}
}
}
}
/* Return SUCCESS */
return STATUS_EFI_SUCCESS;
}
/**
* This routine initializes the COM port debug console.
*
@ -136,6 +238,21 @@ BlComPortInitialize()
/* Initialize COM port */
Status = HlInitializeComPort(&EfiSerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate);
/* Port not found under supplied address */
if(Status == STATUS_NOT_FOUND && PortAddress)
{
/* This might be PCI(E) serial controller, try to activate I/O space access first */
EfiStatus = BlActivateSerialControllerIO();
if(EfiStatus == STATUS_EFI_SUCCESS)
{
/* Try to reinitialize COM port */
BlEfiPrint(L"Enabled I/O space access for all PCI(E) serial controllers found\n");
Status = HlInitializeComPort(&EfiSerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate);
}
}
/* Check COM port initialization status code */
if(Status != STATUS_SUCCESS)
{
/* Serial port initialization failed, mark as not ready */

View File

@ -32,6 +32,10 @@ EXTERN PVOID EfiLoaderStack;
/* Serial port configuration */
EXTERN CPPORT EfiSerialPort;
XTCDECL
EFI_STATUS
BlActivateSerialControllerIO();
XTCDECL
EFI_STATUS
BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,