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