1 /** @file
2 Sample ACPI Platform Driver
3
4 Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
10
11 #include <Protocol/AcpiTable.h>
12 #include <Protocol/FirmwareVolume2.h>
13
14 #include <Library/BaseLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18
19 #include <IndustryStandard/Acpi.h>
20
21 /**
22 Locate the first instance of a protocol. If the protocol requested is an
23 FV protocol, then it will return the first FV that contains the ACPI table
24 storage file.
25
26 @param Instance Return pointer to the first instance of the protocol
27
28 @return EFI_SUCCESS The function completed successfully.
29 @return EFI_NOT_FOUND The protocol could not be located.
30 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
31
32 **/
33 EFI_STATUS
LocateFvInstanceWithTables(OUT EFI_FIRMWARE_VOLUME2_PROTOCOL ** Instance)34 LocateFvInstanceWithTables (
35 OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
36 )
37 {
38 EFI_STATUS Status;
39 EFI_HANDLE *HandleBuffer;
40 UINTN NumberOfHandles;
41 EFI_FV_FILETYPE FileType;
42 UINT32 FvStatus;
43 EFI_FV_FILE_ATTRIBUTES Attributes;
44 UINTN Size;
45 UINTN Index;
46 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
47
48 FvStatus = 0;
49
50 //
51 // Locate protocol.
52 //
53 Status = gBS->LocateHandleBuffer (
54 ByProtocol,
55 &gEfiFirmwareVolume2ProtocolGuid,
56 NULL,
57 &NumberOfHandles,
58 &HandleBuffer
59 );
60 if (EFI_ERROR (Status)) {
61 //
62 // Defined errors at this time are not found and out of resources.
63 //
64 return Status;
65 }
66
67
68
69 //
70 // Looking for FV with ACPI storage file
71 //
72
73 for (Index = 0; Index < NumberOfHandles; Index++) {
74 //
75 // Get the protocol on this handle
76 // This should not fail because of LocateHandleBuffer
77 //
78 Status = gBS->HandleProtocol (
79 HandleBuffer[Index],
80 &gEfiFirmwareVolume2ProtocolGuid,
81 (VOID**) &FvInstance
82 );
83 ASSERT_EFI_ERROR (Status);
84
85 //
86 // See if it has the ACPI storage file
87 //
88 Status = FvInstance->ReadFile (
89 FvInstance,
90 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
91 NULL,
92 &Size,
93 &FileType,
94 &Attributes,
95 &FvStatus
96 );
97
98 //
99 // If we found it, then we are done
100 //
101 if (Status == EFI_SUCCESS) {
102 *Instance = FvInstance;
103 break;
104 }
105 }
106
107 //
108 // Our exit status is determined by the success of the previous operations
109 // If the protocol was found, Instance already points to it.
110 //
111
112 //
113 // Free any allocated buffers
114 //
115 gBS->FreePool (HandleBuffer);
116
117 return Status;
118 }
119
120
121 /**
122 This function calculates and updates an UINT8 checksum.
123
124 @param Buffer Pointer to buffer to checksum
125 @param Size Number of bytes to checksum
126
127 **/
128 VOID
AcpiPlatformChecksum(IN UINT8 * Buffer,IN UINTN Size)129 AcpiPlatformChecksum (
130 IN UINT8 *Buffer,
131 IN UINTN Size
132 )
133 {
134 UINTN ChecksumOffset;
135
136 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
137
138 //
139 // Set checksum to 0 first
140 //
141 Buffer[ChecksumOffset] = 0;
142
143 //
144 // Update checksum value
145 //
146 Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size);
147 }
148
149
150 /**
151 Entrypoint of Acpi Platform driver.
152
153 @param ImageHandle
154 @param SystemTable
155
156 @return EFI_SUCCESS
157 @return EFI_LOAD_ERROR
158 @return EFI_OUT_OF_RESOURCES
159
160 **/
161 EFI_STATUS
162 EFIAPI
AcpiPlatformEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)163 AcpiPlatformEntryPoint (
164 IN EFI_HANDLE ImageHandle,
165 IN EFI_SYSTEM_TABLE *SystemTable
166 )
167 {
168 EFI_STATUS Status;
169 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
170 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
171 INTN Instance;
172 EFI_ACPI_COMMON_HEADER *CurrentTable;
173 UINTN TableHandle;
174 UINT32 FvStatus;
175 UINTN TableSize;
176 UINTN Size;
177
178 Instance = 0;
179 CurrentTable = NULL;
180 TableHandle = 0;
181
182 //
183 // Find the AcpiTable protocol
184 //
185 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
186 if (EFI_ERROR (Status)) {
187 return EFI_ABORTED;
188 }
189
190 //
191 // Locate the firmware volume protocol
192 //
193 Status = LocateFvInstanceWithTables (&FwVol);
194 if (EFI_ERROR (Status)) {
195 return EFI_ABORTED;
196 }
197 //
198 // Read tables from the storage file.
199 //
200 while (Status == EFI_SUCCESS) {
201
202 Status = FwVol->ReadSection (
203 FwVol,
204 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
205 EFI_SECTION_RAW,
206 Instance,
207 (VOID**) &CurrentTable,
208 &Size,
209 &FvStatus
210 );
211 if (!EFI_ERROR(Status)) {
212 //
213 // Add the table
214 //
215 TableHandle = 0;
216
217 TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
218 ASSERT (Size >= TableSize);
219
220 //
221 // Checksum ACPI table
222 //
223 AcpiPlatformChecksum ((UINT8*)CurrentTable, TableSize);
224
225 //
226 // Install ACPI table
227 //
228 Status = AcpiTable->InstallAcpiTable (
229 AcpiTable,
230 CurrentTable,
231 TableSize,
232 &TableHandle
233 );
234
235 //
236 // Free memory allocated by ReadSection
237 //
238 gBS->FreePool (CurrentTable);
239
240 if (EFI_ERROR(Status)) {
241 return EFI_ABORTED;
242 }
243
244 //
245 // Increment the instance
246 //
247 Instance++;
248 CurrentTable = NULL;
249 }
250 }
251
252 //
253 // The driver does not require to be kept loaded.
254 //
255 return EFI_REQUEST_UNLOAD_IMAGE;
256 }
257
258