]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
Add new interface GetVariable2 and GetEfiGlobalVariable2 to return more info. Also...
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
CommitLineData
fb0b259e 1/** @file\r
11baadb6 2 Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and\r
fb0b259e 3 Simple Text Output Protocol upon Serial IO Protocol.\r
95276127 4\r
bf4a3dbd 5Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials\r
95276127 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
fb0b259e 14**/\r
95276127 15\r
16\r
95276127 17#include "Terminal.h"\r
18\r
95276127 19//\r
20// Globals\r
21//\r
22EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
23 TerminalDriverBindingSupported,\r
24 TerminalDriverBindingStart,\r
25 TerminalDriverBindingStop,\r
26 0xa,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
31\r
6b88ceec
A
32EFI_GUID *gTerminalType[] = {\r
33 &gEfiPcAnsiGuid,\r
34 &gEfiVT100Guid,\r
35 &gEfiVT100PlusGuid,\r
36 &gEfiVTUTF8Guid\r
37};\r
38\r
39\r
204ba917 40TERMINAL_DEV mTerminalDevTemplate = {\r
6b88ceec
A
41 TERMINAL_DEV_SIGNATURE,\r
42 NULL,\r
43 0,\r
44 NULL,\r
45 NULL,\r
46 { // SimpleTextInput\r
47 TerminalConInReset,\r
48 TerminalConInReadKeyStroke,\r
49 NULL\r
50 },\r
51 { // SimpleTextOutput\r
52 TerminalConOutReset,\r
53 TerminalConOutOutputString,\r
54 TerminalConOutTestString,\r
55 TerminalConOutQueryMode,\r
56 TerminalConOutSetMode,\r
57 TerminalConOutSetAttribute,\r
58 TerminalConOutClearScreen,\r
59 TerminalConOutSetCursorPosition,\r
60 TerminalConOutEnableCursor,\r
61 NULL\r
62 },\r
63 { // SimpleTextOutputMode\r
64 1, // MaxMode\r
11baadb6 65 0, // Mode\r
6b88ceec
A
66 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
67 0, // CursorColumn\r
68 0, // CursorRow\r
69 TRUE // CursorVisible\r
70 },\r
79d07c66 71 NULL, // TerminalConsoleModeData\r
11baadb6 72 0, // SerialInTimeOut\r
5c998646 73\r
74 NULL, // RawFifo\r
75 NULL, // UnicodeFiFo\r
76 NULL, // EfiKeyFiFo\r
77\r
6b88ceec 78 NULL, // ControllerNameTable\r
f0368006 79 NULL, // TimerEvent\r
11baadb6 80 NULL, // TwoSecondTimeOut\r
6b88ceec
A
81 INPUT_STATE_DEFAULT,\r
82 RESET_STATE_DEFAULT,\r
66aa04e4 83 FALSE,\r
84 { // SimpleTextInputEx\r
85 TerminalConInResetEx,\r
86 TerminalConInReadKeyStrokeEx,\r
87 NULL,\r
88 TerminalConInSetState,\r
89 TerminalConInRegisterKeyNotify,\r
90 TerminalConInUnregisterKeyNotify,\r
91 },\r
11baadb6 92 { // NotifyList\r
66aa04e4 93 NULL,\r
94 NULL,\r
95 }\r
6b88ceec
A
96};\r
97\r
79d07c66 98TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
99 {100, 31},\r
100 //\r
101 // New modes can be added here.\r
79d07c66 102 //\r
79d07c66 103};\r
104\r
8fd98315 105/**\r
677fdb90 106 Test to see if this driver supports Controller.\r
8fd98315 107\r
108 @param This Protocol instance pointer.\r
ab76200c 109 @param Controller Handle of device to test\r
8fd98315 110 @param RemainingDevicePath Optional parameter use to pick a specific child\r
111 device to start.\r
112\r
ab76200c 113 @retval EFI_SUCCESS This driver supports this device.\r
114 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
115 @retval other This driver does not support this device.\r
6b88ceec 116\r
8fd98315 117**/\r
95276127 118EFI_STATUS\r
119EFIAPI\r
120TerminalDriverBindingSupported (\r
121 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
122 IN EFI_HANDLE Controller,\r
123 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
124 )\r
125{\r
126 EFI_STATUS Status;\r
127 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
128 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
129 VENDOR_DEVICE_PATH *Node;\r
130\r
131 //\r
132 // If remaining device path is not NULL, then make sure it is a\r
133 // device path that describes a terminal communications protocol.\r
134 //\r
135 if (RemainingDevicePath != NULL) {\r
95276127 136 //\r
e3dcffcc 137 // Check if RemainingDevicePath is the End of Device Path Node,\r
af4a6385 138 // if yes, go on checking other conditions\r
95276127 139 //\r
af4a6385 140 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
141 //\r
142 // If RemainingDevicePath isn't the End of Device Path Node,\r
143 // check its validation\r
144 //\r
145 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
e3dcffcc 146\r
af4a6385 147 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
148 Node->Header.SubType != MSG_VENDOR_DP ||\r
149 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
e3dcffcc 150\r
af4a6385 151 return EFI_UNSUPPORTED;\r
e3dcffcc 152\r
af4a6385 153 }\r
154 //\r
155 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types\r
156 //\r
157 if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
158 !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
159 !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
160 !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
e3dcffcc 161\r
af4a6385 162 return EFI_UNSUPPORTED;\r
163 }\r
95276127 164 }\r
165 }\r
166 //\r
167 // Open the IO Abstraction(s) needed to perform the supported test\r
af4a6385 168 // The Controller must support the Serial I/O Protocol.\r
169 // This driver is a bus driver with at most 1 child device, so it is\r
170 // ok for it to be already started.\r
95276127 171 //\r
172 Status = gBS->OpenProtocol (\r
173 Controller,\r
af4a6385 174 &gEfiSerialIoProtocolGuid,\r
175 (VOID **) &SerialIo,\r
95276127 176 This->DriverBindingHandle,\r
177 Controller,\r
178 EFI_OPEN_PROTOCOL_BY_DRIVER\r
179 );\r
180 if (Status == EFI_ALREADY_STARTED) {\r
181 return EFI_SUCCESS;\r
182 }\r
183\r
184 if (EFI_ERROR (Status)) {\r
185 return Status;\r
186 }\r
187\r
af4a6385 188 //\r
189 // Close the I/O Abstraction(s) used to perform the supported test\r
190 //\r
95276127 191 gBS->CloseProtocol (\r
192 Controller,\r
af4a6385 193 &gEfiSerialIoProtocolGuid,\r
95276127 194 This->DriverBindingHandle,\r
195 Controller\r
196 );\r
197\r
198 //\r
af4a6385 199 // Open the EFI Device Path protocol needed to perform the supported test\r
95276127 200 //\r
201 Status = gBS->OpenProtocol (\r
202 Controller,\r
af4a6385 203 &gEfiDevicePathProtocolGuid,\r
204 (VOID **) &ParentDevicePath,\r
95276127 205 This->DriverBindingHandle,\r
206 Controller,\r
207 EFI_OPEN_PROTOCOL_BY_DRIVER\r
208 );\r
209 if (Status == EFI_ALREADY_STARTED) {\r
210 return EFI_SUCCESS;\r
211 }\r
212\r
213 if (EFI_ERROR (Status)) {\r
214 return Status;\r
215 }\r
af4a6385 216\r
95276127 217 //\r
af4a6385 218 // Close protocol, don't use device path protocol in the Support() function\r
95276127 219 //\r
220 gBS->CloseProtocol (\r
221 Controller,\r
af4a6385 222 &gEfiDevicePathProtocolGuid,\r
95276127 223 This->DriverBindingHandle,\r
224 Controller\r
225 );\r
226\r
227 return Status;\r
228}\r
229\r
e3dcffcc 230/**\r
231 Build the terminal device path for the child device according to the\r
232 terminal type.\r
233\r
234 @param ParentDevicePath Parent device path.\r
235 @param RemainingDevicePath A specific child device.\r
236\r
237 @return The child device path built.\r
238\r
239**/\r
240EFI_DEVICE_PATH_PROTOCOL*\r
241EFIAPI\r
242BuildTerminalDevpath (\r
243 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
244 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
245 )\r
246{\r
247 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
248 UINT8 TerminalType;\r
249 VENDOR_DEVICE_PATH *Node;\r
250 EFI_STATUS Status;\r
251\r
252 TerminalDevicePath = NULL;\r
253 TerminalType = PCANSITYPE;\r
254\r
255 //\r
256 // Use the RemainingDevicePath to determine the terminal type\r
257 //\r
258 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
259 if (Node == NULL) {\r
260 TerminalType = PCANSITYPE;\r
261\r
262 } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
263\r
264 TerminalType = PCANSITYPE;\r
265\r
266 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
267\r
268 TerminalType = VT100TYPE;\r
269\r
270 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
271\r
272 TerminalType = VT100PLUSTYPE;\r
273\r
274 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
275\r
276 TerminalType = VTUTF8TYPE;\r
277\r
278 } else {\r
279 return NULL;\r
280 }\r
281\r
282 //\r
283 // Build the device path for the child device\r
284 //\r
285 Status = SetTerminalDevicePath (\r
286 TerminalType,\r
287 ParentDevicePath,\r
288 &TerminalDevicePath\r
289 );\r
290 if (EFI_ERROR (Status)) {\r
291 return NULL;\r
292 }\r
293 return TerminalDevicePath;\r
294}\r
295\r
296/**\r
297 Compare a device path data structure to that of all the nodes of a\r
298 second device path instance.\r
299\r
300 @param Multi A pointer to a multi-instance device path data structure.\r
301 @param Single A pointer to a single-instance device path data structure.\r
302\r
303 @retval TRUE If the Single is contained within Multi.\r
304 @retval FALSE The Single is not match within Multi.\r
305\r
306**/\r
307BOOLEAN\r
308MatchDevicePaths (\r
309 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
310 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
311 )\r
312{\r
313 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
314 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
315 UINTN Size;\r
316\r
317 DevicePath = Multi;\r
318 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
319 //\r
320 // Search for the match of 'Single' in 'Multi'\r
321 //\r
322 while (DevicePathInst != NULL) {\r
323 //\r
324 // If the single device path is found in multiple device paths,\r
325 // return success\r
326 //\r
327 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
328 FreePool (DevicePathInst);\r
329 return TRUE;\r
330 }\r
331\r
332 FreePool (DevicePathInst);\r
333 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
334 }\r
335\r
336 return FALSE;\r
337}\r
338\r
339/**\r
340 Check whether the terminal device path is in the global variable.\r
341\r
342 @param VariableName Pointer to one global variable.\r
343 @param TerminalDevicePath Pointer to the terminal device's device path.\r
344\r
345 @retval TRUE The devcie is in the global variable.\r
346 @retval FALSE The devcie is not in the global variable.\r
347\r
348**/\r
349BOOLEAN\r
350IsTerminalInConsoleVariable (\r
351 IN CHAR16 *VariableName,\r
352 IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
353 )\r
354{\r
355 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
356 BOOLEAN ReturnFlag;\r
357\r
358 //\r
359 // Get global variable and its size according to the name given.\r
360 //\r
bf4a3dbd 361 GetEfiGlobalVariable2 (VariableName, &Variable, NULL);\r
e3dcffcc 362 if (Variable == NULL) {\r
363 return FALSE;\r
364 }\r
365\r
366 //\r
367 // Check whether the terminal device path is one of the variable instances.\r
368 //\r
369 ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
370\r
371 FreePool (Variable);\r
372\r
373 return ReturnFlag;\r
374}\r
375\r
376/**\r
377 Free notify functions list.\r
378\r
379 @param ListHead The list head\r
380\r
381 @retval EFI_SUCCESS Free the notify list successfully.\r
382 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
383\r
384**/\r
385EFI_STATUS\r
386TerminalFreeNotifyList (\r
387 IN OUT LIST_ENTRY *ListHead\r
388 )\r
389{\r
390 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
391\r
392 if (ListHead == NULL) {\r
393 return EFI_INVALID_PARAMETER;\r
394 }\r
395 while (!IsListEmpty (ListHead)) {\r
396 NotifyNode = CR (\r
397 ListHead->ForwardLink,\r
398 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
399 NotifyEntry,\r
400 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
401 );\r
402 RemoveEntryList (ListHead->ForwardLink);\r
403 FreePool (NotifyNode);\r
404 }\r
405\r
406 return EFI_SUCCESS;\r
407}\r
408\r
79d07c66 409/**\r
410 Initialize all the text modes which the terminal console supports.\r
411\r
412 It returns information for available text modes that the terminal can support.\r
413\r
414 @param[out] TextModeCount The total number of text modes that terminal console supports.\r
415 @param[out] TextModeData The buffer to the text modes column and row information.\r
416 Caller is responsible to free it when it's non-NULL.\r
417\r
418 @retval EFI_SUCCESS The supporting mode information is returned.\r
419 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
420\r
421**/\r
422EFI_STATUS\r
423InitializeTerminalConsoleTextMode (\r
424 OUT UINTN *TextModeCount,\r
425 OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
426 )\r
427{\r
428 UINTN Index;\r
429 UINTN Count;\r
430 TERMINAL_CONSOLE_MODE_DATA *ModeBuffer;\r
431 TERMINAL_CONSOLE_MODE_DATA *NewModeBuffer;\r
432 UINTN ValidCount;\r
433 UINTN ValidIndex;\r
434 \r
435 if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
436 return EFI_INVALID_PARAMETER;\r
437 }\r
438 \r
79d07c66 439 Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
79d07c66 440 \r
441 //\r
442 // Get defined mode buffer pointer.\r
443 //\r
444 ModeBuffer = mTerminalConsoleModeData;\r
445 \r
446 //\r
447 // Here we make sure that the final mode exposed does not include the duplicated modes,\r
448 // and does not include the invalid modes which exceed the max column and row.\r
449 // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
450 //\r
451 NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
452 ASSERT (NewModeBuffer != NULL);\r
453\r
454 //\r
455 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
456 //\r
457 ValidCount = 0; \r
458\r
459 NewModeBuffer[ValidCount].Columns = 80;\r
460 NewModeBuffer[ValidCount].Rows = 25;\r
461 ValidCount++;\r
462\r
463 NewModeBuffer[ValidCount].Columns = 80;\r
464 NewModeBuffer[ValidCount].Rows = 50;\r
465 ValidCount++;\r
466 \r
467 //\r
468 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
469 //\r
470 for (Index = 0; Index < Count; Index++) {\r
471 if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
472 //\r
473 // Skip the pre-defined mode which is invalid.\r
474 //\r
475 continue;\r
476 }\r
477 for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
478 if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
479 (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
480 //\r
481 // Skip the duplicated mode.\r
482 //\r
483 break;\r
484 }\r
485 }\r
486 if (ValidIndex == ValidCount) {\r
487 NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
488 NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;\r
489 ValidCount++;\r
490 }\r
491 }\r
492 \r
493 DEBUG_CODE (\r
494 for (Index = 0; Index < ValidCount; Index++) {\r
495 DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
496 Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); \r
497 }\r
498 );\r
499 \r
500 //\r
501 // Return valid mode count and mode information buffer.\r
502 //\r
503 *TextModeCount = ValidCount;\r
504 *TextModeData = NewModeBuffer;\r
505 return EFI_SUCCESS;\r
506}\r
e3dcffcc 507\r
e49ef433 508/**\r
ab76200c 509 Start this driver on Controller by opening a Serial IO protocol,\r
8fd98315 510 reading Device Path, and creating a child handle with a Simple Text In,\r
511 Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
512 And store Console Device Environment Variables.\r
e49ef433 513\r
8fd98315 514 @param This Protocol instance pointer.\r
ab76200c 515 @param Controller Handle of device to bind driver to\r
8fd98315 516 @param RemainingDevicePath Optional parameter use to pick a specific child\r
517 device to start.\r
e49ef433 518\r
ab76200c 519 @retval EFI_SUCCESS This driver is added to Controller.\r
520 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
521 @retval other This driver does not support this device.\r
e49ef433 522\r
523**/\r
95276127 524EFI_STATUS\r
525EFIAPI\r
526TerminalDriverBindingStart (\r
527 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
528 IN EFI_HANDLE Controller,\r
529 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
530 )\r
95276127 531{\r
532 EFI_STATUS Status;\r
533 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
534 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
535 VENDOR_DEVICE_PATH *Node;\r
536 VENDOR_DEVICE_PATH *DefaultNode;\r
537 EFI_SERIAL_IO_MODE *Mode;\r
538 UINTN SerialInTimeOut;\r
539 TERMINAL_DEV *TerminalDevice;\r
540 UINT8 TerminalType;\r
541 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
542 UINTN EntryCount;\r
543 UINTN Index;\r
544 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
c4f9201e 545 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
e3dcffcc 546 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;\r
547 BOOLEAN ConInSelected;\r
548 BOOLEAN ConOutSelected;\r
549 BOOLEAN NullRemaining;\r
550 BOOLEAN SimTxtInInstalled;\r
551 BOOLEAN SimTxtOutInstalled;\r
552 BOOLEAN FirstEnter;\r
79d07c66 553 UINTN ModeCount;\r
e3dcffcc 554\r
555 TerminalDevice = NULL;\r
556 DefaultNode = NULL;\r
557 ConInSelected = FALSE;\r
558 ConOutSelected = FALSE;\r
559 NullRemaining = TRUE;\r
560 SimTxtInInstalled = FALSE;\r
561 SimTxtOutInstalled = FALSE;\r
562 FirstEnter = FALSE;\r
95276127 563 //\r
564 // Get the Device Path Protocol to build the device path of the child device\r
565 //\r
566 Status = gBS->OpenProtocol (\r
567 Controller,\r
568 &gEfiDevicePathProtocolGuid,\r
569 (VOID **) &ParentDevicePath,\r
570 This->DriverBindingHandle,\r
571 Controller,\r
572 EFI_OPEN_PROTOCOL_BY_DRIVER\r
573 );\r
574 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
575 return Status;\r
576 }\r
95276127 577\r
578 //\r
579 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.\r
580 //\r
581 Status = gBS->OpenProtocol (\r
582 Controller,\r
583 &gEfiSerialIoProtocolGuid,\r
584 (VOID **) &SerialIo,\r
585 This->DriverBindingHandle,\r
586 Controller,\r
587 EFI_OPEN_PROTOCOL_BY_DRIVER\r
588 );\r
589 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
590 return Status;\r
591 }\r
592\r
593 if (Status != EFI_ALREADY_STARTED) {\r
594 //\r
e3dcffcc 595 // the serial I/O protocol never be opened before, it is the first\r
596 // time to start the serial Io controller\r
95276127 597 //\r
e3dcffcc 598 FirstEnter = TRUE;\r
95276127 599 }\r
e3dcffcc 600\r
95276127 601 //\r
e3dcffcc 602 // Serial I/O is not already open by this driver, then tag the handle\r
603 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
604 // StdErrDev variables with the list of possible terminal types on this\r
605 // serial port.\r
95276127 606 //\r
e3dcffcc 607 Status = gBS->OpenProtocol (\r
95276127 608 Controller,\r
e3dcffcc 609 &gEfiCallerIdGuid,\r
610 NULL,\r
611 This->DriverBindingHandle,\r
612 Controller,\r
613 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
95276127 614 );\r
e3dcffcc 615 if (EFI_ERROR (Status)) {\r
616 Status = gBS->InstallMultipleProtocolInterfaces (\r
617 &Controller,\r
618 &gEfiCallerIdGuid,\r
619 DuplicateDevicePath (ParentDevicePath),\r
620 NULL\r
621 );\r
622 if (EFI_ERROR (Status)) {\r
623 goto Error;\r
95276127 624 }\r
625\r
e3dcffcc 626 if (!IsHotPlugDevice (ParentDevicePath)) {\r
627 //\r
628 // if the serial device is a hot plug device, do not update the\r
629 // ConInDev, ConOutDev, and StdErrDev variables.\r
630 //\r
631 TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
632 TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
633 TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 634 }\r
635 }\r
e3dcffcc 636\r
637 //\r
638 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
95276127 639 //\r
e3dcffcc 640 // Simple In/Out Protocol will not be installed onto the handle if the\r
641 // device path to the handle is not present in the ConIn/ConOut\r
642 // environment variable. But If RemainingDevicePath is NULL, then always\r
643 // produce both Simple In and Simple Text Output Protocols. This is required\r
644 // for the connect all sequences to make sure all possible consoles are\r
645 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 646 //\r
647 if (RemainingDevicePath == NULL) {\r
e3dcffcc 648 NullRemaining = TRUE;\r
649 }\r
650\r
651 DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
652 if (DevicePath != NULL) {\r
653 ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
654 ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
655 FreePool (DevicePath);\r
656 } else {\r
657 goto Error;\r
658 }\r
659 //\r
660 // Not create the child terminal handle if both Simple In/In Ex and\r
661 // Simple text Out protocols are not required to be published\r
662 //\r
663 if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
664 goto Error;\r
665 }\r
666\r
667 //\r
668 // create the child terminal handle during first entry\r
669 //\r
670 if (FirstEnter) {\r
671 //\r
672 // First enther the start funciton\r
673 //\r
674 FirstEnter = FALSE;\r
675 //\r
676 // Make sure a child handle does not already exist. This driver can only\r
677 // produce one child per serial port.\r
678 //\r
679 Status = gBS->OpenProtocolInformation (\r
680 Controller,\r
681 &gEfiSerialIoProtocolGuid,\r
682 &OpenInfoBuffer,\r
683 &EntryCount\r
684 );\r
685 if (!EFI_ERROR (Status)) {\r
686 Status = EFI_SUCCESS;\r
687 for (Index = 0; Index < EntryCount; Index++) {\r
688 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
689 Status = EFI_ALREADY_STARTED;\r
690 }\r
691 }\r
692\r
693 FreePool (OpenInfoBuffer);\r
694 if (EFI_ERROR (Status)) {\r
695 goto Error;\r
696 }\r
697 }\r
698\r
699 //\r
700 // If RemainingDevicePath is NULL, then create default device path node\r
701 //\r
702 if (RemainingDevicePath == NULL) {\r
703 DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
704 if (DefaultNode == NULL) {\r
705 Status = EFI_OUT_OF_RESOURCES;\r
706 goto Error;\r
707 }\r
708\r
188e4e84 709 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 710 //\r
711 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)\r
712 //\r
713 ASSERT (TerminalType <= VTUTF8TYPE);\r
714\r
715 CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
716 RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
717 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
718 //\r
719 // If RemainingDevicePath isn't the End of Device Path Node,\r
720 // Use the RemainingDevicePath to determine the terminal type\r
721 //\r
722 Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
723 if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
724 TerminalType = PCANSITYPE;\r
725 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
726 TerminalType = VT100TYPE;\r
727 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
728 TerminalType = VT100PLUSTYPE;\r
729 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
730 TerminalType = VTUTF8TYPE;\r
731 } else {\r
732 goto Error;\r
733 }\r
734 } else {\r
735 //\r
736 // If RemainingDevicePath is the End of Device Path Node,\r
737 // skip enumerate any device and return EFI_SUCESSS\r
738 //\r
739 return EFI_SUCCESS;\r
740 }\r
741\r
742 //\r
743 // Initialize the Terminal Dev\r
744 //\r
745 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
746 if (TerminalDevice == NULL) {\r
95276127 747 Status = EFI_OUT_OF_RESOURCES;\r
748 goto Error;\r
749 }\r
750\r
e3dcffcc 751 TerminalDevice->TerminalType = TerminalType;\r
752 TerminalDevice->SerialIo = SerialIo;\r
753\r
754 InitializeListHead (&TerminalDevice->NotifyList);\r
755 Status = gBS->CreateEvent (\r
756 EVT_NOTIFY_WAIT,\r
757 TPL_NOTIFY,\r
758 TerminalConInWaitForKeyEx,\r
f0368006 759 TerminalDevice,\r
e3dcffcc 760 &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
761 );\r
762 if (EFI_ERROR (Status)) {\r
763 goto Error;\r
764 }\r
765\r
766 Status = gBS->CreateEvent (\r
767 EVT_NOTIFY_WAIT,\r
768 TPL_NOTIFY,\r
769 TerminalConInWaitForKey,\r
f0368006 770 TerminalDevice,\r
e3dcffcc 771 &TerminalDevice->SimpleInput.WaitForKey\r
772 );\r
773 if (EFI_ERROR (Status)) {\r
774 goto Error;\r
775 }\r
8fd98315 776 //\r
e3dcffcc 777 // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
778 // the pre-read pending characters.\r
8fd98315 779 //\r
e3dcffcc 780 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
781 if (TerminalDevice->RawFiFo == NULL) {\r
782 goto Error;\r
783 }\r
784 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
785 if (TerminalDevice->UnicodeFiFo == NULL) {\r
786 goto Error;\r
787 }\r
788 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
789 if (TerminalDevice->EfiKeyFiFo == NULL) {\r
790 goto Error;\r
791 }\r
95276127 792\r
6b88ceec 793 //\r
e3dcffcc 794 // Set the timeout value of serial buffer for\r
795 // keystroke response performance issue\r
6b88ceec 796 //\r
e3dcffcc 797 Mode = TerminalDevice->SerialIo->Mode;\r
798\r
799 SerialInTimeOut = 0;\r
800 if (Mode->BaudRate != 0) {\r
801 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
802 }\r
803\r
804 Status = TerminalDevice->SerialIo->SetAttributes (\r
805 TerminalDevice->SerialIo,\r
806 Mode->BaudRate,\r
807 Mode->ReceiveFifoDepth,\r
808 (UINT32) SerialInTimeOut,\r
809 (EFI_PARITY_TYPE) (Mode->Parity),\r
810 (UINT8) Mode->DataBits,\r
811 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
812 );\r
813 if (EFI_ERROR (Status)) {\r
814 //\r
815 // if set attributes operation fails, invalidate\r
816 // the value of SerialInTimeOut,thus make it\r
817 // inconsistent with the default timeout value\r
818 // of serial buffer. This will invoke the recalculation\r
819 // in the readkeystroke routine.\r
820 //\r
821 TerminalDevice->SerialInTimeOut = 0;\r
6b88ceec 822 } else {\r
e3dcffcc 823 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
6b88ceec 824 }\r
af4a6385 825 //\r
e3dcffcc 826 // Set Simple Text Output Protocol from template.\r
827 //\r
828 SimpleTextOutput = CopyMem (\r
829 &TerminalDevice->SimpleTextOutput,\r
830 &mTerminalDevTemplate.SimpleTextOutput,\r
831 sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
832 );\r
833 SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
79d07c66 834 \r
835 Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
836 if (EFI_ERROR (Status)) {\r
837 goto ReportError;\r
838 }\r
839 TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
840 \r
e3dcffcc 841 //\r
842 // For terminal devices, cursor is always visible\r
843 //\r
844 TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
845 Status = TerminalConOutSetAttribute (\r
846 SimpleTextOutput,\r
847 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
848 );\r
849 if (EFI_ERROR (Status)) {\r
850 goto ReportError;\r
851 }\r
6b88ceec 852\r
e3dcffcc 853 //\r
854 // Build the component name for the child device\r
855 //\r
856 TerminalDevice->ControllerNameTable = NULL;\r
857 switch (TerminalDevice->TerminalType) {\r
858 case PCANSITYPE:\r
859 AddUnicodeString2 (\r
860 "eng",\r
861 gTerminalComponentName.SupportedLanguages,\r
862 &TerminalDevice->ControllerNameTable,\r
863 (CHAR16 *)L"PC-ANSI Serial Console",\r
864 TRUE\r
865 );\r
866 AddUnicodeString2 (\r
867 "en",\r
868 gTerminalComponentName2.SupportedLanguages,\r
869 &TerminalDevice->ControllerNameTable,\r
870 (CHAR16 *)L"PC-ANSI Serial Console",\r
871 FALSE\r
872 );\r
95276127 873\r
e3dcffcc 874 break;\r
66aa04e4 875\r
e3dcffcc 876 case VT100TYPE:\r
877 AddUnicodeString2 (\r
878 "eng",\r
879 gTerminalComponentName.SupportedLanguages,\r
880 &TerminalDevice->ControllerNameTable,\r
881 (CHAR16 *)L"VT-100 Serial Console",\r
882 TRUE\r
883 );\r
884 AddUnicodeString2 (\r
885 "en",\r
886 gTerminalComponentName2.SupportedLanguages,\r
887 &TerminalDevice->ControllerNameTable,\r
888 (CHAR16 *)L"VT-100 Serial Console",\r
889 FALSE\r
890 );\r
891\r
892 break;\r
893\r
894 case VT100PLUSTYPE:\r
895 AddUnicodeString2 (\r
896 "eng",\r
897 gTerminalComponentName.SupportedLanguages,\r
898 &TerminalDevice->ControllerNameTable,\r
899 (CHAR16 *)L"VT-100+ Serial Console",\r
900 TRUE\r
901 );\r
902 AddUnicodeString2 (\r
903 "en",\r
904 gTerminalComponentName2.SupportedLanguages,\r
905 &TerminalDevice->ControllerNameTable,\r
906 (CHAR16 *)L"VT-100+ Serial Console",\r
907 FALSE\r
908 );\r
909\r
910 break;\r
911\r
912 case VTUTF8TYPE:\r
913 AddUnicodeString2 (\r
914 "eng",\r
915 gTerminalComponentName.SupportedLanguages,\r
916 &TerminalDevice->ControllerNameTable,\r
917 (CHAR16 *)L"VT-UTF8 Serial Console",\r
918 TRUE\r
919 );\r
920 AddUnicodeString2 (\r
921 "en",\r
922 gTerminalComponentName2.SupportedLanguages,\r
923 &TerminalDevice->ControllerNameTable,\r
924 (CHAR16 *)L"VT-UTF8 Serial Console",\r
925 FALSE\r
926 );\r
927\r
928 break;\r
929 }\r
95276127 930\r
95276127 931 //\r
e3dcffcc 932 // Build the device path for the child device\r
95276127 933 //\r
e3dcffcc 934 Status = SetTerminalDevicePath (\r
935 TerminalDevice->TerminalType,\r
936 ParentDevicePath,\r
937 &TerminalDevice->DevicePath\r
938 );\r
939 if (EFI_ERROR (Status)) {\r
940 goto Error;\r
941 }\r
95276127 942\r
abef1c7a 943 Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
944 if (EFI_ERROR (Status)) {\r
945 goto ReportError;\r
946 }\r
947\r
948 Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
949 if (EFI_ERROR (Status)) {\r
950 goto ReportError;\r
951 }\r
952\r
953 Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
954 if (EFI_ERROR (Status)) {\r
955 goto ReportError;\r
956 }\r
957\r
f0368006
RN
958 Status = gBS->CreateEvent (\r
959 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
960 TPL_NOTIFY,\r
961 TerminalConInTimerHandler,\r
962 TerminalDevice,\r
963 &TerminalDevice->TimerEvent\r
964 );\r
965 ASSERT_EFI_ERROR (Status);\r
966\r
967 Status = gBS->SetTimer (\r
968 TerminalDevice->TimerEvent,\r
969 TimerPeriodic,\r
970 KEYBOARD_TIMER_INTERVAL\r
971 );\r
972 ASSERT_EFI_ERROR (Status);\r
973\r
abef1c7a 974 Status = gBS->CreateEvent (\r
975 EVT_TIMER,\r
976 TPL_CALLBACK,\r
977 NULL,\r
978 NULL,\r
979 &TerminalDevice->TwoSecondTimeOut\r
980 );\r
f0368006 981 ASSERT_EFI_ERROR (Status);\r
abef1c7a 982\r
e3dcffcc 983 Status = gBS->InstallProtocolInterface (\r
984 &TerminalDevice->Handle,\r
985 &gEfiDevicePathProtocolGuid,\r
986 EFI_NATIVE_INTERFACE,\r
987 TerminalDevice->DevicePath\r
988 );\r
989 if (EFI_ERROR (Status)) {\r
990 goto Error;\r
991 }\r
95276127 992\r
95276127 993 //\r
e3dcffcc 994 // Register the Parent-Child relationship via\r
995 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
95276127 996 //\r
e3dcffcc 997 Status = gBS->OpenProtocol (\r
998 Controller,\r
999 &gEfiSerialIoProtocolGuid,\r
1000 (VOID **) &TerminalDevice->SerialIo,\r
1001 This->DriverBindingHandle,\r
1002 TerminalDevice->Handle,\r
1003 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1004 );\r
1005 if (EFI_ERROR (Status)) {\r
1006 goto Error;\r
1007 }\r
95276127 1008 }\r
95276127 1009\r
3012ce5c 1010 //\r
e3dcffcc 1011 // Find the child handle, and get its TerminalDevice private data\r
3012ce5c 1012 //\r
e3dcffcc 1013 Status = gBS->OpenProtocolInformation (\r
1014 Controller,\r
1015 &gEfiSerialIoProtocolGuid,\r
1016 &OpenInfoBuffer,\r
1017 &EntryCount\r
1018 );\r
1019 if (!EFI_ERROR (Status)) {\r
1020 Status = EFI_NOT_FOUND;\r
1021 ASSERT (OpenInfoBuffer != NULL);\r
1022 for (Index = 0; Index < EntryCount; Index++) {\r
1023 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
1024 //\r
1025 // Find the child terminal handle.\r
1026 // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
1027 //\r
1028 Status = gBS->OpenProtocol (\r
1029 OpenInfoBuffer[Index].ControllerHandle,\r
1030 &gEfiSimpleTextInProtocolGuid,\r
1031 (VOID **) &SimpleTextInput,\r
1032 This->DriverBindingHandle,\r
1033 OpenInfoBuffer[Index].ControllerHandle,\r
1034 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1035 );\r
1036 if (!EFI_ERROR (Status)) {\r
1037 SimTxtInInstalled = TRUE;\r
1038 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
1039 }\r
3012ce5c 1040\r
e3dcffcc 1041 Status = gBS->OpenProtocol (\r
1042 OpenInfoBuffer[Index].ControllerHandle,\r
1043 &gEfiSimpleTextOutProtocolGuid,\r
1044 (VOID **) &SimpleTextOutput,\r
1045 This->DriverBindingHandle,\r
1046 OpenInfoBuffer[Index].ControllerHandle,\r
1047 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1048 );\r
1049 if (!EFI_ERROR (Status)) {\r
1050 SimTxtOutInstalled = TRUE;\r
1051 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1052 }\r
1053 Status = EFI_SUCCESS;\r
1054 break;\r
1055 }\r
1056 }\r
95276127 1057\r
e3dcffcc 1058 FreePool (OpenInfoBuffer);\r
1059 if (EFI_ERROR (Status)) {\r
1060 goto ReportError;\r
1061 }\r
1062 } else {\r
95276127 1063 goto ReportError;\r
1064 }\r
1065\r
e3dcffcc 1066 ASSERT (TerminalDevice != NULL);\r
1067 //\r
1068 // Only do the reset if the device path is in the Conout variable\r
1069 //\r
1070 if (ConInSelected && !SimTxtInInstalled) {\r
1071 Status = TerminalDevice->SimpleInput.Reset (\r
1072 &TerminalDevice->SimpleInput,\r
1073 FALSE\r
1074 );\r
1075 if (EFI_ERROR (Status)) {\r
1076 //\r
1077 // Need to report Error Code first\r
1078 //\r
1079 goto ReportError;\r
1080 }\r
95276127 1081 }\r
95276127 1082\r
95276127 1083 //\r
e3dcffcc 1084 // Only output the configure string to remote terminal if the device path\r
1085 // is in the Conout variable\r
95276127 1086 //\r
e3dcffcc 1087 if (ConOutSelected && !SimTxtOutInstalled) {\r
1088 Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
1089 &TerminalDevice->SimpleTextOutput,\r
1090 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
1091 );\r
1092 if (EFI_ERROR (Status)) {\r
1093 goto ReportError;\r
1094 }\r
5bca971e 1095\r
e3dcffcc 1096 Status = TerminalDevice->SimpleTextOutput.Reset (\r
1097 &TerminalDevice->SimpleTextOutput,\r
1098 FALSE\r
1099 );\r
1100 if (EFI_ERROR (Status)) {\r
1101 goto ReportError;\r
1102 }\r
95276127 1103\r
e3dcffcc 1104 Status = TerminalDevice->SimpleTextOutput.SetMode (\r
1105 &TerminalDevice->SimpleTextOutput,\r
1106 0\r
1107 );\r
1108 if (EFI_ERROR (Status)) {\r
1109 goto ReportError;\r
1110 }\r
5bca971e 1111\r
e3dcffcc 1112 Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
1113 &TerminalDevice->SimpleTextOutput,\r
1114 TRUE\r
1115 );\r
1116 if (EFI_ERROR (Status)) {\r
1117 goto ReportError;\r
1118 }\r
95276127 1119 }\r
f1aec6cc 1120\r
95276127 1121 //\r
e3dcffcc 1122 // Simple In/Out Protocol will not be installed onto the handle if the\r
1123 // device path to the handle is not present in the ConIn/ConOut\r
1124 // environment variable. But If RemainingDevicePath is NULL, then always\r
1125 // produce both Simple In and Simple Text Output Protocols. This is required\r
1126 // for the connect all sequences to make sure all possible consoles are\r
1127 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 1128 //\r
e3dcffcc 1129 if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
1130 Status = gBS->InstallMultipleProtocolInterfaces (\r
1131 &TerminalDevice->Handle,\r
1132 &gEfiSimpleTextInProtocolGuid,\r
1133 &TerminalDevice->SimpleInput,\r
1134 &gEfiSimpleTextInputExProtocolGuid,\r
1135 &TerminalDevice->SimpleInputEx,\r
1136 NULL\r
1137 );\r
1138 if (EFI_ERROR (Status)) {\r
1139 goto Error;\r
1140 }\r
95276127 1141 }\r
1142\r
e3dcffcc 1143 if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
1144 Status = gBS->InstallProtocolInterface (\r
1145 &TerminalDevice->Handle,\r
1146 &gEfiSimpleTextOutProtocolGuid,\r
1147 EFI_NATIVE_INTERFACE,\r
1148 &TerminalDevice->SimpleTextOutput\r
1149 );\r
1150 if (EFI_ERROR (Status)) {\r
1151 goto Error;\r
1152 }\r
1153 }\r
95276127 1154 if (DefaultNode != NULL) {\r
1155 FreePool (DefaultNode);\r
1156 }\r
1157\r
1158 return EFI_SUCCESS;\r
1159\r
1160ReportError:\r
1161 //\r
1162 // Report error code before exiting\r
1163 //\r
e3dcffcc 1164 DevicePath = ParentDevicePath;\r
95276127 1165 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1166 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 1167 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
95276127 1168 DevicePath\r
1169 );\r
1170\r
1171Error:\r
1172 //\r
1173 // Use the Stop() function to free all resources allocated in Start()\r
1174 //\r
1175 if (TerminalDevice != NULL) {\r
1176\r
1177 if (TerminalDevice->Handle != NULL) {\r
1178 This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
1179 } else {\r
1180\r
1181 if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
1182 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1183 }\r
1184\r
f0368006
RN
1185 if (TerminalDevice->TimerEvent != NULL) {\r
1186 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
1187 }\r
1188\r
95276127 1189 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
1190 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
1191 }\r
1192\r
66aa04e4 1193 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
1194 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
1195 }\r
1196\r
1197 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
1198\r
5c998646 1199 if (TerminalDevice->RawFiFo != NULL) {\r
1200 FreePool (TerminalDevice->RawFiFo);\r
1201 }\r
1202 if (TerminalDevice->UnicodeFiFo != NULL) {\r
1203 FreePool (TerminalDevice->UnicodeFiFo);\r
1204 }\r
1205 if (TerminalDevice->EfiKeyFiFo != NULL) {\r
1206 FreePool (TerminalDevice->EfiKeyFiFo);\r
1207 }\r
1208\r
95276127 1209 if (TerminalDevice->ControllerNameTable != NULL) {\r
1210 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1211 }\r
1212\r
1213 if (TerminalDevice->DevicePath != NULL) {\r
1214 FreePool (TerminalDevice->DevicePath);\r
1215 }\r
1216\r
79d07c66 1217 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1218 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1219 }\r
1220\r
95276127 1221 FreePool (TerminalDevice);\r
1222 }\r
1223 }\r
1224\r
1225 if (DefaultNode != NULL) {\r
1226 FreePool (DefaultNode);\r
1227 }\r
1228\r
1229 This->Stop (This, Controller, 0, NULL);\r
1230\r
1231 return Status;\r
1232}\r
1233\r
e49ef433 1234/**\r
ab76200c 1235 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 1236 In Ex, Simple Text Out protocol, and removing parent device path from\r
677fdb90 1237 Console Device Environment Variables.\r
e49ef433 1238\r
8fd98315 1239 @param This Protocol instance pointer.\r
ab76200c 1240 @param Controller Handle of device to stop driver on\r
8fd98315 1241 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1242 children is zero stop the entire bus driver.\r
1243 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 1244\r
ab76200c 1245 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 1246 @retval other This driver could not be removed from this device.\r
e49ef433 1247\r
1248**/\r
95276127 1249EFI_STATUS\r
1250EFIAPI\r
1251TerminalDriverBindingStop (\r
1252 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1253 IN EFI_HANDLE Controller,\r
1254 IN UINTN NumberOfChildren,\r
1255 IN EFI_HANDLE *ChildHandleBuffer\r
1256 )\r
95276127 1257{\r
1258 EFI_STATUS Status;\r
1259 UINTN Index;\r
1260 BOOLEAN AllChildrenStopped;\r
1261 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
1262 TERMINAL_DEV *TerminalDevice;\r
1263 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1264 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
1265 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1266\r
1267 Status = gBS->HandleProtocol (\r
1268 Controller,\r
1269 &gEfiDevicePathProtocolGuid,\r
1270 (VOID **) &DevicePath\r
1271 );\r
1272 if (EFI_ERROR (Status)) {\r
1273 return Status;\r
1274 }\r
95276127 1275\r
1276 //\r
1277 // Complete all outstanding transactions to Controller.\r
1278 // Don't allow any new transaction to Controller to be started.\r
1279 //\r
1280 if (NumberOfChildren == 0) {\r
1281 //\r
1282 // Close the bus driver\r
1283 //\r
1284 Status = gBS->OpenProtocol (\r
1285 Controller,\r
1286 &gEfiCallerIdGuid,\r
1287 (VOID **) &ParentDevicePath,\r
1288 This->DriverBindingHandle,\r
1289 Controller,\r
1290 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1291 );\r
1292 if (!EFI_ERROR (Status)) {\r
1293 //\r
1294 // Remove Parent Device Path from\r
1295 // the Console Device Environment Variables\r
1296 //\r
ff37790d
A
1297 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
1298 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
1299 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 1300\r
1301 //\r
1302 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
1303 //\r
1304 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1305 Controller,\r
1306 &gEfiCallerIdGuid,\r
1307 ParentDevicePath,\r
1308 NULL\r
1309 );\r
1310\r
1311 //\r
1312 // Free the ParentDevicePath that was duplicated in Start()\r
1313 //\r
1314 if (!EFI_ERROR (Status)) {\r
1315 FreePool (ParentDevicePath);\r
1316 }\r
1317 }\r
1318\r
1319 gBS->CloseProtocol (\r
1320 Controller,\r
1321 &gEfiSerialIoProtocolGuid,\r
1322 This->DriverBindingHandle,\r
1323 Controller\r
1324 );\r
1325\r
1326 gBS->CloseProtocol (\r
1327 Controller,\r
1328 &gEfiDevicePathProtocolGuid,\r
1329 This->DriverBindingHandle,\r
1330 Controller\r
1331 );\r
1332\r
1333 return EFI_SUCCESS;\r
1334 }\r
1335\r
1336 AllChildrenStopped = TRUE;\r
1337\r
1338 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1339\r
1340 Status = gBS->OpenProtocol (\r
1341 ChildHandleBuffer[Index],\r
1342 &gEfiSimpleTextOutProtocolGuid,\r
1343 (VOID **) &SimpleTextOutput,\r
1344 This->DriverBindingHandle,\r
1345 ChildHandleBuffer[Index],\r
1346 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1347 );\r
1348 if (!EFI_ERROR (Status)) {\r
1349\r
1350 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1351\r
1352 gBS->CloseProtocol (\r
1353 Controller,\r
1354 &gEfiSerialIoProtocolGuid,\r
1355 This->DriverBindingHandle,\r
1356 ChildHandleBuffer[Index]\r
1357 );\r
1358\r
1359 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1360 ChildHandleBuffer[Index],\r
1361 &gEfiSimpleTextInProtocolGuid,\r
1362 &TerminalDevice->SimpleInput,\r
66aa04e4 1363 &gEfiSimpleTextInputExProtocolGuid,\r
1364 &TerminalDevice->SimpleInputEx,\r
95276127 1365 &gEfiSimpleTextOutProtocolGuid,\r
1366 &TerminalDevice->SimpleTextOutput,\r
1367 &gEfiDevicePathProtocolGuid,\r
1368 TerminalDevice->DevicePath,\r
1369 NULL\r
1370 );\r
1371 if (EFI_ERROR (Status)) {\r
1372 gBS->OpenProtocol (\r
1373 Controller,\r
1374 &gEfiSerialIoProtocolGuid,\r
1375 (VOID **) &SerialIo,\r
1376 This->DriverBindingHandle,\r
1377 ChildHandleBuffer[Index],\r
1378 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1379 );\r
1380 } else {\r
1381\r
1382 if (TerminalDevice->ControllerNameTable != NULL) {\r
1383 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1384 }\r
1385\r
f0368006 1386 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
95276127 1387 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1388 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 1389 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
1390 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
95276127 1391 FreePool (TerminalDevice->DevicePath);\r
79d07c66 1392 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1393 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1394 }\r
95276127 1395 FreePool (TerminalDevice);\r
1396 }\r
1397 }\r
1398\r
1399 if (EFI_ERROR (Status)) {\r
1400 AllChildrenStopped = FALSE;\r
1401 }\r
1402 }\r
1403\r
1404 if (!AllChildrenStopped) {\r
1405 return EFI_DEVICE_ERROR;\r
1406 }\r
1407\r
1408 return EFI_SUCCESS;\r
1409}\r
1410\r
8fd98315 1411/**\r
1412 Update terminal device path in Console Device Environment Variables.\r
1413\r
1414 @param VariableName The Console Device Environment Variable.\r
11baadb6 1415 @param ParentDevicePath The terminal device path to be updated.\r
8fd98315 1416\r
8fd98315 1417**/\r
95276127 1418VOID\r
1419TerminalUpdateConsoleDevVariable (\r
1420 IN CHAR16 *VariableName,\r
1421 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1422 )\r
1423{\r
1424 EFI_STATUS Status;\r
1425 UINTN VariableSize;\r
1426 UINT8 TerminalType;\r
1427 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1428 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1429 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1430\r
95276127 1431 //\r
1432 // Get global variable and its size according to the name given.\r
1433 //\r
bf4a3dbd 1434 GetEfiGlobalVariable2 (VariableName, &Variable, NULL);\r
e3dcffcc 1435 if (Variable == NULL) {\r
1436 return;\r
1437 }\r
1438\r
95276127 1439 //\r
1440 // Append terminal device path onto the variable.\r
1441 //\r
e49ef433 1442 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 1443 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1444 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
1445 if (Variable != NULL) {\r
1446 FreePool (Variable);\r
1447 }\r
1448\r
1449 if (TempDevicePath != NULL) {\r
1450 FreePool (TempDevicePath);\r
1451 }\r
1452\r
1453 Variable = NewVariable;\r
1454 }\r
1455\r
1456 VariableSize = GetDevicePathSize (Variable);\r
1457\r
1458 Status = gRT->SetVariable (\r
1459 VariableName,\r
1460 &gEfiGlobalVariableGuid,\r
1461 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1462 VariableSize,\r
1463 Variable\r
1464 );\r
1465 ASSERT_EFI_ERROR (Status);\r
1466 FreePool (Variable);\r
1467\r
1468 return ;\r
1469}\r
1470\r
e49ef433 1471\r
1472/**\r
8fd98315 1473 Remove terminal device path from Console Device Environment Variables.\r
e49ef433 1474\r
8fd98315 1475 @param VariableName Console Device Environment Variables.\r
11baadb6 1476 @param ParentDevicePath The terminal device path to be updated.\r
e49ef433 1477\r
e49ef433 1478**/\r
95276127 1479VOID\r
1480TerminalRemoveConsoleDevVariable (\r
1481 IN CHAR16 *VariableName,\r
1482 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1483 )\r
95276127 1484{\r
1485 EFI_STATUS Status;\r
1486 BOOLEAN FoundOne;\r
1487 BOOLEAN Match;\r
1488 UINTN VariableSize;\r
1489 UINTN InstanceSize;\r
1490 UINT8 TerminalType;\r
1491 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1492 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1493 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
1494 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1495 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
1496 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1497\r
95276127 1498 Instance = NULL;\r
1499\r
1500 //\r
1501 // Get global variable and its size according to the name given.\r
1502 //\r
bf4a3dbd 1503 GetEfiGlobalVariable2 (VariableName, &Variable, NULL);\r
95276127 1504 if (Variable == NULL) {\r
1505 return ;\r
1506 }\r
1507\r
1508 FoundOne = FALSE;\r
1509 OriginalVariable = Variable;\r
1510 NewVariable = NULL;\r
1511\r
1512 //\r
1513 // Get first device path instance from Variable\r
1514 //\r
1515 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1516 if (Instance == NULL) {\r
1517 FreePool (OriginalVariable);\r
1518 return ;\r
1519 }\r
1520 //\r
1521 // Loop through all the device path instances of Variable\r
1522 //\r
1523 do {\r
1524 //\r
1525 // Loop through all the terminal types that this driver supports\r
1526 //\r
1527 Match = FALSE;\r
e49ef433 1528 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 1529\r
1530 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1531\r
1532 //\r
11baadb6 1533 // Compare the generated device path to the current device path instance\r
95276127 1534 //\r
1535 if (TempDevicePath != NULL) {\r
1536 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
1537 Match = TRUE;\r
1538 FoundOne = TRUE;\r
1539 }\r
1540\r
1541 FreePool (TempDevicePath);\r
1542 }\r
1543 }\r
1544 //\r
1545 // If a match was not found, then keep the current device path instance\r
1546 //\r
1547 if (!Match) {\r
1548 SavedNewVariable = NewVariable;\r
1549 NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
1550 if (SavedNewVariable != NULL) {\r
1551 FreePool (SavedNewVariable);\r
1552 }\r
1553 }\r
1554 //\r
1555 // Get next device path instance from Variable\r
1556 //\r
1557 FreePool (Instance);\r
1558 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1559 } while (Instance != NULL);\r
1560\r
1561 FreePool (OriginalVariable);\r
1562\r
1563 if (FoundOne) {\r
1564 VariableSize = GetDevicePathSize (NewVariable);\r
1565\r
1566 Status = gRT->SetVariable (\r
1567 VariableName,\r
1568 &gEfiGlobalVariableGuid,\r
1569 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1570 VariableSize,\r
1571 NewVariable\r
1572 );\r
1573 ASSERT_EFI_ERROR (Status);\r
1574 }\r
1575\r
1576 if (NewVariable != NULL) {\r
1577 FreePool (NewVariable);\r
1578 }\r
1579\r
1580 return ;\r
1581}\r
1582\r
8fd98315 1583/**\r
11baadb6 1584 Build terminal device path according to terminal type.\r
8fd98315 1585\r
1586 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
11baadb6 1587 @param ParentDevicePath Parent device path.\r
8fd98315 1588 @param TerminalDevicePath Returned terminal device path, if building successfully.\r
1589\r
1590 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
1591 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
1592 @retval EFI_SUCCESS Build terminal device path successfully.\r
1593\r
1594**/\r
95276127 1595EFI_STATUS\r
1596SetTerminalDevicePath (\r
1597 IN UINT8 TerminalType,\r
1598 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1599 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
1600 )\r
1601{\r
1602 VENDOR_DEVICE_PATH Node;\r
1603\r
1604 *TerminalDevicePath = NULL;\r
1605 Node.Header.Type = MESSAGING_DEVICE_PATH;\r
1606 Node.Header.SubType = MSG_VENDOR_DP;\r
1607\r
1608 //\r
ab76200c 1609 // Generate terminal device path node according to terminal type.\r
95276127 1610 //\r
1611 switch (TerminalType) {\r
1612\r
e49ef433 1613 case PCANSITYPE:\r
ab76200c 1614 CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
95276127 1615 break;\r
1616\r
e49ef433 1617 case VT100TYPE:\r
ab76200c 1618 CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
95276127 1619 break;\r
1620\r
e49ef433 1621 case VT100PLUSTYPE:\r
ab76200c 1622 CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
95276127 1623 break;\r
1624\r
e49ef433 1625 case VTUTF8TYPE:\r
ab76200c 1626 CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
95276127 1627 break;\r
1628\r
1629 default:\r
1630 return EFI_UNSUPPORTED;\r
95276127 1631 }\r
1632\r
ab76200c 1633 //\r
1634 // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
1635 //\r
95276127 1636 SetDevicePathNodeLength (\r
1637 &Node.Header,\r
1638 sizeof (VENDOR_DEVICE_PATH)\r
1639 );\r
ab76200c 1640\r
95276127 1641 //\r
ab76200c 1642 // Append the terminal node onto parent device path\r
95276127 1643 // to generate a complete terminal device path.\r
1644 //\r
1645 *TerminalDevicePath = AppendDevicePathNode (\r
1646 ParentDevicePath,\r
1647 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1648 );\r
1649 if (*TerminalDevicePath == NULL) {\r
1650 return EFI_OUT_OF_RESOURCES;\r
1651 }\r
1652\r
1653 return EFI_SUCCESS;\r
1654}\r
1655\r
97a079ed
A
1656/**\r
1657 The user Entry Point for module Terminal. The user code starts with this function.\r
1658\r
ab76200c 1659 @param ImageHandle The firmware allocated handle for the EFI image.\r
1660 @param SystemTable A pointer to the EFI System Table.\r
fb0b259e 1661\r
97a079ed
A
1662 @retval EFI_SUCCESS The entry point is executed successfully.\r
1663 @retval other Some error occurs when executing this entry point.\r
1664\r
1665**/\r
1666EFI_STATUS\r
1667EFIAPI\r
1668InitializeTerminal(\r
1669 IN EFI_HANDLE ImageHandle,\r
1670 IN EFI_SYSTEM_TABLE *SystemTable\r
1671 )\r
1672{\r
1673 EFI_STATUS Status;\r
1674\r
1675 //\r
1676 // Install driver model protocol(s).\r
1677 //\r
5bca971e 1678 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1679 ImageHandle,\r
1680 SystemTable,\r
1681 &gTerminalDriverBinding,\r
1682 ImageHandle,\r
1683 &gTerminalComponentName,\r
5bca971e 1684 &gTerminalComponentName2\r
97a079ed
A
1685 );\r
1686 ASSERT_EFI_ERROR (Status);\r
1687\r
97a079ed
A
1688 return Status;\r
1689}\r
f1aec6cc 1690\r
1691/**\r
1692 Check if the device supports hot-plug through its device path.\r
1693\r
1694 This function could be updated to check more types of Hot Plug devices.\r
1695 Currently, it checks USB and PCCard device.\r
1696\r
1697 @param DevicePath Pointer to device's device path.\r
1698\r
1699 @retval TRUE The devcie is a hot-plug device\r
1700 @retval FALSE The devcie is not a hot-plug device.\r
1701\r
1702**/\r
1703BOOLEAN\r
1704IsHotPlugDevice (\r
1705 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1706 )\r
1707{\r
1708 EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
1709\r
1710 CheckDevicePath = DevicePath;\r
1711 while (!IsDevicePathEnd (CheckDevicePath)) {\r
1712 //\r
1713 // Check device whether is hot plug device or not throught Device Path\r
e3dcffcc 1714 //\r
f1aec6cc 1715 if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1716 (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
1717 DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
1718 DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
1719 //\r
1720 // If Device is USB device\r
1721 //\r
1722 return TRUE;\r
1723 }\r
1724 if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
1725 (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
1726 //\r
1727 // If Device is PCCard\r
1728 //\r
1729 return TRUE;\r
1730 }\r
e3dcffcc 1731\r
f1aec6cc 1732 CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
1733 }\r
1734\r
1735 return FALSE;\r
1736}\r
1737\r