/src/hbfa-fl/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** @file |
2 | | UEFI handle & protocol handling. |
3 | | |
4 | | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> |
5 | | SPDX-License-Identifier: BSD-2-Clause-Patent |
6 | | |
7 | | **/ |
8 | | |
9 | | #include "DxeMain.h" |
10 | | #include "Handle.h" |
11 | | |
12 | | |
13 | | // |
14 | | // mProtocolDatabase - A list of all protocols in the system. (simple list for now) |
15 | | // gHandleList - A list of all the handles in the system |
16 | | // gProtocolDatabaseLock - Lock to protect the mProtocolDatabase |
17 | | // gHandleDatabaseKey - The Key to show that the handle has been created/modified |
18 | | // |
19 | | LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase); |
20 | | LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList); |
21 | | EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); |
22 | | UINT64 gHandleDatabaseKey = 0; |
23 | | |
24 | | |
25 | | |
26 | | /** |
27 | | Acquire lock on gProtocolDatabaseLock. |
28 | | |
29 | | **/ |
30 | | VOID |
31 | | CoreAcquireProtocolLock ( |
32 | | VOID |
33 | | ) |
34 | 0 | { |
35 | 0 | CoreAcquireLock (&gProtocolDatabaseLock); |
36 | 0 | } |
37 | | |
38 | | |
39 | | |
40 | | /** |
41 | | Release lock on gProtocolDatabaseLock. |
42 | | |
43 | | **/ |
44 | | VOID |
45 | | CoreReleaseProtocolLock ( |
46 | | VOID |
47 | | ) |
48 | 0 | { |
49 | 0 | CoreReleaseLock (&gProtocolDatabaseLock); |
50 | 0 | } |
51 | | |
52 | | |
53 | | |
54 | | /** |
55 | | Check whether a handle is a valid EFI_HANDLE |
56 | | |
57 | | @param UserHandle The handle to check |
58 | | |
59 | | @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE. |
60 | | @retval EFI_SUCCESS The handle is valid EFI_HANDLE. |
61 | | |
62 | | **/ |
63 | | EFI_STATUS |
64 | | CoreValidateHandle ( |
65 | | IN EFI_HANDLE UserHandle |
66 | | ) |
67 | 0 | { |
68 | 0 | IHANDLE *Handle; |
69 | 0 | LIST_ENTRY *Link; |
70 | |
|
71 | 0 | if (UserHandle == NULL) { |
72 | 0 | return EFI_INVALID_PARAMETER; |
73 | 0 | } |
74 | | |
75 | 0 | for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) { |
76 | 0 | Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); |
77 | 0 | if (Handle == (IHANDLE *) UserHandle) { |
78 | 0 | return EFI_SUCCESS; |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | 0 | return EFI_INVALID_PARAMETER; |
83 | 0 | } |
84 | | |
85 | | |
86 | | |
87 | | /** |
88 | | Finds the protocol entry for the requested protocol. |
89 | | The gProtocolDatabaseLock must be owned |
90 | | |
91 | | @param Protocol The ID of the protocol |
92 | | @param Create Create a new entry if not found |
93 | | |
94 | | @return Protocol entry |
95 | | |
96 | | **/ |
97 | | PROTOCOL_ENTRY * |
98 | | CoreFindProtocolEntry ( |
99 | | IN EFI_GUID *Protocol, |
100 | | IN BOOLEAN Create |
101 | | ) |
102 | 0 | { |
103 | 0 | LIST_ENTRY *Link; |
104 | 0 | PROTOCOL_ENTRY *Item; |
105 | 0 | PROTOCOL_ENTRY *ProtEntry; |
106 | |
|
107 | 0 | ASSERT_LOCKED(&gProtocolDatabaseLock); |
108 | | |
109 | | // |
110 | | // Search the database for the matching GUID |
111 | | // |
112 | |
|
113 | 0 | ProtEntry = NULL; |
114 | 0 | for (Link = mProtocolDatabase.ForwardLink; |
115 | 0 | Link != &mProtocolDatabase; |
116 | 0 | Link = Link->ForwardLink) { |
117 | |
|
118 | 0 | Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); |
119 | 0 | if (CompareGuid (&Item->ProtocolID, Protocol)) { |
120 | | |
121 | | // |
122 | | // This is the protocol entry |
123 | | // |
124 | |
|
125 | 0 | ProtEntry = Item; |
126 | 0 | break; |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | | // |
131 | | // If the protocol entry was not found and Create is TRUE, then |
132 | | // allocate a new entry |
133 | | // |
134 | 0 | if ((ProtEntry == NULL) && Create) { |
135 | 0 | ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY)); |
136 | |
|
137 | 0 | if (ProtEntry != NULL) { |
138 | | // |
139 | | // Initialize new protocol entry structure |
140 | | // |
141 | 0 | ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE; |
142 | 0 | CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol); |
143 | 0 | InitializeListHead (&ProtEntry->Protocols); |
144 | 0 | InitializeListHead (&ProtEntry->Notify); |
145 | | |
146 | | // |
147 | | // Add it to protocol database |
148 | | // |
149 | 0 | InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries); |
150 | 0 | } |
151 | 0 | } |
152 | |
|
153 | 0 | return ProtEntry; |
154 | 0 | } |
155 | | |
156 | | |
157 | | |
158 | | /** |
159 | | Finds the protocol instance for the requested handle and protocol. |
160 | | Note: This function doesn't do parameters checking, it's caller's responsibility |
161 | | to pass in valid parameters. |
162 | | |
163 | | @param Handle The handle to search the protocol on |
164 | | @param Protocol GUID of the protocol |
165 | | @param Interface The interface for the protocol being searched |
166 | | |
167 | | @return Protocol instance (NULL: Not found) |
168 | | |
169 | | **/ |
170 | | PROTOCOL_INTERFACE * |
171 | | CoreFindProtocolInterface ( |
172 | | IN IHANDLE *Handle, |
173 | | IN EFI_GUID *Protocol, |
174 | | IN VOID *Interface |
175 | | ) |
176 | 0 | { |
177 | 0 | PROTOCOL_INTERFACE *Prot; |
178 | 0 | PROTOCOL_ENTRY *ProtEntry; |
179 | 0 | LIST_ENTRY *Link; |
180 | |
|
181 | 0 | ASSERT_LOCKED(&gProtocolDatabaseLock); |
182 | 0 | Prot = NULL; |
183 | | |
184 | | // |
185 | | // Lookup the protocol entry for this protocol ID |
186 | | // |
187 | |
|
188 | 0 | ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); |
189 | 0 | if (ProtEntry != NULL) { |
190 | | |
191 | | // |
192 | | // Look at each protocol interface for any matches |
193 | | // |
194 | 0 | for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { |
195 | | |
196 | | // |
197 | | // If this protocol interface matches, remove it |
198 | | // |
199 | 0 | Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); |
200 | 0 | if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { |
201 | 0 | break; |
202 | 0 | } |
203 | | |
204 | 0 | Prot = NULL; |
205 | 0 | } |
206 | 0 | } |
207 | |
|
208 | 0 | return Prot; |
209 | 0 | } |
210 | | |
211 | | |
212 | | /** |
213 | | Removes an event from a register protocol notify list on a protocol. |
214 | | |
215 | | @param Event The event to search for in the protocol |
216 | | database. |
217 | | |
218 | | @return EFI_SUCCESS if the event was found and removed. |
219 | | @return EFI_NOT_FOUND if the event was not found in the protocl database. |
220 | | |
221 | | **/ |
222 | | EFI_STATUS |
223 | | CoreUnregisterProtocolNotifyEvent ( |
224 | | IN EFI_EVENT Event |
225 | | ) |
226 | 0 | { |
227 | 0 | LIST_ENTRY *Link; |
228 | 0 | PROTOCOL_ENTRY *ProtEntry; |
229 | 0 | LIST_ENTRY *NotifyLink; |
230 | 0 | PROTOCOL_NOTIFY *ProtNotify; |
231 | |
|
232 | 0 | CoreAcquireProtocolLock (); |
233 | |
|
234 | 0 | for ( Link = mProtocolDatabase.ForwardLink; |
235 | 0 | Link != &mProtocolDatabase; |
236 | 0 | Link = Link->ForwardLink) { |
237 | |
|
238 | 0 | ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); |
239 | |
|
240 | 0 | for ( NotifyLink = ProtEntry->Notify.ForwardLink; |
241 | 0 | NotifyLink != &ProtEntry->Notify; |
242 | 0 | NotifyLink = NotifyLink->ForwardLink) { |
243 | |
|
244 | 0 | ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); |
245 | |
|
246 | 0 | if (ProtNotify->Event == Event) { |
247 | 0 | RemoveEntryList(&ProtNotify->Link); |
248 | 0 | CoreFreePool(ProtNotify); |
249 | 0 | CoreReleaseProtocolLock (); |
250 | 0 | return EFI_SUCCESS; |
251 | 0 | } |
252 | 0 | } |
253 | 0 | } |
254 | | |
255 | 0 | CoreReleaseProtocolLock (); |
256 | 0 | return EFI_NOT_FOUND; |
257 | 0 | } |
258 | | |
259 | | |
260 | | |
261 | | /** |
262 | | Removes all the events in the protocol database that match Event. |
263 | | |
264 | | @param Event The event to search for in the protocol |
265 | | database. |
266 | | |
267 | | @return EFI_SUCCESS when done searching the entire database. |
268 | | |
269 | | **/ |
270 | | EFI_STATUS |
271 | | CoreUnregisterProtocolNotify ( |
272 | | IN EFI_EVENT Event |
273 | | ) |
274 | 0 | { |
275 | 0 | EFI_STATUS Status; |
276 | |
|
277 | 0 | do { |
278 | 0 | Status = CoreUnregisterProtocolNotifyEvent (Event); |
279 | 0 | } while (!EFI_ERROR (Status)); |
280 | |
|
281 | 0 | return EFI_SUCCESS; |
282 | 0 | } |
283 | | |
284 | | |
285 | | |
286 | | |
287 | | /** |
288 | | Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which |
289 | | Calls the private one which contains a BOOLEAN parameter for notifications |
290 | | |
291 | | @param UserHandle The handle to install the protocol handler on, |
292 | | or NULL if a new handle is to be allocated |
293 | | @param Protocol The protocol to add to the handle |
294 | | @param InterfaceType Indicates whether Interface is supplied in |
295 | | native form. |
296 | | @param Interface The interface for the protocol being added |
297 | | |
298 | | @return Status code |
299 | | |
300 | | **/ |
301 | | EFI_STATUS |
302 | | EFIAPI |
303 | | CoreInstallProtocolInterface ( |
304 | | IN OUT EFI_HANDLE *UserHandle, |
305 | | IN EFI_GUID *Protocol, |
306 | | IN EFI_INTERFACE_TYPE InterfaceType, |
307 | | IN VOID *Interface |
308 | | ) |
309 | 0 | { |
310 | 0 | return CoreInstallProtocolInterfaceNotify ( |
311 | 0 | UserHandle, |
312 | 0 | Protocol, |
313 | 0 | InterfaceType, |
314 | 0 | Interface, |
315 | 0 | TRUE |
316 | 0 | ); |
317 | 0 | } |
318 | | |
319 | | |
320 | | /** |
321 | | Installs a protocol interface into the boot services environment. |
322 | | |
323 | | @param UserHandle The handle to install the protocol handler on, |
324 | | or NULL if a new handle is to be allocated |
325 | | @param Protocol The protocol to add to the handle |
326 | | @param InterfaceType Indicates whether Interface is supplied in |
327 | | native form. |
328 | | @param Interface The interface for the protocol being added |
329 | | @param Notify indicates whether notify the notification list |
330 | | for this protocol |
331 | | |
332 | | @retval EFI_INVALID_PARAMETER Invalid parameter |
333 | | @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate |
334 | | @retval EFI_SUCCESS Protocol interface successfully installed |
335 | | |
336 | | **/ |
337 | | EFI_STATUS |
338 | | CoreInstallProtocolInterfaceNotify ( |
339 | | IN OUT EFI_HANDLE *UserHandle, |
340 | | IN EFI_GUID *Protocol, |
341 | | IN EFI_INTERFACE_TYPE InterfaceType, |
342 | | IN VOID *Interface, |
343 | | IN BOOLEAN Notify |
344 | | ) |
345 | 0 | { |
346 | 0 | PROTOCOL_INTERFACE *Prot; |
347 | 0 | PROTOCOL_ENTRY *ProtEntry; |
348 | 0 | IHANDLE *Handle; |
349 | 0 | EFI_STATUS Status; |
350 | 0 | VOID *ExistingInterface; |
351 | | |
352 | | // |
353 | | // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. |
354 | | // Also added check for invalid UserHandle and Protocol pointers. |
355 | | // |
356 | 0 | if (UserHandle == NULL || Protocol == NULL) { |
357 | 0 | return EFI_INVALID_PARAMETER; |
358 | 0 | } |
359 | | |
360 | 0 | if (InterfaceType != EFI_NATIVE_INTERFACE) { |
361 | 0 | return EFI_INVALID_PARAMETER; |
362 | 0 | } |
363 | | |
364 | | // |
365 | | // Print debug message |
366 | | // |
367 | 0 | DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface)); |
368 | |
|
369 | 0 | Status = EFI_OUT_OF_RESOURCES; |
370 | 0 | Prot = NULL; |
371 | 0 | Handle = NULL; |
372 | |
|
373 | 0 | if (*UserHandle != NULL) { |
374 | 0 | Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); |
375 | 0 | if (!EFI_ERROR (Status)) { |
376 | 0 | return EFI_INVALID_PARAMETER; |
377 | 0 | } |
378 | 0 | } |
379 | | |
380 | | // |
381 | | // Lock the protocol database |
382 | | // |
383 | 0 | CoreAcquireProtocolLock (); |
384 | | |
385 | | // |
386 | | // Lookup the Protocol Entry for the requested protocol |
387 | | // |
388 | 0 | ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); |
389 | 0 | if (ProtEntry == NULL) { |
390 | 0 | goto Done; |
391 | 0 | } |
392 | | |
393 | | // |
394 | | // Allocate a new protocol interface structure |
395 | | // |
396 | 0 | Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE)); |
397 | 0 | if (Prot == NULL) { |
398 | 0 | Status = EFI_OUT_OF_RESOURCES; |
399 | 0 | goto Done; |
400 | 0 | } |
401 | | |
402 | | // |
403 | | // If caller didn't supply a handle, allocate a new one |
404 | | // |
405 | 0 | Handle = (IHANDLE *)*UserHandle; |
406 | 0 | if (Handle == NULL) { |
407 | 0 | Handle = AllocateZeroPool (sizeof(IHANDLE)); |
408 | 0 | if (Handle == NULL) { |
409 | 0 | Status = EFI_OUT_OF_RESOURCES; |
410 | 0 | goto Done; |
411 | 0 | } |
412 | | |
413 | | // |
414 | | // Initialize new handler structure |
415 | | // |
416 | 0 | Handle->Signature = EFI_HANDLE_SIGNATURE; |
417 | 0 | InitializeListHead (&Handle->Protocols); |
418 | | |
419 | | // |
420 | | // Initialize the Key to show that the handle has been created/modified |
421 | | // |
422 | 0 | gHandleDatabaseKey++; |
423 | 0 | Handle->Key = gHandleDatabaseKey; |
424 | | |
425 | | // |
426 | | // Add this handle to the list global list of all handles |
427 | | // in the system |
428 | | // |
429 | 0 | InsertTailList (&gHandleList, &Handle->AllHandles); |
430 | 0 | } else { |
431 | 0 | Status = CoreValidateHandle (Handle); |
432 | 0 | if (EFI_ERROR (Status)) { |
433 | 0 | DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); |
434 | 0 | goto Done; |
435 | 0 | } |
436 | 0 | } |
437 | | |
438 | | // |
439 | | // Each interface that is added must be unique |
440 | | // |
441 | 0 | ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL); |
442 | | |
443 | | // |
444 | | // Initialize the protocol interface structure |
445 | | // |
446 | 0 | Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; |
447 | 0 | Prot->Handle = Handle; |
448 | 0 | Prot->Protocol = ProtEntry; |
449 | 0 | Prot->Interface = Interface; |
450 | | |
451 | | // |
452 | | // Initalize OpenProtocol Data base |
453 | | // |
454 | 0 | InitializeListHead (&Prot->OpenList); |
455 | 0 | Prot->OpenListCount = 0; |
456 | | |
457 | | // |
458 | | // Add this protocol interface to the head of the supported |
459 | | // protocol list for this handle |
460 | | // |
461 | 0 | InsertHeadList (&Handle->Protocols, &Prot->Link); |
462 | | |
463 | | // |
464 | | // Add this protocol interface to the tail of the |
465 | | // protocol entry |
466 | | // |
467 | 0 | InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); |
468 | | |
469 | | // |
470 | | // Notify the notification list for this protocol |
471 | | // |
472 | 0 | if (Notify) { |
473 | 0 | CoreNotifyProtocolEntry (ProtEntry); |
474 | 0 | } |
475 | 0 | Status = EFI_SUCCESS; |
476 | |
|
477 | 0 | Done: |
478 | | // |
479 | | // Done, unlock the database and return |
480 | | // |
481 | 0 | CoreReleaseProtocolLock (); |
482 | 0 | if (!EFI_ERROR (Status)) { |
483 | | // |
484 | | // Return the new handle back to the caller |
485 | | // |
486 | 0 | *UserHandle = Handle; |
487 | 0 | } else { |
488 | | // |
489 | | // There was an error, clean up |
490 | | // |
491 | 0 | if (Prot != NULL) { |
492 | 0 | CoreFreePool (Prot); |
493 | 0 | } |
494 | 0 | DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); |
495 | 0 | } |
496 | |
|
497 | 0 | return Status; |
498 | 0 | } |
499 | | |
500 | | |
501 | | |
502 | | |
503 | | /** |
504 | | Installs a list of protocol interface into the boot services environment. |
505 | | This function calls InstallProtocolInterface() in a loop. If any error |
506 | | occures all the protocols added by this function are removed. This is |
507 | | basically a lib function to save space. |
508 | | |
509 | | @param Handle The pointer to a handle to install the new |
510 | | protocol interfaces on, or a pointer to NULL |
511 | | if a new handle is to be allocated. |
512 | | @param ... EFI_GUID followed by protocol instance. A NULL |
513 | | terminates the list. The pairs are the |
514 | | arguments to InstallProtocolInterface(). All the |
515 | | protocols are added to Handle. |
516 | | |
517 | | @retval EFI_SUCCESS All the protocol interface was installed. |
518 | | @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. |
519 | | @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in |
520 | | the handle database. |
521 | | @retval EFI_INVALID_PARAMETER Handle is NULL. |
522 | | @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. |
523 | | |
524 | | **/ |
525 | | EFI_STATUS |
526 | | EFIAPI |
527 | | CoreInstallMultipleProtocolInterfaces ( |
528 | | IN OUT EFI_HANDLE *Handle, |
529 | | ... |
530 | | ) |
531 | 0 | { |
532 | 0 | VA_LIST Args; |
533 | 0 | EFI_STATUS Status; |
534 | 0 | EFI_GUID *Protocol; |
535 | 0 | VOID *Interface; |
536 | 0 | EFI_TPL OldTpl; |
537 | 0 | UINTN Index; |
538 | 0 | EFI_HANDLE OldHandle; |
539 | 0 | EFI_HANDLE DeviceHandle; |
540 | 0 | EFI_DEVICE_PATH_PROTOCOL *DevicePath; |
541 | |
|
542 | 0 | if (Handle == NULL) { |
543 | 0 | return EFI_INVALID_PARAMETER; |
544 | 0 | } |
545 | | |
546 | | // |
547 | | // Syncronize with notifcations. |
548 | | // |
549 | 0 | OldTpl = CoreRaiseTpl (TPL_NOTIFY); |
550 | 0 | OldHandle = *Handle; |
551 | | |
552 | | // |
553 | | // Check for duplicate device path and install the protocol interfaces |
554 | | // |
555 | 0 | VA_START (Args, Handle); |
556 | 0 | for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { |
557 | | // |
558 | | // If protocol is NULL, then it's the end of the list |
559 | | // |
560 | 0 | Protocol = VA_ARG (Args, EFI_GUID *); |
561 | 0 | if (Protocol == NULL) { |
562 | 0 | break; |
563 | 0 | } |
564 | | |
565 | 0 | Interface = VA_ARG (Args, VOID *); |
566 | | |
567 | | // |
568 | | // Make sure you are installing on top a device path that has already been added. |
569 | | // |
570 | 0 | if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) { |
571 | 0 | DeviceHandle = NULL; |
572 | 0 | DevicePath = Interface; |
573 | 0 | Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle); |
574 | 0 | if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) { |
575 | 0 | Status = EFI_ALREADY_STARTED; |
576 | 0 | continue; |
577 | 0 | } |
578 | 0 | } |
579 | | |
580 | | // |
581 | | // Install it |
582 | | // |
583 | 0 | Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); |
584 | 0 | } |
585 | 0 | VA_END (Args); |
586 | | |
587 | | // |
588 | | // If there was an error, remove all the interfaces that were installed without any errors |
589 | | // |
590 | 0 | if (EFI_ERROR (Status)) { |
591 | | // |
592 | | // Reset the va_arg back to the first argument. |
593 | | // |
594 | 0 | VA_START (Args, Handle); |
595 | 0 | for (; Index > 1; Index--) { |
596 | 0 | Protocol = VA_ARG (Args, EFI_GUID *); |
597 | 0 | Interface = VA_ARG (Args, VOID *); |
598 | 0 | CoreUninstallProtocolInterface (*Handle, Protocol, Interface); |
599 | 0 | } |
600 | 0 | VA_END (Args); |
601 | |
|
602 | 0 | *Handle = OldHandle; |
603 | 0 | } |
604 | | |
605 | | // |
606 | | // Done |
607 | | // |
608 | 0 | CoreRestoreTpl (OldTpl); |
609 | 0 | return Status; |
610 | 0 | } |
611 | | |
612 | | |
613 | | /** |
614 | | Attempts to disconnect all drivers that are using the protocol interface being queried. |
615 | | If failed, reconnect all drivers disconnected. |
616 | | Note: This function doesn't do parameters checking, it's caller's responsibility |
617 | | to pass in valid parameters. |
618 | | |
619 | | @param UserHandle The handle on which the protocol is installed |
620 | | @param Prot The protocol to disconnect drivers from |
621 | | |
622 | | @retval EFI_SUCCESS Drivers using the protocol interface are all |
623 | | disconnected |
624 | | @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers |
625 | | |
626 | | **/ |
627 | | EFI_STATUS |
628 | | CoreDisconnectControllersUsingProtocolInterface ( |
629 | | IN EFI_HANDLE UserHandle, |
630 | | IN PROTOCOL_INTERFACE *Prot |
631 | | ) |
632 | 0 | { |
633 | 0 | EFI_STATUS Status; |
634 | 0 | BOOLEAN ItemFound; |
635 | 0 | LIST_ENTRY *Link; |
636 | 0 | OPEN_PROTOCOL_DATA *OpenData; |
637 | |
|
638 | 0 | Status = EFI_SUCCESS; |
639 | | |
640 | | // |
641 | | // Attempt to disconnect all drivers from this protocol interface |
642 | | // |
643 | 0 | do { |
644 | 0 | ItemFound = FALSE; |
645 | 0 | for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { |
646 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
647 | 0 | if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { |
648 | 0 | CoreReleaseProtocolLock (); |
649 | 0 | Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); |
650 | 0 | CoreAcquireProtocolLock (); |
651 | 0 | if (!EFI_ERROR (Status)) { |
652 | 0 | ItemFound = TRUE; |
653 | 0 | } |
654 | 0 | break; |
655 | 0 | } |
656 | 0 | } |
657 | 0 | } while (ItemFound); |
658 | |
|
659 | 0 | if (!EFI_ERROR (Status)) { |
660 | | // |
661 | | // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items |
662 | | // |
663 | 0 | for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) { |
664 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
665 | 0 | if ((OpenData->Attributes & |
666 | 0 | (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) { |
667 | 0 | Link = RemoveEntryList (&OpenData->Link); |
668 | 0 | Prot->OpenListCount--; |
669 | 0 | CoreFreePool (OpenData); |
670 | 0 | } else { |
671 | 0 | Link = Link->ForwardLink; |
672 | 0 | } |
673 | 0 | } |
674 | 0 | } |
675 | | |
676 | | // |
677 | | // If there are errors or still has open items in the list, then reconnect all the drivers and return an error |
678 | | // |
679 | 0 | if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) { |
680 | 0 | CoreReleaseProtocolLock (); |
681 | 0 | CoreConnectController (UserHandle, NULL, NULL, TRUE); |
682 | 0 | CoreAcquireProtocolLock (); |
683 | 0 | Status = EFI_ACCESS_DENIED; |
684 | 0 | } |
685 | |
|
686 | 0 | return Status; |
687 | 0 | } |
688 | | |
689 | | |
690 | | |
691 | | /** |
692 | | Uninstalls all instances of a protocol:interfacer from a handle. |
693 | | If the last protocol interface is remove from the handle, the |
694 | | handle is freed. |
695 | | |
696 | | @param UserHandle The handle to remove the protocol handler from |
697 | | @param Protocol The protocol, of protocol:interface, to remove |
698 | | @param Interface The interface, of protocol:interface, to remove |
699 | | |
700 | | @retval EFI_INVALID_PARAMETER Protocol is NULL. |
701 | | @retval EFI_SUCCESS Protocol interface successfully uninstalled. |
702 | | |
703 | | **/ |
704 | | EFI_STATUS |
705 | | EFIAPI |
706 | | CoreUninstallProtocolInterface ( |
707 | | IN EFI_HANDLE UserHandle, |
708 | | IN EFI_GUID *Protocol, |
709 | | IN VOID *Interface |
710 | | ) |
711 | 0 | { |
712 | 0 | EFI_STATUS Status; |
713 | 0 | IHANDLE *Handle; |
714 | 0 | PROTOCOL_INTERFACE *Prot; |
715 | | |
716 | | // |
717 | | // Check that Protocol is valid |
718 | | // |
719 | 0 | if (Protocol == NULL) { |
720 | 0 | return EFI_INVALID_PARAMETER; |
721 | 0 | } |
722 | | |
723 | | // |
724 | | // Check that UserHandle is a valid handle |
725 | | // |
726 | 0 | Status = CoreValidateHandle (UserHandle); |
727 | 0 | if (EFI_ERROR (Status)) { |
728 | 0 | return Status; |
729 | 0 | } |
730 | | |
731 | | // |
732 | | // Lock the protocol database |
733 | | // |
734 | 0 | CoreAcquireProtocolLock (); |
735 | | |
736 | | // |
737 | | // Check that Protocol exists on UserHandle, and Interface matches the interface in the database |
738 | | // |
739 | 0 | Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface); |
740 | 0 | if (Prot == NULL) { |
741 | 0 | Status = EFI_NOT_FOUND; |
742 | 0 | goto Done; |
743 | 0 | } |
744 | | |
745 | | // |
746 | | // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed |
747 | | // |
748 | 0 | Status = CoreDisconnectControllersUsingProtocolInterface ( |
749 | 0 | UserHandle, |
750 | 0 | Prot |
751 | 0 | ); |
752 | 0 | if (EFI_ERROR (Status)) { |
753 | | // |
754 | | // One or more drivers refused to release, so return the error |
755 | | // |
756 | 0 | goto Done; |
757 | 0 | } |
758 | | |
759 | | // |
760 | | // Remove the protocol interface from the protocol |
761 | | // |
762 | 0 | Status = EFI_NOT_FOUND; |
763 | 0 | Handle = (IHANDLE *)UserHandle; |
764 | 0 | Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface); |
765 | |
|
766 | 0 | if (Prot != NULL) { |
767 | | // |
768 | | // Update the Key to show that the handle has been created/modified |
769 | | // |
770 | 0 | gHandleDatabaseKey++; |
771 | 0 | Handle->Key = gHandleDatabaseKey; |
772 | | |
773 | | // |
774 | | // Remove the protocol interface from the handle |
775 | | // |
776 | 0 | RemoveEntryList (&Prot->Link); |
777 | | |
778 | | // |
779 | | // Free the memory |
780 | | // |
781 | 0 | Prot->Signature = 0; |
782 | 0 | CoreFreePool (Prot); |
783 | 0 | Status = EFI_SUCCESS; |
784 | 0 | } |
785 | | |
786 | | // |
787 | | // If there are no more handlers for the handle, free the handle |
788 | | // |
789 | 0 | if (IsListEmpty (&Handle->Protocols)) { |
790 | 0 | Handle->Signature = 0; |
791 | 0 | RemoveEntryList (&Handle->AllHandles); |
792 | 0 | CoreFreePool (Handle); |
793 | 0 | } |
794 | |
|
795 | 0 | Done: |
796 | | // |
797 | | // Done, unlock the database and return |
798 | | // |
799 | 0 | CoreReleaseProtocolLock (); |
800 | 0 | return Status; |
801 | 0 | } |
802 | | |
803 | | |
804 | | |
805 | | |
806 | | /** |
807 | | Uninstalls a list of protocol interface in the boot services environment. |
808 | | This function calls UnisatllProtocolInterface() in a loop. This is |
809 | | basically a lib function to save space. |
810 | | |
811 | | @param Handle The handle to uninstall the protocol |
812 | | @param ... EFI_GUID followed by protocol instance. A NULL |
813 | | terminates the list. The pairs are the |
814 | | arguments to UninstallProtocolInterface(). All |
815 | | the protocols are added to Handle. |
816 | | |
817 | | @return Status code |
818 | | |
819 | | **/ |
820 | | EFI_STATUS |
821 | | EFIAPI |
822 | | CoreUninstallMultipleProtocolInterfaces ( |
823 | | IN EFI_HANDLE Handle, |
824 | | ... |
825 | | ) |
826 | 0 | { |
827 | 0 | EFI_STATUS Status; |
828 | 0 | VA_LIST Args; |
829 | 0 | EFI_GUID *Protocol; |
830 | 0 | VOID *Interface; |
831 | 0 | UINTN Index; |
832 | |
|
833 | 0 | VA_START (Args, Handle); |
834 | 0 | for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { |
835 | | // |
836 | | // If protocol is NULL, then it's the end of the list |
837 | | // |
838 | 0 | Protocol = VA_ARG (Args, EFI_GUID *); |
839 | 0 | if (Protocol == NULL) { |
840 | 0 | break; |
841 | 0 | } |
842 | | |
843 | 0 | Interface = VA_ARG (Args, VOID *); |
844 | | |
845 | | // |
846 | | // Uninstall it |
847 | | // |
848 | 0 | Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface); |
849 | 0 | } |
850 | 0 | VA_END (Args); |
851 | | |
852 | | // |
853 | | // If there was an error, add all the interfaces that were |
854 | | // uninstalled without any errors |
855 | | // |
856 | 0 | if (EFI_ERROR (Status)) { |
857 | | // |
858 | | // Reset the va_arg back to the first argument. |
859 | | // |
860 | 0 | VA_START (Args, Handle); |
861 | 0 | for (; Index > 1; Index--) { |
862 | 0 | Protocol = VA_ARG(Args, EFI_GUID *); |
863 | 0 | Interface = VA_ARG(Args, VOID *); |
864 | 0 | CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); |
865 | 0 | } |
866 | 0 | VA_END (Args); |
867 | 0 | } |
868 | |
|
869 | 0 | return Status; |
870 | 0 | } |
871 | | |
872 | | |
873 | | /** |
874 | | Locate a certain GUID protocol interface in a Handle's protocols. |
875 | | |
876 | | @param UserHandle The handle to obtain the protocol interface on |
877 | | @param Protocol The GUID of the protocol |
878 | | |
879 | | @return The requested protocol interface for the handle |
880 | | |
881 | | **/ |
882 | | PROTOCOL_INTERFACE * |
883 | | CoreGetProtocolInterface ( |
884 | | IN EFI_HANDLE UserHandle, |
885 | | IN EFI_GUID *Protocol |
886 | | ) |
887 | 0 | { |
888 | 0 | EFI_STATUS Status; |
889 | 0 | PROTOCOL_ENTRY *ProtEntry; |
890 | 0 | PROTOCOL_INTERFACE *Prot; |
891 | 0 | IHANDLE *Handle; |
892 | 0 | LIST_ENTRY *Link; |
893 | |
|
894 | 0 | Status = CoreValidateHandle (UserHandle); |
895 | 0 | if (EFI_ERROR (Status)) { |
896 | 0 | return NULL; |
897 | 0 | } |
898 | | |
899 | 0 | Handle = (IHANDLE *)UserHandle; |
900 | | |
901 | | // |
902 | | // Look at each protocol interface for a match |
903 | | // |
904 | 0 | for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { |
905 | 0 | Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); |
906 | 0 | ProtEntry = Prot->Protocol; |
907 | 0 | if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) { |
908 | 0 | return Prot; |
909 | 0 | } |
910 | 0 | } |
911 | 0 | return NULL; |
912 | 0 | } |
913 | | |
914 | | |
915 | | |
916 | | /** |
917 | | Queries a handle to determine if it supports a specified protocol. |
918 | | |
919 | | @param UserHandle The handle being queried. |
920 | | @param Protocol The published unique identifier of the protocol. |
921 | | @param Interface Supplies the address where a pointer to the |
922 | | corresponding Protocol Interface is returned. |
923 | | |
924 | | @retval EFI_SUCCESS The interface information for the specified protocol was returned. |
925 | | @retval EFI_UNSUPPORTED The device does not support the specified protocol. |
926 | | @retval EFI_INVALID_PARAMETER Handle is NULL.. |
927 | | @retval EFI_INVALID_PARAMETER Protocol is NULL. |
928 | | @retval EFI_INVALID_PARAMETER Interface is NULL. |
929 | | |
930 | | **/ |
931 | | EFI_STATUS |
932 | | EFIAPI |
933 | | CoreHandleProtocol ( |
934 | | IN EFI_HANDLE UserHandle, |
935 | | IN EFI_GUID *Protocol, |
936 | | OUT VOID **Interface |
937 | | ) |
938 | 0 | { |
939 | 0 | return CoreOpenProtocol ( |
940 | 0 | UserHandle, |
941 | 0 | Protocol, |
942 | 0 | Interface, |
943 | 0 | gDxeCoreImageHandle, |
944 | 0 | NULL, |
945 | 0 | EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL |
946 | 0 | ); |
947 | 0 | } |
948 | | |
949 | | |
950 | | |
951 | | /** |
952 | | Locates the installed protocol handler for the handle, and |
953 | | invokes it to obtain the protocol interface. Usage information |
954 | | is registered in the protocol data base. |
955 | | |
956 | | @param UserHandle The handle to obtain the protocol interface on |
957 | | @param Protocol The ID of the protocol |
958 | | @param Interface The location to return the protocol interface |
959 | | @param ImageHandle The handle of the Image that is opening the |
960 | | protocol interface specified by Protocol and |
961 | | Interface. |
962 | | @param ControllerHandle The controller handle that is requiring this |
963 | | interface. |
964 | | @param Attributes The open mode of the protocol interface |
965 | | specified by Handle and Protocol. |
966 | | |
967 | | @retval EFI_INVALID_PARAMETER Protocol is NULL. |
968 | | @retval EFI_SUCCESS Get the protocol interface. |
969 | | |
970 | | **/ |
971 | | EFI_STATUS |
972 | | EFIAPI |
973 | | CoreOpenProtocol ( |
974 | | IN EFI_HANDLE UserHandle, |
975 | | IN EFI_GUID *Protocol, |
976 | | OUT VOID **Interface OPTIONAL, |
977 | | IN EFI_HANDLE ImageHandle, |
978 | | IN EFI_HANDLE ControllerHandle, |
979 | | IN UINT32 Attributes |
980 | | ) |
981 | 0 | { |
982 | 0 | EFI_STATUS Status; |
983 | 0 | PROTOCOL_INTERFACE *Prot; |
984 | 0 | LIST_ENTRY *Link; |
985 | 0 | OPEN_PROTOCOL_DATA *OpenData; |
986 | 0 | BOOLEAN ByDriver; |
987 | 0 | BOOLEAN Exclusive; |
988 | 0 | BOOLEAN Disconnect; |
989 | 0 | BOOLEAN ExactMatch; |
990 | | |
991 | | // |
992 | | // Check for invalid Protocol |
993 | | // |
994 | 0 | if (Protocol == NULL) { |
995 | 0 | return EFI_INVALID_PARAMETER; |
996 | 0 | } |
997 | | |
998 | | // |
999 | | // Check for invalid Interface |
1000 | | // |
1001 | 0 | if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) { |
1002 | 0 | return EFI_INVALID_PARAMETER; |
1003 | 0 | } |
1004 | | |
1005 | | // |
1006 | | // Check for invalid UserHandle |
1007 | | // |
1008 | 0 | Status = CoreValidateHandle (UserHandle); |
1009 | 0 | if (EFI_ERROR (Status)) { |
1010 | 0 | return Status; |
1011 | 0 | } |
1012 | | |
1013 | | // |
1014 | | // Check for invalid Attributes |
1015 | | // |
1016 | 0 | switch (Attributes) { |
1017 | 0 | case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : |
1018 | 0 | Status = CoreValidateHandle (ImageHandle); |
1019 | 0 | if (EFI_ERROR (Status)) { |
1020 | 0 | return Status; |
1021 | 0 | } |
1022 | 0 | Status = CoreValidateHandle (ControllerHandle); |
1023 | 0 | if (EFI_ERROR (Status)) { |
1024 | 0 | return Status; |
1025 | 0 | } |
1026 | 0 | if (UserHandle == ControllerHandle) { |
1027 | 0 | return EFI_INVALID_PARAMETER; |
1028 | 0 | } |
1029 | 0 | break; |
1030 | 0 | case EFI_OPEN_PROTOCOL_BY_DRIVER : |
1031 | 0 | case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : |
1032 | 0 | Status = CoreValidateHandle (ImageHandle); |
1033 | 0 | if (EFI_ERROR (Status)) { |
1034 | 0 | return Status; |
1035 | 0 | } |
1036 | 0 | Status = CoreValidateHandle (ControllerHandle); |
1037 | 0 | if (EFI_ERROR (Status)) { |
1038 | 0 | return Status; |
1039 | 0 | } |
1040 | 0 | break; |
1041 | 0 | case EFI_OPEN_PROTOCOL_EXCLUSIVE : |
1042 | 0 | Status = CoreValidateHandle (ImageHandle); |
1043 | 0 | if (EFI_ERROR (Status)) { |
1044 | 0 | return Status; |
1045 | 0 | } |
1046 | 0 | break; |
1047 | 0 | case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : |
1048 | 0 | case EFI_OPEN_PROTOCOL_GET_PROTOCOL : |
1049 | 0 | case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : |
1050 | 0 | break; |
1051 | 0 | default: |
1052 | 0 | return EFI_INVALID_PARAMETER; |
1053 | 0 | } |
1054 | | |
1055 | | // |
1056 | | // Lock the protocol database |
1057 | | // |
1058 | 0 | CoreAcquireProtocolLock (); |
1059 | | |
1060 | | // |
1061 | | // Look at each protocol interface for a match |
1062 | | // |
1063 | 0 | Prot = CoreGetProtocolInterface (UserHandle, Protocol); |
1064 | 0 | if (Prot == NULL) { |
1065 | 0 | Status = EFI_UNSUPPORTED; |
1066 | 0 | goto Done; |
1067 | 0 | } |
1068 | | |
1069 | 0 | Status = EFI_SUCCESS; |
1070 | |
|
1071 | 0 | ByDriver = FALSE; |
1072 | 0 | Exclusive = FALSE; |
1073 | 0 | for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { |
1074 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
1075 | 0 | ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) && |
1076 | 0 | (OpenData->Attributes == Attributes) && |
1077 | 0 | (OpenData->ControllerHandle == ControllerHandle)); |
1078 | 0 | if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { |
1079 | 0 | ByDriver = TRUE; |
1080 | 0 | if (ExactMatch) { |
1081 | 0 | Status = EFI_ALREADY_STARTED; |
1082 | 0 | goto Done; |
1083 | 0 | } |
1084 | 0 | } |
1085 | 0 | if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) { |
1086 | 0 | Exclusive = TRUE; |
1087 | 0 | } else if (ExactMatch) { |
1088 | 0 | OpenData->OpenCount++; |
1089 | 0 | Status = EFI_SUCCESS; |
1090 | 0 | goto Done; |
1091 | 0 | } |
1092 | 0 | } |
1093 | | |
1094 | | // |
1095 | | // ByDriver TRUE -> A driver is managing (UserHandle, Protocol) |
1096 | | // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol) |
1097 | | // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol) |
1098 | | // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol) |
1099 | | // |
1100 | | |
1101 | 0 | switch (Attributes) { |
1102 | 0 | case EFI_OPEN_PROTOCOL_BY_DRIVER : |
1103 | 0 | if (Exclusive || ByDriver) { |
1104 | 0 | Status = EFI_ACCESS_DENIED; |
1105 | 0 | goto Done; |
1106 | 0 | } |
1107 | 0 | break; |
1108 | 0 | case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : |
1109 | 0 | case EFI_OPEN_PROTOCOL_EXCLUSIVE : |
1110 | 0 | if (Exclusive) { |
1111 | 0 | Status = EFI_ACCESS_DENIED; |
1112 | 0 | goto Done; |
1113 | 0 | } |
1114 | 0 | if (ByDriver) { |
1115 | 0 | do { |
1116 | 0 | Disconnect = FALSE; |
1117 | 0 | for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { |
1118 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
1119 | 0 | if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { |
1120 | 0 | Disconnect = TRUE; |
1121 | 0 | CoreReleaseProtocolLock (); |
1122 | 0 | Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); |
1123 | 0 | CoreAcquireProtocolLock (); |
1124 | 0 | if (EFI_ERROR (Status)) { |
1125 | 0 | Status = EFI_ACCESS_DENIED; |
1126 | 0 | goto Done; |
1127 | 0 | } else { |
1128 | 0 | break; |
1129 | 0 | } |
1130 | 0 | } |
1131 | 0 | } |
1132 | 0 | } while (Disconnect); |
1133 | 0 | } |
1134 | 0 | break; |
1135 | 0 | case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : |
1136 | 0 | case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : |
1137 | 0 | case EFI_OPEN_PROTOCOL_GET_PROTOCOL : |
1138 | 0 | case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : |
1139 | 0 | break; |
1140 | 0 | } |
1141 | | |
1142 | 0 | if (ImageHandle == NULL) { |
1143 | 0 | Status = EFI_SUCCESS; |
1144 | 0 | goto Done; |
1145 | 0 | } |
1146 | | // |
1147 | | // Create new entry |
1148 | | // |
1149 | 0 | OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA)); |
1150 | 0 | if (OpenData == NULL) { |
1151 | 0 | Status = EFI_OUT_OF_RESOURCES; |
1152 | 0 | } else { |
1153 | 0 | OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE; |
1154 | 0 | OpenData->AgentHandle = ImageHandle; |
1155 | 0 | OpenData->ControllerHandle = ControllerHandle; |
1156 | 0 | OpenData->Attributes = Attributes; |
1157 | 0 | OpenData->OpenCount = 1; |
1158 | 0 | InsertTailList (&Prot->OpenList, &OpenData->Link); |
1159 | 0 | Prot->OpenListCount++; |
1160 | 0 | Status = EFI_SUCCESS; |
1161 | 0 | } |
1162 | |
|
1163 | 0 | Done: |
1164 | |
|
1165 | 0 | if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { |
1166 | | // |
1167 | | // Keep Interface unmodified in case of any Error |
1168 | | // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED. |
1169 | | // |
1170 | 0 | if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) { |
1171 | | // |
1172 | | // According to above logic, if 'Prot' is NULL, then the 'Status' must be |
1173 | | // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot' |
1174 | | // must be not NULL. |
1175 | | // |
1176 | | // The ASSERT here is for addressing a false positive NULL pointer |
1177 | | // dereference issue raised from static analysis. |
1178 | | // |
1179 | 0 | ASSERT (Prot != NULL); |
1180 | | // |
1181 | | // EFI_ALREADY_STARTED is not an error for bus driver. |
1182 | | // Return the corresponding protocol interface. |
1183 | | // |
1184 | 0 | *Interface = Prot->Interface; |
1185 | 0 | } else if (Status == EFI_UNSUPPORTED) { |
1186 | | // |
1187 | | // Return NULL Interface if Unsupported Protocol. |
1188 | | // |
1189 | 0 | *Interface = NULL; |
1190 | 0 | } |
1191 | 0 | } |
1192 | | |
1193 | | // |
1194 | | // Done. Release the database lock and return |
1195 | | // |
1196 | 0 | CoreReleaseProtocolLock (); |
1197 | 0 | return Status; |
1198 | 0 | } |
1199 | | |
1200 | | |
1201 | | |
1202 | | /** |
1203 | | Closes a protocol on a handle that was opened using OpenProtocol(). |
1204 | | |
1205 | | @param UserHandle The handle for the protocol interface that was |
1206 | | previously opened with OpenProtocol(), and is |
1207 | | now being closed. |
1208 | | @param Protocol The published unique identifier of the protocol. |
1209 | | It is the caller's responsibility to pass in a |
1210 | | valid GUID. |
1211 | | @param AgentHandle The handle of the agent that is closing the |
1212 | | protocol interface. |
1213 | | @param ControllerHandle If the agent that opened a protocol is a driver |
1214 | | that follows the EFI Driver Model, then this |
1215 | | parameter is the controller handle that required |
1216 | | the protocol interface. If the agent does not |
1217 | | follow the EFI Driver Model, then this parameter |
1218 | | is optional and may be NULL. |
1219 | | |
1220 | | @retval EFI_SUCCESS The protocol instance was closed. |
1221 | | @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a |
1222 | | valid EFI_HANDLE. |
1223 | | @retval EFI_NOT_FOUND Can not find the specified protocol or |
1224 | | AgentHandle. |
1225 | | |
1226 | | **/ |
1227 | | EFI_STATUS |
1228 | | EFIAPI |
1229 | | CoreCloseProtocol ( |
1230 | | IN EFI_HANDLE UserHandle, |
1231 | | IN EFI_GUID *Protocol, |
1232 | | IN EFI_HANDLE AgentHandle, |
1233 | | IN EFI_HANDLE ControllerHandle |
1234 | | ) |
1235 | 0 | { |
1236 | 0 | EFI_STATUS Status; |
1237 | 0 | PROTOCOL_INTERFACE *ProtocolInterface; |
1238 | 0 | LIST_ENTRY *Link; |
1239 | 0 | OPEN_PROTOCOL_DATA *OpenData; |
1240 | | |
1241 | | // |
1242 | | // Check for invalid parameters |
1243 | | // |
1244 | 0 | Status = CoreValidateHandle (UserHandle); |
1245 | 0 | if (EFI_ERROR (Status)) { |
1246 | 0 | return Status; |
1247 | 0 | } |
1248 | 0 | Status = CoreValidateHandle (AgentHandle); |
1249 | 0 | if (EFI_ERROR (Status)) { |
1250 | 0 | return Status; |
1251 | 0 | } |
1252 | 0 | if (ControllerHandle != NULL) { |
1253 | 0 | Status = CoreValidateHandle (ControllerHandle); |
1254 | 0 | if (EFI_ERROR (Status)) { |
1255 | 0 | return Status; |
1256 | 0 | } |
1257 | 0 | } |
1258 | 0 | if (Protocol == NULL) { |
1259 | 0 | return EFI_INVALID_PARAMETER; |
1260 | 0 | } |
1261 | | |
1262 | | // |
1263 | | // Lock the protocol database |
1264 | | // |
1265 | 0 | CoreAcquireProtocolLock (); |
1266 | | |
1267 | | // |
1268 | | // Look at each protocol interface for a match |
1269 | | // |
1270 | 0 | Status = EFI_NOT_FOUND; |
1271 | 0 | ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); |
1272 | 0 | if (ProtocolInterface == NULL) { |
1273 | 0 | goto Done; |
1274 | 0 | } |
1275 | | |
1276 | | // |
1277 | | // Walk the Open data base looking for AgentHandle |
1278 | | // |
1279 | 0 | Link = ProtocolInterface->OpenList.ForwardLink; |
1280 | 0 | while (Link != &ProtocolInterface->OpenList) { |
1281 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
1282 | 0 | Link = Link->ForwardLink; |
1283 | 0 | if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) { |
1284 | 0 | RemoveEntryList (&OpenData->Link); |
1285 | 0 | ProtocolInterface->OpenListCount--; |
1286 | 0 | CoreFreePool (OpenData); |
1287 | 0 | Status = EFI_SUCCESS; |
1288 | 0 | } |
1289 | 0 | } |
1290 | |
|
1291 | 0 | Done: |
1292 | | // |
1293 | | // Done. Release the database lock and return. |
1294 | | // |
1295 | 0 | CoreReleaseProtocolLock (); |
1296 | 0 | return Status; |
1297 | 0 | } |
1298 | | |
1299 | | |
1300 | | |
1301 | | |
1302 | | /** |
1303 | | Return information about Opened protocols in the system |
1304 | | |
1305 | | @param UserHandle The handle to close the protocol interface on |
1306 | | @param Protocol The ID of the protocol |
1307 | | @param EntryBuffer A pointer to a buffer of open protocol information in the |
1308 | | form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. |
1309 | | @param EntryCount Number of EntryBuffer entries |
1310 | | |
1311 | | @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, |
1312 | | and the number of entries was returned EntryCount. |
1313 | | @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol. |
1314 | | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. |
1315 | | |
1316 | | **/ |
1317 | | EFI_STATUS |
1318 | | EFIAPI |
1319 | | CoreOpenProtocolInformation ( |
1320 | | IN EFI_HANDLE UserHandle, |
1321 | | IN EFI_GUID *Protocol, |
1322 | | OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, |
1323 | | OUT UINTN *EntryCount |
1324 | | ) |
1325 | 0 | { |
1326 | 0 | EFI_STATUS Status; |
1327 | 0 | PROTOCOL_INTERFACE *ProtocolInterface; |
1328 | 0 | LIST_ENTRY *Link; |
1329 | 0 | OPEN_PROTOCOL_DATA *OpenData; |
1330 | 0 | EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer; |
1331 | 0 | UINTN Count; |
1332 | 0 | UINTN Size; |
1333 | |
|
1334 | 0 | *EntryBuffer = NULL; |
1335 | 0 | *EntryCount = 0; |
1336 | | |
1337 | | // |
1338 | | // Lock the protocol database |
1339 | | // |
1340 | 0 | CoreAcquireProtocolLock (); |
1341 | | |
1342 | | // |
1343 | | // Look at each protocol interface for a match |
1344 | | // |
1345 | 0 | Status = EFI_NOT_FOUND; |
1346 | 0 | ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); |
1347 | 0 | if (ProtocolInterface == NULL) { |
1348 | 0 | goto Done; |
1349 | 0 | } |
1350 | | |
1351 | | // |
1352 | | // Count the number of Open Entries |
1353 | | // |
1354 | 0 | for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; |
1355 | 0 | (Link != &ProtocolInterface->OpenList) ; |
1356 | 0 | Link = Link->ForwardLink ) { |
1357 | 0 | Count++; |
1358 | 0 | } |
1359 | |
|
1360 | 0 | ASSERT (Count == ProtocolInterface->OpenListCount); |
1361 | |
|
1362 | 0 | if (Count == 0) { |
1363 | 0 | Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); |
1364 | 0 | } else { |
1365 | 0 | Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); |
1366 | 0 | } |
1367 | |
|
1368 | 0 | Buffer = AllocatePool (Size); |
1369 | 0 | if (Buffer == NULL) { |
1370 | 0 | Status = EFI_OUT_OF_RESOURCES; |
1371 | 0 | goto Done; |
1372 | 0 | } |
1373 | | |
1374 | 0 | Status = EFI_SUCCESS; |
1375 | 0 | for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; |
1376 | 0 | (Link != &ProtocolInterface->OpenList); |
1377 | 0 | Link = Link->ForwardLink, Count++ ) { |
1378 | 0 | OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); |
1379 | |
|
1380 | 0 | Buffer[Count].AgentHandle = OpenData->AgentHandle; |
1381 | 0 | Buffer[Count].ControllerHandle = OpenData->ControllerHandle; |
1382 | 0 | Buffer[Count].Attributes = OpenData->Attributes; |
1383 | 0 | Buffer[Count].OpenCount = OpenData->OpenCount; |
1384 | 0 | } |
1385 | |
|
1386 | 0 | *EntryBuffer = Buffer; |
1387 | 0 | *EntryCount = Count; |
1388 | |
|
1389 | 0 | Done: |
1390 | | // |
1391 | | // Done. Release the database lock. |
1392 | | // |
1393 | 0 | CoreReleaseProtocolLock (); |
1394 | 0 | return Status; |
1395 | 0 | } |
1396 | | |
1397 | | |
1398 | | |
1399 | | |
1400 | | /** |
1401 | | Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated |
1402 | | from pool. |
1403 | | |
1404 | | @param UserHandle The handle from which to retrieve the list of |
1405 | | protocol interface GUIDs. |
1406 | | @param ProtocolBuffer A pointer to the list of protocol interface GUID |
1407 | | pointers that are installed on Handle. |
1408 | | @param ProtocolBufferCount A pointer to the number of GUID pointers present |
1409 | | in ProtocolBuffer. |
1410 | | |
1411 | | @retval EFI_SUCCESS The list of protocol interface GUIDs installed |
1412 | | on Handle was returned in ProtocolBuffer. The |
1413 | | number of protocol interface GUIDs was returned |
1414 | | in ProtocolBufferCount. |
1415 | | @retval EFI_INVALID_PARAMETER Handle is NULL. |
1416 | | @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. |
1417 | | @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL. |
1418 | | @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. |
1419 | | @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the |
1420 | | results. |
1421 | | |
1422 | | **/ |
1423 | | EFI_STATUS |
1424 | | EFIAPI |
1425 | | CoreProtocolsPerHandle ( |
1426 | | IN EFI_HANDLE UserHandle, |
1427 | | OUT EFI_GUID ***ProtocolBuffer, |
1428 | | OUT UINTN *ProtocolBufferCount |
1429 | | ) |
1430 | 0 | { |
1431 | 0 | EFI_STATUS Status; |
1432 | 0 | IHANDLE *Handle; |
1433 | 0 | PROTOCOL_INTERFACE *Prot; |
1434 | 0 | LIST_ENTRY *Link; |
1435 | 0 | UINTN ProtocolCount; |
1436 | 0 | EFI_GUID **Buffer; |
1437 | |
|
1438 | 0 | Status = CoreValidateHandle (UserHandle); |
1439 | 0 | if (EFI_ERROR (Status)) { |
1440 | 0 | return Status; |
1441 | 0 | } |
1442 | | |
1443 | 0 | Handle = (IHANDLE *)UserHandle; |
1444 | |
|
1445 | 0 | if (ProtocolBuffer == NULL) { |
1446 | 0 | return EFI_INVALID_PARAMETER; |
1447 | 0 | } |
1448 | | |
1449 | 0 | if (ProtocolBufferCount == NULL) { |
1450 | 0 | return EFI_INVALID_PARAMETER; |
1451 | 0 | } |
1452 | | |
1453 | 0 | *ProtocolBufferCount = 0; |
1454 | |
|
1455 | 0 | ProtocolCount = 0; |
1456 | |
|
1457 | 0 | CoreAcquireProtocolLock (); |
1458 | |
|
1459 | 0 | for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { |
1460 | 0 | ProtocolCount++; |
1461 | 0 | } |
1462 | | |
1463 | | // |
1464 | | // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE |
1465 | | // |
1466 | 0 | if (ProtocolCount == 0) { |
1467 | 0 | Status = EFI_INVALID_PARAMETER; |
1468 | 0 | goto Done; |
1469 | 0 | } |
1470 | | |
1471 | 0 | Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount); |
1472 | 0 | if (Buffer == NULL) { |
1473 | 0 | Status = EFI_OUT_OF_RESOURCES; |
1474 | 0 | goto Done; |
1475 | 0 | } |
1476 | | |
1477 | 0 | *ProtocolBuffer = Buffer; |
1478 | 0 | *ProtocolBufferCount = ProtocolCount; |
1479 | |
|
1480 | 0 | for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0; |
1481 | 0 | Link != &Handle->Protocols; |
1482 | 0 | Link = Link->ForwardLink, ProtocolCount++) { |
1483 | 0 | Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); |
1484 | 0 | Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID); |
1485 | 0 | } |
1486 | 0 | Status = EFI_SUCCESS; |
1487 | |
|
1488 | 0 | Done: |
1489 | 0 | CoreReleaseProtocolLock (); |
1490 | 0 | return Status; |
1491 | 0 | } |
1492 | | |
1493 | | |
1494 | | |
1495 | | /** |
1496 | | return handle database key. |
1497 | | |
1498 | | |
1499 | | @return Handle database key. |
1500 | | |
1501 | | **/ |
1502 | | UINT64 |
1503 | | CoreGetHandleDatabaseKey ( |
1504 | | VOID |
1505 | | ) |
1506 | 0 | { |
1507 | 0 | return gHandleDatabaseKey; |
1508 | 0 | } |
1509 | | |
1510 | | |
1511 | | |
1512 | | /** |
1513 | | Go connect any handles that were created or modified while a image executed. |
1514 | | |
1515 | | @param Key The Key to show that the handle has been |
1516 | | created/modified |
1517 | | |
1518 | | **/ |
1519 | | VOID |
1520 | | CoreConnectHandlesByKey ( |
1521 | | UINT64 Key |
1522 | | ) |
1523 | 0 | { |
1524 | 0 | UINTN Count; |
1525 | 0 | LIST_ENTRY *Link; |
1526 | 0 | EFI_HANDLE *HandleBuffer; |
1527 | 0 | IHANDLE *Handle; |
1528 | 0 | UINTN Index; |
1529 | | |
1530 | | // |
1531 | | // Lock the protocol database |
1532 | | // |
1533 | 0 | CoreAcquireProtocolLock (); |
1534 | |
|
1535 | 0 | for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { |
1536 | 0 | Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); |
1537 | 0 | if (Handle->Key > Key) { |
1538 | 0 | Count++; |
1539 | 0 | } |
1540 | 0 | } |
1541 | |
|
1542 | 0 | HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE)); |
1543 | 0 | if (HandleBuffer == NULL) { |
1544 | 0 | CoreReleaseProtocolLock (); |
1545 | 0 | return; |
1546 | 0 | } |
1547 | | |
1548 | 0 | for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { |
1549 | 0 | Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); |
1550 | 0 | if (Handle->Key > Key) { |
1551 | 0 | HandleBuffer[Count++] = Handle; |
1552 | 0 | } |
1553 | 0 | } |
1554 | | |
1555 | | // |
1556 | | // Unlock the protocol database |
1557 | | // |
1558 | 0 | CoreReleaseProtocolLock (); |
1559 | | |
1560 | | // |
1561 | | // Connect all handles whose Key value is greater than Key |
1562 | | // |
1563 | 0 | for (Index = 0; Index < Count; Index++) { |
1564 | 0 | CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE); |
1565 | 0 | } |
1566 | |
|
1567 | 0 | CoreFreePool(HandleBuffer); |
1568 | 0 | } |