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