Example #1
0
BOOLEAN
DevicePathIsChildDevice (
  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  IN  EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath
  )
{
  if (ParentDevicePath == NULL || ParentDevicePath == NULL) {
    return FALSE;
  }

  while (!(IsDevicePathEnd (ParentDevicePath) || IsDevicePathEnd (ChildDevicePath))) {
    if (_DevPathCompareDefault (ParentDevicePath, ChildDevicePath) != 0) {
      return FALSE;
    }

    ParentDevicePath  = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (ParentDevicePath);
    ChildDevicePath   = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (ChildDevicePath);
  }

  if (IsDevicePathEnd (ParentDevicePath)) {
    return TRUE;
  }

  return FALSE;
}
Example #2
0
EFI_STATUS
JudgeHandleIsPCIDevice(
    EFI_HANDLE            Handle,
    UINT8                 Device,
    UINT8                 Funs
)
{
    EFI_STATUS  Status;
    EFI_DEVICE_PATH   *DPath;
    EFI_DEVICE_PATH   *DevicePath;

    Status = gBS->HandleProtocol (
                 Handle,
                 &gEfiDevicePathProtocolGuid,
                 (VOID **) &DPath
             );
    if(!EFI_ERROR(Status)) {
        DevicePath = DPath;
        while(!IsDevicePathEnd(DPath)) {
            if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) {
                PCI_DEVICE_PATH   *PCIPath;

                PCIPath = (PCI_DEVICE_PATH*) DPath;
                DPath = NextDevicePathNode(DPath);
                if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) {
                    return EFI_SUCCESS;
                }
            } else {
                DPath = NextDevicePathNode(DPath);
            }
        }
    }
    return EFI_UNSUPPORTED;
}
Example #3
0
BOOLEAN
BdsTftpSupport (
    IN EFI_DEVICE_PATH*           DevicePath,
    IN EFI_HANDLE                 Handle,
    IN EFI_DEVICE_PATH*           RemainingDevicePath
)
{
    EFI_STATUS  Status;
    EFI_DEVICE_PATH  *NextDevicePath;
    EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;

    // Validate the Remaining Device Path
    if (IsDevicePathEnd(RemainingDevicePath)) {
        return FALSE;
    }
    if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&
            !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {
        return FALSE;
    }
    NextDevicePath = NextDevicePathNode (RemainingDevicePath);
    if (IsDevicePathEnd(NextDevicePath)) {
        return FALSE;
    }
    if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {
        return FALSE;
    }

    Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
    if (EFI_ERROR (Status)) {
        return FALSE;
    } else {
        return TRUE;
    }
}
Example #4
0
EFI_DEVICE_PATH *
UnpackDevicePath (
    IN EFI_DEVICE_PATH  *DevPath
    )
{
    EFI_DEVICE_PATH     *Src, *Dest, *NewPath;
    UINTN               Size;
    
    //
    // Walk device path and round sizes to valid boundries
    //    

    Src = DevPath;
    Size = 0;
    for (; ;) {
        Size += DevicePathNodeLength(Src);
        Size += ALIGN_SIZE(Size);

        if (IsDevicePathEnd(Src)) {
            break;
        }

        Src = NextDevicePathNode(Src);
    }


    //
    // Allocate space for the unpacked path
    //

    NewPath = AllocateZeroPool (Size);
    if (NewPath) {

        ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);

        //
        // Copy each node
        //

        Src = DevPath;
        Dest = NewPath;
        for (; ;) {
            Size = DevicePathNodeLength(Src);
            CopyMem (Dest, Src, Size);
            Size += ALIGN_SIZE(Size);
            SetDevicePathNodeLength (Dest, Size);
            Dest->Type |= EFI_DP_TYPE_UNPACKED;
            Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);

            if (IsDevicePathEnd(Src)) {
                break;
            }

            Src = NextDevicePathNode(Src);
        }
    }

    return NewPath;
}
Example #5
0
// Return the device path node right before the end node
static EFI_DEVICE_PATH* GetLastDevicePath(CONST EFI_DEVICE_PATH* dp)
{
    EFI_DEVICE_PATH *next, *p;

    if (IsDevicePathEnd(dp))
        return NULL;

    for (p = (EFI_DEVICE_PATH *) dp, next = NextDevicePathNode(p);
        !IsDevicePathEnd(next);
        p = next, next = NextDevicePathNode(next));

    return p;
}
Example #6
0
BOOLEAN
BdsTftpSupport (
  IN EFI_DEVICE_PATH  *DevicePath,
  IN EFI_HANDLE       Handle,
  IN EFI_DEVICE_PATH  *RemainingDevicePath
  )
{
  EFI_STATUS       Status;
  EFI_DEVICE_PATH  *NextDevicePath;
  VOID             *Interface;

  // Validate the Remaining Device Path
  if (IsDevicePathEnd (RemainingDevicePath)) {
    return FALSE;
  }
  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP) &&
      !IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv6_DP)) {
    return FALSE;
  }
  NextDevicePath = NextDevicePathNode (RemainingDevicePath);
  if (IsDevicePathEnd (NextDevicePath)) {
    return FALSE;
  }
  if (!IS_DEVICE_PATH_NODE (NextDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) {
    return FALSE;
  }

  Status = gBS->HandleProtocol (
                  Handle, &gEfiDevicePathProtocolGuid,
                  &Interface
                  );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  //
  // Check that the controller (identified by its handle "Handle") supports the
  // MTFTPv4 Service Binding Protocol. If it does, it means that it supports the
  // EFI MTFTPv4 Protocol needed to download the image through TFTP.
  //
  Status = gBS->HandleProtocol (
                  Handle, &gEfiMtftp4ServiceBindingProtocolGuid,
                  &Interface
                  );
  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  return TRUE;
}
Example #7
0
/**
  Local worker function to obtain device path information from DebugPort variable.

  Records requested settings in DebugPort device structure.

**/
EFI_DEVICE_PATH_PROTOCOL *
GetDebugPortVariable (
  VOID
  )
{
  UINTN                     DataSize;
  EFI_DEVICE_PATH_PROTOCOL  *DebugPortVariable;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

  GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize);
  if (DebugPortVariable == NULL) {
    return NULL;
  }

  DevicePath = DebugPortVariable;
  while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {
    DevicePath = NextDevicePathNode (DevicePath);
  }

  if (IsDevicePathEnd (DevicePath)) {
    FreePool (DebugPortVariable);
    return NULL;
  } else {
    CopyMem (
      &mDebugPortDevice.BaudRate,
      &((UART_DEVICE_PATH *) DevicePath)->BaudRate,
      sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)
      );
    mDebugPortDevice.ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
    mDebugPortDevice.Timeout          = DEBUGPORT_UART_DEFAULT_TIMEOUT;
    CopyMem (
      &mDebugPortDevice.Parity,
      &((UART_DEVICE_PATH *) DevicePath)->Parity,
      sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)
      );
    CopyMem (
      &mDebugPortDevice.DataBits,
      &((UART_DEVICE_PATH *) DevicePath)->DataBits,
      sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)
      );
    CopyMem (
      &mDebugPortDevice.StopBits,
      &((UART_DEVICE_PATH *) DevicePath)->StopBits,
      sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)
      );
    return DebugPortVariable;
  }
}
Example #8
0
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) {
        EFI_DEVICE_PATH *device_path;
        EFI_STATUS r = EFI_NOT_FOUND;

        /* export the device path this image is started from */
        device_path = DevicePathFromHandle(handle);
        if (device_path) {
                EFI_DEVICE_PATH *path, *paths;

                paths = UnpackDevicePath(device_path);
                for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
                        HARDDRIVE_DEVICE_PATH *drive;

                        if (DevicePathType(path) != MEDIA_DEVICE_PATH)
                                continue;
                        if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP)
                                continue;
                        drive = (HARDDRIVE_DEVICE_PATH *)path;
                        if (drive->SignatureType != SIGNATURE_TYPE_GUID)
                                continue;

                        GuidToString(uuid, (EFI_GUID *)&drive->Signature);
                        r = EFI_SUCCESS;
                        break;
                }
                FreePool(paths);
        }

        return r;
}
Example #9
0
UINTN
DevicePathSize (
    IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
    )
