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