mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-24 03:36:52 -04:00
fs.mitm: add and use memlet module to temporarily steal applet memory while building romfs images.
Starting in 20.0.0, the browser needs more applet memory to function, so we can't steal as much any more. Thus, we now steal 14 MB on 20.0.0+ instead of 40MB. However, since this reduces memory available for custom system modules, we are adjusting to compensate. ams.mitm's heap size has been reduced from 32MB to 12MB (recovering 20MB). In addition, fs.mitm now uses a new mechanism for stealing memory from the applet pool while romfs is being built. On net, we are compromising: * Custom sysmodules lose memory available to them. On 19.0.0/AMS 1.8.0, there was 30 MB available for custom sysmodules. Stealing 14 MB instead of 40 MB, we lose 26 MB of that. Reducing ams.mitm's usage will gain us back 20. Nintendo also appears to...use 4 extra MB, in 20.0.0, from my test homebrew. So on 20.0.0/AMS 1.9.0, there should be 20 MB available for custom sysmodules. On the bright side, on <20.0.0/AMS 1.9.0, I guess there will be 50 MB available for custom sysmodules now? * totk mods will lose the ability to...put every file in the romfs on sd card. There will be some unknown maximum filecount for totk mods. On the bright side, implementing the transient memory stealing should improve compatibility for some mods which strictly add files?
This commit is contained in:
parent
d0cb9b0eb7
commit
0ecc35c062
19 changed files with 672 additions and 12 deletions
|
@ -50,6 +50,7 @@ dist: dist-no-debug
|
||||||
cp $(CURRENT_DIRECTORY)/stratosphere/sm/$(ATMOSPHERE_OUT_DIR)/sm.elf $(DIST_DIR)/sm.elf
|
cp $(CURRENT_DIRECTORY)/stratosphere/sm/$(ATMOSPHERE_OUT_DIR)/sm.elf $(DIST_DIR)/sm.elf
|
||||||
cp $(CURRENT_DIRECTORY)/stratosphere/spl/$(ATMOSPHERE_OUT_DIR)/spl.elf $(DIST_DIR)/spl.elf
|
cp $(CURRENT_DIRECTORY)/stratosphere/spl/$(ATMOSPHERE_OUT_DIR)/spl.elf $(DIST_DIR)/spl.elf
|
||||||
cp $(CURRENT_DIRECTORY)/stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.elf $(DIST_DIR)/TioServer.elf
|
cp $(CURRENT_DIRECTORY)/stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.elf $(DIST_DIR)/TioServer.elf
|
||||||
|
cp $(CURRENT_DIRECTORY)/stratosphere/memlet/$(ATMOSPHERE_OUT_DIR)/memlet.elf $(DIST_DIR)/memlet.elf
|
||||||
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
|
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
|
||||||
cp $(CURRENT_DIRECTORY)/troposphere/haze/haze.elf $(DIST_DIR)/haze.elf
|
cp $(CURRENT_DIRECTORY)/troposphere/haze/haze.elf $(DIST_DIR)/haze.elf
|
||||||
cp $(CURRENT_DIRECTORY)/troposphere/reboot_to_payload/reboot_to_payload.elf $(DIST_DIR)/reboot_to_payload.elf
|
cp $(CURRENT_DIRECTORY)/troposphere/reboot_to_payload/reboot_to_payload.elf $(DIST_DIR)/reboot_to_payload.elf
|
||||||
|
@ -87,6 +88,7 @@ dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||||
#mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000003c
|
#mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000003c
|
||||||
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000042
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000042
|
||||||
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000420
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000420
|
||||||
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000421
|
||||||
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000b240
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000b240
|
||||||
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d609
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d609
|
||||||
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d623
|
mkdir -p $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d623
|
||||||
|
@ -104,6 +106,7 @@ dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||||
cp stratosphere/htc/$(ATMOSPHERE_OUT_DIR)/htc.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000b240/exefs.nsp
|
cp stratosphere/htc/$(ATMOSPHERE_OUT_DIR)/htc.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000b240/exefs.nsp
|
||||||
cp stratosphere/dmnt.gen2/$(ATMOSPHERE_OUT_DIR)/dmnt.gen2.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d609/exefs.nsp
|
cp stratosphere/dmnt.gen2/$(ATMOSPHERE_OUT_DIR)/dmnt.gen2.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d609/exefs.nsp
|
||||||
cp stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d623/exefs.nsp
|
cp stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d623/exefs.nsp
|
||||||
|
cp stratosphere/memlet/$(ATMOSPHERE_OUT_DIR)/memlet.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000421/exefs.nsp
|
||||||
@build_romfs $(DIST_DIR)/stratosphere_romfs $(DIST_DIR)/atmosphere/stratosphere.romfs
|
@build_romfs $(DIST_DIR)/stratosphere_romfs $(DIST_DIR)/atmosphere/stratosphere.romfs
|
||||||
rm -r $(DIST_DIR)/stratosphere_romfs
|
rm -r $(DIST_DIR)/stratosphere_romfs
|
||||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro $(DIST_DIR)/switch/reboot_to_payload.nro
|
cp troposphere/reboot_to_payload/reboot_to_payload.nro $(DIST_DIR)/switch/reboot_to_payload.nro
|
||||||
|
|
|
@ -361,7 +361,9 @@ namespace ams::kern::board::nintendo::nx {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
/* Return (possibly) adjusted size. */
|
/* Return (possibly) adjusted size. */
|
||||||
constexpr size_t ExtraSystemMemoryForAtmosphere = 40_MB;
|
/* NOTE: On 20.0.0+ the browser requires much more memory in the applet pool in order to function. */
|
||||||
|
/* Thus, we have to reduce our extra system memory size by 26 MB to compensate. */
|
||||||
|
const size_t ExtraSystemMemoryForAtmosphere = kern::GetTargetFirmware() >= ams::TargetFirmware_20_0_0 ? 14_MB : 40_MB;
|
||||||
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
|
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,8 @@ namespace ams::impl {
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, TioServer, FileServerHtcsServer);
|
AMS_DEFINE_SYSTEM_THREAD(21, TioServer, FileServerHtcsServer);
|
||||||
AMS_DEFINE_SYSTEM_THREAD(21, TioServer, SdCardObserver);
|
AMS_DEFINE_SYSTEM_THREAD(21, TioServer, SdCardObserver);
|
||||||
|
|
||||||
|
AMS_DEFINE_SYSTEM_THREAD(16, memlet, Main);
|
||||||
|
|
||||||
/* ServiceProfile */
|
/* ServiceProfile */
|
||||||
AMS_DEFINE_SYSTEM_THREAD(-1, sprofile, IpcServer);
|
AMS_DEFINE_SYSTEM_THREAD(-1, sprofile, IpcServer);
|
||||||
|
|
||||||
|
|
|
@ -121,13 +121,15 @@ namespace ams::ncm {
|
||||||
|
|
||||||
static const AtmosphereProgramId Mitm;
|
static const AtmosphereProgramId Mitm;
|
||||||
static const AtmosphereProgramId AtmosphereLogManager;
|
static const AtmosphereProgramId AtmosphereLogManager;
|
||||||
|
static const AtmosphereProgramId AtmosphereMemlet;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr const AtmosphereProgramId AtmosphereProgramId::Mitm = { 0x010041544D530000ul };
|
inline constexpr const AtmosphereProgramId AtmosphereProgramId::Mitm = { 0x010041544D530000ul };
|
||||||
inline constexpr const AtmosphereProgramId AtmosphereProgramId::AtmosphereLogManager = { 0x0100000000000420ul };
|
inline constexpr const AtmosphereProgramId AtmosphereProgramId::AtmosphereLogManager = { 0x0100000000000420ul };
|
||||||
|
inline constexpr const AtmosphereProgramId AtmosphereProgramId::AtmosphereMemlet = { 0x0100000000000421ul };
|
||||||
|
|
||||||
inline constexpr bool IsAtmosphereProgramId(const ProgramId &program_id) {
|
inline constexpr bool IsAtmosphereProgramId(const ProgramId &program_id) {
|
||||||
return program_id == AtmosphereProgramId::Mitm || program_id == AtmosphereProgramId::AtmosphereLogManager;
|
return program_id == AtmosphereProgramId::Mitm || program_id == AtmosphereProgramId::AtmosphereLogManager || program_id == AtmosphereProgramId::AtmosphereMemlet;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr bool IsSystemProgramId(const AtmosphereProgramId &) {
|
inline constexpr bool IsSystemProgramId(const AtmosphereProgramId &) {
|
||||||
|
|
|
@ -450,6 +450,9 @@ namespace ams::boot2 {
|
||||||
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Migration, ncm::StorageId::BuiltInSystem), 0);
|
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Migration, ncm::StorageId::BuiltInSystem), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Launch atmosphere's applet memory service program. */
|
||||||
|
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::AtmosphereProgramId::AtmosphereMemlet, ncm::StorageId::None), 0);
|
||||||
|
|
||||||
/* Launch user programs off of the SD. */
|
/* Launch user programs off of the SD. */
|
||||||
LaunchFlaggedProgramsOnSdCard();
|
LaunchFlaggedProgramsOnSdCard();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace ams::os::impl {
|
||||||
R_TRY_CATCH(svc::CreateSharedMemory(std::addressof(handle), size, svc_my_perm, svc_other_perm)) {
|
R_TRY_CATCH(svc::CreateSharedMemory(std::addressof(handle), size, svc_my_perm, svc_other_perm)) {
|
||||||
R_CONVERT(svc::ResultOutOfHandles, os::ResultOutOfHandles())
|
R_CONVERT(svc::ResultOutOfHandles, os::ResultOutOfHandles())
|
||||||
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultLimitReached, os::ResultOutOfMemory())
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
*out = handle;
|
*out = handle;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace ams {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* TODO: we really shouldn't be using malloc just to avoid dealing with real allocator separation. */
|
/* TODO: we really shouldn't be using malloc just to avoid dealing with real allocator separation. */
|
||||||
constexpr size_t MallocBufferSize = 32_MB;
|
constexpr size_t MallocBufferSize = 12_MB;
|
||||||
alignas(os::MemoryPageSize) constinit u8 g_malloc_buffer[MallocBufferSize];
|
alignas(os::MemoryPageSize) constinit u8 g_malloc_buffer[MallocBufferSize];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../amsmitm_fs_utils.hpp"
|
#include "../amsmitm_fs_utils.hpp"
|
||||||
#include "fsmitm_romfs.hpp"
|
#include "fsmitm_romfs.hpp"
|
||||||
#include "fsmitm_layered_romfs_storage.hpp"
|
#include "fsmitm_layered_romfs_storage.hpp"
|
||||||
|
#include "memlet/memlet.h"
|
||||||
|
|
||||||
namespace ams::mitm::fs {
|
namespace ams::mitm::fs {
|
||||||
|
|
||||||
|
@ -26,6 +27,8 @@ namespace ams::mitm::fs {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr size_t MaximumRomfsBuildAppletMemorySize = 32_MB;
|
||||||
|
|
||||||
struct ApplicationWithDynamicHeapInfo {
|
struct ApplicationWithDynamicHeapInfo {
|
||||||
ncm::ProgramId program_id;
|
ncm::ProgramId program_id;
|
||||||
size_t dynamic_app_heap_size;
|
size_t dynamic_app_heap_size;
|
||||||
|
@ -41,7 +44,7 @@ namespace ams::mitm::fs {
|
||||||
/* Fire Emblem: Engage. */
|
/* Fire Emblem: Engage. */
|
||||||
/* Requirement ~32+ MB. */
|
/* Requirement ~32+ MB. */
|
||||||
/* No particular heap sensitivity. */
|
/* No particular heap sensitivity. */
|
||||||
{ 0x0100A6301214E000, 16_MB, 0_MB },
|
{ 0x0100A6301214E000, 20_MB, 0_MB },
|
||||||
|
|
||||||
/* The Legend of Zelda: Tears of the Kingdom. */
|
/* The Legend of Zelda: Tears of the Kingdom. */
|
||||||
/* Requirement ~48 MB. */
|
/* Requirement ~48 MB. */
|
||||||
|
@ -85,10 +88,12 @@ namespace ams::mitm::fs {
|
||||||
/* NOTE: Lock not necessary, because this is the only location which do 0 -> non-zero. */
|
/* NOTE: Lock not necessary, because this is the only location which do 0 -> non-zero. */
|
||||||
|
|
||||||
R_ABORT_UNLESS(MapImpl(std::addressof(this->heap_address), this->heap_size));
|
R_ABORT_UNLESS(MapImpl(std::addressof(this->heap_address), this->heap_size));
|
||||||
AMS_ABORT_UNLESS(this->heap_address != 0);
|
AMS_ABORT_UNLESS(this->heap_address != 0 || this->heap_size == 0);
|
||||||
|
|
||||||
/* Create heap. */
|
/* Create heap. */
|
||||||
util::ConstructAt(this->heap, reinterpret_cast<void *>(this->heap_address), this->heap_size);
|
if (this->heap_size > 0) {
|
||||||
|
util::ConstructAt(this->heap, reinterpret_cast<void *>(this->heap_address), this->heap_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +161,52 @@ namespace ams::mitm::fs {
|
||||||
R_RETURN(os::SetMemoryHeapSize(0));
|
R_RETURN(os::SetMemoryHeapSize(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constinit os::SharedMemoryType g_applet_shared_memory;
|
||||||
|
|
||||||
|
Result MapAppletMemory(uintptr_t *out, size_t &size) {
|
||||||
|
/* Ensure that we can try to get a native handle for the shared memory. */
|
||||||
|
AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_initialized_memlet, false);
|
||||||
|
if (AMS_UNLIKELY(!s_initialized_memlet)) {
|
||||||
|
R_ABORT_UNLESS(::memletInitialize());
|
||||||
|
s_initialized_memlet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get a shared handle for the memory. */
|
||||||
|
::Handle shmem_handle = INVALID_HANDLE;
|
||||||
|
u64 shmem_size = 0;
|
||||||
|
if (R_FAILED(::memletCreateAppletSharedMemory(std::addressof(shmem_handle), std::addressof(shmem_size), size))) {
|
||||||
|
/* If we fail, set the heap size to 0. */
|
||||||
|
size = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the output size. */
|
||||||
|
size = shmem_size;
|
||||||
|
|
||||||
|
/* Setup the shared memory. */
|
||||||
|
os::AttachSharedMemory(std::addressof(g_applet_shared_memory), shmem_size, shmem_handle, true);
|
||||||
|
|
||||||
|
/* Map the shared memory. */
|
||||||
|
void *mem = os::MapSharedMemory(std::addressof(g_applet_shared_memory), os::MemoryPermission_ReadWrite);
|
||||||
|
AMS_ABORT_UNLESS(mem != nullptr);
|
||||||
|
|
||||||
|
/* Set the output. */
|
||||||
|
*out = reinterpret_cast<uintptr_t>(mem);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result UnmapAppletMemory(uintptr_t, size_t) {
|
||||||
|
/* Check that it's possible for us to unmap. */
|
||||||
|
AMS_ABORT_UNLESS(os::GetSharedMemoryHandle(std::addressof(g_applet_shared_memory)) != os::InvalidNativeHandle);
|
||||||
|
|
||||||
|
/* Unmap. */
|
||||||
|
os::DestroySharedMemory(std::addressof(g_applet_shared_memory));
|
||||||
|
|
||||||
|
/* Check that we unmapped successfully. */
|
||||||
|
AMS_ABORT_UNLESS(os::GetSharedMemoryHandle(std::addressof(g_applet_shared_memory)) == os::InvalidNativeHandle);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
/* Dynamic allocation globals. */
|
/* Dynamic allocation globals. */
|
||||||
constinit os::SdkMutex g_romfs_build_lock;
|
constinit os::SdkMutex g_romfs_build_lock;
|
||||||
constinit ncm::ProgramId g_dynamic_heap_program_id{};
|
constinit ncm::ProgramId g_dynamic_heap_program_id{};
|
||||||
|
@ -164,6 +215,7 @@ namespace ams::mitm::fs {
|
||||||
|
|
||||||
constinit DynamicHeap<os::AllocateUnsafeMemory, os::FreeUnsafeMemory> g_dynamic_app_heap;
|
constinit DynamicHeap<os::AllocateUnsafeMemory, os::FreeUnsafeMemory> g_dynamic_app_heap;
|
||||||
constinit DynamicHeap<MapByHeap, UnmapByHeap> g_dynamic_sys_heap;
|
constinit DynamicHeap<MapByHeap, UnmapByHeap> g_dynamic_sys_heap;
|
||||||
|
constinit DynamicHeap<MapAppletMemory, UnmapAppletMemory> g_dynamic_let_heap;
|
||||||
|
|
||||||
void InitializeDynamicHeapForBuildRomfs(ncm::ProgramId program_id) {
|
void InitializeDynamicHeapForBuildRomfs(ncm::ProgramId program_id) {
|
||||||
if (program_id == g_dynamic_heap_program_id && g_dynamic_app_heap.heap_size > 0) {
|
if (program_id == g_dynamic_heap_program_id && g_dynamic_app_heap.heap_size > 0) {
|
||||||
|
@ -175,6 +227,10 @@ namespace ams::mitm::fs {
|
||||||
if (g_dynamic_sys_heap.heap_size > 0) {
|
if (g_dynamic_sys_heap.heap_size > 0) {
|
||||||
g_dynamic_sys_heap.Map();
|
g_dynamic_sys_heap.Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_dynamic_let_heap.heap_size > 0) {
|
||||||
|
g_dynamic_let_heap.Map();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,15 +239,33 @@ namespace ams::mitm::fs {
|
||||||
g_building_from_dynamic_heap = false;
|
g_building_from_dynamic_heap = false;
|
||||||
|
|
||||||
g_dynamic_app_heap.TryRelease();
|
g_dynamic_app_heap.TryRelease();
|
||||||
|
g_dynamic_let_heap.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool CanAllocateFromDynamicAppletHeap(AllocationType type) {
|
||||||
|
switch (type) {
|
||||||
|
case AllocationType_FullPath:
|
||||||
|
case AllocationType_SourceInfo:
|
||||||
|
case AllocationType_Memory:
|
||||||
|
case AllocationType_TableCache:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *AllocateTracked(AllocationType type, size_t size) {
|
void *AllocateTracked(AllocationType type, size_t size) {
|
||||||
AMS_UNUSED(type);
|
|
||||||
|
|
||||||
if (g_building_from_dynamic_heap) {
|
if (g_building_from_dynamic_heap) {
|
||||||
void *ret = g_dynamic_app_heap.Allocate(size);
|
void *ret = nullptr;
|
||||||
|
if (CanAllocateFromDynamicAppletHeap(type) && g_dynamic_let_heap.heap_address != 0) {
|
||||||
|
ret = g_dynamic_let_heap.Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == nullptr && g_dynamic_app_heap.heap_address != 0) {
|
||||||
|
ret = g_dynamic_app_heap.Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == nullptr && g_dynamic_sys_heap.heap_address != 0) {
|
if (ret == nullptr && g_dynamic_sys_heap.heap_address != 0) {
|
||||||
ret = g_dynamic_sys_heap.Allocate(size);
|
ret = g_dynamic_sys_heap.Allocate(size);
|
||||||
|
@ -211,7 +285,11 @@ namespace ams::mitm::fs {
|
||||||
AMS_UNUSED(type);
|
AMS_UNUSED(type);
|
||||||
AMS_UNUSED(size);
|
AMS_UNUSED(size);
|
||||||
|
|
||||||
if (g_dynamic_app_heap.TryFree(p)) {
|
if (g_dynamic_let_heap.TryFree(p)) {
|
||||||
|
if (!g_building_from_dynamic_heap) {
|
||||||
|
g_dynamic_let_heap.TryRelease();
|
||||||
|
}
|
||||||
|
} else if (g_dynamic_app_heap.TryFree(p)) {
|
||||||
if (!g_building_from_dynamic_heap) {
|
if (!g_building_from_dynamic_heap) {
|
||||||
g_dynamic_app_heap.TryRelease();
|
g_dynamic_app_heap.TryRelease();
|
||||||
}
|
}
|
||||||
|
@ -1021,6 +1099,7 @@ namespace ams::mitm::fs {
|
||||||
g_dynamic_heap_program_id = program_id;
|
g_dynamic_heap_program_id = program_id;
|
||||||
g_dynamic_app_heap.heap_size = GetDynamicAppHeapSize(g_dynamic_heap_program_id);
|
g_dynamic_app_heap.heap_size = GetDynamicAppHeapSize(g_dynamic_heap_program_id);
|
||||||
g_dynamic_sys_heap.heap_size = GetDynamicSysHeapSize(g_dynamic_heap_program_id);
|
g_dynamic_sys_heap.heap_size = GetDynamicSysHeapSize(g_dynamic_heap_program_id);
|
||||||
|
g_dynamic_let_heap.heap_size = MaximumRomfsBuildAppletMemorySize;
|
||||||
|
|
||||||
/* Set output. */
|
/* Set output. */
|
||||||
*out_size = g_dynamic_app_heap.heap_size;
|
*out_size = g_dynamic_app_heap.heap_size;
|
||||||
|
|
41
stratosphere/ams_mitm/source/fs_mitm/memlet/memlet.c
Normal file
41
stratosphere/ams_mitm/source/fs_mitm/memlet/memlet.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "memlet.h"
|
||||||
|
|
||||||
|
static Service g_memletSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(memlet);
|
||||||
|
|
||||||
|
Result _memletInitialize(void) {
|
||||||
|
return smGetService(&g_memletSrv, "memlet");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _memletCleanup(void) {
|
||||||
|
serviceClose(&g_memletSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* memletGetServiceSession(void) {
|
||||||
|
return &g_memletSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result memletCreateAppletSharedMemory(Handle *out_shmem_h, u64 *out_size, u64 desired_size) {
|
||||||
|
return serviceDispatchInOut(&g_memletSrv, 65000, desired_size, *out_size,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
||||||
|
.out_handles = out_shmem_h,
|
||||||
|
);
|
||||||
|
}
|
32
stratosphere/ams_mitm/source/fs_mitm/memlet/memlet.h
Normal file
32
stratosphere/ams_mitm/source/fs_mitm/memlet/memlet.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Result memletInitialize(void);
|
||||||
|
void memletExit(void);
|
||||||
|
Service* memletGetServiceSession(void);
|
||||||
|
|
||||||
|
Result memletCreateAppletSharedMemory(Handle *out_shmem_h, u64 *out_size, u64 desired_size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
65
stratosphere/ams_mitm/source/fs_mitm/memlet/service_guard.h
Normal file
65
stratosphere/ams_mitm/source/fs_mitm/memlet/service_guard.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <switch/types.h>
|
||||||
|
#include <switch/result.h>
|
||||||
|
#include <switch/kernel/mutex.h>
|
||||||
|
#include <switch/sf/service.h>
|
||||||
|
#include <switch/services/sm.h>
|
||||||
|
|
||||||
|
typedef struct ServiceGuard {
|
||||||
|
Mutex mutex;
|
||||||
|
u32 refCount;
|
||||||
|
} ServiceGuard;
|
||||||
|
|
||||||
|
NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g)
|
||||||
|
{
|
||||||
|
mutexLock(&g->mutex);
|
||||||
|
return (g->refCount++) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void))
|
||||||
|
{
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
cleanupFunc();
|
||||||
|
--g->refCount;
|
||||||
|
}
|
||||||
|
mutexUnlock(&g->mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void))
|
||||||
|
{
|
||||||
|
mutexLock(&g->mutex);
|
||||||
|
if (g->refCount && (--g->refCount) == 0)
|
||||||
|
cleanupFunc();
|
||||||
|
mutexUnlock(&g->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \
|
||||||
|
\
|
||||||
|
static ServiceGuard g_##name##Guard; \
|
||||||
|
NX_INLINE Result _##name##Initialize _paramdecl; \
|
||||||
|
static void _##name##Cleanup(void); \
|
||||||
|
\
|
||||||
|
Result name##Initialize _paramdecl \
|
||||||
|
{ \
|
||||||
|
Result rc = 0; \
|
||||||
|
if (serviceGuardBeginInit(&g_##name##Guard)) \
|
||||||
|
rc = _##name##Initialize _parampass; \
|
||||||
|
return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void name##Exit(void) \
|
||||||
|
{ \
|
||||||
|
serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ())
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
41
stratosphere/memlet/Makefile
Normal file
41
stratosphere/memlet/Makefile
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS :=
|
||||||
|
all: nx_release
|
||||||
|
|
||||||
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGET
|
||||||
|
|
||||||
|
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
|
||||||
|
|
||||||
|
$(strip $1):
|
||||||
|
@echo "Building $(strip $1)"
|
||||||
|
@$$(MAKE) -f $(CURRENT_DIRECTORY)/system_module.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
|
||||||
|
|
||||||
|
clean-$(strip $1):
|
||||||
|
@echo "Cleaning $(strip $1)"
|
||||||
|
@$$(MAKE) -f $(CURRENT_DIRECTORY)/system_module.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
define ATMOSPHERE_ADD_TARGETS
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_release, release, $(strip $2), $(strip $3), \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="$(strip $4)" \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_debug, debug, $(strip $2), $(strip $3), \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_DEBUGGING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_audit, audit, $(strip $2), $(strip $3), \
|
||||||
|
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_AUDITING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 ATMOSPHERE_BUILD_FOR_AUDITING=1 \
|
||||||
|
))
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call ATMOSPHERE_ADD_TARGETS, nx, nx-hac-001, arm-cortex-a57,))
|
||||||
|
|
||||||
|
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
|
||||||
|
|
||||||
|
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS), $(config) clean-$(config))
|
93
stratosphere/memlet/memlet.json
Normal file
93
stratosphere/memlet/memlet.json
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
{
|
||||||
|
"name": "memlet",
|
||||||
|
"title_id": "0x0100000000000421",
|
||||||
|
"title_id_range_min": "0x0100000000000421",
|
||||||
|
"title_id_range_max": "0x0100000000000421",
|
||||||
|
"main_thread_stack_size": "0x00002000",
|
||||||
|
"main_thread_priority": 44,
|
||||||
|
"default_cpu_id": 3,
|
||||||
|
"process_category": 0,
|
||||||
|
"is_retail": true,
|
||||||
|
"pool_partition": 1,
|
||||||
|
"is_64_bit": true,
|
||||||
|
"address_space_type": 3,
|
||||||
|
"disable_device_address_space_merge": true,
|
||||||
|
"filesystem_access": {
|
||||||
|
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||||
|
},
|
||||||
|
"service_access": ["fatal:u"],
|
||||||
|
"service_host": ["memlet"],
|
||||||
|
"kernel_capabilities": [{
|
||||||
|
"type": "kernel_flags",
|
||||||
|
"value": {
|
||||||
|
"highest_thread_priority": 63,
|
||||||
|
"lowest_thread_priority": 24,
|
||||||
|
"lowest_cpu_id": 3,
|
||||||
|
"highest_cpu_id": 3
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "syscalls",
|
||||||
|
"value": {
|
||||||
|
"svcSetHeapSize": "0x01",
|
||||||
|
"svcSetMemoryPermission": "0x02",
|
||||||
|
"svcSetMemoryAttribute": "0x03",
|
||||||
|
"svcMapMemory": "0x04",
|
||||||
|
"svcUnmapMemory": "0x05",
|
||||||
|
"svcQueryMemory": "0x06",
|
||||||
|
"svcExitProcess": "0x07",
|
||||||
|
"svcCreateThread": "0x08",
|
||||||
|
"svcStartThread": "0x09",
|
||||||
|
"svcExitThread": "0x0a",
|
||||||
|
"svcSleepThread": "0x0b",
|
||||||
|
"svcGetThreadPriority": "0x0c",
|
||||||
|
"svcSetThreadPriority": "0x0d",
|
||||||
|
"svcGetThreadCoreMask": "0x0e",
|
||||||
|
"svcSetThreadCoreMask": "0x0f",
|
||||||
|
"svcGetCurrentProcessorNumber": "0x10",
|
||||||
|
"svcSignalEvent": "0x11",
|
||||||
|
"svcClearEvent": "0x12",
|
||||||
|
"svcMapSharedMemory": "0x13",
|
||||||
|
"svcUnmapSharedMemory": "0x14",
|
||||||
|
"svcCreateTransferMemory": "0x15",
|
||||||
|
"svcCloseHandle": "0x16",
|
||||||
|
"svcResetSignal": "0x17",
|
||||||
|
"svcWaitSynchronization": "0x18",
|
||||||
|
"svcCancelSynchronization": "0x19",
|
||||||
|
"svcArbitrateLock": "0x1a",
|
||||||
|
"svcArbitrateUnlock": "0x1b",
|
||||||
|
"svcWaitProcessWideKeyAtomic": "0x1c",
|
||||||
|
"svcSignalProcessWideKey": "0x1d",
|
||||||
|
"svcGetSystemTick": "0x1e",
|
||||||
|
"svcConnectToNamedPort": "0x1f",
|
||||||
|
"svcSendSyncRequestLight": "0x20",
|
||||||
|
"svcSendSyncRequest": "0x21",
|
||||||
|
"svcSendSyncRequestWithUserBuffer": "0x22",
|
||||||
|
"svcSendAsyncRequestWithUserBuffer": "0x23",
|
||||||
|
"svcGetProcessId": "0x24",
|
||||||
|
"svcGetThreadId": "0x25",
|
||||||
|
"svcBreak": "0x26",
|
||||||
|
"svcOutputDebugString": "0x27",
|
||||||
|
"svcReturnFromException": "0x28",
|
||||||
|
"svcGetInfo": "0x29",
|
||||||
|
"svcWaitForAddress": "0x34",
|
||||||
|
"svcSignalToAddress": "0x35",
|
||||||
|
"svcSynchronizePreemptionState": "0x36",
|
||||||
|
"svcCreateSession": "0x40",
|
||||||
|
"svcAcceptSession": "0x41",
|
||||||
|
"svcReplyAndReceiveLight": "0x42",
|
||||||
|
"svcReplyAndReceive": "0x43",
|
||||||
|
"svcReplyAndReceiveWithUserBuffer": "0x44",
|
||||||
|
"svcCreateSharedMemory": "0x50",
|
||||||
|
"svcCallSecureMonitor": "0x7f"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "application_type",
|
||||||
|
"value": 2
|
||||||
|
}, {
|
||||||
|
"type": "min_kernel_version",
|
||||||
|
"value": "0x0030"
|
||||||
|
}, {
|
||||||
|
"type": "handle_table_size",
|
||||||
|
"value": 0
|
||||||
|
}]
|
||||||
|
}
|
75
stratosphere/memlet/source/memlet_main.cpp
Normal file
75
stratosphere/memlet/source/memlet_main.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "memlet_service.hpp"
|
||||||
|
|
||||||
|
namespace ams {
|
||||||
|
|
||||||
|
namespace memlet {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||||
|
|
||||||
|
constexpr sm::ServiceName MemServiceName = sm::ServiceName::Encode("memlet");
|
||||||
|
constexpr size_t MemMaxSessions = 1;
|
||||||
|
|
||||||
|
/* memlet. */
|
||||||
|
constexpr size_t NumServers = 1;
|
||||||
|
constexpr size_t NumSessions = MemMaxSessions;
|
||||||
|
|
||||||
|
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||||
|
|
||||||
|
constinit sf::UnmanagedServiceObject<memlet::impl::IService, memlet::Service> g_mem_service_object;
|
||||||
|
|
||||||
|
void InitializeAndLoopIpcServer() {
|
||||||
|
/* Create services. */
|
||||||
|
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_mem_service_object.GetShared(), MemServiceName, MemMaxSessions));
|
||||||
|
|
||||||
|
/* Loop forever, servicing our services. */
|
||||||
|
g_server_manager.LoopProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace init {
|
||||||
|
|
||||||
|
void InitializeSystemModule() {
|
||||||
|
/* Initialize our connection to sm. */
|
||||||
|
R_ABORT_UNLESS(sm::Initialize());
|
||||||
|
|
||||||
|
/* Verify that we can sanely execute. */
|
||||||
|
ams::CheckApiVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FinalizeSystemModule() { /* ... */ }
|
||||||
|
|
||||||
|
void Startup() { /* ... */ }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Main() {
|
||||||
|
/* Set thread name. */
|
||||||
|
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(memlet, Main));
|
||||||
|
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(memlet, Main));
|
||||||
|
|
||||||
|
/* Initialize and service our ipc service. */
|
||||||
|
memlet::InitializeAndLoopIpcServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
58
stratosphere/memlet/source/memlet_service.cpp
Normal file
58
stratosphere/memlet/source/memlet_service.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "memlet_service.hpp"
|
||||||
|
|
||||||
|
namespace ams::memlet {
|
||||||
|
|
||||||
|
Result Service::CreateAppletSharedMemory(sf::Out<u64> out_size, sf::OutMoveHandle out_handle, u64 desired_size) {
|
||||||
|
/* Create a handle to set the output to when done. */
|
||||||
|
os::NativeHandle handle = os::InvalidNativeHandle;
|
||||||
|
ON_SCOPE_EXIT { out_handle.SetValue(handle, true); };
|
||||||
|
|
||||||
|
/* Check that the requested size has megabyte alignment and isn't too big. */
|
||||||
|
R_UNLESS(util::IsAligned(desired_size, 1_MB), os::ResultInvalidParameter());
|
||||||
|
R_UNLESS(desired_size <= 128_MB, os::ResultInvalidParameter());
|
||||||
|
|
||||||
|
/* Try to create a shared memory of the desired size, giving up 1 MB each iteration. */
|
||||||
|
os::SharedMemoryType shmem = {};
|
||||||
|
while (true) {
|
||||||
|
/* If we have zero desired-size left, we've failed. */
|
||||||
|
R_UNLESS(desired_size > 0, os::ResultOutOfMemory());
|
||||||
|
|
||||||
|
/* Try to create a shared memory. */
|
||||||
|
if (R_FAILED(os::CreateSharedMemory(std::addressof(shmem), desired_size, os::MemoryPermission_ReadWrite, os::MemoryPermission_ReadWrite))) {
|
||||||
|
/* We failed, so decrease the size to see if that works. */
|
||||||
|
desired_size -= 1_MB;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We successfully created the shared memory. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the native handle for the shared memory we created. */
|
||||||
|
handle = os::GetSharedMemoryHandle(std::addressof(shmem));
|
||||||
|
|
||||||
|
/* HACK: Clear the shared memory object, since we've stolen its handle, and there's no "correct" way to detach. */
|
||||||
|
shmem = {};
|
||||||
|
|
||||||
|
/* We successfully created a shared memory! */
|
||||||
|
*out_size = desired_size;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
stratosphere/memlet/source/memlet_service.hpp
Normal file
32
stratosphere/memlet/source/memlet_service.hpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
#define AMS_MEMLET_I_SERVICE_INTERFACE_INFO(C, H) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 65000, Result, CreateAppletSharedMemory, (sf::Out<u64> out_size, sf::OutMoveHandle out_handle, u64 desired_size), (out_size, out_handle, desired_size))
|
||||||
|
|
||||||
|
AMS_SF_DEFINE_INTERFACE(ams::memlet::impl, IService, AMS_MEMLET_I_SERVICE_INTERFACE_INFO, 0x00000000)
|
||||||
|
|
||||||
|
namespace ams::memlet {
|
||||||
|
|
||||||
|
class Service {
|
||||||
|
public:
|
||||||
|
Result CreateAppletSharedMemory(sf::Out<u64> out_size, sf::OutMoveHandle out_handle, u64 desired_size);
|
||||||
|
};
|
||||||
|
static_assert(impl::IsIService<Service>);
|
||||||
|
|
||||||
|
}
|
131
stratosphere/memlet/system_module.mk
Normal file
131
stratosphere/memlet/system_module.mk
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# pull in common stratosphere sysmodule configuration
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
|
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/stratosphere.mk
|
||||||
|
|
||||||
|
ATMOSPHERE_SYSTEM_MODULE_TARGETS := nsp
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(__RECURSIVE__),1)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||||
|
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
||||||
|
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
|
||||||
|
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
$(foreach dir,$(AMS_LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(ATMOSPHERE_BUILD_DIR)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) $(foreach dir,$(AMS_LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||||
|
|
||||||
|
export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC)
|
||||||
|
|
||||||
|
ifeq ($(strip $(CONFIG_JSON)),)
|
||||||
|
jsons := $(wildcard *.json)
|
||||||
|
ifneq (,$(findstring $(TARGET).json,$(jsons)))
|
||||||
|
export APP_JSON := $(TOPDIR)/$(TARGET).json
|
||||||
|
else
|
||||||
|
ifneq (,$(findstring config.json,$(jsons)))
|
||||||
|
export APP_JSON := $(TOPDIR)/config.json
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: clean all check_lib
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(ATMOSPHERE_OUT_DIR) $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/$(ATMOSPHERE_LIBRARY_DIR)/libstratosphere.a
|
||||||
|
@$(MAKE) __RECURSIVE__=1 OUTPUT=$(CURDIR)/$(ATMOSPHERE_OUT_DIR)/$(TARGET) \
|
||||||
|
DEPSDIR=$(CURDIR)/$(ATMOSPHERE_BUILD_DIR) \
|
||||||
|
--no-print-directory -C $(ATMOSPHERE_BUILD_DIR) \
|
||||||
|
-f $(THIS_MAKEFILE)
|
||||||
|
|
||||||
|
$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/$(ATMOSPHERE_LIBRARY_DIR)/libstratosphere.a: check_lib
|
||||||
|
@$(SILENTCMD)echo "Checked library."
|
||||||
|
|
||||||
|
ifeq ($(ATMOSPHERE_CHECKED_LIBSTRATOSPHERE),1)
|
||||||
|
check_lib:
|
||||||
|
else
|
||||||
|
check_lib:
|
||||||
|
@$(MAKE) --no-print-directory -C $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere -f $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/libstratosphere.mk
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(ATMOSPHERE_OUT_DIR) $(ATMOSPHERE_BUILD_DIR):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(ATMOSPHERE_OUT_DIR) $(ATMOSPHERE_BUILD_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(foreach target,$(ATMOSPHERE_SYSTEM_MODULE_TARGETS),$(OUTPUT).$(target))
|
||||||
|
|
||||||
|
$(OUTPUT).kip : $(OUTPUT).elf
|
||||||
|
$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
|
||||||
|
$(OUTPUT).nso : $(OUTPUT).elf
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/$(ATMOSPHERE_LIBRARY_DIR)/libstratosphere.a
|
||||||
|
|
||||||
|
%.npdm : %.npdm.json
|
||||||
|
@echo built ... $< $@
|
||||||
|
@npdmtool $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
|
@ -82,7 +82,7 @@ namespace ams::pm::impl {
|
||||||
[svc::LimitableResource_ThreadCountMax] = BaseAppletThreads,
|
[svc::LimitableResource_ThreadCountMax] = BaseAppletThreads,
|
||||||
[svc::LimitableResource_EventCountMax] = 0,
|
[svc::LimitableResource_EventCountMax] = 0,
|
||||||
[svc::LimitableResource_TransferMemoryCountMax] = 32,
|
[svc::LimitableResource_TransferMemoryCountMax] = 32,
|
||||||
[svc::LimitableResource_SessionCountMax] = 5,
|
[svc::LimitableResource_SessionCountMax] = 5 + 1, /* Add a session for atmosphere's memlet system module. */
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
|
||||||
include $(CURRENT_DIRECTORY)/../libraries/config/common.mk
|
include $(CURRENT_DIRECTORY)/../libraries/config/common.mk
|
||||||
|
|
||||||
ALL_MODULES := loader boot ncm pm sm ams_mitm spl eclct.stub ro creport fatal dmnt boot2 erpt pgl jpegdec LogManager cs htc TioServer dmnt.gen2
|
ALL_MODULES := loader boot ncm pm sm ams_mitm spl eclct.stub ro creport fatal dmnt boot2 erpt pgl jpegdec LogManager cs htc TioServer dmnt.gen2 memlet
|
||||||
|
|
||||||
all: $(ALL_MODULES)
|
all: $(ALL_MODULES)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue