2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 handles console redirection from boot manager
24 #include "BootMaint.h"
26 EFI_DEVICE_PATH_PROTOCOL
*
27 DevicePathInstanceDup (
28 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
32 UpdateComAttributeFromVariable (
33 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
37 ChangeTerminalDevicePath (
38 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
39 BOOLEAN ChangeTerminal
42 EFI_DEVICE_PATH_PROTOCOL
*Node
;
43 EFI_DEVICE_PATH_PROTOCOL
*Node1
;
44 ACPI_HID_DEVICE_PATH
*Acpi
;
45 UART_DEVICE_PATH
*Uart
;
46 UART_DEVICE_PATH
*Uart1
;
49 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
50 BM_MENU_ENTRY
*NewMenuEntry
;
52 Match
= EISA_PNP_ID (0x0501);
54 Node
= NextDevicePathNode (Node
);
56 while (!IsDevicePathEnd (Node
)) {
57 if ((DevicePathType (Node
) == ACPI_DEVICE_PATH
) && (DevicePathSubType (Node
) == ACPI_DP
)) {
58 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
59 if (CompareMem (&Acpi
->HID
, &Match
, sizeof (UINT32
)) == 0) {
60 CopyMem (&Com
, &Acpi
->UID
, sizeof (UINT32
));
64 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Com
);
65 if (NULL
== NewMenuEntry
) {
69 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
70 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
71 Uart
= (UART_DEVICE_PATH
*) Node
;
74 &NewTerminalContext
->BaudRate
,
80 &NewTerminalContext
->DataBits
,
86 &NewTerminalContext
->Parity
,
92 &NewTerminalContext
->StopBits
,
96 // Change the device path in the ComPort
99 Node1
= NewTerminalContext
->DevicePath
;
100 Node1
= NextDevicePathNode (Node1
);
101 while (!IsDevicePathEnd (Node1
)) {
102 if ((DevicePathType (Node1
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node1
) == MSG_UART_DP
)) {
103 Uart1
= (UART_DEVICE_PATH
*) Node1
;
106 &NewTerminalContext
->BaudRate
,
112 &NewTerminalContext
->DataBits
,
118 &NewTerminalContext
->Parity
,
124 &NewTerminalContext
->StopBits
,
132 Node1
= NextDevicePathNode (Node1
);
141 Node
= NextDevicePathNode (Node
);
149 ChangeVariableDevicePath (
150 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
153 EFI_DEVICE_PATH_PROTOCOL
*Node
;
154 ACPI_HID_DEVICE_PATH
*Acpi
;
155 UART_DEVICE_PATH
*Uart
;
158 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
159 BM_MENU_ENTRY
*NewMenuEntry
;
161 Match
= EISA_PNP_ID (0x0501);
163 Node
= NextDevicePathNode (Node
);
165 while (!IsDevicePathEnd (Node
)) {
166 if ((DevicePathType (Node
) == ACPI_DEVICE_PATH
) && (DevicePathSubType (Node
) == ACPI_DP
)) {
167 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
168 if (CompareMem (&Acpi
->HID
, &Match
, sizeof (UINT32
)) == 0) {
169 CopyMem (&Com
, &Acpi
->UID
, sizeof (UINT32
));
173 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
174 NewMenuEntry
= BOpt_GetMenuEntry (
178 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
179 Uart
= (UART_DEVICE_PATH
*) Node
;
182 &NewTerminalContext
->BaudRate
,
188 &NewTerminalContext
->DataBits
,
194 &NewTerminalContext
->Parity
,
200 &NewTerminalContext
->StopBits
,
205 Node
= NextDevicePathNode (Node
);
212 IsTerminalDevicePath (
213 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
214 OUT TYPE_OF_TERMINAL
*Termi
,
225 Build a list containing all serial devices
239 ACPI_HID_DEVICE_PATH
*Acpi
;
240 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
242 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
243 EFI_DEVICE_PATH_PROTOCOL
*OutDevicePath
;
244 EFI_DEVICE_PATH_PROTOCOL
*InpDevicePath
;
245 EFI_DEVICE_PATH_PROTOCOL
*ErrDevicePath
;
246 BM_MENU_ENTRY
*NewMenuEntry
;
247 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
248 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
249 VENDOR_DEVICE_PATH Vendor
;
251 // Get all handles that have SerialIo protocol installed
253 InitializeListHead (&TerminalMenu
.Head
);
254 TerminalMenu
.MenuNumber
= 0;
255 Status
= gBS
->LocateHandleBuffer (
257 &gEfiSerialIoProtocolGuid
,
262 if (EFI_ERROR (Status
)) {
264 // No serial ports present
266 return EFI_UNSUPPORTED
;
269 for (Index
= 0; Index
< NoHandles
; Index
++) {
271 // Check to see whether the handle has DevicePath Protocol installed
273 gBS
->HandleProtocol (
275 &gEfiDevicePathProtocolGuid
,
278 Ptr
= (UINT8
*) DevicePath
;
279 while (*Ptr
!= END_DEVICE_PATH_TYPE
) {
283 Ptr
= Ptr
- sizeof (UART_DEVICE_PATH
) - sizeof (ACPI_HID_DEVICE_PATH
);
284 Acpi
= (ACPI_HID_DEVICE_PATH
*) Ptr
;
285 Match
= EISA_PNP_ID (0x0501);
287 if (CompareMem (&Acpi
->HID
, &Match
, sizeof (UINT32
)) == 0) {
288 NewMenuEntry
= BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT
);
290 return EFI_OUT_OF_RESOURCES
;
293 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
294 CopyMem (&NewMenuEntry
->OptionNumber
, &Acpi
->UID
, sizeof (UINT32
));
295 NewTerminalContext
->DevicePath
= DevicePathInstanceDup (DevicePath
);
297 // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
298 // coz' the misc data for each platform is not correct, actually it's the device path stored in
299 // datahub which is not completed, so a searching for end of device path will enter a
302 NewMenuEntry
->DisplayString
= EfiLibStrFromDatahub (DevicePath
);
303 if (NULL
== NewMenuEntry
->DisplayString
) {
304 NewMenuEntry
->DisplayString
= DevicePathToStr (DevicePath
);
307 NewMenuEntry
->HelpString
= NULL
;
309 gBS
->HandleProtocol (
311 &gEfiSerialIoProtocolGuid
,
316 &NewTerminalContext
->BaudRate
,
317 &SerialIo
->Mode
->BaudRate
,
322 &NewTerminalContext
->DataBits
,
323 &SerialIo
->Mode
->DataBits
,
328 &NewTerminalContext
->Parity
,
329 &SerialIo
->Mode
->Parity
,
334 &NewTerminalContext
->StopBits
,
335 &SerialIo
->Mode
->StopBits
,
338 InsertTailList (&TerminalMenu
.Head
, &NewMenuEntry
->Link
);
339 TerminalMenu
.MenuNumber
++;
343 // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
345 OutDevicePath
= EfiLibGetVariable (L
"ConOut", &gEfiGlobalVariableGuid
);
346 InpDevicePath
= EfiLibGetVariable (L
"ConIn", &gEfiGlobalVariableGuid
);
347 ErrDevicePath
= EfiLibGetVariable (L
"ErrOut", &gEfiGlobalVariableGuid
);
349 UpdateComAttributeFromVariable (OutDevicePath
);
353 UpdateComAttributeFromVariable (InpDevicePath
);
357 UpdateComAttributeFromVariable (ErrDevicePath
);
360 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
361 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
362 if (NULL
== NewMenuEntry
) {
363 return EFI_NOT_FOUND
;
366 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
368 NewTerminalContext
->TerminalType
= 0;
369 NewTerminalContext
->IsConIn
= FALSE
;
370 NewTerminalContext
->IsConOut
= FALSE
;
371 NewTerminalContext
->IsStdErr
= FALSE
;
373 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
374 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
376 for (Index2
= 0; Index2
< 4; Index2
++) {
377 CopyMem (&Vendor
.Guid
, &Guid
[Index2
], sizeof (EFI_GUID
));
378 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
379 NewDevicePath
= AppendDevicePathNode (
380 NewTerminalContext
->DevicePath
,
381 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
383 SafeFreePool (NewMenuEntry
->HelpString
);
385 // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
386 // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
388 NewMenuEntry
->HelpString
= NULL
;
390 if (BdsLibMatchDevicePaths (OutDevicePath
, NewDevicePath
)) {
391 NewTerminalContext
->IsConOut
= TRUE
;
392 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
395 if (BdsLibMatchDevicePaths (InpDevicePath
, NewDevicePath
)) {
396 NewTerminalContext
->IsConIn
= TRUE
;
397 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
400 if (BdsLibMatchDevicePaths (ErrDevicePath
, NewDevicePath
)) {
401 NewTerminalContext
->IsStdErr
= TRUE
;
402 NewTerminalContext
->TerminalType
= (UINT8
) Index2
;
411 UpdateComAttributeFromVariable (
412 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
417 Update Com Ports attributes from DevicePath
420 DevicePath - DevicePath that contains Com ports
426 EFI_DEVICE_PATH_PROTOCOL
*Node
;
427 EFI_DEVICE_PATH_PROTOCOL
*SerialNode
;
428 ACPI_HID_DEVICE_PATH
*Acpi
;
429 UART_DEVICE_PATH
*Uart
;
430 UART_DEVICE_PATH
*Uart1
;
432 UINTN TerminalNumber
;
433 BM_MENU_ENTRY
*NewMenuEntry
;
434 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
437 Match
= EISA_PNP_ID (0x0501);
439 Node
= NextDevicePathNode (Node
);
441 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
442 while (!IsDevicePathEnd (Node
)) {
443 if ((DevicePathType (Node
) == ACPI_DEVICE_PATH
) && (DevicePathSubType (Node
) == ACPI_DP
)) {
444 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
445 if (CompareMem (&Acpi
->HID
, &Match
, sizeof (UINT32
)) == 0) {
446 CopyMem (&TerminalNumber
, &Acpi
->UID
, sizeof (UINT32
));
450 if ((DevicePathType (Node
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (Node
) == MSG_UART_DP
)) {
451 Uart
= (UART_DEVICE_PATH
*) Node
;
452 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, TerminalNumber
);
453 if (NULL
== NewMenuEntry
) {
454 return EFI_NOT_FOUND
;
457 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
459 &NewTerminalContext
->BaudRate
,
465 &NewTerminalContext
->DataBits
,
471 &NewTerminalContext
->Parity
,
477 &NewTerminalContext
->StopBits
,
482 SerialNode
= NewTerminalContext
->DevicePath
;
483 SerialNode
= NextDevicePathNode (SerialNode
);
484 while (!IsDevicePathEnd (SerialNode
)) {
485 if ((DevicePathType (SerialNode
) == MESSAGING_DEVICE_PATH
) && (DevicePathSubType (SerialNode
) == MSG_UART_DP
)) {
487 // Update following device paths according to
488 // previous acquired uart attributes
490 Uart1
= (UART_DEVICE_PATH
*) SerialNode
;
493 &NewTerminalContext
->BaudRate
,
499 &NewTerminalContext
->DataBits
,
504 &NewTerminalContext
->Parity
,
509 &NewTerminalContext
->StopBits
,
516 SerialNode
= NextDevicePathNode (SerialNode
);
523 Node
= NextDevicePathNode (Node
);
533 EFI_DEVICE_PATH_PROTOCOL
*
534 DevicePathInstanceDup (
535 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
540 Function creates a device path data structure that identically matches the
541 device path passed in.
544 DevPath - A pointer to a device path data structure.
548 The new copy of DevPath is created to identically match the input.
549 Otherwise, NULL is returned.
553 EFI_DEVICE_PATH_PROTOCOL
*NewDevPath
;
554 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
555 EFI_DEVICE_PATH_PROTOCOL
*Temp
;
560 // get the size of an instance from the input
563 DevicePathInst
= GetNextDevicePathInstance (&Temp
, &Size
);
566 // Make a copy and set proper end type
570 NewDevPath
= AllocateZeroPool (Size
);
571 ASSERT (NewDevPath
!= NULL
);
575 CopyMem (NewDevPath
, DevicePathInst
, Size
);
576 Ptr
= (UINT8
*) NewDevPath
;
577 Ptr
+= Size
- sizeof (EFI_DEVICE_PATH_PROTOCOL
);
578 Temp
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
579 SetDevicePathEndNode (Temp
);
587 IN UINTN ConsoleMenuType
590 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
591 EFI_DEVICE_PATH_PROTOCOL
*AllDevicePath
;
592 EFI_DEVICE_PATH_PROTOCOL
*MultiDevicePath
;
593 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
598 BM_MENU_ENTRY
*NewMenuEntry
;
599 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
600 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
601 TYPE_OF_TERMINAL Terminal
;
602 BM_MENU_ENTRY
*NewTerminalMenuEntry
;
604 BM_MENU_OPTION
*ConsoleMenu
;
607 AllDevicePath
= NULL
;
609 switch (ConsoleMenuType
) {
610 case BM_CONSOLE_IN_CONTEXT_SELECT
:
611 ConsoleMenu
= &ConsoleInpMenu
;
612 DevicePath
= EfiLibGetVariable (
614 &gEfiGlobalVariableGuid
617 AllDevicePath
= EfiLibGetVariable (
619 &gEfiGlobalVariableGuid
623 case BM_CONSOLE_OUT_CONTEXT_SELECT
:
624 ConsoleMenu
= &ConsoleOutMenu
;
625 DevicePath
= EfiLibGetVariable (
627 &gEfiGlobalVariableGuid
630 AllDevicePath
= EfiLibGetVariable (
632 &gEfiGlobalVariableGuid
636 case BM_CONSOLE_ERR_CONTEXT_SELECT
:
637 ConsoleMenu
= &ConsoleErrMenu
;
638 DevicePath
= EfiLibGetVariable (
640 &gEfiGlobalVariableGuid
643 AllDevicePath
= EfiLibGetVariable (
645 &gEfiGlobalVariableGuid
650 return EFI_UNSUPPORTED
;
653 if (NULL
== AllDevicePath
) {
654 return EFI_NOT_FOUND
;
657 InitializeListHead (&ConsoleMenu
->Head
);
659 AllCount
= EfiDevicePathInstanceCount (AllDevicePath
);
660 ConsoleMenu
->MenuNumber
= 0;
662 // Following is menu building up for Console Out Devices
664 MultiDevicePath
= AllDevicePath
;
666 for (Index
= 0; Index
< AllCount
; Index
++) {
667 DevicePathInst
= GetNextDevicePathInstance (&MultiDevicePath
, &Size
);
669 NewMenuEntry
= BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT
);
670 if (NULL
== NewMenuEntry
) {
671 return EFI_OUT_OF_RESOURCES
;
674 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
675 NewMenuEntry
->OptionNumber
= Index2
;
677 NewConsoleContext
->DevicePath
= DevicePathInstanceDup (DevicePathInst
);
678 NewMenuEntry
->DisplayString
= EfiLibStrFromDatahub (NewConsoleContext
->DevicePath
);
679 if (NULL
== NewMenuEntry
->DisplayString
) {
680 NewMenuEntry
->DisplayString
= DevicePathToStr (NewConsoleContext
->DevicePath
);
683 NewConsoleContext
->IsTerminal
= IsTerminalDevicePath (
684 NewConsoleContext
->DevicePath
,
689 NewConsoleContext
->IsActive
= BdsLibMatchDevicePaths (
691 NewConsoleContext
->DevicePath
693 NewTerminalMenuEntry
= NULL
;
694 NewTerminalContext
= NULL
;
696 if (NewConsoleContext
->IsTerminal
) {
697 BOpt_DestroyMenuEntry (NewMenuEntry
);
700 ConsoleMenu
->MenuNumber
++;
701 InsertTailList (&ConsoleMenu
->Head
, &NewMenuEntry
->Link
);
715 Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
725 GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT
);
726 GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT
);
727 GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT
);
738 Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
748 BOpt_FreeMenu (&ConsoleOutMenu
);
749 BOpt_FreeMenu (&ConsoleInpMenu
);
750 BOpt_FreeMenu (&ConsoleErrMenu
);
751 BOpt_FreeMenu (&TerminalMenu
);
756 IsTerminalDevicePath (
757 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
758 OUT TYPE_OF_TERMINAL
*Termi
,
764 Test whether DevicePath is a valid Terminal
767 DevicePath - DevicePath to be checked
768 Termi - If is terminal, give its type
769 Com - If is Com Port, give its type
772 TRUE - If DevicePath point to a Terminal
779 VENDOR_DEVICE_PATH
*Vendor
;
780 ACPI_HID_DEVICE_PATH
*Acpi
;
787 // Parse the Device Path, should be change later!!!
789 Ptr
= (UINT8
*) DevicePath
;
790 while (*Ptr
!= END_DEVICE_PATH_TYPE
) {
794 Ptr
= Ptr
- sizeof (VENDOR_DEVICE_PATH
);
795 Vendor
= (VENDOR_DEVICE_PATH
*) Ptr
;
798 // There are four kinds of Terminal types
799 // check to see whether this devicepath
800 // is one of that type
802 CopyMem (&TempGuid
, &Vendor
->Guid
, sizeof (EFI_GUID
));
804 if (CompareGuid (&TempGuid
, &Guid
[0])) {
808 if (CompareGuid (&TempGuid
, &Guid
[1])) {
812 if (CompareGuid (&TempGuid
, &Guid
[2])) {
813 *Termi
= VT_100_PLUS
;
816 if (CompareGuid (&TempGuid
, &Guid
[3])) {
830 Ptr
= Ptr
- sizeof (UART_DEVICE_PATH
) - sizeof (ACPI_HID_DEVICE_PATH
);
831 Acpi
= (ACPI_HID_DEVICE_PATH
*) Ptr
;
832 Match
= EISA_PNP_ID (0x0501);
833 if (CompareMem (&Acpi
->HID
, &Match
, sizeof (UINT32
)) == 0) {
834 CopyMem (Com
, &Acpi
->UID
, sizeof (UINT32
));