REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			318 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Instance of Runtime PCI Segment Library that support multi-segment PCI configuration access.
 | |
| 
 | |
|   PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to
 | |
|    support multi-segment PCI configuration access through enhanced configuration access mechanism.
 | |
| 
 | |
|   Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PciSegmentLibCommon.h"
 | |
| #include <PiDxe.h>
 | |
| #include <Guid/EventGroup.h>
 | |
| #include <Library/UefiRuntimeLib.h>
 | |
| #include <Library/DxeServicesTableLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/PciSegmentInfoLib.h>
 | |
| 
 | |
| ///
 | |
| /// Define table for mapping PCI Segment MMIO physical addresses to virtual addresses at OS runtime
 | |
| ///
 | |
| typedef struct {
 | |
|   UINTN    PhysicalAddress;
 | |
|   UINTN    VirtualAddress;
 | |
| } PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE;
 | |
| 
 | |
| ///
 | |
| /// Set Virtual Address Map Event
 | |
| ///
 | |
| EFI_EVENT  mDxeRuntimePciSegmentLibVirtualNotifyEvent = NULL;
 | |
| 
 | |
| ///
 | |
| /// The number of PCI devices that have been registered for runtime access.
 | |
| ///
 | |
| UINTN  mDxeRuntimePciSegmentLibNumberOfRuntimeRanges = 0;
 | |
| 
 | |
| ///
 | |
| /// The table of PCI devices that have been registered for runtime access.
 | |
| ///
 | |
| PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE  *mDxeRuntimePciSegmentLibRegistrationTable = NULL;
 | |
| 
 | |
| ///
 | |
| /// The table index of the most recent virtual address lookup.
 | |
| ///
 | |
| UINTN  mDxeRuntimePciSegmentLibLastRuntimeRange = 0;
 | |
| 
 | |
