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