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