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**/
39EFI_STATUS
40LocateFvInstanceWithTables (
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**/
134VOID
135AcpiPlatformChecksum (
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**/
167EFI_STATUS
168EFIAPI
169AcpiPlatformEntryPoint (
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