Coverage Report

Created: 2024-10-17 06:29

/src/hbfa-fl/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Locate.c
Line
Count
Source (jump to first uncovered line)
1
/** @file
2
  Locate handle functions
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
// ProtocolRequest - Last LocateHandle request ID
14
//
15
UINTN mEfiLocateHandleRequest = 0;
16
17
//
18
// Internal prototypes
19
//
20
21
typedef struct {
22
  EFI_GUID        *Protocol;
23
  VOID            *SearchKey;
24
  LIST_ENTRY      *Position;
25
  PROTOCOL_ENTRY  *ProtEntry;
26
} LOCATE_POSITION;
27
28
typedef
29
IHANDLE *
30
(* CORE_GET_NEXT) (
31
  IN OUT LOCATE_POSITION    *Position,
32
  OUT VOID                  **Interface
33
  );
34
35
/**
36
  Routine to get the next Handle, when you are searching for all handles.
37
38
  @param  Position               Information about which Handle to seach for.
39
  @param  Interface              Return the interface structure for the matching
40
                                 protocol.
41
42
  @return An pointer to IHANDLE if the next Position is not the end of the list.
43
          Otherwise,NULL is returned.
44
45
**/
46
IHANDLE *
47
CoreGetNextLocateAllHandles (
48
  IN OUT LOCATE_POSITION    *Position,
49
  OUT VOID                  **Interface
50
  );
51
52
/**
53
  Routine to get the next Handle, when you are searching for register protocol
54
  notifies.
55
56
  @param  Position               Information about which Handle to seach for.
57
  @param  Interface              Return the interface structure for the matching
58
                                 protocol.
59
60
  @return An pointer to IHANDLE if the next Position is not the end of the list.
61
          Otherwise,NULL is returned.
62
63
**/
64
IHANDLE *
65
CoreGetNextLocateByRegisterNotify (
66
  IN OUT LOCATE_POSITION    *Position,
67
  OUT VOID                  **Interface
68
  );
69
70
/**
71
  Routine to get the next Handle, when you are searching for a given protocol.
72
73
  @param  Position               Information about which Handle to seach for.
74
  @param  Interface              Return the interface structure for the matching
75
                                 protocol.
76
77
  @return An pointer to IHANDLE if the next Position is not the end of the list.
78
          Otherwise,NULL is returned.
79
80
**/
81
IHANDLE *
82
CoreGetNextLocateByProtocol (
83
  IN OUT LOCATE_POSITION    *Position,
84
  OUT VOID                  **Interface
85
  );
86
87
88
/**
89
  Locates the requested handle(s) and returns them in Buffer.
90
91
  @param  SearchType             The type of search to perform to locate the
92
                                 handles
93
  @param  Protocol               The protocol to search for
94
  @param  SearchKey              Dependant on SearchType
95
  @param  BufferSize             On input the size of Buffer.  On output the
96
                                 size of data returned.
97
  @param  Buffer                 The buffer to return the results in
98
99
  @retval EFI_BUFFER_TOO_SMALL   Buffer too small, required buffer size is
100
                                 returned in BufferSize.
101
  @retval EFI_INVALID_PARAMETER  Invalid parameter
102
  @retval EFI_SUCCESS            Successfully found the requested handle(s) and
103
                                 returns them in Buffer.
104
105
**/
106
EFI_STATUS
107
EFIAPI
108
CoreLocateHandle (
109
  IN EFI_LOCATE_SEARCH_TYPE   SearchType,
110
  IN EFI_GUID                 *Protocol   OPTIONAL,
111
  IN VOID                     *SearchKey  OPTIONAL,
112
  IN OUT UINTN                *BufferSize,
113
  OUT EFI_HANDLE              *Buffer
114
  )
