pf2: add volume init, context register/unregister

This commit is contained in:
Michael Scire
2020-11-26 03:27:07 -08:00
parent f9c5470ac9
commit 7b01d59b3b
19 changed files with 883 additions and 85 deletions

View File

@@ -25,3 +25,5 @@
#include <vapours/prfile2/prfile2_system.hpp>
#include <vapours/prfile2/pdm/prfile2_pdm_api.hpp>
#include <vapours/prfile2/pdm/prfile2_pdm_disk_management.hpp>
#include <vapours/prfile2/prfile2_fatfs.hpp>
#include <vapours/prfile2/prfile2_volume.hpp>

View File

@@ -25,4 +25,7 @@ namespace ams::prfile2::pdm {
pdm::Error OpenDisk(InitDisk *init_disk_table, HandleType *out);
pdm::Error CloseDisk(HandleType handle);
pdm::Error OpenPartition(HandleType disk_handle, u16 part_id, HandleType *out);
pdm::Error ClosePartition(HandleType handle);
}

View File

@@ -22,4 +22,6 @@ namespace ams::prfile2::pf {
int Initialize(u32 config, void *param);
int Attach(DriveTable **drive_table);
}

View File

@@ -15,46 +15,59 @@
*/
#pragma once
#include <vapours/prfile2/prfile2_build_config.hpp>
#include <vapours/prfile2/prfile2_handle.hpp>
namespace ams::prfile2::pf {
using DriveCharacter = char;
enum Error {
Error_NoError = 0,
Error_Ok = Error_NoError,
Error_NoError = 0,
Error_Ok = Error_NoError,
Error_EPERM = 1,
Error_ENOENT = 2,
Error_ESRCH = 3,
Error_EIO = 5,
Error_ENOEXEC = 8,
Error_EBADF = 9,
Error_ENOMEM = 12,
Error_EACCES = 13,
Error_EBUSY = 16,
Error_EEXIST = 17,
Error_ENODEV = 19,
Error_EISDIR = 21,
Error_EINVAL = 22,
Error_ENFILE = 23,
Error_EMFILE = 24,
Error_EFBIG = 27,
Error_ENOSPC = 28,
Error_ENOLCK = 46,
Error_ENOSYS = 88,
Error_ENOTEMPTY = 90,
Error_Generic = -1,
Error_EMOD_NOTREG = 100,
Error_EMOD_NOTSPRT = 101,
Error_EMOD_FCS = 102,
Error_EMOD_SAFE = 103,
Error_ENOMEDIUM = 123,
Error_EEXFAT_NOTSPRT = 200,
Error_DFNC = 0x1000,
Error_SYSTEM = -1,
Error_InvalidFileName = 1,
Error_InvalidPathName = 2,
Error_FileNotFound = 3,
Error_TooManyVolumesAttached = 4,
Error_DirectoryFull = 5,
Error_VolumeFull = 6,
Error_InvalidDiskFormat = 7,
Error_FileAlreadyExists = 8,
Error_VolumeNotMounted = 9,
Error_InvalidParameter = 10,
Error_WriteProtected = 11,
Error_UnsupportedFormat = 12,
Error_BrokenClusterChain = 13,
Error_InvalidClusterNum = 14,
Error_InvalidBpb = 15,
Error_AccessOutOfVolume = 16,
Error_DriverError = 17,
Error_InvalidVolumeLabel = 18,
Error_FileOpened = 19,
Error_NotADirectory = 20,
Error_TooManyFilesOpenedS = 21,
Error_TooManyFilesOpenedU = 22,
Error_NotAFile = 23,
Error_ReadOnly = 24,
Error_LockError = 25,
Error_InternalError = 26,
Error_EndOfFile = 27,
Error_AccessNotAllowed = 28,
Error_DirectoryNotEmpty = 29,
Error_NotEnoughCachePages = 30,
Error_DifferentDrive = 31,
Error_DifferentEntry = 32,
Error_InvalidEntry = 33,
Error_InvalidSector = 34,
Error_BrokenVolume = 35,
Error_NotEffective = 36,
Error_FileSizeOver = 37,
Error_InvalidFileDiscriptor = 38,
Error_InvalidLockFile = 39,
Error_ExtensionNotRegistered = 40,
Error_ExtensionError = 41,
};
constexpr inline const int ReturnValueNoError = 0;
@@ -68,4 +81,44 @@ namespace ams::prfile2::pf {
}
}
struct CachePage {
u16 status;
u16 option;
u8 *buffer_head;
u8 *buffer_cur;
u8 *buffer_dirty_start;
u8 *buffer_dirty_end;
u32 size;
u32 sector;
void *signature;
CachePage *next;
CachePage *prev;
};
static_assert(util::is_pod<CachePage>::value);
constexpr inline auto SectorBufferSize = 0x200;
constexpr inline auto Log2SectorBufferSize = 9;
static_assert((1u << Log2SectorBufferSize) == SectorBufferSize);
using SectorBuffer = u8[SectorBufferSize];
static_assert(sizeof(SectorBuffer) == SectorBufferSize);
struct CacheSetting {
CachePage *pages;
SectorBuffer *buffers;
u16 num_fat_pages;
u16 num_data_pages;
u32 fat_buf_size;
u32 data_buf_size;
};
struct DriveTable {
CacheSetting *cache;
HandleType partition_handle;
DriveCharacter drive_char;
u8 status;
};
using TailBuf = u32;
}

