From 341c8edab5410f23e7e9cd6a61f9138162e3d819 Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Mon, 22 Sep 2025 16:51:21 -0400 Subject: [PATCH] rebrand --- README.md | 149 +--- .../stratosphere/loader/source/ldr_meta.cpp | 299 +++++++ .../loader/source/ldr_process_creation.cpp | 780 ++++++++++++++++++ .../loader/source/oc/customize.cpp | 2 +- .../loader/source/oc/mtc_timing_value.hpp | 4 +- Source/sys-clk/manager/Makefile | 2 +- Source/sys-clk/overlay/Makefile | 2 +- .../sys-clk/overlay/src/ui/gui/base_gui.cpp | 2 +- .../sys-clk/overlay/src/ui/gui/fatal_gui.cpp | 2 +- assets/logo.png | Bin 0 -> 83519 bytes build.sh | 2 +- build_kip.sh | 0 12 files changed, 1126 insertions(+), 118 deletions(-) create mode 100644 Source/Atmosphere/stratosphere/loader/source/ldr_meta.cpp create mode 100644 Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp create mode 100644 assets/logo.png delete mode 100644 build_kip.sh diff --git a/README.md b/README.md index 49a2285b..860acdb1 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,44 @@ -# Switch OC Suite -[![License: GPL v2](https://img.shields.io/badge/License-GPL_v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![Downloads](https://img.shields.io/github/downloads/hanai3Bi/Switch-OC-Suite/total)](https://github.com/hanai3Bi/Switch-OC-Suite/releases) - - - -*If Switch OC Suite is so good, then why isn't there a Switch OC Suite 2?* - -This project is very dangerous and can possibly damage your console. If you decide to use it, USE AT YOUR OWN RISK. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND. - -Overclocking Suite for Nintendo Switch consoles running Atmosphere CFW. - -[Project Homepage](https://souldbminersmwc.github.io/Switch-OC-Suite-2) - -**DISCLAIMER: USE AT YOUR OWN RISK!** - -- Overclocking in general will shorten the lifespan of some hardware components. **YOU ARE RESPONSIBLE for any problem or potential damage** if unsafe frequencies are ENABLED in sys-clk-OC. Issues like asking for bypassing limit will BE IGNORED OR CLOSED WITHOUT REPLY. - -- Due to HorizonOS design, instabilities from unsafe RAM clocks may cause filesystem corruption. **Always make backup before enabling DRAM OC.** - -## Features - -- Erista variant (HAC-001) - - CPU / GPU Overclock (Safe: 1785 / 921 MHz) - - Unsafe - - Due to the limit of board power draw or power IC - - Unlockable frequencies up to 2091 / 998 MHz - - See [README for sys-clk-OC](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md) - - - DRAM Overclock (Safe: 1862.4 MHz) - -- Mariko variant (HAC-001-01, HDH-001, HEG-001) - - CPU / GPU Overclock (Safe: 1963 / 998 MHz) - - Unsafe - - Due to the limit of board power draw or power IC - - Unlockable frequencies up to 2295 / 1267 MHz - - See [README for sys-clk-OC](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md) - - - DRAM Overclock (Safe: 1996.8 MHz) - -- Modded sys-clk - - Global Profile - - Designated a dummy title id `0xA111111111111111`. - - Priority: "Temp overrides" > "Application profile" > "Global profile" > "System default". - - Real Voltage readings (CPU/GPU/RAM) - - Bug Fixes - -- **[System Settings (Optional)](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/system_settings.md)** +
+![alt text](assets/logo.png "logo") + + +![alt text](https://img.shields.io/badge/GPL--2.0-red?style=for-the-badge "logo") ![alt text](https://img.shields.io/badge/Nintendo_Switch-E60012?style=for-the-badge&logo=nintendo-switch&logoColor=white "logo") [![alt text](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.com/invite/S3eX47dHsB) ![alt text](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge&logo=visual%20studio%20code&logoColor=white) ![alt text](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge&logo=c%2B%2B&logoColor=white) + +
+ +##### DISCLAIMER: THIS TOOL CAN BE DANGEROUS IF MISUSED. PROCEED WITH CAUTION +* Due to the design of Horizon OS, overclocking RAM can cause **NAND DAMAGE**. Ensure to have a NAND Backup + +A open source overclocking tool for Nintendo Switch consoles running Atmosphere custom firmware + + +## Features: +CPU overclock up to 2601MHz on Mariko units, 2091MHz on Erista units +GPU up to 1382MHz on Mariko units, 1075MHz on Erista units +RAM up to 3200MHz on Mariko units, 2250MHz on Erista units +Over/undervolting +Configurator +Works with most homebrew + +*Higher (potentially dangerous) frequencies are unlockable* ## Installation +Grab latest hoc.kip from releases tab +If using hekate, edit hekate_ipl.ini to include "kip1=atmosphere/kips/*". No need for editing if using fusee +Download latest Horizon OC sysmodule from releases tab +Extract sysmodule into root of SD card -1. Download latest [release](https://github.com/hanai3Bi/Switch-OC-Suite/releases). +Ensure you are using latest Atmosphere, otherwise the console will not boot -2. Grab `x.x.x_loader.kip` for your Atmosphere version, rename it to `loader.kip` and place it in `/atmosphere/kips/`. +## Building +Set up a development enviorment ready to compile Atmosphere +Git clone Atmosphere, and move the cloned folder into build/ +Insert Source/stratosphere folder into build/ +Run build.sh -3. (optional) You can customize via [online loader configurator](https://hanai3Bi.github.io/Switch-OC-Suite/#config): -
- - | Defaults | Mariko | Erista | - | ---------- | ------------- | ------------- | - | CPU OC | 2295 MHz Max | 2091 MHz Max | - | CPU Volt | 1235 mV | 1235 mV | - | GPU OC | 1267 MHz Max | 998 Mhz max | - | RAM OC | 1996 MHz | 1862 MHz | - | RAM Volt | Disabled | Disabled | - | RAM Timing | Auto-Adjusted | Auto-Adjusted | - | CPU UV | Disabled | N/A | - | GPU UV | Disabled | N/A | - -
- -4. Hekate-ipl bootloader (fss0) Only (Not required for AMS fusee) - - At boot entry section in `bootloader/hekate_ipl.ini`, Add `kip1=atmosphere/kips/loader.kip` to any line that works. - -5. Install [sys-clk-oc](https://github.com/hanai3Bi/Switch-OC-Suite/releases/latest/download/sys-clk-oc.zip) - - official [sys-clk](https://github.com/retronx-team/sys-clk/releases) (2.0.0+) is compatible, but not recommended (no bugfixes or additional features). - -6. (optional) Copy SdOut.zip for useful utilities. - -## Updating via AIO - -1. Download and copy custom_packs.json to /config/aio-switch-updater/custom_packs.json - -2. Launch AIO Switch Updater and go to Custom Downloads tab - -3. Select Switch-OC-Suite and press Contiune - - -## Build - -
- -1. Copy Switch-OC-Suite files into Atmosphere folder. - -2. Before compiling, run `patch.py` in `Atmosphere/stratosphere/loader/source/` to insert oc module into loader sysmodule. - -3. Compile Atmosphere loader with devkitpro. - -4. When compilation is done, uncompress the kip to make it work with configurator: `hactool -t kip1 loader.kip --uncompress=loader.kip` - -
- - -## Acknowledgement - -- CTCaer for [Hekate-ipl](https://github.com/CTCaer/hekate) bootloader, RE and hardware research -- [devkitPro](https://devkitpro.org/) for All-In-One homebrew toolchains -- masagrator for [ReverseNX-RT](https://github.com/masagrator/ReverseNX-RT) and info on BatteryChargeInfoFields in psm module -- Nvidia for [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual) -- RetroNX team for [sys-clk](https://github.com/retronx-team/sys-clk) -- SciresM and Reswitched Team for the state-of-the-art [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere) CFW of Switch -- Switchbrew [wiki](http://switchbrew.org/wiki/) for Switch in-depth info -- Switchroot for their [modified L4T kernel and device tree](https://gitlab.com/switchroot/kernel) -- ZatchyCatGames for RE and original OC loader patches for Atmosphere -- KazushiMe for [Switch-OC-Suite](https://github.com/KazushiMe/Switch-OC-Suite) -- lineon for research and help +## Credits +meha for Switch-Oc-Suite +sys-clk team for sys-clk +b0rd2auth for Ultrahand sys-clk fork +Lightos and Sammybigio2010 for early testing \ No newline at end of file diff --git a/Source/Atmosphere/stratosphere/loader/source/ldr_meta.cpp b/Source/Atmosphere/stratosphere/loader/source/ldr_meta.cpp new file mode 100644 index 00000000..f0f8fb7d --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/ldr_meta.cpp @@ -0,0 +1,299 @@ +/* + * 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 "ldr_capabilities.hpp" +#include "ldr_content_management.hpp" +#include "ldr_development_manager.hpp" +#include "ldr_meta.hpp" + +namespace ams::ldr { + + namespace { + + /* Convenience definitions. */ + constexpr size_t MetaCacheBufferSize = 0x8000; + constexpr inline const char AtmosphereMetaPath[] = ENCODE_ATMOSPHERE_CODE_PATH("/main.npdm"); + constexpr inline const char SdOrBaseMetaPath[] = ENCODE_SD_OR_CODE_PATH("/main.npdm"); + constexpr inline const char BaseMetaPath[] = ENCODE_CODE_PATH("/main.npdm"); + + /* Types. */ + struct MetaCache { + Meta meta; + u8 buffer[MetaCacheBufferSize]; + }; + + /* Global storage. */ + ncm::ProgramId g_cached_program_id; + cfg::OverrideStatus g_cached_override_status; + MetaCache g_meta_cache; + MetaCache g_original_meta_cache; + + /* Helpers. */ + Result ValidateSubregion(size_t allowed_start, size_t allowed_end, size_t start, size_t size, size_t min_size = 0) { + R_UNLESS(size >= min_size, ldr::ResultInvalidMeta()); + R_UNLESS(allowed_start <= start, ldr::ResultInvalidMeta()); + R_UNLESS(start <= allowed_end, ldr::ResultInvalidMeta()); + R_UNLESS(start + size <= allowed_end, ldr::ResultInvalidMeta()); + R_SUCCEED(); + } + + Result ValidateNpdm(const Npdm *npdm, size_t size) { + /* Validate magic. */ + R_UNLESS(npdm->magic == Npdm::Magic, ldr::ResultInvalidMeta()); + + /* Validate flags. */ + constexpr u32 InvalidMetaFlagMask = 0x80000000; + R_UNLESS(!(npdm->flags & InvalidMetaFlagMask), ldr::ResultInvalidMeta()); + + /* Validate Acid extents. */ + R_TRY(ValidateSubregion(sizeof(Npdm), size, npdm->acid_offset, npdm->acid_size, sizeof(Acid))); + + /* Validate Aci extends. */ + R_TRY(ValidateSubregion(sizeof(Npdm), size, npdm->aci_offset, npdm->aci_size, sizeof(Aci))); + + R_SUCCEED(); + } + + Result ValidateAcid(const Acid *acid, size_t size) { + /* Validate magic. */ + R_UNLESS(acid->magic == Acid::Magic, ldr::ResultInvalidMeta()); + + /* Validate that the acid is for production if not development. */ + if (!IsDevelopmentForAcidProductionCheck()) { + R_UNLESS((acid->flags & Acid::AcidFlag_Production) != 0, ldr::ResultInvalidMeta()); + } + + /* Validate that the acid version is correct. */ + constexpr u8 SupportedSdkMajorVersion = ams::svc::ConvertToSdkMajorVersion(ams::svc::SupportedKernelMajorVersion); + if (acid->unknown_209 < SupportedSdkMajorVersion) { + R_UNLESS(acid->version == 0, ldr::ResultInvalidMeta()); + R_UNLESS(acid->unknown_209 == 0, ldr::ResultInvalidMeta()); + } + + /* Validate Fac, Sac, Kac. */ + R_TRY(ValidateSubregion(sizeof(Acid), size, acid->fac_offset, acid->fac_size)); + R_TRY(ValidateSubregion(sizeof(Acid), size, acid->sac_offset, acid->sac_size)); + R_TRY(ValidateSubregion(sizeof(Acid), size, acid->kac_offset, acid->kac_size)); + + R_SUCCEED(); + } + + Result ValidateAci(const Aci *aci, size_t size) { + /* Validate magic. */ + R_UNLESS(aci->magic == Aci::Magic, ldr::ResultInvalidMeta()); + + /* Validate Fah, Sac, Kac. */ + R_TRY(ValidateSubregion(sizeof(Aci), size, aci->fah_offset, aci->fah_size)); + R_TRY(ValidateSubregion(sizeof(Aci), size, aci->sac_offset, aci->sac_size)); + R_TRY(ValidateSubregion(sizeof(Aci), size, aci->kac_offset, aci->kac_size)); + + R_SUCCEED(); + } + + const u8 *GetAcidSignatureModulus(ncm::ContentMetaPlatform platform, u8 key_generation, bool unk_unused) { + return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused); + } + + size_t GetAcidSignatureModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused) { + return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused); + } + + Result ValidateAcidSignature(Meta *meta, ncm::ContentMetaPlatform platform, bool unk_unused) { + R_SUCCEED(); + /* Loader did not check signatures prior to 10.0.0. */ + if (hos::GetVersion() < hos::Version_10_0_0) { + meta->check_verification_data = false; + R_SUCCEED(); + } + + /* Get the signature key generation. */ + const auto signature_key_generation = meta->npdm->signature_key_generation; + R_UNLESS(fssystem::IsValidSignatureKeyGeneration(platform, signature_key_generation), ldr::ResultInvalidMeta()); + + /* Verify the signature. */ + const u8 *sig = meta->acid->signature; + const size_t sig_size = sizeof(meta->acid->signature); + const u8 *mod = GetAcidSignatureModulus(platform, signature_key_generation, unk_unused); + const size_t mod_size = GetAcidSignatureModulusSize(platform, unk_unused); + const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent(); + const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize; + const u8 *msg = meta->acid->modulus; + const size_t msg_size = meta->acid->size; + const bool is_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size); + R_UNLESS(is_signature_valid || !IsEnabledProgramVerification(), ldr::ResultInvalidAcidSignature()); + + meta->check_verification_data = is_signature_valid; + R_SUCCEED(); + } + + Result LoadMetaFromFile(fs::FileHandle file, MetaCache *cache) { + /* Reset cache. */ + cache->meta = {}; + + /* Read from file. */ + s64 npdm_size = 0; + { + /* Get file size. */ + R_TRY(fs::GetFileSize(std::addressof(npdm_size), file)); + + /* Read data into cache buffer. */ + R_UNLESS(npdm_size <= static_cast(MetaCacheBufferSize), ldr::ResultMetaOverflow()); + R_TRY(fs::ReadFile(file, 0, cache->buffer, npdm_size)); + } + + /* Ensure size is big enough. */ + R_UNLESS(npdm_size >= static_cast(sizeof(Npdm)), ldr::ResultInvalidMeta()); + + /* Validate the meta. */ + { + Meta *meta = std::addressof(cache->meta); + + Npdm *npdm = reinterpret_cast(cache->buffer); + R_TRY(ValidateNpdm(npdm, npdm_size)); + + Acid *acid = reinterpret_cast(cache->buffer + npdm->acid_offset); + Aci *aci = reinterpret_cast(cache->buffer + npdm->aci_offset); + R_TRY(ValidateAcid(acid, npdm->acid_size)); + R_TRY(ValidateAci(aci, npdm->aci_size)); + + /* Set Meta members. */ + meta->npdm = npdm; + meta->acid = acid; + meta->aci = aci; + + meta->acid_fac = reinterpret_cast(acid) + acid->fac_offset; + meta->acid_sac = reinterpret_cast(acid) + acid->sac_offset; + meta->acid_kac = reinterpret_cast(acid) + acid->kac_offset; + + meta->aci_fah = reinterpret_cast(aci) + aci->fah_offset; + meta->aci_sac = reinterpret_cast(aci) + aci->sac_offset; + meta->aci_kac = reinterpret_cast(aci) + aci->kac_offset; + + meta->modulus = acid->modulus; + } + + R_SUCCEED(); + } + + } + + /* API. */ + Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) { + /* Set the cached program id back to zero. */ + g_cached_program_id = {}; + + /* Try to load meta from file. */ + fs::FileHandle file; + R_TRY(fs::OpenFile(std::addressof(file), AtmosphereMetaPath, fs::OpenMode_Read)); + { + ON_SCOPE_EXIT { fs::CloseFile(file); }; + R_TRY(LoadMetaFromFile(file, std::addressof(g_meta_cache))); + } + + /* Patch meta. Start by setting all program ids to the current program id. */ + Meta *meta = std::addressof(g_meta_cache.meta); + meta->acid->program_id_min = loc.program_id; + meta->acid->program_id_max = loc.program_id; + meta->aci->program_id = loc.program_id; + + /* For HBL, we need to copy some information from the base meta. */ + if (status.IsHbl()) { + if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), SdOrBaseMetaPath, fs::OpenMode_Read))) { + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + + if (R_SUCCEEDED(LoadMetaFromFile(file, std::addressof(g_original_meta_cache)))) { + Meta *o_meta = std::addressof(g_original_meta_cache.meta); + + /* Fix pool partition. */ + if (hos::GetVersion() >= hos::Version_5_0_0) { + meta->acid->flags = (meta->acid->flags & 0xFFFFFFC3) | (o_meta->acid->flags & 0x0000003C); + } + + /* Fix flags. */ + const u16 program_info_flags = MakeProgramInfoFlag(static_cast(o_meta->aci_kac), o_meta->aci->kac_size / sizeof(util::BitPack32)); + UpdateProgramInfoFlag(program_info_flags, static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32)); + UpdateProgramInfoFlag(program_info_flags, static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); + } + } + + /* Perform address space override. */ + if (status.HasOverrideAddressSpace()) { + /* Clear the existing address space. */ + meta->npdm->flags &= ~Npdm::MetaFlag_AddressSpaceTypeMask; + + /* Set the new address space flag. */ + switch (status.GetOverrideAddressSpaceFlags()) { + case cfg::impl::OverrideStatusFlag_AddressSpace32Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_32Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64BitDeprecated: meta->npdm->flags |= (Npdm::AddressSpaceType_64BitDeprecated) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias: meta->npdm->flags |= (Npdm::AddressSpaceType_32BitWithoutAlias) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + /* When hbl is applet, adjust main thread priority. */ + if ((MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) { + constexpr auto HblMainThreadPriorityApplication = 44; + constexpr auto HblMainThreadPriorityApplet = 40; + if (meta->npdm->main_thread_priority == HblMainThreadPriorityApplication) { + meta->npdm->main_thread_priority = HblMainThreadPriorityApplet; + } + } + + /* Fix the debug capabilities, to prevent needing a hbl recompilation. */ + FixDebugCapabilityForHbl(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32)); + FixDebugCapabilityForHbl(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); + } else if (hos::GetVersion() >= hos::Version_10_0_0) { + /* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */ + /* However, if we're an application, we are guaranteed a base code filesystem. */ + if (static_cast(loc.storage_id) != ncm::StorageId::None || ncm::IsApplicationId(loc.program_id)) { + R_TRY(fs::OpenFile(std::addressof(file), BaseMetaPath, fs::OpenMode_Read)); + ON_SCOPE_EXIT { fs::CloseFile(file); }; + R_TRY(LoadMetaFromFile(file, std::addressof(g_original_meta_cache))); + R_TRY(ValidateAcidSignature(std::addressof(g_original_meta_cache.meta), platform, unk_unused)); + meta->modulus = g_original_meta_cache.meta.modulus; + meta->check_verification_data = g_original_meta_cache.meta.check_verification_data; + } + } + + /* Pre-process the capabilities. */ + /* This is used to e.g. avoid passing memory region descriptor to older kernels. */ + PreProcessCapability(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32)); + PreProcessCapability(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); + + /* Set output. */ + g_cached_program_id = loc.program_id; + g_cached_override_status = status; + *out_meta = *meta; + + R_SUCCEED(); + } + + Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) { + if (g_cached_program_id != loc.program_id || g_cached_override_status != status) { + R_RETURN(LoadMeta(out_meta, loc, status, platform, false)); + } + *out_meta = g_meta_cache.meta; + R_SUCCEED(); + } + + void InvalidateMetaCache() { + /* Set the cached program id back to zero. */ + g_cached_program_id = {}; + } + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp new file mode 100644 index 00000000..56df8c2d --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp @@ -0,0 +1,780 @@ +/* + * 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 "ldr_capabilities.hpp" +#include "ldr_content_management.hpp" +#include "ldr_development_manager.hpp" +#include "ldr_launch_record.hpp" +#include "ldr_meta.hpp" +#include "ldr_patcher.hpp" +#include "ldr_process_creation.hpp" +#include "ldr_ro_manager.hpp" +#include "ldr_ro_manager.hpp" +#include "oc/oc_loader.hpp" + +namespace ams::ldr { + + namespace { + + /* Convenience defines. */ + constexpr size_t SystemResourceSizeMax = 0x1FE00000; + + /* Types. */ + enum NsoIndex { + Nso_Rtld = 0, + Nso_Main = 1, + Nso_Compat0 = 2, + Nso_Compat1 = 3, + Nso_Compat2 = 4, + Nso_Compat3 = 5, + Nso_Compat4 = 6, + Nso_Compat5 = 7, + Nso_Compat6 = 8, + Nso_Compat7 = 9, + Nso_Compat8 = 10, + Nso_Compat9 = 11, + Nso_SubSdk0 = 12, + Nso_SubSdk1 = 13, + Nso_SubSdk2 = 14, + Nso_SubSdk3 = 15, + Nso_SubSdk4 = 16, + Nso_SubSdk5 = 17, + Nso_SubSdk6 = 18, + Nso_SubSdk7 = 19, + Nso_SubSdk8 = 20, + Nso_SubSdk9 = 21, + Nso_Sdk = 22, + Nso_Count, + }; + + constexpr inline const char *NsoPaths[Nso_Count] = { + ENCODE_ATMOSPHERE_CODE_PATH("/rtld"), + ENCODE_ATMOSPHERE_CODE_PATH("/main"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat0"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat1"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat2"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat3"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat4"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat5"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat6"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat7"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat8"), + ENCODE_ATMOSPHERE_CMPT_PATH("/compat9"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk0"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk1"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk2"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk3"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk4"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk5"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk6"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk7"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk8"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk9"), + ENCODE_ATMOSPHERE_CODE_PATH("/sdk"), + }; + + constexpr const char *GetNsoPath(size_t idx) { + AMS_ABORT_UNLESS(idx < Nso_Count); + return NsoPaths[idx]; + } + + struct ProcessInfo { + os::NativeHandle process_handle; + uintptr_t args_address; + size_t args_size; + uintptr_t nso_address[Nso_Count]; + size_t nso_size[Nso_Count]; + }; + + /* Global NSO header cache. */ + bool g_has_nso[Nso_Count]; + NsoHeader g_nso_headers[Nso_Count]; + + /* Pcv/Ptm check cache */ + bool g_is_pcv; + bool g_is_ptm; + + Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) { + /* No version verification is done before 8.1.0. */ + R_SUCCEED_IF(hos::GetVersion() < hos::Version_8_1_0); + + /* No verification is done if development. */ + R_SUCCEED_IF(IsDevelopmentForAntiDowngradeCheck()); + + /* TODO: Anti-downgrade checking does not make very much sense for us. Should we do anything? */ + AMS_UNUSED(program_id, version); + + R_SUCCEED(); + } + + /* Helpers. */ + Result GetProgramInfoFromMeta(ProgramInfo *out, const Meta *meta) { + /* Copy basic info. */ + out->main_thread_priority = meta->npdm->main_thread_priority; + out->default_cpu_id = meta->npdm->default_cpu_id; + out->main_thread_stack_size = meta->npdm->main_thread_stack_size; + out->program_id = meta->aci->program_id; + + /* Copy access controls. */ + size_t offset = 0; +#define COPY_ACCESS_CONTROL(source, which) \ + ({ \ + const size_t size = meta->source->which##_size; \ + R_UNLESS(offset + size <= sizeof(out->ac_buffer), ldr::ResultInternalError()); \ + out->source##_##which##_size = size; \ + std::memcpy(out->ac_buffer + offset, meta->source##_##which, size); \ + offset += size; \ + }) + + /* Copy all access controls to buffer. */ + COPY_ACCESS_CONTROL(acid, sac); + COPY_ACCESS_CONTROL(aci, sac); + COPY_ACCESS_CONTROL(acid, fac); + COPY_ACCESS_CONTROL(aci, fah); +#undef COPY_ACCESS_CONTROL + + /* Copy flags. */ + out->flags = MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); + R_SUCCEED(); + } + + bool IsApplet(const Meta *meta) { + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet; + } + + bool IsApplication(const Meta *meta) { + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application; + } + + Npdm::AddressSpaceType GetAddressSpaceType(const Meta *meta) { + return static_cast((meta->npdm->flags & Npdm::MetaFlag_AddressSpaceTypeMask) >> Npdm::MetaFlag_AddressSpaceTypeShift); + } + + Acid::PoolPartition GetPoolPartition(const Meta *meta) { + return static_cast((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift); + } + + Result LoadAutoLoadHeaders(NsoHeader *nso_headers, bool *has_nso) { + /* Clear NSOs. */ + std::memset(nso_headers, 0, sizeof(*nso_headers) * Nso_Count); + std::memset(has_nso, 0, sizeof(*has_nso) * Nso_Count); + + for (size_t i = 0; i < Nso_Count; i++) { + fs::FileHandle file; + if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read))) { + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + /* Read NSO header. */ + size_t read_size; + R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, nso_headers + i, sizeof(*nso_headers))); + R_UNLESS(read_size == sizeof(*nso_headers), ldr::ResultInvalidNso()); + + has_nso[i] = true; + } + } + + R_SUCCEED(); + } + + Result CheckAutoLoad(const NsoHeader *nso_headers, const bool *has_nso) { + /* We must always have a main. */ + R_UNLESS(has_nso[Nso_Main], ldr::ResultInvalidNso()); + + /* If we don't have an RTLD, we must only have a main. */ + if (!has_nso[Nso_Rtld]) { + for (size_t i = Nso_Main + 1; i < Nso_Count; i++) { + R_UNLESS(!has_nso[i], ldr::ResultInvalidNso()); + } + } + + /* All NSOs must have zero text offset. */ + for (size_t i = 0; i < Nso_Count; i++) { + R_UNLESS(nso_headers[i].text_dst_offset == 0, ldr::ResultInvalidNso()); + } + + R_SUCCEED(); + } + + constexpr const ncm::ProgramId UnqualifiedApprovalProgramIds[] = { + { 0x010003F003A34000 }, /* Pokemon: Let's Go, Pikachu! */ + { 0x0100152000022000 }, /* Mario Kart 8 Deluxe */ + { 0x0100165003504000 }, /* Nintendo Labo Toy-Con 04: VR Kit */ + { 0x0100187003A36000 }, /* Pokemon: Let's Go, Eevee! */ + { 0x01002E5008C56000 }, /* Pokemon Sword [Live Tournament] */ + { 0x01002FF008C24000 }, /* Ring Fit Adventure */ + { 0x010049900F546001 }, /* Super Mario 3D All-Stars: Super Mario 64 */ + { 0x010057D00ECE4000 }, /* Nintendo Switch Online (Nintendo 64) [for Japan] */ + { 0x01006F8002326000 }, /* Animal Crossing: New Horizons */ + { 0x01006FB00F50E000 }, /* [???] */ + { 0x010070300F50C000 }, /* [???] */ + { 0x010075100E8EC000 }, /* 马力欧卡丁车8 豪华版 [Mario Kart 8 Deluxe for China] */ + { 0x01008DB008C2C000 }, /* Pokemon Shield */ + { 0x01009AD008C4C000 }, /* Pokemon: Let's Go, Pikachu! [Kiosk] */ + { 0x0100A66003384000 }, /* Hulu */ + { 0x0100ABF008968000 }, /* Pokemon Sword */ + { 0x0100C9A00ECE6000 }, /* Nintendo Switch Online (Nintendo 64) [for America] */ + { 0x0100ED100BA3A000 }, /* Mario Kart Live: Home Circuit */ + { 0x0100F38011CFE000 }, /* Animal Crossing: New Horizons Island Transfer Tool */ + { 0x0100F6B011028000 }, /* 健身环大冒险 [Ring Fit Adventure for China] */ + }; + + /* Check that the unqualified approval programs are sorted. */ + static_assert([]() -> bool { + for (size_t i = 0; i < util::size(UnqualifiedApprovalProgramIds) - 1; ++i) { + if (UnqualifiedApprovalProgramIds[i].value >= UnqualifiedApprovalProgramIds[i + 1].value) { + return false; + } + } + + return true; + }()); + + bool IsUnqualifiedApprovalProgramId(ncm::ProgramId program_id) { + /* Check if the program id is one with unqualified approval. */ + return std::binary_search(std::begin(UnqualifiedApprovalProgramIds), std::end(UnqualifiedApprovalProgramIds), program_id); + } + + bool IsUnqualifiedApproval(const Meta *meta) { + /* If the meta has unqualified approval flag, it's unqualified approval. */ + if (meta->acid->flags & ldr::Acid::AcidFlag_UnqualifiedApproval) { + return true; + } + + /* If the unqualified approval flag is not set, the program must be an application. */ + if (!IsApplication(meta)) { + return false; + } + + /* The program id must be a force unqualified approval program id. */ + return IsUnqualifiedApprovalProgramId(meta->acid->program_id_min) && meta->acid->program_id_min == meta->acid->program_id_max; + } + + Result ValidateMeta(const Meta *meta, const ncm::ProgramLocation &loc, const fs::CodeVerificationData &code_verification_data) { + /* Validate version. */ + R_TRY(ValidateProgramVersion(loc.program_id, meta->npdm->version)); + + /* Validate program id. */ + R_UNLESS(meta->aci->program_id >= meta->acid->program_id_min, ldr::ResultInvalidProgramId()); + R_UNLESS(meta->aci->program_id <= meta->acid->program_id_max, ldr::ResultInvalidProgramId()); + + /* Validate the kernel capabilities. */ + R_TRY(TestCapability(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32), static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32))); + +/* Check if NCA is PCV or PTM */ +g_is_pcv = meta->aci->program_id == ncm::SystemProgramId::Pcv; +g_is_ptm = meta->aci->program_id == ncm::SystemProgramId::Ptm; + + + + /* If we have data to validate, validate it. */ + if (meta->check_verification_data) { + const u8 *sig = code_verification_data.signature; + const size_t sig_size = sizeof(code_verification_data.signature); + const u8 *mod = static_cast(meta->modulus); + const size_t mod_size = crypto::Rsa2048PssSha256Verifier::ModulusSize; + const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent(); + const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize; + const u8 *hsh = code_verification_data.target_hash; + const size_t hsh_size = sizeof(code_verification_data.target_hash); + const bool is_signature_valid = crypto::VerifyRsa2048PssSha256WithHash(sig, sig_size, mod, mod_size, exp, exp_size, hsh, hsh_size); + + /* If the signature check fails, we need to check if this is allowable. */ + if (!is_signature_valid) { + /* We have to enforce signature checks on prod and when we have a signature to check on dev. */ + R_UNLESS(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature()); + R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature()); + + /* There was no signature to check on dev. Check if this is acceptable. */ + R_UNLESS(IsUnqualifiedApproval(meta), ldr::ResultInvalidNcaSignature()); + } + } + + /* All good. */ + R_SUCCEED(); + } + + Result GetCreateProcessFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { + const u8 meta_flags = meta->npdm->flags; + + u32 flags = 0; + + /* Set Is64Bit. */ + if (meta_flags & Npdm::MetaFlag_Is64Bit) { + flags |= svc::CreateProcessFlag_Is64Bit; + } + + /* Set AddressSpaceType. */ + switch (GetAddressSpaceType(meta)) { + case Npdm::AddressSpaceType_32Bit: + flags |= svc::CreateProcessFlag_AddressSpace32Bit; + break; + case Npdm::AddressSpaceType_64BitDeprecated: + flags |= svc::CreateProcessFlag_AddressSpace64BitDeprecated; + break; + case Npdm::AddressSpaceType_32BitWithoutAlias: + flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias; + break; + case Npdm::AddressSpaceType_64Bit: + flags |= svc::CreateProcessFlag_AddressSpace64Bit; + break; + default: + R_THROW(ldr::ResultInvalidMeta()); + } + + /* Set Enable Debug. */ + if (ldr_flags & CreateProcessFlag_EnableDebug) { + flags |= svc::CreateProcessFlag_EnableDebug; + } + + /* Set Enable ASLR. */ + if (!(ldr_flags & CreateProcessFlag_DisableAslr)) { + flags |= svc::CreateProcessFlag_EnableAslr; + } + + /* Set Is Application. */ + if (IsApplication(meta)) { + flags |= svc::CreateProcessFlag_IsApplication; + + /* 7.0.0+: Set OptimizeMemoryAllocation if relevant. */ + if (hos::GetVersion() >= hos::Version_7_0_0) { + if (meta_flags & Npdm::MetaFlag_OptimizeMemoryAllocation) { + flags |= svc::CreateProcessFlag_OptimizeMemoryAllocation; + } + } + } + + /* 5.0.0+ Set Pool Partition. */ + if (hos::GetVersion() >= hos::Version_5_0_0) { + /* TODO: Nintendo no longer accepts Applet when pool partition == application. Would this break hbl/anything else in the hb ecosystem? */ + /* TODO: Nintendo uses a helper bool MakeSvcPoolPartitionFlag(u32 *out, Acid::PoolPartition partition); */ + switch (GetPoolPartition(meta)) { + case Acid::PoolPartition_Application: + if (IsApplet(meta)) { + flags |= svc::CreateProcessFlag_PoolPartitionApplet; + } else { + flags |= svc::CreateProcessFlag_PoolPartitionApplication; + } + break; + case Acid::PoolPartition_Applet: + flags |= svc::CreateProcessFlag_PoolPartitionApplet; + break; + case Acid::PoolPartition_System: + flags |= svc::CreateProcessFlag_PoolPartitionSystem; + break; + case Acid::PoolPartition_SystemNonSecure: + flags |= svc::CreateProcessFlag_PoolPartitionSystemNonSecure; + break; + default: + R_THROW(ldr::ResultInvalidMeta()); + } + } else if (hos::GetVersion() >= hos::Version_4_0_0) { + /* On 4.0.0+, the corresponding bit was simply "UseSecureMemory". */ + if (meta->acid->flags & Acid::AcidFlag_DeprecatedUseSecureMemory) { + flags |= svc::CreateProcessFlag_DeprecatedUseSecureMemory; + } + } + + /* 11.0.0+/meso Set Disable DAS merge. */ + if (meta_flags & Npdm::MetaFlag_DisableDeviceAddressSpaceMerge) { + flags |= svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; + } + + /* 18.0.0+/meso Set Alias region extra size. */ + if (meta_flags & Npdm::MetaFlag_EnableAliasRegionExtraSize) { + flags |= svc::CreateProcessFlag_EnableAliasRegionExtraSize; + } + + *out = flags; + R_SUCCEED(); + } + + Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, os::NativeHandle resource_limit) { + /* Clear output. */ + std::memset(out, 0, sizeof(*out)); + + /* Set name, version, program id, resource limit handle. */ + std::memcpy(out->name, meta->npdm->program_name, sizeof(out->name) - 1); + out->version = meta->npdm->version; + out->program_id = meta->aci->program_id.value; + out->reslimit = resource_limit; + + /* Set flags. */ + R_TRY(GetCreateProcessFlags(std::addressof(out->flags), meta, flags)); + + /* 3.0.0+ System Resource Size. */ + if (hos::GetVersion() >= hos::Version_3_0_0) { + /* Validate size is aligned. */ + R_UNLESS(util::IsAligned(meta->npdm->system_resource_size, os::MemoryBlockUnitSize), ldr::ResultInvalidSize()); + + /* Validate system resource usage. */ + if (meta->npdm->system_resource_size) { + /* Process must be 64-bit. */ + R_UNLESS((out->flags & svc::CreateProcessFlag_AddressSpace64Bit), ldr::ResultInvalidMeta()); + + /* Process must be application or applet. */ + R_UNLESS(IsApplication(meta) || IsApplet(meta), ldr::ResultInvalidMeta()); + + /* Size must be less than or equal to max. */ + R_UNLESS(meta->npdm->system_resource_size <= SystemResourceSizeMax, ldr::ResultInvalidMeta()); + } + out->system_resource_num_pages = meta->npdm->system_resource_size >> 12; + } + + R_SUCCEED(); + } + + u64 GenerateSecureRandom(u64 max) { + /* Generate a cryptographically random number. */ + u64 rand; + crypto::GenerateCryptographicallyRandomBytes(std::addressof(rand), sizeof(rand)); + + /* Coerce into range. */ + return rand % (max + 1); + } + + Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument) { + /* Clear output. */ + out->args_address = 0; + out->args_size = 0; + std::memset(out->nso_address, 0, sizeof(out->nso_address)); + std::memset(out->nso_size, 0, sizeof(out->nso_size)); + + size_t total_size = 0; + bool argument_allocated = false; + + /* Calculate base offsets. */ + for (size_t i = 0; i < Nso_Count; i++) { + if (has_nso[i]) { + out->nso_address[i] = total_size; + const size_t text_end = nso_headers[i].text_dst_offset + nso_headers[i].text_size; + const size_t ro_end = nso_headers[i].ro_dst_offset + nso_headers[i].ro_size; + const size_t rw_end = nso_headers[i].rw_dst_offset + nso_headers[i].rw_size + nso_headers[i].bss_size; + out->nso_size[i] = text_end; + out->nso_size[i] = std::max(out->nso_size[i], ro_end); + out->nso_size[i] = std::max(out->nso_size[i], rw_end); + out->nso_size[i] = util::AlignUp(out->nso_size[i], os::MemoryPageSize); + + total_size += out->nso_size[i]; + + if (!argument_allocated && argument != nullptr) { + out->args_address = total_size; + out->args_size = util::AlignUp(2 * sizeof(u32) + argument->argument_size * 2 + ArgumentStore::ArgumentBufferSize, os::MemoryPageSize); + total_size += out->args_size; + argument_allocated = true; + } + } + } + + /* Calculate ASLR. */ + uintptr_t aslr_start = 0; + size_t aslr_size = 0; + if (hos::GetVersion() >= hos::Version_2_0_0) { + switch (out_param->flags & svc::CreateProcessFlag_AddressSpaceMask) { + case svc::CreateProcessFlag_AddressSpace32Bit: + case svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: + aslr_start = svc::AddressSmallMap32Start; + aslr_size = svc::AddressSmallMap32Size; + break; + case svc::CreateProcessFlag_AddressSpace64BitDeprecated: + aslr_start = svc::AddressSmallMap36Start; + aslr_size = svc::AddressSmallMap36Size; + break; + case svc::CreateProcessFlag_AddressSpace64Bit: + aslr_start = svc::AddressMap39Start; + aslr_size = svc::AddressMap39Size; + break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } else { + /* On 1.0.0, only 2 address space types existed. */ + if (out_param->flags & svc::CreateProcessFlag_AddressSpace64BitDeprecated) { + aslr_start = svc::AddressSmallMap36Start; + aslr_size = svc::AddressSmallMap36Size; + } else { + aslr_start = svc::AddressSmallMap32Start; + aslr_size = svc::AddressSmallMap32Size; + } + } + R_UNLESS(total_size <= aslr_size, svc::ResultOutOfMemory()); + + /* Set Create Process output. */ + uintptr_t aslr_slide = 0; + size_t free_size = (aslr_size - total_size); + if (out_param->flags & svc::CreateProcessFlag_EnableAslr) { + aslr_slide = GenerateSecureRandom(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize; + } + + /* Set out. */ + aslr_start += aslr_slide; + for (size_t i = 0; i < Nso_Count; i++) { + if (has_nso[i]) { + out->nso_address[i] += aslr_start; + } + } + if (out->args_address) { + out->args_address += aslr_start; + } + + out_param->code_address = aslr_start; + out_param->code_num_pages = total_size >> 12; + + R_SUCCEED(); + } + + Result LoadAutoLoadModuleSegment(fs::FileHandle file, const NsoHeader::SegmentInfo *segment, size_t file_size, const u8 *file_hash, bool is_compressed, bool check_hash, uintptr_t map_base, uintptr_t map_end) { + /* Select read size based on compression. */ + if (!is_compressed) { + file_size = segment->size; + } + + /* Validate size. */ + R_UNLESS(file_size <= segment->size, ldr::ResultInvalidNso()); + R_UNLESS(segment->size <= std::numeric_limits::max(), ldr::ResultInvalidNso()); + + /* Load data from file. */ + uintptr_t load_address = is_compressed ? map_end - file_size : map_base; + size_t read_size; + R_TRY(fs::ReadFile(std::addressof(read_size), file, segment->file_offset, reinterpret_cast(load_address), file_size)); + R_UNLESS(read_size == file_size, ldr::ResultInvalidNso()); + + /* Uncompress if necessary. */ + if (is_compressed) { + bool decompressed = (util::DecompressLZ4(reinterpret_cast(map_base), segment->size, reinterpret_cast(load_address), file_size) == static_cast(segment->size)); + R_UNLESS(decompressed, ldr::ResultInvalidNso()); + } + + /* Check hash if necessary. */ + if (check_hash) { + u8 hash[crypto::Sha256Generator::HashSize]; + crypto::GenerateSha256(hash, sizeof(hash), reinterpret_cast(map_base), segment->size); + + R_UNLESS(std::memcmp(hash, file_hash, sizeof(hash)) == 0, ldr::ResultInvalidNso()); + } + + R_SUCCEED(); + } + + Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, bool prevent_code_reads) { + /* Map and read data from file. */ + { + /* Map the process memory. */ + void *mapped_memory = nullptr; + R_TRY(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, nso_address, nso_size, GenerateSecureRandom)); + ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, process_handle, nso_address, nso_size); }; + + const uintptr_t map_address = reinterpret_cast(mapped_memory); + + /* Load NSO segments. */ + R_TRY(LoadAutoLoadModuleSegment(file, std::addressof(nso_header->segments[NsoHeader::Segment_Text]), nso_header->text_compressed_size, nso_header->text_hash, (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, + (nso_header->flags & NsoHeader::Flag_CheckHashText) != 0, map_address + nso_header->text_dst_offset, map_address + nso_size)); + R_TRY(LoadAutoLoadModuleSegment(file, std::addressof(nso_header->segments[NsoHeader::Segment_Ro]), nso_header->ro_compressed_size, nso_header->ro_hash, (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, + (nso_header->flags & NsoHeader::Flag_CheckHashRo) != 0, map_address + nso_header->ro_dst_offset, map_address + nso_size)); + R_TRY(LoadAutoLoadModuleSegment(file, std::addressof(nso_header->segments[NsoHeader::Segment_Rw]), nso_header->rw_compressed_size, nso_header->rw_hash, (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, + (nso_header->flags & NsoHeader::Flag_CheckHashRw) != 0, map_address + nso_header->rw_dst_offset, map_address + nso_size)); + + /* Clear unused space to zero. */ + const size_t text_end = nso_header->text_dst_offset + nso_header->text_size; + const size_t ro_end = nso_header->ro_dst_offset + nso_header->ro_size; + const size_t rw_end = nso_header->rw_dst_offset + nso_header->rw_size; + std::memset(reinterpret_cast(map_address + 0), 0, nso_header->text_dst_offset); + std::memset(reinterpret_cast(map_address + text_end), 0, nso_header->ro_dst_offset - text_end); + std::memset(reinterpret_cast(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end); + std::memset(reinterpret_cast(map_address + rw_end), 0, nso_header->bss_size); + + /* Apply embedded patches. */ + ApplyEmbeddedPatchesToModule(nso_header->module_id, map_address, nso_size); + + /* Apply IPS patches. */ + LocateAndApplyIpsPatchesToModule(nso_header->module_id, map_address, nso_size); + + /* Apply PCV and PTM patches */ +if (g_is_pcv) + oc::pcv::Patch(map_address, nso_size); +if (g_is_ptm) + oc::ptm::Patch(map_address, nso_size); + + } + + /* Set permissions. */ + const size_t text_size = util::AlignUp(nso_header->text_size, os::MemoryPageSize); + const size_t ro_size = util::AlignUp(nso_header->ro_size, os::MemoryPageSize); + const size_t rw_size = util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize); + if (text_size) { + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, prevent_code_reads ? os::MemoryPermission_ExecuteOnly : os::MemoryPermission_ReadExecute)); + } + if (ro_size) { + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->ro_dst_offset, ro_size, os::MemoryPermission_ReadOnly)); + } + if (rw_size) { + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->rw_dst_offset, rw_size, os::MemoryPermission_ReadWrite)); + } + + R_SUCCEED(); + } + + Result LoadAutoLoadModules(const ProcessInfo *process_info, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument, bool prevent_code_reads) { + /* Load each NSO. */ + for (size_t i = 0; i < Nso_Count; i++) { + if (has_nso[i]) { + fs::FileHandle file; + R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read)); + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + R_TRY(LoadAutoLoadModule(process_info->process_handle, file, nso_headers + i, process_info->nso_address[i], process_info->nso_size[i], prevent_code_reads)); + } + } + + /* Load arguments, if present. */ + if (argument != nullptr) { + /* Write argument data into memory. */ + { + void *map_address = nullptr; + R_TRY(os::MapProcessMemory(std::addressof(map_address), process_info->process_handle, process_info->args_address, process_info->args_size, GenerateSecureRandom)); + ON_SCOPE_EXIT { os::UnmapProcessMemory(map_address, process_info->process_handle, process_info->args_address, process_info->args_size); }; + + ProgramArguments *args = static_cast(map_address); + std::memset(args, 0, sizeof(*args)); + args->allocated_size = process_info->args_size; + args->arguments_size = argument->argument_size; + std::memcpy(args->arguments, argument->argument, argument->argument_size); + } + + /* Set argument region permissions. */ + /* NOTE: Nintendo uses svc::SetProcessMemoryPermission directly here. */ + R_TRY(os::SetProcessMemoryPermission(process_info->process_handle, process_info->args_address, process_info->args_size, os::MemoryPermission_ReadWrite)); + } + + R_SUCCEED(); + } + + Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { + /* Get CreateProcessParameter. */ + svc::CreateProcessParameter param; + R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit)); + + /* Decide on an NSO layout. */ + R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), nso_headers, has_nso, argument)); + + /* Actually create process. */ + svc::Handle process_handle; + R_TRY(svc::CreateProcess(std::addressof(process_handle), std::addressof(param), static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(u32))); + + /* Set the output handle, and ensure that if we fail after this point we clean it up. */ + out->process_handle = process_handle; + ON_RESULT_FAILURE { svc::CloseHandle(process_handle); }; + + /* Load all auto load modules. */ + R_RETURN(LoadAutoLoadModules(out, nso_headers, has_nso, argument, (meta->npdm->flags & ldr::Npdm::MetaFlag_PreventCodeReads) != 0)); + } + + } + + /* Process Creation API. */ + Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, const ldr::ProgramAttributes &attrs) { + /* Mount code. */ + AMS_UNUSED(path); + ScopedCodeMount mount(loc, override_status, attrs); + R_TRY(mount.GetResult()); + + /* Load meta, possibly from cache. */ + Meta meta; + R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status, attrs.platform)); + + /* Validate meta. */ + R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData())); + + /* Load, validate NSO headers. */ + R_TRY(LoadAutoLoadHeaders(g_nso_headers, g_has_nso)); + R_TRY(CheckAutoLoad(g_nso_headers, g_has_nso)); + + /* Actually create the process and load NSOs into process memory. */ + ProcessInfo info; + R_TRY(CreateProcessAndLoadAutoLoadModules(std::addressof(info), std::addressof(meta), g_nso_headers, g_has_nso, argument, flags, resource_limit)); + + /* Register NSOs with the RoManager. */ + { + /* Nintendo doesn't validate this get, but we do. */ + os::ProcessId process_id = os::GetProcessId(info.process_handle); + + /* Register new process. */ + const auto as_type = GetAddressSpaceType(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated); + + /* Register all NSOs. */ + for (size_t i = 0; i < Nso_Count; i++) { + if (g_has_nso[i]) { + RoManager::GetInstance().AddNso(pin_id, g_nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]); + } + } + } + + /* If we're overriding for HBL, perform HTML document redirection. */ + if (override_status.IsHbl()) { + /* Don't validate result, failure is okay. */ + RedirectHtmlDocumentPathForHbl(loc); + } + + /* Clear the external code for the program. */ + fssystem::DestroyExternalCode(loc.program_id); + + /* Note that we've created the program. */ + SetLaunchedBootProgram(loc.program_id); + + /* Move the process handle to output. */ + *out = info.process_handle; + + R_SUCCEED(); + } + + Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, const ldr::ProgramAttributes &attrs) { + Meta meta; + + /* Load Meta. */ + { + AMS_UNUSED(path); + + ScopedCodeMount mount(loc, attrs); + R_TRY(mount.GetResult()); + R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), attrs.platform, false)); + if (out_status != nullptr) { + *out_status = mount.GetOverrideStatus(); + } + } + + return GetProgramInfoFromMeta(out, std::addressof(meta)); + } + + Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { + R_UNLESS(RoManager::GetInstance().Allocate(out_id, loc, override_status), ldr::ResultMaxProcess()); + R_SUCCEED(); + } + + Result UnpinProgram(PinId id) { + R_UNLESS(RoManager::GetInstance().Free(id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { + R_UNLESS(RoManager::GetInstance().GetProcessModuleInfo(out_count, out, max_out_count, process_id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + + Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) { + R_UNLESS(RoManager::GetInstance().GetProgramLocationAndStatus(out, out_status, pin_id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 95d219cf..b20780da 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -56,7 +56,7 @@ volatile CustomizeTable C = { * - System instabilities * - NAND corruption */ -.eristaEmcMaxClock = 2265280, +.eristaEmcMaxClock = 2240000, /* Mariko CPU: * - Max Voltage in mV: diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp index 13c94636..b6057757 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -79,6 +79,8 @@ // tRC (ACTIVATE-ACTIVATE command period same bank) in ns const u32 tRC = tRPpb + tRAS; + + const u32 tRTW = !C.t6_tRTW ? 10 : tWTR_values[C.t6_tRTW-1]; // DQS output access time from CK_t/CK_c const double tDQSCK_min = 1.5; // DQS output access time from CK_t/CK_c @@ -197,7 +199,7 @@ const u32 RL = 32 - C.mem_burst_latency; // minimum number of cycles from any read command to any write command, irrespective of bank - const u32 R2W = CEIL (RL + CEIL(tDQSCK_max/tCK_avg) + BL/2 - WL + tWPRE + FLOOR(tRPST)); + const u32 R2W = WL + BL/2 + 1 + CEIL(tRTW/tCK_avg); // Delay Time From WRITE-to-READ const u32 W2R = WL + BL/2 + 1 + CEIL(tWTR/tCK_avg); diff --git a/Source/sys-clk/manager/Makefile b/Source/sys-clk/manager/Makefile index 52f9880e..bfd99a64 100644 --- a/Source/sys-clk/manager/Makefile +++ b/Source/sys-clk/manager/Makefile @@ -43,7 +43,7 @@ SOURCES := src ../common/src ../common/src/client RESOURCES := resources DATA := data INCLUDES := ../common/include -APP_TITLE := sys-clk-OCS2 Manager +APP_TITLE := Horizon OC Manager APP_AUTHOR := Souldbminer, meha, b0rd2dEAth and RetroNX Team ROMFS := $(BUILD)/romfs diff --git a/Source/sys-clk/overlay/Makefile b/Source/sys-clk/overlay/Makefile index 35538c0e..0cc33c74 100644 --- a/Source/sys-clk/overlay/Makefile +++ b/Source/sys-clk/overlay/Makefile @@ -26,7 +26,7 @@ DATA := data INCLUDES := ../common/include EXEFS_SRC := exefs_src -APP_TITLE := sys-clk-ocs2 +APP_TITLE := Horizon OC NO_ICON := 1 # This location should reflect where you place the libultrahand directory (lib can vary between projects). diff --git a/Source/sys-clk/overlay/src/ui/gui/base_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/base_gui.cpp index 0f707f19..d32986b2 100644 --- a/Source/sys-clk/overlay/src/ui/gui/base_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/base_gui.cpp @@ -36,7 +36,7 @@ std::string getVersionString() { void BaseGui::preDraw(tsl::gfx::Renderer* renderer) { // renderer->drawBitmap(LOGO_X, LOGO_Y, LOGO_WIDTH, LOGO_HEIGHT, logo_rgba_bin); - renderer->drawString("sys-clk-ocs2 overlay", false, LOGO_X, LOGO_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR)); + renderer->drawString("Horizon OC overlay", false, LOGO_X, LOGO_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR)); // renderer->drawString(TARGET_VERSION, false, VERSION_X, VERSION_Y, VERSION_FONT_SIZE, tsl::bannerVersionTextColor); } diff --git a/Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp index 9804858c..a1f225a0 100644 --- a/Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp @@ -23,7 +23,7 @@ void FatalGui::openWithResultCode(std::string tag, Result rc) info.append(rcStr, snprintf(rcStr, sizeof(rcStr), "\n\n[0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc))); tsl::changeTo( - "Could not connect to sys-clk-ocs2 sysmodule.\n\n" + "Could not connect to Horizon OC sysmodule.\n\n" "\n" "Please make sure everything is\n\n" "correctly installed and enabled.", diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ac30e7de990c42b207137121b989111ab911b1f0 GIT binary patch literal 83519 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%0DG9;{x9YD8xE_E-(U^W@TDX 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πI%9(g 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 literal 0 HcmV?d00001 diff --git a/build.sh b/build.sh index 9b97824a..8353cecc 100644 --- a/build.sh +++ b/build.sh @@ -15,7 +15,7 @@ cd build/stratosphere/loader || exit 1 rm out/nintendo_nx_arm64_armv8a/release/loader.kip rm -rf build/ make -j"$(nproc)" -hactool -t kip1 out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=ocs2.kip +hactool -t kip1 out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=hoc.kip rm out/nintendo_nx_arm64_armv8a/release/loader.kip rm -rf build/ diff --git a/build_kip.sh b/build_kip.sh deleted file mode 100644 index e69de29b..00000000