]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
MdeModulePkg TerminalDxe: Remove a redundant function
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
1 /** @file
2 Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
3 Simple Text Output Protocol upon Serial IO Protocol.
4
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "Terminal.h"
18
19 //
20 // Globals
21 //
22 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
23 TerminalDriverBindingSupported,
24 TerminalDriverBindingStart,
25 TerminalDriverBindingStop,
26 0xa,
27 NULL,
28 NULL
29 };
30
31
32 EFI_GUID *mTerminalType[] = {
33 &gEfiPcAnsiGuid,
34 &gEfiVT100Guid,
35 &gEfiVT100PlusGuid,
36 &gEfiVTUTF8Guid,
37 &gEfiTtyTermGuid
38 };
39
40
41 CHAR16 *mSerialConsoleNames[] = {
42 L"PC-ANSI Serial Console",
43 L"VT-100 Serial Console",
44 L"VT-100+ Serial Console",
45 L"VT-UTF8 Serial Console",
46 L"Tty Terminal Serial Console"
47 };
48
49 TERMINAL_DEV mTerminalDevTemplate = {
50 TERMINAL_DEV_SIGNATURE,
51 NULL,
52 0,
53 NULL,
54 NULL,
55 { // SimpleTextInput
56 TerminalConInReset,
57 TerminalConInReadKeyStroke,
58 NULL
59 },
60 { // SimpleTextOutput
61 TerminalConOutReset,
62 TerminalConOutOutputString,
63 TerminalConOutTestString,
64 TerminalConOutQueryMode,
65 TerminalConOutSetMode,
66 TerminalConOutSetAttribute,
67 TerminalConOutClearScreen,
68 TerminalConOutSetCursorPosition,
69 TerminalConOutEnableCursor,
70 NULL
71 },
72 { // SimpleTextOutputMode
73 1, // MaxMode
74 0, // Mode
75 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute
76 0, // CursorColumn
77 0, // CursorRow
78 TRUE // CursorVisible
79 },
80 NULL, // TerminalConsoleModeData
81 0, // SerialInTimeOut
82
83 NULL, // RawFifo
84 NULL, // UnicodeFiFo
85 NULL, // EfiKeyFiFo
86 NULL, // EfiKeyFiFoForNotify
87
88 NULL, // ControllerNameTable
89 NULL, // TimerEvent
90 NULL, // TwoSecondTimeOut
91 INPUT_STATE_DEFAULT,
92 RESET_STATE_DEFAULT,
93 {
94 0,
95 0,
96 0
97 },
98 0,
99 FALSE,
100 { // SimpleTextInputEx
101 TerminalConInResetEx,
102 TerminalConInReadKeyStrokeEx,
103 NULL,
104 TerminalConInSetState,
105 TerminalConInRegisterKeyNotify,
106 TerminalConInUnregisterKeyNotify,
107 },
108 { // NotifyList
109 NULL,
110 NULL,
111 },
112 NULL // KeyNotifyProcessEvent
113 };
114
115 TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
116 {80, 25},
117 {80, 50},
118 {100, 31},
119 //
120 // New modes can be added here.
121 //
122 };
123
124 /**
125 Convert the GUID representation of terminal type to enum type.
126
127 @param Guid The GUID representation of terminal type.
128
129 @return The terminal type in enum type.
130 **/
131 TERMINAL_TYPE
132 TerminalTypeFromGuid (
133 IN EFI_GUID *Guid
134 )
135 {
136 TERMINAL_TYPE Type;
137
138 for (Type = 0; Type < ARRAY_SIZE (mTerminalType); Type++) {
139 if (CompareGuid (Guid, mTerminalType[Type])) {
140 break;
141 }
142 }
143 return Type;
144 }
145
146 /**
147 Test to see if this driver supports Controller.
148
149 @param This Protocol instance pointer.
150 @param Controller Handle of device to test
151 @param RemainingDevicePath Optional parameter use to pick a specific child
152 device to start.
153
154 @retval EFI_SUCCESS This driver supports this device.
155 @retval EFI_ALREADY_STARTED This driver is already running on this device.
156 @retval other This driver does not support this device.
157
158 **/
159 EFI_STATUS
160 EFIAPI
161 TerminalDriverBindingSupported (
162 IN EFI_DRIVER_BINDING_PROTOCOL *This,
163 IN EFI_HANDLE Controller,
164 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
165 )
166 {
167 EFI_STATUS Status;
168 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
169 EFI_SERIAL_IO_PROTOCOL *SerialIo;
170 VENDOR_DEVICE_PATH *Node;
171
172 //
173 // If remaining device path is not NULL, then make sure it is a
174 // device path that describes a terminal communications protocol.
175 //
176 if (RemainingDevicePath != NULL) {
177 //
178 // Check if RemainingDevicePath is the End of Device Path Node,
179 // if yes, go on checking other conditions
180 //
181 if (!IsDevicePathEnd (RemainingDevicePath)) {
182 //
183 // If RemainingDevicePath isn't the End of Device Path Node,
184 // check its validation
185 //
186 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;
187
188 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||
189 Node->Header.SubType != MSG_VENDOR_DP ||
190 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {
191
192 return EFI_UNSUPPORTED;
193
194 }
195 //
196 // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types
197 //
198 if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {
199 return EFI_UNSUPPORTED;
200 }
201 }
202 }
203 //
204 // Open the IO Abstraction(s) needed to perform the supported test
205 // The Controller must support the Serial I/O Protocol.
206 // This driver is a bus driver with at most 1 child device, so it is
207 // ok for it to be already started.
208 //
209 Status = gBS->OpenProtocol (
210 Controller,
211 &gEfiSerialIoProtocolGuid,
212 (VOID **) &SerialIo,
213 This->DriverBindingHandle,
214 Controller,
215 EFI_OPEN_PROTOCOL_BY_DRIVER
216 );
217 if (Status == EFI_ALREADY_STARTED) {
218 return EFI_SUCCESS;
219 }
220
221 if (EFI_ERROR (Status)) {
222 return Status;
223 }
224
225 //
226 // Close the I/O Abstraction(s) used to perform the supported test
227 //
228 gBS->CloseProtocol (
229 Controller,
230 &gEfiSerialIoProtocolGuid,
231 This->DriverBindingHandle,
232 Controller
233 );
234
235 //
236 // Open the EFI Device Path protocol needed to perform the supported test
237 //
238 Status = gBS->OpenProtocol (
239 Controller,
240 &gEfiDevicePathProtocolGuid,
241 (VOID **) &ParentDevicePath,
242 This->DriverBindingHandle,
243 Controller,
244 EFI_OPEN_PROTOCOL_BY_DRIVER
245 );
246 if (Status == EFI_ALREADY_STARTED) {
247 return EFI_SUCCESS;
248 }
249
250 if (EFI_ERROR (Status)) {
251 return Status;
252 }
253
254 //
255 // Close protocol, don't use device path protocol in the Support() function
256 //
257 gBS->CloseProtocol (
258 Controller,
259 &gEfiDevicePathProtocolGuid,
260 This->DriverBindingHandle,
261 Controller
262 );
263
264 return Status;
265 }
266
267
268 /**
269 Free notify functions list.
270
271 @param ListHead The list head
272
273 @retval EFI_SUCCESS Free the notify list successfully.
274 @retval EFI_INVALID_PARAMETER ListHead is NULL.
275
276 **/
277 EFI_STATUS
278 TerminalFreeNotifyList (
279 IN OUT LIST_ENTRY *ListHead
280 )
281 {
282 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;
283
284 if (ListHead == NULL) {
285 return EFI_INVALID_PARAMETER;
286 }
287 while (!IsListEmpty (ListHead)) {
288 NotifyNode = CR (
289 ListHead->ForwardLink,
290 TERMINAL_CONSOLE_IN_EX_NOTIFY,
291 NotifyEntry,
292 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
293 );
294 RemoveEntryList (ListHead->ForwardLink);
295 FreePool (NotifyNode);
296 }
297
298 return EFI_SUCCESS;
299 }
300
301 /**
302 Initialize all the text modes which the terminal console supports.
303
304 It returns information for available text modes that the terminal can support.
305
306 @param[out] TextModeCount The total number of text modes that terminal console supports.
307
308 @return The buffer to the text modes column and row information.
309 Caller is responsible to free it when it's non-NULL.
310
311 **/
312 TERMINAL_CONSOLE_MODE_DATA *
313 InitializeTerminalConsoleTextMode (
314 OUT INT32 *TextModeCount
315 )
316 {
317 TERMINAL_CONSOLE_MODE_DATA *TextModeData;
318
319 ASSERT (TextModeCount != NULL);
320
321 TextModeData = AllocateCopyPool (sizeof (mTerminalConsoleModeData), mTerminalConsoleModeData);
322 if (TextModeData == NULL) {
323 return NULL;
324 }
325 *TextModeCount = ARRAY_SIZE (mTerminalConsoleModeData);
326
327 DEBUG_CODE (
328 INT32 Index;
329 for (Index = 0; Index < *TextModeCount; Index++) {
330 DEBUG ((DEBUG_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n",
331 Index, TextModeData[Index].Columns, TextModeData[Index].Rows));
332 }
333 );
334 return TextModeData;
335 }
336
337 /**
338 Stop the terminal state machine.
339
340 @param TerminalDevice The terminal device.
341 **/
342 VOID
343 StopTerminalStateMachine (
344 TERMINAL_DEV *TerminalDevice
345 )
346 {
347 EFI_TPL OriginalTpl;
348
349 OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);
350
351 gBS->CloseEvent (TerminalDevice->TimerEvent);
352 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
353
354 gBS->RestoreTPL (OriginalTpl);
355 }
356
357 /**
358 Start the terminal state machine.
359
360 @param TerminalDevice The terminal device.
361 **/
362 VOID
363 StartTerminalStateMachine (
364 TERMINAL_DEV *TerminalDevice
365 )
366 {
367 EFI_STATUS Status;
368 Status = gBS->CreateEvent (
369 EVT_TIMER | EVT_NOTIFY_SIGNAL,
370 TPL_NOTIFY,
371 TerminalConInTimerHandler,
372 TerminalDevice,
373 &TerminalDevice->TimerEvent
374 );
375 ASSERT_EFI_ERROR (Status);
376
377 Status = gBS->SetTimer (
378 TerminalDevice->TimerEvent,
379 TimerPeriodic,
380 KEYBOARD_TIMER_INTERVAL
381 );
382 ASSERT_EFI_ERROR (Status);
383
384 Status = gBS->CreateEvent (
385 EVT_TIMER,
386 TPL_CALLBACK,
387 NULL,
388 NULL,
389 &TerminalDevice->TwoSecondTimeOut
390 );
391 ASSERT_EFI_ERROR (Status);
392 }
393
394 /**
395 Initialize the controller name table.
396
397 @param TerminalType The terminal type.
398 @param ControllerNameTable The controller name table.
399
400 @retval EFI_SUCCESS The controller name table is initialized successfully.
401 @retval others Return status of AddUnicodeString2 ().
402 **/
403 EFI_STATUS
404 InitializeControllerNameTable (
405 TERMINAL_TYPE TerminalType,
406 EFI_UNICODE_STRING_TABLE **ControllerNameTable
407 )
408 {
409 EFI_STATUS Status;
410 EFI_UNICODE_STRING_TABLE *Table;
411
412 ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));
413 Table = NULL;
414 Status = AddUnicodeString2 (
415 "eng",
416 gTerminalComponentName.SupportedLanguages,
417 &Table,
418 mSerialConsoleNames[TerminalType],
419 TRUE
420 );
421 if (!EFI_ERROR (Status)) {
422 Status = AddUnicodeString2 (
423 "en",
424 gTerminalComponentName2.SupportedLanguages,
425 &Table,
426 mSerialConsoleNames[TerminalType],
427 FALSE
428 );
429 if (EFI_ERROR (Status)) {
430 FreeUnicodeStringTable (Table);
431 }
432 }
433 if (!EFI_ERROR (Status)) {
434 *ControllerNameTable = Table;
435 }
436 return Status;
437 }
438
439 /**
440 Start this driver on Controller by opening a Serial IO protocol,
441 reading Device Path, and creating a child handle with a Simple Text In,
442 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
443 And store Console Device Environment Variables.
444
445 @param This Protocol instance pointer.
446 @param Controller Handle of device to bind driver to
447 @param RemainingDevicePath Optional parameter use to pick a specific child
448 device to start.
449
450 @retval EFI_SUCCESS This driver is added to Controller.
451 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
452 @retval other This driver does not support this device.
453
454 **/
455 EFI_STATUS
456 EFIAPI
457 TerminalDriverBindingStart (
458 IN EFI_DRIVER_BINDING_PROTOCOL *This,
459 IN EFI_HANDLE Controller,
460 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
461 )
462 {
463 EFI_STATUS Status;
464 EFI_SERIAL_IO_PROTOCOL *SerialIo;
465 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
466 EFI_DEVICE_PATH_PROTOCOL *Vendor;
467 EFI_HANDLE SerialIoHandle;
468 EFI_SERIAL_IO_MODE *Mode;
469 UINTN SerialInTimeOut;
470 TERMINAL_DEV *TerminalDevice;
471 UINT8 TerminalType;
472 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
473 UINTN EntryCount;
474 UINTN Index;
475 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;
476 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;
477 EFI_UNICODE_STRING_TABLE *ControllerNameTable;
478
479 //
480 // Get the Device Path Protocol to build the device path of the child device
481 //
482 Status = gBS->OpenProtocol (
483 Controller,
484 &gEfiDevicePathProtocolGuid,
485 (VOID **) &ParentDevicePath,
486 This->DriverBindingHandle,
487 Controller,
488 EFI_OPEN_PROTOCOL_BY_DRIVER
489 );
490 ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));
491 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
492 return Status;
493 }
494
495 //
496 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
497 //
498 Status = gBS->OpenProtocol (
499 Controller,
500 &gEfiSerialIoProtocolGuid,
501 (VOID **) &SerialIo,
502 This->DriverBindingHandle,
503 Controller,
504 EFI_OPEN_PROTOCOL_BY_DRIVER
505 );
506 ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_ALREADY_STARTED));
507 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
508 return Status;
509 }
510
511 if (!IsHotPlugDevice (ParentDevicePath)) {
512 //
513 // if the serial device is a hot plug device, do not update the
514 // ConInDev, ConOutDev, and StdErrDev variables.
515 //
516 TerminalUpdateConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);
517 TerminalUpdateConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
518 TerminalUpdateConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
519 }
520
521 //
522 // Do not create any child for END remaining device path.
523 //
524 if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
525 return EFI_SUCCESS;
526 }
527
528 if (Status == EFI_ALREADY_STARTED) {
529
530 if (RemainingDevicePath == NULL) {
531 //
532 // If RemainingDevicePath is NULL or is the End of Device Path Node
533 //
534 return EFI_SUCCESS;
535 }
536
537 //
538 // This driver can only produce one child per serial port.
539 // Change its terminal type as remaining device path requests.
540 //
541 Status = gBS->OpenProtocolInformation (
542 Controller,
543 &gEfiSerialIoProtocolGuid,
544 &OpenInfoBuffer,
545 &EntryCount
546 );
547 if (!EFI_ERROR (Status)) {
548 Status = EFI_NOT_FOUND;
549 for (Index = 0; Index < EntryCount; Index++) {
550 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
551 Status = gBS->OpenProtocol (
552 OpenInfoBuffer[Index].ControllerHandle,
553 &gEfiSimpleTextInProtocolGuid,
554 (VOID **) &SimpleTextInput,
555 This->DriverBindingHandle,
556 Controller,
557 EFI_OPEN_PROTOCOL_GET_PROTOCOL
558 );
559 if (!EFI_ERROR (Status)) {
560 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);
561 TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid);
562 ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));
563 if (TerminalDevice->TerminalType != TerminalType) {
564 Status = InitializeControllerNameTable (TerminalType, &ControllerNameTable);
565 if (!EFI_ERROR (Status)) {
566 StopTerminalStateMachine (TerminalDevice);
567 //
568 // Update the device path
569 //
570 Vendor = TerminalDevice->DevicePath;
571 Status = gBS->LocateDevicePath (&gEfiSerialIoProtocolGuid, &Vendor, &SerialIoHandle);
572 ASSERT_EFI_ERROR (Status);
573 CopyGuid (&((VENDOR_DEVICE_PATH *) Vendor)->Guid, mTerminalType[TerminalType]);
574 Status = gBS->ReinstallProtocolInterface (
575 TerminalDevice->Handle,
576 &gEfiDevicePathProtocolGuid,
577 TerminalDevice->DevicePath,
578 TerminalDevice->DevicePath
579 );
580 if (!EFI_ERROR (Status)) {
581 TerminalDevice->TerminalType = TerminalType;
582 StartTerminalStateMachine (TerminalDevice);
583 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
584 TerminalDevice->ControllerNameTable = ControllerNameTable;
585 } else {
586 //
587 // Restore the device path on failure
588 //
589 CopyGuid (&((VENDOR_DEVICE_PATH *) Vendor)->Guid, mTerminalType[TerminalDevice->TerminalType]);
590 FreeUnicodeStringTable (ControllerNameTable);
591 }
592 }
593 }
594 }
595 break;
596 }
597 }
598 FreePool (OpenInfoBuffer);
599 }
600 return Status;
601 }
602
603 //
604 // Initialize the Terminal Dev
605 //
606 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);
607 if (TerminalDevice == NULL) {
608 Status = EFI_OUT_OF_RESOURCES;
609 goto CloseProtocols;
610 }
611
612 if (RemainingDevicePath == NULL) {
613 //
614 // If RemainingDevicePath is NULL, use default terminal type
615 //
616 TerminalDevice->TerminalType = PcdGet8 (PcdDefaultTerminalType);
617 } else {
618 //
619 // End of Device Path Node is handled in above.
620 //
621 ASSERT (!IsDevicePathEnd (RemainingDevicePath));
622 //
623 // If RemainingDevicePath isn't the End of Device Path Node,
624 // Use the RemainingDevicePath to determine the terminal type
625 //
626 TerminalDevice->TerminalType = TerminalTypeFromGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid);
627 }
628 ASSERT (TerminalDevice->TerminalType < ARRAY_SIZE (mTerminalType));
629 TerminalDevice->SerialIo = SerialIo;
630
631 //
632 // Build the component name for the child device
633 //
634 Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);
635 if (EFI_ERROR (Status)) {
636 goto FreeResources;
637 }
638
639 //
640 // Build the device path for the child device
641 //
642 Status = SetTerminalDevicePath (TerminalDevice->TerminalType, ParentDevicePath, &TerminalDevice->DevicePath);
643 if (EFI_ERROR (Status)) {
644 goto FreeResources;
645 }
646
647 InitializeListHead (&TerminalDevice->NotifyList);
648 Status = gBS->CreateEvent (
649 EVT_NOTIFY_WAIT,
650 TPL_NOTIFY,
651 TerminalConInWaitForKeyEx,
652 TerminalDevice,
653 &TerminalDevice->SimpleInputEx.WaitForKeyEx
654 );
655 ASSERT_EFI_ERROR (Status);
656
657 Status = gBS->CreateEvent (
658 EVT_NOTIFY_WAIT,
659 TPL_NOTIFY,
660 TerminalConInWaitForKey,
661 TerminalDevice,
662 &TerminalDevice->SimpleInput.WaitForKey
663 );
664 ASSERT_EFI_ERROR (Status);
665 Status = gBS->CreateEvent (
666 EVT_NOTIFY_SIGNAL,
667 TPL_CALLBACK,
668 KeyNotifyProcessHandler,
669 TerminalDevice,
670 &TerminalDevice->KeyNotifyProcessEvent
671 );
672 ASSERT_EFI_ERROR (Status);
673
674 //
675 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
676 // the pre-read pending characters.
677 //
678 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));
679 if (TerminalDevice->RawFiFo == NULL) {
680 goto FreeResources;
681 }
682 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));
683 if (TerminalDevice->UnicodeFiFo == NULL) {
684 goto FreeResources;
685 }
686 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));
687 if (TerminalDevice->EfiKeyFiFo == NULL) {
688 goto FreeResources;
689 }
690 TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));
691 if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {
692 goto FreeResources;
693 }
694
695 //
696 // Set the timeout value of serial buffer for keystroke response performance issue
697 //
698 Mode = TerminalDevice->SerialIo->Mode;
699
700 SerialInTimeOut = 0;
701 if (Mode->BaudRate != 0) {
702 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
703 }
704
705 Status = TerminalDevice->SerialIo->SetAttributes (
706 TerminalDevice->SerialIo,
707 Mode->BaudRate,
708 Mode->ReceiveFifoDepth,
709 (UINT32) SerialInTimeOut,
710 (EFI_PARITY_TYPE) (Mode->Parity),
711 (UINT8) Mode->DataBits,
712 (EFI_STOP_BITS_TYPE) (Mode->StopBits)
713 );
714 if (EFI_ERROR (Status)) {
715 //
716 // if set attributes operation fails, invalidate
717 // the value of SerialInTimeOut,thus make it
718 // inconsistent with the default timeout value
719 // of serial buffer. This will invoke the recalculation
720 // in the readkeystroke routine.
721 //
722 TerminalDevice->SerialInTimeOut = 0;
723 } else {
724 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
725 }
726
727 SimpleTextOutput = &TerminalDevice->SimpleTextOutput;
728 SimpleTextInput = &TerminalDevice->SimpleInput;
729
730 //
731 // Initialize SimpleTextOut instance
732 //
733 SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;
734 TerminalDevice->TerminalConsoleModeData = InitializeTerminalConsoleTextMode (
735 &SimpleTextOutput->Mode->MaxMode
736 );
737 if (TerminalDevice->TerminalConsoleModeData == NULL) {
738 goto FreeResources;
739 }
740 //
741 // For terminal devices, cursor is always visible
742 //
743 SimpleTextOutput->Mode->CursorVisible = TRUE;
744 Status = SimpleTextOutput->SetAttribute (SimpleTextOutput, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
745 if (!EFI_ERROR (Status)) {
746 Status = SimpleTextOutput->Reset (SimpleTextOutput, FALSE);
747 }
748 if (EFI_ERROR (Status)) {
749 goto ReportError;
750 }
751
752 //
753 // Initialize SimpleTextInput instance
754 //
755 Status = SimpleTextInput->Reset (SimpleTextInput, FALSE);
756 if (EFI_ERROR (Status)) {
757 goto ReportError;
758 }
759
760 Status = gBS->InstallMultipleProtocolInterfaces (
761 &TerminalDevice->Handle,
762 &gEfiSimpleTextInProtocolGuid, &TerminalDevice->SimpleInput,
763 &gEfiSimpleTextInputExProtocolGuid, &TerminalDevice->SimpleInputEx,
764 &gEfiSimpleTextOutProtocolGuid, &TerminalDevice->SimpleTextOutput,
765 &gEfiDevicePathProtocolGuid, TerminalDevice->DevicePath,
766 NULL
767 );
768 if (!EFI_ERROR (Status)) {
769 Status = gBS->OpenProtocol (
770 Controller,
771 &gEfiSerialIoProtocolGuid,
772 (VOID **) &TerminalDevice->SerialIo,
773 This->DriverBindingHandle,
774 TerminalDevice->Handle,
775 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
776 );
777 ASSERT_EFI_ERROR (Status);
778 StartTerminalStateMachine (TerminalDevice);
779 return Status;
780 }
781
782 ReportError:
783 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
784 EFI_ERROR_CODE | EFI_ERROR_MINOR,
785 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
786 ParentDevicePath
787 );
788
789 FreeResources:
790 ASSERT (TerminalDevice != NULL);
791
792 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {
793 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
794 }
795 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {
796 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);
797 }
798 if (TerminalDevice->KeyNotifyProcessEvent != NULL) {
799 gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);
800 }
801
802 if (TerminalDevice->RawFiFo != NULL) {
803 FreePool (TerminalDevice->RawFiFo);
804 }
805 if (TerminalDevice->UnicodeFiFo != NULL) {
806 FreePool (TerminalDevice->UnicodeFiFo);
807 }
808 if (TerminalDevice->EfiKeyFiFo != NULL) {
809 FreePool (TerminalDevice->EfiKeyFiFo);
810 }
811 if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {
812 FreePool (TerminalDevice->EfiKeyFiFoForNotify);
813 }
814
815 if (TerminalDevice->ControllerNameTable != NULL) {
816 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
817 }
818
819 if (TerminalDevice->DevicePath != NULL) {
820 FreePool (TerminalDevice->DevicePath);
821 }
822
823 if (TerminalDevice->TerminalConsoleModeData != NULL) {
824 FreePool (TerminalDevice->TerminalConsoleModeData);
825 }
826
827 FreePool (TerminalDevice);
828
829 CloseProtocols:
830
831 //
832 // Remove Parent Device Path from
833 // the Console Device Environment Variables
834 //
835 TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);
836 TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
837 TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
838
839 Status = gBS->CloseProtocol (
840 Controller,
841 &gEfiSerialIoProtocolGuid,
842 This->DriverBindingHandle,
843 Controller
844 );
845 ASSERT_EFI_ERROR (Status);
846
847 Status = gBS->CloseProtocol (
848 Controller,
849 &gEfiDevicePathProtocolGuid,
850 This->DriverBindingHandle,
851 Controller
852 );
853 ASSERT_EFI_ERROR (Status);
854 return Status;
855 }
856
857 /**
858 Stop this driver on Controller by closing Simple Text In, Simple Text
859 In Ex, Simple Text Out protocol, and removing parent device path from
860 Console Device Environment Variables.
861
862 @param This Protocol instance pointer.
863 @param Controller Handle of device to stop driver on
864 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
865 children is zero stop the entire bus driver.
866 @param ChildHandleBuffer List of Child Handles to Stop.
867
868 @retval EFI_SUCCESS This driver is removed Controller.
869 @retval other This driver could not be removed from this device.
870
871 **/
872 EFI_STATUS
873 EFIAPI
874 TerminalDriverBindingStop (
875 IN EFI_DRIVER_BINDING_PROTOCOL *This,
876 IN EFI_HANDLE Controller,
877 IN UINTN NumberOfChildren,
878 IN EFI_HANDLE *ChildHandleBuffer
879 )
880 {
881 EFI_STATUS Status;
882 UINTN Index;
883 BOOLEAN AllChildrenStopped;
884 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;
885 TERMINAL_DEV *TerminalDevice;
886 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
887 EFI_SERIAL_IO_PROTOCOL *SerialIo;
888
889 //
890 // Complete all outstanding transactions to Controller.
891 // Don't allow any new transaction to Controller to be started.
892 //
893 if (NumberOfChildren == 0) {
894 //
895 // Close the bus driver
896 //
897 Status = gBS->OpenProtocol (
898 Controller,
899 &gEfiDevicePathProtocolGuid,
900 (VOID **) &ParentDevicePath,
901 This->DriverBindingHandle,
902 Controller,
903 EFI_OPEN_PROTOCOL_GET_PROTOCOL
904 );
905 ASSERT_EFI_ERROR (Status);
906
907 //
908 // Remove Parent Device Path from
909 // the Console Device Environment Variables
910 //
911 TerminalRemoveConsoleDevVariable (EFI_CON_IN_DEV_VARIABLE_NAME, ParentDevicePath);
912 TerminalRemoveConsoleDevVariable (EFI_CON_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
913 TerminalRemoveConsoleDevVariable (EFI_ERR_OUT_DEV_VARIABLE_NAME, ParentDevicePath);
914
915 gBS->CloseProtocol (
916 Controller,
917 &gEfiSerialIoProtocolGuid,
918 This->DriverBindingHandle,
919 Controller
920 );
921
922 gBS->CloseProtocol (
923 Controller,
924 &gEfiDevicePathProtocolGuid,
925 This->DriverBindingHandle,
926 Controller
927 );
928
929 return EFI_SUCCESS;
930 }
931
932 AllChildrenStopped = TRUE;
933
934 for (Index = 0; Index < NumberOfChildren; Index++) {
935
936 Status = gBS->OpenProtocol (
937 ChildHandleBuffer[Index],
938 &gEfiSimpleTextOutProtocolGuid,
939 (VOID **) &SimpleTextOutput,
940 This->DriverBindingHandle,
941 ChildHandleBuffer[Index],
942 EFI_OPEN_PROTOCOL_GET_PROTOCOL
943 );
944 if (!EFI_ERROR (Status)) {
945
946 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);
947
948 gBS->CloseProtocol (
949 Controller,
950 &gEfiSerialIoProtocolGuid,
951 This->DriverBindingHandle,
952 ChildHandleBuffer[Index]
953 );
954
955 Status = gBS->UninstallMultipleProtocolInterfaces (
956 ChildHandleBuffer[Index],
957 &gEfiSimpleTextInProtocolGuid,
958 &TerminalDevice->SimpleInput,
959 &gEfiSimpleTextInputExProtocolGuid,
960 &TerminalDevice->SimpleInputEx,
961 &gEfiSimpleTextOutProtocolGuid,
962 &TerminalDevice->SimpleTextOutput,
963 &gEfiDevicePathProtocolGuid,
964 TerminalDevice->DevicePath,
965 NULL
966 );
967 if (EFI_ERROR (Status)) {
968 gBS->OpenProtocol (
969 Controller,
970 &gEfiSerialIoProtocolGuid,
971 (VOID **) &SerialIo,
972 This->DriverBindingHandle,
973 ChildHandleBuffer[Index],
974 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
975 );
976 } else {
977
978 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
979 StopTerminalStateMachine (TerminalDevice);
980 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
981 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);
982 gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);
983 TerminalFreeNotifyList (&TerminalDevice->NotifyList);
984 FreePool (TerminalDevice->DevicePath);
985 FreePool (TerminalDevice->TerminalConsoleModeData);
986 FreePool (TerminalDevice);
987 }
988 }
989
990 if (EFI_ERROR (Status)) {
991 AllChildrenStopped = FALSE;
992 }
993 }
994
995 if (!AllChildrenStopped) {
996 return EFI_DEVICE_ERROR;
997 }
998
999 return EFI_SUCCESS;
1000 }
1001
1002 /**
1003 Compare a device path data structure to that of all the nodes of a
1004 second device path instance.
1005
1006 @param Multi A pointer to a multi-instance device path data structure.
1007 @param Single A pointer to a single-instance device path data structure.
1008
1009 @retval TRUE If the Single is contained within Multi.
1010 @retval FALSE The Single is not match within Multi.
1011
1012 **/
1013 BOOLEAN
1014 MatchDevicePaths (
1015 IN EFI_DEVICE_PATH_PROTOCOL *Multi,
1016 IN EFI_DEVICE_PATH_PROTOCOL *Single
1017 )
1018 {
1019 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1020 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
1021 UINTN Size;
1022
1023 DevicePath = Multi;
1024 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
1025 //
1026 // Search for the match of 'Single' in 'Multi'
1027 //
1028 while (DevicePathInst != NULL) {
1029 //
1030 // If the single device path is found in multiple device paths,
1031 // return success
1032 //
1033 if (CompareMem (Single, DevicePathInst, Size) == 0) {
1034 FreePool (DevicePathInst);
1035 return TRUE;
1036 }
1037
1038 FreePool (DevicePathInst);
1039 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
1040 }
1041
1042 return FALSE;
1043 }
1044
1045 /**
1046 Update terminal device path in Console Device Environment Variables.
1047
1048 @param VariableName The Console Device Environment Variable.
1049 @param ParentDevicePath The terminal device path to be updated.
1050
1051 **/
1052 VOID
1053 TerminalUpdateConsoleDevVariable (
1054 IN CHAR16 *VariableName,
1055 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath
1056 )
1057 {
1058 EFI_STATUS Status;
1059 UINTN NameSize;
1060 UINTN VariableSize;
1061 TERMINAL_TYPE TerminalType;
1062 EFI_DEVICE_PATH_PROTOCOL *Variable;
1063 EFI_DEVICE_PATH_PROTOCOL *NewVariable;
1064 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
1065 EDKII_SET_VARIABLE_STATUS *SetVariableStatus;
1066
1067 //
1068 // Get global variable and its size according to the name given.
1069 //
1070 Status = GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);
1071 if (Status == EFI_NOT_FOUND) {
1072 Status = EFI_SUCCESS;
1073 Variable = NULL;
1074 }
1075 if (EFI_ERROR (Status)) {
1076 return;
1077 }
1078
1079 //
1080 // Append terminal device path onto the variable.
1081 //
1082 for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {
1083 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);
1084
1085 if (TempDevicePath != NULL) {
1086 if (!MatchDevicePaths (Variable, TempDevicePath)) {
1087 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);
1088 if (NewVariable != NULL) {
1089 if (Variable != NULL) {
1090 FreePool (Variable);
1091 }
1092 Variable = NewVariable;
1093 }
1094 }
1095
1096 FreePool (TempDevicePath);
1097 }
1098
1099 }
1100
1101 VariableSize = GetDevicePathSize (Variable);
1102
1103 Status = gRT->SetVariable (
1104 VariableName,
1105 &gEfiGlobalVariableGuid,
1106 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1107 VariableSize,
1108 Variable
1109 );
1110
1111 if (EFI_ERROR (Status)) {
1112 NameSize = StrSize (VariableName);
1113 SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize);
1114 if (SetVariableStatus != NULL) {
1115 CopyGuid (&SetVariableStatus->Guid, &gEfiGlobalVariableGuid);
1116 SetVariableStatus->NameSize = NameSize;
1117 SetVariableStatus->DataSize = VariableSize;
1118 SetVariableStatus->SetStatus = Status;
1119 SetVariableStatus->Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
1120 CopyMem (SetVariableStatus + 1, VariableName, NameSize);
1121 CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Variable, VariableSize);
1122
1123 REPORT_STATUS_CODE_EX (
1124 EFI_ERROR_CODE,
1125 PcdGet32 (PcdErrorCodeSetVariable),
1126 0,
1127 NULL,
1128 &gEdkiiStatusCodeDataTypeVariableGuid,
1129 SetVariableStatus,
1130 sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize
1131 );
1132
1133 FreePool (SetVariableStatus);
1134 }
1135 }
1136
1137 FreePool (Variable);
1138
1139 return ;
1140 }
1141
1142
1143 /**
1144 Remove terminal device path from Console Device Environment Variables.
1145
1146 @param VariableName Console Device Environment Variables.
1147 @param ParentDevicePath The terminal device path to be updated.
1148
1149 **/
1150 VOID
1151 TerminalRemoveConsoleDevVariable (
1152 IN CHAR16 *VariableName,
1153 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath
1154 )
1155 {
1156 EFI_STATUS Status;
1157 BOOLEAN FoundOne;
1158 BOOLEAN Match;
1159 UINTN VariableSize;
1160 UINTN InstanceSize;
1161 TERMINAL_TYPE TerminalType;
1162 EFI_DEVICE_PATH_PROTOCOL *Instance;
1163 EFI_DEVICE_PATH_PROTOCOL *Variable;
1164 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;
1165 EFI_DEVICE_PATH_PROTOCOL *NewVariable;
1166 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;
1167 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
1168
1169 Instance = NULL;
1170
1171 //
1172 // Get global variable and its size according to the name given.
1173 //
1174 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);
1175 if (Variable == NULL) {
1176 return ;
1177 }
1178
1179 FoundOne = FALSE;
1180 OriginalVariable = Variable;
1181 NewVariable = NULL;
1182
1183 //
1184 // Get first device path instance from Variable
1185 //
1186 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);
1187 if (Instance == NULL) {
1188 FreePool (OriginalVariable);
1189 return ;
1190 }
1191 //
1192 // Loop through all the device path instances of Variable
1193 //
1194 do {
1195 //
1196 // Loop through all the terminal types that this driver supports
1197 //
1198 Match = FALSE;
1199 for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {
1200
1201 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);
1202
1203 //
1204 // Compare the generated device path to the current device path instance
1205 //
1206 if (TempDevicePath != NULL) {
1207 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {
1208 Match = TRUE;
1209 FoundOne = TRUE;
1210 }
1211
1212 FreePool (TempDevicePath);
1213 }
1214 }
1215 //
1216 // If a match was not found, then keep the current device path instance
1217 //
1218 if (!Match) {
1219 SavedNewVariable = NewVariable;
1220 NewVariable = AppendDevicePathInstance (NewVariable, Instance);
1221 if (SavedNewVariable != NULL) {
1222 FreePool (SavedNewVariable);
1223 }
1224 }
1225 //
1226 // Get next device path instance from Variable
1227 //
1228 FreePool (Instance);
1229 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);
1230 } while (Instance != NULL);
1231
1232 FreePool (OriginalVariable);
1233
1234 if (FoundOne) {
1235 VariableSize = GetDevicePathSize (NewVariable);
1236
1237 Status = gRT->SetVariable (
1238 VariableName,
1239 &gEfiGlobalVariableGuid,
1240 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1241 VariableSize,
1242 NewVariable
1243 );
1244 //
1245 // Shrinking variable with existing variable driver implementation shouldn't fail.
1246 //
1247 ASSERT_EFI_ERROR (Status);
1248 }
1249
1250 if (NewVariable != NULL) {
1251 FreePool (NewVariable);
1252 }
1253
1254 return ;
1255 }
1256
1257 /**
1258 Build terminal device path according to terminal type.
1259
1260 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1261 @param ParentDevicePath Parent device path.
1262 @param TerminalDevicePath Returned terminal device path, if building successfully.
1263
1264 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1265 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1266 @retval EFI_SUCCESS Build terminal device path successfully.
1267
1268 **/
1269 EFI_STATUS
1270 SetTerminalDevicePath (
1271 IN TERMINAL_TYPE TerminalType,
1272 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
1273 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath
1274 )
1275 {
1276 VENDOR_DEVICE_PATH Node;
1277
1278 ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));
1279 Node.Header.Type = MESSAGING_DEVICE_PATH;
1280 Node.Header.SubType = MSG_VENDOR_DP;
1281 SetDevicePathNodeLength (&Node.Header, sizeof (VENDOR_DEVICE_PATH));
1282 CopyGuid (&Node.Guid, mTerminalType[TerminalType]);
1283
1284 //
1285 // Append the terminal node onto parent device path
1286 // to generate a complete terminal device path.
1287 //
1288 *TerminalDevicePath = AppendDevicePathNode (
1289 ParentDevicePath,
1290 (EFI_DEVICE_PATH_PROTOCOL *) &Node
1291 );
1292 if (*TerminalDevicePath == NULL) {
1293 return EFI_OUT_OF_RESOURCES;
1294 }
1295
1296 return EFI_SUCCESS;
1297 }
1298
1299 /**
1300 The user Entry Point for module Terminal. The user code starts with this function.
1301
1302 @param ImageHandle The firmware allocated handle for the EFI image.
1303 @param SystemTable A pointer to the EFI System Table.
1304
1305 @retval EFI_SUCCESS The entry point is executed successfully.
1306 @retval other Some error occurs when executing this entry point.
1307
1308 **/
1309 EFI_STATUS
1310 EFIAPI
1311 InitializeTerminal(
1312 IN EFI_HANDLE ImageHandle,
1313 IN EFI_SYSTEM_TABLE *SystemTable
1314 )
1315 {
1316 EFI_STATUS Status;
1317
1318 //
1319 // Install driver model protocol(s).
1320 //
1321 Status = EfiLibInstallDriverBindingComponentName2 (
1322 ImageHandle,
1323 SystemTable,
1324 &gTerminalDriverBinding,
1325 ImageHandle,
1326 &gTerminalComponentName,
1327 &gTerminalComponentName2
1328 );
1329 ASSERT_EFI_ERROR (Status);
1330
1331 return Status;
1332 }
1333
1334 /**
1335 Check if the device supports hot-plug through its device path.
1336
1337 This function could be updated to check more types of Hot Plug devices.
1338 Currently, it checks USB and PCCard device.
1339
1340 @param DevicePath Pointer to device's device path.
1341
1342 @retval TRUE The devcie is a hot-plug device
1343 @retval FALSE The devcie is not a hot-plug device.
1344
1345 **/
1346 BOOLEAN
1347 IsHotPlugDevice (
1348 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1349 )
1350 {
1351 EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;
1352
1353 CheckDevicePath = DevicePath;
1354 while (!IsDevicePathEnd (CheckDevicePath)) {
1355 //
1356 // Check device whether is hot plug device or not throught Device Path
1357 //
1358 if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&
1359 (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||
1360 DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||
1361 DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {
1362 //
1363 // If Device is USB device
1364 //
1365 return TRUE;
1366 }
1367 if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&
1368 (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {
1369 //
1370 // If Device is PCCard
1371 //
1372 return TRUE;
1373 }
1374
1375 CheckDevicePath = NextDevicePathNode (CheckDevicePath);
1376 }
1377
1378 return FALSE;
1379 }
1380