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