Example #1
0
EFI_STATUS EFIAPI fsw_efi_DriverBinding_Start(IN EFI_DRIVER_BINDING_PROTOCOL  *This,
                                              IN EFI_HANDLE                   ControllerHandle,
                                              IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath)
{
    EFI_STATUS          Status;
    EFI_BLOCK_IO        *BlockIo;
    EFI_DISK_IO         *DiskIo;
    FSW_VOLUME_DATA     *Volume;

    VBoxLogFlowFuncEnter();
    // open consumed protocols
    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(BlockIoProtocol),
                              (VOID **) &BlockIo,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);   // NOTE: we only want to look at the MediaId
    if (EFI_ERROR(Status)) {
        VBoxLogFlowFuncLeaveRC(Status);
        return Status;
    }

    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(DiskIoProtocol),
                              (VOID **) &DiskIo,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_BY_DRIVER);
    if (EFI_ERROR(Status)) {
        VBoxLogFlowFuncLeaveRC(Status);
        return Status;
    }

    // allocate volume structure
    Volume = AllocateZeroPool(sizeof(FSW_VOLUME_DATA));
    Status = fsw_efi_ReMount(Volume, ControllerHandle, DiskIo, BlockIo);

    // on errors, close the opened protocols
    if (EFI_ERROR(Status)) {
        if (Volume->vol != NULL)
            fsw_unmount(Volume->vol);
        FreePool(Volume);

#if 0
        if (Status == EFI_MEDIA_CHANGED)
            Status = fsw_efi_ReMount(Volume, ControllerHandle, DiskIo, BlockIo);
        else
#endif
            BS->CloseProtocol(ControllerHandle,
                              &PROTO_NAME(DiskIoProtocol),
                              This->DriverBindingHandle,
                              ControllerHandle);
    }

    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
}
Example #2
0
static EFI_STATUS fsw_efi_ReMount(IN FSW_VOLUME_DATA *pVolume,
                                       IN EFI_HANDLE      ControllerHandle,
                                       EFI_DISK_IO        *pDiskIo,
                                       EFI_BLOCK_IO       *pBlockIo)
{
    EFI_STATUS Status;
    VBoxLogFlowFuncEnter();
    pVolume->Signature       = FSW_VOLUME_DATA_SIGNATURE;
    pVolume->Handle          = ControllerHandle;
    pVolume->DiskIo          = pDiskIo;
    pVolume->MediaId         = pBlockIo->Media->MediaId;
    pVolume->LastIOStatus    = EFI_SUCCESS;

    // mount the filesystem
    Status = fsw_efi_map_status(fsw_mount(pVolume, &fsw_efi_host_table,
                                          &FSW_FSTYPE_TABLE_NAME(FSTYPE), &pVolume->vol),
                                pVolume);

    VBoxLogFlowFuncMarkRC(Status);
    if (!EFI_ERROR(Status)) {
        // register the SimpleFileSystem protocol
        pVolume->FileSystem.Revision     = EFI_FILE_IO_INTERFACE_REVISION;
        pVolume->FileSystem.OpenVolume   = fsw_efi_FileSystem_OpenVolume;
        Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
                                                       &PROTO_NAME(SimpleFileSystemProtocol), &pVolume->FileSystem,
                                                       NULL);
        if (EFI_ERROR(Status))
            Print(L"Fsw ERROR: InstallMultipleProtocolInterfaces returned %x\n", Status);
    }
    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
}
Example #3
0
EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN EFI_DRIVER_BINDING_PROTOCOL  *This,
                                                  IN EFI_HANDLE                   ControllerHandle,
                                                  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath)
{
    EFI_STATUS          Status;
    EFI_DISK_IO         *DiskIo;

    // we check for both DiskIO and BlockIO protocols

    // first, open DiskIO
    VBoxLogFlowFuncEnter();
    VBoxLogFlowFuncMarkDP(RemainingDevicePath);

    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(DiskIoProtocol),
                              (VOID **) &DiskIo,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    if (EFI_ERROR(Status))
    {
        VBoxLogFlowFuncLeaveRC(Status);
        return Status;
    }

    // we were just checking, close it again
    BS->CloseProtocol(ControllerHandle,
                      &PROTO_NAME(DiskIoProtocol),
                      This->DriverBindingHandle,
                      ControllerHandle);

    // next, check BlockIO without actually opening it
    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(BlockIoProtocol),
                              NULL,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
}
Example #4
0
/**
  Test to see if this driver supports ControllerHandle. Any ControllerHandle
  than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
  supported.

  @param[in]  This                Protocol instance pointer.
  @param[in]  ControllerHandle    Handle of device to test.
  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
                                  device to start.

  @retval EFI_SUCCESS         This driver supports this device
  @retval EFI_ALREADY_STARTED This driver is already running on this device
  @retval other               This driver does not support this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
  EFI_DISK_IO_PROTOCOL      *DiskIo;
  EFI_DEV_PATH              *Node;
  VBoxLogFlowFuncEnter();

  //
  // Check RemainingDevicePath validation
  //
  if (RemainingDevicePath != NULL) {
    //
    // Check if RemainingDevicePath is the End of Device Path Node,
    // if yes, go on checking other conditions
    //
    VBoxLogFlowFuncMarkDP(RemainingDevicePath);
    if (!IsDevicePathEnd (RemainingDevicePath)) {
      //
      // If RemainingDevicePath isn't the End of Device Path Node,
      // check its validation
      //
      Node = (EFI_DEV_PATH *) RemainingDevicePath;
      if (     Node->DevPath.Type != MEDIA_DEVICE_PATH
            || Node->DevPath.SubType != MEDIA_HARDDRIVE_DP
            || DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)
            || Node->DevPath.Type != MESSAGING_DEVICE_PATH
            || Node->DevPath.SubType != MSG_SATA_DP) {
        VBoxLogFlowFuncLeaveRC(EFI_UNSUPPORTED);
        return EFI_UNSUPPORTED;
      }
    }
  }

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDiskIoProtocolGuid,
                  (VOID **) &DiskIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (Status == EFI_ALREADY_STARTED) {
    VBoxLogFlowFuncLeaveRC(EFI_SUCCESS);
    return EFI_SUCCESS;
  }
  if (EFI_ERROR (Status)) {
    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
  }
  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         ControllerHandle,
         &gEfiDiskIoProtocolGuid,
         This->DriverBindingHandle,
         ControllerHandle
         );

  //
  // Open the EFI Device Path protocol needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  VBoxLogFlowFuncMarkDP(ParentDevicePath);
  if (Status == EFI_ALREADY_STARTED) {
    VBoxLogFlowFuncLeaveRC(EFI_SUCCESS);
    return EFI_SUCCESS;
  }

  if (EFI_ERROR (Status)) {
    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
  }

  //
  // Close protocol, don't use device path protocol in the Support() function
  //
  gBS->CloseProtocol (
        ControllerHandle,
        &gEfiDevicePathProtocolGuid,
        This->DriverBindingHandle,
        ControllerHandle
        );

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiBlockIoProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    VBoxLogFlowFuncLeaveRC(Status);
    return Status;
  }

  VBoxLogFlowFuncLeaveRC(EFI_SUCCESS);
  return EFI_SUCCESS;
}
Example #5
0
/**
  Start this driver on ControllerHandle by opening a Block IO or a Block IO2
  or both, and Disk IO protocol, reading Device Path, and creating a child
  handle with a Disk IO and device path protocol.

  @param[in]  This                 Protocol instance pointer.
  @param[in]  ControllerHandle     Handle of device to bind driver to
  @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
                                   device to start.

  @retval EFI_SUCCESS          This driver is added to ControllerHandle
  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
  @retval other                This driver does not support this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS                Status;
  EFI_STATUS                OpenStatus;
  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
  EFI_BLOCK_IO2_PROTOCOL    *BlockIo2;
  EFI_DISK_IO_PROTOCOL      *DiskIo;
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
  PARTITION_DETECT_ROUTINE  *Routine;
  BOOLEAN                   MediaPresent;
  EFI_TPL                   OldTpl;
  int                       idxRoutine = 0;

  VBoxLogFlowFuncEnter();
  BlockIo2 = NULL;
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  //
  // Check RemainingDevicePath validation
  //
  if (RemainingDevicePath != NULL) {
    //
    // Check if RemainingDevicePath is the End of Device Path Node,
    // if yes, return EFI_SUCCESS
    //
    if (IsDevicePathEnd (RemainingDevicePath)) {
      Status = EFI_SUCCESS;
      goto Exit;
    }
  }

  //
  // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
  // otherwise, return error.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **) &BlockIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    VBoxLogFlowFuncMarkRC(Status);
    goto Exit;
  }

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiBlockIo2ProtocolGuid,
                  (VOID **) &BlockIo2,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  //
  // Get the Device Path Protocol on ControllerHandle's handle.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    VBoxLogFlowFuncMarkRC(Status);
    goto Exit;
  }

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDiskIoProtocolGuid,
                  (VOID **) &DiskIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    VBoxLogFlowFuncMarkRC(Status);
    goto Exit;
  }

  OpenStatus = Status;

  //
  // Try to read blocks when there's media or it is removable physical partition.
  //
  Status       = EFI_UNSUPPORTED;
  MediaPresent = BlockIo->Media->MediaPresent;
  if (BlockIo->Media->MediaPresent ||
      (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
    //
    // Try for GPT, then El Torito, and then legacy MBR partition types. If the
    // media supports a given partition type install child handles to represent
    // the partitions described by the media.
    //
    Routine = &mPartitionDetectRoutineTable[0];
    while (*Routine != NULL) {
      Status = (*Routine) (
                   This,
                   ControllerHandle,
                   DiskIo,
                   BlockIo,
                   BlockIo2,
                   ParentDevicePath
                   );
      VBoxLogFlowFuncMarkRC(Status);
      if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
        VBoxLogFlowFuncMarkVar(idxRoutine, "%d");
        break;
      }
      Routine++;
      idxRoutine++;
    }
  }
  //
  // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
  // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
  // driver. So don't try to close them. Otherwise, we will break the dependency
  // between the controller and the driver set up before.
  //
  // In the case that when the media changes on a device it will Reinstall the
  // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
  // reentrant call to our Start() successfully. We should leave the device open
  // when this happen. The "media change" case includes either the status is
  // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
  //
  if (EFI_ERROR (Status)          &&
      !EFI_ERROR (OpenStatus)     &&
      Status != EFI_MEDIA_CHANGED &&
      !(MediaPresent && Status == EFI_NO_MEDIA)) {
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDiskIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    //
    // Close Parent BlockIO2 if has.
    //
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiBlockIo2ProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
  }

Exit:
  gBS->RestoreTPL (OldTpl);
  VBoxLogFlowFuncLeaveRC(Status);
  return Status;
}
Example #6
0
STATIC
EFI_STATUS
PciRomLoadEfiDriversFromRomImage (
  IN EFI_PHYSICAL_ADDRESS    Rom,
  IN UINTN                   RomSize
  )
{
  CHAR16                        *FileName;
  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;
  PCI_DATA_STRUCTURE            *Pcir;
  UINTN                         ImageIndex;
  UINTN                         RomOffset;
  UINT32                        ImageSize;
  UINT16                        ImageOffset;
  EFI_HANDLE                    ImageHandle;
  EFI_STATUS                    Status;
  EFI_STATUS                    retStatus;
  EFI_DEVICE_PATH_PROTOCOL      *FilePath;
  BOOLEAN                       SkipImage;
  UINT32                        DestinationSize;
  UINT32                        ScratchSize;
  UINT8                         *Scratch;
  VOID                          *ImageBuffer;
  VOID                          *DecompressedImageBuffer;
  UINT32                        ImageLength;
  EFI_DECOMPRESS_PROTOCOL       *Decompress;
  UINT32                        InitializationSize;

  VBoxLogFlowFuncEnter();
  FileName = L"PciRomInMemory";

  //FileName = L"PciRom Addr=0000000000000000";
  //HexToString (&FileName[12], Rom, 16);

  ImageIndex    = 0;
  retStatus     = EFI_NOT_FOUND;
  RomOffset  = (UINTN) Rom;

  do {

    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;

    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
      return retStatus;
    }

    //
    // If the pointer to the PCI Data Structure is invalid, no further images can be located.
    // The PCI Data Structure must be DWORD aligned.
    //
    if (EfiRomHeader->PcirOffset == 0 ||
        (EfiRomHeader->PcirOffset & 3) != 0 ||
        RomOffset - (UINTN)Rom + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
      break;
    }
    Pcir      = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);
    //
    // If a valid signature is not present in the PCI Data Structure, no further images can be located.
    //
    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
      break;
    }
    ImageSize = Pcir->ImageLength * 512;
    if (RomOffset - (UINTN)Rom + ImageSize > RomSize) {
      break;
    }

    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
        ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
         (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {

      ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;
      InitializationSize      = EfiRomHeader->InitializationSize * 512;

      if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {

        ImageBuffer             = (VOID *) (UINTN) (RomOffset + ImageOffset);
        ImageLength             = InitializationSize - ImageOffset;
        DecompressedImageBuffer = NULL;

        //
        // decompress here if needed
        //
        SkipImage = FALSE;
        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
          SkipImage = TRUE;
        }

        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
          if (EFI_ERROR (Status)) {
            SkipImage = TRUE;
          } else {
            SkipImage = TRUE;
            Status = Decompress->GetInfo (
                                  Decompress,
                                  ImageBuffer,
                                  ImageLength,
                                  &DestinationSize,
                                  &ScratchSize
                                  );
            if (!EFI_ERROR (Status)) {
              DecompressedImageBuffer = NULL;
              DecompressedImageBuffer = AllocatePool (DestinationSize);
              if (DecompressedImageBuffer != NULL) {
                Scratch = AllocatePool (ScratchSize);
                if (Scratch != NULL) {
                  Status = Decompress->Decompress (
                                        Decompress,
                                        ImageBuffer,
                                        ImageLength,
                                        DecompressedImageBuffer,
                                        DestinationSize,
                                        Scratch,
                                        ScratchSize
                                        );
                  if (!EFI_ERROR (Status)) {
                    ImageBuffer = DecompressedImageBuffer;
                    ImageLength = DestinationSize;
                    SkipImage   = FALSE;
                  }

                  gBS->FreePool (Scratch);
                }
              }
            }
          }
        }

        if (!SkipImage) {

          //
          // load image and start image
          //

          FilePath = FileDevicePath (NULL, FileName);

          Status = gBS->LoadImage (
                          FALSE,
                          gImageHandle,
                          FilePath,
                          ImageBuffer,
                          ImageLength,
                          &ImageHandle
                          );
          if (!EFI_ERROR (Status)) {
            Status = gBS->StartImage (ImageHandle, NULL, NULL);
            if (!EFI_ERROR (Status)) {
              retStatus = Status;
            }
          }
          if (FilePath != NULL) {
            gBS->FreePool (FilePath);
          }
        }

        if (DecompressedImageBuffer != NULL) {
          gBS->FreePool (DecompressedImageBuffer);
        }

      }
    }

    RomOffset = RomOffset + ImageSize;
    ImageIndex++;
  } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));


  VBoxLogFlowFuncLeaveRC(retStatus);
  return retStatus;
}