View File

@@ -25,53 +25,43 @@ namespace ams::prfile2 {
constexpr inline const auto MaximumOpenDirectoryCountSystem = pf::MaximumDirectoryCount;
constexpr inline const auto MaximumOpenDirectoryCountUser = pf::MaximumDirectoryCount;
enum InternalError {
InternalError_NoError = 0,
InternalError_Ok = InternalError_NoError,
enum Error {
Error_NoError = 0,
Error_Ok = Error_NoError,
InternalError_Generic = -1,
Error_EPERM = 1,
Error_ENOENT = 2,
Error_ESRCH = 3,
Error_EIO = 5,
Error_ENOEXEC = 8,
Error_EBADF = 9,
Error_ENOMEM = 12,
Error_EACCES = 13,
Error_EBUSY = 16,
Error_EEXIST = 17,
Error_ENODEV = 19,
Error_EISDIR = 21,
Error_EINVAL = 22,
Error_ENFILE = 23,
Error_EMFILE = 24,
Error_EFBIG = 27,
Error_ENOSPC = 28,
Error_ENOLCK = 46,
Error_ENOSYS = 88,
Error_ENOTEMPTY = 90,
InternalError_InvalidFileName = 1,
InternalError_InvalidPathName = 2,
InternalError_FileNotFound = 3,
InternalError_TooManyVolumesAttached = 4,
InternalError_DirectoryFull = 5,
InternalError_VolumeFull = 6,
InternalError_InvalidDiskFormat = 7,
InternalError_FileAlreadyExists = 8,
InternalError_VolumeNotMounted = 9,
InternalError_InvalidParameter = 10,
InternalError_WriteProtected = 11,
InternalError_UnsupportedFormat = 12,
InternalError_BrokenClusterChain = 13,
InternalError_InvalidClusterNum = 14,
InternalError_InvalidBpb = 15,
InternalError_AccessOutOfVolume = 16,
InternalError_DriverError = 17,
InternalError_InvalidVolumeLabel = 18,
InternalError_FileOpened = 19,
InternalError_NotADirectory = 20,
InternalError_TooManyFilesOpenedS = 21,
InternalError_TooManyFilesOpenedU = 22,
InternalError_NotAFile = 23,
InternalError_ReadOnly = 24,
InternalError_LockError = 25,
InternalError_InternalError = 26,
InternalError_EndOfFile = 27,
InternalError_AccessNotAllowed = 28,
InternalError_DirectoryNotEmpty = 29,
InternalError_NotEnoughCachePages = 30,
InternalError_DifferentDrive = 31,
InternalError_DifferentEntry = 32,
InternalError_InvalidEntry = 33,
InternalError_InvalidSector = 34,
InternalError_BrokenVolume = 35,
InternalError_NotEffective = 36,
InternalError_FileSizeOver = 37,
InternalError_InvalidFileDiscriptor = 38,
InternalError_InvalidLockFile = 39,
InternalError_ExtensionNotRegistered = 40,
InternalError_ExtensionError = 41,
Error_EMOD_NOTREG = 100,
Error_EMOD_NOTSPRT = 101,
Error_EMOD_FCS = 102,
Error_EMOD_SAFE = 103,
Error_ENOMEDIUM = 123,
Error_EEXFAT_NOTSPRT = 200,
Error_DFNC = 0x1000,
Error_SYSTEM = -1,
};
constexpr inline const u32 InvalidSector = std::numeric_limits<u32>::max();

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/prfile2/prfile2_common.hpp>
namespace ams::prfile2 {
constexpr inline const auto LongNamePathCharacters = 260;
struct Volume;
struct DirectoryEntry {
u16 long_name[LongNamePathCharacters];
u32 attr;
u64 file_size;
u8 create_time_ms;
u16 create_time;
u16 create_date;
u8 create_flags;
u8 access_time_ms;
u16 access_time;
u16 access_date;
u8 access_flags;
u8 modify_time_ms;
u16 modify_time;
u16 modify_date;
u8 modify_flags;
Volume *volume;
u32 path_len;
u32 start_cluster;
u32 entry_sector;
u16 entry_offset;
/* ... */
u8 num_entry_lfns;
u8 ordinal;
u8 check_sum;
char short_name[13];
u8 small_letter_flag;
/* ... */
u16 full_path[LongNamePathCharacters];
};
struct DirectoryTail {
u32 tracker_size;
pf::TailBuf tracker_buf[1];
u32 *tracker_bits;
};
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/prfile2/prfile2_common.hpp>
namespace ams::prfile2 {
struct FatHint {
u32 chain_index;
u32 cluster;
};
using LastAccess = FatHint;
struct LastCluster {
u32 num_last_cluster;
u32 max_chain_index;
};
struct ClusterLinkForVolume {
u16 flag;
u16 interval;
u32 *buffer;
u32 link_max;
};
using ClusterBuf = u32;
struct ClusterLink {
u64 position;
ClusterBuf *buffer;
u16 interval;
u16 interval_offset;
u32 save_index;
u32 max_count;
};
struct Volume;
struct FatFileDescriptor {
u32 start_cluster;
u32 *p_start_cluster;
LastCluster last_cluster;
LastAccess last_access;
ClusterLink cluster_link;
FatHint *hint;
Volume *volume;
/* ... */
};
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/prfile2/prfile2_common.hpp>
namespace ams::prfile2::fatfs {
pf::Error Initialize(u32 config, void *param);
}

View File

@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/prfile2/prfile2_common.hpp>
#include <vapours/prfile2/prfile2_build_config.hpp>
namespace ams::prfile2 {

View File

@@ -20,6 +20,6 @@ namespace ams::prfile2::system {
void Initialize();
pf::Error GetCurrentContextId(u64 *out);
int GetCurrentContextId(u64 *out);
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/prfile2/prfile2_common.hpp>
#include <vapours/prfile2/prfile2_critical_section.hpp>
#include <vapours/prfile2/prfile2_entry.hpp>
#include <vapours/prfile2/prfile2_fat.hpp>
namespace ams::prfile2 {
constexpr inline const auto MaxVolumes = 5;
struct Cursor {
u64 position;
u32 sector;
u32 file_sector_index;
u16 offset_in_sector;
};
struct DirectoryCursor {
u32 physical_entry_index;
u32 logical_entry_index;
u32 logical_seek_index;
};
struct File;
struct FileLock {
u16 mode;
u16 count;
u16 waiting_count;
File *owner;
u32 resource;
};
struct SystemFileDescriptor {
u32 status;
FatFileDescriptor ffd;
DirectoryEntry dir_entry;
FileLock lock;
u16 num_handlers;
SystemFileDescriptor *next_sfd;
};
struct SystemDirectoryDescriptor {
u32 status;
u16 num_handlers;
FatFileDescriptor ffd;
DirectoryEntry dir_entry;
/* ... */
u64 context_id;
/* ... */
};
struct File {
u32 status;
/* TODO OpenMode */ u32 open_mode;
SystemFileDescriptor *sfd;
FatHint hint;
LastAccess last_access;
pf::Error last_error;
Cursor cursor;
u16 lock_count;
};
struct Directory {
u32 stat;
SystemDirectoryDescriptor *sdd;
FatHint hint;
DirectoryCursor cursor;
/* ... */
};
struct BiosParameterBlock {
u16 bytes_per_sector;
u32 num_reserved_sectors;
u16 num_root_dir_entries;
u32 sectors_per_cluster;
u8 num_fats;
u32 total_sectors;
u32 sectors_per_fat;
u32 root_dir_cluster;
u16 fs_info_sector;
u16 backup_boot_sector;
u16 ext_flags;
u16 ext_flags_;
u8 media;
FatFormat fat_fmt;
u8 log2_bytes_per_sector;
u8 log2_sectors_per_cluster;
u8 num_active_fats;
u8 num_active_fats_;
u16 num_root_dir_sectors;
u32 active_fat_sector;
u32 active_fat_sector_;
u32 first_root_dir_sector;
u32 first_data_sector;
u32 num_clusters;
/* ... */
};
using VolumeCallback = void (*)();
struct VolumeContext {
u64 context_id;
u32 volume_id;
DirectoryEntry dir_entries[MaxVolumes];
pf::Error last_error;
pf::Error last_driver_error[MaxVolumes];
pf::Error last_unk_error[MaxVolumes];
/* ... */
VolumeContext *next_used_context;
union {
VolumeContext *prev_used_context;
VolumeContext *next_free_context;
};
};
struct Volume {
BiosParameterBlock bpb;
u32 num_free_clusters;
u32 num_free_clusters_;
u32 last_free_cluster;
u32 last_free_cluster_;
SystemFileDescriptor sfds[MaximumOpenFileCountSystem];
File ufds[MaximumOpenFileCountUser];
SystemDirectoryDescriptor sdds[MaximumOpenDirectoryCountSystem];
Directory udds[MaximumOpenDirectoryCountUser];
u32 num_open_files;
u32 num_open_directories;
/* ... */
/* TODO: SectorCache cache; */
VolumeContext *context;
u64 context_id;
DirectoryTail tail_entry;
u32 volume_config;
u32 file_config;
u32 flags;
pf::DriveCharacter drive_char;
CriticalSection critical_section;
u16 fsi_flag;
ClusterLinkForVolume cluster_link;
pf::Error last_error;
pf::Error last_driver_error;
/* ... */
void *partition;
VolumeCallback callback;
const u8 *format_param;
/* ... */
/* TODO: ExtensionTable extension_table; */
/* TODO: ExtensionData ext; */
/* ... */
};
struct VolumeSet {
bool initialized;
u32 num_attached_drives;
u32 num_mounted_volumes;
u32 config;
void *param;
/* TODO: CodeSet codeset; */
u32 setting;
CriticalSection critical_section;
VolumeContext default_context;
VolumeContext contexts[MaxVolumes];
VolumeContext *used_context_head;
VolumeContext *used_context_tail;
VolumeContext *free_context_head;
Volume volumes[MaxVolumes];
};
}
namespace ams::prfile2::vol {
pf::Error Initialize(u32 config, void *param);
pf::Error Attach(pf::DriveTable *drive_table);
VolumeContext *RegisterContext(u64 *out_context_id);
pf::Error UnregisterContext();
}