115
0
{
116
0
  EFI_STATUS          Status;
117
0
  LOCATE_POSITION     Position;
118
0
  PROTOCOL_NOTIFY     *ProtNotify;
119
0
  CORE_GET_NEXT       GetNext;
120
0
  UINTN               ResultSize;
121
0
  IHANDLE             *Handle;
122
0
  IHANDLE             **ResultBuffer;
123
0
  VOID                *Interface;
124
125
0
  if (BufferSize == NULL) {
126
0
    return EFI_INVALID_PARAMETER;
127
0
  }
128
129
0
  if ((*BufferSize > 0) && (Buffer == NULL)) {
130
0
    return EFI_INVALID_PARAMETER;
131
0
  }
132
133
0
  GetNext = NULL;
134
135
  //
136
  // Set initial position
137
  //
138
0
  Position.Protocol  = Protocol;
139
0
  Position.SearchKey = SearchKey;
140
0
  Position.Position  = &gHandleList;
141
142
0
  ResultSize = 0;
143
0
  ResultBuffer = (IHANDLE **) Buffer;
144
0
  Status = EFI_SUCCESS;
145
146
  //
147
  // Lock the protocol database
148
  //
149
0
  CoreAcquireProtocolLock ();
150
151
  //
152
  // Get the search function based on type
153
  //
154
0
  switch (SearchType) {
155
0
  case AllHandles:
156
0
    GetNext = CoreGetNextLocateAllHandles;
157
0
    break;
158
159
0
  case ByRegisterNotify:
160
    //
161
    // Must have SearchKey for locate ByRegisterNotify
162
    //
163
0
    if (SearchKey == NULL) {
164
0
      Status = EFI_INVALID_PARAMETER;
165
0
      break;
166
0
    }
167
0
    GetNext = CoreGetNextLocateByRegisterNotify;
168
0
    break;
169
170
0
  case ByProtocol:
171
0
    GetNext = CoreGetNextLocateByProtocol;
172
0
    if (Protocol == NULL) {
173
0
      Status = EFI_INVALID_PARAMETER;
174
0
      break;
175
0
    }
176
    //
177
    // Look up the protocol entry and set the head pointer
178
    //
179
0
    Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
180
0
    if (Position.ProtEntry == NULL) {
181
0
      Status = EFI_NOT_FOUND;
182
0
      break;
183
0
    }
184
0
    Position.Position = &Position.ProtEntry->Protocols;
185
0
    break;
186
187
0
  default:
188
0
    Status = EFI_INVALID_PARAMETER;
189
0
    break;
190
0
  }
191
192
0
  if (EFI_ERROR(Status)) {
193
0
    CoreReleaseProtocolLock ();
194
0
    return Status;
195
0
  }
196
197
0
  ASSERT (GetNext != NULL);
198
  //
199
  // Enumerate out the matching handles
200
  //
201
0
  mEfiLocateHandleRequest += 1;
202
0
  for (; ;) {
203
    //
204
    // Get the next handle.  If no more handles, stop
205
    //
206
0
    Handle = GetNext (&Position, &Interface);
207
0
    if (NULL == Handle) {
208
0
      break;
209
0
    }
210
211
    //
212
    // Increase the resulting buffer size, and if this handle
213
    // fits return it
214
    //
215
0
    ResultSize += sizeof(Handle);
216
0
    if (ResultSize <= *BufferSize) {
217
0
        *ResultBuffer = Handle;
218
0
        ResultBuffer += 1;
219
0
    }
220
0
  }
221
222
  //
223
  // If the result is a zero length buffer, then there were no
224
  // matching handles
225
  //
226
0
  if (ResultSize == 0) {
227
0
    Status = EFI_NOT_FOUND;
228
0
  } else {
229
    //
230
    // Return the resulting buffer size.  If it's larger than what
231
    // was passed, then set the error code
232
    //
233
0
    if (ResultSize > *BufferSize) {
234
0
      Status = EFI_BUFFER_TOO_SMALL;
235
0
    }
236
237
0
    *BufferSize = ResultSize;
238
239
0
    if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
240
      //
241
      // If this is a search by register notify and a handle was
242
      // returned, update the register notification position
243
      //
244
0
      ASSERT (SearchKey != NULL);
245
0
      ProtNotify = SearchKey;
246
0
      ProtNotify->Position = ProtNotify->Position->ForwardLink;
247
0
    }
248
0
  }
249
250
0
  CoreReleaseProtocolLock ();
251
0
  return Status;
252
0
}
253
254
255
256
/**
257
  Routine to get the next Handle, when you are searching for all handles.
258
259
  @param  Position               Information about which Handle to seach for.
260
  @param  Interface              Return the interface structure for the matching
261
                                 protocol.
262
263
  @return An pointer to IHANDLE if the next Position is not the end of the list.
264
          Otherwise,NULL is returned.
265
266
**/
267
IHANDLE *
268
CoreGetNextLocateAllHandles (
269
  IN OUT LOCATE_POSITION    *Position,
270
  OUT VOID                  **Interface
271
  )
