1 /** @file 2 OVMF ACPI Platform Driver 3 4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR> 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 "AcpiPlatform.h" 16 17 EFI_STATUS 18 EFIAPI 19 InstallAcpiTable ( 20 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, 21 IN VOID *AcpiTableBuffer, 22 IN UINTN AcpiTableBufferSize, 23 OUT UINTN *TableKey 24 ) 25 { 26 return AcpiProtocol->InstallAcpiTable ( 27 AcpiProtocol, 28 AcpiTableBuffer, 29 AcpiTableBufferSize, 30 TableKey 31 ); 32 } 33 34 35 /** 36 Locate the first instance of a protocol. If the protocol requested is an 37 FV protocol, then it will return the first FV that contains the ACPI table 38 storage file. 39 40 @param Instance Return pointer to the first instance of the protocol 41 42 @return EFI_SUCCESS The function completed successfully. 43 @return EFI_NOT_FOUND The protocol could not be located. 44 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. 45 46 **/ 47 EFI_STATUS 48 LocateFvInstanceWithTables ( 49 OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance 50 ) 51 { 52 EFI_STATUS Status; 53 EFI_HANDLE *HandleBuffer; 54 UINTN NumberOfHandles; 55 EFI_FV_FILETYPE FileType; 56 UINT32 FvStatus; 57 EFI_FV_FILE_ATTRIBUTES Attributes; 58 UINTN Size; 59 UINTN Index; 60 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; 61 62 FvStatus = 0; 63 64 // 65 // Locate protocol. 66 // 67 Status = gBS->LocateHandleBuffer ( 68 ByProtocol, 69 &gEfiFirmwareVolume2ProtocolGuid, 70 NULL, 71 &NumberOfHandles, 72 &HandleBuffer 73 ); 74 if (EFI_ERROR (Status)) { 75 // 76 // Defined errors at this time are not found and out of resources. 77 // 78 return Status; 79 } 80 81 // 82 // Looking for FV with ACPI storage file 83 // 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 ASSERT_EFI_ERROR (Status); 95 96 // 97 // See if it has the ACPI storage file 98 // 99 Status = FvInstance->ReadFile ( 100 FvInstance, 101 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), 102 NULL, 103 &Size, 104 &FileType, 105 &Attributes, 106 &FvStatus 107 ); 108 109 // 110 // If we found it, then we are done 111 // 112 if (Status == EFI_SUCCESS) { 113 *Instance = FvInstance; 114 break; 115 } 116 } 117 118 // 119 // Our exit status is determined by the success of the previous operations 120 // If the protocol was found, Instance already points to it. 121 // 122 123 // 124 // Free any allocated buffers 125 // 126 gBS->FreePool (HandleBuffer); 127 128 return Status; 129 } 130 131 132 /** 133 Find ACPI tables in an FV and install them. 134 135 This is now a fall-back path. Normally, we will search for tables provided 136 by the VMM first. 137 138 If that fails, we use this function to load the ACPI tables from an FV. The 139 sources for the FV based tables is located under OvmfPkg/AcpiTables. 140 141 @param AcpiTable Protocol instance pointer 142 143 **/ 144 EFI_STATUS 145 EFIAPI 146 InstallOvmfFvTables ( 147 IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable 148 ) 149 { 150 EFI_STATUS Status; 151 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; 152 INTN Instance; 153 EFI_ACPI_COMMON_HEADER *CurrentTable; 154 UINTN TableHandle; 155 UINT32 FvStatus; 156 UINTN TableSize; 157 UINTN Size; 158 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction; 159 160 Instance = 0; 161 CurrentTable = NULL; 162 TableHandle = 0; 163 164 if (QemuDetected ()) { 165 TableInstallFunction = QemuInstallAcpiTable; 166 } else { 167 TableInstallFunction = InstallAcpiTable; 168 } 169 170 // 171 // Locate the firmware volume protocol 172 // 173 Status = LocateFvInstanceWithTables (&FwVol); 174 if (EFI_ERROR (Status)) { 175 return EFI_ABORTED; 176 } 177 // 178 // Read tables from the storage file. 179 // 180 while (Status == EFI_SUCCESS) { 181 182 Status = FwVol->ReadSection ( 183 FwVol, 184 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), 185 EFI_SECTION_RAW, 186 Instance, 187 (VOID**) &CurrentTable, 188 &Size, 189 &FvStatus 190 ); 191 if (!EFI_ERROR (Status)) { 192 // 193 // Add the table 194 // 195 TableHandle = 0; 196 197 TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length; 198 ASSERT (Size >= TableSize); 199 200 // 201 // Install ACPI table 202 // 203 Status = TableInstallFunction ( 204 AcpiTable, 205 CurrentTable, 206 TableSize, 207 &TableHandle 208 ); 209 210 // 211 // Free memory allocated by ReadSection 212 // 213 gBS->FreePool (CurrentTable); 214 215 if (EFI_ERROR (Status)) { 216 return EFI_ABORTED; 217 } 218 219 // 220 // Increment the instance 221 // 222 Instance++; 223 CurrentTable = NULL; 224 } 225 } 226 227 return EFI_SUCCESS; 228 } 229 230 /** 231 Effective entrypoint of Acpi Platform driver. 232 233 @param ImageHandle 234 @param SystemTable 235 236 @return EFI_SUCCESS 237 @return EFI_LOAD_ERROR 238 @return EFI_OUT_OF_RESOURCES 239 240 **/ 241 EFI_STATUS 242 EFIAPI 243 InstallAcpiTables ( 244 IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable 245 ) 246 { 247 EFI_STATUS Status; 248 249 if (XenDetected ()) { 250 Status = InstallXenTables (AcpiTable); 251 } else { 252 Status = InstallQemuFwCfgTables (AcpiTable); 253 } 254 255 if (EFI_ERROR (Status)) { 256 Status = InstallOvmfFvTables (AcpiTable); 257 } 258 259 return Status; 260 } 261 262