]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BootMaint / ConsoleOption.c
1 /*++
2 Copyright (c) 2004 - 2008, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module Name:
12
13 consoleoption.c
14
15 Abstract:
16
17 handles console redirection from boot manager
18
19
20 Revision History
21
22 --*/
23
24 #include "BootMaint.h"
25
26 EFI_DEVICE_PATH_PROTOCOL *
27 DevicePathInstanceDup (
28 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
29 );
30
31 EFI_STATUS
32 UpdateComAttributeFromVariable (
33 EFI_DEVICE_PATH_PROTOCOL *DevicePath
34 );
35
36 EFI_STATUS
37 ChangeTerminalDevicePath (
38 EFI_DEVICE_PATH_PROTOCOL *DevicePath,
39 BOOLEAN ChangeTerminal
40 )
41 {
42 EFI_DEVICE_PATH_PROTOCOL *Node;
43 EFI_DEVICE_PATH_PROTOCOL *Node1;
44 ACPI_HID_DEVICE_PATH *Acpi;
45 UART_DEVICE_PATH *Uart;
46 UART_DEVICE_PATH *Uart1;
47 UINTN Com;
48 UINT32 Match;
49 BM_TERMINAL_CONTEXT *NewTerminalContext;
50 BM_MENU_ENTRY *NewMenuEntry;
51
52 Match = EISA_PNP_ID (0x0501);
53 Node = DevicePath;
54 Node = NextDevicePathNode (Node);
55 Com = 0;
56 while (!IsDevicePathEnd (Node)) {
57 if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
58 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
59 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
60 CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
61 }
62 }
63
64 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
65 if (NULL == NewMenuEntry) {
66 return EFI_NOT_FOUND;
67 }
68
69 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
70 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
71 Uart = (UART_DEVICE_PATH *) Node;
72 CopyMem (
73 &Uart->BaudRate,
74 &NewTerminalContext->BaudRate,
75 sizeof (UINT64)
76 );
77
78 CopyMem (
79 &Uart->DataBits,
80 &NewTerminalContext->DataBits,
81 sizeof (UINT8)
82 );
83
84 CopyMem (
85 &Uart->Parity,
86 &NewTerminalContext->Parity,
87 sizeof (UINT8)
88 );
89
90 CopyMem (
91 &Uart->StopBits,
92 &NewTerminalContext->StopBits,
93 sizeof (UINT8)
94 );
95 //
96 // Change the device path in the ComPort
97 //
98 if (ChangeTerminal) {
99 Node1 = NewTerminalContext->DevicePath;
100 Node1 = NextDevicePathNode (Node1);
101 while (!IsDevicePathEnd (Node1)) {
102 if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {
103 Uart1 = (UART_DEVICE_PATH *) Node1;
104 CopyMem (
105 &Uart1->BaudRate,
106 &NewTerminalContext->BaudRate,
107 sizeof (UINT64)
108 );
109
110 CopyMem (
111 &Uart1->DataBits,
112 &NewTerminalContext->DataBits,
113 sizeof (UINT8)
114 );
115
116 CopyMem (
117 &Uart1->Parity,
118 &NewTerminalContext->Parity,
119 sizeof (UINT8)
120 );
121
122 CopyMem (
123 &Uart1->StopBits,
124 &NewTerminalContext->StopBits,
125 sizeof (UINT8)
126 );
127 break;
128 }
129 //
130 // end if
131 //
132 Node1 = NextDevicePathNode (Node1);
133 }
134 //
135 // end while
136 //
137 break;
138 }
139 }
140
141 Node = NextDevicePathNode (Node);
142 }
143
144 return EFI_SUCCESS;
145
146 }
147
148 VOID
149 ChangeVariableDevicePath (
150 EFI_DEVICE_PATH_PROTOCOL *DevicePath
151 )
152 {
153 EFI_DEVICE_PATH_PROTOCOL *Node;
154 ACPI_HID_DEVICE_PATH *Acpi;
155 UART_DEVICE_PATH *Uart;
156 UINTN Com;
157 UINT32 Match;
158 BM_TERMINAL_CONTEXT *NewTerminalContext;
159 BM_MENU_ENTRY *NewMenuEntry;
160
161 Match = EISA_PNP_ID (0x0501);
162 Node = DevicePath;
163 Node = NextDevicePathNode (Node);
164 Com = 0;
165 while (!IsDevicePathEnd (Node)) {
166 if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
167 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
168 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
169 CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
170 }
171 }
172
173 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
174 NewMenuEntry = BOpt_GetMenuEntry (
175 &TerminalMenu,
176 Com
177 );
178 ASSERT (NewMenuEntry != NULL);
179 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
180 Uart = (UART_DEVICE_PATH *) Node;
181 CopyMem (
182 &Uart->BaudRate,
183 &NewTerminalContext->BaudRate,
184 sizeof (UINT64)
185 );
186
187 CopyMem (
188 &Uart->DataBits,
189 &NewTerminalContext->DataBits,
190 sizeof (UINT8)
191 );
192
193 CopyMem (
194 &Uart->Parity,
195 &NewTerminalContext->Parity,
196 sizeof (UINT8)
197 );
198
199 CopyMem (
200 &Uart->StopBits,
201 &NewTerminalContext->StopBits,
202 sizeof (UINT8)
203 );
204 }
205
206 Node = NextDevicePathNode (Node);
207 }
208
209 return ;
210 }
211
212 BOOLEAN
213 RetrieveUartUid (
214 IN EFI_HANDLE Handle,
215 IN OUT UINT32 *AcpiUid
216 )
217 /*++
218
219 Routine Description:
220 Retrieve ACPI UID of UART from device path
221
222 Arguments:
223 Handles - EFI_SERIAL_IO_PROTOCOL handle
224
225 Returns:
226 TRUE - Find valid UID from device path
227 FALSE - Can't find
228
229 --*/
230 {
231 UINT32 Match;
232 UINT8 *Ptr;
233 ACPI_HID_DEVICE_PATH *Acpi;
234 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
235
236 gBS->HandleProtocol (
237 Handle,
238 &gEfiDevicePathProtocolGuid,
239 (VOID **) &DevicePath
240 );
241 Ptr = (UINT8 *) DevicePath;
242
243 while (*Ptr != END_DEVICE_PATH_TYPE) {
244 Ptr++;
245 }
246
247 Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
248 Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
249 Match = EISA_PNP_ID (0x0501);
250
251 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
252 if (AcpiUid != NULL) {
253 *AcpiUid = Acpi->UID;
254 }
255 return TRUE;
256 } else {
257 return FALSE;
258 }
259 }
260
261 VOID
262 SortedUartHandle (
263 IN EFI_HANDLE *Handles,
264 IN UINTN NoHandles
265 )
266 /*++
267
268 Routine Description:
269 Sort Uart handles array with Acpi->UID from low to high
270
271 Arguments:
272 Handles - EFI_SERIAL_IO_PROTOCOL handle buffer
273 NoHandles - EFI_SERIAL_IO_PROTOCOL handle count
274
275 Returns:
276 None
277
278 --*/
279 {
280 UINTN Index1;
281 UINTN Index2;
282 UINTN Position;
283 UINT32 AcpiUid1;
284 UINT32 AcpiUid2;
285 UINT32 TempAcpiUid;
286 EFI_HANDLE TempHandle;
287
288 for (Index1 = 0; Index1 < NoHandles-1; Index1++) {
289 if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {
290 continue;
291 }
292 TempHandle = Handles[Index1];
293 Position = Index1;
294 TempAcpiUid = AcpiUid1;
295
296 for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {
297 if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {
298 continue;
299 }
300 if (AcpiUid2 < TempAcpiUid) {
301 TempAcpiUid = AcpiUid2;
302 TempHandle = Handles[Index2];
303 Position = Index2;
304 }
305 }
306 Handles[Position] = Handles[Index1];
307 Handles[Index1] = TempHandle;
308 }
309 }
310
311 BOOLEAN
312 IsTerminalDevicePath (
313 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
314 OUT TYPE_OF_TERMINAL *Termi,
315 OUT UINTN *Com
316 );
317
318 EFI_STATUS
319 LocateSerialIo (
320 VOID
321 )
322 /*++
323
324 Routine Description:
325 Build a list containing all serial devices
326
327 Arguments:
328
329 Returns:
330
331 --*/
332 {
333 UINT8 *Ptr;
334 UINTN Index;
335 UINTN Index2;
336 UINTN NoHandles;
337 EFI_HANDLE *Handles;
338 EFI_STATUS Status;
339 ACPI_HID_DEVICE_PATH *Acpi;
340 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
341 UINT32 Match;
342 EFI_SERIAL_IO_PROTOCOL *SerialIo;
343 EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
344 EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
345 EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
346 BM_MENU_ENTRY *NewMenuEntry;
347 BM_TERMINAL_CONTEXT *NewTerminalContext;
348 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
349 VENDOR_DEVICE_PATH Vendor;
350 //
351 // Get all handles that have SerialIo protocol installed
352 //
353 InitializeListHead (&TerminalMenu.Head);
354 TerminalMenu.MenuNumber = 0;
355 Status = gBS->LocateHandleBuffer (
356 ByProtocol,
357 &gEfiSerialIoProtocolGuid,
358 NULL,
359 &NoHandles,
360 &Handles
361 );
362 if (EFI_ERROR (Status)) {
363 //
364 // No serial ports present
365 //
366 return EFI_UNSUPPORTED;
367 }
368
369 //
370 // Sort Uart handles array with Acpi->UID from low to high
371 // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
372 //
373 SortedUartHandle (Handles, NoHandles);
374
375 for (Index = 0; Index < NoHandles; Index++) {
376 //
377 // Check to see whether the handle has DevicePath Protocol installed
378 //
379 gBS->HandleProtocol (
380 Handles[Index],
381 &gEfiDevicePathProtocolGuid,
382 (VOID **) &DevicePath
383 );
384 Ptr = (UINT8 *) DevicePath;
385 while (*Ptr != END_DEVICE_PATH_TYPE) {
386 Ptr++;
387 }
388
389 Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
390 Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
391 Match = EISA_PNP_ID (0x0501);
392
393 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
394 NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
395 if (!NewMenuEntry) {
396 SafeFreePool (Handles);
397 return EFI_OUT_OF_RESOURCES;
398 }
399
400 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
401 CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
402 NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);
403 //
404 // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
405 // coz' the misc data for each platform is not correct, actually it's the device path stored in
406 // datahub which is not completed, so a searching for end of device path will enter a
407 // dead-loop.
408 //
409 NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
410 if (NULL == NewMenuEntry->DisplayString) {
411 NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);
412 }
413
414 NewMenuEntry->HelpString = NULL;
415
416 gBS->HandleProtocol (
417 Handles[Index],
418 &gEfiSerialIoProtocolGuid,
419 (VOID **) &SerialIo
420 );
421
422 CopyMem (
423 &NewTerminalContext->BaudRate,
424 &SerialIo->Mode->BaudRate,
425 sizeof (UINT64)
426 );
427
428 CopyMem (
429 &NewTerminalContext->DataBits,
430 &SerialIo->Mode->DataBits,
431 sizeof (UINT8)
432 );
433
434 CopyMem (
435 &NewTerminalContext->Parity,
436 &SerialIo->Mode->Parity,
437 sizeof (UINT8)
438 );
439
440 CopyMem (
441 &NewTerminalContext->StopBits,
442 &SerialIo->Mode->StopBits,
443 sizeof (UINT8)
444 );
445 InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
446 TerminalMenu.MenuNumber++;
447 }
448 }
449 SafeFreePool (Handles);
450
451 //
452 // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
453 //
454 OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
455 InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
456 ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
457 if (OutDevicePath) {
458 UpdateComAttributeFromVariable (OutDevicePath);
459 }
460
461 if (InpDevicePath) {
462 UpdateComAttributeFromVariable (InpDevicePath);
463 }
464
465 if (ErrDevicePath) {
466 UpdateComAttributeFromVariable (ErrDevicePath);
467 }
468
469 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
470 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
471 if (NULL == NewMenuEntry) {
472 return EFI_NOT_FOUND;
473 }
474
475 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
476
477 NewTerminalContext->TerminalType = 0;
478 NewTerminalContext->IsConIn = FALSE;
479 NewTerminalContext->IsConOut = FALSE;
480 NewTerminalContext->IsStdErr = FALSE;
481
482 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
483 Vendor.Header.SubType = MSG_VENDOR_DP;
484
485 for (Index2 = 0; Index2 < 4; Index2++) {
486 CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));
487 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
488 NewDevicePath = AppendDevicePathNode (
489 NewTerminalContext->DevicePath,
490 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
491 );
492 SafeFreePool (NewMenuEntry->HelpString);
493 //
494 // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
495 // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
496 //
497 NewMenuEntry->HelpString = NULL;
498
499 if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
500 NewTerminalContext->IsConOut = TRUE;
501 NewTerminalContext->TerminalType = (UINT8) Index2;
502 }
503
504 if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
505 NewTerminalContext->IsConIn = TRUE;
506 NewTerminalContext->TerminalType = (UINT8) Index2;
507 }
508
509 if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {
510 NewTerminalContext->IsStdErr = TRUE;
511 NewTerminalContext->TerminalType = (UINT8) Index2;
512 }
513 }
514 }
515
516 return EFI_SUCCESS;
517 }
518
519 EFI_STATUS
520 UpdateComAttributeFromVariable (
521 EFI_DEVICE_PATH_PROTOCOL *DevicePath
522 )
523 /*++
524
525 Routine Description:
526 Update Com Ports attributes from DevicePath
527
528 Arguments:
529 DevicePath - DevicePath that contains Com ports
530
531 Returns:
532
533 --*/
534 {
535 EFI_DEVICE_PATH_PROTOCOL *Node;
536 EFI_DEVICE_PATH_PROTOCOL *SerialNode;
537 ACPI_HID_DEVICE_PATH *Acpi;
538 UART_DEVICE_PATH *Uart;
539 UART_DEVICE_PATH *Uart1;
540 UINT32 Match;
541 UINTN TerminalNumber;
542 BM_MENU_ENTRY *NewMenuEntry;
543 BM_TERMINAL_CONTEXT *NewTerminalContext;
544 UINTN Index;
545
546 Match = EISA_PNP_ID (0x0501);
547 Node = DevicePath;
548 Node = NextDevicePathNode (Node);
549 TerminalNumber = 0;
550 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
551 while (!IsDevicePathEnd (Node)) {
552 if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
553 Acpi = (ACPI_HID_DEVICE_PATH *) Node;
554 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
555 CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
556 }
557 }
558
559 if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
560 Uart = (UART_DEVICE_PATH *) Node;
561 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
562 if (NULL == NewMenuEntry) {
563 return EFI_NOT_FOUND;
564 }
565
566 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
567 CopyMem (
568 &NewTerminalContext->BaudRate,
569 &Uart->BaudRate,
570 sizeof (UINT64)
571 );
572
573 CopyMem (
574 &NewTerminalContext->DataBits,
575 &Uart->DataBits,
576 sizeof (UINT8)
577 );
578
579 CopyMem (
580 &NewTerminalContext->Parity,
581 &Uart->Parity,
582 sizeof (UINT8)
583 );
584
585 CopyMem (
586 &NewTerminalContext->StopBits,
587 &Uart->StopBits,
588 sizeof (UINT8)
589 );
590
591 SerialNode = NewTerminalContext->DevicePath;
592 SerialNode = NextDevicePathNode (SerialNode);
593 while (!IsDevicePathEnd (SerialNode)) {
594 if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
595 //
596 // Update following device paths according to
597 // previous acquired uart attributes
598 //
599 Uart1 = (UART_DEVICE_PATH *) SerialNode;
600 CopyMem (
601 &Uart1->BaudRate,
602 &NewTerminalContext->BaudRate,
603 sizeof (UINT64)
604 );
605
606 CopyMem (
607 &Uart1->DataBits,
608 &NewTerminalContext->DataBits,
609 sizeof (UINT8)
610 );
611 CopyMem (
612 &Uart1->Parity,
613 &NewTerminalContext->Parity,
614 sizeof (UINT8)
615 );
616 CopyMem (
617 &Uart1->StopBits,
618 &NewTerminalContext->StopBits,
619 sizeof (UINT8)
620 );
621
622 break;
623 }
624
625 SerialNode = NextDevicePathNode (SerialNode);
626 }
627 //
628 // end while
629 //
630 }
631
632 Node = NextDevicePathNode (Node);
633 }
634 //
635 // end while
636 //
637 }
638
639 return EFI_SUCCESS;
640 }
641
642 EFI_DEVICE_PATH_PROTOCOL *
643 DevicePathInstanceDup (
644 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
645 )
646 /*++
647
648 Routine Description:
649 Function creates a device path data structure that identically matches the
650 device path passed in.
651
652 Arguments:
653 DevPath - A pointer to a device path data structure.
654
655 Returns:
656
657 The new copy of DevPath is created to identically match the input.
658 Otherwise, NULL is returned.
659
660 --*/
661 {
662 EFI_DEVICE_PATH_PROTOCOL *NewDevPath;
663 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
664 EFI_DEVICE_PATH_PROTOCOL *Temp;
665 UINT8 *Ptr;
666 UINTN Size;
667
668 //
669 // get the size of an instance from the input
670 //
671 Temp = DevPath;
672 DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);
673
674 //
675 // Make a copy and set proper end type
676 //
677 NewDevPath = NULL;
678 if (Size) {
679 NewDevPath = EfiAllocateZeroPool (Size);
680 ASSERT (NewDevPath != NULL);
681 }
682
683 if (NewDevPath) {
684 CopyMem (NewDevPath, DevicePathInst, Size);
685 Ptr = (UINT8 *) NewDevPath;
686 Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
687 Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
688 SetDevicePathEndNode (Temp);
689 }
690
691 return NewDevPath;
692 }
693
694 EFI_STATUS
695 GetConsoleMenu (
696 IN UINTN ConsoleMenuType
697 )
698 {
699 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
700 EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;
701 EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;
702 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
703 UINTN Size;
704 UINTN AllCount;
705 UINTN Index;
706 UINTN Index2;
707 BM_MENU_ENTRY *NewMenuEntry;
708 BM_CONSOLE_CONTEXT *NewConsoleContext;
709 TYPE_OF_TERMINAL Terminal;
710 UINTN Com;
711 BM_MENU_OPTION *ConsoleMenu;
712
713 DevicePath = NULL;
714 AllDevicePath = NULL;
715 AllCount = 0;
716 switch (ConsoleMenuType) {
717 case BM_CONSOLE_IN_CONTEXT_SELECT:
718 ConsoleMenu = &ConsoleInpMenu;
719 DevicePath = EfiLibGetVariable (
720 L"ConIn",
721 &gEfiGlobalVariableGuid
722 );
723
724 AllDevicePath = EfiLibGetVariable (
725 L"ConInDev",
726 &gEfiGlobalVariableGuid
727 );
728 break;
729
730 case BM_CONSOLE_OUT_CONTEXT_SELECT:
731 ConsoleMenu = &ConsoleOutMenu;
732 DevicePath = EfiLibGetVariable (
733 L"ConOut",
734 &gEfiGlobalVariableGuid
735 );
736
737 AllDevicePath = EfiLibGetVariable (
738 L"ConOutDev",
739 &gEfiGlobalVariableGuid
740 );
741 break;
742
743 case BM_CONSOLE_ERR_CONTEXT_SELECT:
744 ConsoleMenu = &ConsoleErrMenu;
745 DevicePath = EfiLibGetVariable (
746 L"ErrOut",
747 &gEfiGlobalVariableGuid
748 );
749
750 AllDevicePath = EfiLibGetVariable (
751 L"ErrOutDev",
752 &gEfiGlobalVariableGuid
753 );
754 break;
755
756 default:
757 return EFI_UNSUPPORTED;
758 }
759
760 if (NULL == AllDevicePath) {
761 return EFI_NOT_FOUND;
762 }
763
764 InitializeListHead (&ConsoleMenu->Head);
765
766 AllCount = EfiDevicePathInstanceCount (AllDevicePath);
767 ConsoleMenu->MenuNumber = 0;
768 //
769 // Following is menu building up for Console Out Devices
770 //
771 MultiDevicePath = AllDevicePath;
772 Index2 = 0;
773 for (Index = 0; Index < AllCount; Index++) {
774 DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);
775
776 NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);
777 if (NULL == NewMenuEntry) {
778 return EFI_OUT_OF_RESOURCES;
779 }
780
781 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
782 NewMenuEntry->OptionNumber = Index2;
783
784 NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);
785 NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
786 if (NULL == NewMenuEntry->DisplayString) {
787 NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);
788 }
789
790 NewConsoleContext->IsTerminal = IsTerminalDevicePath (
791 NewConsoleContext->DevicePath,
792 &Terminal,
793 &Com
794 );
795
796 NewConsoleContext->IsActive = BdsLibMatchDevicePaths (
797 DevicePath,
798 NewConsoleContext->DevicePath
799 );
800
801 if (NewConsoleContext->IsTerminal) {
802 BOpt_DestroyMenuEntry (NewMenuEntry);
803 } else {
804 Index2++;
805 ConsoleMenu->MenuNumber++;
806 InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
807 }
808 }
809
810 return EFI_SUCCESS;
811 }
812
813 EFI_STATUS
814 GetAllConsoles (
815 VOID
816 )
817 /*++
818
819 Routine Description:
820 Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
821
822 Arguments:
823
824 Returns:
825 EFI_SUCCESS
826 Others
827
828 --*/
829 {
830 GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
831 GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
832 GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
833 return EFI_SUCCESS;
834 }
835
836 EFI_STATUS
837 FreeAllConsoles (
838 VOID
839 )
840 /*++
841
842 Routine Description:
843 Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
844
845 Arguments:
846
847 Returns:
848 EFI_SUCCESS
849 Others
850
851 --*/
852 {
853 BOpt_FreeMenu (&ConsoleOutMenu);
854 BOpt_FreeMenu (&ConsoleInpMenu);
855 BOpt_FreeMenu (&ConsoleErrMenu);
856 BOpt_FreeMenu (&TerminalMenu);
857 return EFI_SUCCESS;
858 }
859
860 BOOLEAN
861 IsTerminalDevicePath (
862 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
863 OUT TYPE_OF_TERMINAL *Termi,
864 OUT UINTN *Com
865 )
866 /*++
867
868 Routine Description:
869 Test whether DevicePath is a valid Terminal
870
871 Arguments:
872 DevicePath - DevicePath to be checked
873 Termi - If is terminal, give its type
874 Com - If is Com Port, give its type
875
876 Returns:
877 TRUE - If DevicePath point to a Terminal
878 FALSE
879
880 --*/
881 {
882 UINT8 *Ptr;
883 BOOLEAN IsTerminal;
884 VENDOR_DEVICE_PATH *Vendor;
885 ACPI_HID_DEVICE_PATH *Acpi;
886 UINT32 Match;
887 EFI_GUID TempGuid;
888
889 IsTerminal = FALSE;
890
891 //
892 // Parse the Device Path, should be change later!!!
893 //
894 Ptr = (UINT8 *) DevicePath;
895 while (*Ptr != END_DEVICE_PATH_TYPE) {
896 Ptr++;
897 }
898
899 Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH);
900 Vendor = (VENDOR_DEVICE_PATH *) Ptr;
901
902 //
903 // There are four kinds of Terminal types
904 // check to see whether this devicepath
905 // is one of that type
906 //
907 CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));
908
909 if (CompareGuid (&TempGuid, &Guid[0])) {
910 *Termi = PC_ANSI;
911 IsTerminal = TRUE;
912 } else {
913 if (CompareGuid (&TempGuid, &Guid[1])) {
914 *Termi = VT_100;
915 IsTerminal = TRUE;
916 } else {
917 if (CompareGuid (&TempGuid, &Guid[2])) {
918 *Termi = VT_100_PLUS;
919 IsTerminal = TRUE;
920 } else {
921 if (CompareGuid (&TempGuid, &Guid[3])) {
922 *Termi = VT_UTF8;
923 IsTerminal = TRUE;
924 } else {
925 IsTerminal = FALSE;
926 }
927 }
928 }
929 }
930
931 if (!IsTerminal) {
932 return FALSE;
933 }
934
935 Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
936 Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
937 Match = EISA_PNP_ID (0x0501);
938 if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
939 CopyMem (Com, &Acpi->UID, sizeof (UINT32));
940 } else {
941 return FALSE;
942 }
943
944 return TRUE;
945 }
946
947 VOID
948 GetConsoleOutMode (
949 IN BMM_CALLBACK_DATA *CallbackData
950 )
951 /*++
952
953 Routine Description:
954 Get mode number according to column and row
955
956 Arguments:
957 CallbackData - BMM_CALLBACK_DATA
958
959 Returns:
960 None.
961
962 --*/
963 {
964 UINTN Col;
965 UINTN Row;
966 UINTN CurrentCol;
967 UINTN CurrentRow;
968 UINTN Mode;
969 UINTN MaxMode;
970 EFI_STATUS Status;
971 CONSOLE_OUT_MODE *ModeInfo;
972 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
973
974 ConOut = gST->ConOut;
975 MaxMode = (UINTN) (ConOut->Mode->MaxMode);
976 ModeInfo = EfiLibGetVariable (VarConOutMode, &gEfiGenericPlatformVariableGuid);
977
978 if (ModeInfo != NULL) {
979 CurrentCol = ModeInfo->Column;
980 CurrentRow = ModeInfo->Row;
981 for (Mode = 0; Mode < MaxMode; Mode++) {
982 Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
983 if (!EFI_ERROR(Status)) {
984 if (CurrentCol == Col && CurrentRow == Row) {
985 CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;
986 break;
987 }
988 }
989 }
990 }
991 SafeFreePool (ModeInfo);
992 }