272
0
{
273
0
  IHANDLE     *Handle;
274
275
  //
276
  // Next handle
277
  //
278
0
  Position->Position = Position->Position->ForwardLink;
279
280
  //
281
  // If not at the end of the list, get the handle
282
  //
283
0
  Handle      = NULL;
284
0
  *Interface  = NULL;
285
0
  if (Position->Position != &gHandleList) {
286
0
    Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
287
0
  }
288
289
0
  return Handle;
290
0
}
291
292
293
294
/**
295
  Routine to get the next Handle, when you are searching for register protocol
296
  notifies.
297
298
  @param  Position               Information about which Handle to seach for.
299
  @param  Interface              Return the interface structure for the matching
300
                                 protocol.
301
302
  @return An pointer to IHANDLE if the next Position is not the end of the list.
303
          Otherwise,NULL is returned.
304
305
**/
306
IHANDLE *
307
CoreGetNextLocateByRegisterNotify (
308
  IN OUT LOCATE_POSITION    *Position,
309
  OUT VOID                  **Interface
310
  )
311
0
{
312
0
  IHANDLE             *Handle;
313
0
  PROTOCOL_NOTIFY     *ProtNotify;
314
0
  PROTOCOL_INTERFACE  *Prot;
315
0
  LIST_ENTRY          *Link;
316
317
0
  Handle      = NULL;
318
0
  *Interface  = NULL;
319
0
  ProtNotify = Position->SearchKey;
320
321
  //
322
  // If this is the first request, get the next handle
323
  //
324
0
  if (ProtNotify != NULL) {
325
0
    ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
326
0
    Position->SearchKey = NULL;
327
328
    //
329
    // If not at the end of the list, get the next handle
330
    //
331
0
    Link = ProtNotify->Position->ForwardLink;
332
0
    if (Link != &ProtNotify->Protocol->Protocols) {
333
0
      Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
334
0
      Handle = Prot->Handle;
335
0
      *Interface = Prot->Interface;
336
0
    }
337
0
  }
338
339
0
  return Handle;
340
0
}
341
342
343
/**
344
  Routine to get the next Handle, when you are searching for a given protocol.
345
346
  @param  Position               Information about which Handle to seach for.
347
  @param  Interface              Return the interface structure for the matching
348
                                 protocol.
349
350
  @return An pointer to IHANDLE if the next Position is not the end of the list.
351
          Otherwise,NULL is returned.
352
353
**/
354
IHANDLE *
355
CoreGetNextLocateByProtocol (
356
  IN OUT LOCATE_POSITION    *Position,
357
  OUT VOID                  **Interface
358
  )
359
0
{
360
0
  IHANDLE             *Handle;
361
0
  LIST_ENTRY          *Link;
362
0
  PROTOCOL_INTERFACE  *Prot;
363
364
0
  Handle      = NULL;
365
0
  *Interface  = NULL;
366
0
  for (; ;) {
367
    //
368
    // Next entry
369
    //
370
0
    Link = Position->Position->ForwardLink;
371
0
    Position->Position = Link;
372
373
    //
374
    // If not at the end, return the handle
375
    //
376
0
    if (Link == &Position->ProtEntry->Protocols) {
377
0
      Handle = NULL;
378
0
      break;
379
0
    }
380
381
    //
382
    // Get the handle
383
    //
384
0
    Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
385
0
    Handle = Prot->Handle;
386
0
    *Interface = Prot->Interface;
387
388
    //
389
    // If this handle has not been returned this request, then
390
    // return it now
391
    //
392
0
    if (Handle->LocateRequest != mEfiLocateHandleRequest) {
393
0
      Handle->LocateRequest = mEfiLocateHandleRequest;
394
0
      break;
395
0
    }
396
0
  }
397
398
0
  return Handle;
399
0
}
400
401
402
/**
403
  Locates the handle to a device on the device path that supports the specified protocol.
404
405
  @param  Protocol              Specifies the protocol to search for.
406
  @param  DevicePath            On input, a pointer to a pointer to the device path. On output, the device
407
                                path pointer is modified to point to the remaining part of the device
408
                                path.
409
  @param  Device                A pointer to the returned device handle.
410
411
  @retval EFI_SUCCESS           The resulting handle was returned.
412
  @retval EFI_NOT_FOUND         No handles match the search.
413
  @retval EFI_INVALID_PARAMETER Protocol is NULL.
414
  @retval EFI_INVALID_PARAMETER DevicePath is NULL.
415
  @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
416
417
**/
418
EFI_STATUS
419
EFIAPI
420
CoreLocateDevicePath (
421
  IN EFI_GUID                       *Protocol,
422
  IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,
423
  OUT EFI_HANDLE                    *Device
424
  )
