⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locate.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
  OUT VOID                  **Interface
  )
/*++

Routine Description:

  Routine to get the next Handle, when you are searching for a given protocol.

Arguments:

  Position  - Information about which Handle to seach for.

  Interface - Return the interface structure for the matching protocol.
  
Returns:
  IHANDLE - An IHANDLE is returned if the next Position is not the end of the
            list. A NULL_HANDLE is returned if it's the end of the list.
  
--*/
{
  IHANDLE             *Handle;
  LIST_ENTRY          *Link;
  PROTOCOL_INTERFACE  *Prot;
 
  Handle      = NULL;
  *Interface  = NULL;
  for (; ;) {
    //
    // Next entry
    //
    Link = Position->Position->Flink;
    Position->Position = Link;

    //
    // If not at the end, return the handle
    //
    if (Link == &Position->ProtEntry->Protocols) {
      Handle = NULL;
      break;
    }

    //
    // Get the handle
    //
    Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
    Handle = (IHANDLE *) Prot->Handle;
    *Interface = Prot->Interface;

    //
    // If this handle has not been returned this request, then 
    // return it now
    //
    if (Handle->LocateRequest != EfiLocateHandleRequest) {
      Handle->LocateRequest = EfiLocateHandleRequest;
      break;
    }
  }

  return Handle;
}

EFI_STATUS
BOOTSERVICE
LocateDevicePath (
    IN EFI_GUID             *Protocol,
    IN OUT EFI_DEVICE_PATH  **FilePath,
    OUT EFI_HANDLE          *Device
    )
{
    UINTN                   NoHandles, Index;
    INTN                    BestMatch, SourceSize, Size;
    EFI_HANDLE              *Handles, Handle;
    EFI_DEVICE_PATH         *SourcePath, *DevicePath, *Eop, *Inst;


    // For now just get it working..

    *Device = NULL;
    SourcePath = *FilePath;

    //
    // The source path can only have 1 instance
    //

    if (DevicePathInstanceCount(SourcePath) != 1) {
        DEBUG((D_ERROR, "LocateDevicePath: Device path has too many instances\n"));
        return EFI_INVALID_PARAMETER;
    }

    //
    // Get a list of all handles that support the requested protocol
    //

    LibLocateHandle (ByProtocol, Protocol, NULL, &NoHandles, &Handles);
    SourceSize = DevicePathSize(SourcePath) - sizeof(EFI_DEVICE_PATH);

    BestMatch = -1;
    for(Index = 0; Index < NoHandles; Index += 1) {
        Handle = Handles[Index];
        DevicePath = DevicePathFromHandle (Handle);

        //
        // If this handle doesn't support device path, then skip it
        //

        if (!DevicePath) {
            continue;
        }

        //
        // Check each instance 
        // 

        while (Inst = DevicePathInstance (&DevicePath, &Size)) {

            //
            // Check if DevicePath is first part of SourcePath
            //

            if (Size <= SourceSize &&
                CompareMem (SourcePath, Inst, Size) == 0) {

                Eop = (EFI_DEVICE_PATH *) (((UINT8 *) Inst) + Size);
                if (IsDevicePathEndType(Eop)) {

                    //
                    // If the size is equal to the best match, then we
                    // have a duplice device path for 2 different device
                    // handles
                    //

                    ASSERT (Size != BestMatch);

                    //
                    // We've got a match, see if it's the best match so far
                    //

                    if (Size > BestMatch) {
                        BestMatch = Size;
                        *Device = Handle;
                    }
                }
            }
        }
    }

    if (Handles) {
        FreePool(Handles);
    }
     
    //
    // If there wasn't any match, then no parts of the device path
    // was found.  (which is strange since there is likely a "root level"
    // device path in the system
    //

    if (BestMatch == -1) {
        return EFI_NOT_FOUND;
    }

    //
    // Return the remaining part of the device path
    //

    *FilePath = (EFI_DEVICE_PATH *) (((UINT8 *) SourcePath) + BestMatch);
    return EFI_SUCCESS;
}

EFI_STATUS
BOOTSERVICE
LocateProtocol (
  EFI_GUID  *Protocol,
  VOID      *Registration, OPTIONAL
  VOID      **Interface
  )
