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