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