newline added at end
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / ConsoleOption.c
1 /*++\r
2 Copyright (c) 2006, Intel Corporation                                                         \r
3 All rights reserved. This program and the accompanying materials                          \r
4 are licensed and made available under the terms and conditions of the BSD License         \r
5 which accompanies this distribution.  The full text of the license may be found at        \r
6 http://opensource.org/licenses/bsd-license.php                                            \r
7                                                                                           \r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
10 \r
11 Module Name:\r
12 \r
13     ConsoleOption.c\r
14     \r
15 Abstract:\r
16 \r
17     handles console redirection from boot manager\r
18 \r
19 \r
20 Revision History\r
21 \r
22 --*/\r
23 \r
24 #include "BootMaint.h"\r
25 \r
26 EFI_DEVICE_PATH_PROTOCOL  *\r
27 DevicePathInstanceDup (\r
28   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
29   );\r
30 \r
31 EFI_STATUS\r
32 UpdateComAttributeFromVariable (\r
33   EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
34   );\r
35 \r
36 EFI_STATUS\r
37 ChangeTerminalDevicePath (\r
38   EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
39   BOOLEAN                   ChangeTerminal\r
40   )\r
41 {\r
42   EFI_DEVICE_PATH_PROTOCOL  *Node;\r
43   EFI_DEVICE_PATH_PROTOCOL  *Node1;\r
44   ACPI_HID_DEVICE_PATH      *Acpi;\r
45   UART_DEVICE_PATH          *Uart;\r
46   UART_DEVICE_PATH          *Uart1;\r
47   UINTN                     Com;\r
48   UINT32                    Match;\r
49   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
50   BM_MENU_ENTRY             *NewMenuEntry;\r
51 \r
52   Match = EISA_PNP_ID (0x0501);\r
53   Node  = DevicePath;\r
54   Node  = NextDevicePathNode (Node);\r
55   Com   = 0;\r
56   while (!IsDevicePathEnd (Node)) {\r
57     if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
58       Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
59       if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
60         CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
61       }\r
62     }\r
63 \r
64     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
65     if (NULL == NewMenuEntry) {\r
66       return EFI_NOT_FOUND;\r
67     }\r
68 \r
69     NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
70     if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
71       Uart = (UART_DEVICE_PATH *) Node;\r
72       CopyMem (\r
73         &Uart->BaudRate,\r
74         &NewTerminalContext->BaudRate,\r
75         sizeof (UINT64)\r
76         );\r
77 \r
78       CopyMem (\r
79         &Uart->DataBits,\r
80         &NewTerminalContext->DataBits,\r
81         sizeof (UINT8)\r
82         );\r
83 \r
84       CopyMem (\r
85         &Uart->Parity,\r
86         &NewTerminalContext->Parity,\r
87         sizeof (UINT8)\r
88         );\r
89 \r
90       CopyMem (\r
91         &Uart->StopBits,\r
92         &NewTerminalContext->StopBits,\r
93         sizeof (UINT8)\r
94         );\r
95       //\r
96       // Change the device path in the ComPort\r
97       //\r
98       if (ChangeTerminal) {\r
99         Node1 = NewTerminalContext->DevicePath;\r
100         Node1 = NextDevicePathNode (Node1);\r
101         while (!IsDevicePathEnd (Node1)) {\r
102           if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
103             Uart1 = (UART_DEVICE_PATH *) Node1;\r
104             CopyMem (\r
105               &Uart1->BaudRate,\r
106               &NewTerminalContext->BaudRate,\r
107               sizeof (UINT64)\r
108               );\r
109 \r
110             CopyMem (\r
111               &Uart1->DataBits,\r
112               &NewTerminalContext->DataBits,\r
113               sizeof (UINT8)\r
114               );\r
115 \r
116             CopyMem (\r
117               &Uart1->Parity,\r
118               &NewTerminalContext->Parity,\r
119               sizeof (UINT8)\r
120               );\r
121 \r
122             CopyMem (\r
123               &Uart1->StopBits,\r
124               &NewTerminalContext->StopBits,\r
125               sizeof (UINT8)\r
126               );\r
127             break;\r
128           }\r
129           //\r
130           // end if\r
131           //\r
132           Node1 = NextDevicePathNode (Node1);\r
133         }\r
134         //\r
135         // end while\r
136         //\r
137         break;\r
138       }\r
139     }\r
140 \r
141     Node = NextDevicePathNode (Node);\r
142   }\r
143 \r
144   return EFI_SUCCESS;\r
145 \r
146 }\r
147 \r
148 VOID\r
149 ChangeVariableDevicePath (\r
150   EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
151   )\r
152 {\r
153   EFI_DEVICE_PATH_PROTOCOL  *Node;\r
154   ACPI_HID_DEVICE_PATH      *Acpi;\r
155   UART_DEVICE_PATH          *Uart;\r
156   UINTN                     Com;\r
157   UINT32                    Match;\r
158   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
159   BM_MENU_ENTRY             *NewMenuEntry;\r
160 \r
161   Match = EISA_PNP_ID (0x0501);\r
162   Node  = DevicePath;\r
163   Node  = NextDevicePathNode (Node);\r
164   Com   = 0;\r
165   while (!IsDevicePathEnd (Node)) {\r
166     if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
167       Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
168       if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
169         CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
170       }\r
171     }\r
172 \r
173     if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
174       NewMenuEntry = BOpt_GetMenuEntry (\r
175                       &TerminalMenu,\r
176                       Com\r
177                       );\r
178       ASSERT (NewMenuEntry != NULL);\r
179       NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
180       Uart                = (UART_DEVICE_PATH *) Node;\r
181       CopyMem (\r
182         &Uart->BaudRate,\r
183         &NewTerminalContext->BaudRate,\r
184         sizeof (UINT64)\r
185         );\r
186 \r
187       CopyMem (\r
188         &Uart->DataBits,\r
189         &NewTerminalContext->DataBits,\r
190         sizeof (UINT8)\r
191         );\r
192 \r
193       CopyMem (\r
194         &Uart->Parity,\r
195         &NewTerminalContext->Parity,\r
196         sizeof (UINT8)\r
197         );\r
198 \r
199       CopyMem (\r
200         &Uart->StopBits,\r
201         &NewTerminalContext->StopBits,\r
202         sizeof (UINT8)\r
203         );\r
204     }\r
205 \r
206     Node = NextDevicePathNode (Node);\r
207   }\r
208 \r
209   return ;\r
210 }\r
211 \r
212 BOOLEAN\r
213 IsTerminalDevicePath (\r
214   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
215   OUT TYPE_OF_TERMINAL         *Termi,\r
216   OUT UINTN                    *Com\r
217   );\r
218 \r
219 EFI_STATUS\r
220 LocateSerialIo (\r
221   VOID\r
222   )\r
223 /*++\r
224 \r
225 Routine Description:\r
226   Build a list containing all serial devices \r
227   \r
228 Arguments:\r
229   \r
230 Returns:\r
231   \r
232 --*/\r
233 {\r
234   UINT8                     *Ptr;\r
235   UINTN                     Index;\r
236   UINTN                     Index2;\r
237   UINTN                     NoHandles;\r
238   EFI_HANDLE                *Handles;\r
239   EFI_STATUS                Status;\r
240   ACPI_HID_DEVICE_PATH      *Acpi;\r
241   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
242   UINT32                    Match;\r
243   EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
244   EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
245   EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
246   EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
247   BM_MENU_ENTRY             *NewMenuEntry;\r
248   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
249   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
250   VENDOR_DEVICE_PATH        Vendor;\r
251   //\r
252   // Get all handles that have SerialIo protocol installed\r
253   //\r
254   InitializeListHead (&TerminalMenu.Head);\r
255   TerminalMenu.MenuNumber = 0;\r
256   Status = gBS->LocateHandleBuffer (\r
257                   ByProtocol,\r
258                   &gEfiSerialIoProtocolGuid,\r
259                   NULL,\r
260                   &NoHandles,\r
261                   &Handles\r
262                   );\r
263   if (EFI_ERROR (Status)) {\r
264     //\r
265     // No serial ports present\r
266     //\r
267     return EFI_UNSUPPORTED;\r
268   }\r
269 \r
270   for (Index = 0; Index < NoHandles; Index++) {\r
271     //\r
272     // Check to see whether the handle has DevicePath Protocol installed\r
273     //\r
274     gBS->HandleProtocol (\r
275           Handles[Index],\r
276           &gEfiDevicePathProtocolGuid,\r
277           (VOID**) &DevicePath\r
278           );\r
279     Ptr = (UINT8 *) DevicePath;\r
280     while (*Ptr != END_DEVICE_PATH_TYPE) {\r
281       Ptr++;\r
282     }\r
283 \r
284     Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
285     Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
286     Match = EISA_PNP_ID (0x0501);\r
287 \r
288     if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
289       NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
290       if (!NewMenuEntry) {\r
291         return EFI_OUT_OF_RESOURCES;\r
292       }\r
293 \r
294       NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
295       CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
296       NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);\r
297       //\r
298       // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
299       // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
300       // datahub which is not completed, so a searching for end of device path will enter a\r
301       // dead-loop.\r
302       //\r
303       NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
304       if (NULL == NewMenuEntry->DisplayString) {\r
305         NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
306       }\r
307 \r
308       NewMenuEntry->HelpString = NULL;\r
309 \r
310       gBS->HandleProtocol (\r
311             Handles[Index],\r
312             &gEfiSerialIoProtocolGuid,\r
313             (VOID**) &SerialIo\r
314             );\r
315 \r
316       CopyMem (\r
317         &NewTerminalContext->BaudRate,\r
318         &SerialIo->Mode->BaudRate,\r
319         sizeof (UINT64)\r
320         );\r
321 \r
322       CopyMem (\r
323         &NewTerminalContext->DataBits,\r
324         &SerialIo->Mode->DataBits,\r
325         sizeof (UINT8)\r
326         );\r
327 \r
328       CopyMem (\r
329         &NewTerminalContext->Parity,\r
330         &SerialIo->Mode->Parity,\r
331         sizeof (UINT8)\r
332         );\r
333 \r
334       CopyMem (\r
335         &NewTerminalContext->StopBits,\r
336         &SerialIo->Mode->StopBits,\r
337         sizeof (UINT8)\r
338         );\r
339       InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
340       TerminalMenu.MenuNumber++;\r
341     }\r
342   }\r
343   //\r
344   // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
345   //\r
346   OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
347   InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
348   ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
349   if (OutDevicePath) {\r
350     UpdateComAttributeFromVariable (OutDevicePath);\r
351   }\r
352 \r
353   if (InpDevicePath) {\r
354     UpdateComAttributeFromVariable (InpDevicePath);\r
355   }\r
356 \r
357   if (ErrDevicePath) {\r
358     UpdateComAttributeFromVariable (ErrDevicePath);\r
359   }\r
360 \r
361   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
362     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
363     if (NULL == NewMenuEntry) {\r
364       return EFI_NOT_FOUND;\r
365     }\r
366 \r
367     NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
368 \r
369     NewTerminalContext->TerminalType  = 0;\r
370     NewTerminalContext->IsConIn       = FALSE;\r
371     NewTerminalContext->IsConOut      = FALSE;\r
372     NewTerminalContext->IsStdErr      = FALSE;\r
373 \r
374     Vendor.Header.Type                = MESSAGING_DEVICE_PATH;\r
375     Vendor.Header.SubType             = MSG_VENDOR_DP;\r
376 \r
377     for (Index2 = 0; Index2 < 4; Index2++) {\r
378       CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));\r
379       SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
380       NewDevicePath = AppendDevicePathNode (\r
381                         NewTerminalContext->DevicePath,\r
382                         (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
383                         );\r
384       SafeFreePool (NewMenuEntry->HelpString);\r
385       //\r
386       // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
387       // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
388       //\r
389       NewMenuEntry->HelpString = NULL;\r
390 \r
391       if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
392         NewTerminalContext->IsConOut      = TRUE;\r
393         NewTerminalContext->TerminalType  = (UINT8) Index2;\r
394       }\r
395 \r
396       if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
397         NewTerminalContext->IsConIn       = TRUE;\r
398         NewTerminalContext->TerminalType  = (UINT8) Index2;\r
399       }\r
400 \r
401       if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
402         NewTerminalContext->IsStdErr      = TRUE;\r
403         NewTerminalContext->TerminalType  = (UINT8) Index2;\r
404       }\r
405     }\r
406   }\r
407 \r
408   return EFI_SUCCESS;\r
409 }\r
410 \r
411 EFI_STATUS\r
412 UpdateComAttributeFromVariable (\r
413   EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
414   )\r
415 /*++\r
416 \r
417 Routine Description:\r
418   Update Com Ports attributes from DevicePath\r
419   \r
420 Arguments:\r
421   DevicePath  -   DevicePath that contains Com ports\r
422   \r
423 Returns:\r
424   \r
425 --*/\r
426 {\r
427   EFI_DEVICE_PATH_PROTOCOL  *Node;\r
428   EFI_DEVICE_PATH_PROTOCOL  *SerialNode;\r
429   ACPI_HID_DEVICE_PATH      *Acpi;\r
430   UART_DEVICE_PATH          *Uart;\r
431   UART_DEVICE_PATH          *Uart1;\r
432   UINT32                    Match;\r
433   UINTN                     TerminalNumber;\r
434   BM_MENU_ENTRY             *NewMenuEntry;\r
435   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
436   UINTN                     Index;\r
437 \r
438   Match           = EISA_PNP_ID (0x0501);\r
439   Node            = DevicePath;\r
440   Node            = NextDevicePathNode (Node);\r
441   TerminalNumber  = 0;\r
442   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
443     while (!IsDevicePathEnd (Node)) {\r
444       if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
445         Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
446         if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
447           CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
448         }\r
449       }\r
450 \r
451       if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
452         Uart          = (UART_DEVICE_PATH *) Node;\r
453         NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
454         if (NULL == NewMenuEntry) {\r
455           return EFI_NOT_FOUND;\r
456         }\r
457 \r
458         NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
459         CopyMem (\r
460           &NewTerminalContext->BaudRate,\r
461           &Uart->BaudRate,\r
462           sizeof (UINT64)\r
463           );\r
464 \r
465         CopyMem (\r
466           &NewTerminalContext->DataBits,\r
467           &Uart->DataBits,\r
468           sizeof (UINT8)\r
469           );\r
470 \r
471         CopyMem (\r
472           &NewTerminalContext->Parity,\r
473           &Uart->Parity,\r
474           sizeof (UINT8)\r
475           );\r
476 \r
477         CopyMem (\r
478           &NewTerminalContext->StopBits,\r
479           &Uart->StopBits,\r
480           sizeof (UINT8)\r
481           );\r
482 \r
483         SerialNode  = NewTerminalContext->DevicePath;\r
484         SerialNode  = NextDevicePathNode (SerialNode);\r
485         while (!IsDevicePathEnd (SerialNode)) {\r
486           if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
487             //\r
488             // Update following device paths according to\r
489             // previous acquired uart attributes\r
490             //\r
491             Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
492             CopyMem (\r
493               &Uart1->BaudRate,\r
494               &NewTerminalContext->BaudRate,\r
495               sizeof (UINT64)\r
496               );\r
497 \r
498             CopyMem (\r
499               &Uart1->DataBits,\r
500               &NewTerminalContext->DataBits,\r
501               sizeof (UINT8)\r
502               );\r
503             CopyMem (\r
504               &Uart1->Parity,\r
505               &NewTerminalContext->Parity,\r
506               sizeof (UINT8)\r
507               );\r
508             CopyMem (\r
509               &Uart1->StopBits,\r
510               &NewTerminalContext->StopBits,\r
511               sizeof (UINT8)\r
512               );\r
513 \r
514             break;\r
515           }\r
516 \r
517           SerialNode = NextDevicePathNode (SerialNode);\r
518         }\r
519         //\r
520         // end while\r
521         //\r
522       }\r
523 \r
524       Node = NextDevicePathNode (Node);\r
525     }\r
526     //\r
527     // end while\r
528     //\r
529   }\r
530 \r
531   return EFI_SUCCESS;\r
532 }\r
533 \r
534 EFI_DEVICE_PATH_PROTOCOL *\r
535 DevicePathInstanceDup (\r
536   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
537   )\r
538 /*++\r
539 \r
540 Routine Description:\r
541   Function creates a device path data structure that identically matches the \r
542   device path passed in.\r
543 \r
544 Arguments:\r
545   DevPath      - A pointer to a device path data structure.\r
546 \r
547 Returns:\r
548 \r
549   The new copy of DevPath is created to identically match the input.  \r
550   Otherwise, NULL is returned.\r
551 \r
552 --*/\r
553 {\r
554   EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;\r
555   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
556   EFI_DEVICE_PATH_PROTOCOL  *Temp;\r
557   UINT8                     *Ptr;\r
558   UINTN                     Size;\r
559 \r
560   //\r
561   // get the size of an instance from the input\r
562   //\r
563   Temp            = DevPath;\r
564   DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);\r
565 \r
566   //\r
567   // Make a copy and set proper end type\r
568   //\r
569   NewDevPath = NULL;\r
570   if (Size) {\r
571     NewDevPath = AllocateZeroPool (Size);\r
572     ASSERT (NewDevPath != NULL);\r
573   }\r
574 \r
575   if (NewDevPath) {\r
576     CopyMem (NewDevPath, DevicePathInst, Size);\r
577     Ptr = (UINT8 *) NewDevPath;\r
578     Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
579     Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
580     SetDevicePathEndNode (Temp);\r
581   }\r
582 \r
583   return NewDevPath;\r
584 }\r
585 \r
586 EFI_STATUS\r
587 GetConsoleMenu (\r
588   IN UINTN              ConsoleMenuType\r
589   )\r
590 {\r
591   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
592   EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;\r
593   EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;\r
594   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
595   UINTN                     Size;\r
596   UINTN                     AllCount;\r
597   UINTN                     Index;\r
598   UINTN                     Index2;\r
599   BM_MENU_ENTRY             *NewMenuEntry;\r
600   BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
601   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
602   TYPE_OF_TERMINAL          Terminal;\r
603   BM_MENU_ENTRY             *NewTerminalMenuEntry;\r
604   UINTN                     Com;\r
605   BM_MENU_OPTION            *ConsoleMenu;\r
606 \r
607   DevicePath    = NULL;\r
608   AllDevicePath = NULL;\r
609   AllCount      = 0;\r
610   switch (ConsoleMenuType) {\r
611   case BM_CONSOLE_IN_CONTEXT_SELECT:\r
612     ConsoleMenu = &ConsoleInpMenu;\r
613     DevicePath = EfiLibGetVariable (\r
614                   L"ConIn",\r
615                   &gEfiGlobalVariableGuid\r
616                   );\r
617 \r
618     AllDevicePath = EfiLibGetVariable (\r
619                       L"ConInDev",\r
620                       &gEfiGlobalVariableGuid\r
621                       );\r
622     break;\r
623 \r
624   case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
625     ConsoleMenu = &ConsoleOutMenu;\r
626     DevicePath = EfiLibGetVariable (\r
627                   L"ConOut",\r
628                   &gEfiGlobalVariableGuid\r
629                   );\r
630 \r
631     AllDevicePath = EfiLibGetVariable (\r
632                       L"ConOutDev",\r
633                       &gEfiGlobalVariableGuid\r
634                       );\r
635     break;\r
636 \r
637   case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
638     ConsoleMenu = &ConsoleErrMenu;\r
639     DevicePath = EfiLibGetVariable (\r
640                   L"ErrOut",\r
641                   &gEfiGlobalVariableGuid\r
642                   );\r
643 \r
644     AllDevicePath = EfiLibGetVariable (\r
645                       L"ErrOutDev",\r
646                       &gEfiGlobalVariableGuid\r
647                       );\r
648     break;\r
649 \r
650   default:\r
651     return EFI_UNSUPPORTED;\r
652   }\r
653 \r
654   if (NULL == AllDevicePath) {\r
655     return EFI_NOT_FOUND;\r
656   }\r
657 \r
658   InitializeListHead (&ConsoleMenu->Head);\r
659 \r
660   AllCount                = EfiDevicePathInstanceCount (AllDevicePath);\r
661   ConsoleMenu->MenuNumber = 0;\r
662   //\r
663   // Following is menu building up for Console Out Devices\r
664   //\r
665   MultiDevicePath = AllDevicePath;\r
666   Index2          = 0;\r
667   for (Index = 0; Index < AllCount; Index++) {\r
668     DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
669 \r
670     NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
671     if (NULL == NewMenuEntry) {\r
672       return EFI_OUT_OF_RESOURCES;\r
673     }\r
674 \r
675     NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
676     NewMenuEntry->OptionNumber    = Index2;\r
677 \r
678     NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);\r
679     NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
680     if (NULL == NewMenuEntry->DisplayString) {\r
681       NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
682     }\r
683 \r
684     NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
685                                       NewConsoleContext->DevicePath,\r
686                                       &Terminal,\r
687                                       &Com\r
688                                       );\r
689 \r
690     NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
691                                     DevicePath,\r
692                                     NewConsoleContext->DevicePath\r
693                                     );\r
694     NewTerminalMenuEntry  = NULL;\r
695     NewTerminalContext    = NULL;\r
696 \r
697     if (NewConsoleContext->IsTerminal) {\r
698       BOpt_DestroyMenuEntry (NewMenuEntry);\r
699     } else {\r
700       Index2++;\r
701       ConsoleMenu->MenuNumber++;\r
702       InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
703     }\r
704   }\r
705 \r
706   return EFI_SUCCESS;\r
707 }\r
708 \r
709 EFI_STATUS\r
710 GetAllConsoles (\r
711   VOID\r
712   )\r
713 /*++\r
714 \r
715 Routine Description:\r
716   Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
717 \r
718 Arguments:\r
719   \r
720 Returns:\r
721   EFI_SUCCESS \r
722   Others\r
723   \r
724 --*/\r
725 {\r
726   GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
727   GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
728   GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
729   return EFI_SUCCESS;\r
730 }\r
731 \r
732 EFI_STATUS\r
733 FreeAllConsoles (\r
734   VOID\r
735   )\r
736 /*++\r
737 \r
738 Routine Description:\r
739   Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
740 \r
741 Arguments:\r
742   \r
743 Returns:\r
744   EFI_SUCCESS \r
745   Others\r
746   \r
747 --*/\r
748 {\r
749   BOpt_FreeMenu (&ConsoleOutMenu);\r
750   BOpt_FreeMenu (&ConsoleInpMenu);\r
751   BOpt_FreeMenu (&ConsoleErrMenu);\r
752   BOpt_FreeMenu (&TerminalMenu);\r
753   return EFI_SUCCESS;\r
754 }\r
755 \r
756 BOOLEAN\r
757 IsTerminalDevicePath (\r
758   IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
759   OUT TYPE_OF_TERMINAL         *Termi,\r
760   OUT UINTN                    *Com\r
761   )\r
762 /*++\r
763 \r
764 Routine Description:\r
765   Test whether DevicePath is a valid Terminal\r
766 \r
767 Arguments:\r
768   DevicePath  -   DevicePath to be checked\r
769   Termi       -   If is terminal, give its type\r
770   Com         -   If is Com Port, give its type\r
771   \r
772 Returns:\r
773   TRUE        -   If DevicePath point to a Terminal\r
774   FALSE\r
775   \r
776 --*/\r
777 {\r
778   UINT8                 *Ptr;\r
779   BOOLEAN               IsTerminal;\r
780   VENDOR_DEVICE_PATH    *Vendor;\r
781   ACPI_HID_DEVICE_PATH  *Acpi;\r
782   UINT32                Match;\r
783   EFI_GUID              TempGuid;\r
784 \r
785   IsTerminal = FALSE;\r
786 \r
787   //\r
788   // Parse the Device Path, should be change later!!!\r
789   //\r
790   Ptr = (UINT8 *) DevicePath;\r
791   while (*Ptr != END_DEVICE_PATH_TYPE) {\r
792     Ptr++;\r
793   }\r
794 \r
795   Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
796   Vendor  = (VENDOR_DEVICE_PATH *) Ptr;\r
797 \r
798   //\r
799   // There are four kinds of Terminal types\r
800   // check to see whether this devicepath\r
801   // is one of that type\r
802   //\r
803   CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
804 \r
805   if (CompareGuid (&TempGuid, &Guid[0])) {\r
806     *Termi      = PC_ANSI;\r
807     IsTerminal  = TRUE;\r
808   } else {\r
809     if (CompareGuid (&TempGuid, &Guid[1])) {\r
810       *Termi      = VT_100;\r
811       IsTerminal  = TRUE;\r
812     } else {\r
813       if (CompareGuid (&TempGuid, &Guid[2])) {\r
814         *Termi      = VT_100_PLUS;\r
815         IsTerminal  = TRUE;\r
816       } else {\r
817         if (CompareGuid (&TempGuid, &Guid[3])) {\r
818           *Termi      = VT_UTF8;\r
819           IsTerminal  = TRUE;\r
820         } else {\r
821           IsTerminal = FALSE;\r
822         }\r
823       }\r
824     }\r
825   }\r
826 \r
827   if (!IsTerminal) {\r
828     return FALSE;\r
829   }\r
830 \r
831   Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
832   Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
833   Match = EISA_PNP_ID (0x0501);\r
834   if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
835     CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
836   } else {\r
837     return FALSE;\r
838   }\r
839 \r
840   return TRUE;\r
841 }\r