diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 36d52cb9..19736525 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -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 diff --git a/app/src/main/cpp/skyline/services/am/storage/IStorage.cpp b/app/src/main/cpp/skyline/services/am/storage/IStorage.cpp new file mode 100644 index 00000000..28c86032 --- /dev/null +++ b/app/src/main/cpp/skyline/services/am/storage/IStorage.cpp @@ -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(state, manager, shared_from_this()), session, response); + } +} diff --git a/app/src/main/cpp/skyline/services/am/storage/IStorage.h b/app/src/main/cpp/skyline/services/am/storage/IStorage.h new file mode 100644 index 00000000..2780c3c2 --- /dev/null +++ b/app/src/main/cpp/skyline/services/am/storage/IStorage.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include + +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 { + private: + size_t offset{}; //!< The current offset within the content for pushing data + + public: + std::vector 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 + 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(&value), sizeof(ValueType)); + offset += sizeof(ValueType); + } + }; +} diff --git a/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.cpp b/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.cpp new file mode 100644 index 00000000..56df0677 --- /dev/null +++ b/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.cpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include +#include "IStorage.h" +#include "IStorageAccessor.h" + +namespace skyline::service::am { + IStorageAccessor::IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr 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(parent->content.size()); + } + + void IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto offset = request.Pop(); + 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); + } +} diff --git a/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.h b/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.h new file mode 100644 index 00000000..1be86fea --- /dev/null +++ b/app/src/main/cpp/skyline/services/am/storage/IStorageAccessor.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include + +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 parent; //!< The parent IStorage of the accessor + + public: + IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr 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); + }; +} diff --git a/app/src/main/cpp/skyline/services/base_service.h b/app/src/main/cpp/skyline/services/base_service.h index 57959a51..1a36aa34 100644 --- a/app/src/main/cpp/skyline/services/base_service.h +++ b/app/src/main/cpp/skyline/services/base_service.h @@ -42,6 +42,8 @@ namespace skyline::service { am_ILibraryAppletCreator, am_IDebugFunctions, am_IAppletCommonFunctions, + am_IStorage, + am_IStorageAccessor, audio_IAudioOutManager, audio_IAudioOut, audio_IAudioRendererManager,