]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.c
996d1a6036b9fbe951c42a712a6e28b0a7044ed1
[mirror_edk2.git] / EmbeddedPkg / Drivers / ConsolePrefDxe / ConsolePrefDxe.c
1 /** @file
2 *
3 * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
4 *
5 * This program and the accompanying materials are licensed and made available
6 * under the terms and conditions of the BSD License which accompanies this
7 * 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 <Uefi.h>
16 #include <IndustryStandard/Acpi.h>
17 #include <libfdt.h>
18 #include <Library/BaseLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/DevicePathLib.h>
21 #include <Library/HiiLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/UefiDriverEntryPoint.h>
25 #include <Library/UefiLib.h>
26 #include <Library/UefiRuntimeServicesTableLib.h>
27
28 #include <Protocol/AcpiTable.h>
29 #include <Protocol/AcpiSystemDescriptionTable.h>
30
31 #include "ConsolePrefDxe.h"
32
33 #define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
34
35 extern UINT8 ConsolePrefHiiBin[];
36 extern UINT8 ConsolePrefDxeStrings[];
37
38 typedef struct {
39 VENDOR_DEVICE_PATH VendorDevicePath;
40 EFI_DEVICE_PATH_PROTOCOL End;
41 } HII_VENDOR_DEVICE_PATH;
42
43 STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath = {
44 {
45 {
46 HARDWARE_DEVICE_PATH,
47 HW_VENDOR_DP,
48 {
49 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
50 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
51 }
52 },
53 CONSOLE_PREF_FORMSET_GUID
54 },
55 {
56 END_DEVICE_PATH_TYPE,
57 END_ENTIRE_DEVICE_PATH_SUBTYPE,
58 {
59 (UINT8) (END_DEVICE_PATH_LENGTH),
60 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
61 }
62 }
63 };
64
65 STATIC EFI_EVENT mReadyToBootEvent;
66
67 STATIC
68 EFI_STATUS
69 InstallHiiPages (
70 VOID
71 )
72 {
73 EFI_STATUS Status;
74 EFI_HII_HANDLE HiiHandle;
75 EFI_HANDLE DriverHandle;
76
77 DriverHandle = NULL;
78 Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle,
79 &gEfiDevicePathProtocolGuid,
80 &mConsolePrefDxeVendorDevicePath,
81 NULL);
82 if (EFI_ERROR (Status)) {
83 return Status;
84 }
85
86 HiiHandle = HiiAddPackages (&gConsolePrefFormSetGuid,
87 DriverHandle,
88 ConsolePrefDxeStrings,
89 ConsolePrefHiiBin,
90 NULL);
91
92 if (HiiHandle == NULL) {
93 gBS->UninstallMultipleProtocolInterfaces (DriverHandle,
94 &gEfiDevicePathProtocolGuid,
95 &mConsolePrefDxeVendorDevicePath,
96 NULL);
97 return EFI_OUT_OF_RESOURCES;
98 }
99 return EFI_SUCCESS;
100 }
101
102 STATIC
103 VOID
104 RemoveDtStdoutPath (
105 VOID
106 )
107 {
108 VOID *Dtb;
109 INT32 Node;
110 INT32 Error;
111 EFI_STATUS Status;
112
113 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &Dtb);
114 if (EFI_ERROR (Status)) {
115 DEBUG ((DEBUG_INFO, "%a: could not retrieve DT blob - %r\n", __FUNCTION__,
116 Status));
117 return;
118 }
119
120 Node = fdt_path_offset (Dtb, "/chosen");
121 if (Node < 0) {
122 return;
123 }
124
125 Error = fdt_delprop (Dtb, Node, "stdout-path");
126 if (Error) {
127 DEBUG ((DEBUG_INFO, "%a: Failed to delete 'stdout-path' property: %a\n",
128 __FUNCTION__, fdt_strerror (Error)));
129 }
130 }
131
132 STATIC
133 VOID
134 RemoveSpcrTable (
135 VOID
136 )
137 {
138 EFI_ACPI_SDT_PROTOCOL *Sdt;
139 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
140 EFI_STATUS Status;
141 UINTN TableIndex;
142 EFI_ACPI_SDT_HEADER *TableHeader;
143 EFI_ACPI_TABLE_VERSION TableVersion;
144 UINTN TableKey;
145
146 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL,
147 (VOID **)&AcpiTable);
148 if (EFI_ERROR (Status)) {
149 return;
150 }
151
152 Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&Sdt);
153 if (EFI_ERROR (Status)) {
154 return;
155 }
156
157 TableIndex = 0;
158 TableKey = 0;
159 TableHeader = NULL;
160
161 do {
162 Status = Sdt->GetAcpiTable (TableIndex++, &TableHeader, &TableVersion,
163 &TableKey);
164 if (EFI_ERROR (Status)) {
165 break;
166 }
167
168 if (TableHeader->Signature != SPCR_SIG) {
169 continue;
170 }
171
172 Status = AcpiTable->UninstallAcpiTable (AcpiTable, TableKey);
173 if (EFI_ERROR (Status)) {
174 DEBUG ((DEBUG_WARN, "%a: failed to uninstall SPCR table - %r\n",
175 __FUNCTION__, Status));
176 }
177 break;
178 } while (TRUE);
179 }
180
181 STATIC
182 VOID
183 OnReadyToBoot (
184 IN EFI_EVENT Event,
185 IN VOID *Context
186 )
187 {
188 CONSOLE_PREF_VARSTORE_DATA ConsolePref;
189 UINTN BufferSize;
190 EFI_STATUS Status;
191 VOID *Gop;
192
193 BufferSize = sizeof (ConsolePref);
194 Status = gRT->GetVariable (CONSOLE_PREF_VARIABLE_NAME,
195 &gConsolePrefFormSetGuid, NULL, &BufferSize, &ConsolePref);
196 if (EFI_ERROR (Status)) {
197 DEBUG ((DEBUG_ERROR,
198 "%a: variable '%s' could not be read - bailing!\n", __FUNCTION__,
199 CONSOLE_PREF_VARIABLE_NAME));
200 return;
201 }
202
203 if (ConsolePref.Console == CONSOLE_PREF_SERIAL) {
204 DEBUG ((DEBUG_INFO,
205 "%a: serial console preferred - doing nothing\n", __FUNCTION__));
206 return;
207 }
208
209 //
210 // Check if any GOP instances exist: if so, disable stdout-path and SPCR
211 //
212 Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, &Gop);
213 if (EFI_ERROR (Status)) {
214 DEBUG ((DEBUG_INFO,
215 "%a: no GOP instances found - doing nothing (%r)\n", __FUNCTION__,
216 Status));
217 return;
218 }
219
220 RemoveDtStdoutPath ();
221 RemoveSpcrTable ();
222 }
223
224 /**
225 The entry point for ConsolePrefDxe driver.
226
227 @param[in] ImageHandle The image handle of the driver.
228 @param[in] SystemTable The system table.
229
230 @retval EFI_ALREADY_STARTED The driver already exists in system.
231 @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
232 resources.
233 @retval EFI_SUCCES All the related protocols are installed on
234 the driver.
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 ConsolePrefDxeEntryPoint (
240 IN EFI_HANDLE ImageHandle,
241 IN EFI_SYSTEM_TABLE *SystemTable
242 )
243 {
244 EFI_STATUS Status;
245 CONSOLE_PREF_VARSTORE_DATA ConsolePref;
246 UINTN BufferSize;
247
248 //
249 // Get the current console preference from the ConsolePref variable.
250 //
251 BufferSize = sizeof (ConsolePref);
252 Status = gRT->GetVariable (CONSOLE_PREF_VARIABLE_NAME,
253 &gConsolePrefFormSetGuid, NULL, &BufferSize, &ConsolePref);
254 if (EFI_ERROR (Status)) {
255 DEBUG ((DEBUG_INFO,
256 "%a: no console preference found, defaulting to graphical\n",
257 __FUNCTION__));
258 ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
259 }
260
261 if (!EFI_ERROR (Status) &&
262 ConsolePref.Console != CONSOLE_PREF_GRAPHICAL &&
263 ConsolePref.Console != CONSOLE_PREF_SERIAL) {
264 DEBUG ((DEBUG_WARN, "%a: invalid value for %s, defaulting to graphical\n",
265 __FUNCTION__, CONSOLE_PREF_VARIABLE_NAME));
266 ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
267 Status = EFI_INVALID_PARAMETER; // trigger setvar below
268 }
269
270 //
271 // Write the newly selected value back to the variable store.
272 //
273 if (EFI_ERROR (Status)) {
274 ZeroMem (&ConsolePref.Reserved, sizeof (ConsolePref.Reserved));
275 Status = gRT->SetVariable (CONSOLE_PREF_VARIABLE_NAME,
276 &gConsolePrefFormSetGuid,
277 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
278 sizeof (ConsolePref), &ConsolePref);
279
280 if (EFI_ERROR (Status)) {
281 DEBUG ((DEBUG_ERROR, "%a: gRT->SetVariable () failed - %r\n",
282 __FUNCTION__, Status));
283 return Status;
284 }
285 }
286
287 Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
288 OnReadyToBoot, NULL, &gEfiEventReadyToBootGuid,
289 &mReadyToBootEvent);
290 ASSERT_EFI_ERROR (Status);
291
292 return InstallHiiPages ();
293 }