1 /** @file 2 Entry point of OVMF ACPI Platform Driver 3 4 Copyright (C) 2015, Red Hat, Inc. 5 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR> 6 7 This program and the accompanying materials are licensed and made available 8 under the terms and conditions of the BSD License which accompanies this 9 distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 **/ 15 16 #include <Protocol/PciEnumerationComplete.h> 17 #include "AcpiPlatform.h" 18 19 STATIC 20 EFI_ACPI_TABLE_PROTOCOL * 21 FindAcpiTableProtocol ( 22 VOID 23 ) 24 { 25 EFI_STATUS Status; 26 EFI_ACPI_TABLE_PROTOCOL *AcpiTable; 27 28 Status = gBS->LocateProtocol ( 29 &gEfiAcpiTableProtocolGuid, 30 NULL, 31 (VOID**)&AcpiTable 32 ); 33 ASSERT_EFI_ERROR (Status); 34 return AcpiTable; 35 } 36 37 38 STATIC 39 VOID 40 EFIAPI 41 OnPciEnumerated ( 42 IN EFI_EVENT Event, 43 IN VOID *Context 44 ) 45 { 46 EFI_STATUS Status; 47 48 DEBUG ((EFI_D_INFO, "%a: PCI enumeration complete, installing ACPI tables\n", 49 __FUNCTION__)); 50 Status = InstallAcpiTables (FindAcpiTableProtocol ()); 51 if (EFI_ERROR (Status)) { 52 DEBUG ((EFI_D_ERROR, "%a: InstallAcpiTables: %r\n", __FUNCTION__, Status)); 53 } 54 gBS->CloseEvent (Event); 55 } 56 57 58 EFI_STATUS 59 EFIAPI 60 AcpiPlatformEntryPoint ( 61 IN EFI_HANDLE ImageHandle, 62 IN EFI_SYSTEM_TABLE *SystemTable 63 ) 64 { 65 EFI_STATUS Status; 66 VOID *Interface; 67 EFI_EVENT PciEnumerated; 68 VOID *Registration; 69 70 // 71 // If the platform doesn't support PCI, or PCI enumeration has been disabled, 72 // install the tables at once, and let the entry point's return code reflect 73 // the full functionality. 74 // 75 if (PcdGetBool (PcdPciDisableBusEnumeration)) { 76 DEBUG ((EFI_D_INFO, "%a: PCI or its enumeration disabled, installing " 77 "ACPI tables\n", __FUNCTION__)); 78 return InstallAcpiTables (FindAcpiTableProtocol ()); 79 } 80 81 // 82 // Similarly, if PCI enumeration has already completed, install the tables 83 // immediately. 84 // 85 Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, 86 NULL /* Registration */, &Interface); 87 if (!EFI_ERROR (Status)) { 88 DEBUG ((EFI_D_INFO, "%a: PCI enumeration already complete, " 89 "installing ACPI tables\n", __FUNCTION__)); 90 return InstallAcpiTables (FindAcpiTableProtocol ()); 91 } 92 ASSERT (Status == EFI_NOT_FOUND); 93 94 // 95 // Otherwise, delay installing the ACPI tables until PCI enumeration 96 // completes. The entry point's return status will only reflect the callback 97 // setup. 98 // 99 Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnPciEnumerated, 100 NULL /* Context */, &PciEnumerated); 101 if (EFI_ERROR (Status)) { 102 return Status; 103 } 104 105 Status = gBS->RegisterProtocolNotify ( 106 &gEfiPciEnumerationCompleteProtocolGuid, PciEnumerated, 107 &Registration); 108 if (EFI_ERROR (Status)) { 109 gBS->CloseEvent (PciEnumerated); 110 } else { 111 DEBUG ((EFI_D_INFO, "%a: PCI enumeration pending, registered callback\n", 112 __FUNCTION__)); 113 } 114 115 return Status; 116 } 117