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