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