Implement IStorage services in Applet Manager

In the case of am, IStorage is used to exchange buffers of data such
as application launch parameters or an applets result. It has no
relation to fsp-srv's IStorage.
This commit is contained in:
Billy Laws 2020-07-04 20:15:33 +01:00 committed by ◱ PixelyIon
parent 162df93870
commit 8985fe705f
6 changed files with 122 additions and 0 deletions

View File

@ -83,6 +83,8 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/am/controller/ILibraryAppletCreator.cpp
${source_DIR}/skyline/services/am/controller/ISelfController.cpp
${source_DIR}/skyline/services/am/controller/IWindowController.cpp
${source_DIR}/skyline/services/am/storage/IStorage.cpp
${source_DIR}/skyline/services/am/storage/IStorageAccessor.cpp
${source_DIR}/skyline/services/hid/IHidServer.cpp
${source_DIR}/skyline/services/hid/IAppletResource.cpp
${source_DIR}/skyline/services/timesrv/IStaticService.cpp

View File

@ -0,0 +1,15 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include "IStorageAccessor.h"
#include "IStorage.h"
namespace skyline::service::am {
IStorage::IStorage(const DeviceState &state, ServiceManager &manager, size_t size) : content(size), BaseService(state, manager, Service::am_IStorage, "am:IStorage", {
{0x0, SFUNC(IStorage::Open)}
}) {}
void IStorage::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(std::make_shared<IStorageAccessor>(state, manager, shared_from_this()), session, response);
}
}

View File

@ -0,0 +1,41 @@
// 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>
namespace skyline::service::am {
/**
* @brief IStorage is used to open an IStorageAccessor to access a region of memory (https://switchbrew.org/wiki/Applet_Manager_services#IStorage)
*/
class IStorage : public BaseService, public std::enable_shared_from_this<IStorage> {
private:
size_t offset{}; //!< The current offset within the content for pushing data
public:
std::vector<u8> content; //!< The container for this IStorage's contents
IStorage(const DeviceState &state, ServiceManager &manager, size_t size);
/**
* @brief This returns an IStorageAccessor that can read and write data to an IStorage
*/
void Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function writes an object to the storage
* @tparam ValueType The type of the object to write
* @param value A reference to the object to be written
*/
template<typename ValueType>
inline void Push(const ValueType &value) {
if (offset + sizeof(ValueType) > content.size())
throw exception("The supplied value cannot fit into the IStorage");
std::memcpy(content.data() + offset, reinterpret_cast<const u8 *>(&value), sizeof(ValueType));
offset += sizeof(ValueType);
}
};
}

View File

@ -0,0 +1,30 @@
// 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"
#include "IStorageAccessor.h"
namespace skyline::service::am {
IStorageAccessor::IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent) : parent(parent), BaseService(state, manager, Service::am_IStorageAccessor, "am:IStorageAccessor", {
{0x0, SFUNC(IStorageAccessor::GetSize)},
{0xb, SFUNC(IStorageAccessor::Read)}
}) {}
void IStorageAccessor::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<i64>(parent->content.size());
}
void IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto offset = request.Pop<i64>();
auto size = request.outputBuf.at(0).size;
if (offset + size > parent->content.size())
throw exception("Trying to read past the end of an IStorage");
if (offset < 0)
throw exception("Trying to read before the start of an IStorage");
state.process->WriteMemory(parent->content.data() + offset, request.outputBuf.at(0).address, size);
}
}

View File

@ -0,0 +1,32 @@
// 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>
namespace skyline::service::am {
class IStorage;
/**
* @brief IStorageAccessor is used read and write to an IStorage (https://switchbrew.org/wiki/Applet_Manager_services#IStorageAccessor)
*/
class IStorageAccessor : public BaseService {
private:
std::shared_ptr<IStorage> parent; //!< The parent IStorage of the accessor
public:
IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent);
/**
* @brief This returns the size of the storage in bytes
*/
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a buffer containing the contents of the storage at the specified offset
*/
void Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -42,6 +42,8 @@ namespace skyline::service {
am_ILibraryAppletCreator,
am_IDebugFunctions,
am_IAppletCommonFunctions,
am_IStorage,
am_IStorageAccessor,
audio_IAudioOutManager,
audio_IAudioOut,
audio_IAudioRendererManager,