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