/*++

Routine Description:
  Function returns the size of a device path in bytes.

Arguments:
  DevPath        - A pointer to a device path data structure

Returns:

  Size is returned.

--*/
{
  EFI_DEVICE_PATH_PROTOCOL     *Start;

  //
  // Search for the end of the device path structure
  //

  Start = DevPath;
  while (!IsDevicePathEnd(DevPath)) {
    DevPath = NextDevicePathNode(DevPath);
  }

  //
  // Compute the size
  //
  return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
}
/**
  Returns the size of a device path in bytes.

  This function returns the size, in bytes, of the device path data structure 
  specified by DevicePath including the end of device path node. If DevicePath 
  is NULL, then 0 is returned. If the length of the device path is bigger than
  MaxSize, also return 0 to indicate this is an invalidate device path.

  @param  DevicePath         A pointer to a device path data structure.
  @param  MaxSize            Max valid device path size. If big than this size, 
                             return error.
  
  @retval 0                  An invalid device path.
  @retval Others             The size of a device path in bytes.

**/
UINTN
BmGetDevicePathSizeEx (
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
  IN UINTN                           MaxSize
  )
{
  UINTN  Size;
  UINTN  NodeSize;

  if (DevicePath == NULL) {
    return 0;
  }

  //
  // Search for the end of the device path structure
  //
  Size = 0;
  while (!IsDevicePathEnd (DevicePath)) {
    NodeSize = DevicePathNodeLength (DevicePath);
    if (NodeSize == 0) {
      return 0;
    }
    Size += NodeSize;
    if (Size > MaxSize) {
      return 0;
    }
    DevicePath = NextDevicePathNode (DevicePath);
  }
  Size += DevicePathNodeLength (DevicePath);
  if (Size > MaxSize) {
    return 0;
  }

  return Size;
}
Example #11
0
File: Connect.c Project: b-man/edk2
/**
  Create all handles associate with every device path node.

  @param  DevicePathToConnect           The device path which will be connected.

  @retval EFI_SUCCESS                   All handles associate with every device path node
                                        have been created.
  @retval EFI_INVALID_PARAMETER         DevicePathToConnect is NULL.
  @retval EFI_NOT_FOUND                 Create the handle associate with one device path
                                        node failed

**/
EFI_STATUS
ShellConnectDevicePath (
  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePathToConnect
  )
{
  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
  EFI_STATUS                Status;
  EFI_HANDLE                Handle;
  EFI_HANDLE                PreviousHandle;

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

  PreviousHandle = NULL;
  do{
    RemainingDevicePath = DevicePathToConnect;
    Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);

    if (!EFI_ERROR (Status) && (Handle != NULL)) {
      if (PreviousHandle == Handle) {
        Status = EFI_NOT_FOUND;
      } else {
        PreviousHandle = Handle;
        Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
      }
    }

  } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath) );

  return Status;

}
Example #12
0
BOOLEAN
BdsLoadOptionPxeIsSupported (
  IN  EFI_DEVICE_PATH  *DevicePath
  )
{
  EFI_STATUS  Status;
  EFI_HANDLE Handle;
  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;

  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
  if (EFI_ERROR(Status)) {
    return FALSE;
  }

  if (!IsDevicePathEnd(RemainingDevicePath)) {
    return FALSE;
  }

  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
  if (EFI_ERROR (Status)) {
    return FALSE;
  } else {
    return TRUE;
  }
}
Example #13
0
/**
  Returns the size of a device path in bytes.

  This function returns the size, in bytes, of the device path data structure
  specified by DevicePath including the end of device path node.
  If DevicePath is NULL or invalid, then 0 is returned.

  @param  DevicePath  A pointer to a device path data structure.

  @retval 0           If DevicePath is NULL or invalid.
  @retval Others      The size of a device path in bytes.

**/
UINTN
EFIAPI
UefiDevicePathLibGetDevicePathSize (
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
  )
{
  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;

  if (DevicePath == NULL) {
    return 0;
  }

  if (!IsDevicePathValid (DevicePath, 0)) {
    return 0;
  }

  //
  // Search for the end of the device path structure
  //
  Start = DevicePath;
  while (!IsDevicePathEnd (DevicePath)) {
    DevicePath = NextDevicePathNode (DevicePath);
  }

  //
  // Compute the size and add back in the size of the end device path structure
  //
  return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);
}
Example #14
0
EFI_STATUS
BdsLoadOptionPxeList (
  IN OUT LIST_ENTRY* BdsLoadOptionList
  )
{
  EFI_STATUS                        Status;
  UINTN                             HandleCount;
  EFI_HANDLE                        *HandleBuffer;
  UINTN                             Index;
  BDS_SUPPORTED_DEVICE              *SupportedDevice;
  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;
  EFI_SIMPLE_NETWORK_PROTOCOL*      SimpleNet;
  CHAR16                            DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];
  EFI_MAC_ADDRESS                   *Mac;
  EFI_DEVICE_PATH_PROTOCOL          *DevicePathNode;

  
  // List all the PXE Protocols
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  for (Index = 0; Index < HandleCount; Index++) {
    // We only select the handle WITH a Device Path AND the PXE Protocol
    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
    if (!EFI_ERROR(Status)) {
      // Allocate BDS Supported Device structure
      SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));

      //Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);
       Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&SimpleNet);   
      if (!EFI_ERROR(Status)) {
        Mac = &SimpleNet->Mode->CurrentAddress;
        UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0],  Mac->Addr[1],  Mac->Addr[2],  Mac->Addr[3],  Mac->Addr[4],  Mac->Addr[5]);
      } else {
        Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);
        ASSERT_EFI_ERROR (Status);
      }
      UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription);
      if(NULL != SupportedDevice) {
        SupportedDevice->DevicePathProtocol = DevicePathProtocol;

        DevicePathNode = DevicePathProtocol;
        while (!IsDevicePathEnd (DevicePathNode)) {
          if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
                ( DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP) ) {
            SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE];
            InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);
            break;
          }
          DevicePathNode = NextDevicePathNode (DevicePathNode);
        }
    }
    }
  }

  return EFI_SUCCESS;
}
Example #15
0
VOID
InstallProtocolInterfaces (
  IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice
  )
{
  EFI_STATUS                         Status;
  EFI_HANDLE                         FwbHandle;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;

  ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));

  //
  // Find a handle with a matching device path that has supports FW Block
  // protocol
  //
  Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid,
                  &FvbDevice->DevicePath, &FwbHandle);
  if (EFI_ERROR (Status)) {
    //
    // LocateDevicePath fails so install a new interface and device path
    //
    FwbHandle = NULL;
    DEBUG ((EFI_D_INFO, "Installing QEMU flash FVB\n"));
    Status = gBS->InstallMultipleProtocolInterfaces (
                    &FwbHandle,
                    &gEfiFirmwareVolumeBlockProtocolGuid,
                    &FvbDevice->FwVolBlockInstance,
                    &gEfiDevicePathProtocolGuid,
                    FvbDevice->DevicePath,
                    NULL
                    );
    ASSERT_EFI_ERROR (Status);
  } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
    //
    // Device already exists, so reinstall the FVB protocol
    //
    Status = gBS->HandleProtocol (
                    FwbHandle,
                    &gEfiFirmwareVolumeBlockProtocolGuid,
                    (VOID**)&OldFwbInterface
                    );
    ASSERT_EFI_ERROR (Status);

    DEBUG ((EFI_D_INFO, "Reinstalling FVB for QEMU flash region\n"));
    Status = gBS->ReinstallProtocolInterface (
                    FwbHandle,
                    &gEfiFirmwareVolumeBlockProtocolGuid,
                    OldFwbInterface,
                    &FvbDevice->FwVolBlockInstance
                    );
    ASSERT_EFI_ERROR (Status);
  } else {
    //
    // There was a FVB protocol on an End Device Path node
    //
    ASSERT (FALSE);
  }
}
Example #16
0
/**
  Update the device path that describing a terminal device
  based on the new BaudRate, Data Bits, parity and Stop Bits
  set.

  @param DevicePath terminal device's path

**/
VOID
ChangeVariableDevicePath (
  IN OUT EFI_DEVICE_PATH_PROTOCOL  *DevicePath
  )
{
  EFI_DEVICE_PATH_PROTOCOL  *Node;
  ACPI_HID_DEVICE_PATH      *Acpi;
  UART_DEVICE_PATH          *Uart;
  UINTN                     Com;
  BM_TERMINAL_CONTEXT       *NewTerminalContext;
  BM_MENU_ENTRY             *NewMenuEntry;

  Node  = DevicePath;
  Node  = NextDevicePathNode (Node);
  Com   = 0;
  while (!IsDevicePathEnd (Node)) {
    Acpi = (ACPI_HID_DEVICE_PATH *) Node;
    if (IsIsaSerialNode (Acpi)) {
      CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
    }

    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
      NewMenuEntry = BOpt_GetMenuEntry (
                      &TerminalMenu,
                      Com
                      );
      ASSERT (NewMenuEntry != NULL);
      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
      Uart                = (UART_DEVICE_PATH *) Node;
      CopyMem (
        &Uart->BaudRate,
        &NewTerminalContext->BaudRate,
        sizeof (UINT64)
        );

      CopyMem (
        &Uart->DataBits,
        &NewTerminalContext->DataBits,
        sizeof (UINT8)
        );

      CopyMem (
        &Uart->Parity,
        &NewTerminalContext->Parity,
        sizeof (UINT8)
        );

      CopyMem (
        &Uart->StopBits,
        &NewTerminalContext->StopBits,
        sizeof (UINT8)
        );
    }

    Node = NextDevicePathNode (Node);
  }
}
Example #17
0
EFI_STATUS
EFIAPI
MmcDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS              Status;
  MMC_HOST_INSTANCE       *MmcHostInstance;
  EFI_MMC_HOST_PROTOCOL   *MmcHost;

  //
  // Check RemainingDevicePath validation
  //
  if (RemainingDevicePath != NULL) {
    //
    // Check if RemainingDevicePath is the End of Device Path Node,
    // if yes, return EFI_SUCCESS
    //
    if (IsDevicePathEnd (RemainingDevicePath)) {
      return EFI_SUCCESS;
    }
  }

  //
  // Get the Mmc Host protocol
  //
  Status = gBS->OpenProtocol (
                Controller,
                &gRaspberryPiMmcHostProtocolGuid,
                (VOID **) &MmcHost,
                This->DriverBindingHandle,
                Controller,
                EFI_OPEN_PROTOCOL_BY_DRIVER
                );
  if (EFI_ERROR (Status)) {
    if (Status == EFI_ALREADY_STARTED) {
      return EFI_SUCCESS;
    }
    return Status;
  }

  MmcHostInstance = CreateMmcHostInstance(MmcHost);
  if (MmcHostInstance != NULL) {
    // Add the handle to the pool
    InsertMmcHost (MmcHostInstance);

    MmcHostInstance->Initialized = FALSE;

    // Detect card presence now
    CheckCardsCallback (NULL, NULL);
  }

  return EFI_SUCCESS;
}
Example #18
0
EFI_DEVICE_PATH_PROTOCOL *
AppendDevicePathInstance (
  IN EFI_DEVICE_PATH_PROTOCOL  *Src,
  IN EFI_DEVICE_PATH_PROTOCOL  *Instance
  )
