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