Introduce basic RomFS support

This commit adds support for reading the RomFS data from an NRO and
obtaining an IStorage handle to it through 'OpenDataStorageByCurrentProcess'.
There is currently only support for reading and no support
for enlarging or writing.

Also fixup a few capitalisation issues.
This commit is contained in:
Billy Laws 2020-06-22 12:20:26 +01:00 committed by ◱ PixelyIon
parent b9b889fc3c
commit 8d470d3218
8 changed files with 79 additions and 5 deletions

View File

@ -26,6 +26,7 @@ namespace skyline::loader {
public: public:
std::shared_ptr<vfs::NACP> nacp; //!< The NACP of the current application std::shared_ptr<vfs::NACP> nacp; //!< The NACP of the current application
std::shared_ptr<vfs::Backing> romFs; //!< The RomFS of the current application
/** /**
* @param backing The backing for the NRO * @param backing The backing for the NRO

View File

@ -24,6 +24,9 @@ namespace skyline::loader {
NroAssetSection &nacpHeader = assetHeader.nacp; NroAssetSection &nacpHeader = assetHeader.nacp;
nacp = std::make_shared<vfs::NACP>(std::make_shared<vfs::RegionBacking>(backing, header.size + nacpHeader.offset, nacpHeader.size)); nacp = std::make_shared<vfs::NACP>(std::make_shared<vfs::RegionBacking>(backing, header.size + nacpHeader.offset, nacpHeader.size));
NroAssetSection &romFsHeader = assetHeader.romFs;
romFs = std::make_shared<vfs::RegionBacking>(backing, header.size + romFsHeader.offset, romFsHeader.size);
} }
} }
@ -83,4 +86,4 @@ namespace skyline::loader {
state.os->memory.InitializeRegions(constant::BaseAddress, textSize + rodataSize + dataSize + bssSize + patchSize + padding, memory::AddressSpaceType::AddressSpace39Bit); state.os->memory.InitializeRegions(constant::BaseAddress, textSize + rodataSize + dataSize + bssSize + patchSize + padding, memory::AddressSpaceType::AddressSpace39Bit);
} }
} }

View File

@ -60,8 +60,8 @@ namespace skyline::loader {
u32 magic; //!< The asset section magic "ASET" u32 magic; //!< The asset section magic "ASET"
u32 version; //!< The format version u32 version; //!< The format version
NroAssetSection icon; //!< The header describing the location of the icon NroAssetSection icon; //!< The header describing the location of the icon
NroAssetSection nacp; //!< The header describing the location of the nacp NroAssetSection nacp; //!< The header describing the location of the NACP
NroAssetSection romfs; //!< The header describing the location of the romfs NroAssetSection romFs; //!< The header describing the location of the RomFS
} assetHeader{}; } assetHeader{};
/** /**
@ -87,4 +87,4 @@ namespace skyline::loader {
void LoadProcessData(const std::shared_ptr<kernel::type::KProcess> process, const DeviceState &state); void LoadProcessData(const std::shared_ptr<kernel::type::KProcess> process, const DeviceState &state);
}; };
} }

View File

@ -52,6 +52,7 @@ namespace skyline::service {
timesrv_ITimeZoneService, timesrv_ITimeZoneService,
fssrv_IFileSystemProxy, fssrv_IFileSystemProxy,
fssrv_IFileSystem, fssrv_IFileSystem,
fssrv_IStorage,
nvdrv_INvDrvServices, nvdrv_INvDrvServices,
visrv_IManagerRootService, visrv_IManagerRootService,
visrv_IApplicationDisplayService, visrv_IApplicationDisplayService,

View File

@ -1,12 +1,15 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <loader/loader.h>
#include "IFileSystemProxy.h" #include "IFileSystemProxy.h"
#include "IStorage.h"
namespace skyline::service::fssrv { namespace skyline::service::fssrv {
IFileSystemProxy::IFileSystemProxy(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::fssrv_IFileSystemProxy, "fssrv:IFileSystemProxy", { IFileSystemProxy::IFileSystemProxy(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::fssrv_IFileSystemProxy, "fssrv:IFileSystemProxy", {
{0x1, SFUNC(IFileSystemProxy::SetCurrentProcess)}, {0x1, SFUNC(IFileSystemProxy::SetCurrentProcess)},
{0x12, SFUNC(IFileSystemProxy::OpenSdCardFileSystem)} {0x12, SFUNC(IFileSystemProxy::OpenSdCardFileSystem)},
{0xc8, SFUNC(IFileSystemProxy::OpenDataStorageByCurrentProcess)}
}) {} }) {}
void IFileSystemProxy::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { void IFileSystemProxy::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
@ -16,4 +19,11 @@ namespace skyline::service::fssrv {
void IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { void IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(std::make_shared<IFileSystem>(FsType::SdCard, state, manager), session, response); manager.RegisterService(std::make_shared<IFileSystem>(FsType::SdCard, state, manager), session, response);
} }
void IFileSystemProxy::OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
if (state.loader->romFs)
manager.RegisterService(std::make_shared<IStorage>(state.loader->romFs, state, manager), session, response);
else
throw exception("Tried to call OpenDataStorageByCurrentProcess without a valid RomFS");
}
} }

View File

@ -26,5 +26,10 @@ namespace skyline::service::fssrv {
* @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) with type SDCard * @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) with type SDCard
*/ */
void OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); void OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a handle to an instance of #IStorage (https://switchbrew.org/wiki/Filesystem_services#IStorage) for the application's data storage
*/
void OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
}; };
} }

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <kernel/types/KProcess.h>
#include "IStorage.h"
namespace skyline::service::fssrv {
IStorage::IStorage(std::shared_ptr<vfs::Backing> &backing, const DeviceState &state, ServiceManager &manager) : backing(backing), BaseService(state, manager, Service::fssrv_IStorage, "fssrv:IStorage", {
{0x0, SFUNC(IStorage::Read)},
{0x4, SFUNC(IStorage::GetSize)}
}) {}
void IStorage::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto offset = request.Pop<u64>();
auto size = request.Pop<u64>();
backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size);
}
void IStorage::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<u64>(backing->size);
}
}

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <services/base_service.h>
#include <services/serviceman.h>
#include <vfs/backing.h>
namespace skyline::service::fssrv {
/**
* @brief IStorage is an interface to a raw backing device (https://switchbrew.org/wiki/Filesystem_services#IStorage)
*/
class IStorage : public BaseService {
private:
std::shared_ptr<vfs::Backing> backing; //!< The backing of the IStorage
public:
IStorage(std::shared_ptr<vfs::Backing> &backing, const DeviceState &state, ServiceManager &manager);
/**
* @brief This reads a buffer from a region of an IStorage (https://switchbrew.org/wiki/Filesystem_services#Read)
*/
void Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This obtains the size of an IStorage (https://switchbrew.org/wiki/Filesystem_services#GetSize)
*/
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}