/*++

Routine Description:
  Function is used to add a device path instance to a device path.

Arguments:
  Src          - A pointer to a device path data structure

  Instance     - A pointer to a device path instance.

Returns:

  This function returns a pointer to the new device path.
  If there is not enough temporary pool memory available to complete this function,
  then NULL is returned. It is up to the caller to free the memory used by Src and
  Instance if they are no longer needed.

--*/
{
  UINT8                     *Ptr;
  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
  UINTN                     SrcSize;
  UINTN                     InstanceSize;

  if (Src == NULL) {
    return DuplicateDevicePath (Instance);
  }
  SrcSize = DevicePathSize(Src);
  InstanceSize = DevicePathSize(Instance);
  Ptr = AllocatePool (SrcSize + InstanceSize);
  DevPath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
  ASSERT(DevPath);

  CopyMem (Ptr, Src, SrcSize);
//    FreePool (Src);

  while (!IsDevicePathEnd(DevPath)) {
    DevPath = NextDevicePathNode(DevPath);
  }
  //
  // Convert the End to an End Instance, since we are
  //  appending another instacne after this one its a good
  //  idea.
  //
  DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;

  DevPath = NextDevicePathNode(DevPath);
  CopyMem (DevPath, Instance, InstanceSize);
  return (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
}
Example #19
0
/**
  Determine whether a given device path is valid.
  If DevicePath is NULL, then ASSERT().

  @param  DevicePath  A pointer to a device path data structure.
  @param  MaxSize     The maximum size of the device path data structure.

  @retval TRUE        DevicePath is valid.
  @retval FALSE       The length of any node node in the DevicePath is less
                      than sizeof (EFI_DEVICE_PATH_PROTOCOL).
  @retval FALSE       If MaxSize is not zero, the size of the DevicePath
                      exceeds MaxSize.
  @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
                      count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
**/
BOOLEAN
EFIAPI
IsDevicePathValid (
  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  IN       UINTN                    MaxSize
  )
{
  UINTN Count;
  UINTN Size;
  UINTN NodeLength;

  ASSERT (DevicePath != NULL);

  if (MaxSize == 0) {
    MaxSize = MAX_UINTN;
  }

  //
  // Validate the input size big enough to touch the first node.
  //
  if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
    return FALSE;
  }

  for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
    NodeLength = DevicePathNodeLength (DevicePath);
    if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
      return FALSE;
    }

    if (NodeLength > MAX_UINTN - Size) {
      return FALSE;
    }
    Size += NodeLength;

    //
    // Validate next node before touch it.
    //
    if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
      return FALSE;
    }

    if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
      Count++;
      if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
        return FALSE;
      }
    }
  }

  //
  // Only return TRUE when the End Device Path node is valid.
  //
  return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
}
Example #20
0
/**
 *  Get the device path of floppy disk.
 */
