/* * 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 . */ #pragma once #include #include #include #include #include #include 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; }; }; namespace pdm { struct Partition; } 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; /* ... */ 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; /* ... */ HandleType partition_handle; VolumeCallback callback; const u8 *format_param; /* ... */ /* TODO: ExtensionTable extension_table; */ /* TODO: ExtensionData ext; */ /* ... */ template constexpr ALWAYS_INLINE bool GetFlagsBit() const { constexpr u32 Mask = (1u << Ix); return (this->flags & Mask) != 0; } template constexpr ALWAYS_INLINE void SetFlagsBit(bool en) { constexpr u32 Mask = (1u << Ix); if (en) { this->flags |= Mask; } else { this->flags &= ~Mask; } } constexpr bool IsAttached() const { return this->GetFlagsBit<0>(); } constexpr void SetAttached(bool en) { this->SetFlagsBit<0>(en); } constexpr bool IsMounted() const { return this->GetFlagsBit<1>(); } constexpr void SetMounted(bool en) { this->SetFlagsBit<1>(en); } constexpr bool IsFormatAfterMountRequested() const { return this->GetFlagsBit<4>(); } constexpr void SetFormatAfterMountRequested(bool en) { this->SetFlagsBit<4>(en); } constexpr bool IsNoFormattingByFatFsLayer() const { return this->GetFlagsBit<5>(); } constexpr void SetNoFormattingByFatFsLayer(bool en) { this->SetFlagsBit<5>(en); } constexpr bool IsDataEraseRequested() const { return this->GetFlagsBit<6>(); } constexpr void SetDataEraseRequested(bool en) { this->SetFlagsBit<6>(en); } constexpr bool IsFlag12() const { return this->GetFlagsBit<12>(); } constexpr void SetFlag12(bool en) { this->SetFlagsBit<12>(en); } }; 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(); }