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