]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/GenericBdsLib/BdsConsole.c
Remove SafeFreePool from MemoryAllocationLib as this API's name is misleading. Its...
[mirror_edk2.git] / MdeModulePkg / Library / GenericBdsLib / BdsConsole.c
CommitLineData
897f0eee 1/** @file\r
2 BDS Lib functions which contain all the code to connect console device\r
3\r
4Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "InternalBdsLib.h"\r
16\r
11ef23f9 17/**\r
18 Check if we need to save the EFI variable with "ConVarName" as name\r
19 as NV type\r
20\r
21 @param ConVarName The name of the EFI variable.\r
22\r
23 @retval TRUE Set the EFI variabel as NV type.\r
24 @retval FALSE EFI variabel as NV type can be set NonNV.\r
25**/\r
897f0eee 26BOOLEAN\r
27IsNvNeed (\r
28 IN CHAR16 *ConVarName\r
29 )\r
30{\r
31 CHAR16 *Ptr;\r
32\r
33 Ptr = ConVarName;\r
34\r
35 //\r
36 // If the variable includes "Dev" at last, we consider\r
37 // it does not support NV attribute.\r
38 //\r
11ef23f9 39 while (*Ptr != L'\0') {\r
897f0eee 40 Ptr++;\r
41 }\r
42\r
ec8cd35c 43 if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
897f0eee 44 return FALSE;\r
45 } else {\r
46 return TRUE;\r
47 }\r
48}\r
49\r
50\r
51/**\r
52 This function update console variable based on ConVarName, it can\r
53 add or remove one specific console device path from the variable\r
54\r
55 @param ConVarName Console related variable name, ConIn, ConOut,\r
56 ErrOut.\r
57 @param CustomizedConDevicePath The console device path which will be added to\r
58 the console variable ConVarName, this parameter\r
59 can not be multi-instance.\r
60 @param ExclusiveDevicePath The console device path which will be removed\r
61 from the console variable ConVarName, this\r
62 parameter can not be multi-instance.\r
63\r
64 @retval EFI_UNSUPPORTED Add or remove the same device path.\r
65 @retval EFI_SUCCESS Success add or remove the device path from the\r
66 console variable.\r
67\r
68**/\r
69EFI_STATUS\r
70EFIAPI\r
71BdsLibUpdateConsoleVariable (\r
72 IN CHAR16 *ConVarName,\r
73 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
74 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
75 )\r
76{\r
77 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
78 UINTN DevicePathSize;\r
79 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
80 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
81 UINT32 Attributes;\r
82\r
83 VarConsole = NULL;\r
84 DevicePathSize = 0;\r
85\r
86 //\r
87 // Notes: check the device path point, here should check\r
88 // with compare memory\r
89 //\r
90 if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
91 return EFI_UNSUPPORTED;\r
92 }\r
93 //\r
94 // Delete the ExclusiveDevicePath from current default console\r
95 //\r
96 VarConsole = BdsLibGetVariableAndSize (\r
97 ConVarName,\r
98 &gEfiGlobalVariableGuid,\r
99 &DevicePathSize\r
100 );\r
101\r
102 //\r
103 // Initialize NewDevicePath\r
104 //\r
105 NewDevicePath = VarConsole;\r
106\r
107 //\r
108 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
109 // In the end, NewDevicePath is the final device path.\r
110 //\r
111 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
112 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
113 }\r
114 //\r
115 // Try to append customized device path to NewDevicePath.\r
116 //\r
117 if (CustomizedConDevicePath != NULL) {\r
118 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
119 //\r
120 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
121 //\r
122 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
123 //\r
124 // In the first check, the default console variable will be _ModuleEntryPoint,\r
125 // just append current customized device path\r
126 //\r
127 TempNewDevicePath = NewDevicePath;\r
128 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
676df92c 129 if (TempNewDevicePath != NULL) {\r
130 FreePool(TempNewDevicePath);\r
131 }\r
897f0eee 132 }\r
133 }\r
134\r
135 //\r
136 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
137 //\r
138 if (IsNvNeed(ConVarName)) {\r
139 //\r
140 // ConVarName has NV attribute.\r
141 //\r
142 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
143 } else {\r
144 //\r
145 // ConVarName does not have NV attribute.\r
146 //\r
147 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
148 }\r
149\r
150 //\r
151 // Finally, Update the variable of the default console by NewDevicePath\r
152 //\r
153 gRT->SetVariable (\r
154 ConVarName,\r
155 &gEfiGlobalVariableGuid,\r
156 Attributes,\r
157 GetDevicePathSize (NewDevicePath),\r
158 NewDevicePath\r
159 );\r
160\r
161 if (VarConsole == NewDevicePath) {\r
676df92c 162 if (VarConsole != NULL) {\r
163 FreePool(VarConsole);\r
164 }\r
897f0eee 165 } else {\r
676df92c 166 if (VarConsole != NULL) {\r
167 FreePool(VarConsole);\r
168 }\r
169 if (NewDevicePath) {\r
170 FreePool(NewDevicePath);\r
171 }\r
897f0eee 172 }\r
173\r
174 return EFI_SUCCESS;\r
175\r
176}\r
177\r
178\r
179/**\r
180 Connect the console device base on the variable ConVarName, if\r
181 device path of the ConVarName is multi-instance device path, if\r
182 anyone of the instances is connected success, then this function\r
183 will return success.\r
184\r
185 @param ConVarName Console related variable name, ConIn, ConOut,\r
186 ErrOut.\r
187\r
188 @retval EFI_NOT_FOUND There is not any console devices connected\r
189 success\r
190 @retval EFI_SUCCESS Success connect any one instance of the console\r
191 device path base on the variable ConVarName.\r
192\r
193**/\r
194EFI_STATUS\r
195EFIAPI\r
196BdsLibConnectConsoleVariable (\r
197 IN CHAR16 *ConVarName\r
198 )\r
199{\r
200 EFI_STATUS Status;\r
201 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
202 UINTN VariableSize;\r
203 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
204 EFI_DEVICE_PATH_PROTOCOL *Next;\r
205 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
206 UINTN Size;\r
207 BOOLEAN DeviceExist;\r
208\r
209 Status = EFI_SUCCESS;\r
210 DeviceExist = FALSE;\r
211\r
212 //\r
213 // Check if the console variable exist\r
214 //\r
215 StartDevicePath = BdsLibGetVariableAndSize (\r
216 ConVarName,\r
217 &gEfiGlobalVariableGuid,\r
218 &VariableSize\r
219 );\r
220 if (StartDevicePath == NULL) {\r
221 return EFI_UNSUPPORTED;\r
222 }\r
223\r
224 CopyOfDevicePath = StartDevicePath;\r
225 do {\r
226 //\r
227 // Check every instance of the console variable\r
228 //\r
229 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
230 Next = Instance;\r
231 while (!IsDevicePathEndType (Next)) {\r
232 Next = NextDevicePathNode (Next);\r
233 }\r
234\r
235 SetDevicePathEndNode (Next);\r
236 //\r
237 // Check USB1.1 console\r
238 //\r
239 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
240 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
241 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
242 )) {\r
243 //\r
244 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus\r
245 //\r
246 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);\r
247 if (!EFI_ERROR (Status)) {\r
248 DeviceExist = TRUE;\r
249 }\r
250\r
251 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);\r
252 if (!EFI_ERROR (Status)) {\r
253 DeviceExist = TRUE;\r
254 }\r
255 } else {\r
256 //\r
257 // Connect the instance device path\r
258 //\r
259 Status = BdsLibConnectDevicePath (Instance);\r
260 if (EFI_ERROR (Status)) {\r
261 //\r
262 // Delete the instance from the console varialbe\r
263 //\r
264 BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
265 } else {\r
266 DeviceExist = TRUE;\r
267 }\r
268 }\r
676df92c 269 FreePool(Instance);\r
897f0eee 270 } while (CopyOfDevicePath != NULL);\r
271\r
676df92c 272 FreePool (StartDevicePath);\r
897f0eee 273\r
7471b8cd 274 if (!DeviceExist) {\r
897f0eee 275 return EFI_NOT_FOUND;\r
276 }\r
277\r
278 return EFI_SUCCESS;\r
279}\r
280\r
281\r
282/**\r
283 This function will search every simpletxt devive in current system,\r
284 and make every simpletxt device as pertantial console device.\r
285\r
286**/\r
287VOID\r
288EFIAPI\r
289BdsLibConnectAllConsoles (\r
290 VOID\r
291 )\r
292{\r
293 UINTN Index;\r
294 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
295 UINTN HandleCount;\r
296 EFI_HANDLE *HandleBuffer;\r
297\r
298 Index = 0;\r
299 HandleCount = 0;\r
300 HandleBuffer = NULL;\r
301 ConDevicePath = NULL;\r
302\r
303 //\r
304 // Update all the console varables\r
305 //\r
306 gBS->LocateHandleBuffer (\r
307 ByProtocol,\r
308 &gEfiSimpleTextInProtocolGuid,\r
309 NULL,\r
310 &HandleCount,\r
311 &HandleBuffer\r
312 );\r
313 \r
314 for (Index = 0; Index < HandleCount; Index++) {\r
315 gBS->HandleProtocol (\r
316 HandleBuffer[Index],\r
317 &gEfiDevicePathProtocolGuid,\r
318 (VOID **) &ConDevicePath\r
319 );\r
320 BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
321 }\r
322\r
676df92c 323 if (HandleBuffer != NULL) {\r
324 FreePool(HandleBuffer);\r
325 HandleBuffer = NULL;\r
326 }\r
897f0eee 327\r
328 gBS->LocateHandleBuffer (\r
329 ByProtocol,\r
330 &gEfiSimpleTextOutProtocolGuid,\r
331 NULL,\r
332 &HandleCount,\r
333 &HandleBuffer\r
334 );\r
335 for (Index = 0; Index < HandleCount; Index++) {\r
336 gBS->HandleProtocol (\r
337 HandleBuffer[Index],\r
338 &gEfiDevicePathProtocolGuid,\r
339 (VOID **) &ConDevicePath\r
340 );\r
341 BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
342 BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
343 }\r
344\r
676df92c 345 if (HandleBuffer != NULL) {\r
346 FreePool(HandleBuffer);\r
347 }\r
897f0eee 348\r
349 //\r
350 // Connect all console variables\r
351 //\r
352 BdsLibConnectAllDefaultConsoles ();\r
353\r
354}\r
355\r
897f0eee 356/**\r
357 This function will connect console device base on the console\r
358 device variable ConIn, ConOut and ErrOut.\r
359\r
360 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
361 been connected success.\r
362 @retval EFI_STATUS Return the status of\r
363 BdsLibConnectConsoleVariable ().\r
364\r
365**/\r
366EFI_STATUS\r
367EFIAPI\r
368BdsLibConnectAllDefaultConsoles (\r
369 VOID\r
370 )\r
371{\r
372 EFI_STATUS Status;\r
373\r
374 //\r
375 // Connect all default console variables\r
376 //\r
377\r
378 //\r
379 // It seems impossible not to have any ConOut device on platform,\r
380 // so we check the status here.\r
381 //\r
382 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
383 if (EFI_ERROR (Status)) {\r
384 return Status;\r
385 }\r
386\r
387 //\r
388 // Insert the performance probe for Console Out\r
389 //\r
390 PERF_START (NULL, "ConOut", "BDS", 1);\r
391 PERF_END (NULL, "ConOut", "BDS", 0);\r
392\r
393 //\r
394 // Because possibly the platform is legacy free, in such case,\r
395 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
396 // so we need not check the status.\r
397 //\r
398 BdsLibConnectConsoleVariable (L"ConIn");\r
399\r
400 //\r
401 // The _ModuleEntryPoint err out var is legal.\r
402 //\r
403 BdsLibConnectConsoleVariable (L"ErrOut");\r
404\r
405 return EFI_SUCCESS;\r
406\r
407}\r