コード例 #1
0
EFI_STATUS
EFIAPI
FatOpenVolume (
  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *This,
  OUT EFI_FILE_PROTOCOL                **File
  )
/*++

Routine Description:

  Implements Simple File System Protocol interface function OpenVolume().

Arguments:

  This                  - Calling context.
  File                  - the Root Directory of the volume.

Returns:

  EFI_OUT_OF_RESOURCES  - Can not allocate the memory.
  EFI_VOLUME_CORRUPTED  - The FAT type is error.
  EFI_SUCCESS           - Open the volume successfully.

--*/
{
  EFI_STATUS  Status;
  FAT_VOLUME  *Volume;
  FAT_IFILE   *IFile;

  Volume = VOLUME_FROM_VOL_INTERFACE (This);
  FatAcquireLock ();

  //
  // Open Root file
  //
  Status = FatOpenDirEnt (NULL, &Volume->RootDirEnt);
  if (EFI_ERROR (Status)) {
    goto Done;
  }
  //
  // Open a new instance to the root
  //
  Status = FatAllocateIFile (Volume->Root, &IFile);
  if (!EFI_ERROR (Status)) {
    *File = &IFile->Handle;
  }

Done:

  Status = FatCleanupVolume (Volume, Volume->Root, Status, NULL);
  FatReleaseLock ();

  return Status;
}
コード例 #2
0
/**

  Implements Simple File System Protocol interface function OpenVolume().

  @param  This                  - Calling context.
  @param  File                  - the Root Directory of the volume.

  @retval EFI_OUT_OF_RESOURCES  - Can not allocate the memory.
  @retval EFI_VOLUME_CORRUPTED  - The FAT type is error.
  @retval EFI_SUCCESS           - Open the volume successfully.

**/
EFI_STATUS
EFIAPI
FatOpenVolume (
  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *This,
  OUT EFI_FILE_PROTOCOL                **File
  )
{
  EFI_STATUS  Status;
  FAT_VOLUME  *Volume;
  FAT_IFILE   *IFile;

  Volume = VOLUME_FROM_VOL_INTERFACE (This);
  FatAcquireLock ();

  //
  // Open Root file
  //
  Status = FatOpenDirEnt (NULL, &Volume->RootDirEnt);
  if (EFI_ERROR (Status)) {
    goto Done;
  }
  //
  // Open a new instance to the root
  //
  Status = FatAllocateIFile (Volume->Root, &IFile);
  if (!EFI_ERROR (Status)) {
    *File = &IFile->Handle;
  }

Done:

  Status = FatCleanupVolume (Volume, Volume->Root, Status, NULL);
  FatReleaseLock ();

  return Status;
}
コード例 #3
0
/**

  Called by FatDriverBindingStop(), Abandon the volume.

  @param  Volume                - The volume to be abandoned.

  @retval EFI_SUCCESS           - Abandoned the volume successfully.
  @return Others                - Can not uninstall the protocol interfaces.

**/
EFI_STATUS
FatAbandonVolume (
  IN FAT_VOLUME *Volume
  )
{
  EFI_STATUS  Status;
  BOOLEAN     LockedByMe;

  //
  // Uninstall the protocol interface.
  //
  if (Volume->Handle != NULL) {
    Status = gBS->UninstallMultipleProtocolInterfaces (
                    Volume->Handle,
                    &gEfiSimpleFileSystemProtocolGuid,
                    &Volume->VolumeInterface,
                    NULL
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  LockedByMe = FALSE;

  //
  // Acquire the lock.
  // If the caller has already acquired the lock (which
  // means we are in the process of some Fat operation),
  // we can not acquire again.
  //
  Status = FatAcquireLockOrFail ();
  if (!EFI_ERROR (Status)) {
    LockedByMe = TRUE;
  }
  //
  // The volume is still being used. Hence, set error flag for all OFiles still in
  // use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
  // EFI_NO_MEDIA.
  //
  if (Volume->Root != NULL) {
    FatSetVolumeError (
      Volume->Root,
      Volume->BlockIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
      );
  }

  Volume->Valid = FALSE;

  //
  // Release the lock.
  // If locked by me, this means DriverBindingStop is NOT
  // called within an on-going Fat operation, so we should
  // take responsibility to cleanup and free the volume.
  // Otherwise, the DriverBindingStop is called within an on-going
  // Fat operation, we shouldn't check reference, so just let outer
  // FatCleanupVolume do the task.
  //
  if (LockedByMe) {
    FatCleanupVolume (Volume, NULL, EFI_SUCCESS, NULL);
    FatReleaseLock ();
  }

  return EFI_SUCCESS;
}
コード例 #4
0
ファイル: Fat.c プロジェクト: huaqli/clover
EFI_STATUS
EFIAPI
FatDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
/*++

Routine Description:

  Start this driver on ControllerHandle by opening a Block IO and Disk IO
  protocol, reading Device Path. Add a Simple File System protocol to
  ControllerHandle if the media contains a valid file system.

Arguments:

  This                  - Protocol instance pointer.
  ControllerHandle      - Handle of device to bind driver to.
  RemainingDevicePath   - Not used.

Returns:

  EFI_SUCCESS           - This driver is added to DeviceHandle.
  EFI_ALREADY_STARTED   - This driver is already running on DeviceHandle.
  EFI_OUT_OF_RESOURCES  - Can not allocate the memory.
  other                 - This driver does not support this device.

--*/
{
  EFI_STATUS            Status;
  EFI_BLOCK_IO_PROTOCOL *BlockIo;
  EFI_DISK_IO_PROTOCOL  *DiskIo;
  BOOLEAN               LockedByMe;

  LockedByMe = FALSE;
  //
  // Acquire the lock.
  // If caller has already acquired the lock, cannot lock it again.
  //
  Status = FatAcquireLockOrFail ();
  if (!EFI_ERROR (Status)) {
    LockedByMe = TRUE;
  }

  Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }
  //
  // Open our required BlockIo and DiskIo
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **) &BlockIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDiskIoProtocolGuid,
                  (VOID **) &DiskIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }
  //
  // Allocate Volume structure. In FatAllocateVolume(), Resources
  // are allocated with protocol installed and cached initialized
  //
  Status = FatAllocateVolume (ControllerHandle, DiskIo, BlockIo);

  //
  // 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.
  //
  if (EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    ControllerHandle,
                    &gEfiSimpleFileSystemProtocolGuid,
                    NULL,
                    This->DriverBindingHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      gBS->CloseProtocol (
             ControllerHandle,
             &gEfiDiskIoProtocolGuid,
             This->DriverBindingHandle,
             ControllerHandle
             );
    }
  }