425
0
{
426
0
  INTN                        SourceSize;
427
0
  INTN                        Size;
428
0
  INTN                        BestMatch;
429
0
  UINTN                       HandleCount;
430
0
  UINTN                       Index;
431
0
  EFI_STATUS                  Status;
432
0
  EFI_HANDLE                  *Handles;
433
0
  EFI_HANDLE                  Handle;
434
0
  EFI_HANDLE                  BestDevice;
435
0
  EFI_DEVICE_PATH_PROTOCOL    *SourcePath;
436
0
  EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;
437
438
0
  if (Protocol == NULL) {
439
0
    return EFI_INVALID_PARAMETER;
440
0
  }
441
442
0
  if ((DevicePath == NULL) || (*DevicePath == NULL)) {
443
0
    return EFI_INVALID_PARAMETER;
444
0
  }
445
446
0
  Handles = NULL;
447
0
  BestDevice = NULL;
448
0
  SourcePath = *DevicePath;
449
0
  TmpDevicePath = SourcePath;
450
0
  while (!IsDevicePathEnd (TmpDevicePath)) {
451
0
    if (IsDevicePathEndInstance (TmpDevicePath)) {
452
      //
453
      // If DevicePath is a multi-instance device path,
454
      // the function will operate on the first instance
455
      //
456
0
      break;
457
0
    }
458
0
    TmpDevicePath = NextDevicePathNode (TmpDevicePath);
459
0
  }
460
461
0
  SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;
462
463
  //
464
  // Get a list of all handles that support the requested protocol
465
  //
466
0
  Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
467
0
  if (EFI_ERROR (Status) || HandleCount == 0) {
468
0
    return EFI_NOT_FOUND;
469
0
  }
470
471
0
  BestMatch = -1;
472
0
  for(Index = 0; Index < HandleCount; Index += 1) {
473
0
    Handle = Handles[Index];
474
0
    Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);
475
0
    if (EFI_ERROR (Status)) {
476
      //
477
      // If this handle doesn't support device path, then skip it
478
      //
479
0
      continue;
480
0
    }
481
482
    //
483
    // Check if DevicePath is first part of SourcePath
484
    //
485
0
    Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
486
0
    ASSERT (Size >= 0);
487
0
    if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, (UINTN) Size) == 0) {
488
      //
489
      // If the size is equal to the best match, then we
490
      // have a duplicate device path for 2 different device
491
      // handles
492
      //
493
0
      ASSERT (Size != BestMatch);
494
495
      //
496
      // We've got a match, see if it's the best match so far
497
      //
498
0
      if (Size > BestMatch) {
499
0
        BestMatch = Size;
500
0
        BestDevice = Handle;
501
0
      }
502
0
    }
503
0
  }
504
505
0
  CoreFreePool (Handles);
506
507
  //
508
  // If there wasn't any match, then no parts of the device path was found.
509
  // Which is strange since there is likely a "root level" device path in the system.
510
  //
511
0
  if (BestMatch == -1) {
512
0
    return EFI_NOT_FOUND;
513
0
  }
514
515
0
  if (Device == NULL) {
516
0
    return  EFI_INVALID_PARAMETER;
517
0
  }
518
0
  *Device = BestDevice;
519
520
  //
521
  // Return the remaining part of the device path
522
  //
523
0
  *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
524
0
  return EFI_SUCCESS;
525
0
}
526
527
528
/**
529
  Return the first Protocol Interface that matches the Protocol GUID. If
530
  Registration is passed in, return a Protocol Instance that was just add
531
  to the system. If Registration is NULL return the first Protocol Interface
532
  you find.
533
534
  @param  Protocol               The protocol to search for
535
  @param  Registration           Optional Registration Key returned from
536
                                 RegisterProtocolNotify()
537
  @param  Interface              Return the Protocol interface (instance).
538
539
  @retval EFI_SUCCESS            If a valid Interface is returned
540
  @retval EFI_INVALID_PARAMETER  Invalid parameter
541
  @retval EFI_NOT_FOUND          Protocol interface not found
542
543
**/
544
EFI_STATUS
545
EFIAPI
546
CoreLocateProtocol (
547
  IN  EFI_GUID  *Protocol,
548
  IN  VOID      *Registration OPTIONAL,
549
  OUT VOID      **Interface
550
  )
551
0
{
552
0
  EFI_STATUS              Status;
553
0
  LOCATE_POSITION         Position;
554
0
  PROTOCOL_NOTIFY         *ProtNotify;
555
0
  IHANDLE                 *Handle;
556
557
0
  if ((Interface == NULL) || (Protocol == NULL)) {
558
0
    return EFI_INVALID_PARAMETER;
559
0
  }
560
561
0
  *Interface = NULL;
562
0
  Status = EFI_SUCCESS;
563
564
  //
565
  // Set initial position
566
  //
567
0
  Position.Protocol  = Protocol;
568
0
  Position.SearchKey = Registration;
569
0
  Position.Position  = &gHandleList;
570
571
  //
572
  // Lock the protocol database
573
  //
574
0
  Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);
