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