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