Example #1
0
EFI_STATUS fsw_efi_dnode_fill_FileInfo(IN FSW_VOLUME_DATA *Volume,
                                       IN struct fsw_dnode *dno,
                                       IN OUT UINTN *BufferSize,
                                       OUT VOID *Buffer)
{
    EFI_STATUS          Status;
    EFI_FILE_INFO       *FileInfo;
    UINTN               RequiredSize;
    struct fsw_dnode_stat sb;

    // make sure the dnode has complete info
    Status = fsw_efi_map_status(fsw_dnode_fill(dno), Volume);
    if (EFI_ERROR(Status))
        return Status;

    // TODO: check/assert that the dno's name is in UTF16

    // check buffer size
    RequiredSize = SIZE_OF_EFI_FILE_INFO + fsw_efi_strsize(&dno->name);
    if (*BufferSize < RequiredSize) {
        // TODO: wind back the directory in this case

#if DEBUG_LEVEL
        Print(L"...BUFFER TOO SMALL\n");
#endif
        *BufferSize = RequiredSize;
        return EFI_BUFFER_TOO_SMALL;
    }

    // fill structure
    ZeroMem(Buffer, RequiredSize);
    FileInfo = (EFI_FILE_INFO *)Buffer;
    FileInfo->Size = RequiredSize;
    FileInfo->FileSize          = dno->size;
    FileInfo->Attribute         = 0;
    if (dno->type == FSW_DNODE_TYPE_DIR)
        FileInfo->Attribute    |= EFI_FILE_DIRECTORY;
    fsw_efi_strcpy(FileInfo->FileName, &dno->name);

    // get the missing info from the fs driver
    ZeroMem(&sb, sizeof(struct fsw_dnode_stat));
    sb.store_time_posix = fsw_efi_store_time_posix;
    sb.store_attr_posix = fsw_efi_store_attr_posix;
    sb.host_data = FileInfo;
    Status = fsw_efi_map_status(fsw_dnode_stat(dno, &sb), Volume);
    if (EFI_ERROR(Status))
        return Status;
    FileInfo->PhysicalSize      = sb.used_bytes;

    // prepare for return
    *BufferSize = RequiredSize;
#if DEBUG_LEVEL
    Print(L"...returning '%s'\n", FileInfo->FileName);
#endif
    return EFI_SUCCESS;
}
Example #2
0
EFI_STATUS fsw_efi_dnode_to_FileHandle(IN struct fsw_dnode *dno,
                                       OUT EFI_FILE **NewFileHandle)
{
    EFI_STATUS          Status;
    FSW_FILE_DATA       *File;

    FSW_MSG_DEBUG((FSW_MSGSTR(__FUNCTION__ ": enter\n")));
    // make sure the dnode has complete info
    Status = fsw_efi_map_status(fsw_dnode_fill(dno), (FSW_VOLUME_DATA *)dno->vol->host_data);
    if (EFI_ERROR(Status)) {
        goto Done;
    }

    // check type
    if (dno->type != FSW_DNODE_TYPE_FILE && dno->type != FSW_DNODE_TYPE_DIR) {
        Status = EFI_UNSUPPORTED;
	goto Done;
    }

    // allocate file structure
    File = AllocateZeroPool(sizeof(FSW_FILE_DATA));
    File->Signature = FSW_FILE_DATA_SIGNATURE;
    if (dno->type == FSW_DNODE_TYPE_FILE)
        File->Type = FSW_EFI_FILE_TYPE_FILE;
    else if (dno->type == FSW_DNODE_TYPE_DIR)
        File->Type = FSW_EFI_FILE_TYPE_DIR;

    // open shandle
    Status = fsw_efi_map_status(fsw_shandle_open(dno, &File->shand),
                                (FSW_VOLUME_DATA *)dno->vol->host_data);
    if (EFI_ERROR(Status)) {
        FreePool(File);
        goto Done;
    }

    // populate the file handle
    File->FileHandle.Revision    = EFI_FILE_HANDLE_REVISION;
    File->FileHandle.Open        = fsw_efi_FileHandle_Open;
    File->FileHandle.Close       = fsw_efi_FileHandle_Close;
    File->FileHandle.Delete      = fsw_efi_FileHandle_Delete;
    File->FileHandle.Read        = fsw_efi_FileHandle_Read;
    File->FileHandle.Write       = fsw_efi_FileHandle_Write;
    File->FileHandle.GetPosition = fsw_efi_FileHandle_GetPosition;
    File->FileHandle.SetPosition = fsw_efi_FileHandle_SetPosition;
    File->FileHandle.GetInfo     = fsw_efi_FileHandle_GetInfo;
    File->FileHandle.SetInfo     = fsw_efi_FileHandle_SetInfo;
    File->FileHandle.Flush       = fsw_efi_FileHandle_Flush;

    *NewFileHandle = &File->FileHandle;
    Status = EFI_SUCCESS;

Done:
    FSW_MSG_DEBUG((FSW_MSGSTR(__FUNCTION__ ": leaving with %r\n"), Status));
    return Status;
}
Example #3
0
EFI_STATUS fsw_efi_dir_read(IN FSW_FILE_DATA *File,
                            IN OUT UINTN *BufferSize,
                            OUT VOID *Buffer)
{
    EFI_STATUS          Status;
    FSW_VOLUME_DATA     *Volume = (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data;
    struct fsw_dnode    *dno;

#if DEBUG_LEVEL
    Print(L"fsw_efi_dir_read...\n");
#endif

    // read the next entry
    Status = fsw_efi_map_status(fsw_dnode_dir_read(&File->shand, &dno),
                                Volume);
    if (Status == EFI_NOT_FOUND) {
        // end of directory
        *BufferSize = 0;
#if DEBUG_LEVEL
        Print(L"...no more entries\n");
#endif
        return EFI_SUCCESS;
    }
    if (EFI_ERROR(Status))
        return Status;

    // get info into buffer
    Status = fsw_efi_dnode_fill_FileInfo(Volume, dno, BufferSize, Buffer);
    fsw_dnode_release(dno);
    return Status;
}
Example #4
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 #5
0
EFI_STATUS fsw_efi_dir_open(IN FSW_FILE_DATA *File,
                            OUT EFI_FILE_PROTOCOL **NewHandle,
                            IN CHAR16 *FileName,
                            IN UINT64 OpenMode,
                            IN UINT64 Attributes)
{
    EFI_STATUS          Status;
    FSW_VOLUME_DATA     *Volume = (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data;
    struct fsw_dnode    *dno;
    struct fsw_dnode    *target_dno;
    struct fsw_string   lookup_path;

#if DEBUG_LEVEL
    Print(L"fsw_efi_dir_open: '%s'\n", FileName);
#endif

    if (OpenMode != EFI_FILE_MODE_READ)
        return EFI_WRITE_PROTECTED;

    lookup_path.type = FSW_STRING_TYPE_UTF16;
    lookup_path.len  = (int)StrLen(FileName);
    lookup_path.size = lookup_path.len * sizeof(fsw_u16);
    lookup_path.data = FileName;

    // resolve the path (symlinks along the way are automatically resolved)
    Status = fsw_efi_map_status(fsw_dnode_lookup_path(File->shand.dnode,
                                                      &lookup_path, '\\',
                                                      &dno),
                                Volume);
    if (EFI_ERROR(Status))
        return Status;

    // if the final node is a symlink, also resolve it
    Status = fsw_efi_map_status(fsw_dnode_resolve(dno, &target_dno),
                                Volume);
    fsw_dnode_release(dno);
    if (EFI_ERROR(Status))
        return Status;
    dno = target_dno;

    // make a new EFI handle for the target dnode
    Status = fsw_efi_dnode_to_FileHandle(dno, NewHandle);
    fsw_dnode_release(dno);
    return Status;
}
Example #6
0
EFI_STATUS fsw_efi_file_read(IN FSW_FILE_DATA *File,
                             IN OUT UINTN *BufferSize,
                             OUT VOID *Buffer)
{
    EFI_STATUS          Status;
    fsw_u32             buffer_size;

    FSW_MSG_DEBUG((FSW_MSGSTR(__FUNCTION__ ": enter to read %d bytes\n"), *BufferSize));

    buffer_size = (fsw_u32)(*BufferSize);
    Status = fsw_efi_map_status(fsw_shandle_read(&File->shand, &buffer_size, Buffer),
                                (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data);
    *BufferSize = buffer_size;

    FSW_MSG_DEBUG((FSW_MSGSTR(__FUNCTION__ ": leaving with %r\n"), Status));
    return Status;
}
Example #7
0
EFI_STATUS fsw_efi_file_read(IN FSW_FILE_DATA *File,
                             IN OUT UINTN *BufferSize,
                             OUT VOID *Buffer)
{
  EFI_STATUS          Status;
  fsw_u32             buffer_size;
  
#if DEBUG_LEVEL
  Print(L"fsw_efi_file_read %d bytes\n", *BufferSize);
#endif
  
  buffer_size = (fsw_u32)*BufferSize;
  Status = fsw_efi_map_status(fsw_shandle_read(&File->shand, &buffer_size, Buffer),
                              (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data);
  *BufferSize = buffer_size;
  
  return Status;
}
Example #8
0
EFI_STATUS fsw_efi_AttachVolume(IN EFI_HANDLE            ControllerHandle,
                                  IN EFI_DISK_IO_PROTOCOL  *pDiskIo,
                                  IN EFI_BLOCK_IO_PROTOCOL *pBlockIo)
{
    EFI_STATUS      Status;
    FSW_VOLUME_DATA *pVolume;

    pVolume = AllocateZeroPool(sizeof(FSW_VOLUME_DATA));
    if (pVolume == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    pVolume->Signature                  = FSW_VOLUME_DATA_SIGNATURE;
    pVolume->Handle                     = ControllerHandle;
    pVolume->DiskIo                     = pDiskIo;
    pVolume->MediaId                    = pBlockIo->Media->MediaId;
    pVolume->FileSystem.Revision        = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
    pVolume->FileSystem.OpenVolume      = fsw_efi_FileSystem_OpenVolume;
    pVolume->LastIOStatus               = EFI_SUCCESS;

    Status = fsw_efi_map_status(fsw_mount(pVolume, &fsw_efi_host_table,
                                          &FSW_FSTYPE_TABLE_NAME(FSTYPE), &pVolume->vol),
                                pVolume);
    if (EFI_ERROR(Status)) {
        goto Done;
    }

    Status = BS->InstallMultipleProtocolInterfaces(
                     &pVolume->Handle,
                     &PROTO_NAME(SimpleFileSystemProtocol),
                     &pVolume->FileSystem,
                     NULL); 
    if (EFI_ERROR(Status)) {
        goto Done;
    }
    DEBUG((EFI_D_INIT, "fsw_efi: Installed volume on %p\n", ControllerHandle));
Done:
    if (EFI_ERROR(Status)) {
        fsw_efi_DetachVolume(pVolume);
    }
    return Status;
}
Example #9
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_PROTOCOL  *BlockIo;
    EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
    EFI_DISK_IO_PROTOCOL   *DiskIo;
    EFI_DISK_IO2_PROTOCOL  *DiskIo2;
    FSW_VOLUME_DATA     *Volume;

#if DEBUG_LEVEL
//    Print(L"fsw_efi_DriverBinding_Start\n");
#endif

    // open consumed protocols
    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(BlockIo2Protocol),
                              (VOID **) &BlockIo2,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    if (EFI_ERROR(Status)) {
      BlockIo2 = NULL;
    }

    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 ((BlockIo2 == NULL) && EFI_ERROR(Status)) {
//        Print(L"Fsw ERROR: OpenProtocol(BlockIo) returned %x\n", Status);
        return Status;
    }

    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(DiskIo2Protocol),
                              (VOID **) &DiskIo2,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_BY_DRIVER);
    if (EFI_ERROR(Status)) {
      DiskIo2 = NULL;
    }

    Status = BS->OpenProtocol(ControllerHandle,
                              &PROTO_NAME(DiskIoProtocol),
                              (VOID **) &DiskIo,
                              This->DriverBindingHandle,
                              ControllerHandle,
                              EFI_OPEN_PROTOCOL_BY_DRIVER);
    if ((DiskIo2 == NULL) && EFI_ERROR(Status)) {
 //       DBG("Fsw ERROR: OpenProtocol(DiskIo) returned %r\n", Status);
        return Status;
    }

    // allocate volume structure
    Volume = AllocateZeroPool(sizeof(FSW_VOLUME_DATA));
    Volume->Signature       = FSW_VOLUME_DATA_SIGNATURE;
    Volume->Handle          = ControllerHandle;
    Volume->DiskIo          = DiskIo;
    Volume->DiskIo2         = DiskIo2;
    Volume->LastIOStatus    = EFI_SUCCESS;

    if (BlockIo2 != NULL) {
      Volume->MediaId         = BlockIo2->Media->MediaId;
    } else {
      Volume->MediaId         = BlockIo->Media->MediaId;
    }

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

    if (!EFI_ERROR(Status)) {
        // register the SimpleFileSystem protocol
        Volume->FileSystem.Revision     = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
        Volume->FileSystem.OpenVolume   = fsw_efi_FileSystem_OpenVolume;
        Status = BS->InstallMultipleProtocolInterfaces(
											&ControllerHandle,
											&PROTO_NAME(SimpleFileSystemProtocol), 
											&Volume->FileSystem,
                                            NULL);
        if (EFI_ERROR(Status)) {
//            Print(L"Fsw ERROR: InstallMultipleProtocolInterfaces returned %x\n", Status);
        }
    }

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

        BS->CloseProtocol(ControllerHandle,
                          &PROTO_NAME(DiskIo2Protocol),
                          This->DriverBindingHandle,
                          ControllerHandle);

        BS->CloseProtocol(ControllerHandle,
                          &PROTO_NAME(DiskIoProtocol),
                          This->DriverBindingHandle,
                          ControllerHandle);
    }

    return Status;
}
Example #10
0
EFI_STATUS fsw_efi_dnode_getinfo(IN FSW_FILE_DATA *File,
                                 IN EFI_GUID *InformationType,
                                 IN OUT UINTN *BufferSize,
                                 OUT VOID *Buffer)
{
    EFI_STATUS          Status;
    FSW_VOLUME_DATA     *Volume = (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data;
    EFI_FILE_SYSTEM_INFO *FSInfo;
    UINTN               RequiredSize;
    struct fsw_volume_stat vsb;

    if (CompareGuid(InformationType, &GUID_NAME(FileInfo))) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_INFO\n");
#endif

        Status = fsw_efi_dnode_fill_FileInfo(Volume, File->shand.dnode, BufferSize, Buffer);

    } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemInfo))) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_INFO\n");