EFI_STATUS
GetFloppyDevicePath (
  OUT EFI_DEVICE_PATH_PROTOCOL        **FloppyDevicePath
  )
{
  EFI_STATUS                      Status;
  UINTN                           NoHandle;
  EFI_HANDLE                      *Buffer;
  UINTN                           Index;
  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *RemainPath;
  EFI_DEVICE_PATH_PROTOCOL        *LastNode;
  ACPI_HID_DEVICE_PATH            *AcpiNode;

  Status = gtBS->LocateHandleBuffer (
                   ByProtocol,
                   &gEfiDevicePathProtocolGuid,
                   NULL,
                   &NoHandle,
                   &Buffer
               );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  for (Index = 0; Index < NoHandle; Index++) {
    Status = gtBS->HandleProtocol (
                     Buffer[Index],
                     &gEfiDevicePathProtocolGuid,
                     &DevicePath
                 );
    RemainPath = DevicePath;
    LastNode = DevicePath;
    while (!IsDevicePathEnd (RemainPath)) {
      LastNode = RemainPath;
      RemainPath = NextDevicePathNode (RemainPath);
    }
    //
    // Is LastNode ACPI device path node ?
    //
    if ((DevicePathType (LastNode) == 2) &&
        (DevicePathSubType (LastNode) == 1)) {
      AcpiNode = (ACPI_HID_DEVICE_PATH*)LastNode;
      //
      // Is floppy device path ?
      //
      if (EISA_ID_TO_NUM(AcpiNode->HID) == 0x0604) {
        *FloppyDevicePath = DevicePath;
        return EFI_SUCCESS;
      }
    }
  }
  return EFI_NOT_FOUND;
}
Example #21
0
/**
  Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle.

  @param[in]  QuestionID            The question ID.
  @param[in]  DevicePath            Points to device path.
  @param[in]  OpCodeHandle          Points to container for dynamic created opcodes.

**/
VOID
AddDevicePath (
  IN  UINTN                                     QuestionID,
  IN  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath,
  IN     VOID                                   *OpCodeHandle
  )
{
  EFI_STATUS                        Status;
  EFI_DEVICE_PATH_PROTOCOL          *Next;
  EFI_STRING_ID                     NameID;
  EFI_STRING                        DriverName;
  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *DevicePathText;

  //
  // Locate device path to text protocol.
  //
  Status = gBS->LocateProtocol (
                  &gEfiDevicePathToTextProtocolGuid,
                  NULL,
                  (VOID **) &DevicePathText
                  );
  if (EFI_ERROR (Status)) {
    return ;
  }
  
  //
  // Get driver file name node.
  //
  Next = DevicePath;
  while (!IsDevicePathEnd (Next)) {
    DevicePath  = Next;
    Next        = NextDevicePathNode (Next);
  }

  //
  // Display the device path in form.
  //
  DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL);
  FreePool (DriverName);
  if (NameID == 0) {
    return ;
  }

  HiiCreateActionOpCode (
    OpCodeHandle,                   // Container for dynamic created opcodes
    (UINT16) QuestionID,            // Question ID
    NameID,                         // Prompt text
    STRING_TOKEN (STR_NULL_STRING), // Help text
    EFI_IFR_FLAG_CALLBACK,          // Question flag
    0                               // Action String ID
    );
}
Example #22
0
/**
  Check to see if this driver supports the given controller

  @param  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  @param  Controller           The handle of the controller to test.
  @param  RemainingDevicePath  A pointer to the remaining portion of a device path.

  @return EFI_SUCCESS          This driver can support the given controller

**/
EFI_STATUS
EFIAPI
SerialControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )

