From fca54b99a7198ecf2abd00c7337b5df409fa3c97 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Mon, 3 Oct 2022 20:18:14 +0300 Subject: [PATCH] We can *actually* load commercial carts now --- src/core/loader/ncsd.cpp | 46 ++++++++++++++++++++++++--- src/core/services/service_manager.cpp | 6 ++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/core/loader/ncsd.cpp b/src/core/loader/ncsd.cpp index 8dd2d4b2..a86606e4 100644 --- a/src/core/loader/ncsd.cpp +++ b/src/core/loader/ncsd.cpp @@ -73,14 +73,50 @@ std::optional Memory::loadNCSD(const std::filesystem::path& path) { printf("NCSD with an invalid CXI in partition 0?\n"); return std::nullopt; } + + printf("Text address = %08X, page count = %08X\n", cxi.text.address, cxi.text.size); + printf("Rodata address = %08X, page count = %08X\n", cxi.rodata.address, cxi.rodata.size); + printf("Data address = %08X, page count = %08X\n", cxi.data.address, cxi.data.size); // Map code file to memory - const auto& code = cxi.codeFile; - printf("Text address = %08X page count = %08X\n", cxi.text.address, cxi.text.size); - printf("Rodata address = %08X page count = %08X\n", cxi.rodata.address, cxi.rodata.size); - printf("Data address = %08X page count = %08X\n", cxi.data.address, cxi.data.size); + auto& code = cxi.codeFile; + u32 bssSize = (cxi.bssSize + 0xfff) & ~0xfff; // Round BSS size up to a page boundary + // Total memory to allocate for loading + u32 totalSize = (cxi.text.pageCount + cxi.rodata.pageCount + cxi.data.pageCount) * pageSize + bssSize; + code.resize(code.size() + bssSize, 0); // Pad the .code file with zeroes for the BSS segment - ncsd.entrypoint = cxi.text.address; + if (code.size() < totalSize) { + Helpers::panic("Total code size as reported by the exheader is larger than the .code file"); + return std::nullopt; + } + + const auto opt = findPaddr(totalSize); + if (!opt.has_value()) { + Helpers::panic("Failed to find paddr to map CXI file's code to"); + return std::nullopt; + } + + const auto paddr = opt.value(); + std::memcpy(&fcram[paddr], &code[0], totalSize); // Copy the 3 segments + BSS to FCRAM + + // Map the ROM on the kernel side + u32 textOffset = 0; + u32 textAddr = cxi.text.address; + u32 textSize = cxi.text.pageCount * pageSize; + + u32 rodataOffset = textOffset + textSize; + u32 rodataAddr = cxi.rodata.address; + u32 rodataSize = cxi.rodata.pageCount * pageSize; + + u32 dataOffset = rodataOffset + rodataSize; + u32 dataAddr = cxi.data.address; + u32 dataSize = cxi.data.pageCount * pageSize + bssSize; // We're merging the data and BSS segments, as BSS is just pre-initted .data + + allocateMemory(textAddr, paddr + textOffset, textSize, true, true, false, true); // Text is R-X + allocateMemory(rodataAddr, paddr + rodataOffset, rodataSize, true, true, false, false); // Rodata is R-- + allocateMemory(dataAddr, paddr + dataOffset, dataSize, true, true, true, false); // Data+BSS is RW- + + ncsd.entrypoint = textAddr; return ncsd; } \ No newline at end of file diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 2eed4b2b..768ca1a6 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -67,9 +67,11 @@ void ServiceManager::getServiceHandle(u32 messagePointer) { std::string service = mem.readString(messagePointer + 4, 8); log("srv::getServiceHandle (Service: %s, nameLength: %d, flags: %d)\n", service.c_str(), nameLength, flags); - if (service == "APT:S") { + if (service == "APT:S") { // TODO: APT:A, APT:S and APT:U are slightly different handle = KernelHandles::APT; - } else if (service == "APT:A") { // TODO: APT:A and APT:S are slightly different + } else if (service == "APT:A") { + handle = KernelHandles::APT; + } else if (service == "APT:U") { handle = KernelHandles::APT; } else if (service == "hid:USER") { handle = KernelHandles::HID;