diff --git a/libraries/libstratosphere/include/stratosphere/os.hpp b/libraries/libstratosphere/include/stratosphere/os.hpp index 8439a7963..340ea9265 100644 --- a/libraries/libstratosphere/include/stratosphere/os.hpp +++ b/libraries/libstratosphere/include/stratosphere/os.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/os/os_unsafe_memory_api.hpp b/libraries/libstratosphere/include/stratosphere/os/os_unsafe_memory_api.hpp new file mode 100644 index 000000000..6b456be0a --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/os/os_unsafe_memory_api.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 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 + +namespace ams::os { + + Result AllocateUnsafeMemory(uintptr_t *out_address, size_t size); + Result FreeUnsafeMemory(uintptr_t address, size_t size); + +} diff --git a/libraries/libstratosphere/source/os/impl/os_insecure_memory_impl.os.horizon.cpp b/libraries/libstratosphere/source/os/impl/os_insecure_memory_impl.os.horizon.cpp index 11a63a7ae..fd8e78f9f 100644 --- a/libraries/libstratosphere/source/os/impl/os_insecure_memory_impl.os.horizon.cpp +++ b/libraries/libstratosphere/source/os/impl/os_insecure_memory_impl.os.horizon.cpp @@ -24,6 +24,7 @@ namespace ams::os::impl { R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address, [](uintptr_t map_address, size_t map_size) -> Result { R_TRY_CATCH(svc::MapInsecureMemory(map_address, map_size)) { + R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfMemory()) R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState()) } R_END_TRY_CATCH_WITH_ABORT_UNLESS; diff --git a/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.hpp b/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.hpp new file mode 100644 index 000000000..978a4a71d --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.hpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 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 + +namespace ams::os::impl { + + class UnsafeMemoryImpl { + public: + static Result AllocateUnsafeMemoryImpl(uintptr_t *out_address, size_t size); + static Result FreeUnsafeMemoryImpl(uintptr_t address, size_t size); + }; + +} \ No newline at end of file diff --git a/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.os.horizon.cpp b/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.os.horizon.cpp new file mode 100644 index 000000000..cb1f87f87 --- /dev/null +++ b/libraries/libstratosphere/source/os/impl/os_unsafe_memory_impl.os.horizon.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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 . + */ +#include +#include "os_unsafe_memory_impl.hpp" +#include "os_aslr_space_manager.hpp" + +namespace ams::os::impl { + + Result UnsafeMemoryImpl::AllocateUnsafeMemoryImpl(uintptr_t *out_address, size_t size) { + /* Map at a random address. */ + R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address, + [](uintptr_t map_address, size_t map_size) -> Result { + R_TRY_CATCH(svc::MapPhysicalMemoryUnsafe(map_address, map_size)) { + R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource()) + R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfMemory()) + R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState()) + R_CONVERT(svc::ResultLimitReached, os::ResultOutOfMemory()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + R_SUCCEED(); + }, + [](uintptr_t map_address, size_t map_size) -> void { + R_ABORT_UNLESS(UnsafeMemoryImpl::FreeUnsafeMemoryImpl(map_address, map_size)); + }, + size, + 0 + )); + } + + Result UnsafeMemoryImpl::FreeUnsafeMemoryImpl(uintptr_t address, size_t size) { + R_TRY_CATCH(svc::UnmapPhysicalMemoryUnsafe(address, size)) { + R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource()) + R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfResource()) + R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultBusy()) + R_CONVERT(svc::ResultInvalidMemoryRegion, os::ResultInvalidParameter()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + R_SUCCEED(); + } + +} diff --git a/libraries/libstratosphere/source/os/os_unsafe_memory.cpp b/libraries/libstratosphere/source/os/os_unsafe_memory.cpp new file mode 100644 index 000000000..2b0431c8e --- /dev/null +++ b/libraries/libstratosphere/source/os/os_unsafe_memory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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 . + */ +#include +#include "impl/os_unsafe_memory_impl.hpp" + +namespace ams::os { + + Result AllocateUnsafeMemory(uintptr_t *out_address, size_t size) { + /* Check arguments. */ + AMS_ASSERT(size > 0); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + + /* Allocate memory. */ + R_RETURN(impl::UnsafeMemoryImpl::AllocateUnsafeMemoryImpl(out_address, size)); + } + + Result FreeUnsafeMemory(uintptr_t address, size_t size) { + /* Check arguments. */ + AMS_ASSERT(util::IsAligned(address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + + /* Free memory. */ + R_RETURN(impl::UnsafeMemoryImpl::FreeUnsafeMemoryImpl(address, size)); + } + +}