Search code examples
cuefi

"pointer passing convention" in UEFI module


I want to know when I need to free a pointer that is returned from EFI functions

EFI_DEVICE_PATH_PROTOCOL *
BmExpandFileDevicePath (
  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath,
  IN  EFI_DEVICE_PATH_PROTOCOL    *FullPath
  )
{
  EFI_STATUS                      Status;
  UINTN                           Index;
  UINTN                           HandleCount;
  EFI_HANDLE                      *Handles;
  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
  UINTN                           MediaType;
  EFI_DEVICE_PATH_PROTOCOL        *NextFullPath;
  BOOLEAN                         GetNext;

  EfiBootManagerConnectAll ();
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);
  if (EFI_ERROR (Status)) {
    HandleCount = 0;
    Handles = NULL;
  }

  GetNext = (BOOLEAN)(FullPath == NULL);
  NextFullPath = NULL;
  //
  // Enumerate all removable media devices followed by all fixed media devices,
  //   followed by media devices which don't layer on block io.
  //
  for (MediaType = 0; MediaType < 3; MediaType++) {
    for (Index = 0; Index < HandleCount; Index++) {
      Status = gBS->HandleProtocol (Handles[Index], &gEfiBlockIoProtocolGuid, (VOID *) &BlockIo);
      if (EFI_ERROR (Status)) {
        BlockIo = NULL;
      }
      if ((MediaType == 0 && BlockIo != NULL && BlockIo->Media->RemovableMedia) ||
          (MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||
          (MediaType == 2 && BlockIo == NULL)
          ) {
        NextFullPath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);
        if (GetNext) {
          break;
        } else {
          GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
          FreePool (NextFullPath);
          NextFullPath = NULL;
        }
      }
    }
    if (NextFullPath != NULL) {
      break;
    }
  }

  if (Handles != NULL) {
    FreePool (Handles);
  }

  return NextFullPath;
}

for example, In this code, can I free Handles after calling HandleProtocol and still be able to use BlockIo? Is there a document that explains the "pointer passing convention" of edk2 functions? Thanks.


Solution

  • You have to look into the specification, if you are responsible to free the pointer there is a note.

    For your LocateHandleBuffer example:

    Buffer

    A pointer to the buffer to return the requested array of handles that support Protocol. This buffer is allocated with a call to the Boot Service EFI_BOOT_SERVICES.AllocatePool(). It is the caller's responsibility to call the Boot Service EFI_BOOT_SERVICES.FreePool() when the caller no longer requires the contents of Buffer."

    You can use the BlockIO protocols after you free the buffer, you are not freeing the handle instances (which would be a very bad idea), instead you are freeing an array of them.