2 handles console redirection from boot manager
4 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BootMaint.h"
17 UART_FLOW_CONTROL_DEVICE_PATH mFlowControlDevicePath
=
20 MESSAGING_DEVICE_PATH
,
23 (UINT8
)(sizeof(UART_FLOW_CONTROL_DEVICE_PATH
)),
24 (UINT8
)((sizeof(UART_FLOW_CONTROL_DEVICE_PATH
)) >> 8)
27 DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL
,
28 UART_FLOW_CONTROL_HARDWARE
32 Check the device path node whether it's the Flow Control node or not.
34 @param[in] FlowControl The device path node to be checked.
36 @retval TRUE It's the Flow Control node.
37 @retval FALSE It's not.
41 IsUartFlowControlNode (
42 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
46 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
47 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
48 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
53 Check whether the device path node is ISA Serial Node.
55 @param Acpi Device path node to be checked
57 @retval TRUE It's ISA Serial Node.
58 @retval FALSE It's NOT ISA Serial Node.
63 IN ACPI_HID_DEVICE_PATH
*Acpi
67 (DevicePathType (Acpi
) == ACPI_DEVICE_PATH
) &&
68 (DevicePathSubType (Acpi
) == ACPI_DP
) &&
69 (ReadUnaligned32 (&Acpi
->HID
) == EISA_PNP_ID (0x0501))
74 Update Com Ports attributes from DevicePath
76 @param DevicePath DevicePath that contains Com ports
78 @retval EFI_SUCCESS The update is successful.
82 UpdateComAttributeFromVariable (
83 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
87 Update the multi-instance device path of Terminal Device based on
88 the global TerminalMenu. If ChangeTernimal is TRUE, the terminal
89 device path in the Terminal Device in TerminalMenu is also updated.
91 @param DevicePath The multi-instance device path.
92 @param ChangeTerminal TRUE, then device path in the Terminal Device
93 in TerminalMenu is also updated; FALSE, no update.
95 @return EFI_SUCCESS The function completes successfully.
99 ChangeTerminalDevicePath (
100 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
101 IN BOOLEAN ChangeTerminal
104 EFI_DEVICE_PATH_PROTOCOL
*Node
;
105 EFI_DEVICE_PATH_PROTOCOL
*Node1
;
106 ACPI_HID_DEVICE_PATH
*Acpi
;
107 UART_DEVICE_PATH
*Uart
;
108 UART_DEVICE_PATH
*Uart1
;
110 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
111 BM_MENU_ENTRY
*NewMenuEntry
;
112 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
115 Node
= NextDevicePathNode (Node
);
117 while (!IsDevicePathEnd (Node
)) {
118 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
119 if (IsIsaSerialNode (Acpi
)) {
120 CopyMem (&Com
, &Acpi
->UID
, sizeof (UINT32
));
123 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Com
);
125 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
126 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
127 Uart
= (UART_DEVICE_PATH
*) Node
;
130 &NewTerminalContext
->BaudRate
,
136 &NewTerminalContext
->DataBits
,
142 &NewTerminalContext
->Parity
,
148 &NewTerminalContext
->StopBits
,
152 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Node
);
153 if (IsUartFlowControlNode (FlowControlNode
)) {
154 FlowControlNode
->FlowControlMap
= NewTerminalContext
->FlowControl
;
157 // Append the Flow control device node when user enable flow control.
159 if (NewTerminalContext
->FlowControl
!= 0) {
160 mFlowControlDevicePath
.FlowControlMap
= NewTerminalContext
->FlowControl
;
161 *DevicePath
= AppendDevicePathNode (
163 (EFI_DEVICE_PATH_PROTOCOL
*) (&mFlowControlDevicePath
)
169 // Change the device path in the ComPort
171 if (ChangeTerminal
) {
172 Node1
= NewTerminalContext
->DevicePath
;
173 Node1
= NextDevicePathNode (Node1
);
174 while (!IsDevicePathEnd (Node1
)) {
175 if ((DevicePathType (Node1
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node1
) == MSG_UART_DP
)) {
176 Uart1
= (UART_DEVICE_PATH
*) Node1
;
179 &NewTerminalContext
->BaudRate
,
185 &NewTerminalContext
->DataBits
,
191 &NewTerminalContext
->Parity
,
197 &NewTerminalContext
->StopBits
,
205 Node1
= NextDevicePathNode (Node1
);
214 Node
= NextDevicePathNode (Node
);
222 Update the device path that describing a terminal device
223 based on the new BaudRate, Data Bits, parity and Stop Bits
226 @param DevicePath terminal device's path
230 ChangeVariableDevicePath (
231 IN OUT EFI_DEVICE_PATH_PROTOCOL
*DevicePath
234 EFI_DEVICE_PATH_PROTOCOL
*Node
;
235 ACPI_HID_DEVICE_PATH
*Acpi
;
236 UART_DEVICE_PATH
*Uart
;
238 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
239 BM_MENU_ENTRY
*NewMenuEntry
;
242 Node
= NextDevicePathNode (Node
);
244 while (!IsDevicePathEnd (Node
)) {
245 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
246 if (IsIsaSerialNode (Acpi
)) {
247 CopyMem (&Com
, &Acpi
->UID
, sizeof (UINT32
));
250 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
251 NewMenuEntry
= BOpt_GetMenuEntry (
255 ASSERT (NewMenuEntry
!= NULL
);
256 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
257 Uart
= (UART_DEVICE_PATH
*) Node
;
260 &NewTerminalContext
->BaudRate
,
266 &NewTerminalContext
->DataBits
,
272 &NewTerminalContext
->Parity
,
278 &NewTerminalContext
->StopBits
,
283 Node
= NextDevicePathNode (Node
);
288 Retrieve ACPI UID of UART from device path
290 @param Handle The handle for the UART device.
291 @param AcpiUid The ACPI UID on output.
293 @retval TRUE Find valid UID from device path
294 @retval FALSE Can't find
299 IN EFI_HANDLE Handle
,
300 IN OUT UINT32
*AcpiUid
304 ACPI_HID_DEVICE_PATH
*Acpi
;
305 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
307 Status
= gBS
->HandleProtocol (
309 &gEfiDevicePathProtocolGuid
,
310 (VOID
**) &DevicePath
312 if (EFI_ERROR (Status
)) {
317 for (; !IsDevicePathEnd (DevicePath
); DevicePath
= NextDevicePathNode (DevicePath
)) {
318 if ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (DevicePath
) == MSG_UART_DP
)) {
322 // Acpi points to the node before the Uart node
324 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
327 if ((Acpi
!= NULL
) && IsIsaSerialNode (Acpi
)) {
328 if (AcpiUid
!= NULL
) {
329 CopyMem (AcpiUid
, &Acpi
->UID
, sizeof (UINT32
));
338 Sort Uart handles array with Acpi->UID from low to high.
340 @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer
341 @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count
345 IN EFI_HANDLE
*Handles
,
355 EFI_HANDLE TempHandle
;
357 for (Index1
= 0; Index1
< NoHandles
-1; Index1
++) {
358 if (!RetrieveUartUid (Handles
[Index1
], &AcpiUid1
)) {
361 TempHandle
= Handles
[Index1
];
363 TempAcpiUid
= AcpiUid1
;
365 for (Index2
= Index1
+1; Index2
< NoHandles
; Index2
++) {
366 if (!RetrieveUartUid (Handles
[Index2
], &AcpiUid2
)) {
369 if (AcpiUid2
< TempAcpiUid
) {
370 TempAcpiUid
= AcpiUid2
;
371 TempHandle
= Handles
[Index2
];
375 Handles
[Position
] = Handles
[Index1
];
376 Handles
[Index1
] = TempHandle
;
381 Test whether DevicePath is a valid Terminal
384 @param DevicePath DevicePath to be checked
385 @param Termi If DevicePath is valid Terminal, terminal type is returned.
386 @param Com If DevicePath is valid Terminal, Com Port type is returned.
388 @retval TRUE If DevicePath point to a Terminal.
389 @retval FALSE If DevicePath does not point to a Terminal.
393 IsTerminalDevicePath (
394 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
395 OUT TYPE_OF_TERMINAL
*Termi
,
400 Build a list containing all serial devices.
403 @retval EFI_SUCCESS The function complete successfully.
404 @retval EFI_UNSUPPORTED No serial ports present.
417 ACPI_HID_DEVICE_PATH
*Acpi
;
418 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
419 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
420 EFI_DEVICE_PATH_PROTOCOL
*Node
;
421 EFI_DEVICE_PATH_PROTOCOL
*OutDevicePath
;
422 EFI_DEVICE_PATH_PROTOCOL
*InpDevicePath
;
423 EFI_DEVICE_PATH_PROTOCOL
*ErrDevicePath
;
424 BM_MENU_ENTRY
*NewMenuEntry
;
425 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
426 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
427 VENDOR_DEVICE_PATH Vendor
;
430 // Get all handles that have SerialIo protocol installed
432 InitializeListHead (&TerminalMenu
.Head
);
433 TerminalMenu
.MenuNumber
= 0;
434 Status
= gBS
->LocateHandleBuffer (
436 &gEfiSerialIoProtocolGuid
,
441 if (EFI_ERROR (Status
)) {
443 // No serial ports present
445 return EFI_UNSUPPORTED
;
449 // Sort Uart handles array with Acpi->UID from low to high
450 // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
452 SortedUartHandle (Handles
, NoHandles
);
454 for (Index
= 0; Index
< NoHandles
; Index
++) {
456 // Check to see whether the handle has DevicePath Protocol installed
458 gBS
->HandleProtocol (
460 &gEfiDevicePathProtocolGuid
,
461 (VOID
**) &DevicePath
465 for (Node
= DevicePath
; !IsDevicePathEnd (Node
); Node
= NextDevicePathNode (Node
)) {
466 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
470 // Acpi points to the node before Uart node
472 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
475 if ((Acpi
!= NULL
) && IsIsaSerialNode (Acpi
)) {
476 NewMenuEntry
= BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT
);
477 if (NewMenuEntry
== NULL
) {
479 return EFI_OUT_OF_RESOURCES
;
482 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
483 CopyMem (&NewMenuEntry
->OptionNumber
, &Acpi
->UID
, sizeof (UINT32
));
484 NewTerminalContext
->DevicePath
= DuplicateDevicePath (DevicePath
);
486 // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
487 // coz' the misc data for each platform is not correct, actually it's the device path stored in
488 // datahub which is not completed, so a searching for end of device path will enter a
491 NewMenuEntry
->DisplayString
= EfiLibStrFromDatahub (DevicePath
);
492 if (NULL
== NewMenuEntry
->DisplayString
) {
493 NewMenuEntry
->DisplayString
= DevicePathToStr (DevicePath
);
496 NewMenuEntry
->HelpString
= NULL
;
498 gBS
->HandleProtocol (
500 &gEfiSerialIoProtocolGuid
,
505 &NewTerminalContext
->BaudRate
,
506 &SerialIo
->Mode
->BaudRate
,
511 &NewTerminalContext
->DataBits
,
512 &SerialIo
->Mode
->DataBits
,
517 &NewTerminalContext
->Parity
,
518 &SerialIo
->Mode
->Parity
,
523 &NewTerminalContext
->StopBits
,
524 &SerialIo
->Mode
->StopBits
,
528 NewTerminalContext
->FlowControl
= 0;
529 SerialIo
->GetControl(SerialIo
, &FlowControl
);
530 if ((FlowControl
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) != 0) {
531 NewTerminalContext
->FlowControl
= UART_FLOW_CONTROL_HARDWARE
;
534 InsertTailList (&TerminalMenu
.Head
, &NewMenuEntry
->Link
);
535 TerminalMenu
.MenuNumber
++;
538 if (Handles
!= NULL
) {
543 // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
545 OutDevicePath
= EfiLibGetVariable (L
"ConOut", &gEfiGlobalVariableGuid
);
546 InpDevicePath
= EfiLibGetVariable (L
"ConIn", &gEfiGlobalVariableGuid
);
547 ErrDevicePath
= EfiLibGetVariable (L
"ErrOut", &gEfiGlobalVariableGuid
);
548 if (OutDevicePath
!= NULL
) {
549 UpdateComAttributeFromVariable (OutDevicePath
);
552 if (InpDevicePath
!= NULL
) {
553 UpdateComAttributeFromVariable (InpDevicePath
);
556 if (ErrDevicePath
!= NULL
) {
557 UpdateComAttributeFromVariable (ErrDevicePath
);
560 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
561 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
562 if (NULL
== NewMenuEntry
) {
563 return EFI_NOT_FOUND
;
566 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
568 NewTerminalContext
->TerminalType
= 0;
569 NewTerminalContext
->IsConIn
= FALSE
;
570 NewTerminalContext
->IsConOut
= FALSE
;
571 NewTerminalContext
->IsStdErr
= FALSE
;
573 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
574 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
576 for (Index2
= 0; Index2
< 4; Index2
++) {
577 CopyMem (&Vendor
.Guid
, &TerminalTypeGuid
[Index2
], sizeof (EFI_GUID
));
578 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
579 NewDevicePath
= AppendDevicePathNode (
580 NewTerminalContext
->DevicePath
,
581 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
583 if (NewMenuEntry
->HelpString
!= NULL
) {
584 FreePool (NewMenuEntry
->HelpString
);
587 // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
588 // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
590 NewMenuEntry
->HelpString
= NULL
;
592 if (BdsLibMatchDevicePaths (OutDevicePath
, NewDevicePath
)) {
593 NewTerminalContext
->IsConOut
= TRUE
;
594 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
597 if (BdsLibMatchDevicePaths (InpDevicePath
, NewDevicePath
)) {
598 NewTerminalContext
->IsConIn
= TRUE
;
599 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
602 if (BdsLibMatchDevicePaths (ErrDevicePath
, NewDevicePath
)) {
603 NewTerminalContext
->IsStdErr
= TRUE
;
604 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
613 Update Com Ports attributes from DevicePath
615 @param DevicePath DevicePath that contains Com ports
617 @retval EFI_SUCCESS The update is successful.
618 @retval EFI_NOT_FOUND Can not find specific menu entry
621 UpdateComAttributeFromVariable (
622 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
625 EFI_DEVICE_PATH_PROTOCOL
*Node
;
626 EFI_DEVICE_PATH_PROTOCOL
*SerialNode
;
627 ACPI_HID_DEVICE_PATH
*Acpi
;
628 UART_DEVICE_PATH
*Uart
;
629 UART_DEVICE_PATH
*Uart1
;
630 UINTN TerminalNumber
;
631 BM_MENU_ENTRY
*NewMenuEntry
;
632 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
634 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
635 BOOLEAN HasFlowControlNode
;
637 HasFlowControlNode
= FALSE
;
639 Node
= NextDevicePathNode (Node
);
641 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
642 while (!IsDevicePathEnd (Node
)) {
643 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
644 if (IsIsaSerialNode (Acpi
)) {
645 CopyMem (&TerminalNumber
, &Acpi
->UID
, sizeof (UINT32
));
648 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
649 Uart
= (UART_DEVICE_PATH
*) Node
;
650 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, TerminalNumber
);
651 if (NULL
== NewMenuEntry
) {
652 return EFI_NOT_FOUND
;
655 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
657 &NewTerminalContext
->BaudRate
,
663 &NewTerminalContext
->DataBits
,
669 &NewTerminalContext
->Parity
,
675 &NewTerminalContext
->StopBits
,
680 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Node
);
681 if (IsUartFlowControlNode (FlowControlNode
)) {
682 HasFlowControlNode
= TRUE
;
683 NewTerminalContext
->FlowControl
= (UINT8
) ReadUnaligned32 (&FlowControlNode
->FlowControlMap
);
684 } else if (NewTerminalContext
->FlowControl
!= 0) {
686 // No Flow Control device path node, assumption no Flow control
688 NewTerminalContext
->FlowControl
= 0;
691 SerialNode
= NewTerminalContext
->DevicePath
;
692 SerialNode
= NextDevicePathNode (SerialNode
);
693 while (!IsDevicePathEnd (SerialNode
)) {
694 if ((DevicePathType (SerialNode
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (SerialNode
) == MSG_UART_DP
)) {
696 // Update following device paths according to
697 // previous acquired uart attributes
699 Uart1
= (UART_DEVICE_PATH
*) SerialNode
;
702 &NewTerminalContext
->BaudRate
,
708 &NewTerminalContext
->DataBits
,
713 &NewTerminalContext
->Parity
,
718 &NewTerminalContext
->StopBits
,
722 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (SerialNode
);
723 if (IsUartFlowControlNode (FlowControlNode
)) {
724 FlowControlNode
->FlowControlMap
= NewTerminalContext
->FlowControl
;
726 if (HasFlowControlNode
) {
727 mFlowControlDevicePath
.FlowControlMap
= NewTerminalContext
->FlowControl
;
728 NewTerminalContext
->DevicePath
= AppendDevicePathNode (
729 NewTerminalContext
->DevicePath
,
730 (EFI_DEVICE_PATH_PROTOCOL
*) (&mFlowControlDevicePath
)
737 SerialNode
= NextDevicePathNode (SerialNode
);
744 Node
= NextDevicePathNode (Node
);
755 Build up Console Menu based on types passed in. The type can
756 be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
757 and BM_CONSOLE_ERR_CONTEXT_SELECT.
759 @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
760 and BM_CONSOLE_ERR_CONTEXT_SELECT.
762 @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.
763 @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev",
764 "ConInDev" or "ConErrDev" doesn't exists.
765 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.
766 @retval EFI_SUCCESS Function completes successfully.
771 IN UINTN ConsoleMenuType
774 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
775 EFI_DEVICE_PATH_PROTOCOL
*AllDevicePath
;
776 EFI_DEVICE_PATH_PROTOCOL
*MultiDevicePath
;
777 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
782 BM_MENU_ENTRY
*NewMenuEntry
;
783 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
784 TYPE_OF_TERMINAL Terminal
;
786 BM_MENU_OPTION
*ConsoleMenu
;
789 AllDevicePath
= NULL
;
791 switch (ConsoleMenuType
) {
792 case BM_CONSOLE_IN_CONTEXT_SELECT
:
793 ConsoleMenu
= &ConsoleInpMenu
;
794 DevicePath
= EfiLibGetVariable (
796 &gEfiGlobalVariableGuid
799 AllDevicePath
= EfiLibGetVariable (
801 &gEfiGlobalVariableGuid
805 case BM_CONSOLE_OUT_CONTEXT_SELECT
:
806 ConsoleMenu
= &ConsoleOutMenu
;
807 DevicePath
= EfiLibGetVariable (
809 &gEfiGlobalVariableGuid
812 AllDevicePath
= EfiLibGetVariable (
814 &gEfiGlobalVariableGuid
818 case BM_CONSOLE_ERR_CONTEXT_SELECT
:
819 ConsoleMenu
= &ConsoleErrMenu
;
820 DevicePath
= EfiLibGetVariable (
822 &gEfiGlobalVariableGuid
825 AllDevicePath
= EfiLibGetVariable (
827 &gEfiGlobalVariableGuid
832 return EFI_UNSUPPORTED
;
835 if (NULL
== AllDevicePath
) {
836 return EFI_NOT_FOUND
;
839 InitializeListHead (&ConsoleMenu
->Head
);
841 AllCount
= EfiDevicePathInstanceCount (AllDevicePath
);
842 ConsoleMenu
->MenuNumber
= 0;
844 // Following is menu building up for Console Devices selected.
846 MultiDevicePath
= AllDevicePath
;
848 for (Index
= 0; Index
< AllCount
; Index
++) {
849 DevicePathInst
= GetNextDevicePathInstance (&MultiDevicePath
, &Size
);
851 NewMenuEntry
= BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT
);
852 if (NULL
== NewMenuEntry
) {
853 return EFI_OUT_OF_RESOURCES
;
856 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
857 NewMenuEntry
->OptionNumber
= Index2
;
859 NewConsoleContext
->DevicePath
= DuplicateDevicePath (DevicePathInst
);
860 ASSERT (NewConsoleContext
->DevicePath
!= NULL
);
861 NewMenuEntry
->DisplayString
= EfiLibStrFromDatahub (NewConsoleContext
->DevicePath
);
862 if (NULL
== NewMenuEntry
->DisplayString
) {
863 NewMenuEntry
->DisplayString
= DevicePathToStr (NewConsoleContext
->DevicePath
);
866 NewConsoleContext
->IsTerminal
= IsTerminalDevicePath (
867 NewConsoleContext
->DevicePath
,
872 NewConsoleContext
->IsActive
= BdsLibMatchDevicePaths (
874 NewConsoleContext
->DevicePath
877 if (NewConsoleContext
->IsTerminal
) {
878 BOpt_DestroyMenuEntry (NewMenuEntry
);
881 ConsoleMenu
->MenuNumber
++;
882 InsertTailList (&ConsoleMenu
->Head
, &NewMenuEntry
->Link
);
890 Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
892 @retval EFI_SUCCESS The function always complete successfully.
900 GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT
);
901 GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT
);
902 GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT
);
907 Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
909 @retval EFI_SUCCESS The function always complete successfully.
916 BOpt_FreeMenu (&ConsoleOutMenu
);
917 BOpt_FreeMenu (&ConsoleInpMenu
);
918 BOpt_FreeMenu (&ConsoleErrMenu
);
919 BOpt_FreeMenu (&TerminalMenu
);
924 Test whether DevicePath is a valid Terminal
927 @param DevicePath DevicePath to be checked
928 @param Termi If DevicePath is valid Terminal, terminal type is returned.
929 @param Com If DevicePath is valid Terminal, Com Port type is returned.
931 @retval TRUE If DevicePath point to a Terminal.
932 @retval FALSE If DevicePath does not point to a Terminal.
936 IsTerminalDevicePath (
937 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
938 OUT TYPE_OF_TERMINAL
*Termi
,
943 EFI_DEVICE_PATH_PROTOCOL
*Node
;
944 VENDOR_DEVICE_PATH
*Vendor
;
945 UART_DEVICE_PATH
*Uart
;
946 ACPI_HID_DEVICE_PATH
*Acpi
;
953 for (Node
= DevicePath
; !IsDevicePathEnd (Node
); Node
= NextDevicePathNode (Node
)) {
955 // Vendor points to the node before the End node
957 Vendor
= (VENDOR_DEVICE_PATH
*) Node
;
959 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
960 Uart
= (UART_DEVICE_PATH
*) Node
;
965 // Acpi points to the node before the UART node
967 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
971 if (Vendor
== NULL
||
972 DevicePathType (Vendor
) != MESSAGING_DEVICE_PATH
||
973 DevicePathSubType (Vendor
) != MSG_VENDOR_DP
||
979 // There are four kinds of Terminal types
980 // check to see whether this devicepath
981 // is one of that type
983 if (CompareGuid (&Vendor
->Guid
, &TerminalTypeGuid
[0])) {
984 *Termi
= TerminalTypePcAnsi
;
987 if (CompareGuid (&Vendor
->Guid
, &TerminalTypeGuid
[1])) {
988 *Termi
= TerminalTypeVt100
;
991 if (CompareGuid (&Vendor
->Guid
, &TerminalTypeGuid
[2])) {
992 *Termi
= TerminalTypeVt100Plus
;
995 if (CompareGuid (&Vendor
->Guid
, &TerminalTypeGuid
[3])) {
996 *Termi
= TerminalTypeVtUtf8
;
1009 if ((Acpi
!= NULL
) && IsIsaSerialNode (Acpi
)) {
1010 CopyMem (Com
, &Acpi
->UID
, sizeof (UINT32
));
1019 Get mode number according to column and row
1021 @param CallbackData The BMM context data.
1025 IN BMM_CALLBACK_DATA
*CallbackData
1035 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
1037 ConOut
= gST
->ConOut
;
1038 MaxMode
= (UINTN
) (ConOut
->Mode
->MaxMode
);
1040 CurrentCol
= PcdGet32 (PcdSetupConOutColumn
);
1041 CurrentRow
= PcdGet32 (PcdSetupConOutRow
);
1042 for (Mode
= 0; Mode
< MaxMode
; Mode
++) {
1043 Status
= ConOut
->QueryMode (ConOut
, Mode
, &Col
, &Row
);
1044 if (!EFI_ERROR(Status
)) {
1045 if (CurrentCol
== Col
&& CurrentRow
== Row
) {
1046 CallbackData
->BmmFakeNvData
.ConsoleOutMode
= (UINT16
) Mode
;