878ddf1f |
1 | /*++\r |
2 | \r |
3 | Copyright (c) 2006, 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 | EFI_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 |
31 | EFI_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 |
40 | STATIC\r |
41 | EFI_STATUS\r |
42 | EFIAPI\r |
43 | ConPlatformTextInDriverBindingSupported (\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 |
50 | Routine Description:\r |
51 | Supported \r |
52 | \r |
53 | Arguments:\r |
54 | (Standard DriverBinding Protocol Supported() function)\r |
55 | \r |
56 | Returns:\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 |
70 | STATIC\r |
71 | EFI_STATUS\r |
72 | EFIAPI\r |
73 | ConPlatformTextOutDriverBindingSupported (\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 |
80 | Routine Description:\r |
81 | Supported \r |
82 | \r |
83 | Arguments:\r |
84 | (Standard DriverBinding Protocol Supported() function)\r |
85 | \r |
86 | Returns:\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 |
100 | EFI_STATUS\r |
101 | ConPlatformDriverBindingSupported (\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 |
109 | Routine Description:\r |
110 | Supported \r |
111 | \r |
112 | Arguments:\r |
113 | (Standard DriverBinding Protocol Supported() function)\r |
114 | \r |
115 | Returns:\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 |
164 | STATIC\r |
165 | EFI_STATUS\r |
166 | EFIAPI\r |
167 | ConPlatformTextInDriverBindingStart (\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 |
174 | Routine Description:\r |
175 | \r |
176 | \r |
177 | Arguments:\r |
178 | (Standard DriverBinding Protocol Start() function)\r |
179 | \r |
180 | Returns:\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 |
270 | STATIC\r |
271 | EFI_STATUS\r |
272 | EFIAPI\r |
273 | ConPlatformTextOutDriverBindingStart (\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 |
280 | Routine Description:\r |
281 | \r |
282 | \r |
283 | Arguments:\r |
284 | (Standard DriverBinding Protocol Start() function)\r |
285 | \r |
286 | Returns:\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 |
408 | STATIC\r |
409 | EFI_STATUS\r |
410 | EFIAPI\r |
411 | ConPlatformDriverBindingStop (\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 |
419 | Routine Description:\r |
420 | \r |
421 | Arguments:\r |
422 | (Standard DriverBinding Protocol Stop() function)\r |
423 | \r |
424 | Returns:\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 |
511 | VOID\r |
512 | ConPlatformUnInstallProtocol (\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 |
541 | VOID *\r |
542 | ConPlatformGetVariable (\r |
543 | IN CHAR16 *Name\r |
544 | )\r |
545 | /*++\r |
546 | \r |
547 | Routine 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 |
551 | Arguments:\r |
552 | Name - String part of EFI variable name\r |
553 | \r |
554 | Returns:\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 |
607 | EFI_STATUS\r |
608 | ConPlatformMatchDevicePaths (\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 |
616 | Routine 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 |
620 | Arguments:\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 |
633 | Returns:\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 |
692 | EFI_STATUS\r |
693 | ConPlatformUpdateDeviceVariable (\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 |
700 | Routine Description:\r |
701 | \r |
702 | \r |
703 | Arguments:\r |
704 | \r |
705 | Returns:\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 |
787 | BOOLEAN\r |
788 | IsHotPlugDevice (\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 |