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