1 /** @file 2 * 3 * Copyright (c) 2014-2015, ARM Limited. All rights reserved. 4 * 5 * This program and the accompanying materials 6 * are licensed and made available under the terms and conditions of the BSD License 7 * which accompanies this distribution. The full text of the license may be found at 8 * http://opensource.org/licenses/bsd-license.php 9 * 10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 * 13 **/ 14 15 #include <Uefi.h> 16 17 #include <Library/AcpiLib.h> 18 #include <Library/DebugLib.h> 19 #include <Library/UefiBootServicesTableLib.h> 20 21 #include <Protocol/AcpiTable.h> 22 #include <Protocol/FirmwareVolume2.h> 23 24 #include <IndustryStandard/Acpi.h> 25 26 /** 27 Locate and Install the ACPI tables from the Firmware Volume if it verifies 28 the function condition. 29 30 @param AcpiFile Guid of the ACPI file into the Firmware Volume 31 @param CheckAcpiTableFunction Function that checks if the ACPI table should be installed 32 33 @return EFI_SUCCESS The function completed successfully. 34 @return EFI_NOT_FOUND The protocol could not be located. 35 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. 36 37 **/ 38 EFI_STATUS 39 LocateAndInstallAcpiFromFvConditional ( 40 IN CONST EFI_GUID* AcpiFile, 41 IN EFI_LOCATE_ACPI_CHECK CheckAcpiTableFunction 42 ) 43 { 44 EFI_STATUS Status; 45 EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol; 46 EFI_HANDLE *HandleBuffer; 47 UINTN NumberOfHandles; 48 UINT32 FvStatus; 49 UINTN Index; 50 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; 51 INTN SectionInstance; 52 UINTN SectionSize; 53 EFI_ACPI_COMMON_HEADER *AcpiTable; 54 UINTN AcpiTableSize; 55 UINTN AcpiTableKey; 56 BOOLEAN Valid; 57 58 // Ensure the ACPI Table is present 59 Status = gBS->LocateProtocol ( 60 &gEfiAcpiTableProtocolGuid, 61 NULL, 62 (VOID**)&AcpiProtocol 63 ); 64 if (EFI_ERROR (Status)) { 65 return Status; 66 } 67 68 FvStatus = 0; 69 SectionInstance = 0; 70 71 // Locate all the Firmware Volume protocols. 72 Status = gBS->LocateHandleBuffer ( 73 ByProtocol, 74 &gEfiFirmwareVolume2ProtocolGuid, 75 NULL, 76 &NumberOfHandles, 77 &HandleBuffer 78 ); 79 if (EFI_ERROR (Status)) { 80 return Status; 81 } 82 83 // Looking for FV with ACPI storage file 84 for (Index = 0; Index < NumberOfHandles; Index++) { 85 // 86 // Get the protocol on this handle 87 // This should not fail because of LocateHandleBuffer 88 // 89 Status = gBS->HandleProtocol ( 90 HandleBuffer[Index], 91 &gEfiFirmwareVolume2ProtocolGuid, 92 (VOID**) &FvInstance 93 ); 94 if (EFI_ERROR (Status)) { 95 goto FREE_HANDLE_BUFFER; 96 } 97 98 while (Status == EFI_SUCCESS) { 99 // AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL) 100 AcpiTable = NULL; 101 102 // See if it has the ACPI storage file 103 Status = FvInstance->ReadSection ( 104 FvInstance, 105 AcpiFile, 106 EFI_SECTION_RAW, 107 SectionInstance, 108 (VOID**) &AcpiTable, 109 &SectionSize, 110 &FvStatus 111 ); 112 if (!EFI_ERROR (Status)) { 113 AcpiTableKey = 0; 114 AcpiTableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Length; 115 ASSERT (SectionSize >= AcpiTableSize); 116 117 DEBUG ((EFI_D_ERROR, "- Found '%c%c%c%c' ACPI Table\n", 118 (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature & 0xFF), 119 ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 8) & 0xFF), 120 ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 16) & 0xFF), 121 ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 24) & 0xFF))); 122 123 // Is the ACPI table valid? 124 if (CheckAcpiTableFunction) { 125 Valid = CheckAcpiTableFunction ((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable); 126 } else { 127 Valid = TRUE; 128 } 129 130 // Install the ACPI Table 131 if (Valid) { 132 Status = AcpiProtocol->InstallAcpiTable ( 133 AcpiProtocol, 134 AcpiTable, 135 AcpiTableSize, 136 &AcpiTableKey 137 ); 138 } 139 140 // Free memory allocated by ReadSection 141 gBS->FreePool (AcpiTable); 142 143 if (EFI_ERROR (Status)) { 144 break; 145 } 146 147 // Increment the section instance 148 SectionInstance++; 149 } 150 } 151 } 152 153 FREE_HANDLE_BUFFER: 154 // 155 // Free any allocated buffers 156 // 157 gBS->FreePool (HandleBuffer); 158 159 return EFI_SUCCESS; 160 } 161 162 /** 163 Locate and Install the ACPI tables from the Firmware Volume 164 165 @param AcpiFile Guid of the ACPI file into the Firmware Volume 166 167 @return EFI_SUCCESS The function completed successfully. 168 @return EFI_NOT_FOUND The protocol could not be located. 169 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. 170 171 **/ 172 EFI_STATUS 173 LocateAndInstallAcpiFromFv ( 174 IN CONST EFI_GUID* AcpiFile 175 ) 176 { 177 return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL); 178 } 179