Code scrub.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Console / ConPlatformDxe / ConPlatform.c
1 /** @file\r
2   Console Platfrom DXE Driver, install Console Device Guids and update Console\r
3   Environment Variables.\r
4 \r
5 Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 #include <ConPlatform.h>\r
17 \r
18 \r
19 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding = {\r
20   ConPlatformTextInDriverBindingSupported,\r
21   ConPlatformTextInDriverBindingStart,\r
22   ConPlatformTextInDriverBindingStop,\r
23   0xa,\r
24   NULL,\r
25   NULL\r
26 };\r
27 \r
28 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding = {\r
29   ConPlatformTextOutDriverBindingSupported,\r
30   ConPlatformTextOutDriverBindingStart,\r
31   ConPlatformTextOutDriverBindingStop,\r
32   0xa,\r
33   NULL,\r
34   NULL\r
35 };\r
36 \r
37 /**\r
38   The user Entry Point for module ConPlatform. The user code starts with this function.\r
39 \r
40   @param  ImageHandle       The firmware allocated handle for the EFI image.\r
41   @param  SystemTable       A pointer to the EFI System Table.\r
42 \r
43   @retval EFI_SUCCESS       The entry point is executed successfully.\r
44   @retval other             Some error occurs when executing this entry point.\r
45 \r
46 **/\r
47 EFI_STATUS\r
48 EFIAPI\r
49 InitializeConPlatform(\r
50   IN EFI_HANDLE           ImageHandle,\r
51   IN EFI_SYSTEM_TABLE     *SystemTable\r
52   )\r
53 {\r
54   EFI_STATUS              Status;\r
55 \r
56   //\r
57   // Install driver model protocol(s).\r
58   //\r
59   Status = EfiLibInstallDriverBindingComponentName2 (\r
60              ImageHandle,\r
61              SystemTable,\r
62              &gConPlatformTextInDriverBinding,\r
63              ImageHandle,\r
64              &gConPlatformComponentName,\r
65              &gConPlatformComponentName2\r
66              );\r
67   ASSERT_EFI_ERROR (Status);\r
68 \r
69   Status = EfiLibInstallDriverBindingComponentName2 (\r
70              ImageHandle,\r
71              SystemTable,\r
72              &gConPlatformTextOutDriverBinding,\r
73              NULL,\r
74              &gConPlatformComponentName,\r
75              &gConPlatformComponentName2\r
76              );\r
77   ASSERT_EFI_ERROR (Status);\r
78 \r
79 \r
80   return Status;\r
81 }\r
82 \r
83 \r
84 /**\r
85   Test to see if EFI Text In Protocol could be supported on the ControllerHandle. \r
86 \r
87   @param  This                Protocol instance pointer.\r
88   @param  ControllerHandle    Handle of device to test.\r
89   @param  RemainingDevicePath Optional parameter use to pick a specific child\r
90                               device to start.\r
91 \r
92   @retval EFI_SUCCESS         This driver supports this device.\r
93   @retval other               This driver does not support this device.\r
94 \r
95 **/\r
96 EFI_STATUS\r
97 EFIAPI\r
98 ConPlatformTextInDriverBindingSupported (\r
99   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
100   IN  EFI_HANDLE                   ControllerHandle,\r
101   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
102   )\r
103 {\r
104   return ConPlatformDriverBindingSupported (\r
105           This,\r
106           ControllerHandle,\r
107           RemainingDevicePath,\r
108           &gEfiSimpleTextInProtocolGuid\r
109           );\r
110 }\r
111 \r
112 \r
113 /**\r
114   Test to see if EFI Text Out Protocol could be supported on the ControllerHandle. \r
115 \r
116   @param  This                Protocol instance pointer.\r
117   @param  ControllerHandle    Handle of device to test.\r
118   @param  RemainingDevicePath Optional parameter use to pick a specific child\r
119                               device to start.\r
120 \r
121   @retval EFI_SUCCESS         This driver supports this device.\r
122   @retval other               This driver does not support this device.\r
123 \r
124 **/\r
125 EFI_STATUS\r
126 EFIAPI\r
127 ConPlatformTextOutDriverBindingSupported (\r
128   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
129   IN  EFI_HANDLE                   ControllerHandle,\r
130   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
131   )\r
132 {\r
133   return ConPlatformDriverBindingSupported (\r
134           This,\r
135           ControllerHandle,\r
136           RemainingDevicePath,\r
137           &gEfiSimpleTextOutProtocolGuid\r
138           );\r
139 }\r
140 \r
141 \r
142 /**\r
143   Test to see if the specified Protocol could be supported on the ControllerHandle. \r
144 \r
145   @param  This                Protocol instance pointer.\r
146   @param  ControllerHandle    Handle of device to test.\r
147   @param  RemainingDevicePath Optional parameter use to pick a specific child\r
148                               device to start.\r
149   @param  ProtocolGuid        The specfic protocol.\r
150 \r
151   @retval EFI_SUCCESS         This driver supports this device.\r
152   @retval other               This driver does not support this device.\r
153 \r
154 **/\r
155 EFI_STATUS\r
156 ConPlatformDriverBindingSupported (\r
157   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
158   IN  EFI_HANDLE                   ControllerHandle,\r
159   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath,\r
160   IN  EFI_GUID                     *ProtocolGuid\r
161   )\r
162 {\r
163   EFI_STATUS  Status;\r
164   VOID        *Interface;\r
165 \r
166   //\r
167   // Test to see if this is a physical device by checking if\r
168   // it has a Device Path Protocol.\r
169   //\r
170   Status = gBS->OpenProtocol (\r
171                   ControllerHandle,\r
172                   &gEfiDevicePathProtocolGuid,\r
173                   NULL,\r
174                   This->DriverBindingHandle,\r
175                   ControllerHandle,\r
176                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
177                   );\r
178   if (EFI_ERROR (Status)) {\r
179     return Status;\r
180   }\r
181   //\r
182   // Test to see if this device supports the specified Protocol.\r
183   //\r
184   Status = gBS->OpenProtocol (\r
185                   ControllerHandle,\r
186                   ProtocolGuid,\r
187                   (VOID **) &Interface,\r
188                   This->DriverBindingHandle,\r
189                   ControllerHandle,\r
190                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
191                   );\r
192   if (EFI_ERROR (Status)) {\r
193     return Status;\r
194   }\r
195 \r
196   gBS->CloseProtocol (\r
197         ControllerHandle,\r
198         ProtocolGuid,\r
199         This->DriverBindingHandle,\r
200         ControllerHandle\r
201         );\r
202 \r
203   return EFI_SUCCESS;\r
204 }\r
205 \r
206 /**\r
207   Start this driver on ControllerHandle by opening Simple Text In protocol,\r
208   reading Device Path, and installing Console In Devcice GUID on ControllerHandle.\r
209 \r
210   If this devcie is not one hot-plug devce, append its device path into the \r
211   console environment variables ConInDev.\r
212   \r
213   @param  This                 Protocol instance pointer.\r
214   @param  ControllerHandle     Handle of device to bind driver to\r
215   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
216                                device to start.\r
217 \r
218   @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
219   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
220   @retval other                This driver does not support this device.\r
221 \r
222 **/\r
223 EFI_STATUS\r
224 EFIAPI\r
225 ConPlatformTextInDriverBindingStart (\r
226   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
227   IN  EFI_HANDLE                    ControllerHandle,\r
228   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath\r
229   )\r
230 {\r
231   EFI_STATUS                  Status;\r
232   EFI_DEVICE_PATH_PROTOCOL    *DevicePath;\r
233   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
234 \r
235   //\r
236   // Get the Device Path Protocol so the environment variables can be updated\r
237   //\r
238   Status = gBS->OpenProtocol (\r
239                   ControllerHandle,\r
240                   &gEfiDevicePathProtocolGuid,\r
241                   (VOID **) &DevicePath,\r
242                   This->DriverBindingHandle,\r
243                   ControllerHandle,\r
244                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
245                   );\r
246   if (EFI_ERROR (Status)) {\r
247     return Status;\r
248   }\r
249   //\r
250   // Open the Simple Input Protocol BY_DRIVER\r
251   //\r
252   Status = gBS->OpenProtocol (\r
253                   ControllerHandle,\r
254                   &gEfiSimpleTextInProtocolGuid,\r
255                   (VOID **) &TextIn,\r
256                   This->DriverBindingHandle,\r
257                   ControllerHandle,\r
258                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
259                   );\r
260   if (EFI_ERROR (Status)) {\r
261     return Status;\r
262   }\r
263   //\r
264   // Check the device handle, if it is a hot plug device,\r
265   // do not put the device path into ConInDev, and install\r
266   // gEfiConsoleInDeviceGuid to the device handle directly.\r
267   // The policy is, make hot plug device plug in and play immediately.\r
268   //\r
269   if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
270     gBS->InstallMultipleProtocolInterfaces (\r
271           &ControllerHandle,\r
272           &gEfiConsoleInDeviceGuid,\r
273           NULL,\r
274           NULL\r
275           );\r
276   } else {\r
277     //\r
278     // Append the device path to the ConInDev environment variable\r
279     //\r
280     ConPlatformUpdateDeviceVariable (\r
281       L"ConInDev",\r
282       DevicePath,\r
283       APPEND\r
284       );\r
285 \r
286     //\r
287     // If the device path is an instance in the ConIn environment variable,\r
288     // then install EfiConsoleInDeviceGuid onto ControllerHandle\r
289     //\r
290     Status = ConPlatformUpdateDeviceVariable (\r
291               L"ConIn",\r
292               DevicePath,\r
293               CHECK\r
294               );\r
295 \r
296     if (!EFI_ERROR (Status)) {\r
297       gBS->InstallMultipleProtocolInterfaces (\r
298             &ControllerHandle,\r
299             &gEfiConsoleInDeviceGuid,\r
300             NULL,\r
301             NULL\r
302             );\r
303     } else {\r
304       gBS->CloseProtocol (\r
305             ControllerHandle,\r
306             &gEfiSimpleTextInProtocolGuid,\r
307             This->DriverBindingHandle,\r
308             ControllerHandle\r
309             );\r
310     }\r
311   }\r
312 \r
313   return EFI_SUCCESS;\r
314 }\r
315 \r
316 /**\r
317   Start this driver on ControllerHandle by opening Simple Text Out protocol,\r
318   reading Device Path, and installing Console Out Devcic GUID, Standard Error\r
319   Device GUID on ControllerHandle.\r
320 \r
321   If this devcie is not one hot-plug devce, append its device path into the \r
322   console environment variables ConOutDev, StdErrDev.\r
323   \r
324   @param  This                 Protocol instance pointer.\r
325   @param  ControllerHandle     Handle of device to bind driver to\r
326   @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
327                                device to start.\r
328 \r
329   @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
330   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
331   @retval other                This driver does not support this device\r
332 \r
333 **/\r
334 EFI_STATUS\r
335 EFIAPI\r
336 ConPlatformTextOutDriverBindingStart (\r
337   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
338   IN  EFI_HANDLE                    ControllerHandle,\r
339   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath\r
340   )\r
341 {\r
342   EFI_STATUS                    Status;\r
343   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;\r
344   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *TextOut;\r
345   BOOLEAN                       NeedClose;\r
346 \r
347   NeedClose = TRUE;\r
348 \r
349   //\r
350   // Get the Device Path Protocol so the environment variables can be updated\r
351   //\r
352   Status = gBS->OpenProtocol (\r
353                   ControllerHandle,\r
354                   &gEfiDevicePathProtocolGuid,\r
355                   (VOID **) &DevicePath,\r
356                   This->DriverBindingHandle,\r
357                   ControllerHandle,\r
358                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
359                   );\r
360   if (EFI_ERROR (Status)) {\r
361     return Status;\r
362   }\r
363   //\r
364   // Open the Simple Text Output Protocol BY_DRIVER\r
365   //\r
366   Status = gBS->OpenProtocol (\r
367                   ControllerHandle,\r
368                   &gEfiSimpleTextOutProtocolGuid,\r
369                   (VOID **) &TextOut,\r
370                   This->DriverBindingHandle,\r
371                   ControllerHandle,\r
372                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
373                   );\r
374   if (EFI_ERROR (Status)) {\r
375     return Status;\r
376   }\r
377   //\r
378   // Check the device handle, if it is a hot plug device,\r
379   // do not put the device path into ConOutDev and StdErrDev,\r
380   // and install gEfiConsoleOutDeviceGuid to the device handle directly.\r
381   // The policy is, make hot plug device plug in and play immediately.\r
382   //\r
383   if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
384     gBS->InstallMultipleProtocolInterfaces (\r
385           &ControllerHandle,\r
386           &gEfiConsoleOutDeviceGuid,\r
387           NULL,\r
388           NULL\r
389           );\r
390   } else {\r
391     //\r
392     // Append the device path to the ConOutDev environment variable\r
393     //\r
394     ConPlatformUpdateDeviceVariable (\r
395       L"ConOutDev",\r
396       DevicePath,\r
397       APPEND\r
398       );\r
399     //\r
400     // Append the device path to the StdErrDev environment variable\r
401     //\r
402     ConPlatformUpdateDeviceVariable (\r
403       L"ErrOutDev",\r
404       DevicePath,\r
405       APPEND\r
406       );\r
407 \r
408     //\r
409     // If the device path is an instance in the ConOut environment variable,\r
410     // then install EfiConsoleOutDeviceGuid onto ControllerHandle\r
411     //\r
412     Status = ConPlatformUpdateDeviceVariable (\r
413               L"ConOut",\r
414               DevicePath,\r
415               CHECK\r
416               );\r
417 \r
418     if (!EFI_ERROR (Status)) {\r
419       NeedClose = FALSE;\r
420       Status = gBS->InstallMultipleProtocolInterfaces (\r
421                       &ControllerHandle,\r
422                       &gEfiConsoleOutDeviceGuid,\r
423                       NULL,\r
424                       NULL\r
425                       );\r
426     }\r
427     //\r
428     // If the device path is an instance in the StdErr environment variable,\r
429     // then install EfiStandardErrorDeviceGuid onto ControllerHandle\r
430     //\r
431     Status = ConPlatformUpdateDeviceVariable (\r
432               L"ErrOut",\r
433               DevicePath,\r
434               CHECK\r
435               );\r
436     if (!EFI_ERROR (Status)) {\r
437       NeedClose = FALSE;\r
438       gBS->InstallMultipleProtocolInterfaces (\r
439             &ControllerHandle,\r
440             &gEfiStandardErrorDeviceGuid,\r
441             NULL,\r
442             NULL\r
443             );\r
444     }\r
445 \r
446     if (NeedClose) {\r
447       gBS->CloseProtocol (\r
448             ControllerHandle,\r
449             &gEfiSimpleTextOutProtocolGuid,\r
450             This->DriverBindingHandle,\r
451             ControllerHandle\r
452             );\r
453     }\r
454   }\r
455 \r
456   return EFI_SUCCESS;\r
457 }\r
458 \r
459 /**\r
460   Stop this driver on ControllerHandle by removing Console In Devcice GUID \r
461   and closing the Simple Text In protocol on ControllerHandle.\r
462 \r
463   @param  This              Protocol instance pointer.\r
464   @param  ControllerHandle  Handle of device to stop driver on\r
465   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
466                             children is zero stop the entire bus driver.\r
467   @param  ChildHandleBuffer List of Child Handles to Stop.\r
468 \r
469   @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
470   @retval other             This driver was not removed from this device\r
471 \r
472 **/\r
473 EFI_STATUS\r
474 EFIAPI\r
475 ConPlatformTextInDriverBindingStop (\r
476   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
477   IN  EFI_HANDLE                   ControllerHandle,\r
478   IN  UINTN                        NumberOfChildren,\r
479   IN  EFI_HANDLE                   *ChildHandleBuffer\r
480   )\r
481 {\r
482   EFI_STATUS                Status;\r
483   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
484 \r
485   //\r
486   // hot plug device is not included into the console associated variables,\r
487   // so no need to check variable for those hot plug devices.\r
488   //\r
489   if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
490     //\r
491     // Get the Device Path Protocol so the environment variables can be updated\r
492     //\r
493     Status = gBS->OpenProtocol (\r
494                     ControllerHandle,\r
495                     &gEfiDevicePathProtocolGuid,\r
496                     (VOID **) &DevicePath,\r
497                     This->DriverBindingHandle,\r
498                     ControllerHandle,\r
499                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
500                     );\r
501     if (!EFI_ERROR (Status)) {\r
502       //\r
503       // Remove DevicePath from ConInDev\r
504       //\r
505       ConPlatformUpdateDeviceVariable (\r
506         L"ConInDev",\r
507         DevicePath,\r
508         DELETE\r
509         );\r
510     }\r
511   }\r
512   //\r
513   // Uninstall the Console Device GUIDs from Controller Handle\r
514   //\r
515   ConPlatformUnInstallProtocol (\r
516     This,\r
517     ControllerHandle,\r
518     &gEfiConsoleInDeviceGuid\r
519     );\r
520 \r
521   //\r
522   // Close the Simple Input Protocol\r
523   //\r
524   gBS->CloseProtocol (\r
525         ControllerHandle,\r
526         &gEfiSimpleTextInProtocolGuid,\r
527         This->DriverBindingHandle,\r
528         ControllerHandle\r
529         );\r
530 \r
531   return EFI_SUCCESS;\r
532 }\r
533 \r
534 \r
535 /**\r
536   Stop this driver on ControllerHandle by removing Console Out Devcice GUID \r
537   and closing the Simple Text Out protocol on ControllerHandle.\r
538 \r
539   @param  This              Protocol instance pointer.\r
540   @param  ControllerHandle  Handle of device to stop driver on\r
541   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
542                             children is zero stop the entire bus driver.\r
543   @param  ChildHandleBuffer List of Child Handles to Stop.\r
544 \r
545   @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
546   @retval other             This driver was not removed from this device\r
547 \r
548 **/\r
549 EFI_STATUS\r
550 EFIAPI\r
551 ConPlatformTextOutDriverBindingStop (\r
552   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
553   IN  EFI_HANDLE                   ControllerHandle,\r
554   IN  UINTN                        NumberOfChildren,\r
555   IN  EFI_HANDLE                   *ChildHandleBuffer\r
556   )\r
557 {\r
558   EFI_STATUS                Status;\r
559   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
560 \r
561   //\r
562   // hot plug device is not included into the console associated variables,\r
563   // so no need to check variable for those hot plug devices.\r
564   //\r
565   if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) {\r
566     //\r
567     // Get the Device Path Protocol so the environment variables can be updated\r
568     //\r
569     Status = gBS->OpenProtocol (\r
570                     ControllerHandle,\r
571                     &gEfiDevicePathProtocolGuid,\r
572                     (VOID **) &DevicePath,\r
573                     This->DriverBindingHandle,\r
574                     ControllerHandle,\r
575                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
576                     );\r
577     if (!EFI_ERROR (Status)) {\r
578       //\r
579       // Remove DevicePath from ConOutDev, and StdErrDev\r
580       //\r
581       ConPlatformUpdateDeviceVariable (\r
582         L"ConOutDev",\r
583         DevicePath,\r
584         DELETE\r
585         );\r
586       ConPlatformUpdateDeviceVariable (\r
587         L"ErrOutDev",\r
588         DevicePath,\r
589         DELETE\r
590         );\r
591     }\r
592   }\r
593   //\r
594   // Uninstall the Console Device GUIDs from Controller Handle\r
595   //\r
596   ConPlatformUnInstallProtocol (\r
597     This,\r
598     ControllerHandle,\r
599     &gEfiConsoleOutDeviceGuid\r
600     );\r
601 \r
602   ConPlatformUnInstallProtocol (\r
603     This,\r
604     ControllerHandle,\r
605     &gEfiStandardErrorDeviceGuid\r
606     );\r
607 \r
608   //\r
609   // Close the Simple Text Output Protocol\r
610   //\r
611   gBS->CloseProtocol (\r
612         ControllerHandle,\r
613         &gEfiSimpleTextOutProtocolGuid,\r
614         This->DriverBindingHandle,\r
615         ControllerHandle\r
616         );\r
617 \r
618   return EFI_SUCCESS;\r
619 }\r
620 \r
621 \r
622 /**\r
623   Uninstall the specified protocol.\r
624 \r
625   @param This            Protocol instance pointer.\r
626   @param Handle          Handle of device to uninstall protocol on.\r
627   @param ProtocolGuid    The specified protocol need to be uninstalled.\r
628 \r
629   @return None.\r
630 \r
631 **/\r
632 VOID\r
633 ConPlatformUnInstallProtocol (\r
634   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
635   IN  EFI_HANDLE                   Handle,\r
636   IN  EFI_GUID                     *ProtocolGuid\r
637   )\r
638 {\r
639   EFI_STATUS  Status;\r
640 \r
641   Status = gBS->OpenProtocol (\r
642                   Handle,\r
643                   ProtocolGuid,\r
644                   NULL,\r
645                   This->DriverBindingHandle,\r
646                   Handle,\r
647                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
648                   );\r
649 \r
650   if (!EFI_ERROR (Status)) {\r
651     gBS->UninstallMultipleProtocolInterfaces (\r
652           Handle,\r
653           ProtocolGuid,\r
654           NULL,\r
655           NULL\r
656           );\r
657   }\r
658 \r
659   return ;\r
660 }\r
661 \r
662 /**\r
663   Read the EFI variable (Name) and return a dynamically allocated\r
664   buffer, and the size of the buffer. On failure return NULL.\r
665 \r
666   @param  Name             String part of EFI variable name\r
667 \r
668   @return Dynamically allocated memory that contains a copy of the EFI variable.\r
669           Caller is repsoncible freeing the buffer. Return NULL means Variable \r
670           was not read.\r
671 \r
672 **/\r
673 VOID *\r
674 ConPlatformGetVariable (\r
675   IN  CHAR16    *Name\r
676   )\r
677 {\r
678   EFI_STATUS  Status;\r
679   VOID        *Buffer;\r
680   UINTN       BufferSize;\r
681 \r
682   BufferSize  = 0;\r
683   Buffer      = NULL;\r
684 \r
685   //\r
686   // Test to see if the variable exists.  If it doesn't, reuturn NULL.\r
687   //\r
688   Status = gRT->GetVariable (\r
689                   Name,\r
690                   &gEfiGlobalVariableGuid,\r
691                   NULL,\r
692                   &BufferSize,\r
693                   Buffer\r
694                   );\r
695 \r
696   if (Status == EFI_BUFFER_TOO_SMALL) {\r
697     //\r
698     // Allocate the buffer to return\r
699     //\r
700     Buffer = AllocatePool (BufferSize);\r
701     if (Buffer == NULL) {\r
702       return NULL;\r
703     }\r
704     //\r
705     // Read variable into the allocated buffer.\r
706     //\r
707     Status = gRT->GetVariable (\r
708                     Name,\r
709                     &gEfiGlobalVariableGuid,\r
710                     NULL,\r
711                     &BufferSize,\r
712                     Buffer\r
713                     );\r
714     if (EFI_ERROR (Status)) {\r
715       FreePool (Buffer);\r
716       //\r
717       // To make sure Buffer is NULL if any error occurs.\r
718       //\r
719       Buffer = NULL;\r
720     }\r
721   }\r
722 \r
723   return Buffer;\r
724 }\r
725 \r
726 /**\r
727   Function compares a device path data structure to that of all the nodes of a\r
728   second device path instance.\r
729 \r
730 \r
731   @param Multi           A pointer to a multi-instance device path data structure.\r
732   @param Single          A pointer to a single-instance device path data structure.\r
733   @param NewDevicePath   If Delete is TRUE, this parameter must not be null, and it\r
734                          points to the remaining device path data structure.\r
735                          (remaining device path = Multi - Single.)\r
736   @param Delete          If TRUE, means removing Single from Multi.\r
737                          If FALSE, the routine just check whether Single matches\r
738                          with any instance in Multi.\r
739 \r
740   @retval EFI_SUCCESS    If the Single is contained within Multi.\r
741   @retval EFI_NOT_FOUND  If the Single is not contained within Multi.\r
742 \r
743 **/\r
744 EFI_STATUS\r
745 ConPlatformMatchDevicePaths (\r
746   IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
747   IN  EFI_DEVICE_PATH_PROTOCOL  *Single,\r
748   OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath OPTIONAL,\r
749   IN  BOOLEAN                   Delete\r
750   )\r
751 {\r
752   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
753   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath1;\r
754   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath2;\r
755   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
756   UINTN                     Size;\r
757 \r
758   //\r
759   // The passed in DevicePath should not be NULL\r
760   //\r
761   if ((Multi == NULL) || (Single == NULL)) {\r
762     return EFI_NOT_FOUND;\r
763   }\r
764 \r
765   //\r
766   // If performing Delete operation, the NewDevicePath must not be NULL.\r
767   //\r
768   if (Delete) {\r
769     ASSERT (NewDevicePath != NULL);\r
770   }\r
771 \r
772   TempDevicePath1 = NULL;\r
773 \r
774   DevicePath      = Multi;\r
775   DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
776 \r
777   //\r
778   // Search for the match of 'Single' in 'Multi'\r
779   //\r
780   while (DevicePathInst != NULL) {\r
781     if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
782       if (!Delete) {\r
783         //\r
784         // If Delete is FALSE, return EFI_SUCCESS if Single is found in Multi.\r
785         //\r
786         FreePool (DevicePathInst);\r
787         return EFI_SUCCESS;\r
788       }\r
789     } else {\r
790       if (Delete) {\r
791         //\r
792         // Append the mis-matched devcie path into remaining device path.\r
793         //\r
794         TempDevicePath2 = AppendDevicePathInstance (\r
795                             TempDevicePath1,\r
796                             DevicePathInst\r
797                             );\r
798         SafeFreePool (TempDevicePath1);\r
799         TempDevicePath1 = TempDevicePath2;\r
800       }\r
801     }\r
802 \r
803     FreePool (DevicePathInst);\r
804     DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
805   }\r
806 \r
807   if (Delete) {\r
808     //\r
809     // Return the remaining device path data structure\r
810     //\r
811     *NewDevicePath = TempDevicePath1;\r
812     return EFI_SUCCESS;\r
813   }\r
814 \r
815   return EFI_NOT_FOUND;\r
816 }\r
817 \r
818 /**\r
819   Update console environment variables. \r
820 \r
821   @param  VariableName    Console environment variables, ConOutDev, ConInDev\r
822                           StdErrDev, ConIn or ConOut.\r
823   @param  DevicePath      Console devcie's device path.\r
824   @param  Operation       Variable operations, such as APPEND or DELETE.\r
825 \r
826   @retval EFI_SUCCESS           Variable operates successfully.\r
827   @retval EFI_OUT_OF_RESOURCES  If variable cannot be appended.\r
828   @retval other                 Variable updating failed.\r
829 \r
830 **/\r
831 EFI_STATUS\r
832 ConPlatformUpdateDeviceVariable (\r
833   IN  CHAR16                    *VariableName,\r
834   IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
835   IN  CONPLATFORM_VAR_OPERATION Operation\r
836   )\r
837 {\r
838   EFI_STATUS                Status;\r
839   EFI_DEVICE_PATH_PROTOCOL  *VariableDevicePath;\r
840   EFI_DEVICE_PATH_PROTOCOL  *NewVariableDevicePath;\r
841 \r
842   VariableDevicePath    = NULL;\r
843   NewVariableDevicePath = NULL;\r
844 \r
845   //\r
846   // Get Variable according to variable name.\r
847   // The memory for Variable is allocated within ConPlatformGetVarible(),\r
848   // it is the caller's responsibility to free the memory before return.\r
849   //\r
850   VariableDevicePath = ConPlatformGetVariable (VariableName);\r
851 \r
852   if (Operation != DELETE) {\r
853     //\r
854     // Match specified DevicePath in Console Variable.\r
855     // \r
856     Status = ConPlatformMatchDevicePaths (\r
857               VariableDevicePath,\r
858               DevicePath,\r
859               NULL,\r
860               FALSE\r
861               );\r
862 \r
863     if ((Operation == CHECK) || (!EFI_ERROR (Status))) {\r
864       //\r
865       // The device path is already in the variable\r
866       //\r
867       if (VariableDevicePath != NULL) {\r
868         FreePool (VariableDevicePath);\r
869       }\r
870 \r
871       return Status;\r
872     }\r
873     //\r
874     // The device path is not in variable. Append DevicePath to the\r
875     // environment variable that is a multi-instance device path.\r
876     //\r
877     Status = EFI_SUCCESS;\r
878     NewVariableDevicePath = AppendDevicePathInstance (\r
879                               VariableDevicePath,\r
880                               DevicePath\r
881                               );\r
882     if (NewVariableDevicePath == NULL) {\r
883       Status = EFI_OUT_OF_RESOURCES;\r
884     }\r
885 \r
886   } else {\r
887     //\r
888     // Remove DevicePath from the environment variable that\r
889     // is a multi-instance device path.\r
890     //\r
891     Status = ConPlatformMatchDevicePaths (\r
892               VariableDevicePath,\r
893               DevicePath,\r
894               &NewVariableDevicePath,\r
895               TRUE\r
896               );\r
897   }\r
898 \r
899   if (VariableDevicePath != NULL) {\r
900     FreePool (VariableDevicePath);\r
901   }\r
902 \r
903   if (EFI_ERROR (Status)) {\r
904     return Status;\r
905   }\r
906 \r
907   if (NewVariableDevicePath != NULL) {\r
908     //\r
909     // Update Console Environment Variable.\r
910     //\r
911     Status = gRT->SetVariable (\r
912                     VariableName,\r
913                     &gEfiGlobalVariableGuid,\r
914                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
915                     GetDevicePathSize (NewVariableDevicePath),\r
916                     NewVariableDevicePath\r
917                     );\r
918 \r
919     FreePool (NewVariableDevicePath);\r
920   }\r
921 \r
922   return Status;\r
923 }\r
924 \r
925 /**\r
926   Check if the device is one hot-plug supported.\r
927 \r
928   @param  DriverBindingHandle   Protocol instance pointer.\r
929   @param  ControllerHandle      Handle of device to check.\r
930 \r
931   @retval TRUE                  The devcie is a hot-plug device\r
932   @retval FALSE                 The devcie is not a hot-plug device.\r
933 \r
934 **/\r
935 BOOLEAN\r
936 IsHotPlugDevice (\r
937   EFI_HANDLE    DriverBindingHandle,\r
938   EFI_HANDLE    ControllerHandle\r
939   )\r
940 {\r
941   EFI_STATUS  Status;\r
942 \r
943   //\r
944   // HotPlugDeviceGuid indicates ControllerHandle stands for a hot plug device.\r
945   //\r
946   Status = gBS->OpenProtocol (\r
947                   ControllerHandle,\r
948                   &gEfiHotPlugDeviceGuid,\r
949                   NULL,\r
950                   DriverBindingHandle,\r
951                   ControllerHandle,\r
952                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
953                   );\r
954   if (EFI_ERROR (Status)) {\r
955     return FALSE;\r
956   }\r
957 \r
958   return TRUE;\r
959 }\r