Skip to content

Commit

Permalink
workaround for libnx homebrew under applet shim
Browse files Browse the repository at this point in the history
liuervehc authored and misson20000 committed Jan 13, 2020
1 parent 23f601b commit e4ae169
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions twili_applet_shim/applet_host.cpp
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@
//

#include<libtransistor/cpp/nx.hpp>
#include<libtransistor/svc.h>

#include<cassert>
#include<list>

#include<stdio.h>
@@ -144,6 +146,78 @@ void HostMode(ipc::client::Object &iappletshim) {
}
});

// Mimic nx-hbloader's applet heap override behavior as workaround for libnx
// Reference: https://github.com/switchbrew/nx-hbloader/blob/5d276d1da7a8b0657a8830e99269ea49c85c302f/source/main.c#L102-L145
void *heap_base = nullptr;
size_t heap_size = 0;

size_t total_mem_available, total_mem_usage;

ResultCode::AssertOk(svcGetInfo(&total_mem_available, 6, 0xffff8001, 0));
ResultCode::AssertOk(svcGetInfo(&total_mem_usage, 7, 0xffff8001, 0));

constexpr size_t heap_incr_multiple = 0x200000ul;
constexpr size_t heap_incr_multiple_mask = heap_incr_multiple - 1ul;

if(total_mem_available > (total_mem_usage + heap_incr_multiple)) {
heap_size = (total_mem_available - total_mem_usage - heap_incr_multiple) & ~heap_incr_multiple_mask;
}
if(!heap_size) {
heap_size = 0x20000000ul;
}

uint64_t applet_heap_size, applet_heap_reservation_size;
{
service::SM sm = ResultCode::AssertOk(service::SM::Initialize());

ipc::client::Object set_sys =
ResultCode::AssertOk(sm.GetService("set:sys"));

uint64_t out_size;

ResultCode::AssertOk(
set_sys.SendSyncRequest<38>(
ipc::OutRaw<uint64_t>(out_size),
ipc::Buffer<const char, 0x19>("hbloader", 0x48),
ipc::Buffer<const char, 0x19>("applet_heap_size", 0x48),
ipc::Buffer<decltype(applet_heap_size), 0x6>(
&applet_heap_size, sizeof(applet_heap_size))));
assert(out_size == sizeof(applet_heap_size));

ResultCode::AssertOk(
set_sys.SendSyncRequest<38>(
ipc::OutRaw<uint64_t>(out_size),
ipc::Buffer<const char, 0x19>("hbloader", 0x48),
ipc::Buffer<const char, 0x19>("applet_heap_reservation_size", 0x48),
ipc::Buffer<decltype(applet_heap_reservation_size), 0x6>(
&applet_heap_reservation_size, sizeof(applet_heap_reservation_size))));
assert(out_size == sizeof(applet_heap_reservation_size));
}

if(applet_heap_size) {
const size_t requested_size = (applet_heap_size + heap_incr_multiple_mask) & ~heap_incr_multiple_mask;
if(requested_size < heap_size) {
heap_size = requested_size;
}
} else if(applet_heap_reservation_size) {
const size_t reserved_size = (applet_heap_reservation_size + heap_incr_multiple_mask) & ~heap_incr_multiple_mask;
if(reserved_size < heap_size) {
heap_size -= reserved_size;
}
}

assert(heap_size <= std::numeric_limits<uint32_t>::max());
ResultCode::AssertOk(svcSetHeapSize(&heap_base, static_cast<uint32_t>(heap_size)));

entries.push_back(loader_config_entry_t {
.key = LCONFIG_KEY_OVERRIDE_HEAP,
.flags = LOADER_CONFIG_FLAG_RECOGNITION_MANDATORY,
.override_heap = {
.heap_base = heap_base,
.heap_size = heap_size
}
});

entries.push_back(loader_config_entry_t {
.key = LCONFIG_KEY_END_OF_LIST,
.flags = LOADER_CONFIG_FLAG_RECOGNITION_MANDATORY

0 comments on commit e4ae169

Please sign in to comment.