• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Xen ARM ACPI Platform Driver using Xen ARM multiboot protocol
3 
4   Copyright (C) 2016, Linaro Ltd. All rights reserved.
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiDriverEntryPoint.h>
20 
21 #include <Protocol/AcpiTable.h>
22 #include <Protocol/FdtClient.h>
23 
24 #include <IndustryStandard/Acpi.h>
25 
26 /**
27   Get the address of Xen ACPI Root System Description Pointer (RSDP)
28   structure.
29 
30   @param  RsdpStructurePtr   Return pointer to RSDP structure
31 
32   @return EFI_SUCCESS        Find Xen RSDP structure successfully.
33   @return EFI_NOT_FOUND      Don't find Xen RSDP structure.
34   @return EFI_ABORTED        Find Xen RSDP structure, but it's not integrated.
35 
36 **/
37 STATIC
38 EFI_STATUS
39 EFIAPI
GetXenArmAcpiRsdp(OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER ** RsdpPtr)40 GetXenArmAcpiRsdp (
41   OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   **RsdpPtr
42   )
43 {
44   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *RsdpStructurePtr;
45   EFI_STATUS                                     Status;
46   FDT_CLIENT_PROTOCOL                            *FdtClient;
47   CONST UINT64                                   *Reg;
48   UINT32                                         RegSize;
49   UINTN                                          AddressCells, SizeCells;
50   UINT64                                         RegBase;
51   UINT8                                          Sum;
52 
53   RsdpStructurePtr = NULL;
54   FdtClient = NULL;
55   //
56   // Get the RSDP structure address from DeviceTree
57   //
58   Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
59                   (VOID **)&FdtClient);
60   ASSERT_EFI_ERROR (Status);
61 
62   Status = FdtClient->FindCompatibleNodeReg (FdtClient, "xen,guest-acpi",
63                         (CONST VOID **)&Reg, &AddressCells, &SizeCells,
64                         &RegSize);
65   if (EFI_ERROR (Status)) {
66     DEBUG ((EFI_D_WARN, "%a: No 'xen,guest-acpi' compatible DT node found\n",
67       __FUNCTION__));
68     return EFI_NOT_FOUND;
69   }
70 
71   ASSERT (AddressCells == 2);
72   ASSERT (SizeCells == 2);
73   ASSERT (RegSize == 2 * sizeof (UINT64));
74 
75   RegBase = SwapBytes64(Reg[0]);
76   RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)RegBase;
77 
78   if (RsdpStructurePtr && RsdpStructurePtr->Revision >= 2) {
79     Sum = CalculateSum8 ((CONST UINT8 *)RsdpStructurePtr,
80             sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER));
81     if (Sum != 0) {
82       return EFI_ABORTED;
83     }
84   }
85 
86   *RsdpPtr = RsdpStructurePtr;
87   return EFI_SUCCESS;
88 }
89 
90 /**
91   Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
92   into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
93   ACPI tables are: FACP, APIC, GTDT, DSDT.
94 
95   @param  AcpiProtocol           Protocol instance pointer.
96 
97   @return EFI_SUCCESS            The table was successfully inserted.
98   @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableHandle is
99                                  NULL, or AcpiTableBufferSize and the size
100                                  field embedded in the ACPI table pointed to
101                                  by AcpiTableBuffer are not in sync.
102   @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.
103 
104 **/
105 STATIC
106 EFI_STATUS
107 EFIAPI
InstallXenArmTables(IN EFI_ACPI_TABLE_PROTOCOL * AcpiProtocol)108 InstallXenArmTables (
109   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol
110   )
111 {
112   EFI_STATUS                                       Status;
113   UINTN                                            TableHandle;
114   VOID                                             *CurrentTableEntry;
115   UINTN                                            CurrentTablePointer;
116   EFI_ACPI_DESCRIPTION_HEADER                      *CurrentTable;
117   UINTN                                            Index;
118   UINTN                                            NumberOfTableEntries;
119   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER     *XenAcpiRsdpStructurePtr;
120   EFI_ACPI_DESCRIPTION_HEADER                      *Xsdt;
121   EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE        *FadtTable;
122   EFI_ACPI_DESCRIPTION_HEADER                      *DsdtTable;
123 
124   XenAcpiRsdpStructurePtr = NULL;
125   FadtTable   = NULL;
126   DsdtTable   = NULL;
127   TableHandle = 0;
128   NumberOfTableEntries = 0;
129 
130   //
131   // Try to find Xen ARM ACPI tables
132   //
133   Status = GetXenArmAcpiRsdp (&XenAcpiRsdpStructurePtr);
134   if (EFI_ERROR (Status)) {
135     DEBUG ((EFI_D_INFO, "%a: No RSDP table found\n", __FUNCTION__));
136     return Status;
137   }
138 
139   //
140   // If XSDT table is find, just install its tables.
141   //
142   if (XenAcpiRsdpStructurePtr->XsdtAddress) {
143     //
144     // Retrieve the addresses of XSDT and
145     // calculate the number of its table entries.
146     //
147     Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
148              XenAcpiRsdpStructurePtr->XsdtAddress;
149     NumberOfTableEntries = (Xsdt->Length -
150                              sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
151                              sizeof (UINT64);
152     //
153     // Install ACPI tables found in XSDT.
154     //
155     for (Index = 0; Index < NumberOfTableEntries; Index++) {
156       //
157       // Get the table entry from XSDT
158       //
159       CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +
160                             sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
161                             Index * sizeof (UINT64));
162       CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;
163       CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
164 
165       //
166       // Install the XSDT tables
167       //
168       Status = AcpiProtocol->InstallAcpiTable (
169                  AcpiProtocol,
170                  CurrentTable,
171                  CurrentTable->Length,
172                  &TableHandle
173                  );
174 
175       if (EFI_ERROR (Status)) {
176         return Status;
177       }
178 
179       //
180       // Get the FACS and DSDT table address from the table FADT
181       //
182       if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
183         FadtTable = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
184                       (UINTN) CurrentTablePointer;
185         DsdtTable  = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) FadtTable->Dsdt;
186       }
187     }
188   }
189 
190   //
191   // Install DSDT table.
192   //
193   Status = AcpiProtocol->InstallAcpiTable (
194              AcpiProtocol,
195              DsdtTable,
196              DsdtTable->Length,
197              &TableHandle
198              );
199   if (EFI_ERROR (Status)) {
200     return Status;
201   }
202 
203   return EFI_SUCCESS;
204 }
205 
206 STATIC
207 EFI_ACPI_TABLE_PROTOCOL *
FindAcpiTableProtocol(VOID)208 FindAcpiTableProtocol (
209   VOID
210   )
211 {
212   EFI_STATUS              Status;
213   EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
214 
215   AcpiTable = NULL;
216   Status = gBS->LocateProtocol (
217                   &gEfiAcpiTableProtocolGuid,
218                   NULL,
219                   (VOID**)&AcpiTable
220                   );
221   ASSERT_EFI_ERROR (Status);
222   return AcpiTable;
223 }
224 
225 /**
226   Entrypoint of Xen ARM Acpi Platform driver.
227 
228   @param  ImageHandle
229   @param  SystemTable
230 
231   @return EFI_SUCCESS
232   @return EFI_LOAD_ERROR
233   @return EFI_OUT_OF_RESOURCES
234 
235 **/
236 
237 EFI_STATUS
238 EFIAPI
XenAcpiPlatformEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)239 XenAcpiPlatformEntryPoint (
240   IN EFI_HANDLE         ImageHandle,
241   IN EFI_SYSTEM_TABLE   *SystemTable
242   )
243 {
244   EFI_STATUS                         Status;
245 
246   Status = InstallXenArmTables (FindAcpiTableProtocol ());
247   return Status;
248 }
249