| /**
 | |
|   Convert the physical PCI Express MMIO addresses for all registered PCI devices
 | |
|   to virtual addresses.
 | |
| 
 | |
|   @param[in]    Event   The event that is being processed.
 | |
|   @param[in]    Context The Event Context.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| DxeRuntimePciSegmentLibVirtualNotify (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   UINTN       Index;
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // If there have been no runtime registrations, then just return
 | |
|   //
 | |
|   if (mDxeRuntimePciSegmentLibRegistrationTable == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert physical addresses associated with the set of registered PCI devices to
 | |
|   // virtual addresses.
 | |
|   //
 | |
|   for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
 | |
|     Status = EfiConvertPointer (0, (VOID **)&(mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress));
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
 | |
|   //
 | |
|   Status = EfiConvertPointer (0, (VOID **)&mDxeRuntimePciSegmentLibRegistrationTable);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The constructor function caches the PCI Express Base Address and creates a
 | |
|   Set Virtual Address Map event to convert physical address to virtual addresses.
 | |
| 
 | |
|   @param  ImageHandle   The firmware allocated handle for the EFI image.
 | |
|   @param  SystemTable   A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The constructor completed successfully.
 | |
|   @retval Other value   The constructor did not complete successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DxeRuntimePciSegmentLibConstructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Register SetVirtualAddressMap () notify function
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
 | |
|                   TPL_NOTIFY,
 | |
|                   DxeRuntimePciSegmentLibVirtualNotify,
 | |
|                   NULL,
 | |
|                   &mDxeRuntimePciSegmentLibVirtualNotifyEvent
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The destructor function frees any allocated buffers and closes the Set Virtual
 | |
|   Address Map event.
 | |
| 
 | |
|   @param  ImageHandle   The firmware allocated handle for the EFI image.
 | |
|   @param  SystemTable   A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The destructor completed successfully.
 | |
|   @retval Other value   The destructor did not complete successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DxeRuntimePciSegmentLibDestructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // If one or more PCI devices have been registered for runtime access, then
 | |
|   // free the registration table.
 | |
|   //
 | |
|   if (mDxeRuntimePciSegmentLibRegistrationTable != NULL) {
 | |
|     FreePool (mDxeRuntimePciSegmentLibRegistrationTable);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Close the Set Virtual Address Map event
 | |
|   //
 | |
|   Status = gBS->CloseEvent (mDxeRuntimePciSegmentLibVirtualNotifyEvent);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register a PCI device so PCI configuration registers may be accessed after
 | |
|   SetVirtualAddressMap().
 | |
| 
 | |
|   If any reserved bits in Address are set, then ASSERT().
 | |
| 
 | |
|   @param  Address The address that encodes the PCI Bus, Device, Function and
 | |
|                   Register.
 | |
| 
 | |
|   @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
 | |
|   @retval RETURN_UNSUPPORTED       An attempt was made to call this function
 | |
|                                    after ExitBootServices().
 | |
|   @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
 | |
|                                    at runtime could not be mapped.
 | |
|   @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
 | |
|                                    complete the registration.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| PciSegmentRegisterForRuntimeAccess (
 | |
|   IN UINTN  Address
 | |
|   )
 | |
| {
 | |
|   RETURN_STATUS                    Status;
 | |
|   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;
 | |
|   UINTN                            Index;
 | |
|   VOID                             *NewTable;
 | |
|   UINTN                            Count;
 | |
|   PCI_SEGMENT_INFO                 *SegmentInfo;
 | |
|   UINT64                           EcamAddress;
 | |
| 
 | |
|   //
 | |
|   // Convert Address to a ECAM address at the beginning of the PCI Configuration
 | |
|   // header for the specified PCI Bus/Dev/Func
 | |
|   //
 | |
|   Address    &= ~(UINTN)EFI_PAGE_MASK;
 | |
|   SegmentInfo = GetPciSegmentInfo (&Count);
 | |
|   EcamAddress = PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count);
 | |
| 
 | |
|   //
 | |
|   // Return an error if this function is called after ExitBootServices().
 | |
|   //
 | |
|   if (EfiAtRuntime ()) {
 | |
|     return RETURN_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (sizeof (UINTN) == sizeof (UINT32)) {
 | |
|     ASSERT (EcamAddress < BASE_4GB);
 | |
|   }
 | |
| 
 | |
|   Address = (UINTN)EcamAddress;
 | |
| 
 | |
|   //
 | |
|   // See if Address has already been registered for runtime access
 | |
|   //
 | |
|   for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
 | |
|     if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == Address) {
 | |
|       return RETURN_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the GCD Memory Descriptor for the ECAM Address
 | |
|   //
 | |
|   Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return RETURN_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
 | |
|   // will allocate a virtual address range for the 4KB PCI Configuration Header.
 | |
|   //
 | |
|   Status = gDS->SetMemorySpaceAttributes (Address, EFI_PAGE_SIZE, Descriptor.Attributes | EFI_MEMORY_RUNTIME);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return RETURN_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Grow the size of the registration table
 | |
|   //
 | |
|   NewTable = ReallocateRuntimePool (
 | |
|                (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 0) * sizeof (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE),
 | |
|                (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 1) * sizeof (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE),
 | |
|                mDxeRuntimePciSegmentLibRegistrationTable
 | |
|                );
 | |
|   if (NewTable == NULL) {
 | |
|     return RETURN_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   mDxeRuntimePciSegmentLibRegistrationTable                                                                = NewTable;
 | |
|   mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumberOfRuntimeRanges].PhysicalAddress = Address;
 | |
|   mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumberOfRuntimeRanges].VirtualAddress  = Address;
 | |
|   mDxeRuntimePciSegmentLibNumberOfRuntimeRanges++;
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the linear address for the physical address.
 | |
| 
 | |
|   @param  Address  The physical address.
 | |
| 
 | |
|   @retval The linear address.
 | |
| **/
 | |
| UINTN
 | |
| PciSegmentLibVirtualAddress (
 | |
|   IN UINTN  Address
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
| 
 | |
|   //
 | |
|   // If SetVirtualAddressMap() has not been called, then just return the physical address
 | |
|   //
 | |
|   if (!EfiGoneVirtual ()) {
 | |
|     return Address;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // See if there is a physical address match at the exact same index as the last address match
 | |
|   //
 | |
|   if (mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) {
 | |
|     //
 | |
|     // Convert the physical address to a virtual address and return the virtual address
 | |
|     //
 | |
|     return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].VirtualAddress;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Search the entire table for a physical address match
 | |
|   //
 | |
|   for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
 | |
|     if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) {
 | |
|       //
 | |
|       // Cache the matching index value
 | |
|       //
 | |
|       mDxeRuntimePciSegmentLibLastRuntimeRange = Index;
 | |
|       //
 | |
|       // Convert the physical address to a virtual address and return the virtual address
 | |
|       //
 | |
|       return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // No match was found.  This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
 | |
|   //
 | |
|   ASSERT (FALSE);
 | |
|   CpuBreakpoint ();
 | |
| 
 | |
|   //
 | |
|   // Return the physical address
 | |
|   //
 | |
|   return Address;
 | |
| }
 |