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