]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
IntelFrameworkModulePkg BdsDxe: Remove redundant functions
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / ConsoleOption.c
1 /** @file
2 handles console redirection from boot manager
3
4 Copyright (c) 2004 - 2018, 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
9
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.
12
13 **/
14
15 #include "BootMaint.h"
16
17 UART_FLOW_CONTROL_DEVICE_PATH mFlowControlDevicePath =
18 {
19 {
20 MESSAGING_DEVICE_PATH,
21 MSG_VENDOR_DP,
22 {
23 (UINT8)(sizeof(UART_FLOW_CONTROL_DEVICE_PATH)),
24 (UINT8)((sizeof(UART_FLOW_CONTROL_DEVICE_PATH)) >> 8)
25 }
26 },
27 DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL,
28 UART_FLOW_CONTROL_HARDWARE
29 };
30
31 /**
32 Check the device path node whether it's the Flow Control node or not.
33
34 @param[in] FlowControl The device path node to be checked.
35
36 @retval TRUE It's the Flow Control node.
37 @retval FALSE It's not.
38
39 **/
40 BOOLEAN
41 IsUartFlowControlNode (
42 IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
43 )
44 {
45 return (BOOLEAN) (
46 (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
47 (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
48 (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
49 );
50 }
51
52 /**
53 Check whether the device path node is ISA Serial Node.
54
55 @param Acpi Device path node to be checked
56
57 @retval TRUE It's ISA Serial Node.
58 @retval FALSE It's NOT ISA Serial Node.
59
60 **/
61 BOOLEAN
62 IsIsaSerialNode (
63 IN ACPI_HID_DEVICE_PATH *Acpi
64 )
65 {
66 return (BOOLEAN) (
67 (DevicePathType (Acpi) == ACPI_DEVICE_PATH) &&
68 (DevicePathSubType (Acpi) == ACPI_DP) &&
69 (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501))
70 );
71 }
72
73 /**
74 Update Com Ports attributes from DevicePath
75
76 @param DevicePath DevicePath that contains Com ports
77
78 @retval EFI_SUCCESS The update is successful.
79
80 **/
81 EFI_STATUS
82 UpdateComAttributeFromVariable (
83 EFI_DEVICE_PATH_PROTOCOL *DevicePath
84 );
85
86 /**
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.
90
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.
94
95 @return EFI_SUCCESS The function completes successfully.
96
97 **/
98 EFI_STATUS
99 ChangeTerminalDevicePath (
100 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
101 IN BOOLEAN ChangeTerminal
102 )
103 {
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;
109 UINTN Com;
110 BM_TERMINAL_CONTEXT *NewTerminalContext;
111 BM_MENU_ENTRY *NewMenuEntry;
112 UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
113
114 Node = *DevicePath;
115 Node = NextDevicePathNode (Node);
116 Com = 0;
117 while (!IsDevicePathEnd (Node)) {
118 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
119 if (IsIsaSerialNode (Acpi)) {
120 CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
121 }
122
123 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
124
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;
128 CopyMem (
129 &Uart->BaudRate,
130 &NewTerminalContext->BaudRate,
131 sizeof (UINT64)
132 );
133
134 CopyMem (
135 &Uart->DataBits,
136 &NewTerminalContext->DataBits,
137 sizeof (UINT8)
138 );
139
140 CopyMem (
141 &Uart->Parity,
142 &NewTerminalContext->Parity,
143 sizeof (UINT8)
144 );
145
146 CopyMem (
147 &Uart->StopBits,
148 &NewTerminalContext->StopBits,
149 sizeof (UINT8)
150 );
151
152 FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node);
153 if (IsUartFlowControlNode (FlowControlNode)) {
154 FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl;
155 } else {
156 //
157 // Append the Flow control device node when user enable flow control.
158 //
159 if (NewTerminalContext->FlowControl != 0) {
160 mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl;
161 *DevicePath = AppendDevicePathNode (
162 *DevicePath,
163 (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath)
164 );
165 }
166 }
167
168 //
169 // Change the device path in the ComPort
170 //
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;
177 CopyMem (
178 &Uart1->BaudRate,
179 &NewTerminalContext->BaudRate,
180 sizeof (UINT64)
181 );
182
183 CopyMem (
184 &Uart1->DataBits,
185 &NewTerminalContext->DataBits,
186 sizeof (UINT8)
187 );
188
189 CopyMem (
190 &Uart1->Parity,
191 &NewTerminalContext->Parity,
192 sizeof (UINT8)
193 );
194
195 CopyMem (
196 &Uart1->StopBits,
197 &NewTerminalContext->StopBits,
198 sizeof (UINT8)
199 );
200 break;
201 }
202 //
203 // end if
204 //
205 Node1 = NextDevicePathNode (Node1);
206 }
207 //
208 // end while
209 //
210 break;
211 }
212 }
213
214 Node = NextDevicePathNode (Node);
215 }
216
217 return EFI_SUCCESS;
218
219 }
220
221
222
223 /**
224 Retrieve ACPI UID of UART from device path
225
226 @param Handle The handle for the UART device.
227 @param AcpiUid The ACPI UID on output.
228
229 @retval TRUE Find valid UID from device path
230 @retval FALSE Can't find
231
232 **/
233 BOOLEAN
234 RetrieveUartUid (
235 IN EFI_HANDLE Handle,
236 IN OUT UINT32 *AcpiUid
237 )
238 {
239 EFI_STATUS Status;
240 ACPI_HID_DEVICE_PATH *Acpi;
241 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
242
243 Status = gBS->HandleProtocol (
244 Handle,
245 &gEfiDevicePathProtocolGuid,
246 (VOID **) &DevicePath
247 );
248 if (EFI_ERROR (Status)) {
249 return FALSE;
250 }
251
252 Acpi = NULL;
253 for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
254 if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) {
255 break;
256 }
257 //
258 // Acpi points to the node before the Uart node
259 //
260 Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
261 }
262
263 if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
264 if (AcpiUid != NULL) {
265 CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32));
266 }
267 return TRUE;
268 } else {
269 return FALSE;
270 }
271 }
272
273 /**
274 Sort Uart handles array with Acpi->UID from low to high.
275
276 @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer
277 @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count
278 **/
279 VOID
280 SortedUartHandle (
281 IN EFI_HANDLE *Handles,
282 IN UINTN NoHandles
283 )
284 {
285 UINTN Index1;
286 UINTN Index2;
287 UINTN Position;
288 UINT32 AcpiUid1;
289 UINT32 AcpiUid2;
290 UINT32 TempAcpiUid;
291 EFI_HANDLE TempHandle;
292
293 for (Index1 = 0; Index1 < NoHandles-1; Index1++) {
294 if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {
295 continue;
296 }
297 TempHandle = Handles[Index1];
298 Position = Index1;
299 TempAcpiUid = AcpiUid1;
300
301 for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {
302 if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {
303 continue;
304 }
305 if (AcpiUid2 < TempAcpiUid) {
306 TempAcpiUid = AcpiUid2;
307 TempHandle = Handles[Index2];
308 Position = Index2;
309 }
310 }
311 Handles[Position] = Handles[Index1];
312 Handles[Index1] = TempHandle;
313 }
314 }
315
316 /**
317 Test whether DevicePath is a valid Terminal
318
319
320 @param DevicePath DevicePath to be checked
321 @param Termi If DevicePath is valid Terminal, terminal type is returned.
322 @param Com If DevicePath is valid Terminal, Com Port type is returned.
323
324 @retval TRUE If DevicePath point to a Terminal.
325 @retval FALSE If DevicePath does not point to a Terminal.
326
327 **/
328 BOOLEAN
329 IsTerminalDevicePath (
330 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
331 OUT TYPE_OF_TERMINAL *Termi,
332 OUT UINTN *Com
333 );
334
335 /**
336 Build a list containing all serial devices.
337
338
339 @retval EFI_SUCCESS The function complete successfully.
340 @retval EFI_UNSUPPORTED No serial ports present.
341
342 **/
343 EFI_STATUS
344 LocateSerialIo (
345 VOID
346 )
347 {
348 UINTN Index;
349 UINTN Index2;
350 UINTN NoHandles;
351 EFI_HANDLE *Handles;
352 EFI_STATUS Status;
353 ACPI_HID_DEVICE_PATH *Acpi;
354 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
355 EFI_SERIAL_IO_PROTOCOL *SerialIo;
356 EFI_DEVICE_PATH_PROTOCOL *Node;
357 EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
358 EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
359 EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
360 BM_MENU_ENTRY *NewMenuEntry;
361 BM_TERMINAL_CONTEXT *NewTerminalContext;
362 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
363 VENDOR_DEVICE_PATH Vendor;
364 UINT32 FlowControl;
365 //
366 // Get all handles that have SerialIo protocol installed
367 //
368 InitializeListHead (&TerminalMenu.Head);
369 TerminalMenu.MenuNumber = 0;
370 Status = gBS->LocateHandleBuffer (
371 ByProtocol,
372 &gEfiSerialIoProtocolGuid,
373 NULL,
374 &NoHandles,
375 &Handles
376 );
377 if (EFI_ERROR (Status)) {
378 //
379 // No serial ports present
380 //
381 return EFI_UNSUPPORTED;
382 }
383
384 //
385 // Sort Uart handles array with Acpi->UID from low to high
386 // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
387 //
388 SortedUartHandle (Handles, NoHandles);
389
390 for (Index = 0; Index < NoHandles; Index++) {
391 //
392 // Check to see whether the handle has DevicePath Protocol installed
393 //
394 gBS->HandleProtocol (
395 Handles[Index],
396 &gEfiDevicePathProtocolGuid,
397 (VOID **) &DevicePath
398 );
399
400 Acpi = NULL;
401 for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
402 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
403 break;
404 }
405 //
406 // Acpi points to the node before Uart node
407 //
408 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
409 }
410
411 if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
412 NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
413 if (NewMenuEntry == NULL) {
414 FreePool (Handles);
415 return EFI_OUT_OF_RESOURCES;
416 }
417
418 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
419 CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
420 NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath);
421 //
422 // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
423 // coz' the misc data for each platform is not correct, actually it's the device path stored in
424 // datahub which is not completed, so a searching for end of device path will enter a
425 // dead-loop.
426 //
427 NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
428 if (NULL == NewMenuEntry->DisplayString) {
429 NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);
430 }
431
432 NewMenuEntry->HelpString = NULL;
433
434 gBS->HandleProtocol (
435 Handles[Index],
436 &gEfiSerialIoProtocolGuid,
437 (VOID **) &SerialIo
438 );
439
440 CopyMem (
441 &NewTerminalContext->BaudRate,
442 &SerialIo->Mode->BaudRate,
443 sizeof (UINT64)
444 );
445
446 CopyMem (
447 &NewTerminalContext->DataBits,
448 &SerialIo->Mode->DataBits,
449 sizeof (UINT8)
450 );
451
452 CopyMem (
453 &NewTerminalContext->Parity,
454 &SerialIo->Mode->Parity,
455 sizeof (UINT8)
456 );
457
458 CopyMem (
459 &NewTerminalContext->StopBits,
460 &SerialIo->Mode->StopBits,
461 sizeof (UINT8)
462 );
463
464 NewTerminalContext->FlowControl = 0;
465 SerialIo->GetControl(SerialIo, &FlowControl);
466 if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) {
467 NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE;
468 }
469
470 InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
471 TerminalMenu.MenuNumber++;
472 }
473 }
474 if (Handles != NULL) {
475 FreePool (Handles);
476 }
477
478 //
479 // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
480 //
481 OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
482 InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
483 ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
484 if (OutDevicePath != NULL) {
485 UpdateComAttributeFromVariable (OutDevicePath);
486 }
487
488 if (InpDevicePath != NULL) {
489 UpdateComAttributeFromVariable (InpDevicePath);
490 }
491
492 if (ErrDevicePath != NULL) {
493 UpdateComAttributeFromVariable (ErrDevicePath);
494 }
495
496 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
497 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
498 if (NULL == NewMenuEntry) {
499 return EFI_NOT_FOUND;
500 }
501
502 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
503
504 NewTerminalContext->TerminalType = 0;
505 NewTerminalContext->IsConIn = FALSE;
506 NewTerminalContext->IsConOut = FALSE;
507 NewTerminalContext->IsStdErr = FALSE;
508
509 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
510 Vendor.Header.SubType = MSG_VENDOR_DP;
511
512 for (Index2 = 0; Index2 < 4; Index2++) {
513 CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID));
514 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
515 NewDevicePath = AppendDevicePathNode (
516 NewTerminalContext->DevicePath,
517 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
518 );
519 if (NewMenuEntry->HelpString != NULL) {
520 FreePool (NewMenuEntry->HelpString);
521 }
522 //
523 // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
524 // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
525 //
526 NewMenuEntry->HelpString = NULL;
527
528 if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
529 NewTerminalContext->IsConOut = TRUE;
530 NewTerminalContext->TerminalType = (UINT8) Index2;
531 }
532
533 if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
534 NewTerminalContext->IsConIn = TRUE;
535 NewTerminalContext->TerminalType = (UINT8) Index2;
536 }
537
538 if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {
539 NewTerminalContext->IsStdErr = TRUE;
540 NewTerminalContext->TerminalType = (UINT8) Index2;
541 }
542 }
543 }
544
545 return EFI_SUCCESS;
546 }
547
548 /**
549 Update Com Ports attributes from DevicePath
550
551 @param DevicePath DevicePath that contains Com ports
552
553 @retval EFI_SUCCESS The update is successful.
554 @retval EFI_NOT_FOUND Can not find specific menu entry
555 **/
556 EFI_STATUS
557 UpdateComAttributeFromVariable (
558 EFI_DEVICE_PATH_PROTOCOL *DevicePath
559 )
560 {
561 EFI_DEVICE_PATH_PROTOCOL *Node;
562 EFI_DEVICE_PATH_PROTOCOL *SerialNode;
563 ACPI_HID_DEVICE_PATH *Acpi;
564 UART_DEVICE_PATH *Uart;
565 UART_DEVICE_PATH *Uart1;
566 UINTN TerminalNumber;
567 BM_MENU_ENTRY *NewMenuEntry;
568 BM_TERMINAL_CONTEXT *NewTerminalContext;
569 UINTN Index;
570 UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
571 BOOLEAN HasFlowControlNode;
572
573 HasFlowControlNode = FALSE;
574 Node = DevicePath;
575 Node = NextDevicePathNode (Node);
576 TerminalNumber = 0;
577 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
578 while (!IsDevicePathEnd (Node)) {
579 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
580 if (IsIsaSerialNode (Acpi)) {
581 CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
582 }
583
584 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
585 Uart = (UART_DEVICE_PATH *) Node;
586 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
587 if (NULL == NewMenuEntry) {
588 return EFI_NOT_FOUND;
589 }
590
591 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
592 CopyMem (
593 &NewTerminalContext->BaudRate,
594 &Uart->BaudRate,
595 sizeof (UINT64)
596 );
597
598 CopyMem (
599 &NewTerminalContext->DataBits,
600 &Uart->DataBits,
601 sizeof (UINT8)
602 );
603
604 CopyMem (
605 &NewTerminalContext->Parity,
606 &Uart->Parity,
607 sizeof (UINT8)
608 );
609
610 CopyMem (
611 &NewTerminalContext->StopBits,
612 &Uart->StopBits,
613 sizeof (UINT8)
614 );
615
616 FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node);
617 if (IsUartFlowControlNode (FlowControlNode)) {
618 HasFlowControlNode = TRUE;
619 NewTerminalContext->FlowControl = (UINT8) ReadUnaligned32 (&FlowControlNode->FlowControlMap);
620 } else if (NewTerminalContext->FlowControl != 0) {
621 //
622 // No Flow Control device path node, assumption no Flow control
623 //
624 NewTerminalContext->FlowControl = 0;
625 }
626
627 SerialNode = NewTerminalContext->DevicePath;
628 SerialNode = NextDevicePathNode (SerialNode);
629 while (!IsDevicePathEnd (SerialNode)) {
630 if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
631 //
632 // Update following device paths according to
633 // previous acquired uart attributes
634 //
635 Uart1 = (UART_DEVICE_PATH *) SerialNode;
636 CopyMem (
637 &Uart1->BaudRate,
638 &NewTerminalContext->BaudRate,
639 sizeof (UINT64)
640 );
641
642 CopyMem (
643 &Uart1->DataBits,
644 &NewTerminalContext->DataBits,
645 sizeof (UINT8)
646 );
647 CopyMem (
648 &Uart1->Parity,
649 &NewTerminalContext->Parity,
650 sizeof (UINT8)
651 );
652 CopyMem (
653 &Uart1->StopBits,
654 &NewTerminalContext->StopBits,
655 sizeof (UINT8)
656 );
657
658 FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (SerialNode);
659 if (IsUartFlowControlNode (FlowControlNode)) {
660 FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl;
661 } else {
662 if (HasFlowControlNode) {
663 mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl;
664 NewTerminalContext->DevicePath = AppendDevicePathNode (
665 NewTerminalContext->DevicePath,
666 (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath)
667 );
668 }
669 }
670 break;
671 }
672
673 SerialNode = NextDevicePathNode (SerialNode);
674 }
675 //
676 // end while
677 //
678 }
679
680 Node = NextDevicePathNode (Node);
681 }
682 //
683 // end while
684 //
685 }
686
687 return EFI_SUCCESS;
688 }
689
690 /**
691 Build up Console Menu based on types passed in. The type can
692 be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
693 and BM_CONSOLE_ERR_CONTEXT_SELECT.
694
695 @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT
696 and BM_CONSOLE_ERR_CONTEXT_SELECT.
697
698 @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.
699 @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev",
700 "ConInDev" or "ConErrDev" doesn't exists.
701 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.
702 @retval EFI_SUCCESS Function completes successfully.
703
704 **/
705 EFI_STATUS
706 GetConsoleMenu (
707 IN UINTN ConsoleMenuType
708 )
709 {
710 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
711 EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;
712 EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;
713 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
714 UINTN Size;
715 UINTN AllCount;
716 UINTN Index;
717 UINTN Index2;
718 BM_MENU_ENTRY *NewMenuEntry;
719 BM_CONSOLE_CONTEXT *NewConsoleContext;
720 TYPE_OF_TERMINAL Terminal;
721 UINTN Com;
722 BM_MENU_OPTION *ConsoleMenu;
723
724 DevicePath = NULL;
725 AllDevicePath = NULL;
726 AllCount = 0;
727 switch (ConsoleMenuType) {
728 case BM_CONSOLE_IN_CONTEXT_SELECT:
729 ConsoleMenu = &ConsoleInpMenu;
730 DevicePath = EfiLibGetVariable (
731 L"ConIn",
732 &gEfiGlobalVariableGuid
733 );
734
735 AllDevicePath = EfiLibGetVariable (
736 L"ConInDev",
737 &gEfiGlobalVariableGuid
738 );
739 break;
740
741 case BM_CONSOLE_OUT_CONTEXT_SELECT:
742 ConsoleMenu = &ConsoleOutMenu;
743 DevicePath = EfiLibGetVariable (
744 L"ConOut",
745 &gEfiGlobalVariableGuid
746 );
747
748 AllDevicePath = EfiLibGetVariable (
749 L"ConOutDev",
750 &gEfiGlobalVariableGuid
751 );
752 break;
753
754 case BM_CONSOLE_ERR_CONTEXT_SELECT:
755 ConsoleMenu = &ConsoleErrMenu;
756 DevicePath = EfiLibGetVariable (
757 L"ErrOut",
758 &gEfiGlobalVariableGuid
759 );
760
761 AllDevicePath = EfiLibGetVariable (
762 L"ErrOutDev",
763 &gEfiGlobalVariableGuid
764 );
765 break;
766
767 default:
768 return EFI_UNSUPPORTED;
769 }
770
771 if (NULL == AllDevicePath) {
772 return EFI_NOT_FOUND;
773 }
774
775 InitializeListHead (&ConsoleMenu->Head);
776
777 AllCount = EfiDevicePathInstanceCount (AllDevicePath);
778 ConsoleMenu->MenuNumber = 0;
779 //
780 // Following is menu building up for Console Devices selected.
781 //
782 MultiDevicePath = AllDevicePath;
783 Index2 = 0;
784 for (Index = 0; Index < AllCount; Index++) {
785 DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);
786
787 NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);
788 if (NULL == NewMenuEntry) {
789 return EFI_OUT_OF_RESOURCES;
790 }
791
792 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
793 NewMenuEntry->OptionNumber = Index2;
794
795 NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst);
796 ASSERT (NewConsoleContext->DevicePath != NULL);
797 NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
798 if (NULL == NewMenuEntry->DisplayString) {
799 NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);
800 }
801
802 NewConsoleContext->IsTerminal = IsTerminalDevicePath (
803 NewConsoleContext->DevicePath,
804 &Terminal,
805 &Com
806 );
807
808 NewConsoleContext->IsActive = BdsLibMatchDevicePaths (
809 DevicePath,
810 NewConsoleContext->DevicePath
811 );
812
813 if (NewConsoleContext->IsTerminal) {
814 BOpt_DestroyMenuEntry (NewMenuEntry);
815 } else {
816 Index2++;
817 ConsoleMenu->MenuNumber++;
818 InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
819 }
820 }
821
822 return EFI_SUCCESS;
823 }
824
825 /**
826 Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
827
828 @retval EFI_SUCCESS The function always complete successfully.
829
830 **/
831 EFI_STATUS
832 GetAllConsoles (
833 VOID
834 )
835 {
836 GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
837 GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
838 GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
839 return EFI_SUCCESS;
840 }
841
842 /**
843 Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
844
845 @retval EFI_SUCCESS The function always complete successfully.
846 **/
847 EFI_STATUS
848 FreeAllConsoles (
849 VOID
850 )
851 {
852 BOpt_FreeMenu (&ConsoleOutMenu);
853 BOpt_FreeMenu (&ConsoleInpMenu);
854 BOpt_FreeMenu (&ConsoleErrMenu);
855 BOpt_FreeMenu (&TerminalMenu);
856 return EFI_SUCCESS;
857 }
858
859 /**
860 Test whether DevicePath is a valid Terminal
861
862
863 @param DevicePath DevicePath to be checked
864 @param Termi If DevicePath is valid Terminal, terminal type is returned.
865 @param Com If DevicePath is valid Terminal, Com Port type is returned.
866
867 @retval TRUE If DevicePath point to a Terminal.
868 @retval FALSE If DevicePath does not point to a Terminal.
869
870 **/
871 BOOLEAN
872 IsTerminalDevicePath (
873 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
874 OUT TYPE_OF_TERMINAL *Termi,
875 OUT UINTN *Com
876 )
877 {
878 BOOLEAN IsTerminal;
879 EFI_DEVICE_PATH_PROTOCOL *Node;
880 VENDOR_DEVICE_PATH *Vendor;
881 UART_DEVICE_PATH *Uart;
882 ACPI_HID_DEVICE_PATH *Acpi;
883
884 IsTerminal = FALSE;
885
886 Uart = NULL;
887 Vendor = NULL;
888 Acpi = NULL;
889 for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
890 //
891 // Vendor points to the node before the End node
892 //
893 Vendor = (VENDOR_DEVICE_PATH *) Node;
894
895 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
896 Uart = (UART_DEVICE_PATH *) Node;
897 }
898
899 if (Uart == NULL) {
900 //
901 // Acpi points to the node before the UART node
902 //
903 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
904 }
905 }
906
907 if (Vendor == NULL ||
908 DevicePathType (Vendor) != MESSAGING_DEVICE_PATH ||
909 DevicePathSubType (Vendor) != MSG_VENDOR_DP ||
910 Uart == NULL) {
911 return FALSE;
912 }
913
914 //
915 // There are four kinds of Terminal types
916 // check to see whether this devicepath
917 // is one of that type
918 //
919 if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) {
920 *Termi = TerminalTypePcAnsi;
921 IsTerminal = TRUE;
922 } else {
923 if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) {
924 *Termi = TerminalTypeVt100;
925 IsTerminal = TRUE;
926 } else {
927 if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) {
928 *Termi = TerminalTypeVt100Plus;
929 IsTerminal = TRUE;
930 } else {
931 if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) {
932 *Termi = TerminalTypeVtUtf8;
933 IsTerminal = TRUE;
934 } else {
935 IsTerminal = FALSE;
936 }
937 }
938 }
939 }
940
941 if (!IsTerminal) {
942 return FALSE;
943 }
944
945 if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) {
946 CopyMem (Com, &Acpi->UID, sizeof (UINT32));
947 } else {
948 return FALSE;
949 }
950
951 return TRUE;
952 }
953
954 /**
955 Get mode number according to column and row
956
957 @param CallbackData The BMM context data.
958 **/
959 VOID
960 GetConsoleOutMode (
961 IN BMM_CALLBACK_DATA *CallbackData
962 )
963 {
964 UINTN Col;
965 UINTN Row;
966 UINTN CurrentCol;
967 UINTN CurrentRow;
968 UINTN Mode;
969 UINTN MaxMode;
970 EFI_STATUS Status;
971 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
972
973 ConOut = gST->ConOut;
974 MaxMode = (UINTN) (ConOut->Mode->MaxMode);
975
976 CurrentCol = PcdGet32 (PcdSetupConOutColumn);
977 CurrentRow = PcdGet32 (PcdSetupConOutRow);
978 for (Mode = 0; Mode < MaxMode; Mode++) {
979 Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
980 if (!EFI_ERROR(Status)) {
981 if (CurrentCol == Col && CurrentRow == Row) {
982 CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;
983 break;
984 }
985 }
986 }
987 }
988
989 /**
990
991 Initialize console input device check box to ConsoleInCheck[MAX_MENU_NUMBER]
992 in BMM_FAKE_NV_DATA structure.
993
994 @param CallbackData The BMM context data.
995
996 **/
997 VOID
998 GetConsoleInCheck (
999 IN BMM_CALLBACK_DATA *CallbackData
1000 )
1001 {
1002 UINT16 Index;
1003 BM_MENU_ENTRY *NewMenuEntry;
1004 UINT8 *ConInCheck;
1005 BM_CONSOLE_CONTEXT *NewConsoleContext;
1006
1007 ASSERT (CallbackData != NULL);
1008
1009 ConInCheck = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
1010 for (Index = 0; ((Index < ConsoleInpMenu.MenuNumber) && \
1011 (Index < MAX_MENU_NUMBER)) ; Index++) {
1012 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
1013 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
1014 ConInCheck[Index] = NewConsoleContext->IsActive;
1015 }
1016 }
1017
1018 /**
1019
1020 Initialize console output device check box to ConsoleOutCheck[MAX_MENU_NUMBER]
1021 in BMM_FAKE_NV_DATA structure.
1022
1023 @param CallbackData The BMM context data.
1024
1025 **/
1026 VOID
1027 GetConsoleOutCheck (
1028 IN BMM_CALLBACK_DATA *CallbackData
1029 )
1030 {
1031 UINT16 Index;
1032 BM_MENU_ENTRY *NewMenuEntry;
1033 UINT8 *ConOutCheck;
1034 BM_CONSOLE_CONTEXT *NewConsoleContext;
1035
1036 ASSERT (CallbackData != NULL);
1037 ConOutCheck = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
1038 for (Index = 0; ((Index < ConsoleOutMenu.MenuNumber) && \
1039 (Index < MAX_MENU_NUMBER)) ; Index++) {
1040 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
1041 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
1042 ConOutCheck[Index] = NewConsoleContext->IsActive;
1043 }
1044 }
1045
1046 /**
1047
1048 Initialize standard error output device check box to ConsoleErrCheck[MAX_MENU_NUMBER]
1049 in BMM_FAKE_NV_DATA structure.
1050
1051 @param CallbackData The BMM context data.
1052
1053 **/
1054 VOID
1055 GetConsoleErrCheck (
1056 IN BMM_CALLBACK_DATA *CallbackData
1057 )
1058 {
1059 UINT16 Index;
1060 BM_MENU_ENTRY *NewMenuEntry;
1061 UINT8 *ConErrCheck;
1062 BM_CONSOLE_CONTEXT *NewConsoleContext;
1063
1064 ASSERT (CallbackData != NULL);
1065 ConErrCheck = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
1066 for (Index = 0; ((Index < ConsoleErrMenu.MenuNumber) && \
1067 (Index < MAX_MENU_NUMBER)) ; Index++) {
1068 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
1069 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
1070 ConErrCheck[Index] = NewConsoleContext->IsActive;
1071 }
1072 }
1073
1074 /**
1075
1076 Initialize terminal attributes (baudrate, data rate, stop bits, parity and terminal type)
1077 to BMM_FAKE_NV_DATA structure.
1078
1079 @param CallbackData The BMM context data.
1080
1081 **/
1082 VOID
1083 GetTerminalAttribute (
1084 IN BMM_CALLBACK_DATA *CallbackData
1085 )
1086 {
1087 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
1088 BM_MENU_ENTRY *NewMenuEntry;
1089 BM_TERMINAL_CONTEXT *NewTerminalContext;
1090 UINT16 TerminalIndex;
1091 UINT8 AttributeIndex;
1092
1093 ASSERT (CallbackData != NULL);
1094
1095 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
1096 for (TerminalIndex = 0; ((TerminalIndex < TerminalMenu.MenuNumber) && \
1097 (TerminalIndex < MAX_MENU_NUMBER)); TerminalIndex++) {
1098 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalIndex);
1099 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
1100 for (AttributeIndex = 0; AttributeIndex < sizeof (BaudRateList) / sizeof (BaudRateList [0]); AttributeIndex++) {
1101 if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[AttributeIndex].Value)) {
1102 NewTerminalContext->BaudRateIndex = AttributeIndex;
1103 break;
1104 }
1105 }
1106 for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (DataBitsList); AttributeIndex++) {
1107 if (NewTerminalContext->DataBits == (UINT64) (DataBitsList[AttributeIndex].Value)) {
1108 NewTerminalContext->DataBitsIndex = AttributeIndex;
1109 break;
1110 }
1111 }
1112
1113 for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (ParityList); AttributeIndex++) {
1114 if (NewTerminalContext->Parity == (UINT64) (ParityList[AttributeIndex].Value)) {
1115 NewTerminalContext->ParityIndex = AttributeIndex;
1116 break;
1117 }
1118 }
1119
1120 for (AttributeIndex = 0; AttributeIndex < ARRAY_SIZE (StopBitsList); AttributeIndex++) {
1121 if (NewTerminalContext->StopBits == (UINT64) (StopBitsList[AttributeIndex].Value)) {
1122 NewTerminalContext->StopBitsIndex = AttributeIndex;
1123 break;
1124 }
1125 }
1126 CurrentFakeNVMap->COMBaudRate[TerminalIndex] = NewTerminalContext->BaudRateIndex;
1127 CurrentFakeNVMap->COMDataRate[TerminalIndex] = NewTerminalContext->DataBitsIndex;
1128 CurrentFakeNVMap->COMStopBits[TerminalIndex] = NewTerminalContext->StopBitsIndex;
1129 CurrentFakeNVMap->COMParity[TerminalIndex] = NewTerminalContext->ParityIndex;
1130 CurrentFakeNVMap->COMTerminalType[TerminalIndex] = NewTerminalContext->TerminalType;
1131 CurrentFakeNVMap->COMFlowControl[TerminalIndex] = NewTerminalContext->FlowControl;
1132 }
1133 }
1134