575
0
  if (EFI_ERROR (Status)) {
576
0
    return EFI_NOT_FOUND;
577
0
  }
578
579
0
  mEfiLocateHandleRequest += 1;
580
581
0
  if (Registration == NULL) {
582
    //
583
    // Look up the protocol entry and set the head pointer
584
    //
585
0
    Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
586
0
    if (Position.ProtEntry == NULL) {
587
0
      Status = EFI_NOT_FOUND;
588
0
      goto Done;
589
0
    }
590
0
    Position.Position = &Position.ProtEntry->Protocols;
591
592
0
    Handle = CoreGetNextLocateByProtocol (&Position, Interface);
593
0
  } else {
594
0
    Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
595
0
  }
596
597
0
  if (Handle == NULL) {
598
0
    Status = EFI_NOT_FOUND;
599
0
  } else if (Registration != NULL) {
600
    //
601
    // If this is a search by register notify and a handle was
602
    // returned, update the register notification position
603
    //
604
0
    ProtNotify = Registration;
605
0
    ProtNotify->Position = ProtNotify->Position->ForwardLink;
606
0
  }
607
608
0
Done:
609
0
  CoreReleaseProtocolLock ();
610
0
  return Status;
611
0
}
612
613
614
/**
615
  Function returns an array of handles that support the requested protocol
616
  in a buffer allocated from pool. This is a version of CoreLocateHandle()
617
  that allocates a buffer for the caller.
618
619
  @param  SearchType             Specifies which handle(s) are to be returned.
620
  @param  Protocol               Provides the protocol to search by.    This
621
                                 parameter is only valid for SearchType
622
                                 ByProtocol.
623
  @param  SearchKey              Supplies the search key depending on the
624
                                 SearchType.
625
  @param  NumberHandles          The number of handles returned in Buffer.
626
  @param  Buffer                 A pointer to the buffer to return the requested
627
                                 array of  handles that support Protocol.
628
629
  @retval EFI_SUCCESS            The result array of handles was returned.
630
  @retval EFI_NOT_FOUND          No handles match the search.
631
  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
632
                                 matching results.
633
  @retval EFI_INVALID_PARAMETER  One or more parameters are not valid.
634
635
**/
636
EFI_STATUS
637
EFIAPI
638
CoreLocateHandleBuffer (
639
  IN EFI_LOCATE_SEARCH_TYPE       SearchType,
640
  IN EFI_GUID                     *Protocol OPTIONAL,
641
  IN VOID                         *SearchKey OPTIONAL,
642
  IN OUT UINTN                    *NumberHandles,
643
  OUT EFI_HANDLE                  **Buffer
644
  )
645
0
{
646
0
  EFI_STATUS          Status;
647
0
  UINTN               BufferSize;
648
649
0
  if (NumberHandles == NULL) {
650
0
    return EFI_INVALID_PARAMETER;
651
0
  }
652
653
0
  if (Buffer == NULL) {
654
0
    return EFI_INVALID_PARAMETER;
655
0
  }
656
657
0
  BufferSize = 0;
658
0
  *NumberHandles = 0;
659
0
  *Buffer = NULL;
660
0
  Status = CoreLocateHandle (
661
0
             SearchType,
662
0
             Protocol,
663
0
             SearchKey,
664
0
             &BufferSize,
665
0
             *Buffer
666
0
             );
667
  //
668
  // LocateHandleBuffer() returns incorrect status code if SearchType is
669
  // invalid.
670
  //
671
  // Add code to correctly handle expected errors from CoreLocateHandle().
672
  //
673
0
  if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
674
0
    if (Status != EFI_INVALID_PARAMETER) {
675
0
      Status = EFI_NOT_FOUND;
676
0
    }
677
0
    return Status;
678
0
  }
679
680
0
  *Buffer = AllocatePool (BufferSize);
681
0
  if (*Buffer == NULL) {
682
0
    return EFI_OUT_OF_RESOURCES;
683
0
  }
684
685
0
  Status = CoreLocateHandle (
686
0
             SearchType,
687
0
             Protocol,
688
0
             SearchKey,
689
0
             &BufferSize,
690
0
             *Buffer
691
0
             );
692
693
0
  *NumberHandles = BufferSize / sizeof(EFI_HANDLE);
694
0
  if (EFI_ERROR(Status)) {
695
0
    *NumberHandles = 0;
696
0
  }
697
698
0
  return Status;
699
0
}
700
701
702