Exit:
  //
  // Unlock if locked by myself.
  //
  if (LockedByMe) {
    FatReleaseLock ();
  }
  return Status;
}
コード例 #5
0
ファイル: ReadWrite.c プロジェクト: jief666/clover
EFI_STATUS
FatIFileAccess (
  IN     EFI_FILE_PROTOCOL     *FHand,
  IN     IO_MODE               IoMode,
  IN OUT UINTN                 *BufferSize,
  IN OUT VOID                  *Buffer,
  IN     EFI_FILE_IO_TOKEN     *Token
  )
/*++

Routine Description:

  Get the file info from the open file of the IFile into Buffer.

Arguments:

  FHand                 - The file handle to access.
  IoMode                - Indicate whether the access mode is reading or writing.
  BufferSize            - Size of Buffer.
  Buffer                - Buffer containing read data.
  Token                 - A pointer to the token associated with the transaction.

Returns:

  EFI_SUCCESS           - Get the file info successfully.
  EFI_DEVICE_ERROR      - Can not find the OFile for the file.
  EFI_VOLUME_CORRUPTED  - The file type of open file is error.
  EFI_WRITE_PROTECTED   - The disk is write protect.
  EFI_ACCESS_DENIED     - The file is read-only.
  other                 - An error occurred when operating on the disk.

--*/
{
  EFI_STATUS  Status;
  FAT_IFILE   *IFile;
  FAT_OFILE   *OFile;
  FAT_VOLUME  *Volume;
  UINT64      EndPosition;
  FAT_TASK    *Task;

  IFile  = IFILE_FROM_FHAND (FHand);
  OFile  = IFile->OFile;
  Volume = OFile->Volume;
  Task   = NULL;

  //
  // Write to a directory is unsupported
  //
  if ((OFile->ODir != NULL) && (IoMode == WRITE_DATA)) {
    return EFI_UNSUPPORTED;
  }

  if (OFile->Error == EFI_NOT_FOUND) {
    return EFI_DEVICE_ERROR;
  }

  if (IoMode == READ_DATA) {
    //
    // If position is at EOF, then return device error
    //
    if (IFile->Position > OFile->FileSize) {
      return EFI_DEVICE_ERROR;
    }
  } else {
    //
    // Check if the we can write data
    //
    if (Volume->ReadOnly) {
      return EFI_WRITE_PROTECTED;
    }

    if (IFile->ReadOnly) {
      return EFI_ACCESS_DENIED;
    }
  }

  if (Token == NULL) {
    FatWaitNonblockingTask (IFile);
  } else {
    //
    // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
    // But if it calls, the below check can avoid crash.
    //
    if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
      return EFI_UNSUPPORTED;
    }
    Task = FatCreateTask (IFile, Token);
    if (Task == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  }

  FatAcquireLock ();

  Status = OFile->Error;
  if (!EFI_ERROR (Status)) {
    if (OFile->ODir != NULL) {
      //
      // Read a directory is supported
      //
      ASSERT (IoMode == READ_DATA);
      Status = FatIFileReadDir (IFile, BufferSize, Buffer);
      OFile = NULL;
    } else {
      //
      // Access a file
      //
      EndPosition = IFile->Position + *BufferSize;
      if (EndPosition > OFile->FileSize) {
        //
        // The position goes beyond the end of file
        //
        if (IoMode == READ_DATA) {
          //
          // Adjust the actual size read
          //
          *BufferSize -= (UINTN) EndPosition - OFile->FileSize;
        } else {
          //
          // We expand the file size of OFile
          //
          Status = FatGrowEof (OFile, EndPosition);
          if (EFI_ERROR (Status)) {
            //
            // Must update the file's info into the file's Directory Entry
            // and then flush the dirty cache info into disk.
            //
            *BufferSize = 0;
            FatOFileFlush (OFile);
            OFile = NULL;
            goto Done;
          }

          FatUpdateDirEntClusterSizeInfo (OFile);
        }
      }

      Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer, Task);
      IFile->Position += *BufferSize;
    }
  }

  if (Token != NULL) {
    if (!EFI_ERROR (Status)) {
      Status = FatQueueTask (IFile, Task);
    } else {
      FatDestroyTask (Task);
    }
  }

