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