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