/*++

Routine Description:

  Return the first Protocol Interface that matches the Protocol GUID. If
  Registration is pasased in return a Protocol Instance that was just add
  to the system. If Retistration is NULL return the first Protocol Interface
  you find.

Arguments:

  Protocol     - The protocol to search for
  
  Registration - Optional Registration Key returned from RegisterProtocolNotify() 

  Interface    - Return the Protocol interface (instance).

Returns:

  EFI_SUCCESS - If a valid Interface is returned
  other       - Interface not found and NULL is returned.

--*/
{
  EFI_STATUS              Status;
  LOCATE_POSITION         Position;
  PROTOCOL_NOTIFY         *ProtNotify;
  IHANDLE                 *Handle;

  if (Interface == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  *Interface = NULL;
  Status = EFI_SUCCESS;

  //
  // Set initial position
  //
  Position.Protocol  = Protocol;
  Position.SearchKey = Registration;
  Position.Position  = &HandleList;
  
  //
  // Lock the protocol database
  //
  AcquireLock (&ProtocolDatabaseLock);

  EfiLocateHandleRequest += 1;

  if (NULL == Registration) {
    //
    // Look up the protocol entry and set the head pointer
    //
    Position.ProtEntry = FindProtocolEntry (Protocol, FALSE);
    if (!Position.ProtEntry) {
      Status = EFI_NOT_FOUND;
      goto Done;
    }
    Position.Position = &Position.ProtEntry->Protocols;

    Handle = GetNextLocateByProtocol (&Position, Interface);
  } else {
    Handle = GetNextLocateByRegisterNotify (&Position, Interface);   
  }

  if (NULL == Handle) {
    Status = EFI_NOT_FOUND;
  } else if (NULL != Registration) {
    //
    // If this is a search by register notify and a handle was
    // returned, update the register notification position
    // 
    ProtNotify = Registration;
    ProtNotify->Position = ProtNotify->Position->Flink;
  }

Done:
  ReleaseLock (&ProtocolDatabaseLock);
  return Status;
}

EFI_STATUS
BOOTSERVICE
LocateHandleBuffer (
  IN EFI_LOCATE_SEARCH_TYPE       SearchType,
  IN EFI_GUID                     *Protocol OPTIONAL,
  IN VOID                         *SearchKey OPTIONAL,
  IN OUT UINTN                    *NumberHandles,
  OUT EFI_HANDLE                  **Buffer
  )
/*++

Routine Description:

  Function returns an array of handles that support the requested protocol 
  in a buffer allocated from pool. This is a version of LocateHandle()
  that allocates a buffer for the caller.

Arguments:

  SearchType           - Specifies which handle(s) are to be returned.
  Protocol             - Provides the protocol to search by.   
                         This parameter is only valid for SearchType ByProtocol.
  SearchKey            - Supplies the search key depending on the SearchType.
  NoHandles            - The number of handles returned in Buffer.
  Buffer               - A pointer to the buffer to return the requested array of 
                         handles that support Protocol.

Returns:
  
  EFI_SUCCESS	         - The result array of handles was returned.
  EFI_NOT_FOUND	       - No handles match the search. 
  EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
  EFI_INVALIDE_PARAMETER - One of the parameters has an invalid value.

--*/
{
  EFI_STATUS          Status;
  UINTN               BufferSize;

  if (NumberHandles == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  BufferSize = 0;
  *NumberHandles = 0;
  *Buffer = NULL;
  Status = LocateHandle (
             SearchType,  Protocol, SearchKey,
             &BufferSize, *Buffer
             );
  //
  //EFI_INVALID_PARAMETER should be returned if one of the parameters is invalid, otherwise return EFI_NOT_FOUND.
  //
  switch(Status){
    case EFI_BUFFER_TOO_SMALL:
        break;
    case EFI_INVALID_PARAMETER:
        return Status;
    default:
        return EFI_NOT_FOUND;
    }

  Status = BS->AllocatePool (EfiBootServicesData, BufferSize, (VOID *)Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = LocateHandle (
             SearchType,  Protocol, SearchKey,
             &BufferSize, *Buffer
             );

  *NumberHandles = BufferSize/sizeof(EFI_HANDLE);
  if (EFI_ERROR(Status)) {
    *NumberHandles = 0;
  }

  return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -