Update for latest libnx

This commit is contained in:
Michael Scire 2019-06-03 12:15:39 -07:00
parent 4387da1ecc
commit 50e307b4b7
19 changed files with 97 additions and 215 deletions

View file

@ -39,7 +39,7 @@ void BpcRebootManager::Initialize() {
/* Read payload file. */ /* Read payload file. */
size_t actual_size; size_t actual_size;
fsFileRead(&payload_file, 0, g_reboot_payload, IRAM_PAYLOAD_MAX_SIZE, &actual_size); fsFileRead(&payload_file, 0, g_reboot_payload, IRAM_PAYLOAD_MAX_SIZE, FS_READOPTION_NONE, &actual_size);
g_payload_loaded = true; g_payload_loaded = true;

View file

@ -48,13 +48,13 @@ class DirectorySaveDataFile : public IFile {
virtual Result FlushImpl() override { virtual Result FlushImpl() override {
return this->base_file->Flush(); return this->base_file->Flush();
} }
virtual Result WriteImpl(u64 offset, void *buffer, u64 size, bool flush) override { virtual Result WriteImpl(u64 offset, void *buffer, u64 size, u32 option) override {
return this->base_file->Write(offset, buffer, size, flush); return this->base_file->Write(offset, buffer, size, option);
} }
virtual Result SetSizeImpl(u64 size) override { virtual Result SetSizeImpl(u64 size) override {
return this->base_file->SetSize(size); return this->base_file->SetSize(size);
} }
virtual Result OperateRangeImpl(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { virtual Result OperateRangeImpl(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return this->base_file->OperateRange(operation_type, offset, size, out_range_info); return this->base_file->OperateRange(operation_type, offset, size, out_range_info);
} }
}; };

View file

@ -45,7 +45,12 @@ Result FileStorage::Read(void *buffer, size_t size, u64 offset) {
return ResultFsOutOfRange; return ResultFsOutOfRange;
} }
return this->file->Read(&read_size, offset, buffer, size); /* Nintendo doesn't do check output read size, but we will for safety. */
R_TRY(this->file->Read(&read_size, offset, buffer, size));
if (read_size != size && read_size) {
return this->Read(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + read_size), size - read_size, offset + read_size);
}
return ResultSuccess;
} }
Result FileStorage::Write(void *buffer, size_t size, u64 offset) { Result FileStorage::Write(void *buffer, size_t size, u64 offset) {
@ -85,14 +90,14 @@ Result FileStorage::SetSize(u64 size) {
return this->file->SetSize(size); return this->file->SetSize(size);
} }
Result FileStorage::OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { Result FileStorage::OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) {
Result rc; Result rc;
switch (operation_type) { switch (operation_type) {
case 2: /* TODO: OperationType_Invalidate */ case FsOperationId_InvalidateCache:
case 3: /* TODO: OperationType_Query */ case FsOperationId_QueryRange:
if (size == 0) { if (size == 0) {
if (operation_type == 3) { if (operation_type == FsOperationId_QueryRange) {
if (out_range_info == nullptr) { if (out_range_info == nullptr) {
return ResultFsNullptrArgument; return ResultFsNullptrArgument;
} }

View file

@ -50,5 +50,5 @@ class FileStorage : public IStorage {
virtual Result Flush() override; virtual Result Flush() override;
virtual Result GetSize(u64 *out_size) override; virtual Result GetSize(u64 *out_size) override;
virtual Result SetSize(u64 size) override; virtual Result SetSize(u64 size) override;
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override; virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override;
}; };

View file

@ -70,8 +70,7 @@ class IFile {
if (buffer == nullptr) { if (buffer == nullptr) {
return ResultFsNullptrArgument; return ResultFsNullptrArgument;
} }
const bool flush = (flags & 1) != 0; return WriteImpl(offset, buffer, size, flags);
return WriteImpl(offset, buffer, size, flush);
} }
Result Write(uint64_t offset, void *buffer, uint64_t size, bool flush = false) { Result Write(uint64_t offset, void *buffer, uint64_t size, bool flush = false) {
@ -88,8 +87,8 @@ class IFile {
return SetSizeImpl(size); return SetSizeImpl(size);
} }
Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) {
if (operation_type == 3) { if (operation_type == FsOperationId_QueryRange) {
return OperateRangeImpl(operation_type, offset, size, out_range_info); return OperateRangeImpl(operation_type, offset, size, out_range_info);
} }
return ResultFsUnsupportedOperation; return ResultFsUnsupportedOperation;
@ -101,9 +100,9 @@ class IFile {
virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) = 0; virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) = 0;
virtual Result GetSizeImpl(u64 *out) = 0; virtual Result GetSizeImpl(u64 *out) = 0;
virtual Result FlushImpl() = 0; virtual Result FlushImpl() = 0;
virtual Result WriteImpl(u64 offset, void *buffer, u64 size, bool flush) = 0; virtual Result WriteImpl(u64 offset, void *buffer, u64 size, u32 option) = 0;
virtual Result SetSizeImpl(u64 size) = 0; virtual Result SetSizeImpl(u64 size) = 0;
virtual Result OperateRangeImpl(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0; virtual Result OperateRangeImpl(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0;
}; };
class IFileInterface : public IServiceObject { class IFileInterface : public IServiceObject {
@ -135,7 +134,7 @@ class IFileInterface : public IServiceObject {
return this->base_file->GetSize(size.GetPointer()); return this->base_file->GetSize(size.GetPointer());
}; };
virtual Result OperateRange(Out<FsRangeInfo> range_info, u32 operation_type, u64 offset, u64 size) final { virtual Result OperateRange(Out<FsRangeInfo> range_info, u32 operation_type, u64 offset, u64 size) final {
return this->base_file->OperateRange(operation_type, offset, size, range_info.GetPointer()); return this->base_file->OperateRange(static_cast<FsOperationId>(operation_type), offset, size, range_info.GetPointer());
}; };
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
@ -174,7 +173,7 @@ class ProxyFile : public IFile {
virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) override { virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) override {
size_t out_sz; size_t out_sz;
Result rc = fsFileRead(this->base_file.get(), offset, buffer, size, &out_sz); Result rc = fsFileRead(this->base_file.get(), offset, buffer, size, FS_READOPTION_NONE, &out_sz);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
*out = out_sz; *out = out_sz;
} }
@ -187,18 +186,13 @@ class ProxyFile : public IFile {
virtual Result FlushImpl() override { virtual Result FlushImpl() override {
return fsFileFlush(this->base_file.get()); return fsFileFlush(this->base_file.get());
} }
virtual Result WriteImpl(u64 offset, void *buffer, u64 size, bool flush) override { virtual Result WriteImpl(u64 offset, void *buffer, u64 size, u32 option) override {
Result rc = fsFileWrite(this->base_file.get(), offset, buffer, size); return fsFileWrite(this->base_file.get(), offset, buffer, size, option);
if (R_SUCCEEDED(rc)) {
/* libnx doesn't allow passing the flush flag. */
rc = fsFileFlush(this->base_file.get());
}
return rc;
} }
virtual Result SetSizeImpl(u64 size) override { virtual Result SetSizeImpl(u64 size) override {
return fsFileSetSize(this->base_file.get(), size); return fsFileSetSize(this->base_file.get(), size);
} }
virtual Result OperateRangeImpl(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { virtual Result OperateRangeImpl(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return fsFileOperateRange(this->base_file.get(), operation_type, offset, size, out_range_info); return fsFileOperateRange(this->base_file.get(), operation_type, offset, size, out_range_info);
} }
}; };

View file

@ -39,7 +39,7 @@ class IStorage {
virtual Result Flush() = 0; virtual Result Flush() = 0;
virtual Result SetSize(u64 size) = 0; virtual Result SetSize(u64 size) = 0;
virtual Result GetSize(u64 *out_size) = 0; virtual Result GetSize(u64 *out_size) = 0;
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0; virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0;
static inline bool IsRangeValid(uint64_t offset, uint64_t size, uint64_t total_size) { static inline bool IsRangeValid(uint64_t offset, uint64_t size, uint64_t total_size) {
return size <= total_size && offset <= total_size - size; return size <= total_size && offset <= total_size - size;
@ -76,7 +76,7 @@ class IStorageInterface : public IServiceObject {
return this->base_storage->GetSize(size.GetPointer()); return this->base_storage->GetSize(size.GetPointer());
}; };
virtual Result OperateRange(Out<FsRangeInfo> range_info, u32 operation_type, u64 offset, u64 size) final { virtual Result OperateRange(Out<FsRangeInfo> range_info, u32 operation_type, u64 offset, u64 size) final {
return this->base_storage->OperateRange(operation_type, offset, size, range_info.GetPointer()); return this->base_storage->OperateRange(static_cast<FsOperationId>(operation_type), offset, size, range_info.GetPointer());
}; };
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
@ -109,7 +109,7 @@ class IROStorage : public IStorage {
return ResultFsUnsupportedOperation; return ResultFsUnsupportedOperation;
}; };
virtual Result GetSize(u64 *out_size) = 0; virtual Result GetSize(u64 *out_size) = 0;
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0; virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0;
}; };
@ -143,33 +143,33 @@ class ProxyStorage : public IStorage {
virtual Result SetSize(u64 size) override { virtual Result SetSize(u64 size) override {
return fsStorageSetSize(this->base_storage, size); return fsStorageSetSize(this->base_storage, size);
}; };
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info);
}; };
}; };
class ROProxyStorage : public IROStorage { class ReadOnlyStorageAdapter : public IROStorage {
private: private:
FsStorage *base_storage; std::shared_ptr<IStorage> base_storage;
IStorage *storage;
public: public:
ROProxyStorage(FsStorage *s) : base_storage(s) { ReadOnlyStorageAdapter(IStorage *s) : base_storage(s) {
this->storage = this->base_storage.get();
}
ReadOnlyStorageAdapter(std::shared_ptr<IStorage> s) : base_storage(s) {
this->storage = this->base_storage.get();
}
virtual ~ReadOnlyStorageAdapter() {
/* ... */ /* ... */
}; }
ROProxyStorage(FsStorage s) {
this->base_storage = new FsStorage(s);
};
virtual ~ROProxyStorage() {
fsStorageClose(base_storage);
delete base_storage;
};
public: public:
virtual Result Read(void *buffer, size_t size, u64 offset) override { virtual Result Read(void *buffer, size_t size, u64 offset) override {
return fsStorageRead(this->base_storage, offset, buffer, size); return this->base_storage->Read(buffer, size, offset);
}; };
virtual Result GetSize(u64 *out_size) override { virtual Result GetSize(u64 *out_size) override {
return fsStorageGetSize(this->base_storage, out_size); return this->base_storage->GetSize(out_size);
}; };
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); return this->base_storage->OperateRange(operation_type, offset, size, out_range_info);
}; };
}; };