Done:
  //
  // On EFI_SUCCESS case, not calling FatCleanupVolume():
  // 1) The Cache flush operation is avoided to enhance
  // performance. Caller is responsible to call Flush() when necessary.
  // 2) The volume dirty bit is probably set already, and is expected to be
  // cleaned in subsequent Flush() or other operations.
  // 3) Write operation doesn't affect OFile/IFile structure, so
  // Reference checking is not necessary.
  //
  if (EFI_ERROR (Status)) {
    Status = FatCleanupVolume (Volume, OFile, Status, NULL);
  }

  FatReleaseLock ();
  return Status;
}
コード例 #6
0
ファイル: Open.c プロジェクト: MattDevo/edk2
/**

  Implements OpenEx() of Simple File System Protocol.

  @param  FHand                 - File handle of the file serves as a starting reference point.
  @param  NewHandle             - Handle of the file that is newly opened.
  @param  FileName              - File name relative to FHand.
  @param  OpenMode              - Open mode.
  @param  Attributes            - Attributes to set if the file is created.
  @param  Token                 - A pointer to the token associated with the transaction.:

  @retval EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
                          The OpenMode is not supported.
                          The Attributes is not the valid attributes.
  @retval EFI_OUT_OF_RESOURCES  - Can not allocate the memory for file string.
  @retval EFI_SUCCESS           - Open the file successfully.
  @return Others                - The status of open file.

**/
EFI_STATUS
EFIAPI
FatOpenEx (
  IN  EFI_FILE_PROTOCOL       *FHand,
  OUT EFI_FILE_PROTOCOL       **NewHandle,
  IN  CHAR16                  *FileName,
  IN  UINT64                  OpenMode,
  IN  UINT64                  Attributes,
  IN OUT EFI_FILE_IO_TOKEN    *Token
  )
{
  FAT_IFILE   *IFile;
  FAT_IFILE   *NewIFile;
  FAT_OFILE   *OFile;
  EFI_STATUS  Status;
  FAT_TASK    *Task;

  //
  // Perform some parameter checking
  //
  if (FileName == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check for a valid mode
  //
  switch (OpenMode) {
  case EFI_FILE_MODE_READ:
  case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
  case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
    break;

  default:
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check for valid Attributes for file creation case.
  //
  if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) {
    return EFI_INVALID_PARAMETER;
  }

  IFile = IFILE_FROM_FHAND (FHand);
  OFile = IFile->OFile;
  Task  = NULL;

  if (Token == NULL) {
    FatWaitNonblockingTask (IFile);
  } else {
    //
    // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
    // But if it calls, the below check can avoid crash.
    //
    if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
      return EFI_UNSUPPORTED;
    }
    Task = FatCreateTask (IFile, Token);
    if (Task == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  }

  //
  // Lock
  //
  FatAcquireLock ();

  //
  // Open the file
  //
  Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);

  //
  // If the file was opened, return the handle to the caller
  //
  if (!EFI_ERROR (Status)) {
    *NewHandle = &NewIFile->Handle;
  }
  //
  // Unlock
  //
  Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task);
  FatReleaseLock ();

  if (Token != NULL) {
    if (!EFI_ERROR (Status)) {
      Status = FatQueueTask (IFile, Task);
    } else {
      FatDestroyTask (Task);
    }
  }

  return Status;
}
コード例 #7
0
ファイル: Open.c プロジェクト: Clover-EFI-Bootloader/clover
EFI_STATUS
EFIAPI
FatOpenEx (
  IN  EFI_FILE_PROTOCOL       *FHand,
  OUT EFI_FILE_PROTOCOL       **NewHandle,
  IN  CHAR16                  *FileName,
  IN  UINT64                  OpenMode,
  IN  UINT64                  Attributes,
  IN OUT EFI_FILE_IO_TOKEN    *Token
  )
