Coverage Report

Created: 2024-10-17 06:29

/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
}