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