View file

@ -19,7 +19,7 @@
#include "fs_shim.h" #include "fs_shim.h"
/* Missing fsp-srv commands. */ /* Missing fsp-srv commands. */
Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId) { Result fsOpenBisStorageFwd(Service* s, FsStorage* out, FsBisStorageId PartitionId) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -264,85 +264,3 @@ Result fsOpenSaveDataFileSystemFwd(Service *s, FsFileSystem* out, u8 inval, FsSa
return rc; return rc;
} }
/* Missing FS File commands. */
Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 op_id;
u64 off;
u64 len;
} *raw;
raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
raw->op_id = op_id;
raw->off = off;
raw->len = len;
Result rc = serviceIpcDispatch(&f->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp;
serviceIpcParse(&f->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
}
return rc;
}
/* Missing FS Storage commands. */
Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeInfo *out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 op_id;
u64 off;
u64 len;
} *raw;
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
raw->op_id = op_id;
raw->off = off;
raw->len = len;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
}
return rc;
}

View file

@ -11,25 +11,14 @@
extern "C" { extern "C" {
#endif #endif
/* TODO: Reverse this more. */
typedef struct {
u32 flags[0x40/sizeof(u32)];
} FsRangeInfo;
/* Missing fsp-srv commands. */ /* Missing fsp-srv commands. */
Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId); Result fsOpenBisStorageFwd(Service* s, FsStorage* out, FsBisStorageId PartitionId);
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
Result fsOpenFileSystemWithPatchFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType); Result fsOpenFileSystemWithPatchFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType);
Result fsOpenFileSystemWithIdFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath); Result fsOpenFileSystemWithIdFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath);
Result fsOpenSaveDataFileSystemFwd(Service* s, FsFileSystem* out, u8 inval, FsSave *save); Result fsOpenSaveDataFileSystemFwd(Service* s, FsFileSystem* out, u8 inval, FsSave *save);
/* Missing FS File commands. */
Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out);
/* Missing FS Storage commands. */
Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeInfo *out);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -23,7 +23,7 @@
IStorage::~IStorage() = default; IStorage::~IStorage() = default;
LayeredRomFS::LayeredRomFS(std::shared_ptr<RomInterfaceStorage> s_r, std::shared_ptr<RomFileStorage> f_r, u64 tid) : storage_romfs(s_r), file_romfs(f_r), title_id(tid) { LayeredRomFS::LayeredRomFS(std::shared_ptr<IROStorage> s_r, std::shared_ptr<IROStorage> f_r, u64 tid) : storage_romfs(s_r), file_romfs(f_r), title_id(tid) {
/* Start building the new virtual romfs. */ /* Start building the new virtual romfs. */
RomFSBuildContext build_ctx(this->title_id); RomFSBuildContext build_ctx(this->title_id);
this->p_source_infos = std::shared_ptr<std::vector<RomFSSourceInfo>>(new std::vector<RomFSSourceInfo>(), [](std::vector<RomFSSourceInfo> *to_delete) { this->p_source_infos = std::shared_ptr<std::vector<RomFSSourceInfo>>(new std::vector<RomFSSourceInfo>(), [](std::vector<RomFSSourceInfo> *to_delete) {
@ -95,7 +95,7 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
fatalSimple(rc); fatalSimple(rc);
} }
size_t out_read; size_t out_read;
if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read)))) {
fatalSimple(rc); fatalSimple(rc);
} }
if (out_read != cur_read_size) { if (out_read != cur_read_size) {
@ -111,7 +111,7 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
fatalSimple(rc); fatalSimple(rc);
} }
size_t out_read; size_t out_read;
if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read)))) {
fatalSimple(rc); fatalSimple(rc);
} }
if (out_read != cur_read_size) { if (out_read != cur_read_size) {
@ -164,9 +164,9 @@ Result LayeredRomFS::GetSize(u64 *out_size) {
*out_size = (*this->p_source_infos)[this->p_source_infos->size() - 1].virtual_offset + (*this->p_source_infos)[this->p_source_infos->size() - 1].size; *out_size = (*this->p_source_infos)[this->p_source_infos->size() - 1].virtual_offset + (*this->p_source_infos)[this->p_source_infos->size() - 1].size;
return ResultSuccess; return ResultSuccess;
} }
Result LayeredRomFS::OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { Result LayeredRomFS::OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) {
/* TODO: How should I implement this for a virtual romfs? */ /* TODO: How should I implement this for a virtual romfs? */
if (operation_type == 3) { if (operation_type == FsOperationId_QueryRange) {
*out_range_info = {0}; *out_range_info = {0};
} }
return ResultSuccess; return ResultSuccess;

View file

@ -18,7 +18,7 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "fsmitm_romstorage.hpp" #include "fs_istorage.hpp"
#include "fsmitm_romfsbuild.hpp" #include "fsmitm_romfsbuild.hpp"
#include "../utils.hpp" #include "../utils.hpp"
@ -27,17 +27,17 @@
class LayeredRomFS : public IROStorage { class LayeredRomFS : public IROStorage {
private: private:
/* Data Sources. */ /* Data Sources. */
std::shared_ptr<RomInterfaceStorage> storage_romfs; std::shared_ptr<IROStorage> storage_romfs;
std::shared_ptr<RomFileStorage> file_romfs; std::shared_ptr<IROStorage> file_romfs;
/* Information about the merged RomFS. */ /* Information about the merged RomFS. */
u64 title_id; u64 title_id;
std::shared_ptr<std::vector<RomFSSourceInfo>> p_source_infos; std::shared_ptr<std::vector<RomFSSourceInfo>> p_source_infos;
public: public:
LayeredRomFS(std::shared_ptr<RomInterfaceStorage> s_r, std::shared_ptr<RomFileStorage> f_r, u64 tid); LayeredRomFS(std::shared_ptr<IROStorage> s_r, std::shared_ptr<IROStorage> f_r, u64 tid);
virtual ~LayeredRomFS() = default; virtual ~LayeredRomFS() = default;
virtual Result Read(void *buffer, size_t size, u64 offset) override; virtual Result Read(void *buffer, size_t size, u64 offset) override;
virtual Result GetSize(u64 *out_size) override; virtual Result GetSize(u64 *out_size) override;
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override; virtual Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override;
}; };

View file

@ -19,9 +19,8 @@
#include <switch.h> #include <switch.h>
#include <map> #include <map>
#include "fsmitm_romstorage.hpp"
#include "../debug.hpp" #include "../debug.hpp"
#include "fs_istorage.hpp"
#define ROMFS_ENTRY_EMPTY 0xFFFFFFFF #define ROMFS_ENTRY_EMPTY 0xFFFFFFFF
#define ROMFS_FILEPARTITION_OFS 0x200 #define ROMFS_FILEPARTITION_OFS 0x200
@ -65,7 +64,7 @@ struct RomFSSourceInfo {
RomFSFileSourceInfo file_source_info; RomFSFileSourceInfo file_source_info;
RomFSLooseSourceInfo loose_source_info; RomFSLooseSourceInfo loose_source_info;
RomFSMemorySourceInfo memory_source_info; RomFSMemorySourceInfo memory_source_info;
RomFSMemorySourceInfo metadata_source_info; RomFSMetaDataSourceInfo metadata_source_info;
}; };
RomFSDataSource type; RomFSDataSource type;

View file

@ -38,7 +38,7 @@ class RomFileStorage : public IROStorage {
public: public:
Result Read(void *buffer, size_t size, u64 offset) override { Result Read(void *buffer, size_t size, u64 offset) override {
size_t out_sz = 0; size_t out_sz = 0;
Result rc = fsFileRead(this->base_file, offset, buffer, size, &out_sz); Result rc = fsFileRead(this->base_file, offset, buffer, size, FS_READOPTION_NONE, &out_sz);
if (R_SUCCEEDED(rc) && out_sz != size && out_sz) { if (R_SUCCEEDED(rc) && out_sz != size && out_sz) {
return this->Read((void *)((uintptr_t)buffer + out_sz), size - out_sz, offset + out_sz); return this->Read((void *)((uintptr_t)buffer + out_sz), size - out_sz, offset + out_sz);
} }
@ -47,7 +47,7 @@ class RomFileStorage : public IROStorage {
Result GetSize(u64 *out_size) override { Result GetSize(u64 *out_size) override {
return fsFileGetSize(this->base_file, out_size); return fsFileGetSize(this->base_file, out_size);
}; };
Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { Result OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
/* TODO: Merge into libnx? */ /* TODO: Merge into libnx? */
return fsFileOperateRange(this->base_file, operation_type, offset, size, out_range_info); return fsFileOperateRange(this->base_file, operation_type, offset, size, out_range_info);
}; };

View file

@ -25,11 +25,11 @@
#include "../utils.hpp" #include "../utils.hpp"
#include "fsmitm_boot0storage.hpp" #include "fsmitm_boot0storage.hpp"
#include "fsmitm_romstorage.hpp"
#include "fsmitm_layeredrom.hpp" #include "fsmitm_layeredrom.hpp"
#include "fs_dir_utils.hpp" #include "fs_dir_utils.hpp"
#include "fs_save_utils.hpp" #include "fs_save_utils.hpp"
#include "fs_file_storage.hpp"
#include "fs_subdirectory_filesystem.hpp" #include "fs_subdirectory_filesystem.hpp"
#include "fs_directory_savedata_filesystem.hpp" #include "fs_directory_savedata_filesystem.hpp"
@ -241,10 +241,11 @@ Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInte
} }
/* Gate access to the BIS partitions. */ /* Gate access to the BIS partitions. */
Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 bis_partition_id) { Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 _bis_partition_id) {
std::shared_ptr<IStorageInterface> storage = nullptr; std::shared_ptr<IStorageInterface> storage = nullptr;
u32 out_domain_id = 0; u32 out_domain_id = 0;
Result rc = ResultSuccess; Result rc = ResultSuccess;
const FsBisStorageId bis_partition_id = static_cast<FsBisStorageId>(_bis_partition_id);
ON_SCOPE_EXIT { ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
@ -262,12 +263,12 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out
const bool is_sysmodule = TitleIdIsSystem(this->title_id); const bool is_sysmodule = TitleIdIsSystem(this->title_id);
const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write"); const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write");
const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read"); const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read");
if (bis_partition_id == BisStorageId_Boot0) { if (bis_partition_id == FsBisStorageId_Boot0) {
storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id));
} else if (bis_partition_id == BisStorageId_Prodinfo) { } else if (bis_partition_id == FsBisStorageId_CalibrationBinary) {
/* PRODINFO should *never* be writable. */ /* PRODINFO should *never* be writable. */
if (is_sysmodule || has_cal0_read_flag) { if (is_sysmodule || has_cal0_read_flag) {
storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); storage = std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage)));
} else { } else {
/* Do not allow non-sysmodules to read *or* write CAL0. */ /* Do not allow non-sysmodules to read *or* write CAL0. */
fsStorageClose(&bis_storage); fsStorageClose(&bis_storage);
@ -279,14 +280,15 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out
/* Sysmodules should still be allowed to read and write. */ /* Sysmodules should still be allowed to read and write. */
storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage));
} else if (Utils::IsHblTid(this->title_id) && } else if (Utils::IsHblTid(this->title_id) &&
((BisStorageId_BcPkg2_1 <= bis_partition_id && bis_partition_id <= BisStorageId_BcPkg2_6) || bis_partition_id == BisStorageId_Boot1)) { ((FsBisStorageId_BootConfigAndPackage2NormalMain <= bis_partition_id && bis_partition_id <= FsBisStorageId_BootConfigAndPackage2RepairSub) ||
bis_partition_id == FsBisStorageId_Boot1)) {
/* Allow HBL to write to boot1 (safe firm) + package2. */ /* Allow HBL to write to boot1 (safe firm) + package2. */
/* This is needed to not break compatibility with ChoiDujourNX, which does not check for write access before beginning an update. */ /* This is needed to not break compatibility with ChoiDujourNX, which does not check for write access before beginning an update. */
/* TODO: get fixed so that this can be turned off without causing bricks :/ */ /* TODO: get fixed so that this can be turned off without causing bricks :/ */
storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage));
} else { } else {
/* Non-sysmodules should be allowed to read. */ /* Non-sysmodules should be allowed to read. */
storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); storage = std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage)));
} }
} }
if (out_storage.IsDomain()) { if (out_storage.IsDomain()) {
@ -348,9 +350,9 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora
if (Utils::HasSdRomfsContent(this->title_id)) { if (Utils::HasSdRomfsContent(this->title_id)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), this->title_id)); storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), this->title_id));
} else { } else {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, this->title_id));
} }
if (out_storage.IsDomain()) { if (out_storage.IsDomain()) {
out_domain_id = data_storage.s.object_id; out_domain_id = data_storage.s.object_id;
@ -415,9 +417,9 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf
if (Utils::HasSdRomfsContent(data_id)) { if (Utils::HasSdRomfsContent(data_id)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), data_id));
} else { } else {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, data_id));
} }
if (out_storage.IsDomain()) { if (out_storage.IsDomain()) {
out_domain_id = data_storage.s.object_id; out_domain_id = data_storage.s.object_id;

View file

@ -263,7 +263,7 @@ void SettingsItemManager::LoadConfiguration() {
/* Read from file. */ /* Read from file. */
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
size_t actual_size; size_t actual_size;
rc = fsFileRead(&config_file, 0, config_buf, 0xFFFF, &actual_size); rc = fsFileRead(&config_file, 0, config_buf, 0xFFFF, FS_READOPTION_NONE, &actual_size);
} }
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {

View file

@ -99,7 +99,7 @@ void Utils::InitializeThreadFunc(void *args) {
fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups"); fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups");
{ {
FsStorage cal0_storage; FsStorage cal0_storage;
if (R_FAILED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize))) { if (R_FAILED(fsOpenBisStorage(&cal0_storage, FsBisStorageId_CalibrationBinary)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize))) {
std::abort(); std::abort();
} }
fsStorageClose(&cal0_storage); fsStorageClose(&cal0_storage);
@ -119,7 +119,7 @@ void Utils::InitializeThreadFunc(void *args) {
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) { if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) {
bool has_auto_backup = false; bool has_auto_backup = false;
size_t read = 0; size_t read = 0;
if (R_SUCCEEDED(fsFileRead(&g_cal0_file, 0, g_cal0_backup, sizeof(g_cal0_backup), &read)) && read == sizeof(g_cal0_backup)) { if (R_SUCCEEDED(fsFileRead(&g_cal0_file, 0, g_cal0_backup, sizeof(g_cal0_backup), FS_READOPTION_NONE, &read)) && read == sizeof(g_cal0_backup)) {
bool is_cal0_valid = true; bool is_cal0_valid = true;
is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0; is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0;
is_cal0_valid &= memcmp(g_cal0_backup + 0x250, serial_number, 0x18) == 0; is_cal0_valid &= memcmp(g_cal0_backup + 0x250, serial_number, 0x18) == 0;
@ -135,8 +135,7 @@ void Utils::InitializeThreadFunc(void *args) {
if (!has_auto_backup) { if (!has_auto_backup) {
fsFileSetSize(&g_cal0_file, ProdinfoSize); fsFileSetSize(&g_cal0_file, ProdinfoSize);
fsFileWrite(&g_cal0_file, 0, g_cal0_storage_backup, ProdinfoSize); fsFileWrite(&g_cal0_file, 0, g_cal0_storage_backup, ProdinfoSize, FS_WRITEOPTION_FLUSH);
fsFileFlush(&g_cal0_file);
} }
/* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */ /* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */
@ -378,7 +377,7 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data,
} }
/* Try to write the data. */ /* Try to write the data. */
rc = fsFileWrite(&f, 0, data, size); rc = fsFileWrite(&f, 0, data, size, FS_WRITEOPTION_FLUSH);
return rc; return rc;
} }
@ -614,7 +613,7 @@ OverrideKey Utils::GetTitleOverrideKey(u64 tid) {
ON_SCOPE_EXIT { free(config_buf); }; ON_SCOPE_EXIT { free(config_buf); };
/* Read title ini contents. */ /* Read title ini contents. */
fsFileRead(&cfg_file, 0, config_buf, config_file_size, &config_file_size); fsFileRead(&cfg_file, 0, config_buf, config_file_size, FS_READOPTION_NONE, &config_file_size);
/* Parse title ini. */ /* Parse title ini. */
ini_parse_string(config_buf, FsMitmTitleSpecificIniHandler, &cfg); ini_parse_string(config_buf, FsMitmTitleSpecificIniHandler, &cfg);
@ -672,7 +671,7 @@ OverrideLocale Utils::GetTitleOverrideLocale(u64 tid) {
ON_SCOPE_EXIT { free(config_buf); }; ON_SCOPE_EXIT { free(config_buf); };
/* Read title ini contents. */ /* Read title ini contents. */
fsFileRead(&cfg_file, 0, config_buf, config_file_size, &config_file_size); fsFileRead(&cfg_file, 0, config_buf, config_file_size, FS_READOPTION_NONE, &config_file_size);
/* Parse title ini. */ /* Parse title ini. */
ini_parse_string(config_buf, FsMitmTitleSpecificLocaleIniHandler, &locale); ini_parse_string(config_buf, FsMitmTitleSpecificLocaleIniHandler, &locale);
@ -698,7 +697,7 @@ void Utils::RefreshConfiguration() {
/* Read in string. */ /* Read in string. */
std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0); std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0);
size_t r_s; size_t r_s;
fsFileRead(&config_file, 0, g_config_ini_data, size, &r_s); fsFileRead(&config_file, 0, g_config_ini_data, size, FS_READOPTION_NONE, &r_s);
fsFileClose(&config_file); fsFileClose(&config_file);
ini_parse_string(g_config_ini_data, FsMitmIniHandler, NULL); ini_parse_string(g_config_ini_data, FsMitmIniHandler, NULL);

View file

@ -18,25 +18,6 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
enum BisStorageId : u32 {
BisStorageId_Boot0 = 0,
BisStorageId_Boot1 = 10,
BisStorageId_RawNand = 20,
BisStorageId_BcPkg2_1 = 21,
BisStorageId_BcPkg2_2 = 22,
BisStorageId_BcPkg2_3 = 23,
BisStorageId_BcPkg2_4 = 24,
BisStorageId_BcPkg2_5 = 25,
BisStorageId_BcPkg2_6 = 26,
BisStorageId_Prodinfo = 27,
BisStorageId_ProdinfoF = 28,
BisStorageId_Safe = 29,
BisStorageId_User = 30,
BisStorageId_System = 31,
BisStorageId_SystemProperEncryption = 32,
BisStorageId_SystemProperPartition = 33,
};
struct OverrideKey { struct OverrideKey {
u64 key_combination; u64 key_combination;
bool override_by_default; bool override_by_default;

View file

@ -21,8 +21,6 @@ static constexpr size_t BatteryLotSize = 0x20;
static constexpr size_t BatteryVersionOffset = 0x4310; static constexpr size_t BatteryVersionOffset = 0x4310;
static constexpr size_t BatteryVersionSize = 0x10; static constexpr size_t BatteryVersionSize = 0x10;
static constexpr u32 BisStorageId_Prodinfo = 27;
static constexpr u32 DefaultBatteryVendor = static_cast<u32>('A'); static constexpr u32 DefaultBatteryVendor = static_cast<u32>('A');
static constexpr u32 DefaultBatteryVersion = 0; static constexpr u32 DefaultBatteryVersion = 0;
@ -57,7 +55,7 @@ static Result ValidateCalibrationCrc16(const void *data, size_t size) {
static Result GetBatteryVendorImpl(u32 *vendor) { static Result GetBatteryVendorImpl(u32 *vendor) {
FsStorage s; FsStorage s;
Result rc = fsOpenBisStorage(&s, BisStorageId_Prodinfo); Result rc = fsOpenBisStorage(&s, FsBisStorageId_CalibrationBinary);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
return rc; return rc;
} }
@ -78,7 +76,7 @@ static Result GetBatteryVendorImpl(u32 *vendor) {
static Result GetBatteryVersionImpl(u32 *version) { static Result GetBatteryVersionImpl(u32 *version) {
FsStorage s; FsStorage s;
Result rc = fsOpenBisStorage(&s, BisStorageId_Prodinfo); Result rc = fsOpenBisStorage(&s, FsBisStorageId_CalibrationBinary);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
return rc; return rc;
} }

View file

@ -25,10 +25,10 @@ class BisAccessor {
static constexpr size_t SectorAlignment = 0x200; static constexpr size_t SectorAlignment = 0x200;
private: private:
FsStorage storage = {}; FsStorage storage = {};
u32 partition_id; FsBisStorageId partition_id;
bool active; bool active;
public: public:
BisAccessor(u32 id) : partition_id(id), active(false) { } BisAccessor(FsBisStorageId id) : partition_id(id), active(false) { }
~BisAccessor() { ~BisAccessor() {
if (this->active) { if (this->active) {
fsStorageClose(&storage); fsStorageClose(&storage);
@ -126,7 +126,7 @@ class PartitionAccessor : public BisAccessor {
using EnumType = typename Meta::EnumType; using EnumType = typename Meta::EnumType;
using OffsetSizeType = typename Meta::OffsetSizeType; using OffsetSizeType = typename Meta::OffsetSizeType;
public: public:
PartitionAccessor(u32 id) : BisAccessor(id) { } PartitionAccessor(FsBisStorageId id) : BisAccessor(id) { }
private: private:
constexpr const OffsetSizeType *FindEntry(EnumType which) { constexpr const OffsetSizeType *FindEntry(EnumType which) {
for (size_t i = 0; i < Meta::NumEntries; i++) { for (size_t i = 0; i < Meta::NumEntries; i++) {
@ -177,9 +177,6 @@ class PartitionAccessor : public BisAccessor {
} }
}; };
static constexpr u32 BisStorageId_Boot0 = 0;
static constexpr u32 BisStorageId_Boot1 = 10;
enum class Package2Type { enum class Package2Type {
NormalMain, NormalMain,
NormalSub, NormalSub,
@ -189,20 +186,20 @@ enum class Package2Type {
RepairSub, RepairSub,
}; };
static constexpr u32 GetPackage2StorageId(Package2Type which) { static constexpr FsBisStorageId GetPackage2StorageId(Package2Type which) {
switch (which) { switch (which) {
case Package2Type::NormalMain: case Package2Type::NormalMain:
return 21; return FsBisStorageId_BootConfigAndPackage2NormalMain;
case Package2Type::NormalSub: case Package2Type::NormalSub:
return 22; return FsBisStorageId_BootConfigAndPackage2NormalSub;
case Package2Type::SafeMain: case Package2Type::SafeMain:
return 23; return FsBisStorageId_BootConfigAndPackage2SafeMain;
case Package2Type::SafeSub: case Package2Type::SafeSub:
return 24; return FsBisStorageId_BootConfigAndPackage2SafeSub;
case Package2Type::RepairMain: case Package2Type::RepairMain:
return 25; return FsBisStorageId_BootConfigAndPackage2RepairMain;
case Package2Type::RepairSub: case Package2Type::RepairSub:
return 26; return FsBisStorageId_BootConfigAndPackage2RepairSub;
default: default:
std::abort(); std::abort();
} }
@ -210,7 +207,7 @@ static constexpr u32 GetPackage2StorageId(Package2Type which) {
class Boot0Accessor : public PartitionAccessor<Boot0Meta> { class Boot0Accessor : public PartitionAccessor<Boot0Meta> {
public: public:
static constexpr u32 PartitionId = 0; static constexpr FsBisStorageId PartitionId = FsBisStorageId_Boot0;
static constexpr size_t BctPubkOffset = 0x210; static constexpr size_t BctPubkOffset = 0x210;
static constexpr size_t BctPubkSize = 0x100; static constexpr size_t BctPubkSize = 0x100;
static constexpr size_t BctEksOffset = 0x450; static constexpr size_t BctEksOffset = 0x450;
@ -230,7 +227,7 @@ class Boot0Accessor : public PartitionAccessor<Boot0Meta> {
class Boot1Accessor : public PartitionAccessor<Boot1Meta> { class Boot1Accessor : public PartitionAccessor<Boot1Meta> {
public: public:
static constexpr u32 PartitionId = 10; static constexpr FsBisStorageId PartitionId = FsBisStorageId_Boot1;
public: public:
Boot1Accessor() : PartitionAccessor<Boot1Meta>(PartitionId) { } Boot1Accessor() : PartitionAccessor<Boot1Meta>(PartitionId) { }
}; };

@ -1 +1 @@
Subproject commit 8f2328975a66519275ada907cbc0000377ce5ede Subproject commit 05c58ef00263552d4925ed29ac0828cacdfc2ed1