/*++
Routine Description:

  Implements OpenEx() of Simple File System Protocol.

Arguments:

  FHand                 - File handle of the file serves as a starting reference point.
  NewHandle             - Handle of the file that is newly opened.
  FileName              - File name relative to FHand.
  OpenMode              - Open mode.
  Attributes            - Attributes to set if the file is created.
  Token                 - A pointer to the token associated with the transaction.

Returns:

  EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
                          The OpenMode is not supported.
                          The Attributes is not the valid attributes.
  EFI_OUT_OF_RESOURCES  - Can not allocate the memory for file string.
  EFI_SUCCESS           - Open the file successfully.
  Others                - The status of open file.

--*/
{
  FAT_IFILE   *IFile;
  FAT_IFILE   *NewIFile;
  FAT_OFILE   *OFile;
  EFI_STATUS  Status;
  FAT_TASK    *Task;

  //
  // Perform some parameter checking
  //
  if (FileName == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check for a valid mode
  //
  switch (OpenMode) {
  case EFI_FILE_MODE_READ:
  case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
  case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
    break;

  default:
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check for valid Attributes for file creation case. 
  //
  if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) {
    return EFI_INVALID_PARAMETER;
  }

  IFile = IFILE_FROM_FHAND (FHand);
  OFile = IFile->OFile;
  Task  = NULL;

  if (Token == NULL) {
    FatWaitNonblockingTask (IFile);
  } else {
    //
    // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
    // But if it calls, the below check can avoid crash.
    //
    if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
      return EFI_UNSUPPORTED;
    }
    Task = FatCreateTask (IFile, Token);
    if (Task == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  }

  //
  // Lock
  //
  FatAcquireLock ();

  //
  // Open the file
  //
  Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);

  //
  // If the file was opened, return the handle to the caller
  //
  if (!EFI_ERROR (Status)) {
    *NewHandle = &NewIFile->Handle;
  }
  //
  // Unlock
  //
  Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task);
  FatReleaseLock ();

  if (Token != NULL) {
    if (!EFI_ERROR (Status)) {
      Status = FatQueueTask (IFile, Task);
    } else {
      FatDestroyTask (Task);
    }
  }

  return Status;
}