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