{
  EFI_STATUS                                Status;
  UART_DEVICE_PATH                          *Uart;
  UART_FLOW_CONTROL_DEVICE_PATH             *FlowControl;

  //
  // Test RemainingDevicePath
  //
  if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
    Status = EFI_UNSUPPORTED;

    Uart = SkipControllerDevicePathNode (RemainingDevicePath, NULL, NULL);
    if (DevicePathType (Uart) != MESSAGING_DEVICE_PATH ||
        DevicePathSubType (Uart) != MSG_UART_DP ||
        DevicePathNodeLength (Uart) != sizeof (UART_DEVICE_PATH)
        ) {
      return EFI_UNSUPPORTED;
    }

    //
    // Do a rough check because Clock Rate is unknown until DriverBindingStart()
    //
    if (!VerifyUartParameters (0, Uart->BaudRate, Uart->DataBits, Uart->Parity, Uart->StopBits, NULL, NULL)) {
      return EFI_UNSUPPORTED;
    }

    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
    if (IsUartFlowControlDevicePathNode (FlowControl)) {
      //
      // If the second node is Flow Control Node,
      //   return error when it request other than hardware flow control.
      //
      if ((ReadUnaligned32 (&FlowControl->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
        return EFI_UNSUPPORTED;
      }
    }
  }

  Status = IsSioSerialController (Controller);
  if (EFI_ERROR (Status)) {
    Status = IsPciSerialController (Controller);
  }
  return Status;
}
VOID
AddLoadFileBootOptions (
  VOID
  )
{
  EFI_STATUS                            Status;
  EFI_HANDLE                            *HandleArray;
  UINTN                                 HandleArrayCount;
  UINTN                                 Index;
  EFI_DEVICE_PATH_PROTOCOL              *FilePath;
  EFI_DEVICE_PATH_PROTOCOL              *DevicePathNode;
  CHAR16                                *FileName;
  EFI_SIMPLE_NETWORK_PROTOCOL           *Snp;

  //
  // If there is a removable media device that does not have media present do a read.
  // The read will cause media to be detected and the partition drivers and file system
  // drivers to layer on top following the EFI driver model
  //
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleArrayCount, &HandleArray);
  if (EFI_ERROR (Status)) {
    return;
  }
  for (Index = 0; Index < HandleArrayCount; Index++) {
    //
    // if the LoadFileProtocol is provided by PXE, skip it. BdsLibBootOptionNetwork() will handle it.
    //
    Status = gBS->HandleProtocol (HandleArray[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);
    if (!EFI_ERROR (Status)) {
      continue;
    }

    //
    // Add the file name
    //
    Status = gBS->HandleProtocol (HandleArray[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FilePath);
    if (!EFI_ERROR (Status)) {
      FileName = L"Load File";
      DevicePathNode = FilePath;
      while (!IsDevicePathEnd (DevicePathNode)) {
        if (DevicePathNode->Type == MEDIA_DEVICE_PATH && DevicePathNode->SubType == MEDIA_FILEPATH_DP) {
          FileName = (CHAR16 *)(DevicePathNode + 1);
          break;
        }
        DevicePathNode = NextDevicePathNode (DevicePathNode);
      }
      BdsPlatformAddBootableImage (FileName, FilePath);
    }
  }
  FreePool (HandleArray);
}
Example #24
0
EFI_STATUS
BdsGetDeviceHd (
    IN  EFI_DEVICE_PATH*  RemovableDevicePath,
    OUT EFI_HANDLE*       DeviceHandle,
    OUT EFI_DEVICE_PATH** NewDevicePath
)
{
    EFI_STATUS                    Status;
    UINTN                         Index;
    UINTN                         PartitionHandleCount;
    EFI_HANDLE                    *PartitionBuffer;
    EFI_DEVICE_PATH*              PartitionDevicePath;
    EFI_DEVICE_PATH*              TmpDevicePath;
    HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath1;
    HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath2;

    // Get all the DiskIo handles
    PartitionHandleCount = 0;
    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer);
    if (EFI_ERROR(Status) || (PartitionHandleCount == 0)) {
        return Status;
    }

    // Check if one of the handles matches the Hard Disk Description
    for (Index = 0; Index < PartitionHandleCount; Index++) {
        Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath);
        if (!EFI_ERROR(Status)) {
            TmpDevicePath = PartitionDevicePath;
            while (!IsDevicePathEnd (TmpDevicePath)) {
                // Check if the Device Path node is a HD Removable device Path node
                if (BdsIsRemovableHd (TmpDevicePath)) {
                    HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath;
                    HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath;
                    if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) &&
                            (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature,(EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) &&
                            (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber))
                    {
                        *DeviceHandle = PartitionBuffer[Index];
                        // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
                        *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode(RemovableDevicePath));
                        return EFI_SUCCESS;
                    }
                }
                TmpDevicePath = NextDevicePathNode (TmpDevicePath);
            }

        }
    }

    return EFI_NOT_FOUND;
}
Example #25
0
/**
  Check the device path node whether it contains Flow Control node or not.

  @param[in] DevicePath     The device path to be checked.
  
  @retval TRUE              It contains the Flow Control node.
  @retval FALSE             It doesn't.

**/
BOOLEAN
ContainsFlowControl (
  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
  )
{
  while (!IsDevicePathEnd (DevicePath)) {
    if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
      return TRUE;
    }
    DevicePath = NextDevicePathNode (DevicePath);
  }

  return FALSE;
}
Example #26
0
/**
  Get the URI address string from the input device path.

  Caller need to free the buffer in the UriAddress pointer.
  
  @param[in]   FilePath         Pointer to the device path which contains a URI device path node.
  @param[out]  UriAddress       The URI address string extract from the device path.
  
  @retval EFI_SUCCESS            The URI string is returned.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.

**/
EFI_STATUS
HttpBootParseFilePath (
  IN     EFI_DEVICE_PATH_PROTOCOL     *FilePath,
     OUT CHAR8                        **UriAddress
  )
{
  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
  URI_DEVICE_PATH           *UriDevicePath;
  CHAR8                     *Uri;
  UINTN                     UriStrLength;

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

  *UriAddress = NULL;

  //
  // Extract the URI address from the FilePath
  //
  TempDevicePath = FilePath;
  while (!IsDevicePathEnd (TempDevicePath)) {
    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
        (DevicePathSubType (TempDevicePath) == MSG_URI_DP)) {
      UriDevicePath = (URI_DEVICE_PATH*) TempDevicePath;
      //
      // UEFI Spec doesn't require the URI to be a NULL-terminated string
      // So we allocate a new buffer and always append a '\0' to it.
      //
      UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
      if (UriStrLength == 0) {
        //
        // return a NULL UriAddress if it's a empty URI device path node.
        //
        break;
      }
      Uri = AllocatePool (UriStrLength + 1);
      if (Uri == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }
      CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL));
      Uri[DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL)] = '\0';

      *UriAddress = Uri;
    }
    TempDevicePath = NextDevicePathNode (TempDevicePath);
  }

  return EFI_SUCCESS;
}
Example #27
0
/**
  Determine whether a given device path is valid.
  If DevicePath is NULL, then ASSERT().

  @param  DevicePath  A pointer to a device path data structure.
  @param  MaxSize     The maximum size of the device path data structure.

  @retval TRUE        DevicePath is valid.
  @retval FALSE       The length of any node node in the DevicePath is less
                      than sizeof (EFI_DEVICE_PATH_PROTOCOL).
  @retval FALSE       If MaxSize is not zero, the size of the DevicePath
                      exceeds MaxSize.
  @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
                      count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
**/
BOOLEAN
EFIAPI
IsDevicePathValid (
  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  IN       UINTN                    MaxSize
  )
{
  UINTN Count;
  UINTN Size;
  UINTN NodeLength;

  ASSERT (DevicePath != NULL);

  if (MaxSize == 0){
    MaxSize = MAX_UINTN;
  }

  Size = 0;
  Count = 0;

  while (MaxSize >= sizeof (EFI_DEVICE_PATH_PROTOCOL) &&
        (MaxSize - sizeof (EFI_DEVICE_PATH_PROTOCOL) >= Size) &&
        !IsDevicePathEnd (DevicePath)) {
    NodeLength = DevicePathNodeLength (DevicePath);
    if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
      return FALSE;
    }

    if (NodeLength > MAX_UINTN - Size) {
      return FALSE;
    }

    Size += NodeLength;

    if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
      Count++;
      if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
        return FALSE;
      }
    }

    DevicePath = NextDevicePathNode (DevicePath);
  }

  //
  // Only return TRUE when the End Device Path node is valid.
  //
  return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
}
Example #28
0
STATIC
EFI_STATUS
TryRemovableDevice (
    IN  EFI_DEVICE_PATH*  DevicePath,
    OUT EFI_HANDLE*       DeviceHandle,
    OUT EFI_DEVICE_PATH** NewDevicePath
)
{
    EFI_STATUS        Status;
    UINTN             Index;
    EFI_DEVICE_PATH*  TmpDevicePath;
    BDS_REMOVABLE_DEVICE_SUPPORT* RemovableDevice;
    EFI_DEVICE_PATH* RemovableDevicePath;
    BOOLEAN         RemovableFound;

    RemovableDevice     = NULL;
    RemovableDevicePath = NULL;
    RemovableFound      = FALSE;
    TmpDevicePath       = DevicePath;

    while (!IsDevicePathEnd (TmpDevicePath) && !RemovableFound) {
        for (Index = 0; Index < sizeof(RemovableDeviceSupport) / sizeof(BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {
            RemovableDevice = &RemovableDeviceSupport[Index];
            if (RemovableDevice->IsRemovable(TmpDevicePath)) {
                RemovableDevicePath = TmpDevicePath;
                RemovableFound = TRUE;
                break;
            }
        }
        TmpDevicePath = NextDevicePathNode (TmpDevicePath);
    }

    if (!RemovableFound) {
        return EFI_NOT_FOUND;
    }

    // Search into the current started drivers
    Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);
    if (Status == EFI_NOT_FOUND) {
        // Connect all the drivers
        BdsConnectAllDrivers ();

        // Search again into all the drivers
        Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);
    }

    return Status;
}
Example #29
0
/**
  Function to walk the device path looking for a dumpable node.

  @param[in] MappingItem      The Item to fill with data.
  @param[in] DevicePath       The path of the item to get data on.

  @return EFI_SUCCESS         Always returns success.
**/
EFI_STATUS
EFIAPI
GetDeviceConsistMappingInfo (
  IN DEVICE_CONSIST_MAPPING_INFO    *MappingItem,
  IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath
  )
{
  VOID (EFIAPI *SerialFun) (EFI_DEVICE_PATH_PROTOCOL *, DEVICE_CONSIST_MAPPING_INFO *);

  UINTN Index;

  ASSERT(DevicePath != NULL);
  ASSERT(MappingItem != NULL);

  SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0);

  while (!IsDevicePathEnd (DevicePath)) {
    //
    // Find the handler to dump this device path node
    //
    SerialFun = NULL;
    for (Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) {

      if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type &&
          DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType
         ) {
        SerialFun = DevPathConsistMappingTable[Index].SerialFun;
        break;
      }
    }
    //
    // If not found, use a generic function
    //
    if (!SerialFun) {
      SerialFun = DevPathSerialDefault;
    }

    SerialFun (DevicePath, MappingItem);

    //
    // Next device path node
    //
    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
  }

  return EFI_SUCCESS;
}
Example #30
0
static INTN
simple_scheme(device_t *tab, UINTN n)
{
	EFI_DEVICE_PATH *dp1, *dp;
	devices_types_t *p;
	UINTN i;

	/*
	 * note that this test is necessary but not sufficient to guarantee that this scheme
	 * will work because, we have no way of detecting that the machine got actually
	 * rebooted if the EDD30 variable was forced. this comes from the fact, that elilo
	 * can be invoked once, aborted and then restarted with no machine reboot.
	 *
	 * XXX: there may be a way to detect this with the another variable which would
	 * be in volatile memory only
	 */
	if (elilo_opt.edd30_on == 0) {
		VERB_PRT(4, Print(L"%s device naming scheme only works with EDD3.0 enabled\n", NAMING_SCHEME));
		return -1;
	}

	for(i=0; i < n; i++) {
		dp = DevicePathFromHandle(tab[i].dev);
		if (dp == NULL) {
			ERR_PRT((L"cannot get device path for device %d", i));
			continue;
		}
		dp1 = dp = UnpackDevicePath(dp);

		while (!IsDevicePathEnd(dp)) {
			p = dev_types;
			while (p->type) {
				if (   p->type == DevicePathType(dp) 
				    && p->subtype == DevicePathSubType(dp)) {
					(*p->device_func)(tab+i, dp);
				        goto done;
				}

				p++;
			}
        		dp = NextDevicePathNode(dp);
		}
done:
       		FreePool(dp1); 
	}
	return 0;
}