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