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