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