#endif

        // check buffer size
        RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + fsw_efi_strsize(&Volume->vol->label);
        if (*BufferSize < RequiredSize) {
            *BufferSize = RequiredSize;
            return EFI_BUFFER_TOO_SMALL;
        }

        // fill structure
        FSInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
        FSInfo->Size        = RequiredSize;
        FSInfo->ReadOnly    = TRUE;
        FSInfo->BlockSize   = Volume->vol->log_blocksize;
        fsw_efi_strcpy(FSInfo->VolumeLabel, &Volume->vol->label);

        // get the missing info from the fs driver
        ZeroMem(&vsb, sizeof(struct fsw_volume_stat));
        Status = fsw_efi_map_status(fsw_volume_stat(Volume->vol, &vsb), Volume);
        if (EFI_ERROR(Status))
            return Status;
        FSInfo->VolumeSize  = vsb.total_bytes;
        FSInfo->FreeSpace   = vsb.free_bytes;

        // prepare for return
        *BufferSize = RequiredSize;
        Status = EFI_SUCCESS;

    } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemVolumeLabelInfoId))) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_VOLUME_LABEL\n");
#endif

        // check buffer size
        RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + fsw_efi_strsize(&Volume->vol->label);
        if (*BufferSize < RequiredSize) {
            *BufferSize = RequiredSize;
            return EFI_BUFFER_TOO_SMALL;
        }

        // copy volume label
        fsw_efi_strcpy(((EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Buffer)->VolumeLabel, &Volume->vol->label);

        // prepare for return
        *BufferSize = RequiredSize;
        Status = EFI_SUCCESS;

    } else {
        Status = EFI_UNSUPPORTED;
    }

    return Status;
}