• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 *
3 *  Copyright (c) 2017, Linaro, Ltd. 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 <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/DevicePathLib.h>
18 #include <Library/DtPlatformDtbLoaderLib.h>
19 #include <Library/HiiLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiDriverEntryPoint.h>
23 #include <Library/UefiRuntimeServicesTableLib.h>
24 
25 #include "DtPlatformDxe.h"
26 
27 extern  UINT8                     DtPlatformHiiBin[];
28 extern  UINT8                     DtPlatformDxeStrings[];
29 
30 typedef struct {
31   VENDOR_DEVICE_PATH              VendorDevicePath;
32   EFI_DEVICE_PATH_PROTOCOL        End;
33 } HII_VENDOR_DEVICE_PATH;
34 
35 STATIC HII_VENDOR_DEVICE_PATH     mDtPlatformDxeVendorDevicePath = {
36   {
37     {
38       HARDWARE_DEVICE_PATH,
39       HW_VENDOR_DP,
40       {
41         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
42         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
43       }
44     },
45     DT_PLATFORM_FORMSET_GUID
46   },
47   {
48     END_DEVICE_PATH_TYPE,
49     END_ENTIRE_DEVICE_PATH_SUBTYPE,
50     {
51       (UINT8) (END_DEVICE_PATH_LENGTH),
52       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
53     }
54   }
55 };
56 
57 STATIC
58 EFI_STATUS
InstallHiiPages(VOID)59 InstallHiiPages (
60   VOID
61   )
62 {
63   EFI_STATUS                      Status;
64   EFI_HII_HANDLE                  HiiHandle;
65   EFI_HANDLE                      DriverHandle;
66 
67   DriverHandle = NULL;
68   Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle,
69                   &gEfiDevicePathProtocolGuid,
70                   &mDtPlatformDxeVendorDevicePath,
71                   NULL);
72   if (EFI_ERROR (Status)) {
73     return Status;
74   }
75 
76   HiiHandle = HiiAddPackages (&gDtPlatformFormSetGuid,
77                               DriverHandle,
78                               DtPlatformDxeStrings,
79                               DtPlatformHiiBin,
80                               NULL);
81 
82   if (HiiHandle == NULL) {
83     gBS->UninstallMultipleProtocolInterfaces (DriverHandle,
84                   &gEfiDevicePathProtocolGuid,
85                   &mDtPlatformDxeVendorDevicePath,
86                   NULL);
87     return EFI_OUT_OF_RESOURCES;
88   }
89   return EFI_SUCCESS;
90 }
91 
92 /**
93   The entry point for DtPlatformDxe driver.
94 
95   @param[in] ImageHandle     The image handle of the driver.
96   @param[in] SystemTable     The system table.
97 
98   @retval EFI_ALREADY_STARTED     The driver already exists in system.
99   @retval EFI_OUT_OF_RESOURCES    Fail to execute entry point due to lack of
100                                   resources.
101   @retval EFI_SUCCES              All the related protocols are installed on
102                                   the driver.
103 
104 **/
105 EFI_STATUS
106 EFIAPI
DtPlatformDxeEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)107 DtPlatformDxeEntryPoint (
108   IN EFI_HANDLE                   ImageHandle,
109   IN EFI_SYSTEM_TABLE             *SystemTable
110   )
111 {
112   EFI_STATUS                      Status;
113   DT_ACPI_VARSTORE_DATA           DtAcpiPref;
114   UINTN                           BufferSize;
115   VOID                            *Dtb;
116   UINTN                           DtbSize;
117 
118   Dtb = NULL;
119   Status = DtPlatformLoadDtb (&Dtb, &DtbSize);
120   if (EFI_ERROR (Status)) {
121     DEBUG ((DEBUG_WARN,
122       "%a: no DTB blob could be loaded, defaulting to ACPI (Status == %r)\n",
123       __FUNCTION__, Status));
124     DtAcpiPref.Pref = DT_ACPI_SELECT_ACPI;
125   } else {
126     //
127     // Get the current DT/ACPI preference from the DtAcpiPref variable.
128     //
129     BufferSize = sizeof (DtAcpiPref);
130     Status = gRT->GetVariable(DT_ACPI_VARIABLE_NAME, &gDtPlatformFormSetGuid,
131                     NULL, &BufferSize, &DtAcpiPref);
132     if (EFI_ERROR (Status)) {
133       DEBUG ((DEBUG_WARN, "%a: no DT/ACPI preference found, defaulting to DT\n",
134         __FUNCTION__));
135       DtAcpiPref.Pref = DT_ACPI_SELECT_DT;
136     }
137   }
138 
139   if (!EFI_ERROR (Status) &&
140       DtAcpiPref.Pref != DT_ACPI_SELECT_ACPI &&
141       DtAcpiPref.Pref != DT_ACPI_SELECT_DT) {
142     DEBUG ((DEBUG_WARN, "%a: invalid value for %s, defaulting to DT\n",
143       __FUNCTION__, DT_ACPI_VARIABLE_NAME));
144     DtAcpiPref.Pref = DT_ACPI_SELECT_DT;
145     Status = EFI_INVALID_PARAMETER; // trigger setvar below
146   }
147 
148   //
149   // Write the newly selected default value back to the variable store.
150   //
151   if (EFI_ERROR (Status)) {
152     Status = gRT->SetVariable(DT_ACPI_VARIABLE_NAME, &gDtPlatformFormSetGuid,
153                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
154                     sizeof (DtAcpiPref), &DtAcpiPref);
155     if (EFI_ERROR (Status)) {
156       goto FreeDtb;
157     }
158   }
159 
160   if (DtAcpiPref.Pref == DT_ACPI_SELECT_ACPI) {
161     //
162     // ACPI was selected: install the gEdkiiPlatformHasAcpiGuid GUID as a
163     // NULL protocol to unlock dispatch of ACPI related drivers.
164     //
165     Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
166                     &gEdkiiPlatformHasAcpiGuid, NULL, NULL);
167     if (EFI_ERROR (Status)) {
168       DEBUG ((DEBUG_ERROR,
169         "%a: failed to install gEdkiiPlatformHasAcpiGuid as a protocol\n",
170         __FUNCTION__));
171       goto FreeDtb;
172     }
173   } else if (DtAcpiPref.Pref == DT_ACPI_SELECT_DT) {
174     //
175     // DT was selected: copy the blob into newly allocated memory and install
176     // a reference to it as the FDT configuration table.
177     //
178     Status = gBS->InstallConfigurationTable (&gFdtTableGuid, Dtb);
179     if (EFI_ERROR (Status)) {
180       DEBUG ((DEBUG_ERROR, "%a: failed to install FDT configuration table\n",
181         __FUNCTION__));
182       goto FreeDtb;
183     }
184   } else {
185     ASSERT (FALSE);
186   }
187 
188   //
189   // No point in installing the HII pages if ACPI is the only description
190   // we have
191   //
192   if (Dtb == NULL) {
193     return EFI_SUCCESS;
194   }
195 
196   //
197   // Note that we don't uninstall the gEdkiiPlatformHasAcpiGuid protocol nor
198   // the FDT configuration table if the following call fails. While that will
199   // cause loading of this driver to fail, proceeding with ACPI and DT both
200   // disabled will guarantee a failed boot, and so it is better to leave them
201   // installed in that case.
202   //
203   return InstallHiiPages ();
204 
205 FreeDtb:
206   if (Dtb != NULL) {
207     FreePool (Dtb);
208   }
209 
210   return Status;
211 }
212