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
LocateAndInstallAcpiFromFvConditional(IN CONST EFI_GUID * AcpiFile,IN EFI_LOCATE_ACPI_CHECK CheckAcpiTableFunction)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
LocateAndInstallAcpiFromFv(IN CONST EFI_GUID * AcpiFile)173 LocateAndInstallAcpiFromFv (
174 IN CONST EFI_GUID* AcpiFile
175 )
176 {
177 return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL);
178 }
179