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