From b05166d502e6acd80a9351442b1ed7c4a6767b56 Mon Sep 17 00:00:00 2001 From: dogty Date: Tue, 14 Jul 2026 13:35:56 +0200 Subject: [PATCH 01/52] sf: close request copy handles in mitm ForwardRequest ForwardRequest closes copy handles from the forward response but never from the request. Any mitm'd command that carries a client copy handle therefore leaks that handle in the mitm process for its lifetime. A leaked transfer memory pins the client process object after it dies, its application memory reservation never releases, and the next application launch blocks forever freezing the console. Close the request's copy handles after the forward send, parsed from the saved message. --- .../source/sf/hipc/sf_hipc_server_session_manager.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp index 692ed092b..b8bf1ee19 100644 --- a/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp +++ b/libraries/libstratosphere/source/sf/hipc/sf_hipc_server_session_manager.cpp @@ -60,7 +60,16 @@ namespace ams::sf::hipc { PreProcessCommandBufferForMitm(ctx, m_pointer_buffer, reinterpret_cast(message_buffer)); /* Dispatch forwards. */ - R_TRY(svc::SendSyncRequest(util::GetReference(m_forward_service)->session)); + { + ON_SCOPE_EXIT { + const auto saved_request = hipcParseRequest(const_cast(m_saved_message.GetPointer())); + for (u32 i = 0; i < saved_request.meta.num_copy_handles; i++) { + os::CloseNativeHandle(saved_request.data.copy_handles[i]); + } + }; + + R_TRY(svc::SendSyncRequest(util::GetReference(m_forward_service)->session)); + } /* Parse, to ensure we catch any copy handles and close them. */ { From f7d46d38fafa114d7c784dbdc24d9382a0a0ba32 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Fri, 21 Aug 2026 23:13:40 +0100 Subject: [PATCH 02/52] meso: only increment send/recv/exch on success --- .../libmesosphere/source/kern_k_session_request.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/libmesosphere/source/kern_k_session_request.cpp b/libraries/libmesosphere/source/kern_k_session_request.cpp index deb1619d5..a40611949 100644 --- a/libraries/libmesosphere/source/kern_k_session_request.cpp +++ b/libraries/libmesosphere/source/kern_k_session_request.cpp @@ -44,16 +44,19 @@ namespace ams::kern { Result KSessionRequest::SessionMappings::PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) { MESOSPHERE_ASSERT(m_num_recv == 0); MESOSPHERE_ASSERT(m_num_exch == 0); - R_RETURN(this->PushMap(client, server, size, state, m_num_send++)); + ON_RESULT_SUCCESS { ++m_num_send; }; + R_RETURN(this->PushMap(client, server, size, state, m_num_send)); } Result KSessionRequest::SessionMappings::PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) { MESOSPHERE_ASSERT(m_num_exch == 0); - R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv++)); + ON_RESULT_SUCCESS { ++m_num_recv; }; + R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv)); } Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) { - R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++)); + ON_RESULT_SUCCESS { ++m_num_exch; }; + R_RETURN(this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch)); } void KSessionRequest::SessionMappings::Finalize() { From cb4b882e3b176480ac57a1161a85ff175c3f162c Mon Sep 17 00:00:00 2001 From: hexkyz Date: Fri, 21 Aug 2026 23:15:32 +0100 Subject: [PATCH 03/52] git subrepo push libraries subrepo: subdir: "libraries" merged: "edb2cca26" upstream: origin: "https://github.com/Atmosphere-NX/Atmosphere-libs" branch: "master" commit: "edb2cca26" git-subrepo: version: "0.4.9" origin: "???" commit: "???" --- libraries/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/.gitrepo b/libraries/.gitrepo index e8ed07d70..5efbca955 100644 --- a/libraries/.gitrepo +++ b/libraries/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/Atmosphere-NX/Atmosphere-libs branch = master - commit = d3083af1827cd6ca2a96feb9316eb85cd01bae1f - parent = 974a1025b834136134e8133d8db23f69cb5ae0be + commit = edb2cca26f658ef7863eb4c349399d273aab4fae + parent = f7d46d38fafa114d7c784dbdc24d9382a0a0ba32 method = merge cmdver = 0.4.9 From 332926fc17d7d8f1a8822b95016b57affb06a6e8 Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 10 Sep 2026 11:07:49 +0200 Subject: [PATCH 04/52] ams: add Dockerfile with build environment --- Dockerfile | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..7421d0037 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,81 @@ +FROM devkitpro/devkita64:20260219 + +ARG PYTHON_VERSION=2.7.18 +ARG PYTHON_SHA256=da3080e3b488f648a3d7a4560ddee895284c3380b11d6de75edb986526b9a814 +ARG PYTHON_LZ4_VERSION=2.2.1 +ARG PYTHON_LZ4_SHA256=9f529a443f9eb1b49d040f0791bb3934c64b9a927609a30319c3b82f93d9525a + +RUN apt update && \ + apt install automake build-essential ca-certificates wget libbz2-dev libffi-dev libgdbm-dev liblz4-dev libncurses5-dev libreadline-dev libsqlite3-dev libssl-dev liblzma-dev sudo tk-dev uuid-dev zlib1g-dev python3-lz4 python3-pip -y && \ + cd /tmp && \ + wget -q https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz && \ + echo "${PYTHON_SHA256} Python-${PYTHON_VERSION}.tgz" | sha256sum --check && \ + tar -xzf Python-${PYTHON_VERSION}.tgz && \ + cd /tmp/Python-${PYTHON_VERSION} && \ + ./configure --prefix=/usr/local --with-ensurepip=install && \ + make -j"$(nproc)" altinstall && \ + cd /tmp && \ + wget -q https://files.pythonhosted.org/packages/86/4f/028a9ff9cfc73f317c22dc3b8f29a7c5c94098d4da590405e6b78af00e57/lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \ + echo "${PYTHON_LZ4_SHA256} lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl" | sha256sum --check && \ + /usr/local/bin/python2.7 -m pip install --no-deps --no-index lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \ + ln -fs /usr/local/bin/python2.7 /usr/local/bin/python2 && \ + ln -fs /usr/local/bin/python2.7 /usr/local/bin/python && \ + rm -rf /tmp/Python-${PYTHON_VERSION} /tmp/Python-${PYTHON_VERSION}.tgz /tmp/lz4-${PYTHON_LZ4_VERSION}-cp27-cp27m-manylinux1_x86_64.whl && \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/* /usr/share/doc /usr/share/man + +# Install latest hactool & switch-tools from dkp pacman & update everything +RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfirm + +# # Install hactool from Git (optional) +# ENV HACTOOL_REV=1d64a83450e025622f3468c28fc4164dad2c5ef6 +# RUN cd /tmp && \ +# mkdir -p /tmp/hactool && \ +# cd /tmp/hactool && \ +# git init && \ +# git remote add origin https://github.com/SciresM/hactool.git && \ +# git fetch --depth 1 origin $HACTOOL_REV && \ +# git reset --hard FETCH_HEAD && \ +# cp config.mk.template config.mk && \ +# make -j$(nproc) && \ +# cp hactool /opt/devkitpro/tools/bin/hactool && \ +# cd /tmp && \ +# rm -rf /tmp/hactool + +# # Install switch-tools from Git (optional) +# ENV SWITCH_TOOLS_REV=22756068dd0ed6ff9734c59cb4f99ebd3f62555b +# RUN cd /tmp && \ +# mkdir -p /tmp/switch-tools && \ +# cd /tmp/switch-tools && \ +# git init && \ +# git remote add origin https://github.com/switchbrew/switch-tools.git && \ +# git fetch --depth 1 origin $SWITCH_TOOLS_REV && \ +# git reset --hard FETCH_HEAD && \ +# ./autogen.sh && ./configure && make -j$(nproc) && \ +# make install prefix=/opt/devkitpro/tools && \ +# cd /tmp && \ +# rm -rf /tmp/switch-tools + +# Install libnx from Git (optional) +# ENV LIBNX_REV=dbcc1beafc6b47b5ffbeb8ba82463a7d45da40bb +# RUN cd /tmp && \ +# mkdir -p /tmp/libnx && \ +# cd /tmp/libnx && \ +# git init && \ +# git remote add origin https://github.com/switchbrew/libnx.git && \ +# git fetch --depth 1 origin $LIBNX_REV && \ +# git reset --hard FETCH_HEAD && \ +# make -j$(nproc) && \ +# mkdir -p /opt/devkitpro/libnx && \ +# cd nx && \ +# make DESTDIR=/opt/devkitpro/libnx install && \ +# cd /tmp && \ +# rm -rf /tmp/libnx + +RUN useradd -m atmosphere && \ + echo "atmosphere ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/atmosphere && \ + chmod 0440 /etc/sudoers.d/atmosphere && \ + echo "atmosphere:atmosphere" | chpasswd && \ + usermod -aG sudo atmosphere + +USER atmosphere +CMD ["/bin/bash"] From 3d3f0c2dafa954e4d40d2737539ca870af65064b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 10 Sep 2026 15:31:12 +0100 Subject: [PATCH 05/52] fusee/exo/ams: update with new keydata/version enums --- .../program/source/boot/secmon_boot_key_data.s | 11 ++++++++--- exosphere/program/source/boot/secmon_package2.cpp | 2 +- fusee/program/source/fusee_key_derivation.cpp | 11 ++++++++--- fusee/program/source/fusee_package2.cpp | 2 +- fusee/program/source/fusee_setup_horizon.cpp | 2 ++ fusee/program/source/fusee_stratosphere.cpp | 13 +++++++++++++ .../include/exosphere/pkg1/pkg1_key_generation.hpp | 1 + libraries/libexosphere/include/exosphere/pkg2.hpp | 2 +- libraries/libexosphere/source/fuse/fuse_api.cpp | 1 + .../include/stratosphere/hos/hos_types.hpp | 1 + .../source/fs/impl/fs_id_string_impl.os.generic.cpp | 5 +++-- .../include/vapours/ams/ams_api_version.h | 8 ++++---- .../include/vapours/ams/ams_target_firmware.h | 4 +++- 13 files changed, 47 insertions(+), 16 deletions(-) diff --git a/exosphere/program/source/boot/secmon_boot_key_data.s b/exosphere/program/source/boot/secmon_boot_key_data.s index f418d25c9..8ccccbed3 100644 --- a/exosphere/program/source/boot/secmon_boot_key_data.s +++ b/exosphere/program/source/boot/secmon_boot_key_data.s @@ -85,10 +85,10 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: /* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */ /* TODO: Update on next change of keys. */ /* Mariko Development Master Kek Source. */ -.byte 0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B +.byte 0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13 /* Mariko Production Master Kek Source. */ -.byte 0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13 +.byte 0x08, 0x11, 0xF7, 0xE8, 0x76, 0x9E, 0xA3, 0xD5, 0x3A, 0x3D, 0x7A, 0x68, 0x1A, 0x24, 0x2A, 0x99 /* Development Master Key Vectors. */ .byte 0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE /* Zeroes encrypted with Master Key 00. */ @@ -113,6 +113,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE /* Master key 12 encrypted with Master key 13. */ .byte 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E /* Master key 13 encrypted with Master key 14. */ .byte 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF /* Master key 14 encrypted with Master key 15. */ +.byte 0xA6, 0x25, 0x12, 0x6D, 0xA1, 0x12, 0x1F, 0x15, 0x08, 0x2F, 0x30, 0x5F, 0xCB, 0x7D, 0x32, 0x82 /* Master key 15 encrypted with Master key 16. */ /* Production Master Key Vectors. */ .byte 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D /* Zeroes encrypted with Master Key 00. */ @@ -137,6 +138,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 /* Master key 12 encrypted with Master key 13. */ .byte 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA /* Master key 13 encrypted with Master key 14. */ .byte 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 /* Master key 14 encrypted with Master key 15. */ +.byte 0x26, 0x87, 0xDF, 0x21, 0x44, 0xD4, 0x5F, 0x4E, 0x61, 0x03, 0x9E, 0xF3, 0x40, 0x04, 0xC3, 0x87 /* Master Key 15 encrypted with Master Key 16. */ /* Device Master Key Source Sources. */ .byte 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D /* 4.0.0 Device Master Key Source Source. */ @@ -158,6 +160,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 /* 20.0.0 Device Master Key Source Source. */ .byte 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F /* 21.0.0 Device Master Key Source Source. */ .byte 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 /* 22.0.0 Device Master Key Source Source. */ +.byte 0x95, 0xC1, 0xAC, 0xB7, 0xB2, 0xCA, 0x9B, 0x8C, 0xD5, 0xEA, 0x40, 0xD9, 0x9C, 0xD2, 0x7C, 0x47 /* 23.0.0 Device Master Key Source Source. */ /* Development Device Master Kek Sources. */ .byte 0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34 /* 4.0.0 Device Master Kek Source. */ @@ -179,6 +182,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D /* 20.0.0 Device Master Kek Source. */ .byte 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F /* 21.0.0 Device Master Kek Source. */ .byte 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F /* 22.0.0 Device Master Kek Source. */ +.byte 0x54, 0xAD, 0x79, 0x15, 0x11, 0x7C, 0x1E, 0x52, 0xBF, 0x2E, 0x40, 0xBB, 0x8B, 0x11, 0x54, 0x38 /* 23.0.0 Device Master Kek Source. */ /* Production Device Master Kek Sources. */ .byte 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D /* 4.0.0 Device Master Kek Source. */ @@ -199,4 +203,5 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F /* 19.0.0 Device Master Kek Source. */ .byte 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 /* 20.0.0 Device Master Kek Source. */ .byte 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 /* 21.0.0 Device Master Kek Source. */ -.byte 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 /* 22.0.0 Device Master Kek Source. */ \ No newline at end of file +.byte 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 /* 22.0.0 Device Master Kek Source. */ +.byte 0xA0, 0xC8, 0x44, 0x39, 0x8A, 0x1F, 0xD8, 0x6A, 0x3D, 0x0A, 0x23, 0xFF, 0x43, 0xA6, 0x95, 0x80 /* 23.0.0 Device Master Kek Source. */ \ No newline at end of file diff --git a/exosphere/program/source/boot/secmon_package2.cpp b/exosphere/program/source/boot/secmon_package2.cpp index 005549f4a..cd8dfbb85 100644 --- a/exosphere/program/source/boot/secmon_package2.cpp +++ b/exosphere/program/source/boot/secmon_package2.cpp @@ -94,7 +94,7 @@ namespace ams::secmon::boot { } /* Check that the key generation is one that we can use. */ - static_assert(pkg1::KeyGeneration_Count == 22); + static_assert(pkg1::KeyGeneration_Count == 23); if (key_generation >= pkg1::KeyGeneration_Count) { return false; } diff --git a/fusee/program/source/fusee_key_derivation.cpp b/fusee/program/source/fusee_key_derivation.cpp index f392f67c6..ea9d3387e 100644 --- a/fusee/program/source/fusee_key_derivation.cpp +++ b/fusee/program/source/fusee_key_derivation.cpp @@ -23,17 +23,17 @@ namespace ams::nxboot { alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13 + 0x08, 0x11, 0xF7, 0xE8, 0x76, 0x9E, 0xA3, 0xD5, 0x3A, 0x3D, 0x7A, 0x68, 0x1A, 0x24, 0x2A, 0x99 }; alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B + 0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13 }; alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0x15, 0xAC, 0x96, 0x34, 0xF5, 0x32, 0x56, 0x68, 0xFE, 0x5B, 0x9D, 0xD7, 0xED, 0x19, 0xB7, 0x8E + 0x92, 0xC8, 0x9C, 0x8A, 0x58, 0xE6, 0xE7, 0xB6, 0xE4, 0x27, 0xE2, 0x31, 0xEF, 0x4B, 0xD8, 0x82 }; alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = { @@ -76,6 +76,7 @@ namespace ams::nxboot { { 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 }, /* 20.0.0 Device Master Key Source Source. */ { 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F }, /* 21.0.0 Device Master Key Source Source. */ { 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 }, /* 22.0.0 Device Master Key Source Source. */ + { 0x95, 0xC1, 0xAC, 0xB7, 0xB2, 0xCA, 0x9B, 0x8C, 0xD5, 0xEA, 0x40, 0xD9, 0x9C, 0xD2, 0x7C, 0x47 }, /* 23.0.0 Device Master Key Source Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { @@ -98,6 +99,7 @@ namespace ams::nxboot { { 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 }, /* 20.0.0 Device Master Kek Source. */ { 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 }, /* 21.0.0 Device Master Kek Source. */ { 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 }, /* 22.0.0 Device Master Kek Source. */ + { 0xA0, 0xC8, 0x44, 0x39, 0x8A, 0x1F, 0xD8, 0x6A, 0x3D, 0x0A, 0x23, 0xFF, 0x43, 0xA6, 0x95, 0x80 }, /* 23.0.0 Device Master Kek Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { @@ -120,6 +122,7 @@ namespace ams::nxboot { { 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D }, /* 20.0.0 Device Master Kek Source. */ { 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F }, /* 21.0.0 Device Master Kek Source. */ { 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F }, /* 22.0.0 Device Master Kek Source. */ + { 0x54, 0xAD, 0x79, 0x15, 0x11, 0x7C, 0x1E, 0x52, 0xBF, 0x2E, 0x40, 0xBB, 0x8B, 0x11, 0x54, 0x38 }, /* 23.0.0 Device Master Kek Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = { @@ -145,6 +148,7 @@ namespace ams::nxboot { { 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 }, /* Master key 12 encrypted with Master key 13. */ { 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA }, /* Master key 13 encrypted with Master key 14. */ { 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 }, /* Master key 14 encrypted with Master key 15. */ + { 0x26, 0x87, 0xDF, 0x21, 0x44, 0xD4, 0x5F, 0x4E, 0x61, 0x03, 0x9E, 0xF3, 0x40, 0x04, 0xC3, 0x87 }, /* Master key 15 encrypted with Master key 16. */ }; alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = { @@ -170,6 +174,7 @@ namespace ams::nxboot { { 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE }, /* Master key 12 encrypted with Master key 13. */ { 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E }, /* Master key 13 encrypted with Master key 14. */ { 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF }, /* Master key 14 encrypted with Master key 15. */ + { 0xA6, 0x25, 0x12, 0x6D, 0xA1, 0x12, 0x1F, 0x15, 0x08, 0x2F, 0x30, 0x5F, 0xCB, 0x7D, 0x32, 0x82 }, /* Master key 15 encrypted with Master key 16. */ }; alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {}; diff --git a/fusee/program/source/fusee_package2.cpp b/fusee/program/source/fusee_package2.cpp index 236413eb7..83bfb7aac 100644 --- a/fusee/program/source/fusee_package2.cpp +++ b/fusee/program/source/fusee_package2.cpp @@ -80,7 +80,7 @@ namespace ams::nxboot { } /* Check that the key generation is one that we can use. */ - static_assert(pkg1::KeyGeneration_Count == 22); + static_assert(pkg1::KeyGeneration_Count == 23); if (key_generation >= pkg1::KeyGeneration_Count) { return false; } diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index f5ec03ce3..b978e513b 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -269,6 +269,8 @@ namespace ams::nxboot { return ams::TargetFirmware_21_0_0; } else if (std::memcmp(package1 + 0x10, "20260123", 8) == 0) { return ams::TargetFirmware_22_0_0; + } else if (std::memcmp(package1 + 0x10, "20260730", 8) == 0) { + return ams::TargetFirmware_23_0_0; } break; default: diff --git a/fusee/program/source/fusee_stratosphere.cpp b/fusee/program/source/fusee_stratosphere.cpp index 8f34237d6..92cde52a8 100644 --- a/fusee/program/source/fusee_stratosphere.cpp +++ b/fusee/program/source/fusee_stratosphere.cpp @@ -308,6 +308,9 @@ namespace ams::nxboot { { 0x53, 0x6D, 0x93, 0x84, 0x69, 0xFE, 0x73, 0xBE }, /* FsVersion_22_5_0 */ { 0xD4, 0x45, 0x28, 0x29, 0x5B, 0x41, 0x92, 0xBA }, /* FsVersion_22_5_0_Exfat */ + + { 0x34, 0x38, 0x3E, 0xE7, 0x99, 0x92, 0x63, 0x40 }, /* FsVersion_23_0_0 */ + { 0xFD, 0xAF, 0x16, 0x32, 0x88, 0xE1, 0x08, 0x05 }, /* FsVersion_23_0_0_Exfat */ }; const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) { @@ -733,6 +736,16 @@ namespace ams::nxboot { AddPatch(fs_meta, 0x1BB445, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x18E250, NogcPatch1, sizeof(NogcPatch1)); break; + case FsVersion_23_0_0: + AddPatch(fs_meta, 0x1B36BD, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x1B36D5, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x186340, NogcPatch1, sizeof(NogcPatch1)); + break; + case FsVersion_23_0_0_Exfat: + AddPatch(fs_meta, 0x1BE8BD, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x1BE8D5, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x191540, NogcPatch1, sizeof(NogcPatch1)); + break; default: break; } diff --git a/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp b/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp index f8480acc2..5453fdcb3 100644 --- a/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp +++ b/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp @@ -42,6 +42,7 @@ namespace ams::pkg1 { KeyGeneration_20_0_0 = 0x13, KeyGeneration_21_0_0 = 0x14, KeyGeneration_22_0_0 = 0x15, + KeyGeneration_23_0_0 = 0x16, KeyGeneration_Count, diff --git a/libraries/libexosphere/include/exosphere/pkg2.hpp b/libraries/libexosphere/include/exosphere/pkg2.hpp index d6649d9d0..be84a6ae7 100644 --- a/libraries/libexosphere/include/exosphere/pkg2.hpp +++ b/libraries/libexosphere/include/exosphere/pkg2.hpp @@ -24,7 +24,7 @@ namespace ams::pkg2 { constexpr inline int PayloadCount = 3; constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x18 in Nintendo's code. */ - constexpr inline int CurrentBootloaderVersion = 0x17; + constexpr inline int CurrentBootloaderVersion = 0x18; struct Package2Meta { using Magic = util::FourCC<'P','K','2','1'>; diff --git a/libraries/libexosphere/source/fuse/fuse_api.cpp b/libraries/libexosphere/source/fuse/fuse_api.cpp index 927c611b3..2c0eb1f14 100644 --- a/libraries/libexosphere/source/fuse/fuse_api.cpp +++ b/libraries/libexosphere/source/fuse/fuse_api.cpp @@ -177,6 +177,7 @@ namespace ams::fuse { } constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = { + TargetFirmware_23_0_0, TargetFirmware_22_0_0, TargetFirmware_21_0_0, TargetFirmware_20_0_0, diff --git a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp index c9ee30d02..70f9bec97 100644 --- a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp @@ -103,6 +103,7 @@ namespace ams::hos { Version_22_0_0 = ::ams::TargetFirmware_22_0_0, Version_22_1_0 = ::ams::TargetFirmware_22_1_0, Version_22_5_0 = ::ams::TargetFirmware_22_5_0, + Version_23_0_0 = ::ams::TargetFirmware_23_0_0, Version_Current = ::ams::TargetFirmware_Current, diff --git a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp index f38e8b4be..a1e1ac6ac 100644 --- a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp +++ b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp @@ -21,7 +21,7 @@ namespace ams::fs::impl { #define ADD_ENUM_CASE(v) case v: return #v template<> const char *IdString::ToString(pkg1::KeyGeneration id) { - static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_22_0_0); + static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_23_0_0); switch (id) { using enum pkg1::KeyGeneration; case KeyGeneration_1_0_0: return "1.0.0-2.3.0"; @@ -45,7 +45,8 @@ namespace ams::fs::impl { case KeyGeneration_19_0_0: return "19.0.0-19.0.1"; case KeyGeneration_20_0_0: return "20.0.0-20.5.0"; case KeyGeneration_21_0_0: return "21.0.0-21.2.0"; - case KeyGeneration_22_0_0: return "22.0.0"; + case KeyGeneration_22_0_0: return "22.0.0-22.5.0"; + case KeyGeneration_23_0_0: return "23.0.0"; default: return "Unknown"; } } diff --git a/libraries/libvapours/include/vapours/ams/ams_api_version.h b/libraries/libvapours/include/vapours/ams/ams_api_version.h index 264737f0d..2fd987485 100644 --- a/libraries/libvapours/include/vapours/ams/ams_api_version.h +++ b/libraries/libvapours/include/vapours/ams/ams_api_version.h @@ -16,11 +16,11 @@ #pragma once #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 -#define ATMOSPHERE_RELEASE_VERSION_MINOR 11 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 +#define ATMOSPHERE_RELEASE_VERSION_MINOR 12 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO -#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22 -#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 5 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 23 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 diff --git a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h index 6791a99ca..109405664 100644 --- a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h +++ b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h @@ -101,8 +101,9 @@ #define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_22_1_0 ATMOSPHERE_TARGET_FIRMWARE(22, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_22_5_0 ATMOSPHERE_TARGET_FIRMWARE(22, 5, 0) +#define ATMOSPHERE_TARGET_FIRMWARE_23_0_0 ATMOSPHERE_TARGET_FIRMWARE(23, 0, 0) -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_5_0 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_23_0_0 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT @@ -196,6 +197,7 @@ namespace ams { TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0, TargetFirmware_22_1_0 = ATMOSPHERE_TARGET_FIRMWARE_22_1_0, TargetFirmware_22_5_0 = ATMOSPHERE_TARGET_FIRMWARE_22_5_0, + TargetFirmware_23_0_0 = ATMOSPHERE_TARGET_FIRMWARE_23_0_0, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, From bce987792d0b521d46af2d2acd01b0727905876e Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 10 Sep 2026 16:23:01 +0100 Subject: [PATCH 06/52] emummc: update for 23.0.0 --- emummc/README.md | 2 +- emummc/source/FS/FS_offsets.c | 8 ++++ emummc/source/FS/FS_versions.h | 3 ++ emummc/source/FS/offsets/2300.h | 59 +++++++++++++++++++++++++++ emummc/source/FS/offsets/2300_exfat.h | 59 +++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 emummc/source/FS/offsets/2300.h create mode 100644 emummc/source/FS/offsets/2300_exfat.h diff --git a/emummc/README.md b/emummc/README.md index f63004065..752223788 100644 --- a/emummc/README.md +++ b/emummc/README.md @@ -2,7 +2,7 @@ *A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** ### Supported Horizon Versions -**1.0.0 - 22.5.0** +**1.0.0 - 23.0.0** ## Features * Arbitrary SDMMC backend selection diff --git a/emummc/source/FS/FS_offsets.c b/emummc/source/FS/FS_offsets.c index 133e0e816..f7a2bacf8 100644 --- a/emummc/source/FS/FS_offsets.c +++ b/emummc/source/FS/FS_offsets.c @@ -87,6 +87,8 @@ #include "offsets/2200_exfat.h" #include "offsets/2250.h" #include "offsets/2250_exfat.h" +#include "offsets/2300.h" +#include "offsets/2300_exfat.h" #include "../utils/fatal.h" #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers @@ -185,6 +187,8 @@ DEFINE_OFFSET_STRUCT(_2200); DEFINE_OFFSET_STRUCT(_2200_EXFAT); DEFINE_OFFSET_STRUCT(_2250); DEFINE_OFFSET_STRUCT(_2250_EXFAT); +DEFINE_OFFSET_STRUCT(_2300); +DEFINE_OFFSET_STRUCT(_2300_EXFAT); const fs_offsets_t *get_fs_offsets(enum FS_VER version) { switch (version) { @@ -330,6 +334,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) { return &(GET_OFFSET_STRUCT_NAME(_2250)); case FS_VER_22_5_0_EXFAT: return &(GET_OFFSET_STRUCT_NAME(_2250_EXFAT)); + case FS_VER_23_0_0: + return &(GET_OFFSET_STRUCT_NAME(_2300)); + case FS_VER_23_0_0_EXFAT: + return &(GET_OFFSET_STRUCT_NAME(_2300_EXFAT)); default: fatal_abort(Fatal_UnknownVersion); } diff --git a/emummc/source/FS/FS_versions.h b/emummc/source/FS/FS_versions.h index af2913d0f..d2c240b20 100644 --- a/emummc/source/FS/FS_versions.h +++ b/emummc/source/FS/FS_versions.h @@ -127,6 +127,9 @@ enum FS_VER FS_VER_22_5_0, FS_VER_22_5_0_EXFAT, + + FS_VER_23_0_0, + FS_VER_23_0_0_EXFAT, FS_VER_MAX, }; diff --git a/emummc/source/FS/offsets/2300.h b/emummc/source/FS/offsets/2300.h new file mode 100644 index 000000000..87bd5b130 --- /dev/null +++ b/emummc/source/FS/offsets/2300.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 m4xw + * Copyright (c) 2019 Atmosphere-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 . + */ +#ifndef __FS_2300_H__ +#define __FS_2300_H__ + +// Accessor vtable getters +#define FS_OFFSET_2300_SDMMC_ACCESSOR_GC 0x1B3640 +#define FS_OFFSET_2300_SDMMC_ACCESSOR_SD 0x1B5640 +#define FS_OFFSET_2300_SDMMC_ACCESSOR_NAND 0x1B3C70 + +// Hooks +#define FS_OFFSET_2300_SDMMC_WRAPPER_READ 0x1AF570 +#define FS_OFFSET_2300_SDMMC_WRAPPER_WRITE 0x1AF5D0 +#define FS_OFFSET_2300_RTLD 0x2F520 +#define FS_OFFSET_2300_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C))) + +#define FS_OFFSET_2300_CLKRST_SET_MIN_V_CLK_RATE 0x1D27E0 + +// Misc funcs +#define FS_OFFSET_2300_LOCK_MUTEX 0x1A8090 +#define FS_OFFSET_2300_UNLOCK_MUTEX 0x1A80E0 + +#define FS_OFFSET_2300_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AF530 +#define FS_OFFSET_2300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AF550 + +// Misc Data +#define FS_OFFSET_2300_SD_MUTEX 0xFF5408 +#define FS_OFFSET_2300_NAND_MUTEX 0xFF0D70 +#define FS_OFFSET_2300_ACTIVE_PARTITION 0xFF0DB0 +#define FS_OFFSET_2300_SDMMC_DAS_HANDLE 0xFD2BE8 + +// NOPs +#define FS_OFFSET_2300_SD_DAS_INIT 0x2CA98 + +// Nintendo Paths +#define FS_OFFSET_2300_NINTENDO_PATHS \ +{ \ + {.opcode_reg = 3, .adrp_offset = 0x00072D7C, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 3, .adrp_offset = 0x00081BA4, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 4, .adrp_offset = 0x0008A668, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 4, .adrp_offset = 0x0009F97C, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ +} + +#endif // __FS_2300_H__ diff --git a/emummc/source/FS/offsets/2300_exfat.h b/emummc/source/FS/offsets/2300_exfat.h new file mode 100644 index 000000000..a0f49372f --- /dev/null +++ b/emummc/source/FS/offsets/2300_exfat.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 m4xw + * Copyright (c) 2019 Atmosphere-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 . + */ +#ifndef __FS_2300_EXFAT_H__ +#define __FS_2300_EXFAT_H__ + +// Accessor vtable getters +#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_GC 0x1BE840 +#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_SD 0x1C0840 +#define FS_OFFSET_2300_EXFAT_SDMMC_ACCESSOR_NAND 0x1BEE70 + +// Hooks +#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_READ 0x1BA770 +#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_WRITE 0x1BA7D0 +#define FS_OFFSET_2300_EXFAT_RTLD 0x2F530 +#define FS_OFFSET_2300_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C))) + +#define FS_OFFSET_2300_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DD9E0 + +// Misc funcs +#define FS_OFFSET_2300_EXFAT_LOCK_MUTEX 0x1B3290 +#define FS_OFFSET_2300_EXFAT_UNLOCK_MUTEX 0x1B32E0 + +#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1BA730 +#define FS_OFFSET_2300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1BA750 + +// Misc Data +#define FS_OFFSET_2300_EXFAT_SD_MUTEX 0x1006408 +#define FS_OFFSET_2300_EXFAT_NAND_MUTEX 0x1001D70 +#define FS_OFFSET_2300_EXFAT_ACTIVE_PARTITION 0x1001DB0 +#define FS_OFFSET_2300_EXFAT_SDMMC_DAS_HANDLE 0xFDFBE8 + +// NOPs +#define FS_OFFSET_2300_EXFAT_SD_DAS_INIT 0x2CAA8 + +// Nintendo Paths +#define FS_OFFSET_2300_EXFAT_NINTENDO_PATHS \ +{ \ + {.opcode_reg = 3, .adrp_offset = 0x00072D8C, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 3, .adrp_offset = 0x00081BB4, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 4, .adrp_offset = 0x0008A678, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 4, .adrp_offset = 0x0009F98C, .add_rel_offset = 0x00000004}, \ + {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ +} + +#endif // __FS_2300_EXFAT_H__ \ No newline at end of file From 8ec1288bd619e5b7ccfe0486f1ba8c826d8a7539 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 10 Sep 2026 16:31:52 +0100 Subject: [PATCH 07/52] loader: update USB 3.0 patches for 23.0.0 --- stratosphere/loader/source/ldr_embedded_usb_patches.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/loader/source/ldr_embedded_usb_patches.inc b/stratosphere/loader/source/ldr_embedded_usb_patches.inc index 0ac5bc23c..1ed107817 100644 --- a/stratosphere/loader/source/ldr_embedded_usb_patches.inc +++ b/stratosphere/loader/source/ldr_embedded_usb_patches.inc @@ -102,4 +102,5 @@ constexpr inline const EmbeddedPatch Usb30ForceEnablePatches[] = { { ParseModuleId("766D0C2277207B40AD9B8DE309396D50CCE94885"), util::size(Usb30ForceEnablePatches_21_0_0), Usb30ForceEnablePatches_21_0_0 }, /* 21.0.0 */ { ParseModuleId("B734339F2280170AF0200573F9B943242CEF8C15"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 22.0.0 - 22.1.0 */ { ParseModuleId("AD8D36F2029822A4C498F055ADBDAA789EB913C6"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 22.5.0 */ + { ParseModuleId("760E48C572F8192C9BC6DC8FEB3D6213F0551505"), util::size(Usb30ForceEnablePatches_22_0_0), Usb30ForceEnablePatches_22_0_0 }, /* 23.0.0 */ }; From 85aea12e5324582613770516907adaaed4b869c8 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 10 Sep 2026 16:57:39 +0100 Subject: [PATCH 08/52] erpt: add new IDs and category changes for 23.0.0 --- .../stratosphere/erpt/erpt_ids.autogen.hpp | 84 +++++++++++-------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp index cb4272bfd..6bede3d6f 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp @@ -195,6 +195,8 @@ HANDLER(PscTransitionStateInfo, 154 ) \ HANDLER(FsProxyErrorInfo3, 155 ) \ HANDLER(BluetoothErrorInfo, 156 ) \ + HANDLER(Category_Unknown157, 157 ) \ + HANDLER(Category_Unknown158, 158 ) \ HANDLER(TestNx, 1000) \ HANDLER(NANDTypeInfo, 1001) \ HANDLER(NANDExtendedCsd, 1002) \ @@ -239,9 +241,9 @@ HANDLER(WirelessAPMacAddress, 35, WirelessAPMacAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(GlobalIPAddress, 36, GlobalIPAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(EnableWirelessInterfaceFlag, 37, EnableWirelessInterfaceInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableWifiFlag, 38, EnableWifiInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableBluetoothFlag, 39, EnableBluetoothInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableNFCFlag, 40, EnableNFCInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableWifiFlag, 38, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableBluetoothFlag, 39, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableNFCFlag, 40, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(NintendoZoneSSIDListVersion, 41, NintendoZoneSSIDListVersionInfo, FieldType_String, FieldFlag_None ) \ HANDLER(LANAdapterMacAddress, 42, LANAdapterMacAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(ApplicationID, 43, ApplicationInfo, FieldType_String, FieldFlag_None ) \ @@ -259,9 +261,9 @@ HANDLER(ApplicationRunningFlag, 55, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(DataCorruptionDetectedFlag, 56, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(ProductModel, 57, ProductModelInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(CurrentLanguage, 58, CurrentLanguageInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(UseNetworkTimeProtocolFlag, 59, UseNetworkTimeProtocolInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(TimeZone, 60, TimeZoneInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(CurrentLanguage, 58, Category_Unknown157, FieldType_String, FieldFlag_None ) \ + HANDLER(UseNetworkTimeProtocolFlag, 59, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(TimeZone, 60, Category_Unknown157, FieldType_String, FieldFlag_None ) \ HANDLER(ControllerFirmware, 61, ControllerFirmwareInfo, FieldType_String, FieldFlag_None ) \ HANDLER(VideoOutputSetting, 62, VideoOutputInfo, FieldType_String, FieldFlag_None ) \ HANDLER(NANDFreeSpace, 63, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \ @@ -272,23 +274,23 @@ HANDLER(HdmiAudioOutputMode, 68, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ HANDLER(SpeakerAudioOutputMode, 69, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ HANDLER(HeadphoneAudioOutputMode, 70, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(MuteOnHeadsetUnpluggedFlag, 71, MuteOnHeadsetUnpluggedInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(MuteOnHeadsetUnpluggedFlag, 71, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(NumUserRegistered, 72, NumUserRegisteredInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(StorageAutoOrganizeFlag, 73, DataDeletionInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(ControllerVibrationVolume, 74, ControllerVibrationInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(LockScreenFlag, 75, LockScreenInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(ControllerVibrationVolume, 74, Category_Unknown157, FieldType_String, FieldFlag_None ) \ + HANDLER(LockScreenFlag, 75, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(InternalBatteryLotNumber, 76, InternalBatteryLotNumberInfo, FieldType_String, FieldFlag_None ) \ HANDLER(LeftControllerSerialNumber, 77, LeftControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \ HANDLER(RightControllerSerialNumber, 78, RightControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(NotifyInGameDownloadCompletionFlag, 79, NotificationInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(NotificationSoundFlag, 80, NotificationInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(NotifyInGameDownloadCompletionFlag, 79, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(NotificationSoundFlag, 80, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(TVResolutionSetting, 81, TVInfo, FieldType_String, FieldFlag_None ) \ HANDLER(RGBRangeSetting, 82, TVInfo, FieldType_String, FieldFlag_None ) \ HANDLER(ReduceScreenBurnFlag, 83, TVInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(TVAllowsCecFlag, 84, TVInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(HandheldModeTimeToScreenSleep, 85, SleepInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(ConsoleModeTimeToScreenSleep, 86, SleepInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SleepInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(HandheldModeTimeToScreenSleep, 85, Category_Unknown157, FieldType_String, FieldFlag_None ) \ + HANDLER(ConsoleModeTimeToScreenSleep, 86, Category_Unknown157, FieldType_String, FieldFlag_None ) \ + HANDLER(StopAutoSleepDuringContentPlayFlag, 87, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(LastConnectionTestDownloadSpeed, 88, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \ HANDLER(LastConnectionTestUploadSpeed, 89, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \ HANDLER(DEPRECATED_ServerFQDN, 90, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \ @@ -611,7 +613,7 @@ HANDLER(ElapsedTimeSincePowerOn, 407, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(ElapsedTimeSinceLastAwake, 408, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(OccurrenceTick, 409, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(RetailInteractiveDisplayFlag, 410, RetailInteractiveDisplayInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(RetailInteractiveDisplayFlag, 410, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ HANDLER(FatFsError, 411, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FatFsExtraError, 412, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FatFsErrorDrive, 413, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ @@ -627,7 +629,7 @@ HANDLER(Is720P60Hz, 423, MonitorCapability, FieldType_Bool, FieldFlag_None ) \ HANDLER(PcmChannelMax, 424, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(CrashReportHash, 425, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \ - HANDLER(ErrorReportSharePermission, 426, ErrorReportSharePermissionInfo, FieldType_NumericU8, FieldFlag_None ) \ + HANDLER(ErrorReportSharePermission, 426, Category_Unknown157, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(VideoCodecTypeEnum, 427, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(VideoBitRate, 428, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(VideoFrameRate, 429, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ @@ -673,10 +675,10 @@ HANDLER(FsPatrolReadAllocateBufferFailureCount, 469, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(SteadyClockInternalOffset, 470, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(SteadyClockCurrentTimePointValue, 471, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(UserClockContextOffset, 472, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(UserClockContextTimeStampValue, 473, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(NetworkClockContextOffset, 474, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(NetworkClockContextTimeStampValue, 475, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(UserClockContextOffset, 472, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(UserClockContextTimeStampValue, 473, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(NetworkClockContextOffset, 474, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(NetworkClockContextTimeStampValue, 475, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(SystemAbortFlag, 476, ErrorInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(ApplicationAbortFlag, 477, ErrorInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(NifmErrorCode, 478, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \ @@ -819,16 +821,16 @@ HANDLER(ErrorContext, 615, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \ HANDLER(ErrorContextSize, 616, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(ErrorContextTotalSize, 617, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \ - HANDLER(SystemPhysicalMemoryLimit, 618, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemThreadCountLimit, 619, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemEventCountLimit, 620, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemTransferMemoryCountLimit, 621, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemSessionCountLimit, 622, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemPhysicalMemoryPeak, 623, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemThreadCountPeak, 624, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemEventCountPeak, 625, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemTransferMemoryCountPeak, 626, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(SystemSessionCountPeak, 627, ResourceLimitInfo, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemPhysicalMemoryLimit, 618, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemThreadCountLimit, 619, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemEventCountLimit, 620, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemTransferMemoryCountLimit, 621, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemSessionCountLimit, 622, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemPhysicalMemoryPeak, 623, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemThreadCountPeak, 624, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemEventCountPeak, 625, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemTransferMemoryCountPeak, 626, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(SystemSessionCountPeak, 627, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(GpuCrashHash, 628, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(TouchScreenPanelGpioValue, 629, TouchScreenInfo, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(BrowserCertificateHostName, 630, ErrorInfo, FieldType_String, FieldFlag_None ) \ @@ -886,10 +888,10 @@ HANDLER(AppletId, 682, ApplicationInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(PrevReportIdentifier, 683, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \ HANDLER(SyslogStartupTimeBase, 684, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(NxdmpIsAttached, 685, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(ScreenshotIsAttached, 686, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(SyslogIsAttached, 687, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(SaveSyslogResult, 688, AttachmentFileInfo, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(NxdmpIsAttached, 685, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ + HANDLER(ScreenshotIsAttached, 686, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ + HANDLER(SyslogIsAttached, 687, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ + HANDLER(SaveSyslogResult, 688, ErrorInfoAuto, FieldType_NumericU32, FieldFlag_None ) \ HANDLER(EncryptionKeyGeneration, 689, ErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FsBufferManagerNonBlockingRetriedCount, 690, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(FsPooledBufferNonBlockingRetriedCount, 691, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ @@ -897,11 +899,11 @@ HANDLER(LastConnectionTestUploadSpeed64, 693, ConnectionInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(EncryptionKeyV1, 694, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(GpuCrashDumpAttachmentId, 695, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \ - HANDLER(GpuCrashDumpIsAttached, 696, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(GpuCrashDumpIsAttached, 696, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ HANDLER(CallerIdentifier, 697, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(WlanMainState, 698, WlanInfo, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(WlanSubState, 699, WlanInfo, FieldType_NumericU8, FieldFlag_None ) \ - HANDLER(AdspSyslogIsAttached, 702, AttachmentFileInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(AdspSyslogIsAttached, 702, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ HANDLER(LastHalfAwakeTime, 703, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(LastHalfAwakeTimeAfterBackgroundTaskDone, 704, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(LastHalfAwakeTimeAfterStateUnlocked, 705, HalfAwakeStateInfo, FieldType_NumericI64, FieldFlag_None ) \ @@ -979,7 +981,17 @@ HANDLER(FsSaveDataFileSystemPeakMountCount, 777, FsProxyErrorInfo3, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(TestBool, 778, Test, FieldType_Bool, FieldFlag_None ) \ HANDLER(TestI8Array, 779, Test, FieldType_I8Array, FieldFlag_None ) \ + HANDLER(CloudFrontAmzCfId, 780, ErrorInfo, FieldType_String, FieldFlag_None ) \ HANDLER(SslProcessHeapAllocatable, 781, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(AppletSyslogIsAttached, 782, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \ + HANDLER(FsBisSaveDataFailedRetryMountCount, 783, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(FsSdSaveDataFailedRetryMountCount, 784, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(FsBisSaveDataRecoveredRetryMountCount, 785, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(FsSdSaveDataRecoveredRetryMountCount, 786, FsProxyErrorInfo3, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(BrowserEngineOpenUrl, 787, ErrorInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(FsVariant, 788, SystemSettingInfo, FieldType_NumericU8, FieldFlag_None ) \ + HANDLER(KnownServerFqdnId, 789, ErrorInfoAuto, FieldType_NumericU32, FieldFlag_None ) \ + HANDLER(AcpStreamPlaySaveDataKeyType, 790, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(TestStringNx, 1000, TestNx, FieldType_String, FieldFlag_None ) \ HANDLER(BoostModeCurrentLimit, 1001, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(ChargeConfiguration, 1002, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \ From 22bbe413c65fe0b733614ae770631c379e55f19a Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 11 Sep 2026 02:14:16 +0200 Subject: [PATCH 09/52] fusee: fix missing FS enum --- fusee/program/source/fusee_stratosphere.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fusee/program/source/fusee_stratosphere.cpp b/fusee/program/source/fusee_stratosphere.cpp index 92cde52a8..884d691a5 100644 --- a/fusee/program/source/fusee_stratosphere.cpp +++ b/fusee/program/source/fusee_stratosphere.cpp @@ -198,6 +198,9 @@ namespace ams::nxboot { FsVersion_22_5_0, FsVersion_22_5_0_Exfat, + FsVersion_23_0_0, + FsVersion_23_0_0_Exfat, + FsVersion_Count, }; From 3d8caba822dc0cc44efe8c873fe8e5ae5660a1a1 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sat, 12 Sep 2026 18:33:22 +0100 Subject: [PATCH 10/52] erpt: update categories for 23.0.0 --- .../stratosphere/erpt/erpt_ids.autogen.hpp | 44 +++++++++---------- utilities/erpt.py | 2 + 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp index 6bede3d6f..7aabf7299 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp @@ -195,8 +195,8 @@ HANDLER(PscTransitionStateInfo, 154 ) \ HANDLER(FsProxyErrorInfo3, 155 ) \ HANDLER(BluetoothErrorInfo, 156 ) \ - HANDLER(Category_Unknown157, 157 ) \ - HANDLER(Category_Unknown158, 158 ) \ + HANDLER(SystemConfigInfo, 157 ) \ + HANDLER(ClockContextInfo, 158 ) \ HANDLER(TestNx, 1000) \ HANDLER(NANDTypeInfo, 1001) \ HANDLER(NANDExtendedCsd, 1002) \ @@ -241,9 +241,9 @@ HANDLER(WirelessAPMacAddress, 35, WirelessAPMacAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(GlobalIPAddress, 36, GlobalIPAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(EnableWirelessInterfaceFlag, 37, EnableWirelessInterfaceInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableWifiFlag, 38, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableBluetoothFlag, 39, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ - HANDLER(EnableNFCFlag, 40, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableWifiFlag, 38, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableBluetoothFlag, 39, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(EnableNFCFlag, 40, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(NintendoZoneSSIDListVersion, 41, NintendoZoneSSIDListVersionInfo, FieldType_String, FieldFlag_None ) \ HANDLER(LANAdapterMacAddress, 42, LANAdapterMacAddressInfo, FieldType_String, FieldFlag_None ) \ HANDLER(ApplicationID, 43, ApplicationInfo, FieldType_String, FieldFlag_None ) \ @@ -261,9 +261,9 @@ HANDLER(ApplicationRunningFlag, 55, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(DataCorruptionDetectedFlag, 56, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(ProductModel, 57, ProductModelInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(CurrentLanguage, 58, Category_Unknown157, FieldType_String, FieldFlag_None ) \ - HANDLER(UseNetworkTimeProtocolFlag, 59, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ - HANDLER(TimeZone, 60, Category_Unknown157, FieldType_String, FieldFlag_None ) \ + HANDLER(CurrentLanguage, 58, SystemConfigInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(UseNetworkTimeProtocolFlag, 59, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(TimeZone, 60, SystemConfigInfo, FieldType_String, FieldFlag_None ) \ HANDLER(ControllerFirmware, 61, ControllerFirmwareInfo, FieldType_String, FieldFlag_None ) \ HANDLER(VideoOutputSetting, 62, VideoOutputInfo, FieldType_String, FieldFlag_None ) \ HANDLER(NANDFreeSpace, 63, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \ @@ -274,23 +274,23 @@ HANDLER(HdmiAudioOutputMode, 68, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ HANDLER(SpeakerAudioOutputMode, 69, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ HANDLER(HeadphoneAudioOutputMode, 70, AudioFormatInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(MuteOnHeadsetUnpluggedFlag, 71, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(MuteOnHeadsetUnpluggedFlag, 71, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(NumUserRegistered, 72, NumUserRegisteredInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(StorageAutoOrganizeFlag, 73, DataDeletionInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(ControllerVibrationVolume, 74, Category_Unknown157, FieldType_String, FieldFlag_None ) \ - HANDLER(LockScreenFlag, 75, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(ControllerVibrationVolume, 74, SystemConfigInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(LockScreenFlag, 75, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(InternalBatteryLotNumber, 76, InternalBatteryLotNumberInfo, FieldType_String, FieldFlag_None ) \ HANDLER(LeftControllerSerialNumber, 77, LeftControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \ HANDLER(RightControllerSerialNumber, 78, RightControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \ - HANDLER(NotifyInGameDownloadCompletionFlag, 79, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ - HANDLER(NotificationSoundFlag, 80, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(NotifyInGameDownloadCompletionFlag, 79, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ + HANDLER(NotificationSoundFlag, 80, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(TVResolutionSetting, 81, TVInfo, FieldType_String, FieldFlag_None ) \ HANDLER(RGBRangeSetting, 82, TVInfo, FieldType_String, FieldFlag_None ) \ HANDLER(ReduceScreenBurnFlag, 83, TVInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(TVAllowsCecFlag, 84, TVInfo, FieldType_Bool, FieldFlag_None ) \ - HANDLER(HandheldModeTimeToScreenSleep, 85, Category_Unknown157, FieldType_String, FieldFlag_None ) \ - HANDLER(ConsoleModeTimeToScreenSleep, 86, Category_Unknown157, FieldType_String, FieldFlag_None ) \ - HANDLER(StopAutoSleepDuringContentPlayFlag, 87, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(HandheldModeTimeToScreenSleep, 85, SystemConfigInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(ConsoleModeTimeToScreenSleep, 86, SystemConfigInfo, FieldType_String, FieldFlag_None ) \ + HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(LastConnectionTestDownloadSpeed, 88, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \ HANDLER(LastConnectionTestUploadSpeed, 89, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \ HANDLER(DEPRECATED_ServerFQDN, 90, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \ @@ -613,7 +613,7 @@ HANDLER(ElapsedTimeSincePowerOn, 407, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(ElapsedTimeSinceLastAwake, 408, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(OccurrenceTick, 409, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(RetailInteractiveDisplayFlag, 410, Category_Unknown157, FieldType_Bool, FieldFlag_None ) \ + HANDLER(RetailInteractiveDisplayFlag, 410, SystemConfigInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(FatFsError, 411, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FatFsExtraError, 412, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(FatFsErrorDrive, 413, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \ @@ -629,7 +629,7 @@ HANDLER(Is720P60Hz, 423, MonitorCapability, FieldType_Bool, FieldFlag_None ) \ HANDLER(PcmChannelMax, 424, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(CrashReportHash, 425, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \ - HANDLER(ErrorReportSharePermission, 426, Category_Unknown157, FieldType_NumericU8, FieldFlag_None ) \ + HANDLER(ErrorReportSharePermission, 426, SystemConfigInfo, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(VideoCodecTypeEnum, 427, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(VideoBitRate, 428, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ HANDLER(VideoFrameRate, 429, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \ @@ -675,10 +675,10 @@ HANDLER(FsPatrolReadAllocateBufferFailureCount, 469, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(SteadyClockInternalOffset, 470, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(SteadyClockCurrentTimePointValue, 471, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(UserClockContextOffset, 472, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(UserClockContextTimeStampValue, 473, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(NetworkClockContextOffset, 474, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ - HANDLER(NetworkClockContextTimeStampValue, 475, Category_Unknown158, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(UserClockContextOffset, 472, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(UserClockContextTimeStampValue, 473, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(NetworkClockContextOffset, 474, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ + HANDLER(NetworkClockContextTimeStampValue, 475, ClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \ HANDLER(SystemAbortFlag, 476, ErrorInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(ApplicationAbortFlag, 477, ErrorInfo, FieldType_Bool, FieldFlag_None ) \ HANDLER(NifmErrorCode, 478, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \ diff --git a/utilities/erpt.py b/utilities/erpt.py index 7f23d7fb4..1c0e719f4 100644 --- a/utilities/erpt.py +++ b/utilities/erpt.py @@ -253,6 +253,8 @@ CATEGORIES = { 154 : 'PscTransitionStateInfo', 155 : 'FsProxyErrorInfo3', 156 : 'BluetoothErrorInfo', + 157 : 'SystemConfigInfo', + 158 : 'ClockContextInfo', 1000 : 'TestNx', 1001 : 'NANDTypeInfo', 1002 : 'NANDExtendedCsd', From 819da013ed7735e4d35c8fb2f29c995e76575117 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sat, 12 Sep 2026 21:23:53 +0100 Subject: [PATCH 11/52] erpt: implement new command changes for 23.0.0 --- .../include/stratosphere/erpt/erpt_types.hpp | 9 ++++ .../erpt/sf/erpt_sf_i_context.hpp | 5 +- .../source/erpt/srv/erpt_srv_context_impl.cpp | 50 ++++++++++++------- .../source/erpt/srv/erpt_srv_context_impl.hpp | 3 +- .../source/erpt/srv/erpt_srv_journal.hpp | 2 +- .../srv/erpt_srv_journal_for_attachments.cpp | 9 ++-- 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp b/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp index c3b92f62e..c07aec05e 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp @@ -272,5 +272,14 @@ namespace ams::erpt { char product_model[16]; const char *region; }; + + struct SubmitAttachmentOptionFlag { + using Lz4Compression = util::BitFlagSet::Flag<0>; + using Unknown0x10000 = util::BitFlagSet::Flag<16>; /* TODO: Figure out what this is. Always forced to 1. */ + }; + + using SubmitAttachmentOptionFlagSet = util::BitFlagSet; + static_assert(util::is_pod::value); + static_assert(sizeof(SubmitAttachmentOptionFlagSet) == sizeof(u32)); } diff --git a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp index d1244bb46..2fece2bc9 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_context.hpp @@ -34,14 +34,15 @@ AMS_SF_METHOD_INFO(C, H, 7, Result, RegisterRunningApplicationInfo, (ncm::ApplicationId app_id, ncm::ProgramId program_id), (app_id, program_id), hos::Version_21_0_0) \ AMS_SF_METHOD_INFO(C, H, 8, Result, ClearApplicationLaunchTime, (), (), hos::Version_6_0_0, hos::Version_20_5_0) \ AMS_SF_METHOD_INFO(C, H, 8, Result, UnregisterRunningApplicationInfo, (), (), hos::Version_21_0_0) \ - AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachment, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_8_0_0) \ + AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachmentDeprecated, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_8_0_0, hos::Version_22_5_0) \ AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer), hos::Version_8_0_0, hos::Version_10_2_0) \ AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated2, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer, result), hos::Version_11_0_0, hos::Version_16_1_0) \ AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachments, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags), (report_type, ctx_buffer, str_buffer, attachment_ids_buffer, result, flags), hos::Version_17_0_0) \ AMS_SF_METHOD_INFO(C, H, 11, Result, CreateReportV1, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, Result result), (report_type, ctx_buffer, str_buffer, meta_buffer, result), hos::Version_11_0_0) \ AMS_SF_METHOD_INFO(C, H, 12, Result, CreateReport, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, Result result, erpt::CreateReportOptionFlagSet flags), (report_type, ctx_buffer, str_buffer, meta_buffer, result, flags), hos::Version_17_0_0) \ - AMS_SF_METHOD_INFO(C, H, 13, Result, SubmitAttachmentWithLz4Compression, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_20_0_0) \ + AMS_SF_METHOD_INFO(C, H, 13, Result, SubmitAttachmentWithLz4Compression, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), (out, attachment_name, attachment_data), hos::Version_20_0_0, hos::Version_22_5_0) \ AMS_SF_METHOD_INFO(C, H, 14, Result, CreateReportWithSpecifiedReprotId, (erpt::ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags, const erpt::ReportId &report_id), (report_type, ctx_buffer, str_buffer, meta_buffer, attachment_ids_buffer, result, flags, report_id), hos::Version_20_0_0) \ + AMS_SF_METHOD_INFO(C, H, 15, Result, SubmitAttachment, (ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, erpt::SubmitAttachmentOptionFlagSet flags), (out, attachment_name, attachment_data, flags), hos::Version_23_0_0) \ AMS_SF_METHOD_INFO(C, H, 20, Result, RegisterRunningApplet, (ncm::ProgramId program_id), (program_id), hos::Version_12_0_0) \ AMS_SF_METHOD_INFO(C, H, 21, Result, UnregisterRunningApplet, (ncm::ProgramId program_id), (program_id), hos::Version_12_0_0) \ AMS_SF_METHOD_INFO(C, H, 22, Result, UpdateAppletSuspendedDuration, (ncm::ProgramId program_id, TimeSpanType duration), (program_id, duration), hos::Version_12_0_0) \ diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp index 125501821..3f57c4c4e 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp @@ -73,9 +73,30 @@ namespace ams::erpt::srv { /* We succeeded. */ R_SUCCEED(); } + + Result SubmitAttachmentImpl(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, bool lz4_compression, bool unk) { + const char *name = reinterpret_cast(attachment_name.GetPointer()); + const u8 *data = reinterpret_cast(attachment_data.GetPointer()); + const u32 name_size = static_cast(attachment_name.GetSize()); + const u32 data_size = static_cast(attachment_data.GetSize()); + + R_UNLESS(data != nullptr, erpt::ResultInvalidArgument()); + R_UNLESS(data_size <= AttachmentSizeMax, erpt::ResultInvalidArgument()); + R_UNLESS(name != nullptr, erpt::ResultInvalidArgument()); + R_UNLESS(name_size <= AttachmentNameSizeMax, erpt::ResultInvalidArgument()); + + char name_safe[AttachmentNameSizeMax]; + util::Strlcpy(name_safe, name, sizeof(name_safe)); + + /* NOTE: This is tested, but goes unused and is never passed to JournalForAttachments. */ + (void)unk; + + R_RETURN(JournalForAttachments::SubmitAttachment(out.GetPointer(), name_safe, data, data_size, lz4_compression)); + } + } - + Result ContextImpl::SubmitContext(const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer) { const ContextEntry *ctx = reinterpret_cast( ctx_buffer.GetPointer()); const u8 *data = reinterpret_cast(data_buffer.GetPointer()); @@ -213,27 +234,14 @@ namespace ams::erpt::srv { R_SUCCEED(); } - Result ContextImpl::SubmitAttachment(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) { - const char *name = reinterpret_cast(attachment_name.GetPointer()); - const u8 *data = reinterpret_cast(attachment_data.GetPointer()); - - const u32 name_size = static_cast(attachment_name.GetSize()); - const u32 data_size = static_cast(attachment_data.GetSize()); - - R_UNLESS(data != nullptr, erpt::ResultInvalidArgument()); - R_UNLESS(data_size <= AttachmentSizeMax, erpt::ResultInvalidArgument()); - R_UNLESS(name != nullptr, erpt::ResultInvalidArgument()); - R_UNLESS(name_size <= AttachmentNameSizeMax, erpt::ResultInvalidArgument()); - - char name_safe[AttachmentNameSizeMax]; - util::Strlcpy(name_safe, name, sizeof(name_safe)); - - R_RETURN(JournalForAttachments::SubmitAttachment(out.GetPointer(), name_safe, data, data_size)); + Result ContextImpl::SubmitAttachmentDeprecated(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) { + R_RETURN(SubmitAttachmentImpl(out, attachment_name, attachment_data, false, false)); } Result ContextImpl::SubmitAttachmentWithLz4Compression(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) { - /* TODO: Implement LZ4 compression on attachments. */ - R_RETURN(this->SubmitAttachment(out, attachment_name, attachment_data)); + /* NOTE: This should actually call JournalForAttachments::SubmitAttachmentWithLz4Compression. */ + /* We consolidate the logic in the new SubmitAttachmentImpl for simplicity (that's what ends up happening in JournalForAttachments anyway). */ + R_RETURN(SubmitAttachmentImpl(out, attachment_name, attachment_data, true, false)); } Result ContextImpl::CreateReportWithAttachments(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags) { @@ -285,6 +293,10 @@ namespace ams::erpt::srv { R_SUCCEED(); } + + Result ContextImpl::SubmitAttachment(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, erpt::SubmitAttachmentOptionFlagSet flags) { + R_RETURN(SubmitAttachmentImpl(out, attachment_name, attachment_data, flags.Test(), flags.Test())); + } Result ContextImpl::RegisterRunningApplet(ncm::ProgramId program_id) { R_RETURN(Reporter::RegisterRunningApplet(program_id)); diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.hpp index 506a5c244..af5915389 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.hpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.hpp @@ -33,7 +33,7 @@ namespace ams::erpt::srv { Result RegisterRunningApplicationInfo(ncm::ApplicationId app_id, ncm::ProgramId program_id); Result ClearApplicationLaunchTime(); Result UnregisterRunningApplicationInfo(); - Result SubmitAttachment(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data); + Result SubmitAttachmentDeprecated(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data); Result CreateReportWithAttachmentsDeprecated(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &attachment_ids_buffer); Result CreateReportWithAttachmentsDeprecated2(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result); Result CreateReportWithAttachments(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result, erpt::CreateReportOptionFlagSet flags); @@ -41,6 +41,7 @@ namespace ams::erpt::srv { Result CreateReport(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &meta_buffer, Result result, erpt::CreateReportOptionFlagSet flags); Result SubmitAttachmentWithLz4Compression(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data); Result CreateReportWithSpecifiedReprotId(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &data_buffer, const ams::sf::InBuffer &meta_buffer, const ams::sf::InBuffer &attachment_data, Result result, erpt::CreateReportOptionFlagSet flags, const ReportId &report_id); + Result SubmitAttachment(ams::sf::Out out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, erpt::SubmitAttachmentOptionFlagSet flags); Result RegisterRunningApplet(ncm::ProgramId program_id); Result UnregisterRunningApplet(ncm::ProgramId program_id); Result UpdateAppletSuspendedDuration(ncm::ProgramId program_id, TimeSpanType duration); diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal.hpp index 16011e75a..ceaff7f4b 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal.hpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal.hpp @@ -90,7 +90,7 @@ namespace ams::erpt::srv { static Result SetOwner(AttachmentId attachment_id, ReportId report_id); static Result StoreRecord(JournalRecord *record); - static Result SubmitAttachment(AttachmentId *out, char *name, const u8 *data, u32 data_size); + static Result SubmitAttachment(AttachmentId *out, char *name, const u8 *data, u32 data_size, bool lz4_compression); }; class Journal { diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp index d2a9bedfb..36cfe98c6 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp @@ -185,8 +185,11 @@ namespace ams::erpt::srv { R_SUCCEED(); } - - Result JournalForAttachments::SubmitAttachment(AttachmentId *out, char *name, const u8 *data, u32 data_size) { + + Result JournalForAttachments::SubmitAttachment(AttachmentId *out, char *name, const u8 *data, u32 data_size, bool lz4_compression) { + /* TODO: Implement LZ4 compression on attachments. */ + (void)lz4_compression; + R_UNLESS(data_size > 0, erpt::ResultInvalidArgument()); R_UNLESS(data_size < AttachmentSizeMax, erpt::ResultInvalidArgument()); @@ -229,5 +232,5 @@ namespace ams::erpt::srv { R_SUCCEED(); } - + } From e6a3d71692d54a4d3aa66092672420321fbde510 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 14 Sep 2026 23:04:57 +0100 Subject: [PATCH 12/52] exo/spl: new ConfigItem in 23.0.0 is wild --- exosphere/program/source/smc/secmon_smc_info.cpp | 3 +++ exosphere/program/source/smc/secmon_smc_info.hpp | 1 + .../include/exosphere/pkg1/pkg1_boot_config.hpp | 14 +++++++++----- .../include/stratosphere/spl/spl_types.hpp | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/exosphere/program/source/smc/secmon_smc_info.cpp b/exosphere/program/source/smc/secmon_smc_info.cpp index 88cdeefe0..8c0710b04 100644 --- a/exosphere/program/source/smc/secmon_smc_info.cpp +++ b/exosphere/program/source/smc/secmon_smc_info.cpp @@ -271,6 +271,9 @@ namespace ams::secmon::smc { std::memcpy(std::addressof(args.r[1]), std::addressof(tmp_hash), sizeof(tmp_hash)); } break; + case ConfigItem::Unknown18: + args.r[1] = GetBootConfig().data.GetUnknown70(); + break; case ConfigItem::ExosphereApiVersion: /* Get information about the current exosphere version. */ if (kern || g_set_true_target_firmware) { diff --git a/exosphere/program/source/smc/secmon_smc_info.hpp b/exosphere/program/source/smc/secmon_smc_info.hpp index 605bbf333..2f81d066d 100644 --- a/exosphere/program/source/smc/secmon_smc_info.hpp +++ b/exosphere/program/source/smc/secmon_smc_info.hpp @@ -38,6 +38,7 @@ namespace ams::secmon::smc { RegulatorType = 15, DeviceUniqueKeyGeneration = 16, Package2Hash = 17, + Unknown18 = 18, /* Extension config items for exosphere. */ ExosphereApiVersion = 65000, diff --git a/libraries/libexosphere/include/exosphere/pkg1/pkg1_boot_config.hpp b/libraries/libexosphere/include/exosphere/pkg1/pkg1_boot_config.hpp index b61fb7e07..f7a67a1ec 100644 --- a/libraries/libexosphere/include/exosphere/pkg1/pkg1_boot_config.hpp +++ b/libraries/libexosphere/include/exosphere/pkg1/pkg1_boot_config.hpp @@ -61,14 +61,15 @@ namespace ams::pkg1 { } struct BootConfigData { - u32 version; - u32 reserved_04; + u64 version; u32 reserved_08; u32 reserved_0C; u8 flags1[0x10]; u8 flags0[0x10]; u64 initial_tsc_value; - u8 padding_38[0x200 - 0x38]; + u8 padding_38[0x38]; + u64 unknown_70; + u8 padding_78[0x200 - 0x78]; constexpr bool IsDevelopmentFunctionEnabled() const { return (this->flags1[0] & (1 << 1)) != 0; @@ -97,13 +98,16 @@ namespace ams::pkg1 { constexpr u64 GetInitialTscValue() const { return this->IsInitialTscValueValid() ? this->initial_tsc_value : 0; } + + constexpr u64 GetUnknown70() const { + return this->unknown_70; + } }; static_assert(util::is_pod::value); static_assert(sizeof(BootConfigData) == 0x200); struct BootConfigSignedData { - u32 version; - u32 reserved_04; + u64 version; u8 flags; u8 reserved_09[0x10 - 9]; u8 ecid[0x10]; diff --git a/libraries/libstratosphere/include/stratosphere/spl/spl_types.hpp b/libraries/libstratosphere/include/stratosphere/spl/spl_types.hpp index 11c80ad48..65c25fe58 100644 --- a/libraries/libstratosphere/include/stratosphere/spl/spl_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/spl/spl_types.hpp @@ -230,6 +230,7 @@ namespace ams::spl { RegulatorType = 15, DeviceUniqueKeyGeneration = 16, Package2Hash = 17, + Unknown18 = 18, /* Extension config items for exosphere. */ ExosphereApiVersion = 65000, From 0f15010ba542cbaf78934fd50e30ef8399ce48a9 Mon Sep 17 00:00:00 2001 From: Alula Date: Sun, 13 Sep 2026 11:41:53 +0200 Subject: [PATCH 13/52] kern/loader: make aware of new address space and shadow stack region --- .../arch/arm64/kern_cpu_system_registers.hpp | 1 + .../arch/arm64/kern_k_page_table.hpp | 12 +++- .../arch/arm64/kern_k_process_page_table.hpp | 26 +++---- .../mesosphere/init/kern_init_slab_setup.hpp | 19 ++++++ .../mesosphere/kern_k_address_space_info.hpp | 2 +- .../mesosphere/kern_k_memory_block.hpp | 20 +++--- .../mesosphere/kern_k_page_table_base.hpp | 55 +++++++++------ .../include/mesosphere/kern_k_process.hpp | 1 + .../source/arch/arm64/kern_k_page_table.cpp | 4 +- .../source/init/kern_init_slab_setup.cpp | 19 ------ .../source/kern_k_address_space_info.cpp | 12 +++- .../source/kern_k_initial_process_reader.cpp | 2 +- .../source/kern_k_page_table_base.cpp | 67 ++++++++++++++----- .../source/svc/kern_svc_info.cpp | 12 ++++ .../source/svc/kern_svc_process.cpp | 8 ++- .../include/stratosphere/cfg/cfg_types.hpp | 1 + .../include/stratosphere/ldr/ldr_types.hpp | 8 ++- .../cfg/cfg_override.board.nintendo_nx.inc | 2 + .../impl/osdbg_thread_info.os.horizon.hpp | 4 +- .../include/vapours/svc/svc_memory_map.hpp | 16 +++++ .../include/vapours/svc/svc_types_common.hpp | 19 +++++- .../include/vapours/svc/svc_version.hpp | 2 +- .../source/arch/arm64/init/kern_init_core.cpp | 17 ++++- stratosphere/loader/source/ldr_meta.cpp | 1 + .../loader/source/ldr_process_creation.cpp | 7 ++ 25 files changed, 238 insertions(+), 99 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp index 61e066fee..1b6d93201 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp @@ -81,6 +81,7 @@ namespace ams::kern::arch::arm64::cpu { MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(SpEl0, sp_el0) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Dfr0El1, id_aa64dfr0_el1) + MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Mmfr0El1, id_aa64mmfr0_el1) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmcrEl0, pmcr_el0) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmUserEnrEl0, pmuserenr_el0) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index 2ab8527c9..356dc4217 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -94,10 +94,10 @@ namespace ams::kern::arch::arm64 { return KPageTable::GetBlockSize(static_cast(KPageTable::GetBlockType(alignment) + 1)); } public: - /* TODO: How should this size be determined. Does the KProcess slab count need to go in a header as a define? */ - static constexpr size_t NumTtbr0Entries = 81; + static constexpr size_t NumPTEntries = ::ams::kern::init::SlabCountKProcess + 1; /* +1 for kernel. */ private: - static constinit inline const volatile u64 s_ttbr0_entries[NumTtbr0Entries] = {}; + static constinit inline const volatile u64 s_ttbr0_entries[NumPTEntries] = {}; + static constinit inline const volatile u64 s_tcr_el1_entries[NumPTEntries] = {}; private: KPageTableManager *m_manager; u8 m_asid; @@ -188,6 +188,12 @@ namespace ams::kern::arch::arm64 { return s_ttbr0_entries[0]; } + static const volatile u64 &GetTcrEL1Entry(size_t index) { return s_tcr_el1_entries[index]; } + + static ALWAYS_INLINE u64 GetKernelTcrEL1() { + return s_tcr_el1_entries[0]; + } + static ALWAYS_INLINE void ActivateKernel() { /* Activate, using asid 0 and process id = 0xFFFFFFFF */ cpu::SwitchProcess(GetKernelTtbr0(), 0xFFFFFFFF); diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index e18a6fbc8..63a357e0e 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -302,19 +302,21 @@ namespace ams::kern::arch::arm64 { bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); } bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { return m_page_table.CanContain(addr, size, state); } - KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } - KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } - KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); } - KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); } - KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); } - KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); } + KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } + KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); } + KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } + KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); } + KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); } + KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); } + KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); } - size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } - size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); } - size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); } - size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); } - size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); } - size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); } + size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } + size_t GetShadowStackRegionSize() const { return m_page_table.GetShadowStackRegionSize(); } + size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); } + size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); } + size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); } + size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); } + size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); } size_t GetAliasRegionExtraSize() const { return m_page_table.GetAliasRegionExtraSize(); } diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp index 209b8d732..32bba1e5a 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp @@ -18,6 +18,25 @@ #include namespace ams::kern::init { + /* Constexpr counts. */ + constexpr size_t SlabCountKProcess = 80; + constexpr size_t SlabCountKThread = 800; + constexpr size_t SlabCountKEvent = 900; + constexpr size_t SlabCountKInterruptEvent = 100; + constexpr size_t SlabCountKPort = 384; + constexpr size_t SlabCountKSharedMemory = 80; + constexpr size_t SlabCountKTransferMemory = 200; + constexpr size_t SlabCountKCodeMemory = 10; + constexpr size_t SlabCountKDeviceAddressSpace = 300; + constexpr size_t SlabCountKSession = 1133; + constexpr size_t SlabCountKLightSession = 100; + constexpr size_t SlabCountKObjectName = 7; + constexpr size_t SlabCountKResourceLimit = 5; + constexpr size_t SlabCountKDebug = cpu::NumCores; + constexpr size_t SlabCountKIoPool = 1; + constexpr size_t SlabCountKIoRegion = 6; + constexpr size_t SlabcountKSessionRequestMappings = 40; + struct KSlabResourceCounts { size_t num_KProcess; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp index 775c0054c..00d942a66 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp @@ -24,7 +24,7 @@ namespace ams::kern { enum Type { Type_MapSmall = 0, Type_MapLarge = 1, - Type_Map39Bit = 2, + Type_MapHuge = 2, Type_Heap = 3, Type_Stack = 4, Type_Alias = 5, diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index 57876fbcb..9e9e9c7a4 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -211,15 +211,15 @@ namespace ams::kern { uintptr_t m_address; size_t m_size; KMemoryState m_state; - u16 m_device_disable_merge_left_count; - u16 m_device_disable_merge_right_count; - u16 m_ipc_lock_count; - u16 m_device_use_count; - u16 m_ipc_disable_merge_count; KMemoryPermission m_permission; KMemoryAttribute m_attribute; KMemoryPermission m_original_permission; + u16 m_ipc_lock_count; + u16 m_device_use_count; KMemoryBlockDisableMergeAttribute m_disable_merge_attribute; + u16 m_ipc_disable_merge_count; + u16 m_device_disable_merge_left_count; + u16 m_device_disable_merge_right_count; constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const { return { @@ -365,15 +365,15 @@ namespace ams::kern { .m_address = GetInteger(this->GetAddress()), .m_size = this->GetSize(), .m_state = m_memory_state, - .m_device_disable_merge_left_count = m_device_disable_merge_left_count, - .m_device_disable_merge_right_count = m_device_disable_merge_right_count, - .m_ipc_lock_count = m_ipc_lock_count, - .m_device_use_count = m_device_use_count, - .m_ipc_disable_merge_count = m_ipc_disable_merge_count, .m_permission = m_permission, .m_attribute = m_attribute, .m_original_permission = m_original_permission, + .m_ipc_lock_count = m_ipc_lock_count, + .m_device_use_count = m_device_use_count, .m_disable_merge_attribute = m_disable_merge_attribute, + .m_ipc_disable_merge_count = m_ipc_disable_merge_count, + .m_device_disable_merge_left_count = m_device_disable_merge_left_count, + .m_device_disable_merge_right_count = m_device_disable_merge_right_count, }; } public: diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 25c149b7f..759fd1758 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -90,10 +90,11 @@ namespace ams::kern { }; enum RegionType { - RegionType_KernelMap = 0, - RegionType_Stack = 1, - RegionType_Alias = 2, - RegionType_Heap = 3, + RegionType_KernelMap = 0, + RegionType_Stack = 1, + RegionType_Alias = 2, + RegionType_Heap = 3, + RegionType_ShadowStack = 4, RegionType_Count, }; @@ -196,7 +197,6 @@ namespace ams::kern { KPageTableImpl m_impl; KMemoryBlockManager m_memory_block_manager; u32 m_allocate_option; - u32 m_address_space_width; bool m_is_kernel; bool m_enable_aslr; bool m_enable_device_address_space_merge; @@ -212,23 +212,24 @@ namespace ams::kern { public: constexpr explicit KPageTableBase(util::ConstantInitializeTag) : m_address_space_start(Null), m_address_space_end(Null), - m_region_starts{Null, Null, Null, Null}, - m_region_ends{Null, Null, Null, Null}, + m_region_starts{Null, Null, Null, Null, Null}, + m_region_ends{Null, Null, Null, Null, Null}, m_current_heap_end(Null), m_alias_code_region_start(Null), m_alias_code_region_end(Null), m_code_region_start(Null), m_code_region_end(Null), - m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), m_alias_region_extra_size(), - m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize), - m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(), - m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(), - m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value() + m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), + m_mapped_ipc_server_memory(), m_alias_region_extra_size(), m_general_lock(), m_map_physical_memory_lock(), + m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize), + m_allocate_option(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(), + m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), + m_cached_physical_heap_region(), m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value() { /* ... */ } explicit KPageTableBase() { /* ... */ } - NOINLINE void InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end); - NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); + NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); void Finalize(); @@ -247,6 +248,14 @@ namespace ams::kern { return this->Contains(addr, size) && m_region_starts[RegionType_Alias] <= addr && addr + size - 1 <= m_region_ends[RegionType_Alias] - 1; } + constexpr bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && m_region_starts[RegionType_ShadowStack] <= addr && addr + size - 1 <= m_region_ends[RegionType_ShadowStack] - 1; + } + + constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && !this->IsInShadowStackRegion(addr, size); + } + bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const { /* Even though Unsafe physical memory is KMemoryState_Normal, it must be mapped inside the alias code region. */ return this->CanContain(addr, size, ams::svc::MemoryState_AliasCode); @@ -490,19 +499,21 @@ namespace ams::kern { public: KProcessAddress GetAddressSpaceStart() const { return m_address_space_start; } - KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; } - KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; } - KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; } - KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; } + KProcessAddress GetShadowStackRegionStart() const { return m_region_starts[RegionType_ShadowStack]; } + KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; } + KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; } + KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; } + KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; } KProcessAddress GetAliasCodeRegionStart() const { return m_alias_code_region_start; } size_t GetAddressSpaceSize() const { return m_address_space_end - m_address_space_start; } - size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; } - size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; } - size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; } - size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; } + size_t GetShadowStackRegionSize() const { return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; } + size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; } + size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; } + size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; } + size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; } size_t GetAliasCodeRegionSize() const { return m_alias_code_region_end - m_alias_code_region_start; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 0b0622869..d20e49c7c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -215,6 +215,7 @@ namespace ams::kern { } u32 GetAllocateOption() const { return m_page_table.GetAllocateOption(); } + size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } ThreadList &GetThreadList() { return m_thread_list; } const ThreadList &GetThreadList() const { return m_thread_list; } diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index 6992281dd..b22874027 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -125,7 +125,7 @@ namespace ams::kern::arch::arm64 { m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer(); /* Initialize the base page table. */ - KPageTableBase::InitializeForKernel(true, table, start, end); + KPageTableBase::InitializeForKernel(table, start, end); } Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) { @@ -144,7 +144,7 @@ namespace ams::kern::arch::arm64 { const size_t as_width = GetAddressSpaceWidth(flags); const KProcessAddress as_start = 0; const KProcessAddress as_end = (1ul << as_width); - R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, pool, GetVoidPointer(ttbr0_virt), as_start, as_end, code_address, code_size, system_resource, resource_limit)); + R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, GetVoidPointer(ttbr0_virt), as_start, as_end, pool, code_address, code_size, system_resource, resource_limit)); /* Note that we've updated the table (since we created it). */ this->NoteUpdated(); diff --git a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp index b82e78f84..3336c94a9 100644 --- a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp +++ b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp @@ -60,25 +60,6 @@ namespace ams::kern::init { #undef DEFINE_SLAB_TYPE_ENUM_MEMBER - /* Constexpr counts. */ - constexpr size_t SlabCountKProcess = 80; - constexpr size_t SlabCountKThread = 800; - constexpr size_t SlabCountKEvent = 900; - constexpr size_t SlabCountKInterruptEvent = 100; - constexpr size_t SlabCountKPort = 384; - constexpr size_t SlabCountKSharedMemory = 80; - constexpr size_t SlabCountKTransferMemory = 200; - constexpr size_t SlabCountKCodeMemory = 10; - constexpr size_t SlabCountKDeviceAddressSpace = 300; - constexpr size_t SlabCountKSession = 1133; - constexpr size_t SlabCountKLightSession = 100; - constexpr size_t SlabCountKObjectName = 7; - constexpr size_t SlabCountKResourceLimit = 5; - constexpr size_t SlabCountKDebug = cpu::NumCores; - constexpr size_t SlabCountKIoPool = 1; - constexpr size_t SlabCountKIoRegion = 6; - constexpr size_t SlabcountKSessionRequestMappings = 40; - constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread; namespace test { diff --git a/libraries/libmesosphere/source/kern_k_address_space_info.cpp b/libraries/libmesosphere/source/kern_k_address_space_info.cpp index 3aa24c5de..022dc9b54 100644 --- a/libraries/libmesosphere/source/kern_k_address_space_info.cpp +++ b/libraries/libmesosphere/source/kern_k_address_space_info.cpp @@ -30,15 +30,20 @@ namespace ams::kern { { 36, ams::svc::AddressLargeMap36Start, ams::svc::AddressLargeMap36Size, KAddressSpaceInfo::Type_MapLarge, }, { 36, Invalid, ams::svc::AddressMemoryRegionHeap36Size, KAddressSpaceInfo::Type_Heap, }, { 36, Invalid, ams::svc::AddressMemoryRegionAlias36Size, KAddressSpaceInfo::Type_Alias, }, - { 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_Map39Bit, }, + { 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_MapHuge, }, { 39, Invalid, ams::svc::AddressMemoryRegionSmall39Size, KAddressSpaceInfo::Type_MapSmall, }, { 39, Invalid, ams::svc::AddressMemoryRegionHeap39Size, KAddressSpaceInfo::Type_Heap, }, { 39, Invalid, ams::svc::AddressMemoryRegionAlias39Size, KAddressSpaceInfo::Type_Alias, }, { 39, Invalid, ams::svc::AddressMemoryRegionStack39Size, KAddressSpaceInfo::Type_Stack, }, + { 42, ams::svc::AddressMap42Start, ams::svc::AddressMap42Size, KAddressSpaceInfo::Type_MapHuge, }, + { 42, Invalid, ams::svc::AddressMemoryRegionSmall42Size, KAddressSpaceInfo::Type_MapSmall, }, + { 42, Invalid, 0, KAddressSpaceInfo::Type_Heap, }, + { 42, Invalid, ams::svc::AddressMemoryRegionAlias42Size, KAddressSpaceInfo::Type_Alias, }, + { 42, Invalid, ams::svc::AddressMemoryRegionStack42Size, KAddressSpaceInfo::Type_Stack, }, }; - constexpr u8 FlagsToAddressSpaceWidthTable[4] = { - 32, 36, 32, 39 + constexpr u8 FlagsToAddressSpaceWidthTable[5] = { + 32, 36, 32, 39, 42 }; constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) { @@ -54,6 +59,7 @@ namespace ams::kern { static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36); static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32); static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) == 42); KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) { for (auto &info : AddressSpaceInfos) { diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index 5d9164efb..61c04dd18 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -233,7 +233,7 @@ namespace ams::kern { /* a number of pages here. Even though this is presumably only used for debug assertions, this is */ /* almost certainly a bug. */ using ASType = KAddressSpaceInfo::Type; - const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; + const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_MapHuge : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(out->flags), as_type, out->code_num_pages); const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(out->flags), as_type); const uintptr_t map_end = map_start + map_size; diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 5d34dbe1f..98988dde6 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -88,14 +88,14 @@ namespace ams::kern { } } - void KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) { + void KPageTableBase::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) { /* Initialize our members. */ - m_address_space_width = (is_64_bit) ? BITSIZEOF(u64) : BITSIZEOF(u32); m_address_space_start = KProcessAddress(GetInteger(start)); m_address_space_end = KProcessAddress(GetInteger(end)); m_is_kernel = true; m_enable_aslr = true; m_enable_device_address_space_merge = false; + m_allowed_exec_device_mapping = false; for (auto i = 0; i < RegionType_Count; ++i) { m_region_starts[i] = 0; @@ -133,7 +133,7 @@ namespace ams::kern { MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager)); } - Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { + Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { /* Validate the region. */ MESOSPHERE_ABORT_UNLESS(start <= code_address); MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size); @@ -151,9 +151,9 @@ namespace ams::kern { m_alias_region_extra_size = 0; /* Set our width and heap/alias sizes. */ - m_address_space_width = GetAddressSpaceWidth(flags); - size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias); - size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); + size_t address_space_width = GetAddressSpaceWidth(flags); + size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias); + size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); /* Set code regions and determine remaining sizes. */ KProcessAddress process_code_start; @@ -162,12 +162,12 @@ namespace ams::kern { size_t kernel_map_region_size; KProcessAddress before_process_code_start, after_process_code_start; size_t before_process_code_size, after_process_code_size; - if (m_address_space_width == 39) { + if (address_space_width == 39 || address_space_width == 42) { stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack); kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall); - m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit); - m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit); + m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapHuge); + m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapHuge); m_alias_code_region_start = m_code_region_start; m_alias_code_region_end = m_code_region_end; @@ -182,7 +182,7 @@ namespace ams::kern { /* If we have a 39-bit address space and should, enable extra size to the alias region. */ if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) { /* Extra size is 1/8th of the address space. */ - m_alias_region_extra_size = (static_cast(1) << m_address_space_width) / 8; + m_alias_region_extra_size = (static_cast(1) << address_space_width) / 8; alias_region_size += m_alias_region_extra_size; } @@ -208,6 +208,9 @@ namespace ams::kern { after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge); } + m_region_starts[RegionType_ShadowStack] = Null; + m_region_ends[RegionType_ShadowStack] = Null; + /* Set other basic fields. */ m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; @@ -237,6 +240,9 @@ namespace ams::kern { region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, }; region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, }; + if (flags & ams::svc::CreateProcessFlag_EnableShadowStack) { + region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, }; + } /* Selection-sort the regions by size largest-to-smallest. */ for (size_t i = 0; i < num_regions - 1; ++i) { @@ -399,6 +405,18 @@ namespace ams::kern { break; } } + + /* Check for overlap with shadow stack. */ + for (size_t ss = 0; ss < num_regions; ++ss) { + if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { + if (shadow_stack_region.size != 0) { + const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; + const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; + MESOSPHERE_ABORT_UNLESS(kmap_last < shadow_stack_start || shadow_stack_last < kmap_start); + } + break; + } + } } } @@ -494,6 +512,25 @@ namespace ams::kern { MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start); } } + + /* Check that the ShadowStack region is valid. */ + for (size_t ss = 0; ss < num_regions; ++ss) { + if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { + /* If there's no shadow stack region, we have nothing to check. */ + if (shadow_stack_region.size == 0) { + break; + } + + /* Check that the shadow stack region is within our address space. */ + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_ShadowStack])); + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_ShadowStack])); + + /* Check for overlap with process code. */ + const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; + const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; + MESOSPHERE_ABORT_UNLESS(shadow_stack_last < process_code_start || process_code_last < shadow_stack_start); + } + } } /* Set heap and fill members. */ @@ -1997,15 +2034,15 @@ namespace ams::kern { .m_address = GetInteger(m_address_space_end), .m_size = 0 - GetInteger(m_address_space_end), .m_state = static_cast(ams::svc::MemoryState_Inaccessible), - .m_device_disable_merge_left_count = 0, - .m_device_disable_merge_right_count = 0, - .m_ipc_lock_count = 0, - .m_device_use_count = 0, - .m_ipc_disable_merge_count = 0, .m_permission = KMemoryPermission_None, .m_attribute = KMemoryAttribute_None, .m_original_permission = KMemoryPermission_None, + .m_ipc_lock_count = 0, + .m_device_use_count = 0, .m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None, + .m_ipc_disable_merge_count = 0, + .m_device_disable_merge_left_count = 0, + .m_device_disable_merge_right_count = 0, }; out_page_info->flags = 0; diff --git a/libraries/libmesosphere/source/svc/kern_svc_info.cpp b/libraries/libmesosphere/source/svc/kern_svc_info.cpp index ec41ef59a..8b51c7fba 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_info.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_info.cpp @@ -109,6 +109,15 @@ namespace ams::kern::svc { case ams::svc::InfoType_AliasRegionExtraSize: *out = process->GetPageTable().GetAliasRegionExtraSize(); break; + case ams::svc::InfoType_AddressSpaceSize: + *out = process->GetAddressSpaceSize(); + break; + case ams::svc::InfoType_ShadowStackRegionAddress: + *out = GetInteger(process->GetPageTable().GetShadowStackRegionStart()); + break; + case ams::svc::InfoType_ShadowStackRegionSize: + *out = process->GetPageTable().GetShadowStackRegionSize(); + break; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } @@ -138,6 +147,9 @@ namespace ams::kern::svc { case ams::svc::InfoType_IsApplication: case ams::svc::InfoType_FreeThreadCount: case ams::svc::InfoType_AliasRegionExtraSize: + case ams::svc::InfoType_AddressSpaceSize: + case ams::svc::InfoType_ShadowStackRegionAddress: + case ams::svc::InfoType_ShadowStackRegionSize: { /* These info types don't support non-zero subtypes. */ R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination()); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 6e516a51f..54f598d1e 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -100,6 +100,9 @@ namespace ams::kern::svc { /* Validate that the parameter flags are valid. */ R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue()); + /* The 64KB page size is not yet allowed. */ + R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) != ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage, svc::ResultInvalidCombination()); + /* Validate that 64-bit process is okay. */ const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0; if constexpr (sizeof(void *) < sizeof(u64)) { @@ -130,12 +133,13 @@ namespace ams::kern::svc { } break; case ams::svc::CreateProcessFlag_AddressSpace64Bit: + case ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage: { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit, code_size); - map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size); + map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge); map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); } diff --git a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp index dd898a96f..20976587c 100644 --- a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp @@ -35,6 +35,7 @@ namespace ams::cfg { OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit64KPage = (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, #endif }; diff --git a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp index aa33b4e15..c97711a53 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp @@ -235,11 +235,16 @@ namespace ams::ldr { MetaFlag_PreventCodeReads = (1 << 7), }; + enum MetaFlag2 { + MetaFlag2_EnableShadowStack = (1 << 0), + }; + enum AddressSpaceType { AddressSpaceType_32Bit = 0, AddressSpaceType_64BitDeprecated = 1, AddressSpaceType_32BitWithoutAlias = 2, AddressSpaceType_64Bit = 3, + AddressSpaceType_64Bit64KPage = 4, }; #if defined(ATMOSPHERE_OS_HORIZON) @@ -247,13 +252,14 @@ namespace ams::ldr { static_assert(AddressSpaceType_64BitDeprecated == (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift)); static_assert(AddressSpaceType_32BitWithoutAlias == (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift)); static_assert(AddressSpaceType_64Bit == (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift)); + static_assert(AddressSpaceType_64Bit64KPage == (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift)); #endif u32 magic; u32 signature_key_generation; u8 reserved_08[4]; u8 flags; - u8 reserved_0D; + u8 flags2; u8 main_thread_priority; u8 default_cpu_id; u8 reserved_10[4]; diff --git a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc index a91da9268..420f71198 100644 --- a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc +++ b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc @@ -153,6 +153,8 @@ namespace ams::cfg { impl::OverrideStatusFlag ParseOverrideAddressSpace(const char *value) { if (strcasecmp(value, "39_bit") == 0 || strcasecmp(value, "39") == 0) { return impl::OverrideStatusFlag_AddressSpace64Bit; + } else if (strcasecmp(value, "42_bit") == 0 || strcasecmp(value, "42") == 0) { + return impl::OverrideStatusFlag_AddressSpace64Bit64KPage; } else if (strcasecmp(value, "36_bit") == 0 || strcasecmp(value, "36") == 0) { return impl::OverrideStatusFlag_AddressSpace64BitDeprecated; } else if (strcasecmp(value, "32_bit") == 0 || strcasecmp(value, "32") == 0) { diff --git a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp index e43fec1e1..1bd74bfba 100644 --- a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp +++ b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp @@ -28,7 +28,9 @@ namespace ams::osdbg::impl { constexpr inline bool IsLp64(const ThreadInfo *info) { const auto as = info->_debug_info_create_process.flags & svc::CreateProcessFlag_AddressSpaceMask; - return as == svc::CreateProcessFlag_AddressSpace64Bit || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated; + return as == svc::CreateProcessFlag_AddressSpace64Bit + || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated + || as == svc::CreateProcessFlag_AddressSpace64Bit64KPage; } constexpr inline bool Is64BitArch(const ThreadInfo *info) { diff --git a/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp b/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp index 08bf1773b..55bb5ec36 100644 --- a/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp @@ -37,6 +37,13 @@ namespace ams::svc { constexpr inline size_t AddressMemoryRegion39Size = 512_GB; + constexpr inline size_t AddressMemoryRegionSmall42Size = 64_GB; + constexpr inline size_t AddressMemoryRegionAlias42Size = 512_GB; + constexpr inline size_t AddressMemoryRegionStack42Size = 2_GB; + + constexpr inline size_t AddressMemoryRegion42Size = 4096_GB; + + constexpr inline size_t AddressShadowStackRegionSize = 4_GB; #elif defined(ATMOSPHERE_ARCH_ARM) constexpr inline size_t AddressMemoryRegionSmall32Size = 512_MB; @@ -56,6 +63,12 @@ namespace ams::svc { constexpr inline size_t AddressMemoryRegion39Size = 0; + constexpr inline size_t AddressMemoryRegionSmall42Size = 0; + constexpr inline size_t AddressMemoryRegionAlias42Size = 0; + constexpr inline size_t AddressMemoryRegionStack42Size = 0; + + constexpr inline size_t AddressMemoryRegion42Size = 0; + #else #error "Unknown architecture for svc::AddressMemoryRegion*Size" @@ -97,4 +110,7 @@ namespace ams::svc { constexpr inline uintptr_t AddressMap39End = AddressMemoryRegion39Size; constexpr inline size_t AddressMap39Size = AddressMap39End - AddressMap39Start; + constexpr inline uintptr_t AddressMap42Start = 0 + AddressNullGuard64Size; + constexpr inline uintptr_t AddressMap42End = AddressMemoryRegion42Size; + constexpr inline size_t AddressMap42Size = AddressMap42End - AddressMap42Start; } diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 21ab685d0..20aa4ea90 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -191,8 +191,16 @@ namespace ams::svc { InfoType_IsSvcPermitted = 26, InfoType_IoRegionHint = 27, InfoType_AliasRegionExtraSize = 28, - /* ... */ + InfoType_RemoteRegionAddress = 29, + InfoType_RemoteRegionSize = 30, + InfoType_RemoteMemorySize = 31, + InfoType_RemoteMemoryUsageMax = 32, + InfoType_AllocateAlignment = 33, InfoType_TransferMemoryHint = 34, + /* ... */ + InfoType_AddressSpaceSize = 36, + InfoType_ShadowStackRegionAddress = 37, + InfoType_ShadowStackRegionSize = 38, InfoType_MesosphereMeta = 65000, InfoType_MesosphereCurrentProcess = 65001, @@ -408,11 +416,12 @@ namespace ams::svc { /* What kind of address space? */ CreateProcessFlag_AddressSpaceShift = 1, - CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), + CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), /* Should be 15 but Nintendo didn't make 64K isn't usable yet */ CreateProcessFlag_AddressSpace32Bit = (0 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace64BitDeprecated = (1 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace32BitWithoutAlias = (2 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace64Bit = (3 << CreateProcessFlag_AddressSpaceShift), + CreateProcessFlag_AddressSpace64Bit64KPage = (4 << CreateProcessFlag_AddressSpaceShift), /* Should JIT debug be done on crash? */ CreateProcessFlag_EnableDebug = (1 << 4), @@ -443,6 +452,9 @@ namespace ams::svc { /* 18.x EnableAliasRegionExtraSize. */ CreateProcessFlag_EnableAliasRegionExtraSize = (1 << 13), + /* 23.x EnableShadowStack. */ + CreateProcessFlag_EnableShadowStack = (1 << 17), + /* Mask of all flags. */ CreateProcessFlag_All = CreateProcessFlag_Is64Bit | CreateProcessFlag_AddressSpaceMask | @@ -452,7 +464,8 @@ namespace ams::svc { CreateProcessFlag_PoolPartitionMask | CreateProcessFlag_OptimizeMemoryAllocation | CreateProcessFlag_DisableDeviceAddressSpaceMerge | - CreateProcessFlag_EnableAliasRegionExtraSize, + CreateProcessFlag_EnableAliasRegionExtraSize | + CreateProcessFlag_EnableShadowStack, }; /* Debug types. */ diff --git a/libraries/libvapours/include/vapours/svc/svc_version.hpp b/libraries/libvapours/include/vapours/svc/svc_version.hpp index 500da0e21..e8c2b3ae8 100644 --- a/libraries/libvapours/include/vapours/svc/svc_version.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_version.hpp @@ -57,7 +57,7 @@ namespace ams::svc { /* This is the highest SVC version supported by Atmosphere, to be updated on new kernel releases. */ /* NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. */ - constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(22); + constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(23); constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 2); constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); diff --git a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp index 10a000c6d..415b5bca2 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -224,15 +224,20 @@ namespace ams::kern::init { static_assert(kern::arch::arm64::init::IsInitialPageAllocator); void SetupAllTtbr0Entries(KInitialPageTable &init_pt, KInitialPageAllocator &allocator) { - /* Validate that the ttbr0 array is in rodata. */ + /* Validate that the ttbr0/tcr_el1 arrays are in rodata. */ const uintptr_t rodata_start = reinterpret_cast(__rodata_start); const uintptr_t rodata_end = reinterpret_cast(__rodata_end); MESOSPHERE_INIT_ABORT_UNLESS(rodata_start < rodata_end); MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(0)))); - MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumTtbr0Entries))) < rodata_end); + MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumPTEntries))) < rodata_end); + MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast(std::addressof(KPageTable::GetTcrEL1Entry(0)))); + MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTcrEL1Entry(KPageTable::NumPTEntries))) < rodata_end); + + /* Get the default tcr_el1 value, with T0SZ set for a 39-bit address space. */ + const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | UINT64_C(64 - 39); /* Allocate pages for all ttbr0 entries. */ - for (size_t i = 0; i < KPageTable::NumTtbr0Entries; ++i) { + for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) { /* Allocate a page. */ KPhysicalAddress page = allocator.Allocate(PageSize); MESOSPHERE_INIT_ABORT_UNLESS(page != Null); @@ -245,6 +250,12 @@ namespace ams::kern::init { /* Set the entry to the newly allocated page. */ *reinterpret_cast(GetInteger(ttbr0_phys_ptr)) = (static_cast(i) << 48) | GetInteger(page); + + /* Get the physical address of the tcr_el1 entry. */ + const auto tcr_el1_phys_ptr = init_pt.GetPhysicalAddress(KVirtualAddress(std::addressof(KPageTable::GetTcrEL1Entry(i)))); + + /* Set the entry to the default tcr_el1 value. */ + *reinterpret_cast(GetInteger(tcr_el1_phys_ptr)) = tcr_el1; } } diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index d6b6d7852..f7da96292 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -270,6 +270,7 @@ namespace ams::ldr { 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; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit64KPage: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit64KPage) << Npdm::MetaFlag_AddressSpaceTypeShift; break; AMS_UNREACHABLE_DEFAULT_CASE(); } } diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index bea773f44..d05450541 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -423,6 +423,9 @@ namespace ams::ldr { case Npdm::AddressSpaceType_64Bit: flags |= svc::CreateProcessFlag_AddressSpace64Bit; break; + case Npdm::AddressSpaceType_64Bit64KPage: + flags |= svc::CreateProcessFlag_AddressSpace64Bit64KPage; + break; default: R_THROW(ldr::ResultInvalidMeta()); } @@ -597,6 +600,10 @@ namespace ams::ldr { aslr_start = svc::AddressMap39Start; aslr_size = svc::AddressMap39Size; break; + case svc::CreateProcessFlag_AddressSpace64Bit64KPage: + aslr_start = svc::AddressMap42Start; + aslr_size = svc::AddressMap42Size; + break; AMS_UNREACHABLE_DEFAULT_CASE(); } } else { From 289ba7104e988d4e9feeb29a40b233a21440b94d Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 15 Sep 2026 16:57:27 +0200 Subject: [PATCH 14/52] kern: add new unknown DebugThreadParam --- libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp | 4 ++++ libraries/libmesosphere/source/kern_k_process.cpp | 3 +++ libraries/libmesosphere/source/svc/kern_svc_debug.cpp | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index 8904a6a92..7e294473c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -341,6 +341,7 @@ namespace ams::kern { bool m_debug_attached; s8 m_priority_inheritance_count; bool m_resource_limit_release_hint; + bool m_debug_unknown5; public: constexpr explicit KThread(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapAndContainer(util::ConstantInitialize), KTimerTask(util::ConstantInitialize), @@ -683,6 +684,9 @@ namespace ams::kern { constexpr void SetDebugAttached() { m_debug_attached = true; } constexpr bool IsAttachedToDebugger() const { return m_debug_attached; } + constexpr void SetDebugUnknown5(bool value) { m_debug_unknown5 = value; } + constexpr bool IsDebugUnknown5() const { return m_debug_unknown5; } + void AddCpuTime(s32 core_id, s64 amount) { m_cpu_time += amount; /* TODO: Debug kernels track per-core tick counts. Should we? */ diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 91048f4f6..7d1b0d0f4 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -970,6 +970,9 @@ namespace ams::kern { /* Initialize the thread. */ R_TRY(KThread::InitializeUserThread(main_thread, reinterpret_cast(GetVoidPointer(this->GetEntryPoint())), 0, stack_top, priority, m_ideal_core_id, this)); + /* TODO: what is this? */ + main_thread->SetDebugUnknown5(true); + /* Register the thread, and commit our reservation. */ KThread::Register(main_thread); thread_reservation.Commit(); diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp index 986654ce4..635b91cbe 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp @@ -429,6 +429,11 @@ namespace ams::kern::svc { *out_32 = affinity_mask; } break; + case ams::svc::DebugThreadParam_Unknown5: + { + *out_32 = thread->IsDebugUnknown5(); + } + break; default: R_THROW(ams::svc::ResultInvalidEnumValue()); } From 7e58f5fbae70971d5f84df61122ef3983345288f Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 15 Sep 2026 17:03:11 +0200 Subject: [PATCH 15/52] kern: finish shadow stack region, 64k page process segregation implementation, fix some long-standing issues --- .../arch/arm64/kern_k_page_table.hpp | 1 + .../arch/arm64/kern_k_process_page_table.hpp | 9 + .../arm64/kern_userspace_memory_access.hpp | 2 +- .../mesosphere/kern_k_page_table_base.hpp | 10 +- .../source/kern_k_page_table_base.cpp | 247 +++++------------- .../source/kern_k_system_control_base.cpp | 7 + .../source/svc/kern_svc_process.cpp | 38 ++- .../include/vapours/svc/svc_types_common.hpp | 4 + .../source/arch/arm64/init/kern_init_core.cpp | 2 +- 9 files changed, 132 insertions(+), 188 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index 356dc4217..9fd7dbd2f 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace ams::kern::arch::arm64 { diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index 63a357e0e..e80311a47 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -32,6 +32,11 @@ namespace ams::kern::arch::arm64 { R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit, process_index)); } + static ALWAYS_INLINE u64 GetProcessTcrEl1(size_t process_index) { + /* The kernel's root table is entry zero; processes are indexed from one. */ + return KPageTable::GetTcrEL1Entry(process_index + 1); + } + void Finalize() { m_page_table.Finalize(); } ALWAYS_INLINE KScopedLightLock AcquireDeviceMapLock() { @@ -302,6 +307,10 @@ namespace ams::kern::arch::arm64 { bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); } bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { return m_page_table.CanContain(addr, size, state); } + bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInShadowStackRegion(addr, size); } + bool IsInShadowStackRegion(KProcessAddress addr) const { return m_page_table.IsInShadowStackRegion(addr); } + bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { return m_page_table.IsSafeUserPointer(addr, size); } + KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); } KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp index fc075178b..28580e038 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp @@ -77,7 +77,7 @@ namespace ams::kern::arch::arm64 { static bool CopyMemoryFromUserSize32BitWithSupervisorAccess(void *dst, const void *src) { /* Check that the address is within the valid userspace range. */ - if (const uintptr_t src_uptr = reinterpret_cast(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion39Size) { + if (const uintptr_t src_uptr = reinterpret_cast(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion42Size) { return false; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 759fd1758..c0139ab79 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -249,7 +249,15 @@ namespace ams::kern { } constexpr bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { - return this->Contains(addr, size) && m_region_starts[RegionType_ShadowStack] <= addr && addr + size - 1 <= m_region_ends[RegionType_ShadowStack] - 1; + const auto start = m_region_starts[RegionType_ShadowStack]; + const auto end = m_region_ends[RegionType_ShadowStack]; + return start != end && addr < end && start < addr + size; + } + + constexpr bool IsInShadowStackRegion(KProcessAddress addr) const { + const auto start = m_region_starts[RegionType_ShadowStack]; + const auto end = m_region_ends[RegionType_ShadowStack]; + return start <= addr && addr < end; } constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 98988dde6..652583fd4 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -353,182 +353,36 @@ namespace ams::kern { const KProcessAddress process_code_last = process_code_end - 1; auto IsInAddressSpace = [&](KProcessAddress addr) ALWAYS_INLINE_LAMBDA { return m_address_space_start <= addr && addr <= m_address_space_end; }; - /* Ensure that the KernelMap region is valid. */ - for (size_t k = 0; k < num_regions; ++k) { - if (const auto &kmap_region = region_layouts[k]; kmap_region.type == RegionType_KernelMap) { - /* If there's no kmap region, we have nothing to check. */ - if (kmap_region.size == 0) { - break; - } - - /* Check that the kmap region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_KernelMap])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_KernelMap])); - - /* Check for overlap with process code. */ - const KProcessAddress kmap_start = m_region_starts[RegionType_KernelMap]; - const KProcessAddress kmap_last = m_region_ends[RegionType_KernelMap] - 1; - MESOSPHERE_ABORT_UNLESS(kernel_map_region_size == 0 || kmap_last < process_code_start || process_code_last < kmap_start); - - /* Check for overlap with stack. */ - for (size_t s = 0; s < num_regions; ++s) { - if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) { - if (stack_region.size != 0) { - const KProcessAddress stack_start = m_region_starts[RegionType_Stack]; - const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1; - MESOSPHERE_ABORT_UNLESS((kernel_map_region_size == 0 && stack_region_size == 0) || kmap_last < stack_start || stack_last < kmap_start); - } - break; - } - } - - /* Check for overlap with alias. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - if (alias_region.size != 0) { - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(kmap_last < alias_start || alias_last < kmap_start); - } - break; - } - } - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(kmap_last < heap_start || heap_last < kmap_start); - } - break; - } - } - - /* Check for overlap with shadow stack. */ - for (size_t ss = 0; ss < num_regions; ++ss) { - if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { - if (shadow_stack_region.size != 0) { - const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; - const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; - MESOSPHERE_ABORT_UNLESS(kmap_last < shadow_stack_start || shadow_stack_last < kmap_start); - } - break; - } - } - } + /* Map each region type to its layout entry. */ + const RegionLayoutInfo *region_layouts_by_type[RegionType_Count] = {}; + for (size_t i = 0; i < num_regions; ++i) { + region_layouts_by_type[region_layouts[i].type] = std::addressof(region_layouts[i]); } - /* Check that the Stack region is valid. */ - for (size_t s = 0; s < num_regions; ++s) { - if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) { - /* If there's no stack region, we have nothing to check. */ - if (stack_region.size == 0) { - break; - } - - /* Check that the stack region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Stack])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Stack])); - - /* Check for overlap with process code. */ - const KProcessAddress stack_start = m_region_starts[RegionType_Stack]; - const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1; - MESOSPHERE_ABORT_UNLESS(stack_region_size == 0 || stack_last < process_code_start || process_code_last < stack_start); - - /* Check for overlap with alias. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - if (alias_region.size != 0) { - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(stack_last < alias_start || alias_last < stack_start); - } - break; - } - } - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(stack_last < heap_start || heap_last < stack_start); - } - break; - } - } + /* Validate each region. */ + for (size_t i = 0; i < RegionType_Count; ++i) { + /* If the region isn't present, there's nothing to check. */ + const RegionLayoutInfo * const region = region_layouts_by_type[i]; + if (region == nullptr || region->size == 0) { + continue; } - } - /* Check that the Alias region is valid. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - /* If there's no alias region, we have nothing to check. */ - if (alias_region.size == 0) { - break; + /* Check that the region is within our address space. */ + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[i])); + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[i])); + + /* Check for overlap with process code. */ + MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < process_code_start || process_code_last < m_region_starts[i]); + + /* Check for overlap with every later region. */ + for (size_t j = i; j < RegionType_ShadowStack; ++j) { + /* If the other region isn't present, there's nothing to check. */ + const RegionLayoutInfo * const other = region_layouts_by_type[j + 1]; + if (other == nullptr || other->size == 0) { + continue; } - /* Check that the alias region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Alias])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Alias])); - - /* Check for overlap with process code. */ - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(alias_last < process_code_start || process_code_last < alias_start); - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(alias_last < heap_start || heap_last < alias_start); - } - break; - } - } - } - } - - /* Check that the Heap region is valid. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - /* If there's no heap region, we have nothing to check. */ - if (heap_region.size == 0) { - break; - } - - /* Check that the heap region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Heap])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Heap])); - - /* Check for overlap with process code. */ - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start); - } - } - - /* Check that the ShadowStack region is valid. */ - for (size_t ss = 0; ss < num_regions; ++ss) { - if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { - /* If there's no shadow stack region, we have nothing to check. */ - if (shadow_stack_region.size == 0) { - break; - } - - /* Check that the shadow stack region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_ShadowStack])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_ShadowStack])); - - /* Check for overlap with process code. */ - const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; - const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; - MESOSPHERE_ABORT_UNLESS(shadow_stack_last < process_code_start || process_code_last < shadow_stack_start); + MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < m_region_starts[j + 1] || m_region_ends[j + 1] - 1 < m_region_starts[i]); } } } @@ -598,6 +452,8 @@ namespace ams::kern { case ams::svc::MemoryState_Static: case ams::svc::MemoryState_ThreadLocal: return m_region_starts[RegionType_KernelMap]; + case ams::svc::MemoryState_ShadowStack: + return m_region_starts[RegionType_ShadowStack]; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Shared: case ams::svc::MemoryState_AliasCode: @@ -633,6 +489,8 @@ namespace ams::kern { case ams::svc::MemoryState_Static: case ams::svc::MemoryState_ThreadLocal: return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; + case ams::svc::MemoryState_ShadowStack: + return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Shared: case ams::svc::MemoryState_AliasCode: @@ -659,12 +517,20 @@ namespace ams::kern { const KProcessAddress region_start = this->GetRegionAddress(state); const size_t region_size = this->GetRegionSize(state); + if (region_size == 0) { + return false; + } + const bool is_in_region = region_start <= addr && addr < end && last <= region_start + region_size - 1; - const bool is_in_heap = !(end <= m_region_starts[RegionType_Heap] || m_region_ends[RegionType_Heap] <= addr || m_region_starts[RegionType_Heap] == m_region_ends[RegionType_Heap]); - const bool is_in_alias = !(end <= m_region_starts[RegionType_Alias] || m_region_ends[RegionType_Alias] <= addr || m_region_starts[RegionType_Alias] == m_region_ends[RegionType_Alias]); + switch (state) { case ams::svc::MemoryState_Free: + case ams::svc::MemoryState_Normal: + case ams::svc::MemoryState_Ipc: + case ams::svc::MemoryState_NonSecureIpc: + case ams::svc::MemoryState_NonDeviceIpc: case ams::svc::MemoryState_Kernel: + case ams::svc::MemoryState_ShadowStack: return is_in_region; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Static: @@ -682,17 +548,32 @@ namespace ams::kern { case ams::svc::MemoryState_CodeOut: case ams::svc::MemoryState_Coverage: case ams::svc::MemoryState_Insecure: - return is_in_region && !is_in_heap && !is_in_alias; - case ams::svc::MemoryState_Normal: - MESOSPHERE_ASSERT(is_in_heap); - return is_in_region && !is_in_alias; - case ams::svc::MemoryState_Ipc: - case ams::svc::MemoryState_NonSecureIpc: - case ams::svc::MemoryState_NonDeviceIpc: - MESOSPHERE_ASSERT(is_in_alias); - return is_in_region && !is_in_heap; - default: - return false; + { + if (!is_in_region) { + return false; + } + + const auto heap_start = m_region_starts[RegionType_Heap]; + const auto heap_end = m_region_ends[RegionType_Heap]; + if (heap_start != heap_end && addr < heap_end && heap_start < end) { + return false; + } + + const auto alias_start = m_region_starts[RegionType_Alias]; + const auto alias_end = m_region_ends[RegionType_Alias]; + if (alias_start != alias_end && addr < alias_end && alias_start < end) { + return false; + } + + const auto shadow_start = m_region_starts[RegionType_ShadowStack]; + const auto shadow_end = m_region_ends[RegionType_ShadowStack]; + if (shadow_start != shadow_end && addr < shadow_end && shadow_start < end) { + return false; + } + + return true; + } + MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } } diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index dece074ef..38c507486 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -170,6 +170,13 @@ namespace ams::kern { KAddressSpaceInfo::SetAddressSpaceSize(39, KAddressSpaceInfo::Type_Alias, alias_size); } + /* Update 42-bit address space infos. */ + { + /* Heap should be equal to the total memory size, maximum 128 GB. */ + /* Alias/Stack/MapSmall are left at their static defaults. */ + KAddressSpaceInfo::SetAddressSpaceSize(42, KAddressSpaceInfo::Type_Heap, std::min(util::AlignUp(total_memory_size, 1_GB), 128_GB)); + } + const auto &slab_counts = init::GetSlabResourceCounts(); MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax, total_memory_size)); MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_ThreadCountMax, slab_counts.num_KThread)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 54f598d1e..375386562 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -86,6 +86,40 @@ namespace ams::kern::svc { R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count)); } + constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessFlag flags) { + if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) { + return (64 - 42); + } else { + return (64 - 39); + } + } + + KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessFlag flags) { + /* Find a process slab slot whose root page table is meant for the requested address space. */ + const size_t desired_t0sz = GetProcessSlotT0Sz(flags); + + KProcess *process = nullptr; + KProcess *rejected[init::SlabCountKProcess]; + size_t num_rejected = 0; + while ((process = KProcess::Create()) != nullptr) { + /* Stop once we find a slot whose T0SZ matches. */ + if ((KProcessPageTable::GetProcessTcrEl1(process->GetSlabIndex()) & 0x3F) == desired_t0sz) { + break; + } + + /* Otherwise, park the process and try the next slot. */ + rejected[num_rejected++] = process; + process = nullptr; + } + + /* Release every process we parked while searching. */ + for (size_t i = 0; i < num_rejected; ++i) { + rejected[i]->Close(); + } + + return process; + } + Result CreateProcess(ams::svc::Handle *out, const ams::svc::CreateProcessParameter ¶ms, KUserPointer user_caps, int32_t num_caps) { /* Validate the capabilities pointer. */ R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer()); @@ -219,8 +253,8 @@ namespace ams::kern::svc { /* Get the current handle table. */ auto &handle_table = GetCurrentProcess().GetHandleTable(); - /* Create the new process. */ - KProcess *process = KProcess::Create(); + /* Create the new process, ensuring its page table slot matches the requested address space. */ + KProcess *process = CreateProcessForAddressSpace(static_cast(params.flags)); R_UNLESS(process != nullptr, svc::ResultOutOfResource()); /* Ensure that the only reference to the process is in the handle table when we're done. */ diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 20aa4ea90..66f5a5648 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -96,6 +96,9 @@ namespace ams::svc { MemoryState_CodeOut = 0x15, MemoryState_Coverage = 0x16, MemoryState_Insecure = 0x17, + MemoryState_Remote = 0x18, + MemoryState_Protected = 0x19, + MemoryState_ShadowStack = 0x1A, }; enum MemoryPermission : u32 { @@ -483,6 +486,7 @@ namespace ams::svc { DebugThreadParam_IdealCore = 2, DebugThreadParam_CurrentCore = 3, DebugThreadParam_AffinityMask = 4, + DebugThreadParam_Unknown5 = 5, }; enum DebugException : u32 { diff --git a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp index 415b5bca2..e37780b7e 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -234,7 +234,7 @@ namespace ams::kern::init { MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTcrEL1Entry(KPageTable::NumPTEntries))) < rodata_end); /* Get the default tcr_el1 value, with T0SZ set for a 39-bit address space. */ - const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | UINT64_C(64 - 39); + const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | (64 - 39); /* Allocate pages for all ttbr0 entries. */ for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) { From dbfe192b2faf5de748b63f60fa1eaa7d2a6c953d Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 15 Sep 2026 17:04:18 +0200 Subject: [PATCH 16/52] kern: reject shadow stack accesses in syscalls --- .../libmesosphere/source/kern_k_debug_base.cpp | 8 ++++---- .../source/kern_k_page_table_base.cpp | 4 ++-- .../source/svc/kern_svc_address_arbiter.cpp | 10 ++++++---- .../libmesosphere/source/svc/kern_svc_cache.cpp | 2 +- .../source/svc/kern_svc_condition_variable.cpp | 8 +++++--- .../libmesosphere/source/svc/kern_svc_debug.cpp | 10 ++++++++++ .../source/svc/kern_svc_debug_string.cpp | 2 +- .../libmesosphere/source/svc/kern_svc_ipc.cpp | 2 +- .../libmesosphere/source/svc/kern_svc_lock.cpp | 10 ++++++---- .../libmesosphere/source/svc/kern_svc_port.cpp | 17 ++++++++++++++--- .../source/svc/kern_svc_process.cpp | 4 ++-- .../source/svc/kern_svc_process_memory.cpp | 4 ++-- .../source/svc/kern_svc_query_memory.cpp | 2 ++ .../source/svc/kern_svc_synchronization.cpp | 2 +- .../source/svc/kern_svc_thread.cpp | 4 +++- 15 files changed, 60 insertions(+), 29 deletions(-) diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 453eb745c..40ff0ce3f 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -100,8 +100,8 @@ namespace ams::kern { KProcessPageTable &target_pt = process->GetPageTable(); /* Verify that the regions are in range. */ - R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory()); - R_UNLESS(debugger_pt.Contains(buffer, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(debugger_pt.IsSafeUserPointer(buffer, size), svc::ResultInvalidCurrentMemory()); /* Iterate over the target process's memory blocks. */ KProcessAddress cur_address = address; @@ -166,8 +166,8 @@ namespace ams::kern { KProcessPageTable &target_pt = process->GetPageTable(); /* Verify that the regions are in range. */ - R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory()); - R_UNLESS(debugger_pt.Contains(buffer, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(debugger_pt.IsSafeUserPointer(buffer, size), svc::ResultInvalidCurrentMemory()); /* Iterate over the target process's memory blocks. */ KProcessAddress cur_address = address; diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 652583fd4..5b40e20e0 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -3205,7 +3205,7 @@ namespace ams::kern { Result KPageTableBase::CopyMemoryFromLinearToUser(KProcessAddress dst_addr, size_t size, KProcessAddress src_addr, u32 src_state_mask, u32 src_state, KMemoryPermission src_test_perm, u32 src_attr_mask, u32 src_attr) { /* Lightly validate the range before doing anything else. */ - R_UNLESS(this->Contains(src_addr, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(this->IsSafeUserPointer(src_addr, size), svc::ResultInvalidCurrentMemory()); /* Copy the memory. */ { @@ -3354,7 +3354,7 @@ namespace ams::kern { Result KPageTableBase::CopyMemoryFromUserToLinear(KProcessAddress dst_addr, size_t size, u32 dst_state_mask, u32 dst_state, KMemoryPermission dst_test_perm, u32 dst_attr_mask, u32 dst_attr, KProcessAddress src_addr) { /* Lightly validate the range before doing anything else. */ - R_UNLESS(this->Contains(dst_addr, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(this->IsSafeUserPointer(dst_addr, size), svc::ResultInvalidCurrentMemory()); /* Copy the memory. */ { diff --git a/libraries/libmesosphere/source/svc/kern_svc_address_arbiter.cpp b/libraries/libmesosphere/source/svc/kern_svc_address_arbiter.cpp index 2b495ad45..939c29107 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_address_arbiter.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_address_arbiter.cpp @@ -21,8 +21,10 @@ namespace ams::kern::svc { namespace { - constexpr bool IsKernelAddress(uintptr_t address) { - return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; + constexpr bool IsValidAddress(uintptr_t address) { + if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false; + if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false; + return true; } constexpr bool IsValidSignalType(ams::svc::SignalType type) { @@ -50,7 +52,7 @@ namespace ams::kern::svc { Result WaitForAddress(uintptr_t address, ams::svc::ArbitrationType arb_type, int64_t value, int64_t timeout_ns) { /* Validate input. */ - R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidCurrentMemory()); if (arb_type == ams::svc::ArbitrationType_WaitIfEqual64) { R_UNLESS(util::IsAligned(address, sizeof(int64_t)), svc::ResultInvalidAddress()); } else { @@ -79,7 +81,7 @@ namespace ams::kern::svc { Result SignalToAddress(uintptr_t address, ams::svc::SignalType signal_type, int32_t value, int32_t count) { /* Validate input. */ - R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidCurrentMemory()); R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress()); R_UNLESS(IsValidSignalType(signal_type), svc::ResultInvalidEnumValue()); diff --git a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp index 00f84781f..895959f9a 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_cache.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_cache.cpp @@ -83,7 +83,7 @@ namespace ams::kern::svc { R_SUCCEED_IF(size == 0); /* Validate that the region is within range. */ - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(address, size), svc::ResultInvalidCurrentMemory()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(address, size), svc::ResultInvalidCurrentMemory()); /* did N intend ResultInvalidPointer like everywhere else? */ /* Flush the cache. */ R_TRY(cpu::FlushDataCache(reinterpret_cast(address), size)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_condition_variable.cpp b/libraries/libmesosphere/source/svc/kern_svc_condition_variable.cpp index 2d3a031ef..aebe88443 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_condition_variable.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_condition_variable.cpp @@ -21,13 +21,15 @@ namespace ams::kern::svc { namespace { - constexpr bool IsKernelAddress(uintptr_t address) { - return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; + constexpr bool IsValidAddress(uintptr_t address) { + if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false; + if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false; + return true; } Result WaitProcessWideKeyAtomic(uintptr_t address, uintptr_t cv_key, uint32_t tag, int64_t timeout_ns) { /* Validate input. */ - R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(AMS_LIKELY(IsValidAddress(address)), svc::ResultInvalidPointer()); R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress()); /* Convert timeout from nanoseconds to ticks. */ diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp index 635b91cbe..39db3775b 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp @@ -97,6 +97,8 @@ namespace ams::kern::svc { /* Only allow invoking the svc on development hardware or if force debug prod. */ R_UNLESS(KTargetSystem::IsDebugMode() || GetCurrentProcess().CanForceDebugProd(), svc::ResultNotImplemented()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_info.GetUnsafePointer()), sizeof(EventInfoType)), svc::ResultInvalidPointer()); + /* Get the debug object. */ KScopedAutoObject debug = GetCurrentProcess().GetHandleTable().GetObject(debug_handle); R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle()); @@ -139,6 +141,8 @@ namespace ams::kern::svc { /* Verify that the number of thread ids is valid. */ R_UNLESS((0 <= num_thread_ids && num_thread_ids <= MaximumDebuggableThreadCount), svc::ResultOutOfRange()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_thread_ids.GetUnsafePointer()), num_thread_ids * sizeof(uint64_t)), svc::ResultInvalidPointer()); + /* Copy the threads from userspace. */ uint64_t thread_ids[MaximumDebuggableThreadCount]; if (num_thread_ids > 0) { @@ -172,6 +176,8 @@ namespace ams::kern::svc { /* Only allow invoking the svc on development hardware or if force debug prod. */ R_UNLESS(KTargetSystem::IsDebugMode() || GetCurrentProcess().CanForceDebugProd(), svc::ResultNotImplemented()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer()); + /* Validate the context flags. */ R_UNLESS((context_flags | ams::svc::ThreadContextFlag_All) == ams::svc::ThreadContextFlag_All, svc::ResultInvalidEnumValue()); @@ -193,6 +199,8 @@ namespace ams::kern::svc { /* Only allow invoking the svc on development hardware. */ R_UNLESS(KTargetSystem::IsDebugMode(), svc::ResultNotImplemented()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer()); + /* Validate the context flags. */ #if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP) { @@ -243,6 +251,8 @@ namespace ams::kern::svc { template Result QueryDebugProcessMemory(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, uint64_t address) { + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_memory_info.GetUnsafePointer()), sizeof(T)), svc::ResultInvalidPointer()); + /* Get an ams::svc::MemoryInfo for the region. */ ams::svc::MemoryInfo info = {}; R_TRY(QueryDebugProcessMemory(std::addressof(info), out_page_info, debug_handle, address)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp index c36c93ffe..5f15e77f4 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp @@ -26,7 +26,7 @@ namespace ams::kern::svc { R_SUCCEED_IF(len == 0); /* Ensure that the data being output is in range. */ - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(debug_str.GetUnsafePointer()), len), svc::ResultInvalidCurrentMemory()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(debug_str.GetUnsafePointer()), len), svc::ResultInvalidPointer()); /* Output the string. */ R_RETURN(KDebugLog::PrintUserString(debug_str, len)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp b/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp index e2013a1b3..603db823c 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_ipc.cpp @@ -110,7 +110,7 @@ namespace ams::kern::svc { /* Copy user handles. */ if (num_handles > 0) { /* Ensure that we can try to get the handles. */ - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer()); /* Get the handles. */ R_TRY(user_handles.CopyArrayTo(handles, num_handles)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_lock.cpp b/libraries/libmesosphere/source/svc/kern_svc_lock.cpp index be19bc0ed..9ada8d0fc 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_lock.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_lock.cpp @@ -21,13 +21,15 @@ namespace ams::kern::svc { namespace { - constexpr bool IsKernelAddress(uintptr_t address) { - return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; + constexpr bool IsValidAddress(uintptr_t address) { + if (KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd) return false; + if (GetCurrentProcess().GetPageTable().IsInShadowStackRegion(address)) return false; + return true; } Result ArbitrateLock(ams::svc::Handle thread_handle, uintptr_t address, uint32_t tag) { /* Validate the input address. */ - R_UNLESS(!IsKernelAddress(address), svc::ResultInvalidCurrentMemory()); + R_UNLESS(IsValidAddress(address), svc::ResultInvalidCurrentMemory()); R_UNLESS(util::IsAligned(address, sizeof(u32)), svc::ResultInvalidAddress()); R_RETURN(KConditionVariable::WaitForAddress(thread_handle, address, tag)); @@ -35,7 +37,7 @@ namespace ams::kern::svc { Result ArbitrateUnlock(uintptr_t address) { /* Validate the input address. */ - R_UNLESS(!IsKernelAddress(address), svc::ResultInvalidCurrentMemory()); + R_UNLESS(IsValidAddress(address), svc::ResultInvalidCurrentMemory()); R_UNLESS(util::IsAligned(address, sizeof(u32)), svc::ResultInvalidAddress()); R_RETURN(KConditionVariable::SignalToAddress(address)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_port.cpp b/libraries/libmesosphere/source/svc/kern_svc_port.cpp index 1ac5803d2..cfc13a3a8 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_port.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_port.cpp @@ -21,11 +21,22 @@ namespace ams::kern::svc { namespace { + static Result GetPortName(char (&name)[KObjectName::NameLengthMax], KUserPointer user_name) { + /* Copy the provided name from user memory to kernel memory. */ + R_TRY(user_name.CopyStringTo(name, sizeof(name))); + + /* Oddly enough N here first copies then validates if it's not in forbidden range. */ + const auto name_len = util::Strnlen(name, sizeof(name)); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_name.GetUnsafePointer()), name_len + 1), svc::ResultInvalidPointer()); + + R_SUCCEED(); + } + Result ManageNamedPort(ams::svc::Handle *out_server_handle, KUserPointer user_name, s32 max_sessions) { /* Copy the provided name from user memory to kernel memory. */ char name[KObjectName::NameLengthMax] = {}; - R_TRY(user_name.CopyStringTo(name, sizeof(name))); - + R_TRY(GetPortName(name, user_name)); + /* Validate that sessions and name are valid. */ R_UNLESS(max_sessions >= 0, svc::ResultOutOfRange()); R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange()); @@ -106,7 +117,7 @@ namespace ams::kern::svc { Result ConnectToNamedPort(ams::svc::Handle *out, KUserPointer user_name) { /* Copy the provided name from user memory to kernel memory. */ char name[KObjectName::NameLengthMax] = {}; - R_TRY(user_name.CopyStringTo(name, sizeof(name))); + R_TRY(GetPortName(name, user_name)); /* Validate that name is valid. */ R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange()); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 375386562..c570c40d6 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -79,7 +79,7 @@ namespace ams::kern::svc { /* Validate that the pointer is in range. */ if (max_out_count > 0) { - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(out_process_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_process_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidPointer()); } /* Get the process list. */ @@ -128,7 +128,7 @@ namespace ams::kern::svc { R_UNLESS(((num_caps * sizeof(u32)) / sizeof(u32)) == static_cast(num_caps), svc::ResultInvalidPointer()); /* Validate that the pointer is in range. */ - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_caps.GetUnsafePointer()), num_caps * sizeof(u32)), svc::ResultInvalidPointer()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_caps.GetUnsafePointer()), num_caps * sizeof(u32)), svc::ResultInvalidPointer()); } /* Validate that the parameter flags are valid. */ diff --git a/libraries/libmesosphere/source/svc/kern_svc_process_memory.cpp b/libraries/libmesosphere/source/svc/kern_svc_process_memory.cpp index 41420ca06..56978b1cd 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process_memory.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process_memory.cpp @@ -148,7 +148,7 @@ namespace ams::kern::svc { /* Validate that the mapping is in range. */ auto &page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(src_address, size), svc::ResultInvalidCurrentMemory()); - R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidCurrentMemory()); + R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidMemoryRegion()); /* Map the memory. */ R_TRY(page_table.MapCodeMemory(dst_address, src_address, size)); @@ -175,7 +175,7 @@ namespace ams::kern::svc { /* Validate that the mapping is in range. */ auto &page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(src_address, size), svc::ResultInvalidCurrentMemory()); - R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidCurrentMemory()); + R_UNLESS(page_table.CanContain(dst_address, size, KMemoryState_AliasCode), svc::ResultInvalidMemoryRegion()); /* Unmap the memory. */ R_TRY(page_table.UnmapCodeMemory(dst_address, src_address, size)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_query_memory.cpp b/libraries/libmesosphere/source/svc/kern_svc_query_memory.cpp index 555130743..d93e3310f 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_query_memory.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_query_memory.cpp @@ -37,6 +37,8 @@ namespace ams::kern::svc { template Result QueryProcessMemory(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle process_handle, uint64_t address) { + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_memory_info.GetUnsafePointer()), sizeof(T)), svc::ResultInvalidPointer()); + /* Get an ams::svc::MemoryInfo for the region. */ ams::svc::MemoryInfo info = {}; R_TRY(QueryProcessMemory(std::addressof(info), out_page_info, process_handle, address)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_synchronization.cpp b/libraries/libmesosphere/source/svc/kern_svc_synchronization.cpp index 20e025bb5..ae23f50bd 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_synchronization.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_synchronization.cpp @@ -82,7 +82,7 @@ namespace ams::kern::svc { /* Copy user handles. */ if (num_handles > 0) { /* Ensure that we can try to get the handles. */ - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_handles.GetUnsafePointer()), num_handles * sizeof(ams::svc::Handle)), svc::ResultInvalidPointer()); /* Get the handles. */ R_TRY(user_handles.CopyArrayTo(handles, num_handles)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp index 14af1bb11..d0c3dc012 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp @@ -204,6 +204,8 @@ namespace ams::kern::svc { /* Get the thread from its handle. */ KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject(thread_handle); R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle()); + + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_context.GetUnsafePointer()), sizeof(ams::svc::ThreadContext)), svc::ResultInvalidPointer()); /* Require the handle be to a non-current thread in the current process. */ R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(), svc::ResultInvalidHandle()); @@ -228,7 +230,7 @@ namespace ams::kern::svc { /* Validate that the pointer is in range. */ if (max_out_count > 0) { - R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(out_thread_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(out_thread_ids.GetUnsafePointer()), max_out_count * sizeof(u64)), svc::ResultInvalidPointer()); } /* Get the handle table. */ From 49b12237e85cd11bc8f44c83e1ded63ceb165e24 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 15 Sep 2026 22:16:29 +0100 Subject: [PATCH 17/52] pgl: clean up and add new 23.0.0 command --- .../stratosphere/pgl/pgl_event_observer.hpp | 28 ++++---- .../stratosphere/pgl/pgl_shell_api.hpp | 12 ++-- .../include/stratosphere/pgl/pgl_types.hpp | 7 +- .../pgl/sf/pgl_sf_i_event_observer.hpp | 4 +- .../pgl/sf/pgl_sf_i_shell_interface.hpp | 11 ++-- .../pgl/srv/pgl_srv_shell_interface.hpp | 32 ++++----- .../pgl/tipc/pgl_tipc_i_event_observer.hpp | 4 +- .../pgl/tipc/pgl_tipc_i_shell_interface.hpp | 26 ++++---- .../source/pgl/pgl_remote_event_observer.hpp | 16 ++--- .../source/pgl/pgl_shell_api.cpp | 41 +++++++----- .../source/pgl/srv/pgl_srv_shell.cpp | 34 +++++++--- .../source/pgl/srv/pgl_srv_shell.hpp | 7 +- .../pgl/srv/pgl_srv_shell_event_observer.cpp | 8 +-- .../pgl/srv/pgl_srv_shell_event_observer.hpp | 8 +-- .../pgl/srv/pgl_srv_shell_host_utils.cpp | 4 +- .../pgl/srv/pgl_srv_shell_host_utils.hpp | 2 +- .../pgl/srv/pgl_srv_shell_interface.cpp | 66 ++++++++++--------- 17 files changed, 170 insertions(+), 140 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/pgl/pgl_event_observer.hpp b/libraries/libstratosphere/include/stratosphere/pgl/pgl_event_observer.hpp index 2a9eff313..3a98dfa14 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/pgl_event_observer.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/pgl_event_observer.hpp @@ -33,8 +33,8 @@ namespace ams::pgl { virtual ~EventObserverInterface() { /* ... */ } - virtual Result GetSystemEvent(os::SystemEventType *out) = 0; - virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) = 0; + virtual Result GetShellEvent(os::SystemEventType *out) = 0; + virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) = 0; }; class EventObserverByCmif final : public EventObserverInterface { @@ -45,9 +45,9 @@ namespace ams::pgl { public: explicit EventObserverByCmif(ams::sf::SharedPointer intf) : m_cmif_interface(intf) { /* ... */ } public: - virtual Result GetSystemEvent(os::SystemEventType *out) override { + virtual Result GetShellEvent(os::SystemEventType *out) override { ams::sf::NativeHandle handle; - R_TRY(m_cmif_interface->GetProcessEventHandle(std::addressof(handle))); + R_TRY(m_cmif_interface->GetShellEvent(std::addressof(handle))); os::AttachReadableHandleToSystemEvent(out, handle.GetOsHandle(), handle.IsManaged(), os::EventClearMode_AutoClear); handle.Detach(); @@ -55,8 +55,8 @@ namespace ams::pgl { R_SUCCEED(); } - virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) override { - R_RETURN(m_cmif_interface->GetProcessEventInfo(out)); + virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) override { + R_RETURN(m_cmif_interface->GetShellEventInfo(out)); } }; @@ -70,15 +70,15 @@ namespace ams::pgl { template explicit EventObserverByTipc(Args &&... args) : m_tipc_interface(std::forward(args)...) { /* ... */ } public: - virtual Result GetSystemEvent(os::SystemEventType *out) override { + virtual Result GetShellEvent(os::SystemEventType *out) override { os::NativeHandle handle; - R_TRY(m_tipc_interface.GetProcessEventHandle(std::addressof(handle))); + R_TRY(m_tipc_interface.GetShellEvent(std::addressof(handle))); os::AttachReadableHandleToSystemEvent(out, handle, true, os::EventClearMode_AutoClear); R_SUCCEED(); } - virtual Result GetProcessEventInfo(pm::ProcessEventInfo *out) override { - R_RETURN(m_tipc_interface.GetProcessEventInfo(ams::tipc::Out(out))); + virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) override { + R_RETURN(m_tipc_interface.GetShellEventInfo(ams::tipc::Out(out))); } }; @@ -112,12 +112,12 @@ namespace ams::pgl { std::swap(m_impl, rhs.m_impl); } public: - Result GetSystemEvent(os::SystemEventType *out) { - R_RETURN(m_impl->GetSystemEvent(out)); + Result GetShellEvent(os::SystemEventType *out) { + R_RETURN(m_impl->GetShellEvent(out)); } - Result GetProcessEventInfo(pm::ProcessEventInfo *out) { - R_RETURN(m_impl->GetProcessEventInfo(out)); + Result GetShellEventInfo(pm::ProcessEventInfo *out) { + R_RETURN(m_impl->GetShellEventInfo(out)); } }; diff --git a/libraries/libstratosphere/include/stratosphere/pgl/pgl_shell_api.hpp b/libraries/libstratosphere/include/stratosphere/pgl/pgl_shell_api.hpp index f61d008e6..e6dbeed31 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/pgl_shell_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/pgl_shell_api.hpp @@ -27,15 +27,15 @@ namespace ams::pgl { Result LaunchProgram(os::ProcessId *out, const ncm::ProgramLocation &loc, u32 process_flags, u8 pgl_flags); Result TerminateProcess(os::ProcessId process_id); Result LaunchProgramFromHost(os::ProcessId *out, const char *content_path, u32 process_flags); - Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *content_path); - Result GetApplicationProcessId(os::ProcessId *out); + Result GetProgramLaunchPropertyFromHost(pgl::ProgramLaunchProperty *out, const char *content_path); + Result GetRunningApplicationProcessId(os::ProcessId *out); Result BoostSystemMemoryResourceLimit(u64 size); - Result IsProcessTracked(bool *out, os::ProcessId process_id); + Result IsRunningProcess(bool *out, os::ProcessId process_id); Result EnableApplicationCrashReport(bool enabled); Result IsApplicationCrashReportEnabled(bool *out); Result EnableApplicationAllThreadDumpOnCrash(bool enabled); - Result TriggerApplicationSnapShotDumper(const char *arg, SnapShotDumpType dump_type); - - Result GetEventObserver(pgl::EventObserver *out); + Result TriggerSnapShotDumper(const char *arg, SnapShotDumpType dump_type); + Result CreateShellEvent(pgl::EventObserver *out); + Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled); } diff --git a/libraries/libstratosphere/include/stratosphere/pgl/pgl_types.hpp b/libraries/libstratosphere/include/stratosphere/pgl/pgl_types.hpp index 25ed20d9c..268c3e6f6 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/pgl_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/pgl_types.hpp @@ -35,8 +35,7 @@ namespace ams::pgl { Full = 2, }; - /* TODO: Is this really nn::ncm::ContentInfo? */ - struct ContentMetaInfo { + struct ProgramLaunchProperty { u64 id; u32 version; ncm::ContentType content_type; @@ -44,7 +43,7 @@ namespace ams::pgl { ncm::ContentMetaType content_meta_type; u8 reserved_0F; - static constexpr ContentMetaInfo Make(u64 id, u32 version, ncm::ContentType content_type, u8 id_offset) { + static constexpr ProgramLaunchProperty Make(u64 id, u32 version, ncm::ContentType content_type, u8 id_offset) { return { .id = id, .version = version, @@ -53,6 +52,6 @@ namespace ams::pgl { }; } }; - static_assert(sizeof(ContentMetaInfo) == 0x10 && util::is_pod::value); + static_assert(sizeof(ProgramLaunchProperty) == 0x10 && util::is_pod::value); } diff --git a/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_event_observer.hpp b/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_event_observer.hpp index 387fb8147..d08ce89bb 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_event_observer.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_event_observer.hpp @@ -21,8 +21,8 @@ #include #define AMS_PGL_SF_I_EVENT_OBSERVER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, GetProcessEventHandle, (ams::sf::OutCopyHandle out), (out)) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, GetProcessEventInfo, (ams::sf::Out out), (out)) + AMS_SF_METHOD_INFO(C, H, 0, Result, GetShellEvent, (ams::sf::OutCopyHandle out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, GetShellEventInfo, (ams::sf::Out out), (out)) AMS_SF_DEFINE_INTERFACE(ams::pgl::sf, IEventObserver, AMS_PGL_SF_I_EVENT_OBSERVER_INTERFACE_INFO, 0x00000000); diff --git a/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_shell_interface.hpp b/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_shell_interface.hpp index bafda6364..405b54650 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_shell_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/sf/pgl_sf_i_shell_interface.hpp @@ -25,16 +25,15 @@ AMS_SF_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::sf::Out out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \ AMS_SF_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \ AMS_SF_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::sf::Out out, const ams::sf::InBuffer &content_path, u32 pm_flags), (out, content_path, pm_flags)) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, GetHostContentMetaInfo, (ams::sf::Out out, const ams::sf::InBuffer &content_path), (out, content_path)) \ - AMS_SF_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, GetProgramLaunchPropertyFromHost, (ams::sf::Out out, const ams::sf::InBuffer &content_path), (out, content_path)) \ + AMS_SF_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::sf::Out out), (out)) \ AMS_SF_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \ - AMS_SF_METHOD_INFO(C, H, 7, Result, IsProcessTracked, (ams::sf::Out out, os::ProcessId process_id), (out, process_id)) \ + AMS_SF_METHOD_INFO(C, H, 7, Result, IsRunningProcess, (ams::sf::Out out, os::ProcessId process_id), (out, process_id)) \ AMS_SF_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \ AMS_SF_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::sf::Out out), (out)) \ AMS_SF_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \ - AMS_SF_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::sf::Out out, ncm::ProgramId program_id), (out, program_id)) \ - AMS_SF_METHOD_INFO(C, H, 12, Result, TriggerApplicationSnapShotDumper, (pgl::SnapShotDumpType dump_type, const ams::sf::InBuffer &arg), (dump_type, arg)) \ - AMS_SF_METHOD_INFO(C, H, 20, Result, GetShellEventObserver, (ams::sf::Out> out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 12, Result, TriggerSnapShotDumper, (pgl::SnapShotDumpType dump_type, const ams::sf::InBuffer &arg), (dump_type, arg), hos::Version_10_0_0) \ + AMS_SF_METHOD_INFO(C, H, 20, Result, CreateShellEvent, (ams::sf::Out> out), (out)) \ AMS_SF_METHOD_INFO(C, H, 21, Result, Command21NotImplemented, (ams::sf::Out out, u32 in, const ams::sf::InBuffer &buf1, const ams::sf::InBuffer &buf2), (out, in, buf1, buf2), hos::Version_11_0_0) AMS_SF_DEFINE_INTERFACE(ams::pgl::sf, IShellInterface, AMS_PGL_I_SHELL_INTERFACE_INTERFACE_INFO, 0x00000000); diff --git a/libraries/libstratosphere/include/stratosphere/pgl/srv/pgl_srv_shell_interface.hpp b/libraries/libstratosphere/include/stratosphere/pgl/srv/pgl_srv_shell_interface.hpp index 9f488b318..a9d534d9e 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/srv/pgl_srv_shell_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/srv/pgl_srv_shell_interface.hpp @@ -30,15 +30,16 @@ namespace ams::pgl::srv { Result LaunchProgramImpl(os::ProcessId *out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags); Result TerminateProcessImpl(os::ProcessId process_id); Result LaunchProgramFromHostImpl(os::ProcessId *out, const void *content_path, size_t content_path_size, u32 pm_flags); - Result GetHostContentMetaInfoImpl(pgl::ContentMetaInfo *out, const void *content_path, size_t content_path_size); - Result GetApplicationProcessIdImpl(os::ProcessId *out); + Result GetProgramLaunchPropertyFromHostImpl(pgl::ProgramLaunchProperty *out, const void *content_path, size_t content_path_size); + Result GetRunningApplicationProcessIdImpl(os::ProcessId *out); Result BoostSystemMemoryResourceLimitImpl(u64 size); - Result IsProcessTrackedImpl(bool *out, os::ProcessId process_id); + Result IsRunningProcessImpl(bool *out, os::ProcessId process_id); Result EnableApplicationCrashReportImpl(bool enabled); Result IsApplicationCrashReportEnabledImpl(bool *out); Result EnableApplicationAllThreadDumpOnCrashImpl(bool enabled); - Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id); - Result TriggerApplicationSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size); + Result GetProcessIdImpl(os::ProcessId *out, ncm::ProgramId program_id); + Result TriggerSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size); + Result EnableApplicationCrashReport2Impl(os::ProcessId process_id, bool enabled); }; class ShellInterfaceCmif : public ShellInterfaceCommon { @@ -56,17 +57,15 @@ namespace ams::pgl::srv { Result LaunchProgram(ams::sf::Out out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags); Result TerminateProcess(os::ProcessId process_id); Result LaunchProgramFromHost(ams::sf::Out out, const ams::sf::InBuffer &content_path, u32 pm_flags); - Result GetHostContentMetaInfo(ams::sf::Out out, const ams::sf::InBuffer &content_path); - Result GetApplicationProcessId(ams::sf::Out out); + Result GetProgramLaunchPropertyFromHost(ams::sf::Out out, const ams::sf::InBuffer &content_path); + Result GetRunningApplicationProcessId(ams::sf::Out out); Result BoostSystemMemoryResourceLimit(u64 size); - Result IsProcessTracked(ams::sf::Out out, os::ProcessId process_id); + Result IsRunningProcess(ams::sf::Out out, os::ProcessId process_id); Result EnableApplicationCrashReport(bool enabled); Result IsApplicationCrashReportEnabled(ams::sf::Out out); Result EnableApplicationAllThreadDumpOnCrash(bool enabled); - Result GetProcessId(ams::sf::Out out, ncm::ProgramId program_id); - Result TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg); - - Result GetShellEventObserver(ams::sf::Out> out); + Result TriggerSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg); + Result CreateShellEvent(ams::sf::Out> out); Result Command21NotImplemented(ams::sf::Out out, u32 in, const ams::sf::InBuffer &buf1, const ams::sf::InBuffer &buf2); }; static_assert(pgl::sf::IsIShellInterface); @@ -81,15 +80,16 @@ namespace ams::pgl::srv { Result LaunchProgram(ams::tipc::Out out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags); Result TerminateProcess(os::ProcessId process_id); Result LaunchProgramFromHost(ams::tipc::Out out, const ams::tipc::InBuffer content_path, u32 pm_flags); - Result GetHostContentMetaInfo(ams::tipc::Out out, const ams::tipc::InBuffer content_path); - Result GetApplicationProcessId(ams::tipc::Out out); + Result GetProgramLaunchPropertyFromHost(ams::tipc::Out out, const ams::tipc::InBuffer content_path); + Result GetRunningApplicationProcessId(ams::tipc::Out out); Result BoostSystemMemoryResourceLimit(u64 size); - Result IsProcessTracked(ams::tipc::Out out, os::ProcessId process_id); + Result IsRunningProcess(ams::tipc::Out out, os::ProcessId process_id); Result EnableApplicationCrashReport(bool enabled); Result IsApplicationCrashReportEnabled(ams::tipc::Out out); Result EnableApplicationAllThreadDumpOnCrash(bool enabled); Result GetProcessId(ams::tipc::Out out, ncm::ProgramId program_id); - Result GetShellEventObserver(ams::tipc::OutMoveHandle out); + Result CreateShellEvent(ams::tipc::OutMoveHandle out); + Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled); }; static_assert(pgl::tipc::IsIShellInterface); diff --git a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp index 2287344c5..7036e9922 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp @@ -22,8 +22,8 @@ #include #define AMS_PGL_TIPC_I_EVENT_OBSERVER_INTERFACE_INFO(C, H) \ - AMS_TIPC_METHOD_INFO(C, H, 0, Result, GetProcessEventHandle, (ams::tipc::OutCopyHandle out), (out)) \ - AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetProcessEventInfo, (ams::tipc::Out out), (out)) + AMS_TIPC_METHOD_INFO(C, H, 0, Result, GetShellEvent, (ams::tipc::OutCopyHandle out), (out)) \ + AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetShellEventInfo, (ams::tipc::Out out), (out)) AMS_TIPC_DEFINE_INTERFACE(ams::pgl::tipc, IEventObserver, AMS_PGL_TIPC_I_EVENT_OBSERVER_INTERFACE_INFO); diff --git a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp index ad61a71e4..d86e0f7d8 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp @@ -22,17 +22,19 @@ #include #include -#define AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \ - AMS_TIPC_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::tipc::Out out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \ - AMS_TIPC_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \ - AMS_TIPC_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::tipc::Out out, const ams::tipc::InBuffer content_path, u32 pm_flags), (out, content_path, pm_flags)) \ - AMS_TIPC_METHOD_INFO(C, H, 4, Result, GetHostContentMetaInfo, (ams::tipc::Out out, const ams::tipc::InBuffer content_path), (out, content_path)) \ - AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::tipc::Out out), (out)) \ - AMS_TIPC_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \ - AMS_TIPC_METHOD_INFO(C, H, 7, Result, IsProcessTracked, (ams::tipc::Out out, os::ProcessId process_id), (out, process_id)) \ - AMS_TIPC_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \ - AMS_TIPC_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::tipc::Out out), (out)) \ - AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \ - AMS_TIPC_METHOD_INFO(C, H, 20, Result, GetShellEventObserver, (ams::tipc::OutMoveHandle out), (out)) +#define AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \ + AMS_TIPC_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::tipc::Out out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags), (out, loc, pm_flags, pgl_flags)) \ + AMS_TIPC_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \ + AMS_TIPC_METHOD_INFO(C, H, 2, Result, LaunchProgramFromHost, (ams::tipc::Out out, const ams::tipc::InBuffer content_path, u32 pm_flags), (out, content_path, pm_flags)) \ + AMS_TIPC_METHOD_INFO(C, H, 4, Result, GetProgramLaunchPropertyFromHost, (ams::tipc::Out out, const ams::tipc::InBuffer content_path), (out, content_path)) \ + AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::tipc::Out out), (out)) \ + AMS_TIPC_METHOD_INFO(C, H, 6, Result, BoostSystemMemoryResourceLimit, (u64 size), (size)) \ + AMS_TIPC_METHOD_INFO(C, H, 7, Result, IsRunningProcess, (ams::tipc::Out out, os::ProcessId process_id), (out, process_id)) \ + AMS_TIPC_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \ + AMS_TIPC_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::tipc::Out out), (out)) \ + AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \ + AMS_TIPC_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::sf::Out out, ncm::ProgramId program_id), (out, program_id), hos::Version_19_0_0) \ + AMS_TIPC_METHOD_INFO(C, H, 20, Result, CreateShellEvent, (ams::tipc::OutMoveHandle out), (out)) \ + AMS_TIPC_METHOD_INFO(C, H, 31, Result, EnableApplicationCrashReport2, (os::ProcessId process_id, bool enabled), (process_id, enabled), hos::Version_23_0_0) AMS_TIPC_DEFINE_INTERFACE(ams::pgl::tipc, IShellInterface, AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO); diff --git a/libraries/libstratosphere/source/pgl/pgl_remote_event_observer.hpp b/libraries/libstratosphere/source/pgl/pgl_remote_event_observer.hpp index 96f45f6eb..b31a3fc5e 100644 --- a/libraries/libstratosphere/source/pgl/pgl_remote_event_observer.hpp +++ b/libraries/libstratosphere/source/pgl/pgl_remote_event_observer.hpp @@ -30,28 +30,28 @@ namespace ams::pgl { ::pglEventObserverClose(std::addressof(m_observer)); } - Result GetProcessEventHandle(ams::sf::OutCopyHandle out) { + Result GetShellEvent(ams::sf::OutCopyHandle out) { ::Event ev; ON_RESULT_SUCCESS { out.SetValue(ev.revent, true); }; - R_RETURN(::pglEventObserverGetProcessEvent(std::addressof(m_observer), std::addressof(ev))); + R_RETURN(::pglEventObserverGetShellEvent(std::addressof(m_observer), std::addressof(ev))); } - Result GetProcessEventInfo(ams::sf::Out out) { + Result GetShellEventInfo(ams::sf::Out out) { static_assert(sizeof(*out.GetPointer()) == sizeof(::PmProcessEventInfo)); - R_RETURN(::pglEventObserverGetProcessEventInfo(std::addressof(m_observer), reinterpret_cast<::PmProcessEventInfo *>(out.GetPointer()))); + R_RETURN(::pglEventObserverGetShellEventInfo(std::addressof(m_observer), reinterpret_cast<::PmProcessEventInfo *>(out.GetPointer()))); } - Result GetProcessEventHandle(ams::tipc::OutCopyHandle out) { + Result GetShellEvent(ams::tipc::OutCopyHandle out) { ::Event ev; ON_RESULT_SUCCESS { out.SetValue(ev.revent); }; - R_RETURN(::pglEventObserverGetProcessEvent(std::addressof(m_observer), std::addressof(ev))); + R_RETURN(::pglEventObserverGetShellEvent(std::addressof(m_observer), std::addressof(ev))); } - Result GetProcessEventInfo(ams::tipc::Out out) { + Result GetShellEventInfo(ams::tipc::Out out) { static_assert(sizeof(*out.GetPointer()) == sizeof(::PmProcessEventInfo)); - R_RETURN(::pglEventObserverGetProcessEventInfo(std::addressof(m_observer), reinterpret_cast<::PmProcessEventInfo *>(out.GetPointer()))); + R_RETURN(::pglEventObserverGetShellEventInfo(std::addressof(m_observer), reinterpret_cast<::PmProcessEventInfo *>(out.GetPointer()))); } }; static_assert(pgl::sf::IsIEventObserver); diff --git a/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp b/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp index 8bbd0da0b..4b87961ff 100644 --- a/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp +++ b/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp @@ -80,22 +80,22 @@ namespace ams::pgl { R_RETURN(::pglLaunchProgramFromHost(reinterpret_cast(out), content_path, process_flags)); } - Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *content_path) { - static_assert(sizeof(*out) == sizeof(::PglContentMetaInfo)); - R_RETURN(::pglGetHostContentMetaInfo(reinterpret_cast<::PglContentMetaInfo *>(out), content_path)); + Result GetHostProgramLaunchProperty(pgl::ProgramLaunchProperty *out, const char *content_path) { + static_assert(sizeof(*out) == sizeof(::PglProgramLaunchProperty)); + R_RETURN(::pglGetHostProgramLaunchProperty(reinterpret_cast<::PglProgramLaunchProperty *>(out), content_path)); } - Result GetApplicationProcessId(os::ProcessId *out) { + Result GetRunningApplicationProcessId(os::ProcessId *out) { static_assert(sizeof(*out) == sizeof(u64)); - R_RETURN(::pglGetApplicationProcessId(reinterpret_cast(out))); + R_RETURN(::pglGetRunningApplicationProcessId(reinterpret_cast(out))); } Result BoostSystemMemoryResourceLimit(u64 size) { R_RETURN(::pglBoostSystemMemoryResourceLimit(size)); } - Result IsProcessTracked(bool *out, os::ProcessId process_id) { - R_RETURN(::pglIsProcessTracked(out, static_cast(process_id))); + Result IsRunningProcess(bool *out, os::ProcessId process_id) { + R_RETURN(::pglIsRunningProcess(out, static_cast(process_id))); } Result EnableApplicationCrashReport(bool enabled) { @@ -110,13 +110,13 @@ namespace ams::pgl { R_RETURN(::pglEnableApplicationAllThreadDumpOnCrash(enabled)); } - Result TriggerApplicationSnapShotDumper(const char *arg, SnapShotDumpType dump_type) { - R_RETURN(::pglTriggerApplicationSnapShotDumper(static_cast<::PglSnapShotDumpType>(dump_type), arg)); + Result TriggerSnapShotDumper(const char *arg, SnapShotDumpType dump_type) { + R_RETURN(::pglTriggerSnapShotDumper(static_cast<::PglSnapShotDumpType>(dump_type), arg)); } - Result GetEventObserver(pgl::EventObserver *out) { + Result CreateShellEvent(pgl::EventObserver *out) { ::PglEventObserver obs; - R_TRY(::pglGetEventObserver(std::addressof(obs))); + R_TRY(::pglCreateShellEvent(std::addressof(obs))); if (hos::GetVersion() >= hos::Version_12_0_0) { auto observer_holder = MakeUniqueFromStaticExpHeap>(obs); @@ -135,6 +135,10 @@ namespace ams::pgl { R_SUCCEED(); } + + Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { + R_RETURN(::pglEnableApplicationCrashReport2(process_id, enabled)); + } #else Result Initialize() { AMS_ABORT("TODO"); @@ -159,12 +163,12 @@ namespace ams::pgl { AMS_ABORT("TODO"); } - Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *content_path) { + Result GetHostProgramLaunchProperty(pgl::ProgramLaunchProperty *out, const char *content_path) { AMS_UNUSED(out, content_path); AMS_ABORT("TODO"); } - Result GetApplicationProcessId(os::ProcessId *out) { + Result GetRunningApplicationProcessId(os::ProcessId *out) { AMS_UNUSED(out); AMS_ABORT("TODO"); } @@ -174,7 +178,7 @@ namespace ams::pgl { AMS_ABORT("TODO"); } - Result IsProcessTracked(bool *out, os::ProcessId process_id) { + Result IsRunningProcess(bool *out, os::ProcessId process_id) { AMS_UNUSED(out, process_id); AMS_ABORT("TODO"); } @@ -194,15 +198,20 @@ namespace ams::pgl { AMS_ABORT("TODO"); } - Result TriggerApplicationSnapShotDumper(const char *arg, SnapShotDumpType dump_type) { + Result TriggerSnapShotDumper(const char *arg, SnapShotDumpType dump_type) { AMS_UNUSED(arg, dump_type); AMS_ABORT("TODO"); } - Result GetEventObserver(pgl::EventObserver *out) { + Result CreateShellEvent(pgl::EventObserver *out) { AMS_UNUSED(out); AMS_ABORT("TODO"); } + + Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { + AMS_UNUSED(process_id, enabled); + AMS_ABORT("TODO"); + } #endif } \ No newline at end of file diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp index 577f59560..7178e3a29 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp @@ -85,7 +85,7 @@ namespace ams::pgl::srv { } } - util::optional GetRunningApplicationProcessId() { + util::optional GetRunningApplicationProcessIdInternal() { os::ProcessId process_id; if (R_SUCCEEDED(pm::shell::GetApplicationProcessIdForShell(std::addressof(process_id)))) { return process_id; @@ -403,9 +403,9 @@ namespace ams::pgl::srv { R_RETURN(pm::shell::TerminateProcess(process_id)); } - Result GetApplicationProcessId(os::ProcessId *out) { - /* Get the application process id. */ - auto application_process_id = GetRunningApplicationProcessId(); + Result GetRunningApplicationProcessId(os::ProcessId *out) { + /* Get the running application process id. */ + auto application_process_id = GetRunningApplicationProcessIdInternal(); R_UNLESS(application_process_id, pgl::ResultApplicationNotRunning()); /* Return the id. */ @@ -418,7 +418,7 @@ namespace ams::pgl::srv { R_RETURN(pm::shell::BoostSystemMemoryResourceLimit(size)); } - bool IsProcessTracked(os::ProcessId process_id) { + bool IsRunningProcess(os::ProcessId process_id) { /* Check whether a ProcessData exists for the process. */ std::scoped_lock lk(g_process_data_mutex); return FindProcessData(process_id) != nullptr; @@ -426,7 +426,7 @@ namespace ams::pgl::srv { void EnableApplicationCrashReport(bool enabled) { /* Get the application process id. */ - auto application_process_id = GetRunningApplicationProcessId(); + auto application_process_id = GetRunningApplicationProcessIdInternal(); if (application_process_id) { /* Find the data for the application process. */ std::scoped_lock lk(g_process_data_mutex); @@ -446,7 +446,7 @@ namespace ams::pgl::srv { bool IsApplicationCrashReportEnabled() { /* Get the application process id. */ - auto application_process_id = GetRunningApplicationProcessId(); + auto application_process_id = GetRunningApplicationProcessIdInternal(); if (!application_process_id) { return false; } @@ -462,7 +462,7 @@ namespace ams::pgl::srv { void EnableApplicationAllThreadDumpOnCrash(bool enabled) { /* Get the application process id. */ - auto application_process_id = GetRunningApplicationProcessId(); + auto application_process_id = GetRunningApplicationProcessIdInternal(); if (application_process_id) { /* Find the data for the application process. */ std::scoped_lock lk(g_process_data_mutex); @@ -486,7 +486,7 @@ namespace ams::pgl::srv { } } - Result TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const char *arg) { + Result TriggerSnapShotDumper(SnapShotDumpType dump_type, const char *arg) { /* Try to get the application process id. */ os::ProcessId process_id; R_TRY(pm::shell::GetApplicationProcessIdForShell(std::addressof(process_id))); @@ -495,5 +495,21 @@ namespace ams::pgl::srv { ON_SCOPE_EXIT { g_ssd_process_id = os::InvalidProcessId; }; R_RETURN(TriggerSnapShotDumper(process_id, dump_type, arg)); } + + void EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { + /* Find the data for the process. */ + std::scoped_lock lk(g_process_data_mutex); + ProcessData *data = FindProcessData(*process_id); + /* It's okay if we aren't tracking the process. */ + if (data != nullptr) { + /* Set or clear the flag. */ + if (enabled) { + data->flags |= ProcessDataFlag_DetailedCrashReportEnabled; + } else { + data->flags &= ~ProcessDataFlag_DetailedCrashReportEnabled; + } + } + } + } diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.hpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.hpp index 11228d78a..b4001e4ab 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.hpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.hpp @@ -27,12 +27,13 @@ namespace ams::pgl::srv { Result LaunchProgram(os::ProcessId *out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags); Result TerminateProcess(os::ProcessId process_id); - Result GetApplicationProcessId(os::ProcessId *out); + Result GetRunningApplicationProcessId(os::ProcessId *out); Result BoostSystemMemoryResourceLimit(u64 size); - bool IsProcessTracked(os::ProcessId process_id); + bool IsRunningProcess(os::ProcessId process_id); void EnableApplicationCrashReport(bool enabled); bool IsApplicationCrashReportEnabled(); void EnableApplicationAllThreadDumpOnCrash(bool enabled); - Result TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const char *arg); + Result TriggerSnapShotDumper(SnapShotDumpType dump_type, const char *arg); + void EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled); } diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.cpp index 047123d36..e60712816 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.cpp @@ -65,21 +65,21 @@ namespace ams::pgl::srv { m_event.Signal(); } - Result ShellEventObserverCmif::GetProcessEventHandle(ams::sf::OutCopyHandle out) { + Result ShellEventObserverCmif::GetShellEvent(ams::sf::OutCopyHandle out) { out.SetValue(this->GetEvent().GetReadableHandle(), false); R_SUCCEED(); } - Result ShellEventObserverCmif::GetProcessEventInfo(ams::sf::Out out) { + Result ShellEventObserverCmif::GetShellEventInfo(ams::sf::Out out) { R_RETURN(this->PopEventInfo(out.GetPointer())); } - Result ShellEventObserverTipc::GetProcessEventHandle(ams::tipc::OutCopyHandle out) { + Result ShellEventObserverTipc::GetShellEvent(ams::tipc::OutCopyHandle out) { out.SetValue(this->GetEvent().GetReadableHandle()); R_SUCCEED(); } - Result ShellEventObserverTipc::GetProcessEventInfo(ams::tipc::Out out) { + Result ShellEventObserverTipc::GetShellEventInfo(ams::tipc::Out out) { R_RETURN(this->PopEventInfo(out.GetPointer())); } diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.hpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.hpp index 8fc52d0ed..d55163af1 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.hpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_event_observer.hpp @@ -60,15 +60,15 @@ namespace ams::pgl::srv { class ShellEventObserverCmif : public ShellEventObserverImpl { public: - Result GetProcessEventHandle(ams::sf::OutCopyHandle out); - Result GetProcessEventInfo(ams::sf::Out out); + Result GetShellEvent(ams::sf::OutCopyHandle out); + Result GetShellEventInfo(ams::sf::Out out); }; static_assert(pgl::sf::IsIEventObserver); class ShellEventObserverTipc : public ShellEventObserverImpl { public: - Result GetProcessEventHandle(ams::tipc::OutCopyHandle out); - Result GetProcessEventInfo(ams::tipc::Out out); + Result GetShellEvent(ams::tipc::OutCopyHandle out); + Result GetShellEventInfo(ams::tipc::Out out); }; static_assert(pgl::tipc::IsIEventObserver); diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.cpp index 720ff476a..0cb14b620 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.cpp @@ -335,7 +335,7 @@ namespace ams::pgl::srv { R_RETURN(pgl::srv::LaunchProgram(out, ncm::ProgramLocation::Make(reader.GetProgramId(), ncm::StorageId::Host), pm_flags, pgl::LaunchFlags_None)); } - Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *package_path) { + Result GetProgramLaunchPropertyFromHost(pgl::ProgramLaunchProperty *out, const char *package_path) { /* Read the package. */ HostPackageReader reader; R_TRY(reader.Initialize(package_path, HostPackageMountName)); @@ -343,7 +343,7 @@ namespace ams::pgl::srv { /* Read the program info. */ R_TRY(reader.ReadProgramInfo()); - /* Get the content meta info. */ + /* Get the program launch property. */ *out = { .id = reader.GetProgramId().value, .version = reader.GetProgramVersion(), diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.hpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.hpp index 263f813b7..d09755fb9 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.hpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_host_utils.hpp @@ -19,6 +19,6 @@ namespace ams::pgl::srv { Result LaunchProgramFromHost(os::ProcessId *out, const char *content_path, u32 pm_flags); - Result GetHostContentMetaInfo(pgl::ContentMetaInfo *out, const char *content_path); + Result GetProgramLaunchPropertyFromHost(pgl::ProgramLaunchProperty *out, const char *content_path); } diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_interface.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_interface.cpp index f6c018bf0..63a53f892 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_interface.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell_interface.cpp @@ -34,21 +34,21 @@ namespace ams::pgl::srv { R_RETURN(pgl::srv::LaunchProgramFromHost(out, static_cast(content_path), pm_flags)); } - Result ShellInterfaceCommon::GetHostContentMetaInfoImpl(pgl::ContentMetaInfo *out, const void *content_path, size_t content_path_size) { + Result ShellInterfaceCommon::GetProgramLaunchPropertyFromHostImpl(pgl::ProgramLaunchProperty *out, const void *content_path, size_t content_path_size) { AMS_UNUSED(content_path_size); - R_RETURN(pgl::srv::GetHostContentMetaInfo(out, static_cast(content_path))); + R_RETURN(pgl::srv::GetProgramLaunchPropertyFromHost(out, static_cast(content_path))); } - Result ShellInterfaceCommon::GetApplicationProcessIdImpl(os::ProcessId *out) { - R_RETURN(pgl::srv::GetApplicationProcessId(out)); + Result ShellInterfaceCommon::GetRunningApplicationProcessIdImpl(os::ProcessId *out) { + R_RETURN(pgl::srv::GetRunningApplicationProcessId(out)); } Result ShellInterfaceCommon::BoostSystemMemoryResourceLimitImpl(u64 size) { R_RETURN(pgl::srv::BoostSystemMemoryResourceLimit(size)); } - Result ShellInterfaceCommon::IsProcessTrackedImpl(bool *out, os::ProcessId process_id) { - *out = pgl::srv::IsProcessTracked(process_id); + Result ShellInterfaceCommon::IsRunningProcessImpl(bool *out, os::ProcessId process_id) { + *out = pgl::srv::IsRunningProcess(process_id); R_SUCCEED(); } @@ -67,13 +67,18 @@ namespace ams::pgl::srv { R_SUCCEED(); } - Result ShellInterfaceCommon::GetProcessId(os::ProcessId *out, ncm::ProgramId program_id) { + Result ShellInterfaceCommon::GetProcessIdImpl(os::ProcessId *out, ncm::ProgramId program_id) { R_RETURN(pm::shell::GetProcessId(out, program_id)); } - Result ShellInterfaceCommon::TriggerApplicationSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size) { + Result ShellInterfaceCommon::TriggerSnapShotDumperImpl(SnapShotDumpType dump_type, const void *arg, size_t arg_size) { AMS_UNUSED(arg_size); - R_RETURN(pgl::srv::TriggerApplicationSnapShotDumper(dump_type, static_cast(arg))); + R_RETURN(pgl::srv::TriggerSnapShotDumper(dump_type, static_cast(arg))); + } + + Result ShellInterfaceCommon::EnableApplicationCrashReport2Impl(os::ProcessId process_id, bool enabled) { + pgl::srv::EnableApplicationCrashReport2(process_id, enabled); + R_SUCCEED(); } Result ShellInterfaceCmif::LaunchProgram(ams::sf::Out out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags) { @@ -88,20 +93,20 @@ namespace ams::pgl::srv { R_RETURN(this->LaunchProgramFromHostImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize(), pm_flags)); } - Result ShellInterfaceCmif::GetHostContentMetaInfo(ams::sf::Out out, const ams::sf::InBuffer &content_path) { - R_RETURN(this->GetHostContentMetaInfoImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize())); + Result ShellInterfaceCmif::GetProgramLaunchPropertyFromHost(ams::sf::Out out, const ams::sf::InBuffer &content_path) { + R_RETURN(this->GetProgramLaunchPropertyFromHostImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize())); } - Result ShellInterfaceCmif::GetApplicationProcessId(ams::sf::Out out) { - R_RETURN(this->GetApplicationProcessIdImpl(out.GetPointer())); + Result ShellInterfaceCmif::GetRunningApplicationProcessId(ams::sf::Out out) { + R_RETURN(this->GetRunningApplicationProcessIdImpl(out.GetPointer())); } Result ShellInterfaceCmif::BoostSystemMemoryResourceLimit(u64 size) { R_RETURN(this->BoostSystemMemoryResourceLimitImpl(size)); } - Result ShellInterfaceCmif::IsProcessTracked(ams::sf::Out out, os::ProcessId process_id) { - R_RETURN(this->IsProcessTrackedImpl(out.GetPointer(), process_id)); + Result ShellInterfaceCmif::IsRunningProcess(ams::sf::Out out, os::ProcessId process_id) { + R_RETURN(this->IsRunningProcessImpl(out.GetPointer(), process_id)); } Result ShellInterfaceCmif::EnableApplicationCrashReport(bool enabled) { @@ -116,15 +121,11 @@ namespace ams::pgl::srv { R_RETURN(this->EnableApplicationAllThreadDumpOnCrashImpl(enabled)); } - Result ShellInterfaceCmif::TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg) { - R_RETURN(this->TriggerApplicationSnapShotDumperImpl(dump_type, arg.GetPointer(), arg.GetSize())); + Result ShellInterfaceCmif::TriggerSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg) { + R_RETURN(this->TriggerSnapShotDumperImpl(dump_type, arg.GetPointer(), arg.GetSize())); } - Result ShellInterfaceCmif::GetProcessId(ams::sf::Out out, ncm::ProgramId program_id) { - R_RETURN(ShellInterfaceCommon::GetProcessId(out.GetPointer(), program_id)); - } - - Result ShellInterfaceCmif::GetShellEventObserver(ams::sf::Out> out) { + Result ShellInterfaceCmif::CreateShellEvent(ams::sf::Out> out) { /* Allocate a new interface. */ auto session = ObjectFactory::CreateSharedEmplaced(m_allocator); R_UNLESS(session != nullptr, pgl::ResultOutOfMemory()); @@ -150,20 +151,20 @@ namespace ams::pgl::srv { R_RETURN(this->LaunchProgramFromHostImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize(), pm_flags)); } - Result ShellInterfaceTipc::GetHostContentMetaInfo(ams::tipc::Out out, const ams::tipc::InBuffer content_path) { - R_RETURN(this->GetHostContentMetaInfoImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize())); + Result ShellInterfaceTipc::GetProgramLaunchPropertyFromHost(ams::tipc::Out out, const ams::tipc::InBuffer content_path) { + R_RETURN(this->GetProgramLaunchPropertyFromHostImpl(out.GetPointer(), content_path.GetPointer(), content_path.GetSize())); } - Result ShellInterfaceTipc::GetApplicationProcessId(ams::tipc::Out out) { - R_RETURN(this->GetApplicationProcessIdImpl(out.GetPointer())); + Result ShellInterfaceTipc::GetRunningApplicationProcessId(ams::tipc::Out out) { + R_RETURN(this->GetRunningApplicationProcessIdImpl(out.GetPointer())); } Result ShellInterfaceTipc::BoostSystemMemoryResourceLimit(u64 size) { R_RETURN(this->BoostSystemMemoryResourceLimitImpl(size)); } - Result ShellInterfaceTipc::IsProcessTracked(ams::tipc::Out out, os::ProcessId process_id) { - R_RETURN(this->IsProcessTrackedImpl(out.GetPointer(), process_id)); + Result ShellInterfaceTipc::IsRunningProcess(ams::tipc::Out out, os::ProcessId process_id) { + R_RETURN(this->IsRunningProcessImpl(out.GetPointer(), process_id)); } Result ShellInterfaceTipc::EnableApplicationCrashReport(bool enabled) { @@ -179,11 +180,14 @@ namespace ams::pgl::srv { } Result ShellInterfaceTipc::GetProcessId(ams::tipc::Out out, ncm::ProgramId program_id) { - R_RETURN(ShellInterfaceCommon::GetProcessId(out.GetPointer(), program_id)); + R_RETURN(this->GetProcessIdImpl(out.GetPointer(), program_id)); } - Result ShellInterfaceTipc::GetShellEventObserver(ams::tipc::OutMoveHandle out) { + Result ShellInterfaceTipc::CreateShellEvent(ams::tipc::OutMoveHandle out) { R_RETURN(pgl::srv::AllocateShellEventObserverForTipc(out.GetPointer())); } - + + Result ShellInterfaceTipc::EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { + R_RETURN(this->EnableApplicationCrashReport2Impl(process_id, enabled)); + } } From 092f451c3391d39fd7caf30296ec4a680befb4cf Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 15 Sep 2026 22:26:03 +0100 Subject: [PATCH 18/52] pgl: fix bad copy paste --- .../stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp index d86e0f7d8..02c54738a 100644 --- a/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/pgl/tipc/pgl_tipc_i_shell_interface.hpp @@ -33,7 +33,7 @@ AMS_TIPC_METHOD_INFO(C, H, 8, Result, EnableApplicationCrashReport, (bool enabled), (enabled)) \ AMS_TIPC_METHOD_INFO(C, H, 9, Result, IsApplicationCrashReportEnabled, (ams::tipc::Out out), (out)) \ AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \ - AMS_TIPC_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::sf::Out out, ncm::ProgramId program_id), (out, program_id), hos::Version_19_0_0) \ + AMS_TIPC_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::tipc::Out out, ncm::ProgramId program_id), (out, program_id), hos::Version_19_0_0) \ AMS_TIPC_METHOD_INFO(C, H, 20, Result, CreateShellEvent, (ams::tipc::OutMoveHandle out), (out)) \ AMS_TIPC_METHOD_INFO(C, H, 31, Result, EnableApplicationCrashReport2, (os::ProcessId process_id, bool enabled), (process_id, enabled), hos::Version_23_0_0) From b7048ec59529a1fa1f753681cbdfae92082813d1 Mon Sep 17 00:00:00 2001 From: Alula Date: Wed, 16 Sep 2026 05:30:17 +0200 Subject: [PATCH 19/52] kern: fix kthread constinit --- libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index 7e294473c..f6193dd71 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -353,7 +353,7 @@ namespace ams::kern { m_wait_result{svc::ResultNoSynchronizationObject()}, m_debug_exception_result{ResultSuccess()}, m_base_priority{}, m_base_priority_on_unpin{}, m_physical_ideal_core_id{}, m_virtual_ideal_core_id{}, m_num_kernel_waiters{}, m_current_core_id{}, m_core_id{}, m_original_physical_affinity_mask{}, m_original_physical_ideal_core_id{}, m_num_core_migration_disables{}, m_thread_state{}, m_termination_requested{false}, m_wait_cancelled{}, - m_cancellable{}, m_signaled{}, m_initialized{}, m_debug_attached{}, m_priority_inheritance_count{}, m_resource_limit_release_hint{} + m_cancellable{}, m_signaled{}, m_initialized{}, m_debug_attached{}, m_priority_inheritance_count{}, m_resource_limit_release_hint{}, m_debug_unknown5{} { /* ... */ } From afff8cbf16c4e737d19b439d4e194e38490548ed Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 00:28:26 +0100 Subject: [PATCH 20/52] erpt: use the AMS_UNUSED macro --- .../libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp | 2 +- .../source/erpt/srv/erpt_srv_journal_for_attachments.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp index 3f57c4c4e..43d32e9b5 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_context_impl.cpp @@ -90,7 +90,7 @@ namespace ams::erpt::srv { util::Strlcpy(name_safe, name, sizeof(name_safe)); /* NOTE: This is tested, but goes unused and is never passed to JournalForAttachments. */ - (void)unk; + AMS_UNUSED(unk); R_RETURN(JournalForAttachments::SubmitAttachment(out.GetPointer(), name_safe, data, data_size, lz4_compression)); } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp index 36cfe98c6..762d15e3f 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp @@ -188,7 +188,7 @@ namespace ams::erpt::srv { Result JournalForAttachments::SubmitAttachment(AttachmentId *out, char *name, const u8 *data, u32 data_size, bool lz4_compression) { /* TODO: Implement LZ4 compression on attachments. */ - (void)lz4_compression; + AMS_UNUSED(lz4_compression); R_UNLESS(data_size > 0, erpt::ResultInvalidArgument()); R_UNLESS(data_size < AttachmentSizeMax, erpt::ResultInvalidArgument()); From 7cc625946eb9c097bcee85902c4284ee56e89125 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 00:30:00 +0100 Subject: [PATCH 21/52] pgl: add missing changes and fix bugs --- libraries/libstratosphere/source/pgl/pgl_shell_api.cpp | 2 +- libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp | 2 +- libraries/libstratosphere/source/scs/scs_shell.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp b/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp index 4b87961ff..336fcac91 100644 --- a/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp +++ b/libraries/libstratosphere/source/pgl/pgl_shell_api.cpp @@ -137,7 +137,7 @@ namespace ams::pgl { } Result EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { - R_RETURN(::pglEnableApplicationCrashReport2(process_id, enabled)); + R_RETURN(::pglEnableApplicationCrashReport2(static_cast(process_id), enabled)); } #else Result Initialize() { diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp index 7178e3a29..2fff47715 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp @@ -499,7 +499,7 @@ namespace ams::pgl::srv { void EnableApplicationCrashReport2(os::ProcessId process_id, bool enabled) { /* Find the data for the process. */ std::scoped_lock lk(g_process_data_mutex); - ProcessData *data = FindProcessData(*process_id); + ProcessData *data = FindProcessData(process_id); /* It's okay if we aren't tracking the process. */ if (data != nullptr) { diff --git a/libraries/libstratosphere/source/scs/scs_shell.cpp b/libraries/libstratosphere/source/scs/scs_shell.cpp index 841b36e41..89794ce61 100644 --- a/libraries/libstratosphere/source/scs/scs_shell.cpp +++ b/libraries/libstratosphere/source/scs/scs_shell.cpp @@ -279,11 +279,11 @@ namespace ams::scs { void EventHandlerThread(void *) { /* Get event observer. */ pgl::EventObserver observer; - R_ABORT_UNLESS(pgl::GetEventObserver(std::addressof(observer))); + R_ABORT_UNLESS(pgl::CreateShellEvent(std::addressof(observer))); /* Get the observer's event. */ os::SystemEventType shell_event; - R_ABORT_UNLESS(observer.GetSystemEvent(std::addressof(shell_event))); + R_ABORT_UNLESS(observer.GetShellEvent(std::addressof(shell_event))); /* Loop handling events. */ while (true) { @@ -294,7 +294,7 @@ namespace ams::scs { while (true) { /* Get the next event info. */ pm::ProcessEventInfo event_info; - if (R_FAILED(observer.GetProcessEventInfo(std::addressof(event_info)))) { + if (R_FAILED(observer.GetShellEventInfo(std::addressof(event_info)))) { break; } From 98d64c28d87112cb973d2364cc3ef38567c6dc8b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 00:34:00 +0100 Subject: [PATCH 22/52] sprofile: clean up and update for 23.0.0 --- .../stratosphere/sprofile/sprofile_types.hpp | 10 +-- ...ile_srv_i_profile_controller_for_debug.hpp | 6 +- .../srv/sprofile_srv_i_profile_importer.hpp | 6 +- .../srv/sprofile_srv_i_profile_reader.hpp | 18 +++-- ...sprofile_srv_i_profile_update_observer.hpp | 6 +- .../sprofile_srv_i_service_for_bg_agent.hpp | 10 +-- ..._srv_profile_controller_for_debug_impl.cpp | 12 +++- ..._srv_profile_controller_for_debug_impl.hpp | 5 +- .../srv/sprofile_srv_profile_importer.hpp | 34 +++++----- .../sprofile_srv_profile_importer_impl.cpp | 4 +- .../sprofile_srv_profile_importer_impl.hpp | 4 +- .../srv/sprofile_srv_profile_manager.cpp | 49 +++++++------ .../srv/sprofile_srv_profile_manager.hpp | 20 +++--- .../srv/sprofile_srv_profile_reader_impl.cpp | 68 ++++++++++++++++--- .../srv/sprofile_srv_profile_reader_impl.hpp | 18 +++-- ...ofile_srv_profile_update_observer_impl.hpp | 12 ++-- .../srv/sprofile_srv_service_for_bg_agent.cpp | 8 +-- .../srv/sprofile_srv_service_for_bg_agent.hpp | 6 +- .../sprofile/srv/sprofile_srv_types.hpp | 50 +++++++------- .../vapours/results/sprofile_results.hpp | 25 ++++--- 20 files changed, 225 insertions(+), 146 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/sprofile/sprofile_types.hpp b/libraries/libstratosphere/include/stratosphere/sprofile/sprofile_types.hpp index 362a823cd..3fa6a84a8 100644 --- a/libraries/libstratosphere/include/stratosphere/sprofile/sprofile_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/sprofile/sprofile_types.hpp @@ -18,18 +18,18 @@ namespace ams::sprofile { - struct Identifier { + struct HashKey { u8 data[7]; - friend bool operator==(const Identifier &lhs, const Identifier &rhs) { + friend bool operator==(const HashKey &lhs, const HashKey &rhs) { return std::memcmp(lhs.data, rhs.data, sizeof(lhs.data)) == 0; } - friend bool operator!=(const Identifier &lhs, const Identifier &rhs) { + friend bool operator!=(const HashKey &lhs, const HashKey &rhs) { return !(lhs == rhs); } }; - static_assert(sizeof(Identifier) == 7); - static_assert(util::is_pod::value); + static_assert(sizeof(HashKey) == 7); + static_assert(util::is_pod::value); } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_controller_for_debug.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_controller_for_debug.hpp index 7d51c7df2..4713e7894 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_controller_for_debug.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_controller_for_debug.hpp @@ -17,8 +17,8 @@ #include #define AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ()) \ - AMS_SF_METHOD_INFO(C, H, 2001, Result, GetRaw, (sf::Out out_type, sf::Out out_value, sprofile::Identifier profile, sprofile::Identifier key), (out_type, out_value, profile, key)) - + AMS_SF_METHOD_INFO(C, H, 2000, Result, ClearSaveData, (), ()) \ + AMS_SF_METHOD_INFO(C, H, 2001, Result, QueryValue, (sf::Out out_type, sf::Out out_value, sprofile::HashKey profile, sprofile::HashKey key), (out_type, out_value, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 2002, Result, QueryValueArray, (sf::Out out_type, sf::Out out_count, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out_type, out_count, out_buffer, profile, key), hos::Version_23_0_0) AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileControllerForDebug, AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO, 0xA8C14F64) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_importer.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_importer.hpp index 8d0c2b32b..5c07e9b81 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_importer.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_importer.hpp @@ -18,8 +18,8 @@ #include "sprofile_srv_types.hpp" #define AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, ImportProfile, (const sprofile::srv::ProfileDataForImportData &import), (import)) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, Commit, (), ()) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, ImportMetadata, (const sprofile::srv::ProfileMetadataForImportMetadata &import), (import)) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, ImportProfile, (const sprofile::srv::ProfilePayload &import), (import)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, Commit, (), (), hos::Version_13_0_0, hos::Version_22_5_0) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, ImportMetadata, (const sprofile::srv::MetadataPayload &import), (import), hos::Version_13_0_0, hos::Version_22_5_0) AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileImporter, AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO, 0x1629C4E6) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_reader.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_reader.hpp index e9a48faae..699c99a63 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_reader.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_reader.hpp @@ -17,10 +17,18 @@ #include #define AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, GetSigned64, (sf::Out out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, GetUnsigned64, (sf::Out out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, GetSigned32, (sf::Out out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \ - AMS_SF_METHOD_INFO(C, H, 3, Result, GetUnsigned32, (sf::Out out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, GetByte, (sf::Out out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) + AMS_SF_METHOD_INFO(C, H, 0, Result, GetInt64Value, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, GetUInt64Value, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, GetInt32Value, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetUInt32Value, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, GetBooleanValue, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key)) \ + AMS_SF_METHOD_INFO(C, H, 5, Result, GetAnyValue, (sf::Out out, sprofile::HashKey profile, sprofile::HashKey key), (out, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 6, Result, GetInt8ValueArray, (sf::Out out, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 7, Result, GetInt64ValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 8, Result, GetUInt64ValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 9, Result, GetInt32ValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 10, Result, GetUInt32ValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 11, Result, GetUInt8ValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 12, Result, GetAnyValueArray, (sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key), (out, out_buffer, profile, key), hos::Version_23_0_0) AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileReader, AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO, 0x97090D4D) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_update_observer.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_update_observer.hpp index ab68ad3bf..1f5b1d6fa 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_update_observer.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_profile_update_observer.hpp @@ -17,8 +17,8 @@ #include #define AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, Listen, (sprofile::Identifier profile), (profile)) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, Unlisten, (sprofile::Identifier profile), (profile)) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, GetEventHandle, (ams::sf::OutCopyHandle out), (out)) + AMS_SF_METHOD_INFO(C, H, 0, Result, Subscribe, (sprofile::HashKey profile), (profile)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, Unsubscribe, (sprofile::HashKey profile), (profile)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, GetUpdateEventNativeHandle, (ams::sf::OutCopyHandle out), (out)) AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileUpdateObserver, AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO, 0xB52A765C) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp index 5edce1d7d..e0f86adca 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_i_service_for_bg_agent.hpp @@ -17,10 +17,10 @@ #include #include "sprofile_srv_i_profile_importer.hpp" -#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out> out), (out)) \ - AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \ - AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out out, sprofile::Identifier revision_key), (out, revision_key)) \ - AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ()) +#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out> out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 200, Result, GetProfileDownloadUrlList, (sf::Out out_count, const sf::OutArray &out, const sprofile::srv::MetadataPayload &arg), (out_count, out, arg), hos::Version_13_0_0, hos::Version_22_5_0) \ + AMS_SF_METHOD_INFO(C, H, 201, Result, GetMetadataNewness, (sf::Out out, sprofile::HashKey revision_key), (out, revision_key), hos::Version_13_0_0, hos::Version_22_5_0) \ + AMS_SF_METHOD_INFO(C, H, 2000, Result, ClearSaveDataForTest, (), ()) AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, ISprofileServiceForBgAgent, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO, 0xCCD828EC) diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.cpp index 1bf965f21..af31ba30c 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.cpp @@ -19,12 +19,18 @@ namespace ams::sprofile::srv { - Result ProfileControllerForDebugImpl::Reset() { + Result ProfileControllerForDebugImpl::ClearSaveData() { R_RETURN(m_manager->ResetSaveData()); } - Result ProfileControllerForDebugImpl::GetRaw(sf::Out out_type, sf::Out out_value, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetRaw(out_type.GetPointer(), out_value.GetPointer(), profile, key)); + Result ProfileControllerForDebugImpl::QueryValue(sf::Out out_type, sf::Out out_value, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->QueryValue(out_type.GetPointer(), out_value.GetPointer(), profile, key)); + } + + Result ProfileControllerForDebugImpl::QueryValueArray(sf::Out out_type, sf::Out out_count, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out_type, out_count, out_buffer, profile, key); + R_SUCCEED(); } } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.hpp index edb9d9eb2..1a6bb7cd6 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_controller_for_debug_impl.hpp @@ -27,8 +27,9 @@ namespace ams::sprofile::srv { public: ProfileControllerForDebugImpl(ProfileManager *manager) : m_manager(manager) { /* ... */ } public: - Result Reset(); - Result GetRaw(sf::Out out_type, sf::Out out_value, sprofile::Identifier profile, sprofile::Identifier key); + Result ClearSaveData(); + Result QueryValue(sf::Out out_type, sf::Out out_value, sprofile::HashKey profile, sprofile::HashKey key); + Result QueryValueArray(sf::Out out_type, sf::Out out_count, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); }; static_assert(IsIProfileControllerForDebug); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer.hpp index 20df0fbe2..c2e5a5c00 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer.hpp @@ -22,8 +22,8 @@ namespace ams::sprofile::srv { class ProfileImporter { private: struct ImportingProfile { - Identifier identifier_0; - Identifier identifier_1; + HashKey hash_key_0; + HashKey hash_key_1; bool is_new_import; }; private: @@ -33,7 +33,7 @@ namespace ams::sprofile::srv { util::optional m_metadata; ImportingProfile m_importing_profiles[50]; util::BitFlagSet<50> m_is_profile_importable; - Identifier m_revision_key; + HashKey m_revision_key; public: ProfileImporter(const util::optional &meta) : m_committed(false), m_imported_metadata(false), m_importing_count(0), m_metadata(util::nullopt), m_is_profile_importable(), m_revision_key() { if (meta.has_value()) { @@ -41,12 +41,12 @@ namespace ams::sprofile::srv { } } public: - bool HasProfile(Identifier id0, Identifier id1) { + bool HasProfile(HashKey id0, HashKey id1) { /* Require that we have metadata. */ if (m_metadata.has_value()) { for (auto i = 0u; i < std::min(m_metadata->num_entries, util::size(m_metadata->entries)); ++i) { const auto &entry = m_metadata->entries[i]; - if (entry.identifier_0 == id0 && entry.identifier_1 == id1) { + if (entry.hash_key_0 == id0 && entry.hash_key_1 == id1) { return true; } } @@ -80,23 +80,23 @@ namespace ams::sprofile::srv { for (auto i = 0; i < m_importing_count; ++i) { const auto &import_entry = meta.entries[i]; - const bool is_new_import = !this->HasProfile(import_entry.identifier_0, import_entry.identifier_1); + const bool is_new_import = !this->HasProfile(import_entry.hash_key_0, import_entry.hash_key_1); m_importing_profiles[i] = { - .identifier_0 = import_entry.identifier_0, - .identifier_1 = import_entry.identifier_1, + .hash_key_0 = import_entry.hash_key_0, + .hash_key_1 = import_entry.hash_key_1, .is_new_import = is_new_import, }; m_is_profile_importable[i] = is_new_import; } } - bool CanImportProfile(Identifier profile) { + bool CanImportProfile(HashKey profile) { /* Require that we imported metadata. */ if (m_imported_metadata) { /* Find the specified profile. */ for (auto i = 0; i < m_importing_count; ++i) { - if (m_importing_profiles[i].identifier_0 == profile) { + if (m_importing_profiles[i].hash_key_0 == profile) { /* Require the profile be importable. */ return m_is_profile_importable[i]; } @@ -107,10 +107,10 @@ namespace ams::sprofile::srv { return false; } - void OnImportProfile(Identifier profile) { + void OnImportProfile(HashKey profile) { /* Set the profile as not importable (as it's imported). */ for (auto i = 0; i < m_importing_count; ++i) { - if (m_importing_profiles[i].identifier_0 == profile) { + if (m_importing_profiles[i].hash_key_0 == profile) { m_is_profile_importable[i] = false; break; } @@ -135,15 +135,15 @@ namespace ams::sprofile::srv { int GetImportingCount() const { return m_importing_count; } const ImportingProfile &GetImportingProfile(int i) const { return m_importing_profiles[i]; } - Identifier GetRevisionKey() const { return m_revision_key; } + HashKey GetRevisionKey() const { return m_revision_key; } Result CleanupOrphanedProfiles(auto cleanup_impl) const { /* Cleanup any orphaned profiles in our metadata. */ if (m_metadata.has_value()) { for (auto i = 0u; i < std::min(m_metadata->num_entries, util::size(m_metadata->entries)); ++i) { const auto &entry = m_metadata->entries[i]; - if (!this->IsImportingProfile(entry.identifier_0)) { - R_TRY(cleanup_impl(entry.identifier_0)); + if (!this->IsImportingProfile(entry.hash_key_0)) { + R_TRY(cleanup_impl(entry.hash_key_0)); } } } @@ -151,10 +151,10 @@ namespace ams::sprofile::srv { R_SUCCEED(); } private: - bool IsImportingProfile(Identifier profile) const { + bool IsImportingProfile(HashKey profile) const { /* Check if we're importing the desired profile. */ for (auto i = 0; i < m_importing_count; ++i) { - if (m_importing_profiles[i].identifier_0 == profile) { + if (m_importing_profiles[i].hash_key_0 == profile) { return true; } } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.cpp index 7e64a3a48..0b49dbd2f 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.cpp @@ -19,7 +19,7 @@ namespace ams::sprofile::srv { - Result ProfileImporterImpl::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) { + Result ProfileImporterImpl::ImportProfile(const sprofile::srv::ProfilePayload &import) { R_RETURN(m_manager->ImportProfile(import)); } @@ -27,7 +27,7 @@ namespace ams::sprofile::srv { R_RETURN(m_manager->Commit()); } - Result ProfileImporterImpl::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) { + Result ProfileImporterImpl::ImportMetadata(const sprofile::srv::MetadataPayload &import) { R_RETURN(m_manager->ImportMetadata(import)); } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.hpp index fce94f2b0..0f7e0d41f 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_importer_impl.hpp @@ -31,9 +31,9 @@ namespace ams::sprofile::srv { m_manager->CloseProfileImporter(); } public: - Result ImportProfile(const sprofile::srv::ProfileDataForImportData &import); + Result ImportProfile(const sprofile::srv::ProfilePayload &import); Result Commit(); - Result ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import); + Result ImportMetadata(const sprofile::srv::MetadataPayload &import); }; static_assert(IsIProfileImporter); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp index 0167371ba..3e2d11e9e 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp @@ -54,15 +54,15 @@ namespace ams::sprofile::srv { CreateMetadataPathImpl(dst, dst_size, mount, TemporaryDirectoryName); } - void CreateProfilePathImpl(char *dst, size_t dst_size, const char *mount, const char *dir, const Identifier &id) { + void CreateProfilePathImpl(char *dst, size_t dst_size, const char *mount, const char *dir, const HashKey &id) { SafePrint(dst, dst_size, "%s:/%s/profiles/%02x%02x%02x%02x%02x%02x%02x", mount, dir, id.data[0], id.data[1], id.data[2], id.data[3], id.data[4], id.data[5], id.data[6]); } - void CreatePrimaryProfilePath(char *dst, size_t dst_size, const char *mount, const Identifier &id) { + void CreatePrimaryProfilePath(char *dst, size_t dst_size, const char *mount, const HashKey &id) { CreateProfilePathImpl(dst, dst_size, mount, PrimaryDirectoryName, id); } - void CreateTemporaryProfilePath(char *dst, size_t dst_size, const char *mount, const Identifier &id) { + void CreateTemporaryProfilePath(char *dst, size_t dst_size, const char *mount, const HashKey &id) { CreateProfilePathImpl(dst, dst_size, mount, TemporaryDirectoryName, id); } @@ -185,7 +185,12 @@ namespace ams::sprofile::srv { this->CloseProfileImporterImpl(); } - Result ProfileManager::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) { + Result ProfileManager::ImportProfile(const sprofile::srv::ProfilePayload &import) { + /* On 23.0.0+ profile importing is no longer supported. */ + if (hos::GetVersion() >= hos::Version_23_0_0) { + R_THROW(sprofile::ResultNotImplemented()); + } + /* Acquire locks. */ std::scoped_lock lk1(m_profile_importer_mutex); std::scoped_lock lk2(m_fs_mutex); @@ -211,21 +216,21 @@ namespace ams::sprofile::srv { } /* Succeed if we already have the profile. */ - R_SUCCEED_IF(m_profile_importer->HasProfile(import.header.identifier_0, import.header.identifier_1)); + R_SUCCEED_IF(m_profile_importer->HasProfile(import.header.hash_key_0, import.header.hash_key_1)); /* Check that we're importing the profile. */ - R_UNLESS(m_profile_importer->CanImportProfile(import.header.identifier_0), sprofile::ResultInvalidState()); + R_UNLESS(m_profile_importer->CanImportProfile(import.header.hash_key_0), sprofile::ResultInvalidState()); /* Create temporary directories. */ R_TRY(this->EnsureTemporaryDirectories()); /* Create profile. */ char path[0x30]; - CreateTemporaryProfilePath(path, sizeof(path), m_save_data_info.mount_name, import.header.identifier_0); + CreateTemporaryProfilePath(path, sizeof(path), m_save_data_info.mount_name, import.header.hash_key_0); R_TRY(WriteFile(path, std::addressof(import.data), sizeof(import.data))); /* Set profile imported. */ - m_profile_importer->OnImportProfile(import.header.identifier_0); + m_profile_importer->OnImportProfile(import.header.hash_key_0); R_SUCCEED(); } @@ -266,7 +271,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) { + Result ProfileManager::ImportMetadata(const sprofile::srv::MetadataPayload &import) { /* Acquire locks. */ std::scoped_lock lk1(m_profile_importer_mutex); std::scoped_lock lk2(m_fs_mutex); @@ -340,7 +345,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::LoadProfile(Identifier profile) { + Result ProfileManager::LoadProfile(HashKey profile) { /* Check if we already have the profile. */ if (m_service_profile.has_value()) { R_SUCCEED_IF(m_service_profile->name == profile); @@ -362,7 +367,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key) { + Result ProfileManager::GetDataEntry(ProfileDataEntry *out, HashKey profile, HashKey key) { /* Acquire locks. */ std::scoped_lock lk1(m_service_profile_mutex); std::scoped_lock lk2(m_general_mutex); @@ -381,7 +386,7 @@ namespace ams::sprofile::srv { R_THROW(sprofile::ResultKeyNotFound()); } - Result ProfileManager::GetSigned64(s64 *out, Identifier profile, Identifier key) { + Result ProfileManager::GetInt64Value(s64 *out, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -394,7 +399,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetUnsigned64(u64 *out, Identifier profile, Identifier key) { + Result ProfileManager::GetUInt64Value(u64 *out, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -407,7 +412,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetSigned32(s32 *out, Identifier profile, Identifier key) { + Result ProfileManager::GetInt32Value(s32 *out, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -420,7 +425,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetUnsigned32(u32 *out, Identifier profile, Identifier key) { + Result ProfileManager::GetUInt32Value(u32 *out, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -433,7 +438,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetByte(u8 *out, Identifier profile, Identifier key) { + Result ProfileManager::GetBooleanValue(u8 *out, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -446,7 +451,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ProfileManager::GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key) { + Result ProfileManager::QueryValue(u8 *out_type, u64 *out_value, HashKey profile, HashKey key) { /* Get the data entry. */ ProfileDataEntry entry; R_TRY(this->GetDataEntry(std::addressof(entry), profile, key)); @@ -477,8 +482,8 @@ namespace ams::sprofile::srv { const auto &profile = m_profile_importer->GetImportingProfile(i); if (profile.is_new_import) { - CreateTemporaryProfilePath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name, profile.identifier_0); - CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile.identifier_0); + CreateTemporaryProfilePath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name, profile.hash_key_0); + CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile.hash_key_0); R_TRY(MoveFile(tmp_path, pri_path)); } } @@ -494,7 +499,7 @@ namespace ams::sprofile::srv { char pri_path[0x30]; /* Cleanup the profiles. */ - R_RETURN(m_profile_importer->CleanupOrphanedProfiles([&](Identifier profile) ALWAYS_INLINE_LAMBDA -> Result { + R_RETURN(m_profile_importer->CleanupOrphanedProfiles([&](HashKey profile) ALWAYS_INLINE_LAMBDA -> Result { CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile); R_RETURN(DeleteFile(pri_path)); })); @@ -506,7 +511,7 @@ namespace ams::sprofile::srv { /* If we need to, invalidate the loaded service profile. */ if (m_service_profile.has_value()) { for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) { - if (m_service_profile->name == m_profile_importer->GetImportingProfile(i).identifier_0) { + if (m_service_profile->name == m_profile_importer->GetImportingProfile(i).hash_key_0) { m_service_profile = util::nullopt; break; } @@ -521,7 +526,7 @@ namespace ams::sprofile::srv { const auto &profile = m_profile_importer->GetImportingProfile(i); if (profile.is_new_import) { - m_update_observer_manager.OnUpdate(profile.identifier_0); + m_update_observer_manager.OnUpdate(profile.hash_key_0); } } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.hpp index 40484b998..6154a73fd 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.hpp @@ -52,19 +52,19 @@ namespace ams::sprofile::srv { Result OpenProfileImporter(); void CloseProfileImporter(); - Result ImportProfile(const sprofile::srv::ProfileDataForImportData &data); + Result ImportProfile(const sprofile::srv::ProfilePayload &data); Result Commit(); - Result ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &data); + Result ImportMetadata(const sprofile::srv::MetadataPayload &data); Result LoadPrimaryMetadata(ProfileMetadata *out); - Result GetSigned64(s64 *out, Identifier profile, Identifier key); - Result GetUnsigned64(u64 *out, Identifier profile, Identifier key); - Result GetSigned32(s32 *out, Identifier profile, Identifier key); - Result GetUnsigned32(u32 *out, Identifier profile, Identifier key); - Result GetByte(u8 *out, Identifier profile, Identifier key); + Result GetInt64Value(s64 *out, HashKey profile, HashKey key); + Result GetUInt64Value(u64 *out, HashKey profile, HashKey key); + Result GetInt32Value(s32 *out, HashKey profile, HashKey key); + Result GetUInt32Value(u32 *out, HashKey profile, HashKey key); + Result GetBooleanValue(u8 *out, HashKey profile, HashKey key); - Result GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key); + Result QueryValue(u8 *out_type, u64 *out_value, HashKey profile, HashKey key); ProfileUpdateObserverManager &GetUpdateObserverManager() { return m_update_observer_manager; } private: @@ -76,9 +76,9 @@ namespace ams::sprofile::srv { void OnCommitted(); - Result GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key); + Result GetDataEntry(ProfileDataEntry *out, HashKey profile, HashKey key); - Result LoadProfile(Identifier profile); + Result LoadProfile(HashKey profile); Result EnsurePrimaryDirectories(); Result EnsureTemporaryDirectories(); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.cpp index b601764af..d2a981bd4 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.cpp @@ -19,24 +19,72 @@ namespace ams::sprofile::srv { - Result ProfileReaderImpl::GetSigned64(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetSigned64(out.GetPointer(), profile, key)); + Result ProfileReaderImpl::GetInt64Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->GetInt64Value(out.GetPointer(), profile, key)); } - Result ProfileReaderImpl::GetUnsigned64(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetUnsigned64(out.GetPointer(), profile, key)); + Result ProfileReaderImpl::GetUInt64Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->GetUInt64Value(out.GetPointer(), profile, key)); } - Result ProfileReaderImpl::GetSigned32(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetSigned32(out.GetPointer(), profile, key)); + Result ProfileReaderImpl::GetInt32Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->GetInt32Value(out.GetPointer(), profile, key)); } - Result ProfileReaderImpl::GetUnsigned32(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetUnsigned32(out.GetPointer(), profile, key)); + Result ProfileReaderImpl::GetUInt32Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->GetUInt32Value(out.GetPointer(), profile, key)); } - Result ProfileReaderImpl::GetByte(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key) { - R_RETURN(m_manager->GetByte(out.GetPointer(), profile, key)); + Result ProfileReaderImpl::GetBooleanValue(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + R_RETURN(m_manager->GetBooleanValue(out.GetPointer(), profile, key)); + } + + Result ProfileReaderImpl::GetAnyValue(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetInt8ValueArray(sf::Out out, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetInt64ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetUInt64ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetInt32ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetUInt32ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetUInt8ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); + } + + Result ProfileReaderImpl::GetAnyValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key) { + /* On 23.0.0+ this isn't reachable from HIPC. */ + AMS_UNUSED(out, out_buffer, profile, key); + R_SUCCEED(); } } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.hpp index 4768538e4..2f193cd80 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_reader_impl.hpp @@ -27,11 +27,19 @@ namespace ams::sprofile::srv { public: ProfileReaderImpl(ProfileManager *manager) : m_manager(manager) { /* ... */ } public: - Result GetSigned64(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key); - Result GetUnsigned64(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key); - Result GetSigned32(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key); - Result GetUnsigned32(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key); - Result GetByte(sf::Out out, sprofile::Identifier profile, sprofile::Identifier key); + Result GetInt64Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetUInt64Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetInt32Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetUInt32Value(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetBooleanValue(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetAnyValue(sf::Out out, sprofile::HashKey profile, sprofile::HashKey key); + Result GetInt8ValueArray(sf::Out out, const sf::OutBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetInt64ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetUInt64ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetInt32ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetUInt32ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetUInt8ValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); + Result GetAnyValueArray(sf::Out out, const sf::OutPointerBuffer &out_buffer, sprofile::HashKey profile, sprofile::HashKey key); }; static_assert(IsIProfileReader); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_update_observer_impl.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_update_observer_impl.hpp index f54d230d4..b7c8dbee7 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_update_observer_impl.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_update_observer_impl.hpp @@ -24,7 +24,7 @@ namespace ams::sprofile::srv { static constexpr auto MaxProfiles = 4; private: os::SystemEvent m_event; - Identifier m_profiles[MaxProfiles]; + HashKey m_profiles[MaxProfiles]; int m_profile_count; os::SdkMutex m_mutex; public: @@ -34,7 +34,7 @@ namespace ams::sprofile::srv { os::SystemEvent &GetEvent() { return m_event; } const os::SystemEvent &GetEvent() const { return m_event; } public: - Result Listen(Identifier profile) { + Result Subscribe(HashKey profile) { /* Lock ourselves. */ std::scoped_lock lk(m_mutex); @@ -51,7 +51,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result Unlisten(Identifier profile) { + Result Unsubscribe(HashKey profile) { /* Check that we're listening. */ for (auto i = 0; i < m_profile_count; ++i) { if (m_profiles[i] == profile) { @@ -64,12 +64,12 @@ namespace ams::sprofile::srv { R_THROW(sprofile::ResultNotListening()); } - Result GetEventHandle(sf::OutCopyHandle out) { + Result GetUpdateEventNativeHandle(sf::OutCopyHandle out) { out.SetValue(m_event.GetReadableHandle(), false); R_SUCCEED(); } public: - void OnUpdate(Identifier profile) { + void OnUpdate(HashKey profile) { for (auto i = 0; i < m_profile_count; ++i) { if (m_profiles[i] == profile) { m_event.Signal(); @@ -93,7 +93,7 @@ namespace ams::sprofile::srv { Result OpenObserver(sf::Out> &out, MemoryResource *memory_resource); void CloseObserver(ProfileUpdateObserverImpl *observer); - void OnUpdate(Identifier profile) { + void OnUpdate(HashKey profile) { std::scoped_lock lk(m_mutex); for (auto i = 0; i < m_observer_count; ++i) { diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp index c8e4e5036..43f3ed9af 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.cpp @@ -34,7 +34,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ServiceForBgAgent::GetImportableProfileUrls(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg) { + Result ServiceForBgAgent::GetProfileDownloadUrlList(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::MetadataPayload &arg) { /* Check size. */ R_UNLESS(out.GetSize() >= arg.metadata.num_entries, sprofile::ResultInvalidArgument()); @@ -57,7 +57,7 @@ namespace ams::sprofile::srv { for (u32 j = 0; j < primary_metadata.num_entries; ++j) { const auto &pri_entry = primary_metadata.entries[j]; - if (pri_entry.identifier_0 == arg_entry.identifier_0 && pri_entry.identifier_1 == arg_entry.identifier_1) { + if (pri_entry.hash_key_0 == arg_entry.hash_key_0 && pri_entry.hash_key_1 == arg_entry.hash_key_1) { have_entry = true; break; } @@ -75,7 +75,7 @@ namespace ams::sprofile::srv { } - Result ServiceForBgAgent::IsUpdateNeeded(sf::Out out, Identifier revision_key) { + Result ServiceForBgAgent::GetMetadataNewness(sf::Out out, HashKey revision_key) { /* Load primary metadata. */ bool loaded_metadata = true; sprofile::srv::ProfileMetadata primary_metadata; @@ -91,7 +91,7 @@ namespace ams::sprofile::srv { R_SUCCEED(); } - Result ServiceForBgAgent::Reset() { + Result ServiceForBgAgent::ClearSaveDataForTest() { R_RETURN(m_profile_manager->ResetSaveData()); } diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp index 43d308966..66416fd1a 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_service_for_bg_agent.hpp @@ -29,9 +29,9 @@ namespace ams::sprofile::srv { constexpr ServiceForBgAgent(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ } public: Result OpenProfileImporter(sf::Out> out); - Result GetImportableProfileUrls(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg); - Result IsUpdateNeeded(sf::Out out, Identifier revision_key); - Result Reset(); + Result GetProfileDownloadUrlList(sf::Out out_count, const sf::OutArray &out, const sprofile::srv::MetadataPayload &arg); + Result GetMetadataNewness(sf::Out out, HashKey revision_key); + Result ClearSaveDataForTest(); }; static_assert(sprofile::srv::IsISprofileServiceForBgAgent); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp index d20610a17..ddddaa26e 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_types.hpp @@ -33,7 +33,7 @@ namespace ams::sprofile::srv { }; struct ProfileDataEntry { - Identifier key; + HashKey key; ValueType type; union { s64 value_s64; @@ -65,7 +65,7 @@ namespace ams::sprofile::srv { static_assert(AMS_OFFSETOF(ProfileData, entries) == 0x30); struct ServiceProfile { - Identifier name; + HashKey name; ProfileData data; }; static_assert(util::is_pod::value); @@ -74,10 +74,10 @@ namespace ams::sprofile::srv { static_assert(AMS_OFFSETOF(ServiceProfile, name) == 0x00); static_assert(AMS_OFFSETOF(ServiceProfile, data) == 0x08); - struct ProfileDataForImportData : public sf::LargeData, public sf::PrefersMapAliasTransferMode { + struct ProfilePayload : public sf::LargeData, public sf::PrefersMapAliasTransferMode { struct { - Identifier identifier_0; - Identifier identifier_1; + HashKey hash_key_0; + HashKey hash_key_1; u8 unk_0E[2]; u32 version; u8 unk_14[0x1C]; @@ -86,25 +86,25 @@ namespace ams::sprofile::srv { ProfileData data; u8 unk_4040[0x4400 - 0x4040]; }; - static_assert(util::is_pod::value); - static_assert(sizeof(ProfileDataForImportData) == 0x4400); + static_assert(util::is_pod::value); + static_assert(sizeof(ProfilePayload) == 0x4400); - static_assert(AMS_OFFSETOF(ProfileDataForImportData, header) == 0x00); - static_assert(AMS_OFFSETOF(ProfileDataForImportData, hash) == 0x30); - static_assert(AMS_OFFSETOF(ProfileDataForImportData, data) == 0x40); - static_assert(AMS_OFFSETOF(ProfileDataForImportData, unk_4040) == 0x4040); + static_assert(AMS_OFFSETOF(ProfilePayload, header) == 0x00); + static_assert(AMS_OFFSETOF(ProfilePayload, hash) == 0x30); + static_assert(AMS_OFFSETOF(ProfilePayload, data) == 0x40); + static_assert(AMS_OFFSETOF(ProfilePayload, unk_4040) == 0x4040); struct ProfileMetadataEntry { - Identifier identifier_0; - Identifier identifier_1; + HashKey hash_key_0; + HashKey hash_key_1; u8 unk_0E[0x32]; }; static_assert(util::is_pod::value); static_assert(sizeof(ProfileMetadataEntry) == 0x40); - static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_0) == 0x00); - static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_1) == 0x07); - static_assert(AMS_OFFSETOF(ProfileMetadataEntry, unk_0E) == 0x0E); + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, hash_key_0) == 0x00); + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, hash_key_1) == 0x07); + static_assert(AMS_OFFSETOF(ProfileMetadataEntry, unk_0E) == 0x0E); struct ProfileUrl : public sf::PrefersMapAliasTransferMode { char url[0x100]; @@ -115,7 +115,7 @@ namespace ams::sprofile::srv { struct ProfileMetadata { u32 num_entries; u32 unk_04; - Identifier revision_key; + HashKey revision_key; u8 unk_0F[0x1]; u8 unk_10[0x30]; ProfileMetadataEntry entries[50]; @@ -130,7 +130,7 @@ namespace ams::sprofile::srv { static_assert(AMS_OFFSETOF(ProfileMetadata, unk_10) == 0x10); static_assert(AMS_OFFSETOF(ProfileMetadata, entries) == 0x40); - struct ProfileMetadataForImportMetadata : public sf::LargeData, public sf::PrefersMapAliasTransferMode { + struct MetadataPayload : public sf::LargeData, public sf::PrefersMapAliasTransferMode { struct { u32 version; u8 unk_04[0x1C]; @@ -140,13 +140,13 @@ namespace ams::sprofile::srv { ProfileUrl profile_urls[50]; u8 unk_3EF0[0x8000 - 0x3EF0]; }; - static_assert(util::is_pod::value); - static_assert(sizeof(ProfileMetadataForImportMetadata) == 0x8000); + static_assert(util::is_pod::value); + static_assert(sizeof(MetadataPayload) == 0x8000); - static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, header) == 0x00); - static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, hash) == 0x20); - static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, metadata) == 0x30); - static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, profile_urls) == 0xCF0); - static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, unk_3EF0) == 0x3EF0); + static_assert(AMS_OFFSETOF(MetadataPayload, header) == 0x00); + static_assert(AMS_OFFSETOF(MetadataPayload, hash) == 0x20); + static_assert(AMS_OFFSETOF(MetadataPayload, metadata) == 0x30); + static_assert(AMS_OFFSETOF(MetadataPayload, profile_urls) == 0xCF0); + static_assert(AMS_OFFSETOF(MetadataPayload, unk_3EF0) == 0x3EF0); } diff --git a/libraries/libvapours/include/vapours/results/sprofile_results.hpp b/libraries/libvapours/include/vapours/results/sprofile_results.hpp index 4000bd8f1..78168028e 100644 --- a/libraries/libvapours/include/vapours/results/sprofile_results.hpp +++ b/libraries/libvapours/include/vapours/results/sprofile_results.hpp @@ -21,20 +21,23 @@ R_DEFINE_NAMESPACE_RESULT_MODULE(ams::sprofile, 246); namespace ams::sprofile { - R_DEFINE_ERROR_RESULT(InvalidArgument, 100); - R_DEFINE_ERROR_RESULT(InvalidState, 101); + R_DEFINE_ERROR_RESULT(InvalidArgument, 100); + R_DEFINE_ERROR_RESULT(InvalidState, 101); + + R_DEFINE_ERROR_RESULT(NotImplemented, 300); + R_DEFINE_ERROR_RESULT(NotSupported, 301); + R_DEFINE_ERROR_RESULT(Delayed, 302); + R_DEFINE_ERROR_RESULT(NotPermitted, 303); - R_DEFINE_ERROR_RESULT(NotPermitted, 303); + R_DEFINE_ERROR_RESULT(AllocationFailed, 401); - R_DEFINE_ERROR_RESULT(AllocationFailed, 401); + R_DEFINE_ERROR_RESULT(KeyNotFound, 600); + R_DEFINE_ERROR_RESULT(InvalidDataType, 601); - R_DEFINE_ERROR_RESULT(KeyNotFound, 600); - R_DEFINE_ERROR_RESULT(InvalidDataType, 601); - - R_DEFINE_ERROR_RESULT(MaxListeners, 620); - R_DEFINE_ERROR_RESULT(AlreadyListening, 621); - R_DEFINE_ERROR_RESULT(NotListening, 622); - R_DEFINE_ERROR_RESULT(MaxObservers, 623); + R_DEFINE_ERROR_RESULT(MaxListeners, 620); + R_DEFINE_ERROR_RESULT(AlreadyListening, 621); + R_DEFINE_ERROR_RESULT(NotListening, 622); + R_DEFINE_ERROR_RESULT(MaxObservers, 623); R_DEFINE_ERROR_RESULT(InvalidMetadataVersion, 3210); R_DEFINE_ERROR_RESULT(InvalidMetadataHash, 3211); From ff09b598d5333d6f6f4de14753275b676ca9982f Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 17:11:51 +0100 Subject: [PATCH 23/52] i2c: deprecate SetRetryPolicy as of 23.0.0 --- .../stratosphere/i2c/sf/i2c_sf_i_manager.hpp | 12 ++++++------ .../stratosphere/i2c/sf/i2c_sf_i_session.hpp | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_manager.hpp b/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_manager.hpp index 7342f08c7..b0888381c 100644 --- a/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_manager.hpp @@ -20,11 +20,11 @@ #include #include -#define AMS_I2C_I_MANAGER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode), (out, bus_idx, slave_address, addressing_mode, speed_mode) ) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out> out, i2c::I2cDevice device), (out, device) ) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out out, i2c::I2cDevice device), (out, device), hos::Version_Min, hos::Version_5_1_0) \ - AMS_SF_METHOD_INFO(C, H, 3, Result, HasDeviceForDev, (ams::sf::Out out, i2c::I2cDevice device), (out, device), hos::Version_Min, hos::Version_5_1_0) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, OpenSession2, (ams::sf::Out> out, DeviceCode device_code), (out, device_code), hos::Version_6_0_0 ) +#define AMS_I2C_I_MANAGER_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode), (out, bus_idx, slave_address, addressing_mode, speed_mode)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out> out, i2c::I2cDevice device), (out, device)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out out, i2c::I2cDevice device), (out, device), hos::Version_1_0_0, hos::Version_5_1_0) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, HasDeviceForDev, (ams::sf::Out out, i2c::I2cDevice device), (out, device), hos::Version_1_0_0, hos::Version_5_1_0) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, OpenSession2, (ams::sf::Out> out, DeviceCode device_code), (out, device_code), hos::Version_6_0_0) AMS_SF_DEFINE_INTERFACE(ams::i2c::sf, IManager, AMS_I2C_I_MANAGER_INTERFACE_INFO, 0xE4C9D8F0) diff --git a/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_session.hpp b/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_session.hpp index 22cf9afa8..aee01e4b6 100644 --- a/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_session.hpp +++ b/libraries/libstratosphere/include/stratosphere/i2c/sf/i2c_sf_i_session.hpp @@ -18,13 +18,13 @@ #include #include -#define AMS_I2C_I_SESSION_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SendOld, (const ams::sf::InBuffer &in_data, i2c::TransactionOption option), (in_data, option), hos::Version_Min, hos::Version_5_1_0) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, ReceiveOld, (const ams::sf::OutBuffer &out_data, i2c::TransactionOption option), (out_data, option), hos::Version_Min, hos::Version_5_1_0) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, ExecuteCommandListOld, (const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray &command_list), (rcv_buf, command_list), hos::Version_Min, hos::Version_5_1_0) \ - AMS_SF_METHOD_INFO(C, H, 10, Result, Send, (const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option), (in_data, option) ) \ - AMS_SF_METHOD_INFO(C, H, 11, Result, Receive, (const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option), (out_data, option) ) \ - AMS_SF_METHOD_INFO(C, H, 12, Result, ExecuteCommandList, (const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray &command_list), (rcv_buf, command_list) ) \ - AMS_SF_METHOD_INFO(C, H, 13, Result, SetRetryPolicy, (s32 max_retry_count, s32 retry_interval_us), (max_retry_count, retry_interval_us), hos::Version_6_0_0 ) +#define AMS_I2C_I_SESSION_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SendOld, (const ams::sf::InBuffer &in_data, i2c::TransactionOption option), (in_data, option), hos::Version_1_0_0, hos::Version_5_1_0) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, ReceiveOld, (const ams::sf::OutBuffer &out_data, i2c::TransactionOption option), (out_data, option), hos::Version_1_0_0, hos::Version_5_1_0) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, ExecuteCommandListOld, (const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray &command_list), (rcv_buf, command_list), hos::Version_1_0_0, hos::Version_5_1_0) \ + AMS_SF_METHOD_INFO(C, H, 10, Result, Send, (const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option), (in_data, option)) \ + AMS_SF_METHOD_INFO(C, H, 11, Result, Receive, (const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option), (out_data, option)) \ + AMS_SF_METHOD_INFO(C, H, 12, Result, ExecuteCommandList, (const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray &command_list), (rcv_buf, command_list)) \ + AMS_SF_METHOD_INFO(C, H, 13, Result, SetRetryPolicy, (s32 max_retry_count, s32 retry_interval_us), (max_retry_count, retry_interval_us), hos::Version_6_0_0, hos::Version_22_5_0) AMS_SF_DEFINE_INTERFACE(ams::i2c::sf, ISession, AMS_I2C_I_SESSION_INTERFACE_INFO, 0x40154EFE) From 9b4e4a219052696fbca00983bcbade7be902180a Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 19:40:17 +0100 Subject: [PATCH 24/52] gpio: update for 23.0.0 --- .../gpio/sf/gpio_sf_i_manager.hpp | 24 +++++------ .../gpio/sf/gpio_sf_i_pad_session.hpp | 42 ++++++++++--------- .../source/gpio/gpio_client_api.cpp | 10 ++--- .../source/gpio/gpio_remote_manager_impl.cpp | 4 +- .../source/gpio/gpio_remote_manager_impl.hpp | 20 ++++----- .../gpio/gpio_remote_pad_session_impl.hpp | 27 +++++++++++- .../gpio/server/gpio_server_manager_impl.cpp | 22 +++++----- .../gpio/server/gpio_server_manager_impl.hpp | 20 ++++----- .../server/gpio_server_pad_session_impl.hpp | 39 ++++++++++++++++- 9 files changed, 135 insertions(+), 73 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp index 077885fc8..fee82ffe8 100644 --- a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_manager.hpp @@ -21,17 +21,17 @@ #include #include -#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out> out, s32 pad_descriptor), (out, pad_descriptor) ) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out> out, gpio::GpioPadName pad_name), (out, pad_name) ) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out> out, gpio::GpioPadName pad_name), (out, pad_name) ) \ - AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out out, gpio::GpioPadName pad_name), (out, pad_name), hos::Version_Min, hos::Version_6_2_0) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSet, (ams::sf::Out out), (out), hos::Version_Min, hos::Version_6_2_0) \ - AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebug, (gpio::GpioPadName pad_name, bool is_enabled), (pad_name, is_enabled), hos::Version_Min, hos::Version_6_2_0) \ - AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode), (mode) ) \ - AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession2, (ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode), (out, device_code, access_mode), hos::Version_5_0_0 ) \ - AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive2, (ams::sf::Out out, DeviceCode device_code), (out, device_code), hos::Version_5_0_0 ) \ - AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug2, (DeviceCode device_code, bool is_enabled), (device_code, is_enabled), hos::Version_5_0_0 ) \ - AMS_SF_METHOD_INFO(C, H, 10, Result, SetRetryValues, (u32 arg0, u32 arg1), (arg0, arg1), hos::Version_6_0_0 ) +#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDevDeprecated, (ams::sf::Out> out, s32 pad_descriptor), (out, pad_descriptor)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSessionDeprecated, (ams::sf::Out> out, gpio::GpioPadName pad_name), (out, pad_name)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTestDeprecated, (ams::sf::Out> out, gpio::GpioPadName pad_name), (out, pad_name)) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActiveDeprecated, (ams::sf::Out out, gpio::GpioPadName pad_name), (out, pad_name), hos::Version_1_0_0, hos::Version_6_2_0) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, GetWakeEventActiveFlagSetDeprecated, (ams::sf::Out out), (out), hos::Version_1_0_0, hos::Version_6_2_0) \ + AMS_SF_METHOD_INFO(C, H, 5, Result, SetWakeEventActiveFlagSetForDebugDeprecated, (gpio::GpioPadName pad_name, bool is_enabled), (pad_name, is_enabled), hos::Version_1_0_0, hos::Version_6_2_0) \ + AMS_SF_METHOD_INFO(C, H, 6, Result, SetWakePinDebugMode, (s32 mode), (mode)) \ + AMS_SF_METHOD_INFO(C, H, 7, Result, OpenSession, (ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode), (out, device_code, access_mode), hos::Version_5_0_0) \ + AMS_SF_METHOD_INFO(C, H, 8, Result, IsWakeEventActive, (ams::sf::Out out, DeviceCode device_code), (out, device_code), hos::Version_5_0_0) \ + AMS_SF_METHOD_INFO(C, H, 9, Result, SetWakeEventActiveFlagSetForDebug, (DeviceCode device_code, bool is_enabled), (device_code, is_enabled), hos::Version_5_0_0) \ + AMS_SF_METHOD_INFO(C, H, 10, Result, DumpStateForDebug, (u32 arg0, u32 arg1), (arg0, arg1), hos::Version_6_0_0) AMS_SF_DEFINE_INTERFACE(ams::gpio::sf, IManager, AMS_GPIO_I_MANAGER_INTERFACE_INFO, 0xD219501E) diff --git a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp index 9c0fb619e..eaf055b1d 100644 --- a/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp +++ b/libraries/libstratosphere/include/stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp @@ -18,24 +18,28 @@ #include #include -#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirection, (gpio::Direction direction), (direction) ) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode), (mode) ) \ - AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable), (enable) ) \ - AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, (), () ) \ - AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value), (value) ) \ - AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, (), () ) \ - AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable), (enable) ) \ - AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms), (ms) ) \ - AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out out), (out) ) \ - AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), (value), hos::Version_4_0_0) \ - AMS_SF_METHOD_INFO(C, H, 16, Result, GetValueForSleepState, (ams::sf::Out out), (out), hos::Version_6_0_0) +#define AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SetDirectionDeprecated, (gpio::Direction direction), (direction)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, GetDirection, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, SetInterruptMode, (gpio::InterruptMode mode), (mode)) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetInterruptMode, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, SetInterruptEnable, (bool enable), (enable)) \ + AMS_SF_METHOD_INFO(C, H, 5, Result, GetInterruptEnable, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out out), (out), hos::Version_1_0_0, hos::Version_16_1_0) \ + AMS_SF_METHOD_INFO(C, H, 7, Result, ClearInterruptStatus, (), (), hos::Version_1_0_0, hos::Version_16_1_0) \ + AMS_SF_METHOD_INFO(C, H, 8, Result, SetValue, (gpio::GpioValue value), (value)) \ + AMS_SF_METHOD_INFO(C, H, 9, Result, GetValue, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 10, Result, BindInterrupt, (ams::sf::OutCopyHandle out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 11, Result, UnbindInterrupt, (), ()) \ + AMS_SF_METHOD_INFO(C, H, 12, Result, SetDebounceEnabled, (bool enable), (enable)) \ + AMS_SF_METHOD_INFO(C, H, 13, Result, GetDebounceEnabled, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 14, Result, SetDebounceTime, (s32 ms), (ms)) \ + AMS_SF_METHOD_INFO(C, H, 15, Result, GetDebounceTime, (ams::sf::Out out), (out)) \ + AMS_SF_METHOD_INFO(C, H, 16, Result, SetValueForSleepState, (gpio::GpioValue value), (value), hos::Version_4_0_0) \ + AMS_SF_METHOD_INFO(C, H, 17, Result, GetMaxDebounceTime, (ams::sf::Out out), (out), hos::Version_6_0_0) \ + AMS_SF_METHOD_INFO(C, H, 18, Result, SetDirectionInput, (), (), hos::Version_12_0_0) \ + AMS_SF_METHOD_INFO(C, H, 19, Result, SetDirectionOutput, (gpio::GpioValue value), (value), hos::Version_12_0_0) \ + AMS_SF_METHOD_INFO(C, H, 20, Result, SetUnknownEnabled, (bool enable), (enable), hos::Version_23_0_0) \ + AMS_SF_METHOD_INFO(C, H, 21, Result, GetUnknownEnabled, (ams::sf::Out out), (out), hos::Version_23_0_0) AMS_SF_DEFINE_INTERFACE(ams::gpio::sf, IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO, 0x7448A8A7) diff --git a/libraries/libstratosphere/source/gpio/gpio_client_api.cpp b/libraries/libstratosphere/source/gpio/gpio_client_api.cpp index ce51b8cef..8da47933d 100644 --- a/libraries/libstratosphere/source/gpio/gpio_client_api.cpp +++ b/libraries/libstratosphere/source/gpio/gpio_client_api.cpp @@ -81,9 +81,9 @@ namespace ams::gpio { ams::sf::SharedPointer session; { if (hos::GetVersion() >= hos::Version_7_0_0) { - R_TRY(g_manager->OpenSession2(std::addressof(session), device_code, ddsf::AccessMode_ReadWrite)); + R_TRY(g_manager->OpenSession(std::addressof(session), device_code, ddsf::AccessMode_ReadWrite)); } else { - R_TRY(g_manager->OpenSession(std::addressof(session), ConvertToGpioPadName(device_code))); + R_TRY(g_manager->OpenSessionDeprecated(std::addressof(session), ConvertToGpioPadName(device_code))); } } @@ -110,9 +110,9 @@ namespace ams::gpio { Result IsWakeEventActive(bool *out_is_active, ams::DeviceCode device_code) { if (hos::GetVersion() >= hos::Version_7_0_0) { - R_TRY(g_manager->IsWakeEventActive2(out_is_active, device_code)); + R_TRY(g_manager->IsWakeEventActive(out_is_active, device_code)); } else { - R_TRY(g_manager->IsWakeEventActive(out_is_active, ConvertToGpioPadName(device_code))); + R_TRY(g_manager->IsWakeEventActiveDeprecated(out_is_active, ConvertToGpioPadName(device_code))); } R_SUCCEED(); @@ -125,7 +125,7 @@ namespace ams::gpio { } void SetDirection(GpioPadSession *session, Direction direction) { - R_ABORT_UNLESS(GetInterface(session)->SetDirection(direction)); + R_ABORT_UNLESS(GetInterface(session)->SetDirectionDeprecated(direction)); } GpioValue GetValue(GpioPadSession *session) { diff --git a/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.cpp b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.cpp index 72da31d0e..968c2769a 100644 --- a/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.cpp +++ b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.cpp @@ -34,7 +34,7 @@ namespace ams::gpio { } - Result RemoteManagerImpl::OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name) { + Result RemoteManagerImpl::OpenSessionDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name) { ::GpioPadSession p; R_TRY(::gpioOpenSession(std::addressof(p), static_cast<::GpioPadName>(static_cast(pad_name)))); @@ -42,7 +42,7 @@ namespace ams::gpio { R_SUCCEED(); } - Result RemoteManagerImpl::OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) { + Result RemoteManagerImpl::OpenSession(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) { ::GpioPadSession p; R_TRY(::gpioOpenSession2(std::addressof(p), device_code.GetInternalValue(), access_mode)); diff --git a/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp index bd6e47fcd..ec3ad8c6c 100644 --- a/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp +++ b/libraries/libstratosphere/source/gpio/gpio_remote_manager_impl.hpp @@ -27,31 +27,31 @@ namespace ams::gpio { ~RemoteManagerImpl() { /* ... */ } public: /* Actual commands. */ - Result OpenSessionForDev(ams::sf::Out> out, s32 pad_descriptor) { + Result OpenSessionForDevDeprecated(ams::sf::Out> out, s32 pad_descriptor) { /* TODO: libnx bindings */ AMS_UNUSED(out, pad_descriptor); AMS_ABORT(); } - Result OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name); + Result OpenSessionDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name); - Result OpenSessionForTest(ams::sf::Out> out, gpio::GpioPadName pad_name) { + Result OpenSessionForTestDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name) { /* TODO: libnx bindings */ AMS_UNUSED(out, pad_name); AMS_ABORT(); } - Result IsWakeEventActive(ams::sf::Out out, gpio::GpioPadName pad_name) { + Result IsWakeEventActiveDeprecated(ams::sf::Out out, gpio::GpioPadName pad_name) { R_RETURN(::gpioIsWakeEventActive2(out.GetPointer(), static_cast<::GpioPadName>(static_cast(pad_name)))); } - Result GetWakeEventActiveFlagSet(ams::sf::Out out) { + Result GetWakeEventActiveFlagSetDeprecated(ams::sf::Out out) { /* TODO: libnx bindings */ AMS_UNUSED(out); AMS_ABORT(); } - Result SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled) { + Result SetWakeEventActiveFlagSetForDebugDeprecated(gpio::GpioPadName pad_name, bool is_enabled) { /* TODO: libnx bindings */ AMS_UNUSED(pad_name, is_enabled); AMS_ABORT(); @@ -63,19 +63,19 @@ namespace ams::gpio { AMS_ABORT(); } - Result OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode); + Result OpenSession(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode); - Result IsWakeEventActive2(ams::sf::Out out, DeviceCode device_code) { + Result IsWakeEventActive(ams::sf::Out out, DeviceCode device_code) { R_RETURN(::gpioIsWakeEventActive2(out.GetPointer(), device_code.GetInternalValue())); } - Result SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled) { + Result SetWakeEventActiveFlagSetForDebug(DeviceCode device_code, bool is_enabled) { /* TODO: libnx bindings */ AMS_UNUSED(device_code, is_enabled); AMS_ABORT(); } - Result SetRetryValues(u32 arg0, u32 arg1) { + Result DumpStateForDebug(u32 arg0, u32 arg1) { /* TODO: libnx bindings */ AMS_UNUSED(arg0, arg1); AMS_ABORT(); diff --git a/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp b/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp index ee5874504..18f63d61e 100644 --- a/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp +++ b/libraries/libstratosphere/source/gpio/gpio_remote_pad_session_impl.hpp @@ -28,7 +28,7 @@ namespace ams::gpio { ~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(m_srv)); } public: /* Actual commands. */ - Result SetDirection(gpio::Direction direction) { + Result SetDirectionDeprecated(gpio::Direction direction) { R_RETURN(::gpioPadSetDirection(std::addressof(m_srv), static_cast<::GpioDirection>(static_cast(direction)))); } @@ -105,7 +105,30 @@ namespace ams::gpio { AMS_ABORT(); } - Result GetValueForSleepState(ams::sf::Out out) { + Result GetMaxDebounceTime(ams::sf::Out out) { + /* TODO: libnx bindings. */ + AMS_UNUSED(out); + AMS_ABORT(); + } + + Result SetDirectionInput() { + /* TODO: libnx bindings. */ + AMS_ABORT(); + } + + Result SetDirectionOutput(gpio::GpioValue value) { + /* TODO: libnx bindings. */ + AMS_UNUSED(value); + AMS_ABORT(); + } + + Result SetUnknownEnabled(bool enable) { + /* TODO: libnx bindings. */ + AMS_UNUSED(enable); + AMS_ABORT(); + } + + Result GetUnknownEnabled(ams::sf::Out out) { /* TODO: libnx bindings. */ AMS_UNUSED(out); AMS_ABORT(); diff --git a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp index 226813219..052541bec 100644 --- a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp +++ b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.cpp @@ -27,35 +27,35 @@ namespace ams::gpio::server { lmem::DestroyExpHeap(m_heap_handle); } - Result ManagerImpl::OpenSessionForDev(ams::sf::Out> out, s32 pad_descriptor) { + Result ManagerImpl::OpenSessionForDevDeprecated(ams::sf::Out> out, s32 pad_descriptor) { /* TODO */ AMS_UNUSED(out, pad_descriptor); AMS_ABORT(); } - Result ManagerImpl::OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name) { - R_RETURN(this->OpenSession2(out, ConvertToDeviceCode(pad_name), ddsf::AccessMode_ReadWrite)); + Result ManagerImpl::OpenSessionDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name) { + R_RETURN(this->OpenSession(out, ConvertToDeviceCode(pad_name), ddsf::AccessMode_ReadWrite)); } - Result ManagerImpl::OpenSessionForTest(ams::sf::Out> out, gpio::GpioPadName pad_name) { + Result ManagerImpl::OpenSessionForTestDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name) { /* TODO */ AMS_UNUSED(out, pad_name); AMS_ABORT(); } - Result ManagerImpl::IsWakeEventActive(ams::sf::Out out, gpio::GpioPadName pad_name) { + Result ManagerImpl::IsWakeEventActiveDeprecated(ams::sf::Out out, gpio::GpioPadName pad_name) { /* TODO */ AMS_UNUSED(out, pad_name); AMS_ABORT(); } - Result ManagerImpl::GetWakeEventActiveFlagSet(ams::sf::Out out) { + Result ManagerImpl::GetWakeEventActiveFlagSetDeprecated(ams::sf::Out out) { /* TODO */ AMS_UNUSED(out); AMS_ABORT(); } - Result ManagerImpl::SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled) { + Result ManagerImpl::SetWakeEventActiveFlagSetForDebugDeprecated(gpio::GpioPadName pad_name, bool is_enabled) { /* TODO */ AMS_UNUSED(pad_name, is_enabled); AMS_ABORT(); @@ -67,7 +67,7 @@ namespace ams::gpio::server { AMS_ABORT(); } - Result ManagerImpl::OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) { + Result ManagerImpl::OpenSession(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode) { /* Allocate a session. */ auto session = Factory::CreateSharedEmplaced(std::addressof(m_pad_allocator), this); @@ -79,19 +79,19 @@ namespace ams::gpio::server { R_SUCCEED(); } - Result ManagerImpl::IsWakeEventActive2(ams::sf::Out out, DeviceCode device_code) { + Result ManagerImpl::IsWakeEventActive(ams::sf::Out out, DeviceCode device_code) { /* TODO */ AMS_UNUSED(out, device_code); AMS_ABORT(); } - Result ManagerImpl::SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled) { + Result ManagerImpl::SetWakeEventActiveFlagSetForDebug(DeviceCode device_code, bool is_enabled) { /* TODO */ AMS_UNUSED(device_code, is_enabled); AMS_ABORT(); } - Result ManagerImpl::SetRetryValues(u32 arg0, u32 arg1) { + Result ManagerImpl::DumpStateForDebug(u32 arg0, u32 arg1) { /* TODO */ AMS_UNUSED(arg0, arg1); AMS_ABORT(); diff --git a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.hpp b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.hpp index be5d862ab..2e51f0fda 100644 --- a/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.hpp +++ b/libraries/libstratosphere/source/gpio/server/gpio_server_manager_impl.hpp @@ -33,17 +33,17 @@ namespace ams::gpio::server { ~ManagerImpl(); public: /* Actual commands. */ - Result OpenSessionForDev(ams::sf::Out> out, s32 pad_descriptor); - Result OpenSession(ams::sf::Out> out, gpio::GpioPadName pad_name); - Result OpenSessionForTest(ams::sf::Out> out, gpio::GpioPadName pad_name); - Result IsWakeEventActive(ams::sf::Out out, gpio::GpioPadName pad_name); - Result GetWakeEventActiveFlagSet(ams::sf::Out out); - Result SetWakeEventActiveFlagSetForDebug(gpio::GpioPadName pad_name, bool is_enabled); + Result OpenSessionForDevDeprecated(ams::sf::Out> out, s32 pad_descriptor); + Result OpenSessionDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name); + Result OpenSessionForTestDeprecated(ams::sf::Out> out, gpio::GpioPadName pad_name); + Result IsWakeEventActiveDeprecated(ams::sf::Out out, gpio::GpioPadName pad_name); + Result GetWakeEventActiveFlagSetDeprecated(ams::sf::Out out); + Result SetWakeEventActiveFlagSetForDebugDeprecated(gpio::GpioPadName pad_name, bool is_enabled); Result SetWakePinDebugMode(s32 mode); - Result OpenSession2(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode); - Result IsWakeEventActive2(ams::sf::Out out, DeviceCode device_code); - Result SetWakeEventActiveFlagSetForDebug2(DeviceCode device_code, bool is_enabled); - Result SetRetryValues(u32 arg0, u32 arg1); + Result OpenSession(ams::sf::Out> out, DeviceCode device_code, ddsf::AccessMode access_mode); + Result IsWakeEventActive(ams::sf::Out out, DeviceCode device_code); + Result SetWakeEventActiveFlagSetForDebug(DeviceCode device_code, bool is_enabled); + Result DumpStateForDebug(u32 arg0, u32 arg1); }; static_assert(gpio::sf::IsIManager); diff --git a/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp b/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp index a1ce1e6a5..441534888 100644 --- a/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp +++ b/libraries/libstratosphere/source/gpio/server/gpio_server_pad_session_impl.hpp @@ -44,7 +44,7 @@ namespace ams::gpio::server { } public: /* Actual commands. */ - Result SetDirection(gpio::Direction direction) { + Result SetDirectionDeprecated(gpio::Direction direction) { /* Validate our state. */ AMS_ASSERT(m_has_session); @@ -205,7 +205,42 @@ namespace ams::gpio::server { AMS_ABORT(); } - Result GetValueForSleepState(ams::sf::Out out) { + Result GetMaxDebounceTime(ams::sf::Out out) { + /* Validate our state. */ + AMS_ASSERT(m_has_session); + + /* TODO */ + AMS_UNUSED(out); + AMS_ABORT(); + } + + Result SetDirectionInput() { + /* Validate our state. */ + AMS_ASSERT(m_has_session); + + /* TODO */ + AMS_ABORT(); + } + + Result SetDirectionOutput(gpio::GpioValue value) { + /* Validate our state. */ + AMS_ASSERT(m_has_session); + + /* TODO */ + AMS_UNUSED(value); + AMS_ABORT(); + } + + Result SetUnknownEnabled(bool enable) { + /* Validate our state. */ + AMS_ASSERT(m_has_session); + + /* TODO */ + AMS_UNUSED(enable); + AMS_ABORT(); + } + + Result GetUnknownEnabled(ams::sf::Out out) { /* Validate our state. */ AMS_ASSERT(m_has_session); From ab1e8a3e3265fad263368927e90c7b22fb6a2dc8 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 21:42:22 +0100 Subject: [PATCH 25/52] kern/loader/svc: adopt updated names --- .../arch/arm64/kern_k_page_table.hpp | 2 +- .../arch/arm64/kern_k_process_page_table.hpp | 2 +- .../mesosphere/kern_k_address_space_info.hpp | 4 +- .../mesosphere/kern_k_page_table_base.hpp | 14 +-- .../include/mesosphere/kern_k_process.hpp | 4 +- .../source/arch/arm64/kern_k_page_table.cpp | 2 +- .../source/kern_k_address_space_info.cpp | 22 ++--- .../source/kern_k_debug_base.cpp | 2 +- .../source/kern_k_initial_process_reader.cpp | 14 +-- .../source/kern_k_page_table_base.cpp | 12 +-- .../libmesosphere/source/kern_k_process.cpp | 20 ++-- .../source/svc/kern_svc_process.cpp | 72 +++++++------- .../include/stratosphere/cfg/cfg_types.hpp | 10 +- .../include/stratosphere/ldr/ldr_types.hpp | 60 ++++++------ .../cfg/cfg_override.board.nintendo_nx.inc | 28 +++--- .../impl/osdbg_thread_info.os.horizon.hpp | 10 +- .../include/vapours/svc/svc_types_common.hpp | 71 +++++++------- .../creport/source/creport_crash_report.hpp | 4 +- .../dmnt.gen2/source/dmnt2_debug_process.cpp | 8 +- stratosphere/loader/source/ldr_meta.cpp | 16 ++-- .../loader/source/ldr_process_creation.cpp | 94 +++++++++---------- .../pm/source/impl/pm_process_manager.cpp | 8 +- 22 files changed, 239 insertions(+), 240 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index 9fd7dbd2f..240da83de 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -205,7 +205,7 @@ namespace ams::kern::arch::arm64 { } NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); - NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index); void Finalize(); static void NoteUpdatedCallback(const void *pt) { diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index e80311a47..c4180594c 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -28,7 +28,7 @@ namespace ams::kern::arch::arm64 { m_page_table.ActivateProcess(process_index, id); } - Result Initialize(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) { + Result Initialize(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) { R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit, process_index)); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp index 00d942a66..462ef3a71 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp @@ -37,8 +37,8 @@ namespace ams::kern { size_t m_size; Type m_type; public: - static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, Type type, size_t code_size); - static size_t GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, Type type); + static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessParameterFlag flags, Type type, size_t code_size); + static size_t GetAddressSpaceSize(ams::svc::CreateProcessParameterFlag flags, Type type); static void SetAddressSpaceSize(size_t width, Type type, size_t size); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index c0139ab79..02c8eb5ea 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -151,14 +151,14 @@ namespace ams::kern { static constexpr u32 DefaultMemoryIgnoreAttr = KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared; - static constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag as_type) { - switch (static_cast(as_type & ams::svc::CreateProcessFlag_AddressSpaceMask)) { - case ams::svc::CreateProcessFlag_AddressSpace64Bit: + static constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag as_type) { + switch (static_cast(as_type & ams::svc::CreateProcessParameterFlag_AddressSpaceMask)) { + case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39: return 39; - case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated: + case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36: return 36; - case ams::svc::CreateProcessFlag_AddressSpace32Bit: - case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: + case ams::svc::CreateProcessParameterFlag_AddressSpace32Bit: + case ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved: return 32; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } @@ -229,7 +229,7 @@ namespace ams::kern { explicit KPageTableBase() { /* ... */ } NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); - NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); void Finalize(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index d20e49c7c..4a45ade8a 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -165,9 +165,9 @@ namespace ams::kern { constexpr bool CheckThreadPriority(s32 prio) const { return ((1ul << prio) & this->GetPriorityMask()) != 0; } - constexpr u32 GetCreateProcessFlags() const { return m_flags; } + constexpr u32 GetCreateProcessParameterFlags() const { return m_flags; } - constexpr bool Is64Bit() const { return m_flags & ams::svc::CreateProcessFlag_Is64Bit; } + constexpr bool Is64Bit() const { return m_flags & ams::svc::CreateProcessParameterFlag_64Bit; } constexpr KProcessAddress GetEntryPoint() const { return m_code_address; } diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index b22874027..3b21ab818 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -128,7 +128,7 @@ namespace ams::kern::arch::arm64 { KPageTableBase::InitializeForKernel(table, start, end); } - Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) { + Result KPageTable::InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit, size_t process_index) { /* Determine our ASID */ m_asid = process_index + 1; MESOSPHERE_ABORT_UNLESS(0 < m_asid && m_asid < util::size(s_ttbr0_entries)); diff --git a/libraries/libmesosphere/source/kern_k_address_space_info.cpp b/libraries/libmesosphere/source/kern_k_address_space_info.cpp index 022dc9b54..700e6dce9 100644 --- a/libraries/libmesosphere/source/kern_k_address_space_info.cpp +++ b/libraries/libmesosphere/source/kern_k_address_space_info.cpp @@ -46,20 +46,20 @@ namespace ams::kern { 32, 36, 32, 39, 42 }; - constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) { + constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag flags) { /* Convert the input flags to an array index. */ - const size_t idx = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask) >> ams::svc::CreateProcessFlag_AddressSpaceShift; + const size_t idx = (flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) >> ams::svc::CreateProcessParameterFlag_AddressSpaceShift; MESOSPHERE_ABORT_UNLESS(idx < sizeof(FlagsToAddressSpaceWidthTable)); /* Return the width. */ return FlagsToAddressSpaceWidthTable[idx]; } - static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32Bit) == 32); - static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36); - static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32); - static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39); - static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) == 42); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace32Bit) == 32); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36) == 36); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved) == 32); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39) == 39); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42) == 42); KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) { for (auto &info : AddressSpaceInfos) { @@ -72,14 +72,14 @@ namespace ams::kern { } - uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type, size_t code_size) { + uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessParameterFlag flags, KAddressSpaceInfo::Type type, size_t code_size) { MESOSPHERE_UNUSED(code_size); return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetAddress(); } - size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) { + size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessParameterFlag flags, KAddressSpaceInfo::Type type) { /* Extract the address space from the create process flags. */ - const auto as_flags = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask); + const auto as_flags = (flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask); /* Get the address space width. */ const auto as_width = GetAddressSpaceWidth(flags); @@ -88,7 +88,7 @@ namespace ams::kern { size_t as_size = GetAddressSpaceInfo(as_width, type).GetSize(); /* If we're getting size for 32-bit without alias, adjust the sizes accordingly. */ - if (as_flags == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) { + if (as_flags == ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved) { switch (type) { /* The heap space receives space that would otherwise go to the alias space. */ case KAddressSpaceInfo::Type_Heap: diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 40ff0ce3f..7150c8a4e 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -884,7 +884,7 @@ namespace ams::kern { { out->info.create_process.program_id = process->GetProgramId(); out->info.create_process.process_id = process->GetId(); - out->info.create_process.flags = process->GetCreateProcessFlags(); + out->info.create_process.flags = process->GetCreateProcessParameterFlags(); out->info.create_process.user_exception_context_address = GetInteger(process->GetProcessLocalRegionAddress()); std::memcpy(out->info.create_process.name, process->GetName(), sizeof(out->info.create_process.name)); diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index 61c04dd18..6037c3b78 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -214,19 +214,19 @@ namespace ams::kern { /* Apply other flags. */ if (this->Is64Bit()) { - out->flags |= ams::svc::CreateProcessFlag_Is64Bit; + out->flags |= ams::svc::CreateProcessParameterFlag_64Bit; } if (this->Is64BitAddressSpace()) { - out->flags |= (GetTargetFirmware() >= TargetFirmware_2_0_0) ? ams::svc::CreateProcessFlag_AddressSpace64Bit : ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated; + out->flags |= (GetTargetFirmware() >= TargetFirmware_2_0_0) ? ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39 : ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36; } else { - out->flags |= ams::svc::CreateProcessFlag_AddressSpace32Bit; + out->flags |= ams::svc::CreateProcessParameterFlag_AddressSpace32Bit; } if (enable_aslr) { - out->flags |= ams::svc::CreateProcessFlag_EnableAslr; + out->flags |= ams::svc::CreateProcessParameterFlag_EnableAslr; } /* All initial processes should disable device address space merge. */ - out->flags |= ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; + out->flags |= ams::svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge; /* Set and check code address. */ /* NOTE: Even though Nintendo passes a size to GetAddressSpaceStart at other call sites, they pass */ @@ -234,8 +234,8 @@ namespace ams::kern { /* almost certainly a bug. */ using ASType = KAddressSpaceInfo::Type; const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_MapHuge : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; - const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(out->flags), as_type, out->code_num_pages); - const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(out->flags), as_type); + const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(out->flags), as_type, out->code_num_pages); + const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(out->flags), as_type); const uintptr_t map_end = map_start + map_size; out->code_address = map_start + start_address; MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize)); diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 5b40e20e0..5f1a5b19b 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -133,7 +133,7 @@ namespace ams::kern { MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager)); } - Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { + Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessParameterFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { /* Validate the region. */ MESOSPHERE_ABORT_UNLESS(start <= code_address); MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size); @@ -179,8 +179,8 @@ namespace ams::kern { after_process_code_start = process_code_end; after_process_code_size = m_code_region_end - process_code_end; - /* If we have a 39-bit address space and should, enable extra size to the alias region. */ - if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) { + /* If we have a 39-bit address space and should, enable extra size for the address sanitizer. */ + if (flags & ams::svc::CreateProcessParameterFlag_EnableAddressSanitizer) { /* Extra size is 1/8th of the address space. */ m_alias_region_extra_size = (static_cast(1) << address_space_width) / 8; @@ -212,8 +212,8 @@ namespace ams::kern { m_region_ends[RegionType_ShadowStack] = Null; /* Set other basic fields. */ - m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; - m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; + m_enable_aslr = (flags & ams::svc::CreateProcessParameterFlag_EnableAslr) != 0; + m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge) == 0; m_allowed_exec_device_mapping = false; m_address_space_start = start; m_address_space_end = end; @@ -240,7 +240,7 @@ namespace ams::kern { region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, }; region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, }; - if (flags & ams::svc::CreateProcessFlag_EnableShadowStack) { + if (flags & ams::svc::CreateProcessParameterFlag_EnableShadowStack) { region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, }; } diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 7d1b0d0f4..ad49b783b 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -210,7 +210,7 @@ namespace ams::kern { m_program_id = params.program_id; m_code_address = params.code_address; m_code_size = params.code_num_pages * PageSize; - m_is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication); + m_is_application = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication); m_is_jit_debug = false; #if defined(MESOSPHERE_ENABLE_PROCESS_CREATION_TIME) @@ -226,7 +226,7 @@ namespace ams::kern { } /* Set max memory. */ - m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(m_flags), KAddressSpaceInfo::Type_Heap); + m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(m_flags), KAddressSpaceInfo::Type_Heap); /* Generate random entropy. */ KSystemControl::GenerateRandom(m_entropy, util::size(m_entropy)); @@ -279,7 +279,7 @@ namespace ams::kern { m_system_resource = secure_resource; } else { /* Use the system-wide system resource. */ - const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication); + const bool is_app = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication); m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource()); m_is_default_application_system_resource = is_app; @@ -293,8 +293,8 @@ namespace ams::kern { /* Setup page table. */ { - const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0; - R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit, this->GetSlabIndex())); + const bool from_back = (params.flags & ams::svc::CreateProcessParameterFlag_EnableAslr) == 0; + R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit, this->GetSlabIndex())); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); }; @@ -358,7 +358,7 @@ namespace ams::kern { } else { /* Use the system-wide system resource. */ - const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication); + const bool is_app = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication); m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource()); m_is_default_application_system_resource = is_app; @@ -372,8 +372,8 @@ namespace ams::kern { /* Setup page table. */ { - const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0; - R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, code_size, m_system_resource, res_limit, this->GetSlabIndex())); + const bool from_back = (params.flags & ams::svc::CreateProcessParameterFlag_EnableAslr) == 0; + R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, code_size, m_system_resource, res_limit, this->GetSlabIndex())); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); }; @@ -392,7 +392,7 @@ namespace ams::kern { MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax); /* If we should optimize memory allocations, do so. */ - if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) { + if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessParameterFlag_OptimizeMemoryAllocation) != 0) { R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool)); } @@ -1192,7 +1192,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(this == GetCurrentProcessPointer()); /* If we aren't allowed to enter jit debug, don't. */ - if ((m_flags & ams::svc::CreateProcessFlag_EnableDebug) == 0) { + if ((m_flags & ams::svc::CreateProcessParameterFlag_EnableJitDebug) == 0) { return false; } diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index c570c40d6..982719d41 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -86,15 +86,15 @@ namespace ams::kern::svc { R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count)); } - constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessFlag flags) { - if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) { + constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessParameterFlag flags) { + if ((flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) == ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42) { return (64 - 42); } else { return (64 - 39); } } - KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessFlag flags) { + KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessParameterFlag flags) { /* Find a process slab slot whose root page table is meant for the requested address space. */ const size_t desired_t0sz = GetProcessSlotT0Sz(flags); @@ -132,13 +132,13 @@ namespace ams::kern::svc { } /* Validate that the parameter flags are valid. */ - R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue()); + R_UNLESS((params.flags & ~ams::svc::CreateProcessParameterFlag_All) == 0, svc::ResultInvalidEnumValue()); /* The 64KB page size is not yet allowed. */ - R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) != ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage, svc::ResultInvalidCombination()); + R_UNLESS((params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) != ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42, svc::ResultInvalidCombination()); /* Validate that 64-bit process is okay. */ - const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0; + const bool is_64_bit = (params.flags & ams::svc::CreateProcessParameterFlag_64Bit) != 0; if constexpr (sizeof(void *) < sizeof(u64)) { R_UNLESS(!is_64_bit, svc::ResultInvalidCombination()); } @@ -147,35 +147,35 @@ namespace ams::kern::svc { uintptr_t map_start, map_end; size_t map_size; const size_t code_size = params.code_num_pages * PageSize; - switch (params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) { - case ams::svc::CreateProcessFlag_AddressSpace32Bit: - case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: + switch (params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) { + case ams::svc::CreateProcessParameterFlag_AddressSpace32Bit: + case ams::svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved: { - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } break; - case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated: + case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit36: { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } break; - case ams::svc::CreateProcessFlag_AddressSpace64Bit: - case ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage: + case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39: + case ams::svc::CreateProcessParameterFlag_AddressSpace64Bit42: { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size); - map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size); + map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); } break; default: @@ -184,11 +184,11 @@ namespace ams::kern::svc { /* Validate the pool partition. */ if (GetTargetFirmware() >= TargetFirmware_5_0_0) { - switch (params.flags & ams::svc::CreateProcessFlag_PoolPartitionMask) { - case ams::svc::CreateProcessFlag_PoolPartitionApplication: - case ams::svc::CreateProcessFlag_PoolPartitionApplet: - case ams::svc::CreateProcessFlag_PoolPartitionSystem: - case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure: + switch (params.flags & ams::svc::CreateProcessParameterFlag_PoolPartitionMask) { + case ams::svc::CreateProcessParameterFlag_PoolPartitionApplication: + case ams::svc::CreateProcessParameterFlag_PoolPartitionApplet: + case ams::svc::CreateProcessParameterFlag_PoolPartitionSystem: + case ams::svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure: break; default: R_THROW(svc::ResultInvalidEnumValue()); @@ -204,10 +204,10 @@ namespace ams::kern::svc { /* Check that the number of extra resource pages is >= 0. */ R_UNLESS(params.system_resource_num_pages >= 0, svc::ResultInvalidSize()); - /* Validate that the alias region extra size is allowed, if enabled. */ - if (params.flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) { + /* Validate that the address sanitizer is allowed, if enabled. */ + if (params.flags & ams::svc::CreateProcessParameterFlag_EnableAddressSanitizer) { /* Check that we have a 64-bit address space. */ - R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit, svc::ResultInvalidState()); + R_UNLESS((params.flags & ams::svc::CreateProcessParameterFlag_AddressSpaceMask) == ams::svc::CreateProcessParameterFlag_AddressSpace64Bit39, svc::ResultInvalidState()); /* Check that the system resource page count is non-zero. */ R_UNLESS(params.system_resource_num_pages > 0, svc::ResultInvalidState()); @@ -243,8 +243,8 @@ namespace ams::kern::svc { R_UNLESS(total_pages < (kern::MainMemorySizeMax / PageSize), svc::ResultOutOfMemory()); /* Check that optimized memory allocation is used only for applications. */ - const bool optimize_allocs = (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0; - const bool is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0; + const bool optimize_allocs = (params.flags & ams::svc::CreateProcessParameterFlag_OptimizeMemoryAllocation) != 0; + const bool is_application = (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) != 0; R_UNLESS(!optimize_allocs || is_application, svc::ResultBusy()); /* Check that the user-provided capabilities are accessible and refer to valid regions. */ @@ -254,7 +254,7 @@ namespace ams::kern::svc { auto &handle_table = GetCurrentProcess().GetHandleTable(); /* Create the new process, ensuring its page table slot matches the requested address space. */ - KProcess *process = CreateProcessForAddressSpace(static_cast(params.flags)); + KProcess *process = CreateProcessForAddressSpace(static_cast(params.flags)); R_UNLESS(process != nullptr, svc::ResultOutOfResource()); /* Ensure that the only reference to the process is in the handle table when we're done. */ @@ -270,19 +270,19 @@ namespace ams::kern::svc { /* Get the pool for the process. */ const auto pool = [](u32 flags) ALWAYS_INLINE_LAMBDA -> KMemoryManager::Pool { if (GetTargetFirmware() >= TargetFirmware_5_0_0) { - switch (flags & ams::svc::CreateProcessFlag_PoolPartitionMask) { - case ams::svc::CreateProcessFlag_PoolPartitionApplication: + switch (flags & ams::svc::CreateProcessParameterFlag_PoolPartitionMask) { + case ams::svc::CreateProcessParameterFlag_PoolPartitionApplication: return KMemoryManager::Pool_Application; - case ams::svc::CreateProcessFlag_PoolPartitionApplet: + case ams::svc::CreateProcessParameterFlag_PoolPartitionApplet: return KMemoryManager::Pool_Applet; - case ams::svc::CreateProcessFlag_PoolPartitionSystem: + case ams::svc::CreateProcessParameterFlag_PoolPartitionSystem: return KMemoryManager::Pool_System; - case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure: + case ams::svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure: default: return KMemoryManager::Pool_SystemNonSecure; } } else if (GetTargetFirmware() >= TargetFirmware_4_0_0) { - if ((flags & ams::svc::CreateProcessFlag_DeprecatedUseSecureMemory) != 0) { + if ((flags & ams::svc::CreateProcessParameterFlag_DeprecatedUseSecureMemory) != 0) { return KMemoryManager::Pool_Secure; } else { return static_cast(KSystemControl::GetCreateProcessMemoryPool()); diff --git a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp index 20976587c..785c278dc 100644 --- a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp @@ -31,11 +31,11 @@ namespace ams::cfg { OverrideStatusFlag_AddressSpaceMask = ((1u << 2) - 1) << OverrideStatusFlag_AddressSpaceShift, #if defined(ATMOSPHERE_OS_HORIZON) - OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, - OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, - OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, - OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, - OverrideStatusFlag_AddressSpace64Bit64KPage = (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessParameterFlag_AddressSpace32Bit >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit36 = (svc::CreateProcessParameterFlag_AddressSpace64Bit36 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace32BitNoReserved = (svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit39 = (svc::CreateProcessParameterFlag_AddressSpace64Bit39 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit42 = (svc::CreateProcessParameterFlag_AddressSpace64Bit42 >> svc::CreateProcessParameterFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, #endif }; diff --git a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp index c97711a53..7d36cae1c 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp @@ -50,9 +50,9 @@ namespace ams::ldr { ProgramInfoFlag_AllowDebug = (1 << 2), }; - enum CreateProcessFlag { - CreateProcessFlag_EnableDebug = (1 << 0), - CreateProcessFlag_DisableAslr = (1 << 1), + enum CreateProcessParameterFlag { + CreateProcessParameterFlag_EnableJitDebug = (1 << 0), + CreateProcessParameterFlag_DisableAslr = (1 << 1), }; struct ProgramArguments { @@ -194,10 +194,10 @@ namespace ams::ldr { }; #if defined(ATMOSPHERE_OS_HORIZON) - static_assert(PoolPartition_Application == (svc::CreateProcessFlag_PoolPartitionApplication >> svc::CreateProcessFlag_PoolPartitionShift)); - static_assert(PoolPartition_Applet == (svc::CreateProcessFlag_PoolPartitionApplet >> svc::CreateProcessFlag_PoolPartitionShift)); - static_assert(PoolPartition_System == (svc::CreateProcessFlag_PoolPartitionSystem >> svc::CreateProcessFlag_PoolPartitionShift)); - static_assert(PoolPartition_SystemNonSecure == (svc::CreateProcessFlag_PoolPartitionSystemNonSecure >> svc::CreateProcessFlag_PoolPartitionShift)); + static_assert(PoolPartition_Application == (svc::CreateProcessParameterFlag_PoolPartitionApplication >> svc::CreateProcessParameterFlag_PoolPartitionShift)); + static_assert(PoolPartition_Applet == (svc::CreateProcessParameterFlag_PoolPartitionApplet >> svc::CreateProcessParameterFlag_PoolPartitionShift)); + static_assert(PoolPartition_System == (svc::CreateProcessParameterFlag_PoolPartitionSystem >> svc::CreateProcessParameterFlag_PoolPartitionShift)); + static_assert(PoolPartition_SystemNonSecure == (svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure >> svc::CreateProcessParameterFlag_PoolPartitionShift)); #endif u8 signature[0x100]; @@ -223,43 +223,43 @@ namespace ams::ldr { struct Npdm { static constexpr u32 Magic = util::FourCC<'M','E','T','A'>::Code; - enum MetaFlag { - MetaFlag_Is64Bit = (1 << 0), + enum MetaFlag0 { + MetaFlag0_Is64BitInstruction = (1 << 0), - MetaFlag_AddressSpaceTypeShift = 1, - MetaFlag_AddressSpaceTypeMask = (7 << MetaFlag_AddressSpaceTypeShift), + MetaFlag0_ProcessAddressSpaceShift = 1, + MetaFlag0_ProcessAddressSpaceMask = (7 << MetaFlag0_ProcessAddressSpaceShift), - MetaFlag_OptimizeMemoryAllocation = (1 << 4), - MetaFlag_DisableDeviceAddressSpaceMerge = (1 << 5), - MetaFlag_EnableAliasRegionExtraSize = (1 << 6), - MetaFlag_PreventCodeReads = (1 << 7), + MetaFlag0_OptimizeMemoryAllocation = (1 << 4), + MetaFlag0_DisableDeviceAddressSpaceMerge = (1 << 5), + MetaFlag0_EnableAddressSanitizer = (1 << 6), + MetaFlag0_PreventCodeReads = (1 << 7), }; - enum MetaFlag2 { - MetaFlag2_EnableShadowStack = (1 << 0), + enum MetaFlag1 { + MetaFlag1_EnableShadowStack = (1 << 0), }; - enum AddressSpaceType { - AddressSpaceType_32Bit = 0, - AddressSpaceType_64BitDeprecated = 1, - AddressSpaceType_32BitWithoutAlias = 2, - AddressSpaceType_64Bit = 3, - AddressSpaceType_64Bit64KPage = 4, + enum ProcessAddressSpace { + ProcessAddressSpace_32Bit = 0, + ProcessAddressSpace_64Bit36 = 1, + ProcessAddressSpace_32BitNoReserved = 2, + ProcessAddressSpace_64Bit39 = 3, + ProcessAddressSpace_64Bit42 = 4, }; #if defined(ATMOSPHERE_OS_HORIZON) - static_assert(AddressSpaceType_32Bit == (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift)); - static_assert(AddressSpaceType_64BitDeprecated == (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift)); - static_assert(AddressSpaceType_32BitWithoutAlias == (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift)); - static_assert(AddressSpaceType_64Bit == (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift)); - static_assert(AddressSpaceType_64Bit64KPage == (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift)); + static_assert(ProcessAddressSpace_32Bit == (svc::CreateProcessParameterFlag_AddressSpace32Bit >> svc::CreateProcessParameterFlag_AddressSpaceShift)); + static_assert(ProcessAddressSpace_64Bit36 == (svc::CreateProcessParameterFlag_AddressSpace64Bit36 >> svc::CreateProcessParameterFlag_AddressSpaceShift)); + static_assert(ProcessAddressSpace_32BitNoReserved == (svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved >> svc::CreateProcessParameterFlag_AddressSpaceShift)); + static_assert(ProcessAddressSpace_64Bit39 == (svc::CreateProcessParameterFlag_AddressSpace64Bit39 >> svc::CreateProcessParameterFlag_AddressSpaceShift)); + static_assert(ProcessAddressSpace_64Bit42 == (svc::CreateProcessParameterFlag_AddressSpace64Bit42 >> svc::CreateProcessParameterFlag_AddressSpaceShift)); #endif u32 magic; u32 signature_key_generation; u8 reserved_08[4]; - u8 flags; - u8 flags2; + u8 flags0; + u8 flags1; u8 main_thread_priority; u8 default_cpu_id; u8 reserved_10[4]; diff --git a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc index 420f71198..ecdc1ecaf 100644 --- a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc +++ b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc @@ -79,20 +79,20 @@ namespace ams::cfg { InvalidProgramOverrideKey, }, .program_as_flags = { - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, - impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, + impl::OverrideStatusFlag_AddressSpace64Bit39, }, .override_any_app_key = { .key_combination = HidNpadButton_R, .override_by_default = false, }, - .override_any_app_as_flag = impl::OverrideStatusFlag_AddressSpace64Bit, + .override_any_app_as_flag = impl::OverrideStatusFlag_AddressSpace64Bit39, .override_any_app = true, }; @@ -152,11 +152,11 @@ namespace ams::cfg { impl::OverrideStatusFlag ParseOverrideAddressSpace(const char *value) { if (strcasecmp(value, "39_bit") == 0 || strcasecmp(value, "39") == 0) { - return impl::OverrideStatusFlag_AddressSpace64Bit; + return impl::OverrideStatusFlag_AddressSpace64Bit39; } else if (strcasecmp(value, "42_bit") == 0 || strcasecmp(value, "42") == 0) { - return impl::OverrideStatusFlag_AddressSpace64Bit64KPage; + return impl::OverrideStatusFlag_AddressSpace64Bit42; } else if (strcasecmp(value, "36_bit") == 0 || strcasecmp(value, "36") == 0) { - return impl::OverrideStatusFlag_AddressSpace64BitDeprecated; + return impl::OverrideStatusFlag_AddressSpace64Bit36; } else if (strcasecmp(value, "32_bit") == 0 || strcasecmp(value, "32") == 0) { return impl::OverrideStatusFlag_AddressSpace32Bit; } else if (strcasecmp(value, "32_bit_without_alias") == 0 || @@ -168,10 +168,10 @@ namespace ams::cfg { strcasecmp(value, "32_without_map") == 0 || strcasecmp(value, "32_no_map") == 0) { - return impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias; + return impl::OverrideStatusFlag_AddressSpace32BitNoReserved; } else { /* Default to 39-bit. */ - return impl::OverrideStatusFlag_AddressSpace64Bit; + return impl::OverrideStatusFlag_AddressSpace64Bit39; } } diff --git a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp index 1bd74bfba..4ab701ea3 100644 --- a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp +++ b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp @@ -27,14 +27,14 @@ namespace ams::osdbg::impl { using ThreadInfoImpl = ThreadInfoHorizonImpl; constexpr inline bool IsLp64(const ThreadInfo *info) { - const auto as = info->_debug_info_create_process.flags & svc::CreateProcessFlag_AddressSpaceMask; - return as == svc::CreateProcessFlag_AddressSpace64Bit - || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated - || as == svc::CreateProcessFlag_AddressSpace64Bit64KPage; + const auto as = info->_debug_info_create_process.flags & svc::CreateProcessParameterFlag_AddressSpaceMask; + return as == svc::CreateProcessParameterFlag_AddressSpace64Bit39 + || as == svc::CreateProcessParameterFlag_AddressSpace64Bit36 + || as == svc::CreateProcessParameterFlag_AddressSpace64Bit42; } constexpr inline bool Is64BitArch(const ThreadInfo *info) { - return (info->_debug_info_create_process.flags & svc::CreateProcessFlag_Is64Bit); + return (info->_debug_info_create_process.flags & svc::CreateProcessParameterFlag_64Bit); } } diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 66f5a5648..96a18a721 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -96,8 +96,7 @@ namespace ams::svc { MemoryState_CodeOut = 0x15, MemoryState_Coverage = 0x16, MemoryState_Insecure = 0x17, - MemoryState_Remote = 0x18, - MemoryState_Protected = 0x19, + /* ... */ MemoryState_ShadowStack = 0x1A, }; @@ -413,62 +412,62 @@ namespace ams::svc { ProcessActivity_Paused = 1, }; - enum CreateProcessFlag : u32 { + enum CreateProcessParameterFlag : u32 { /* Is 64 bit? */ - CreateProcessFlag_Is64Bit = (1 << 0), + CreateProcessParameterFlag_64Bit = (1 << 0), /* What kind of address space? */ - CreateProcessFlag_AddressSpaceShift = 1, - CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), /* Should be 15 but Nintendo didn't make 64K isn't usable yet */ - CreateProcessFlag_AddressSpace32Bit = (0 << CreateProcessFlag_AddressSpaceShift), - CreateProcessFlag_AddressSpace64BitDeprecated = (1 << CreateProcessFlag_AddressSpaceShift), - CreateProcessFlag_AddressSpace32BitWithoutAlias = (2 << CreateProcessFlag_AddressSpaceShift), - CreateProcessFlag_AddressSpace64Bit = (3 << CreateProcessFlag_AddressSpaceShift), - CreateProcessFlag_AddressSpace64Bit64KPage = (4 << CreateProcessFlag_AddressSpaceShift), + CreateProcessParameterFlag_AddressSpaceShift = 1, + CreateProcessParameterFlag_AddressSpaceMask = (7 << CreateProcessParameterFlag_AddressSpaceShift), /* Should be 15 but Nintendo didn't make 64K usable yet */ + CreateProcessParameterFlag_AddressSpace32Bit = (0 << CreateProcessParameterFlag_AddressSpaceShift), + CreateProcessParameterFlag_AddressSpace64Bit36 = (1 << CreateProcessParameterFlag_AddressSpaceShift), + CreateProcessParameterFlag_AddressSpace32BitNoReserved = (2 << CreateProcessParameterFlag_AddressSpaceShift), + CreateProcessParameterFlag_AddressSpace64Bit39 = (3 << CreateProcessParameterFlag_AddressSpaceShift), + CreateProcessParameterFlag_AddressSpace64Bit42 = (4 << CreateProcessParameterFlag_AddressSpaceShift), /* Should JIT debug be done on crash? */ - CreateProcessFlag_EnableDebug = (1 << 4), + CreateProcessParameterFlag_EnableJitDebug = (1 << 4), /* Should ASLR be enabled for the process? */ - CreateProcessFlag_EnableAslr = (1 << 5), + CreateProcessParameterFlag_EnableAslr = (1 << 5), /* Is the process an application? */ - CreateProcessFlag_IsApplication = (1 << 6), + CreateProcessParameterFlag_IsApplication = (1 << 6), /* 4.x deprecated: Should use secure memory? */ - CreateProcessFlag_DeprecatedUseSecureMemory = (1 << 7), + CreateProcessParameterFlag_DeprecatedUseSecureMemory = (1 << 7), /* 5.x+ Pool partition type. */ - CreateProcessFlag_PoolPartitionShift = 7, - CreateProcessFlag_PoolPartitionMask = (0xF << CreateProcessFlag_PoolPartitionShift), - CreateProcessFlag_PoolPartitionApplication = (0 << CreateProcessFlag_PoolPartitionShift), - CreateProcessFlag_PoolPartitionApplet = (1 << CreateProcessFlag_PoolPartitionShift), - CreateProcessFlag_PoolPartitionSystem = (2 << CreateProcessFlag_PoolPartitionShift), - CreateProcessFlag_PoolPartitionSystemNonSecure = (3 << CreateProcessFlag_PoolPartitionShift), + CreateProcessParameterFlag_PoolPartitionShift = 7, + CreateProcessParameterFlag_PoolPartitionMask = (0xF << CreateProcessParameterFlag_PoolPartitionShift), + CreateProcessParameterFlag_PoolPartitionApplication = (0 << CreateProcessParameterFlag_PoolPartitionShift), + CreateProcessParameterFlag_PoolPartitionApplet = (1 << CreateProcessParameterFlag_PoolPartitionShift), + CreateProcessParameterFlag_PoolPartitionSystem = (2 << CreateProcessParameterFlag_PoolPartitionShift), + CreateProcessParameterFlag_PoolPartitionSystemNonSecure = (3 << CreateProcessParameterFlag_PoolPartitionShift), /* 7.x+ Should memory allocation be optimized? This requires IsApplication. */ - CreateProcessFlag_OptimizeMemoryAllocation = (1 << 11), + CreateProcessParameterFlag_OptimizeMemoryAllocation = (1 << 11), /* 11.x+ DisableDeviceAddressSpaceMerge. */ - CreateProcessFlag_DisableDeviceAddressSpaceMerge = (1 << 12), + CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge = (1 << 12), - /* 18.x EnableAliasRegionExtraSize. */ - CreateProcessFlag_EnableAliasRegionExtraSize = (1 << 13), + /* 18.x EnableAddressSanitizer. */ + CreateProcessParameterFlag_EnableAddressSanitizer = (1 << 13), /* 23.x EnableShadowStack. */ - CreateProcessFlag_EnableShadowStack = (1 << 17), + CreateProcessParameterFlag_EnableShadowStack = (1 << 17), /* Mask of all flags. */ - CreateProcessFlag_All = CreateProcessFlag_Is64Bit | - CreateProcessFlag_AddressSpaceMask | - CreateProcessFlag_EnableDebug | - CreateProcessFlag_EnableAslr | - CreateProcessFlag_IsApplication | - CreateProcessFlag_PoolPartitionMask | - CreateProcessFlag_OptimizeMemoryAllocation | - CreateProcessFlag_DisableDeviceAddressSpaceMerge | - CreateProcessFlag_EnableAliasRegionExtraSize | - CreateProcessFlag_EnableShadowStack, + CreateProcessParameterFlag_All = CreateProcessParameterFlag_64Bit | + CreateProcessParameterFlag_AddressSpaceMask | + CreateProcessParameterFlag_EnableJitDebug | + CreateProcessParameterFlag_EnableAslr | + CreateProcessParameterFlag_IsApplication | + CreateProcessParameterFlag_PoolPartitionMask | + CreateProcessParameterFlag_OptimizeMemoryAllocation | + CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge | + CreateProcessParameterFlag_EnableAddressSanitizer | + CreateProcessParameterFlag_EnableShadowStack, }; /* Debug types. */ diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 36aee6b11..79080d93a 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -67,11 +67,11 @@ namespace ams::creport { } bool IsApplication() const { - return (m_process_info.flags & svc::CreateProcessFlag_IsApplication) != 0; + return (m_process_info.flags & svc::CreateProcessParameterFlag_IsApplication) != 0; } bool Is64Bit() const { - return (m_process_info.flags & svc::CreateProcessFlag_Is64Bit) != 0; + return (m_process_info.flags & svc::CreateProcessParameterFlag_64Bit) != 0; } bool IsUserBreak() const { diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp index 90505a4a9..4f25c1f5e 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp @@ -88,8 +88,8 @@ namespace ams::dmnt { m_create_process_info = d.info.create_process; /* Cache our bools. */ - m_is_64_bit = (m_create_process_info.flags & svc::CreateProcessFlag_Is64Bit); - m_is_64_bit_address_space = (m_create_process_info.flags & svc::CreateProcessFlag_AddressSpaceMask) == svc::CreateProcessFlag_AddressSpace64Bit; + m_is_64_bit = (m_create_process_info.flags & svc::CreateProcessParameterFlag_64Bit); + m_is_64_bit_address_space = (m_create_process_info.flags & svc::CreateProcessParameterFlag_AddressSpaceMask) == svc::CreateProcessParameterFlag_AddressSpace64Bit39; } break; case svc::DebugEvent_CreateThread: @@ -522,8 +522,8 @@ namespace ams::dmnt { m_create_process_info = out->info.create_process; /* Cache our bools. */ - m_is_64_bit = (m_create_process_info.flags & svc::CreateProcessFlag_Is64Bit); - m_is_64_bit_address_space = (m_create_process_info.flags & svc::CreateProcessFlag_AddressSpaceMask) == svc::CreateProcessFlag_AddressSpace64Bit; + m_is_64_bit = (m_create_process_info.flags & svc::CreateProcessParameterFlag_64Bit); + m_is_64_bit_address_space = (m_create_process_info.flags & svc::CreateProcessParameterFlag_AddressSpaceMask) == svc::CreateProcessParameterFlag_AddressSpace64Bit39; } break; case svc::DebugEvent_CreateThread: diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index f7da96292..87475196f 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -88,8 +88,8 @@ namespace ams::ldr { R_UNLESS(npdm->magic == Npdm::Magic, ldr::ResultInvalidMeta()); /* Validate flags. */ - constexpr u32 InvalidMetaFlagMask = 0x80000000; - R_UNLESS(!(npdm->flags & InvalidMetaFlagMask), ldr::ResultInvalidMeta()); + constexpr u32 InvalidMetaFlag0Mask = 0x80000000; + R_UNLESS(!(npdm->flags0 & InvalidMetaFlag0Mask), ldr::ResultInvalidMeta()); /* Validate Acid extents. */ R_TRY(ValidateSubregion(sizeof(Npdm), size, npdm->acid_offset, npdm->acid_size, sizeof(Acid))); @@ -262,15 +262,15 @@ namespace ams::ldr { /* Perform address space override. */ if (status.HasOverrideAddressSpace()) { /* Clear the existing address space. */ - meta->npdm->flags &= ~Npdm::MetaFlag_AddressSpaceTypeMask; + meta->npdm->flags0 &= ~Npdm::MetaFlag0_ProcessAddressSpaceMask; /* 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; - case cfg::impl::OverrideStatusFlag_AddressSpace64Bit64KPage: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit64KPage) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace32Bit: meta->npdm->flags0 |= (Npdm::ProcessAddressSpace_32Bit) << Npdm::MetaFlag0_ProcessAddressSpaceShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit36: meta->npdm->flags0 |= (Npdm::ProcessAddressSpace_64Bit36) << Npdm::MetaFlag0_ProcessAddressSpaceShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace32BitNoReserved: meta->npdm->flags0 |= (Npdm::ProcessAddressSpace_32BitNoReserved) << Npdm::MetaFlag0_ProcessAddressSpaceShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit39: meta->npdm->flags0 |= (Npdm::ProcessAddressSpace_64Bit39) << Npdm::MetaFlag0_ProcessAddressSpaceShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit42: meta->npdm->flags0 |= (Npdm::ProcessAddressSpace_64Bit42) << Npdm::MetaFlag0_ProcessAddressSpaceShift; break; AMS_UNREACHABLE_DEFAULT_CASE(); } } diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index d05450541..019f7c1e8 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -175,8 +175,8 @@ namespace ams::ldr { 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); + Npdm::ProcessAddressSpace GetProcessAddressSpace(const Meta *meta) { + return static_cast((meta->npdm->flags0 & Npdm::MetaFlag0_ProcessAddressSpaceMask) >> Npdm::MetaFlag0_ProcessAddressSpaceShift); } Acid::PoolPartition GetPoolPartition(const Meta *meta) { @@ -399,55 +399,55 @@ namespace ams::ldr { R_SUCCEED(); } - Result GetCreateProcessFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { - const u8 meta_flags = meta->npdm->flags; + Result GetCreateProcessParameterFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { + const u8 meta_flags = meta->npdm->flags0; u32 flags = 0; /* Set Is64Bit. */ - if (meta_flags & Npdm::MetaFlag_Is64Bit) { - flags |= svc::CreateProcessFlag_Is64Bit; + if (meta_flags & Npdm::MetaFlag0_Is64BitInstruction) { + flags |= svc::CreateProcessParameterFlag_64Bit; } - /* Set AddressSpaceType. */ - switch (GetAddressSpaceType(meta)) { - case Npdm::AddressSpaceType_32Bit: - flags |= svc::CreateProcessFlag_AddressSpace32Bit; + /* Set ProcessAddressSpace. */ + switch (GetProcessAddressSpace(meta)) { + case Npdm::ProcessAddressSpace_32Bit: + flags |= svc::CreateProcessParameterFlag_AddressSpace32Bit; break; - case Npdm::AddressSpaceType_64BitDeprecated: - flags |= svc::CreateProcessFlag_AddressSpace64BitDeprecated; + case Npdm::ProcessAddressSpace_64Bit36: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit36; break; - case Npdm::AddressSpaceType_32BitWithoutAlias: - flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias; + case Npdm::ProcessAddressSpace_32BitNoReserved: + flags |= svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved; break; - case Npdm::AddressSpaceType_64Bit: - flags |= svc::CreateProcessFlag_AddressSpace64Bit; + case Npdm::ProcessAddressSpace_64Bit39: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit39; break; - case Npdm::AddressSpaceType_64Bit64KPage: - flags |= svc::CreateProcessFlag_AddressSpace64Bit64KPage; + case Npdm::ProcessAddressSpace_64Bit42: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit42; break; default: R_THROW(ldr::ResultInvalidMeta()); } /* Set Enable Debug. */ - if (ldr_flags & CreateProcessFlag_EnableDebug) { - flags |= svc::CreateProcessFlag_EnableDebug; + if (ldr_flags & CreateProcessParameterFlag_EnableJitDebug) { + flags |= svc::CreateProcessParameterFlag_EnableJitDebug; } /* Set Enable ASLR. */ - if (!(ldr_flags & CreateProcessFlag_DisableAslr)) { - flags |= svc::CreateProcessFlag_EnableAslr; + if (!(ldr_flags & CreateProcessParameterFlag_DisableAslr)) { + flags |= svc::CreateProcessParameterFlag_EnableAslr; } /* Set Is Application. */ if (IsApplication(meta)) { - flags |= svc::CreateProcessFlag_IsApplication; + flags |= svc::CreateProcessParameterFlag_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; + if (meta_flags & Npdm::MetaFlag0_OptimizeMemoryAllocation) { + flags |= svc::CreateProcessParameterFlag_OptimizeMemoryAllocation; } } } @@ -459,19 +459,19 @@ namespace ams::ldr { switch (GetPoolPartition(meta)) { case Acid::PoolPartition_Application: if (IsApplet(meta)) { - flags |= svc::CreateProcessFlag_PoolPartitionApplet; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; } else { - flags |= svc::CreateProcessFlag_PoolPartitionApplication; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplication; } break; case Acid::PoolPartition_Applet: - flags |= svc::CreateProcessFlag_PoolPartitionApplet; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; break; case Acid::PoolPartition_System: - flags |= svc::CreateProcessFlag_PoolPartitionSystem; + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystem; break; case Acid::PoolPartition_SystemNonSecure: - flags |= svc::CreateProcessFlag_PoolPartitionSystemNonSecure; + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure; break; default: R_THROW(ldr::ResultInvalidMeta()); @@ -479,18 +479,18 @@ namespace ams::ldr { } 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; + flags |= svc::CreateProcessParameterFlag_DeprecatedUseSecureMemory; } } /* 11.0.0+/meso Set Disable DAS merge. */ - if (meta_flags & Npdm::MetaFlag_DisableDeviceAddressSpaceMerge) { - flags |= svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; + if (meta_flags & Npdm::MetaFlag0_DisableDeviceAddressSpaceMerge) { + flags |= svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge; } /* 18.0.0+/meso Set Alias region extra size. */ - if (meta_flags & Npdm::MetaFlag_EnableAliasRegionExtraSize) { - flags |= svc::CreateProcessFlag_EnableAliasRegionExtraSize; + if (meta_flags & Npdm::MetaFlag0_EnableAddressSanitizer) { + flags |= svc::CreateProcessParameterFlag_EnableAddressSanitizer; } *out = flags; @@ -508,7 +508,7 @@ namespace ams::ldr { out->reslimit = resource_limit; /* Set flags. */ - R_TRY(GetCreateProcessFlags(std::addressof(out->flags), meta, flags)); + R_TRY(GetCreateProcessParameterFlags(std::addressof(out->flags), meta, flags)); /* 3.0.0+ System Resource Size. */ if (hos::GetVersion() >= hos::Version_3_0_0) { @@ -518,7 +518,7 @@ namespace ams::ldr { /* Validate system resource usage. */ if (meta->npdm->system_resource_size) { /* Process must be 64-bit. */ - R_UNLESS((out->flags & svc::CreateProcessFlag_AddressSpace64Bit), ldr::ResultInvalidMeta()); + R_UNLESS((out->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit39), ldr::ResultInvalidMeta()); /* Process must be application or applet. */ R_UNLESS(IsApplication(meta) || IsApplet(meta), ldr::ResultInvalidMeta()); @@ -586,21 +586,21 @@ namespace ams::ldr { 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: + switch (out_param->flags & svc::CreateProcessParameterFlag_AddressSpaceMask) { + case svc::CreateProcessParameterFlag_AddressSpace32Bit: + case svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved: aslr_start = svc::AddressSmallMap32Start; aslr_size = svc::AddressSmallMap32Size; break; - case svc::CreateProcessFlag_AddressSpace64BitDeprecated: + case svc::CreateProcessParameterFlag_AddressSpace64Bit36: aslr_start = svc::AddressSmallMap36Start; aslr_size = svc::AddressSmallMap36Size; break; - case svc::CreateProcessFlag_AddressSpace64Bit: + case svc::CreateProcessParameterFlag_AddressSpace64Bit39: aslr_start = svc::AddressMap39Start; aslr_size = svc::AddressMap39Size; break; - case svc::CreateProcessFlag_AddressSpace64Bit64KPage: + case svc::CreateProcessParameterFlag_AddressSpace64Bit42: aslr_start = svc::AddressMap42Start; aslr_size = svc::AddressMap42Size; break; @@ -608,7 +608,7 @@ namespace ams::ldr { } } else { /* On 1.0.0, only 2 address space types existed. */ - if (out_param->flags & svc::CreateProcessFlag_AddressSpace64BitDeprecated) { + if (out_param->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit36) { aslr_start = svc::AddressSmallMap36Start; aslr_size = svc::AddressSmallMap36Size; } else { @@ -621,7 +621,7 @@ namespace ams::ldr { /* Set Create Process output. */ uintptr_t aslr_slide = 0; size_t free_size = (aslr_size - total_size); - if (out_param->flags & svc::CreateProcessFlag_EnableAslr) { + if (out_param->flags & svc::CreateProcessParameterFlag_EnableAslr) { aslr_slide = GenerateSecureRandom(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize; } @@ -864,8 +864,8 @@ namespace ams::ldr { 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); + const auto as_type = GetProcessAddressSpace(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::ProcessAddressSpace_64Bit39 || as_type == Npdm::ProcessAddressSpace_64Bit36); /* Register all NSOs. */ for (int i = 0; i < ctx.nso_count; i++) { diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index 8a4d7ba16..dc1fbbdf2 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -86,14 +86,14 @@ namespace ams::pm::impl { R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_hook_to_create_application_process_event), os::EventClearMode_AutoClear, true)); } - inline u32 GetLoaderCreateProcessFlags(u32 launch_flags) { + inline u32 GetLoaderCreateProcessParameterFlags(u32 launch_flags) { u32 ldr_flags = 0; if (ShouldSignalOnException(launch_flags) || (hos::GetVersion() >= hos::Version_2_0_0 && !ShouldStartSuspended(launch_flags))) { - ldr_flags |= ldr::CreateProcessFlag_EnableDebug; + ldr_flags |= ldr::CreateProcessParameterFlag_EnableJitDebug; } if (ShouldDisableAslr(launch_flags)) { - ldr_flags |= ldr::CreateProcessFlag_DisableAslr; + ldr_flags |= ldr::CreateProcessParameterFlag_DisableAslr; } return ldr_flags; @@ -166,7 +166,7 @@ namespace ams::pm::impl { WaitResourceAvailable(std::addressof(program_info)); /* Actually create the process. */ - R_TRY(ldr::pm::CreateProcess(std::addressof(process_handle), pin_id, GetLoaderCreateProcessFlags(flags), GetResourceLimitHandle(std::addressof(program_info)), attrs.program_attrs)); + R_TRY(ldr::pm::CreateProcess(std::addressof(process_handle), pin_id, GetLoaderCreateProcessParameterFlags(flags), GetResourceLimitHandle(std::addressof(program_info)), attrs.program_attrs)); } /* Get the process id. */ From 8ad3efdd798f48beccc3f80df2949ca23e3ed545 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 17 Sep 2026 21:44:25 +0100 Subject: [PATCH 26/52] loader: add missing EnableShadowStack to process flags --- .../loader/source/ldr_process_creation.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 019f7c1e8..9b8386081 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -400,12 +400,13 @@ namespace ams::ldr { } Result GetCreateProcessParameterFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { - const u8 meta_flags = meta->npdm->flags0; + const u8 meta_flags0 = meta->npdm->flags0; + const u8 meta_flags1 = meta->npdm->flags1; u32 flags = 0; /* Set Is64Bit. */ - if (meta_flags & Npdm::MetaFlag0_Is64BitInstruction) { + if (meta_flags0 & Npdm::MetaFlag0_Is64BitInstruction) { flags |= svc::CreateProcessParameterFlag_64Bit; } @@ -446,7 +447,7 @@ namespace ams::ldr { /* 7.0.0+: Set OptimizeMemoryAllocation if relevant. */ if (hos::GetVersion() >= hos::Version_7_0_0) { - if (meta_flags & Npdm::MetaFlag0_OptimizeMemoryAllocation) { + if (meta_flags0 & Npdm::MetaFlag0_OptimizeMemoryAllocation) { flags |= svc::CreateProcessParameterFlag_OptimizeMemoryAllocation; } } @@ -483,15 +484,20 @@ namespace ams::ldr { } } - /* 11.0.0+/meso Set Disable DAS merge. */ - if (meta_flags & Npdm::MetaFlag0_DisableDeviceAddressSpaceMerge) { + /* 11.0.0+/meso Set Disable DAS Merge. */ + if (meta_flags0 & Npdm::MetaFlag0_DisableDeviceAddressSpaceMerge) { flags |= svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge; } - /* 18.0.0+/meso Set Alias region extra size. */ - if (meta_flags & Npdm::MetaFlag0_EnableAddressSanitizer) { + /* 18.0.0+/meso Set Enable Address Sanitizer . */ + if (meta_flags0 & Npdm::MetaFlag0_EnableAddressSanitizer) { flags |= svc::CreateProcessParameterFlag_EnableAddressSanitizer; } + + /* 23.0.0+/meso Set Enable Shadow Stack. */ + if (meta_flags1 & Npdm::MetaFlag1_EnableShadowStack) { + flags |= svc::CreateProcessParameterFlag_EnableShadowStack; + } *out = flags; R_SUCCEED(); From 1d308207f77c32394ed89d2cfb83d8900529875e Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 17 Sep 2026 10:59:43 +0200 Subject: [PATCH 27/52] pinmux: configure logport via exosphere --- .../include/stratosphere/spl/spl_api.hpp | 6 +++ .../nintendo/nx/pinmux_board_driver_api.cpp | 52 ++++++++++--------- .../board/nintendo/nx/pinmux_build_config.hpp | 20 ------- 3 files changed, 33 insertions(+), 45 deletions(-) delete mode 100644 libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp diff --git a/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp b/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp index 3d60504fe..ec6de4ebc 100644 --- a/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/spl/spl_api.hpp @@ -89,6 +89,12 @@ namespace ams::spl { return ::ams::spl::GetConfigBool(::ams::spl::ConfigItem::ExosphereForceEnableUsb30); } + inline std::pair GetLogConfiguration() { + u64 v; + R_ABORT_UNLESS(::ams::spl::GetConfig(std::addressof(v), ::ams::spl::ConfigItem::ExosphereLogConfiguration)); + return std::make_pair(static_cast(v >> 32), static_cast(v)); + } + Result SetBootReason(BootReasonValue boot_reason); Result GetBootReason(BootReasonValue *out); diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp index e687f9bbc..5212724cc 100644 --- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp +++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp @@ -17,7 +17,6 @@ #include "pinmux_pad_index.hpp" #include "pinmux_board_driver_api.hpp" #include "pinmux_platform_pads.hpp" -#include "pinmux_build_config.hpp" namespace ams::pinmux::driver::board::nintendo::nx { @@ -101,30 +100,33 @@ namespace ams::pinmux::driver::board::nintendo::nx { UpdateSinglePinmuxPad({ PinmuxPadIndex_Sdmmc2Dat7, 0x2000, 0x2000 }); } - #if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART) - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart2Tx, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart2Cts, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - #endif - #if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART) - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart3Tx, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - UpdateSinglePinmuxPad({ - .index = PinmuxPadIndex_Uart3Cts, - .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, - .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, - }); - #endif + auto [log_port, log_baud_rate] = spl::GetLogConfiguration(); + AMS_UNUSED(log_baud_rate); + + if (log_port == 1) { + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Tx, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Cts, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + } + if (log_port == 2) { + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Tx, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Cts, + .option = (u32)PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input, + .option_mask = (u32)PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir, + }); + } } void SetInitialDrivePadConfig() { diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp deleted file mode 100644 index 530af4325..000000000 --- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once -#include - -// #define AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART -// #define AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART \ No newline at end of file From af14725916aa5c11c4df52bce7b7efec188814eb Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 17 Sep 2026 11:57:47 +0200 Subject: [PATCH 28/52] kern: handle SVE exceptions --- .../source/arch/arm64/kern_exception_handlers.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp index 6c21b455b..712ac7bd7 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp @@ -196,6 +196,7 @@ namespace ams::kern::arch::arm64 { case EsrEc_Cp14McrMrc: case EsrEc_Cp14Mrrc: case EsrEc_SystemInstruction64: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: type = ams::svc::ExceptionType_InstructionAbort; @@ -267,6 +268,7 @@ namespace ams::kern::arch::arm64 { switch (ec) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: { @@ -474,6 +476,7 @@ namespace ams::kern::arch::arm64 { switch (ec) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: { @@ -564,6 +567,7 @@ namespace ams::kern::arch::arm64 { switch ((esr >> 26) & 0x3F) { case EsrEc_Unknown: case EsrEc_IllegalExecution: + case EsrEc_SveZen: case EsrEc_BkptInstruction: case EsrEc_BrkInstruction: far = context->pc; From f40b85cd5dd69c52687a2811c9326d179caffc37 Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 17 Sep 2026 11:58:12 +0200 Subject: [PATCH 29/52] loader: pass enable shadow stack flag --- stratosphere/loader/source/ldr_process_creation.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 9b8386081..fc976a495 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -499,6 +499,11 @@ namespace ams::ldr { flags |= svc::CreateProcessParameterFlag_EnableShadowStack; } + /* 23.0.0+/meso Set EnableShadowStack. */ + if (meta->npdm->flags2 & Npdm::MetaFlag2_EnableShadowStack) { + flags |= svc::CreateProcessFlag_EnableShadowStack; + } + *out = flags; R_SUCCEED(); } From 4e917d700fc25b1f992f67993b2d368f653d5e68 Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 17 Sep 2026 16:27:44 +0200 Subject: [PATCH 30/52] kern: allocate the shadow stack --- .../mesosphere/kern_k_memory_block.hpp | 3 ++ .../include/mesosphere/kern_k_thread.hpp | 5 ++- .../libmesosphere/source/kern_k_thread.cpp | 33 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index 9e9e9c7a4..7e95a98cb 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -119,6 +119,8 @@ namespace ams::kern { KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, + + KMemoryState_ShadowStack = ams::svc::MemoryState_ShadowStack, }; #if 1 @@ -147,6 +149,7 @@ namespace ams::kern { static_assert(KMemoryState_CodeOut == 0x04402015); static_assert(KMemoryState_Coverage == 0x00002016); /* TODO: Is this correct? */ static_assert(KMemoryState_Insecure == 0x055C3817); + static_assert(KMemoryState_ShadowStack == 0x0000001A); #endif enum KMemoryPermission : u8 { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index f6193dd71..429af04ec 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -29,6 +29,7 @@ namespace ams::kern { class KProcess; class KConditionVariable; class KAddressArbiter; + class KPageBuffer; using KThreadFunction = void (*)(uintptr_t); @@ -305,6 +306,8 @@ namespace ams::kern { u32 *m_light_ipc_data; KProcessAddress m_tls_address; void *m_tls_heap_address; + KProcessAddress m_shadow_stack_address; + KPageBuffer *m_shadow_stack_page; KLightLock m_activity_pause_lock; SyncObjectBuffer m_sync_object_buffer; s64 m_schedule_count; @@ -347,7 +350,7 @@ namespace ams::kern { : KAutoObjectWithSlabHeapAndContainer(util::ConstantInitialize), KTimerTask(util::ConstantInitialize), m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{}, m_caller_save_fpu_registers{}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null}, m_parent{}, - m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize}, + m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null}, m_tls_heap_address{}, m_shadow_stack_address{Null}, m_shadow_stack_page{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize}, m_schedule_count{}, m_last_scheduled_tick{}, m_per_core_priority_queue_entry{}, m_wait_queue{}, m_held_lock_info_list{}, m_waiting_lock_info{}, m_pinned_waiter_list{}, m_debug_params{}, m_closed_object{}, m_address_key_value{}, m_suspend_request_flags{}, m_suspend_allowed_flags{}, m_synced_index{}, m_wait_result{svc::ResultNoSynchronizationObject()}, m_debug_exception_result{ResultSuccess()}, m_base_priority{}, m_base_priority_on_unpin{}, diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index 9cf5ea862..374640710 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -214,6 +214,10 @@ namespace ams::kern { m_tls_address = 0; m_tls_heap_address = 0; + /* Set shadow stack address and page. */ + m_shadow_stack_address = Null; + m_shadow_stack_page = nullptr; + /* Set parent and condvar tree. */ m_parent = nullptr; m_condvar_tree = nullptr; @@ -281,6 +285,29 @@ namespace ams::kern { R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); m_tls_heap_address = owner->GetThreadLocalRegionPointer(m_tls_address); std::memset(m_tls_heap_address, 0, ams::svc::ThreadLocalRegionSize); + + /* If the owning process has a shadow stack, allocate and map a page for this thread. */ + if (owner->GetCreateProcessFlags() & ams::svc::CreateProcessFlag_EnableShadowStack) { + /* Allocate the backing page. */ + KPageBuffer *page = KPageBuffer::AllocateChecked(); + if (page == nullptr) { + owner->DeleteThreadLocalRegion(m_tls_address); + m_tls_address = Null; + R_THROW(svc::ResultOutOfMemory()); + } + + /* If we fail to map the page, free it and undo the TLS region we just created. */ + ON_RESULT_FAILURE { + KPageBuffer::Free(page); + owner->DeleteThreadLocalRegion(m_tls_address); + m_tls_address = Null; + }; + + /* Map the page into the process's shadow stack region. */ + R_TRY(owner->GetPageTable().MapPages(std::addressof(m_shadow_stack_address), 1, PageSize, page->GetPhysicalAddress(), KMemoryState_ShadowStack, KMemoryPermission_UserReadWrite)); + + m_shadow_stack_page = page; + } } /* Set parent, if relevant. */ @@ -390,6 +417,12 @@ namespace ams::kern { m_parent->UnregisterThread(this); } + /* If the thread has a shadow stack, unmap and free its page. */ + if (m_shadow_stack_address != Null) { + MESOSPHERE_R_ABORT_UNLESS(m_parent->GetPageTable().UnmapPages(m_shadow_stack_address, 1, KMemoryState_ShadowStack)); + KPageBuffer::Free(m_shadow_stack_page); + } + /* If the thread has a local region, delete it. */ if (m_tls_address != Null) { m_parent->DeleteThreadLocalRegion(m_tls_address); From 3cfac4c2d8e4ea30d9d2450e2d25c8c082c76576 Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 03:38:26 +0200 Subject: [PATCH 31/52] kern: switch RNG to CTR-DBRG --- .../nintendo/nx/kern_k_system_control.hpp | 4 +- .../mesosphere/kern_k_system_control_base.hpp | 31 ++- libraries/libmesosphere/libmesosphere.mk | 2 + .../nintendo/nx/kern_k_system_control.cpp | 40 +--- .../libmesosphere/source/kern_k_process.cpp | 10 + .../source/kern_k_system_control_base.cpp | 204 +++++++++++++++--- .../vapours/crypto/impl/crypto_aes_impl.hpp | 4 +- .../impl/crypto_aes_impl.arch.arm64.cpp | 7 +- 8 files changed, 229 insertions(+), 73 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp index 8e1829849..ae12326a1 100644 --- a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp @@ -51,9 +51,7 @@ namespace ams::kern::board::nintendo::nx { static NOINLINE u32 GetCreateProcessMemoryPool(); /* Randomness. */ - static void GenerateRandom(u64 *dst, size_t count); - static u64 GenerateRandomRange(u64 min, u64 max); - static u64 GenerateRandomU64(); + static void GenerateRandomBytesForUninitialized(void *dst, size_t size); /* Privileged Access. */ static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp index 3d7ea5310..cc8f0f317 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp @@ -33,17 +33,30 @@ namespace ams::kern { class KResourceLimit; + struct CtrDrbgContext { + u8 v[16]; + u8 key[16]; + u8 seed[32]; + u8 temp[32]; + u32 reseed_counter; + u8 output[128]; + u32 remaining; + }; + class KSystemControlBase { public: /* This can be overridden as needed. */ static constexpr size_t SecureAppletMemorySize = 0; protected: - /* Nintendo uses std::mt19937_t for randomness. */ - /* To save space (and because mt19337_t isn't secure anyway), */ - /* We will use TinyMT. */ - static constinit inline bool s_uninitialized_random_generator{true}; - static constinit inline util::TinyMT s_random_generator{util::ConstantInitialize}; - static constinit inline KSpinLock s_random_lock; + static constinit inline bool s_uninitialized_random_generator{true}; + static constinit inline CtrDrbgContext s_random_generator{}; + static constinit inline KSpinLock s_random_lock; + private: + /* Randomness helpers. */ + static void InitializeRandomGenerator(const void *seed, size_t size); + static void ReseedRandomGeneratorInternal(); + static u32 GenerateRandomU32(); + static u64 GenerateRandomU64Internal(); public: class Init { private: @@ -66,7 +79,7 @@ namespace ams::kern { static u64 GenerateRandomRange(u64 min, u64 max); }; protected: - static NOINLINE void InitializePhase1Base(u64 seed); + static NOINLINE void InitializePhase1Base(const void *seed, size_t size); public: /* Initialization. */ static NOINLINE void ConfigureKTargetSystem(); @@ -78,6 +91,10 @@ namespace ams::kern { static void GenerateRandom(u64 *dst, size_t count); static u64 GenerateRandomRange(u64 min, u64 max); static u64 GenerateRandomU64(); + static void ReseedRandomGenerator(); + + /* Obtains random bytes while the generator is not yet initialized. Board-provided. */ + static void GenerateRandomBytesForUninitialized(void *dst, size_t size); /* Register access Access. */ static Result ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value); diff --git a/libraries/libmesosphere/libmesosphere.mk b/libraries/libmesosphere/libmesosphere.mk index 2ab310a25..7998d5f78 100644 --- a/libraries/libmesosphere/libmesosphere.mk +++ b/libraries/libmesosphere/libmesosphere.mk @@ -108,6 +108,8 @@ $(OFILES_SRC) : $(HFILES_BIN) kern_libc_generic.o: CFLAGS += -fno-builtin +crypto_aes_impl.arch.arm64.o: CXXFLAGS := $(filter-out -mgeneral-regs-only,$(CXXFLAGS)) + #--------------------------------------------------------------------------------- %_bin.h %.bin.o : %.bin #--------------------------------------------------------------------------------- diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index bb7581c83..2cc6f0f81 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -74,12 +74,6 @@ namespace ams::kern::board::nintendo::nx { return value; } - ALWAYS_INLINE u64 GenerateRandomU64FromSmc() { - u64 value; - smc::GenerateRandomBytes(std::addressof(value), sizeof(value)); - return value; - } - ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) { u64 value; smc::GetConfig(&value, 1, which); @@ -477,9 +471,9 @@ namespace ams::kern::board::nintendo::nx { /* Initialize random and resource limit. */ { - u64 seed; - smc::GenerateRandomBytes(std::addressof(seed), sizeof(seed)); - KSystemControlBase::InitializePhase1Base(seed); + u8 seed[32]; + smc::GenerateRandomBytes(seed, sizeof(seed)); + KSystemControlBase::InitializePhase1Base(seed, sizeof(seed)); } /* Configure the Kernel Carveout region. */ @@ -524,32 +518,8 @@ namespace ams::kern::board::nintendo::nx { } /* Randomness. */ - void KSystemControl::GenerateRandom(u64 *dst, size_t count) { - MESOSPHERE_INIT_ABORT_UNLESS(count <= 7); - smc::GenerateRandomBytes(dst, count * sizeof(u64)); - } - - u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { - KScopedInterruptDisable intr_disable; - KScopedSpinLock lk(s_random_lock); - - - if (AMS_LIKELY(!s_uninitialized_random_generator)) { - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); - } else { - return KSystemControlBase::GenerateUniformRange(min, max, GenerateRandomU64FromSmc); - } - } - - u64 KSystemControl::GenerateRandomU64() { - KScopedInterruptDisable intr_disable; - KScopedSpinLock lk(s_random_lock); - - if (AMS_LIKELY(!s_uninitialized_random_generator)) { - return s_random_generator.GenerateRandomU64(); - } else { - return GenerateRandomU64FromSmc(); - } + void KSystemControl::GenerateRandomBytesForUninitialized(void *dst, size_t size) { + smc::GenerateRandomBytes(dst, size); } void KSystemControl::SleepSystem() { diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index ad49b783b..88694cfea 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -264,6 +264,11 @@ namespace ams::kern { m_is_default_application_system_resource = false; m_is_immortal = immortal; + /* Reseed the random generator on application launch. */ + if (params.flags & ams::svc::CreateProcessFlag_IsApplication) { + KSystemControl::ReseedRandomGenerator(); + } + /* Setup our system resource. */ if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { /* Create a secure system resource. */ @@ -332,6 +337,11 @@ namespace ams::kern { m_is_default_application_system_resource = false; m_is_immortal = false; + /* Reseed the random generator on application launch. */ + if (params.flags & ams::svc::CreateProcessFlag_IsApplication) { + KSystemControl::ReseedRandomGenerator(); + } + /* Get the memory sizes. */ const size_t code_num_pages = params.code_num_pages; const size_t system_resource_num_pages = params.system_resource_num_pages; diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index 38c507486..ffe172846 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #include +#include #if defined(ATMOSPHERE_ARCH_ARM64) #include #endif @@ -27,6 +28,55 @@ namespace ams::kern { } + namespace { + + /* The kernel is otherwise FP/SIMD-free, but AES instructions require the NEON registers. */ + class KScopedFpuEnable { + private: + u64 m_saved_cpacr_el1; + public: + ALWAYS_INLINE KScopedFpuEnable() : m_saved_cpacr_el1(cpu::GetCpacrEl1()) { + cpu::SetCpacrEl1(m_saved_cpacr_el1 | 0x100000); + cpu::InstructionMemoryBarrier(); + } + + ALWAYS_INLINE ~KScopedFpuEnable() { + cpu::SetCpacrEl1(m_saved_cpacr_el1); + cpu::InstructionMemoryBarrier(); + } + }; + + ALWAYS_INLINE void CtrDrbgIncrementCounter(u8 *v) { + for (size_t i = 16; i > 0; --i) { + if ((++v[i - 1]) != 0) { + break; + } + } + } + + void CtrDrbgUpdate(CtrDrbgContext &ctx, const u8 *data) { + /* Initialize the block cipher with the current key. */ + ams::crypto::impl::AesImpl<16> aes; + aes.Initialize(ctx.key, sizeof(ctx.key), true); + + /* Generate two blocks of new key/counter material. */ + CtrDrbgIncrementCounter(ctx.v); + aes.EncryptBlock(ctx.temp + 0, 16, ctx.v, 16); + CtrDrbgIncrementCounter(ctx.v); + aes.EncryptBlock(ctx.temp + 16, 16, ctx.v, 16); + + /* Mix in the provided data. */ + for (size_t i = 0; i < sizeof(ctx.temp); ++i) { + ctx.temp[i] ^= data[i]; + } + + /* Update the key and counter. */ + std::memcpy(ctx.key, ctx.temp, sizeof(ctx.key)); + std::memcpy(ctx.v, ctx.temp + sizeof(ctx.key), sizeof(ctx.v)); + } + + } + /* Initialization. */ size_t KSystemControlBase::Init::GetRealMemorySize() { return ams::kern::MainMemorySize; @@ -102,25 +152,13 @@ namespace ams::kern { /* Randomness for Initialization. */ void KSystemControlBase::Init::GenerateRandom(u64 *dst, size_t count) { - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - const u64 seed = KHardwareTimer::GetTick(); - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } - for (size_t i = 0; i < count; ++i) { - dst[i] = s_random_generator.GenerateRandomU64(); + dst[i] = KSystemControlBase::GenerateRandomU64(); } } u64 KSystemControlBase::Init::GenerateRandomRange(u64 min, u64 max) { - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - const u64 seed = KHardwareTimer::GetTick(); - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } - - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); + return KSystemControlBase::GenerateRandomRange(min, max); } /* System Initialization. */ @@ -135,15 +173,17 @@ namespace ams::kern { } /* Initialize random and resource limit. */ - KSystemControlBase::InitializePhase1Base(KHardwareTimer::GetTick()); + u64 seed[4]; + for (size_t i = 0; i < util::size(seed); ++i) { + seed[i] = KHardwareTimer::GetTick(); + } + KSystemControlBase::InitializePhase1Base(seed, sizeof(seed)); } - void KSystemControlBase::InitializePhase1Base(u64 seed) { - /* Initialize the rng, if we somehow haven't already. */ - if (AMS_UNLIKELY(s_uninitialized_random_generator)) { - s_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); - s_uninitialized_random_generator = false; - } + void KSystemControlBase::InitializePhase1Base(const void *seed, size_t size) { + /* Initialize the random generator. */ + KSystemControlBase::InitializeRandomGenerator(seed, size); + s_uninitialized_random_generator = false; /* Initialize debug logging. */ KDebugLog::Initialize(); @@ -213,13 +253,97 @@ namespace ams::kern { R_THROW(svc::ResultNotImplemented()); } + /* Randomness helpers. Assume the caller holds the random lock. */ + void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) { + MESOSPHERE_ASSERT(size == sizeof(s_random_generator.seed)); + + KScopedFpuEnable fp_enabled; + auto &ctx = s_random_generator; + + /* Zero the counter and key, then derive the initial state from the seed. */ + std::memset(ctx.v, 0, sizeof(ctx.v)); + std::memset(ctx.key, 0, sizeof(ctx.key)); + std::memcpy(ctx.seed, seed, sizeof(ctx.seed)); + + CtrDrbgUpdate(ctx, ctx.seed); + + ctx.reseed_counter = 1; + ctx.remaining = 0; + } + + void KSystemControlBase::ReseedRandomGeneratorInternal() { + KScopedFpuEnable fp_enabled; + auto &ctx = s_random_generator; + + /* Pull fresh entropy, then derive a new state from it. */ + KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); + CtrDrbgUpdate(ctx, ctx.seed); + + ctx.remaining = 0; + ctx.reseed_counter = 1; + } + + u32 KSystemControlBase::GenerateRandomU32() { + auto &ctx = s_random_generator; + + if (ctx.remaining == 0) { + KScopedFpuEnable fp_enabled; + + /* Reseed if we've exhausted this generation's entropy, otherwise use zero additional input. */ + if (ctx.reseed_counter <= 0x7FFFFFF0) { + std::memset(ctx.seed, 0, sizeof(ctx.seed)); + } else { + KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); + CtrDrbgUpdate(ctx, ctx.seed); + ctx.remaining = 0; + std::memset(ctx.seed, 0, sizeof(ctx.seed)); + ctx.reseed_counter = 1; + } + + /* Generate eight blocks of output. */ + ams::crypto::impl::AesImpl<16> aes; + aes.Initialize(ctx.key, sizeof(ctx.key), true); + for (size_t i = 0; i < 8; ++i) { + CtrDrbgIncrementCounter(ctx.v); + aes.EncryptBlock(ctx.output + 16 * i, 16, ctx.v, 16); + } + + /* Derive the next state. */ + CtrDrbgUpdate(ctx, ctx.seed); + + ++ctx.reseed_counter; + ctx.remaining = 32; + } + + /* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */ + const size_t index = 32 - ctx.remaining; + u32 value; + std::memcpy(std::addressof(value), ctx.output + 4 * index, sizeof(value)); + std::memset(ctx.output + 4 * index, 0, sizeof(value)); + --ctx.remaining; + return value; + } + + u64 KSystemControlBase::GenerateRandomU64Internal() { + /* Fall back to the board's raw source while the generator is uninitialized. */ + if (AMS_UNLIKELY(s_uninitialized_random_generator)) { + u64 value; + KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value)); + return value; + } + + const u64 high = KSystemControlBase::GenerateRandomU32(); + const u64 low = KSystemControlBase::GenerateRandomU32(); + return (high << 32) | low; + } + /* Randomness. */ void KSystemControlBase::GenerateRandom(u64 *dst, size_t count) { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); for (size_t i = 0; i < count; ++i) { - dst[i] = s_random_generator.GenerateRandomU64(); + dst[i] = KSystemControlBase::GenerateRandomU64Internal(); } } @@ -227,14 +351,46 @@ namespace ams::kern { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); - return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); }); + /* While uninitialized, fall back to a raw single-draw modulo. */ + if (AMS_UNLIKELY(s_uninitialized_random_generator)) { + u64 value; + KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value)); + + const u64 difference = max - min; + if (difference == std::numeric_limits::max()) { + return value; + } + + return min + (value % (difference + 1)); + } + + return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return KSystemControlBase::GenerateRandomU64Internal(); }); } u64 KSystemControlBase::GenerateRandomU64() { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(s_random_lock); - return s_random_generator.GenerateRandomU64(); + return KSystemControlBase::GenerateRandomU64Internal(); + } + + void KSystemControlBase::ReseedRandomGenerator() { + /* This must be unreachable while the generator is uninitialized. */ + MESOSPHERE_ABORT_UNLESS(!s_uninitialized_random_generator); + + KScopedInterruptDisable intr_disable; + KScopedSpinLock lk(s_random_lock); + + KSystemControlBase::ReseedRandomGeneratorInternal(); + } + + void KSystemControlBase::GenerateRandomBytesForUninitialized(void *dst, size_t size) { + /* The default board has no secure monitor; fall back to the hardware timer. */ + u8 *dst_8 = static_cast(dst); + for (size_t offset = 0; offset < size; offset += sizeof(u64)) { + const u64 tick = KHardwareTimer::GetTick(); + std::memcpy(dst_8 + offset, std::addressof(tick), std::min(sizeof(tick), size - offset)); + } } void KSystemControlBase::SleepSystem() { diff --git a/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp b/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp index 066687771..42e72d7d6 100644 --- a/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp +++ b/libraries/libvapours/include/vapours/crypto/impl/crypto_aes_impl.hpp @@ -33,7 +33,7 @@ namespace ams::crypto::impl { #ifdef ATMOSPHERE_IS_EXOSPHERE int m_slot; #endif - #ifdef ATMOSPHERE_IS_STRATOSPHERE + #if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) u32 m_round_keys[RoundKeySize / sizeof(u32)]; #endif public: @@ -43,7 +43,7 @@ namespace ams::crypto::impl { void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const; void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const; - #ifdef ATMOSPHERE_IS_STRATOSPHERE + #if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) const u8 *GetRoundKey() const { return reinterpret_cast(m_round_keys); } diff --git a/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp b/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp index 35fdf4fa2..c07a20f2e 100644 --- a/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp +++ b/libraries/libvapours/source/crypto/impl/crypto_aes_impl.arch.arm64.cpp @@ -14,13 +14,16 @@ * along with this program. If not, see . */ #include -#if defined(ATMOSPHERE_IS_STRATOSPHERE) +#if defined(ATMOSPHERE_IS_MESOSPHERE) +#include +#endif +#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) #include #endif namespace ams::crypto::impl { -#if defined(ATMOSPHERE_IS_STRATOSPHERE) +#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE) namespace { From 85f119a5c4b3d734443eaf99c7f8d87dd668dcad Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 07:21:22 +0200 Subject: [PATCH 32/52] kern/loader: fix git rebase errors --- libraries/libmesosphere/source/kern_k_process.cpp | 4 ++-- libraries/libmesosphere/source/kern_k_thread.cpp | 2 +- stratosphere/loader/source/ldr_process_creation.cpp | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 88694cfea..0bdcaab85 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -265,7 +265,7 @@ namespace ams::kern { m_is_immortal = immortal; /* Reseed the random generator on application launch. */ - if (params.flags & ams::svc::CreateProcessFlag_IsApplication) { + if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) { KSystemControl::ReseedRandomGenerator(); } @@ -338,7 +338,7 @@ namespace ams::kern { m_is_immortal = false; /* Reseed the random generator on application launch. */ - if (params.flags & ams::svc::CreateProcessFlag_IsApplication) { + if (params.flags & ams::svc::CreateProcessParameterFlag_IsApplication) { KSystemControl::ReseedRandomGenerator(); } diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index 374640710..b2ec76302 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -287,7 +287,7 @@ namespace ams::kern { std::memset(m_tls_heap_address, 0, ams::svc::ThreadLocalRegionSize); /* If the owning process has a shadow stack, allocate and map a page for this thread. */ - if (owner->GetCreateProcessFlags() & ams::svc::CreateProcessFlag_EnableShadowStack) { + if (owner->GetCreateProcessParameterFlags() & ams::svc::CreateProcessParameterFlag_EnableShadowStack) { /* Allocate the backing page. */ KPageBuffer *page = KPageBuffer::AllocateChecked(); if (page == nullptr) { diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index fc976a495..9b8386081 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -499,11 +499,6 @@ namespace ams::ldr { flags |= svc::CreateProcessParameterFlag_EnableShadowStack; } - /* 23.0.0+/meso Set EnableShadowStack. */ - if (meta->npdm->flags2 & Npdm::MetaFlag2_EnableShadowStack) { - flags |= svc::CreateProcessFlag_EnableShadowStack; - } - *out = flags; R_SUCCEED(); } From 866c831f7a26e02d5ba31889487fea5f54077397 Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 07:22:42 +0200 Subject: [PATCH 33/52] spl/vapours: move CTR_DRBG to vapours --- .../libstratosphere/source/crypto/crypto_csrng.os.generic.cpp | 4 ++-- libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp | 4 ++-- .../include/vapours/crypto/impl/crypto_ctr_drbg.hpp} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename libraries/{libstratosphere/source/spl/impl/spl_ctr_drbg.hpp => libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp} (99%) diff --git a/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp b/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp index ecb9e2d0a..414953364 100644 --- a/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp +++ b/libraries/libstratosphere/source/crypto/crypto_csrng.os.generic.cpp @@ -14,14 +14,14 @@ * along with this program. If not, see . */ #include -#include "../spl/impl/spl_ctr_drbg.hpp" +#include #include namespace ams::crypto { namespace { - using Drbg = ::ams::spl::impl::CtrDrbg; + using Drbg = ::ams::crypto::impl::CtrDrbg; constinit util::TypedStorage g_drbg = {}; diff --git a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp index c5c450b1b..93821f85b 100644 --- a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp +++ b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #include -#include "spl_ctr_drbg.hpp" +#include #include "spl_device_address_mapper.hpp" #include "spl_key_slot_cache.hpp" @@ -29,7 +29,7 @@ namespace ams::spl::impl { namespace { /* Drbg type. */ - using Drbg = CtrDrbg; + using Drbg = crypto::impl::CtrDrbg; /* Convenient defines. */ #if defined(ATMOSPHERE_OS_HORIZON) diff --git a/libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp b/libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp similarity index 99% rename from libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp rename to libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp index b615f02c1..6454fae02 100644 --- a/libraries/libstratosphere/source/spl/impl/spl_ctr_drbg.hpp +++ b/libraries/libvapours/include/vapours/crypto/impl/crypto_ctr_drbg.hpp @@ -14,9 +14,9 @@ * along with this program. If not, see . */ #pragma once -#include +#include -namespace ams::spl::impl { +namespace ams::crypto::impl { constexpr inline int BitsPerByte = BITSIZEOF(u8); From 1d6e593abad4f95a8ffec132ec76e7da83d0dd8b Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 07:25:48 +0200 Subject: [PATCH 34/52] kern: use CTR_DRBG from vapours --- .../mesosphere/kern_k_system_control_base.hpp | 14 --- .../source/kern_k_system_control_base.cpp | 105 ++++++------------ 2 files changed, 36 insertions(+), 83 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp index cc8f0f317..95d601959 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp @@ -33,24 +33,10 @@ namespace ams::kern { class KResourceLimit; - struct CtrDrbgContext { - u8 v[16]; - u8 key[16]; - u8 seed[32]; - u8 temp[32]; - u32 reseed_counter; - u8 output[128]; - u32 remaining; - }; - class KSystemControlBase { public: /* This can be overridden as needed. */ static constexpr size_t SecureAppletMemorySize = 0; - protected: - static constinit inline bool s_uninitialized_random_generator{true}; - static constinit inline CtrDrbgContext s_random_generator{}; - static constinit inline KSpinLock s_random_lock; private: /* Randomness helpers. */ static void InitializeRandomGenerator(const void *seed, size_t size); diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index ffe172846..c92bbe60e 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -14,7 +14,8 @@ * along with this program. If not, see . */ #include -#include +#include +#include #if defined(ATMOSPHERE_ARCH_ARM64) #include #endif @@ -46,33 +47,19 @@ namespace ams::kern { } }; - ALWAYS_INLINE void CtrDrbgIncrementCounter(u8 *v) { - for (size_t i = 16; i > 0; --i) { - if ((++v[i - 1]) != 0) { - break; - } - } - } + using RandomGenerator = ::ams::crypto::impl::CtrDrbg<::ams::crypto::AesEncryptor128, 16, false>; - void CtrDrbgUpdate(CtrDrbgContext &ctx, const u8 *data) { - /* Initialize the block cipher with the current key. */ - ams::crypto::impl::AesImpl<16> aes; - aes.Initialize(ctx.key, sizeof(ctx.key), true); + constexpr size_t RandomGeneratorOutputSize = 8 * RandomGenerator::OutSize; + constexpr u32 RandomGeneratorOutputCount = RandomGeneratorOutputSize / sizeof(u32); - /* Generate two blocks of new key/counter material. */ - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.temp + 0, 16, ctx.v, 16); - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.temp + 16, 16, ctx.v, 16); + constinit util::TypedStorage s_random_generator = {}; + constinit bool s_uninitialized_random_generator = true; + constinit u8 s_random_output[RandomGeneratorOutputSize] = {}; + constinit u32 s_random_remaining = 0; + constinit KSpinLock s_random_lock; - /* Mix in the provided data. */ - for (size_t i = 0; i < sizeof(ctx.temp); ++i) { - ctx.temp[i] ^= data[i]; - } - - /* Update the key and counter. */ - std::memcpy(ctx.key, ctx.temp, sizeof(ctx.key)); - std::memcpy(ctx.v, ctx.temp + sizeof(ctx.key), sizeof(ctx.v)); + void GenerateRandomSeed(void *dst, size_t size) { + KSystemControl::GenerateRandomBytesForUninitialized(dst, size); } } @@ -255,72 +242,52 @@ namespace ams::kern { /* Randomness helpers. Assume the caller holds the random lock. */ void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) { - MESOSPHERE_ASSERT(size == sizeof(s_random_generator.seed)); + MESOSPHERE_ASSERT(size == RandomGenerator::SeedSize); KScopedFpuEnable fp_enabled; - auto &ctx = s_random_generator; - /* Zero the counter and key, then derive the initial state from the seed. */ - std::memset(ctx.v, 0, sizeof(ctx.v)); - std::memset(ctx.key, 0, sizeof(ctx.key)); - std::memcpy(ctx.seed, seed, sizeof(ctx.seed)); + /* Construct the generator, and derive the initial state from the seed. */ + util::ConstructAt(s_random_generator); + util::GetReference(s_random_generator).Initialize(seed, size, nullptr, 0, nullptr, 0); - CtrDrbgUpdate(ctx, ctx.seed); - - ctx.reseed_counter = 1; - ctx.remaining = 0; + s_random_remaining = 0; } void KSystemControlBase::ReseedRandomGeneratorInternal() { KScopedFpuEnable fp_enabled; - auto &ctx = s_random_generator; /* Pull fresh entropy, then derive a new state from it. */ - KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); - CtrDrbgUpdate(ctx, ctx.seed); + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + util::GetReference(s_random_generator).Reseed(seed, sizeof(seed), nullptr, 0); - ctx.remaining = 0; - ctx.reseed_counter = 1; + s_random_remaining = 0; } u32 KSystemControlBase::GenerateRandomU32() { - auto &ctx = s_random_generator; - - if (ctx.remaining == 0) { + if (s_random_remaining == 0) { KScopedFpuEnable fp_enabled; - /* Reseed if we've exhausted this generation's entropy, otherwise use zero additional input. */ - if (ctx.reseed_counter <= 0x7FFFFFF0) { - std::memset(ctx.seed, 0, sizeof(ctx.seed)); - } else { - KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); - CtrDrbgUpdate(ctx, ctx.seed); - ctx.remaining = 0; - std::memset(ctx.seed, 0, sizeof(ctx.seed)); - ctx.reseed_counter = 1; + auto &drbg = util::GetReference(s_random_generator); + + /* Derive the next state, or reseed if we've exhausted this generation's entropy. */ + if (AMS_UNLIKELY(!drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0))) { + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + drbg.Reseed(seed, sizeof(seed), nullptr, 0); + + MESOSPHERE_ABORT_UNLESS(drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0)); } - /* Generate eight blocks of output. */ - ams::crypto::impl::AesImpl<16> aes; - aes.Initialize(ctx.key, sizeof(ctx.key), true); - for (size_t i = 0; i < 8; ++i) { - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.output + 16 * i, 16, ctx.v, 16); - } - - /* Derive the next state. */ - CtrDrbgUpdate(ctx, ctx.seed); - - ++ctx.reseed_counter; - ctx.remaining = 32; + s_random_remaining = RandomGeneratorOutputCount; } /* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */ - const size_t index = 32 - ctx.remaining; + const size_t index = RandomGeneratorOutputCount - s_random_remaining; u32 value; - std::memcpy(std::addressof(value), ctx.output + 4 * index, sizeof(value)); - std::memset(ctx.output + 4 * index, 0, sizeof(value)); - --ctx.remaining; + std::memcpy(std::addressof(value), s_random_output + sizeof(value) * index, sizeof(value)); + std::memset(s_random_output + sizeof(value) * index, 0, sizeof(value)); + --s_random_remaining; return value; } From 518e4947445f5cd8aad2a7022138ef6bd1d26628 Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 08:35:14 +0200 Subject: [PATCH 35/52] ams: fix libnx build in dockerfile --- Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7421d0037..577f336af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,7 +56,7 @@ RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfir # rm -rf /tmp/switch-tools # Install libnx from Git (optional) -# ENV LIBNX_REV=dbcc1beafc6b47b5ffbeb8ba82463a7d45da40bb +# ENV LIBNX_REV=146c3d1446d35546943c7b6cfcd479bc1f5e9b67 # RUN cd /tmp && \ # mkdir -p /tmp/libnx && \ # cd /tmp/libnx && \ @@ -65,9 +65,8 @@ RUN dkp-pacman -S switch-tools hactool --noconfirm && dkp-pacman -Syu --noconfir # git fetch --depth 1 origin $LIBNX_REV && \ # git reset --hard FETCH_HEAD && \ # make -j$(nproc) && \ -# mkdir -p /opt/devkitpro/libnx && \ # cd nx && \ -# make DESTDIR=/opt/devkitpro/libnx install && \ +# make install && \ # cd /tmp && \ # rm -rf /tmp/libnx From 1748644f81b96ace157d0a9e145844376deb6498 Mon Sep 17 00:00:00 2001 From: Lazy-Coder-03 Date: Sun, 20 Sep 2026 21:38:31 +0530 Subject: [PATCH 36/52] htcfs: fix swapped path lengths in RenameFile/RenameDirectory --- .../libstratosphere/source/htcfs/htcfs_client_impl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp b/libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp index 50fa2ee81..313f54a9c 100644 --- a/libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp +++ b/libraries/libstratosphere/source/htcfs/htcfs_client_impl.cpp @@ -532,8 +532,8 @@ namespace ams::htcfs { Header request, response; /* Create header for the request. */ - const auto old_path_len = std::strlen(new_path); - const auto new_path_len = std::strlen(old_path); + const auto old_path_len = std::strlen(old_path); + const auto new_path_len = std::strlen(new_path); m_header_factory.MakeRenameFileHeader(std::addressof(request), old_path_len, new_path_len, case_sensitive); /* Send the request to the host. */ @@ -734,8 +734,8 @@ namespace ams::htcfs { Header request, response; /* Create header for the request. */ - const auto old_path_len = std::strlen(new_path); - const auto new_path_len = std::strlen(old_path); + const auto old_path_len = std::strlen(old_path); + const auto new_path_len = std::strlen(new_path); m_header_factory.MakeRenameDirectoryHeader(std::addressof(request), old_path_len, new_path_len, case_sensitive); /* Send the request to the host. */ From 56d301ef5cf60f290e5a5fdb226027462528f6fd Mon Sep 17 00:00:00 2001 From: Ludwig Date: Sun, 20 Sep 2026 22:17:14 +0200 Subject: [PATCH 37/52] fs.mitm: add danganronpa v3 to games needing stolen heap for layeredfs --- stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp index 484e078ce..93f983fc1 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp @@ -36,6 +36,11 @@ namespace ams::mitm::fs { }; constexpr const ApplicationWithDynamicHeapInfo ApplicationsWithDynamicHeap[] = { + /* Danganronpa V3: Killing Harmony Anniversary Edition. */ + /* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */ + /* Unknown heap sensitivity. */ + { 0x010063F014176000, 16_MB, 0_MB }, + /* Until Then. */ /* Requirement ~34 MB. */ /* No particular heap sensitivity. */ From 0411dbfddae9b5fe5fdce3bf871b14586e692dc7 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 20 Sep 2026 23:23:56 +0100 Subject: [PATCH 38/52] ro: start implementing 23.0.0 changes --- .../stratosphere/ro/impl/ro_ro_interface.hpp | 14 +- .../include/stratosphere/ro/ro_types.hpp | 117 +++++++--- .../include/stratosphere/rocrt/rocrt.hpp | 9 +- .../include/vapours/results/ro_results.hpp | 8 +- .../ro/source/impl/ro_service_impl.cpp | 206 +++++++++++++++--- stratosphere/ro/source/ro_ro_service.cpp | 2 +- stratosphere/ro/source/ro_ro_service.hpp | 2 +- 7 files changed, 280 insertions(+), 78 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/ro/impl/ro_ro_interface.hpp b/libraries/libstratosphere/include/stratosphere/ro/impl/ro_ro_interface.hpp index 8a993f65b..e84a6fcf2 100644 --- a/libraries/libstratosphere/include/stratosphere/ro/impl/ro_ro_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/ro/impl/ro_ro_interface.hpp @@ -19,12 +19,12 @@ #include #include -#define AMS_RO_I_RO_INTERFACE_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, MapManualLoadModuleMemory, (sf::Out out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size), (out_load_address, client_pid, nro_address, nro_size, bss_address, bss_size)) \ - AMS_SF_METHOD_INFO(C, H, 1, Result, UnmapManualLoadModuleMemory, (const sf::ClientProcessId &client_pid, u64 nro_address), (client_pid, nro_address)) \ - AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size), (client_pid, nrr_address, nrr_size)) \ - AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address), (client_pid, nrr_address)) \ - AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h), (client_pid, std::move(process_h))) \ - AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterProcessModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h), (client_pid, nrr_address, nrr_size, std::move(process_h)), hos::Version_7_0_0) +#define AMS_RO_I_RO_INTERFACE_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, MapManualLoadModuleMemory, (sf::Out out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size), (out_load_address, client_pid, nro_address, nro_size, bss_address, bss_size)) \ + AMS_SF_METHOD_INFO(C, H, 1, Result, UnmapManualLoadModuleMemory, (const sf::ClientProcessId &client_pid, u64 nro_address), (client_pid, nro_address)) \ + AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size), (client_pid, nrr_address, nrr_size)) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterModuleInfo, (const sf::ClientProcessId &client_pid, u64 nrr_address), (client_pid, nrr_address)) \ + AMS_SF_METHOD_INFO(C, H, 4, Result, RegisterProcessHandle, (const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h), (client_pid, std::move(process_h))) \ + AMS_SF_METHOD_INFO(C, H, 10, Result, RegisterModuleInfoWithUserProcessHandle, (const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h), (client_pid, nrr_address, nrr_size, std::move(process_h)), hos::Version_7_0_0) AMS_SF_DEFINE_INTERFACE(ams::ro::impl, IRoInterface, AMS_RO_I_RO_INTERFACE_INTERFACE_INFO, 0xA52C55A9) diff --git a/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp b/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp index 4a1ce2684..86c57d0fc 100644 --- a/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ro/ro_types.hpp @@ -17,6 +17,7 @@ #pragma once #include #include +#include namespace ams::ro { @@ -40,30 +41,30 @@ namespace ams::ro { u64 program_id_mask; u64 program_id_pattern; u8 reserved_10[0x10]; - u8 modulus[RsaKeySize]; - u8 signature[RsaKeySize]; + u8 public_key[RsaKeySize]; + u8 sign[RsaKeySize]; }; static_assert(sizeof(NrrCertification) == NrrCertification::RsaKeySize + NrrCertification::SignedSize); class NrrHeader { public: - static constexpr u32 Magic = util::FourCC<'N','R','R','0'>::Code; + static constexpr u32 Signature = util::FourCC<'N','R','R','0'>::Code; private: - u32 m_magic; + u32 m_signature; u32 m_key_generation; u8 m_reserved_08[0x08]; NrrCertification m_certification; - u8 m_signature[0x100]; + u8 m_sign[0x100]; ncm::ProgramId m_program_id; u32 m_size; u8 m_nrr_kind; /* 7.0.0+ */ u8 m_reserved_33D[3]; - u32 m_hashes_offset; - u32 m_num_hashes; + u32 m_hash_list_offset_address; + u32 m_num_hash; u8 m_reserved_348[8]; public: bool IsMagicValid() const { - return m_magic == Magic; + return m_signature == Signature; } bool IsProgramIdValid() const { @@ -85,11 +86,11 @@ namespace ams::ro { } u32 GetNumHashes() const { - return m_num_hashes; + return m_num_hash; } size_t GetHashesOffset() const { - return m_hashes_offset; + return m_hash_list_offset_address; } uintptr_t GetHashes() const { @@ -101,7 +102,7 @@ namespace ams::ro { } const u8 *GetCertificationSignature() const { - return m_certification.signature; + return m_certification.sign; } const u8 *GetCertificationSignedArea() const { @@ -109,11 +110,11 @@ namespace ams::ro { } const u8 *GetCertificationModulus() const { - return m_certification.modulus; + return m_certification.public_key; } const u8 *GetSignature() const { - return m_signature; + return m_sign; } const u8 *GetSignedArea() const { @@ -131,32 +132,45 @@ namespace ams::ro { constexpr size_t NrrHeader::GetSignedAreaOffset() { return AMS_OFFSETOF(NrrHeader, m_program_id); } + + static constexpr size_t RocrtHeaderSize = 0x10; + struct RocrtHeader { + rocrt::ModuleHeaderLocation module_header_location; + u32 reserved; + }; + static_assert(sizeof(RocrtHeader) == RocrtHeaderSize); class NroHeader { public: - static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code; + static constexpr u32 Signature = util::FourCC<'N','R','O','0'>::Code; static constexpr u32 FlagAlignedHeader = 1; + static constexpr u32 FlagCompress = 2; private: - u32 m_entrypoint_insn; - u32 m_mod_offset; - u8 m_reserved_08[0x8]; - u32 m_magic; - u8 m_version; + RocrtHeader m_rocrt; + u32 m_signature; + u32 m_version; u32 m_size; u32 m_flags; - u32 m_text_offset; + u32 m_text_memory_offset; u32 m_text_size; - u32 m_ro_offset; + u32 m_ro_memory_offset; u32 m_ro_size; - u32 m_rw_offset; - u32 m_rw_size; + u32 m_data_memory_offset; + u32 m_data_size; u32 m_bss_size; - u8 m_reserved_3C[0x4]; + u32 m_additional_header_offset; /* 23.0.0+ */ ModuleId m_module_id; - u8 m_reserved_60[0x20]; + u32 m_dso_handle_offset; + u32 m_reserved_64; + u32 m_embedded_offset; + u32 m_embedded_size; + u32 m_dyn_str_offset; + u32 m_dyn_str_size; + u32 m_dyn_sym_offset; + u32 m_dyn_sym_size; public: bool IsMagicValid() const { - return m_magic == Magic; + return m_signature == Signature; } u32 GetVersion() const { @@ -174,9 +188,13 @@ namespace ams::ro { bool IsAlignedHeader() const { return m_flags & FlagAlignedHeader; } + + bool IsCompress() const { + return m_flags & FlagCompress; + } u32 GetTextOffset() const { - return m_text_offset; + return m_text_memory_offset; } u32 GetTextSize() const { @@ -184,7 +202,7 @@ namespace ams::ro { } u32 GetRoOffset() const { - return m_ro_offset; + return m_ro_memory_offset; } u32 GetRoSize() const { @@ -192,21 +210,60 @@ namespace ams::ro { } u32 GetRwOffset() const { - return m_rw_offset; + return m_data_memory_offset; } u32 GetRwSize() const { - return m_rw_size; + return m_data_size; } u32 GetBssSize() const { return m_bss_size; } + + u32 GetAdditionalHeaderOffset() const { + return m_additional_header_offset; + } const ModuleId *GetModuleId() const { return std::addressof(m_module_id); } }; static_assert(sizeof(NroHeader) == 0x80, "NroHeader definition!"); + + class AdditionalNroHeader { + public: + static constexpr u32 Signature = util::FourCC<'N','R','A','0'>::Code; + private: + u32 m_signature; + u8 m_reserved_04[0xC]; + u32 m_compressed_size; + u32 m_reserved_14; + u32 m_hash_size; + u32 m_hash_offset; + u8 m_reserved_20[0x40]; + u8 m_hash[0x20]; + public: + bool IsMagicValid() const { + return m_signature == Signature; + } + + u32 GetCompressedSize() const { + return m_compressed_size; + } + + u32 GetHashSize() const { + return m_hash_size; + } + + u32 GetHashOffset() const { + return m_hash_offset; + } + + const u8 *GetHash() const { + return m_hash; + } + }; + static_assert(sizeof(AdditionalNroHeader) == 0x80, "AdditionalNroHeader definition!"); } diff --git a/libraries/libstratosphere/include/stratosphere/rocrt/rocrt.hpp b/libraries/libstratosphere/include/stratosphere/rocrt/rocrt.hpp index 6a4c0ce82..0758c9648 100644 --- a/libraries/libstratosphere/include/stratosphere/rocrt/rocrt.hpp +++ b/libraries/libstratosphere/include/stratosphere/rocrt/rocrt.hpp @@ -29,11 +29,18 @@ namespace ams::rocrt { u32 exception_info_start_offset; u32 exception_info_end_offset; u32 module_offset; + u32 relro_start_offset; /* 19.0.0+ */ + u32 full_relro_end_offset; /* 19.0.0+ */ + u32 nx_debug_link_start_offset; /* 19.0.0+ */ + u32 nx_debug_link_end_offset; /* 19.0.0+ */ + u32 note_gnu_build_id_start_offset; /* 19.0.0+ */ + u32 note_gnu_build_id_end_offset; /* 19.0.0+ */ }; struct ModuleHeaderLocation { - u32 pad; + u32 version; u32 header_offset; + u32 version_offset; }; constexpr inline u32 CheckModuleHeaderSignature(const ModuleHeader *header) { diff --git a/libraries/libvapours/include/vapours/results/ro_results.hpp b/libraries/libvapours/include/vapours/results/ro_results.hpp index c187749dc..e3ad6b53f 100644 --- a/libraries/libvapours/include/vapours/results/ro_results.hpp +++ b/libraries/libvapours/include/vapours/results/ro_results.hpp @@ -25,18 +25,20 @@ namespace ams::ro { R_DEFINE_ERROR_RESULT(OutOfAddressSpace, 2); R_DEFINE_ERROR_RESULT(AlreadyLoaded, 3); R_DEFINE_ERROR_RESULT(InvalidNro, 4); - + R_DEFINE_ERROR_RESULT(NotFound, 5); R_DEFINE_ERROR_RESULT(InvalidNrr, 6); R_DEFINE_ERROR_RESULT(TooManyNro, 7); R_DEFINE_ERROR_RESULT(TooManyNrr, 8); R_DEFINE_ERROR_RESULT(NotAuthorized, 9); R_DEFINE_ERROR_RESULT(InvalidNrrKind, 10); - + R_DEFINE_ERROR_RESULT(InvalidBssSize, 11); + + R_DEFINE_ERROR_RESULT(NotImplemented, 1022); R_DEFINE_ERROR_RESULT(InternalError, 1023); R_DEFINE_ERROR_RESULT(InvalidAddress, 1025); R_DEFINE_ERROR_RESULT(InvalidSize, 1026); - + R_DEFINE_ERROR_RESULT(InvalidCurrentMemory, 1027); R_DEFINE_ERROR_RESULT(NotLoaded, 1028); R_DEFINE_ERROR_RESULT(NotRegistered, 1029); R_DEFINE_ERROR_RESULT(InvalidSession, 1030); diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index 0eee275eb..6beff3c8f 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -47,7 +47,7 @@ namespace ams::ro::impl { } }; static_assert(sizeof(Sha256Hash) == sizeof(Sha256Hash::hash)); - + struct NroInfo { u64 base_address; u64 nro_heap_address; @@ -55,8 +55,10 @@ namespace ams::ro::impl { u64 bss_heap_address; u64 bss_heap_size; u64 code_size; + u64 ro_size; /* 23.0.0+ */ u64 rw_size; ModuleId module_id; + bool is_compress; /* 23.0.0+ */ }; struct NrrInfo { @@ -72,7 +74,17 @@ namespace ams::ro::impl { u8 cached_signed_area[sizeof(NrrHeader) - NrrHeader::GetSignedAreaOffset()]; Sha256Hash signed_area_hash; }; - + + struct AdditionalNroHeaderInfo { + u32 signature; + u8 reserved_04[0xC]; + u32 compressed_size; + u32 reserved_14; + u32 hash_size; + u32 hash_offset; + u8 reserved_20[0x40]; + }; + struct ProcessContext { private: bool m_nro_in_use[MaxNroInfos]{}; @@ -246,21 +258,12 @@ namespace ams::ro::impl { R_THROW(ro::ResultNotAuthorized()); } - - Result ValidateNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, bool *out_aligned_header, u64 base_address, u64 expected_nro_size, u64 expected_bss_size) { - /* Map the NRO. */ - void *mapped_memory = nullptr; - R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) { - R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace()) - } R_END_TRY_CATCH; - - /* When we're done, unmap the memory. */ - ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, m_process_handle, base_address, expected_nro_size); }; - + + Result ValidateNro(NroHeader **out_header, AdditionalNroHeaderInfo **out_additional_header_info, void *out_additional_header_hash, u8 *mapped_memory, u64 expected_nro_size, u64 expected_bss_size) { /* Validate header. */ - const NroHeader *header = static_cast(mapped_memory); + NroHeader *header = reinterpret_cast(mapped_memory); R_UNLESS(header->IsMagicValid(), ro::ResultInvalidNro()); - + /* Read sizes from header. */ const u64 nro_size = header->GetSize(); const u64 text_ofs = header->GetTextOffset(); @@ -270,17 +273,28 @@ namespace ams::ro::impl { const u64 rw_ofs = header->GetRwOffset(); const u64 rw_size = header->GetRwSize(); const u64 bss_size = header->GetBssSize(); - - /* Validate sizes meet expected. */ - R_UNLESS(nro_size == expected_nro_size, ro::ResultInvalidNro()); - R_UNLESS(bss_size == expected_bss_size, ro::ResultInvalidNro()); - + /* Validate all sizes are aligned. */ R_UNLESS(util::IsAligned(text_size, os::MemoryPageSize), ro::ResultInvalidNro()); R_UNLESS(util::IsAligned(ro_size, os::MemoryPageSize), ro::ResultInvalidNro()); R_UNLESS(util::IsAligned(rw_size, os::MemoryPageSize), ro::ResultInvalidNro()); R_UNLESS(util::IsAligned(bss_size, os::MemoryPageSize), ro::ResultInvalidNro()); + /* Validate sizes meet expected. */ + R_UNLESS(nro_size == expected_nro_size, ro::ResultInvalidNro()); + + /* Account for compression when checking bss size. */ + if (header->IsCompress()) { + R_UNLESS((bss_size - expected_nro_size + (rw_ofs + rw_size)) == expected_bss_size, ro::ResultInvalidBssSize()); + } else { + /* 23.0.0+ uses the new error code here too. */ + if (hos::GetVersion() >= hos::Version_23_0_0) { + R_UNLESS(bss_size == expected_bss_size, ro::ResultInvalidBssSize()); + } else { + R_UNLESS(bss_size == expected_bss_size, ro::ResultInvalidNro()); + } + } + /* Validate sections are in order. */ R_UNLESS(text_ofs <= ro_ofs, ro::ResultInvalidNro()); R_UNLESS(ro_ofs <= rw_ofs, ro::ResultInvalidNro()); @@ -289,24 +303,119 @@ namespace ams::ro::impl { R_UNLESS(text_ofs == 0, ro::ResultInvalidNro()); R_UNLESS(text_ofs + text_size == ro_ofs, ro::ResultInvalidNro()); R_UNLESS(ro_ofs + ro_size == rw_ofs, ro::ResultInvalidNro()); - R_UNLESS(rw_ofs + rw_size == nro_size, ro::ResultInvalidNro()); - + + /* Only check data section if not using compression. */ + if (!header->IsCompress()) { + R_UNLESS(rw_ofs + rw_size == nro_size, ro::ResultInvalidNro()); + } + /* Verify NRO hash. */ R_TRY(this->ValidateHasNroHash(header)); /* Check if NRO has already been loaded. */ const ModuleId *module_id = header->GetModuleId(); R_UNLESS(R_FAILED(this->GetNroInfoByModuleId(nullptr, module_id)), ro::ResultAlreadyLoaded()); + + /* Validate compression related fields. */ + if (header->IsCompress()) { + const u64 additional_header_offset = header->GetAdditionalHeaderOffset(); + + /* Compression must have aligned header as well. */ + R_UNLESS(header->IsAlignedHeader(), ro::ResultInvalidNro()); + + /* Validate additional header offset. */ + R_UNLESS(additional_header_offset == 0x80, ro::ResultInvalidNro()); + + /* Validate additional header. */ + AdditionalNroHeader *additional_header = reinterpret_cast(mapped_memory + additional_header_offset); + R_UNLESS(additional_header->IsMagicValid(), ro::ResultInvalidNro()); + + /* Read sizes from header. */ + const u64 hash_size = additional_header->GetHashSize(); + const u64 hash_offset = additional_header->GetHashOffset(); + const u64 compressed_size = additional_header->GetCompressedSize(); + + /* Validate additional header hash size and offset. */ + R_UNLESS(hash_size == 0x20, ro::ResultInvalidNro()); + R_UNLESS(hash_offset == 0xE0, ro::ResultInvalidNro()); + + /* Copy the additional header hash to output. */ + std::memcpy(out_additional_header_hash, additional_header->GetHash(), hash_size); + + /* Validate compressed size. */ + R_UNLESS(rw_ofs + rw_size > nro_size, ro::ResultInvalidNro()); + R_UNLESS(compressed_size >= 0x1000, ro::ResultInvalidNro()); + R_UNLESS(util::AlignUp(compressed_size, os::MemoryPageSize) == expected_nro_size, ro::ResultInvalidNro()); + + /* Copy the additional header info to output. This is AdditionalNroHeader minus the hash. */ + std::memcpy(out_additional_header_info, additional_header, sizeof(*additional_header) - hash_size); + } else { + /* Explicitly clear additional header hash and info. */ + std::memset(out_additional_header_hash, 0, crypto::Sha256Generator::HashSize); + std::memset(out_additional_header_info, 0, sizeof(AdditionalNroHeaderInfo)); + } + + /* Copy the header to output. */ + *out_header = header; + R_SUCCEED(); + } + + Result DecompressNro(u8 *mapped_nro, u64 expected_nro_size, const NroHeader *nro_header, u32 compressed_size) { + /* TODO */ + AMS_UNUSED(mapped_nro, expected_nro_size, nro_header, compressed_size); + R_SUCCEED(); + } + + Result CheckAdditionalHeaderHash(const u8 *mapped_nro, const void *additional_nro_header_hash, size_t additional_nro_header_hash_size, u64 rw_ofs, u64 rw_size) { + /* Calculate hash. */ + Sha256Hash nro_rw_hash; + crypto::GenerateSha256(std::addressof(nro_rw_hash), additional_nro_header_hash_size, mapped_nro + 0x1000, (rw_ofs + rw_size) - 0x1000); + + /* Compare the hashes. */ + const Sha256Hash *expected_hash = reinterpret_cast(additional_nro_header_hash); + if (*expected_hash != nro_rw_hash) { + R_THROW(ro::ResultInvalidNro()); + } + R_SUCCEED(); + } + Result ParseNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, bool *out_aligned_header, bool *out_is_compress, u64 base_address, u64 expected_nro_size, u64 expected_bss_size) { + /* Map the NRO. */ + void *mapped_memory = nullptr; + R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) { + R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace()) + } R_END_TRY_CATCH; + + /* When we're done, unmap the memory. */ + ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, m_process_handle, base_address, expected_nro_size); }; + + /* ValidateNro */ + NroHeader *nro_header = nullptr; + AdditionalNroHeaderInfo *additional_nro_header_info = nullptr; + u8 additional_nro_header_hash[crypto::Sha256Generator::HashSize]; + R_TRY(this->ValidateNro(std::addressof(nro_header), std::addressof(additional_nro_header_info), std::addressof(additional_nro_header_hash), static_cast(mapped_memory), expected_nro_size, expected_bss_size)); + + /* DecompressNro */ + if (nro_header->IsCompress()) { + R_TRY(this->DecompressNro(static_cast(mapped_memory), expected_nro_size, nro_header, additional_nro_header_info->compressed_size)); + + /* CheckAdditionalHeaderHash */ + if (nro_header->GetAdditionalHeaderOffset() != 0) { + R_TRY(this->CheckAdditionalHeaderHash(static_cast(mapped_memory), std::addressof(additional_nro_header_hash), sizeof(additional_nro_header_hash), nro_header->GetRwOffset(), nro_header->GetRwSize())); + } + } + /* Apply patches to NRO. */ - LocateAndApplyIpsPatchesToModule(module_id, static_cast(mapped_memory), nro_size); + const ModuleId *module_id = nro_header->GetModuleId(); + LocateAndApplyIpsPatchesToModule(module_id, static_cast(mapped_memory), nro_header->GetSize()); /* Copy to output. */ *out_module_id = *module_id; - *out_rx_size = text_size; - *out_ro_size = ro_size; - *out_rw_size = rw_size; - *out_aligned_header = header->IsAlignedHeader(); + *out_rx_size = nro_header->GetTextSize(); + *out_ro_size = nro_header->GetRoSize(); + *out_rw_size = nro_header->GetRwSize(); + *out_aligned_header = nro_header->IsAlignedHeader(); + *out_is_compress = nro_header->IsCompress(); R_SUCCEED(); } @@ -547,26 +656,34 @@ namespace ams::ro::impl { /* Check we have space for a new NRO. */ NroInfo *nro_info = nullptr; R_TRY(context->GetFreeNroInfo(std::addressof(nro_info))); - nro_info->nro_heap_address = nro_address; - nro_info->nro_heap_size = nro_size; - nro_info->bss_heap_address = bss_address; - nro_info->bss_heap_size = bss_size; - + /* Map the NRO. */ R_TRY(MapNro(std::addressof(nro_info->base_address), context->GetProcessHandle(), nro_address, nro_size, bss_address, bss_size)); ON_RESULT_FAILURE { UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size); }; - /* Validate the NRO (parsing region extents). */ + /* Parse the NRO. */ u64 rx_size = 0, ro_size = 0, rw_size = 0; bool aligned_header = false; - R_TRY(context->ValidateNro(std::addressof(nro_info->module_id), std::addressof(rx_size), std::addressof(ro_size), std::addressof(rw_size), std::addressof(aligned_header), nro_info->base_address, nro_size, bss_size)); + bool is_compress = false; + R_TRY(context->ParseNro(std::addressof(nro_info->module_id), std::addressof(rx_size), std::addressof(ro_size), std::addressof(rw_size), std::addressof(aligned_header), std::addressof(is_compress), nro_info->base_address, nro_size, bss_size)); /* Set NRO perms. */ R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, rx_size, ro_size, rw_size + bss_size, aligned_header)); context->SetNroInfoInUse(nro_info, true); - nro_info->code_size = rx_size + ro_size; + nro_info->nro_heap_address = nro_address; + nro_info->nro_heap_size = nro_size; + nro_info->bss_heap_address = bss_address; + nro_info->bss_heap_size = bss_size; + if (hos::GetVersion() >= hos::Version_23_0_0) { + nro_info->code_size = rx_size; + nro_info->ro_size = ro_size; + } else { + nro_info->code_size = rx_size + ro_size; + nro_info->ro_size = 0; + } nro_info->rw_size = rw_size; + nro_info->is_compress = is_compress; *out_address = nro_info->base_address; R_SUCCEED(); } @@ -582,6 +699,25 @@ namespace ams::ro::impl { /* Check the NRO is loaded. */ NroInfo *nro_info = nullptr; R_TRY(context->GetNroInfoByAddress(std::addressof(nro_info), nro_address)); + + /* Handle compression related mappings. */ + if (nro_info->is_compress) { + const u64 code_address = nro_info->base_address + 0x1000; + const u64 code_size = nro_info->code_size - 0x1000; + + /* Remove code region permissions. */ + R_TRY(os::SetProcessMemoryPermission(context->GetProcessHandle(), code_address, code_size, os::MemoryPermission_None)); + + /* Map the code region. */ + void *mapped_memory = nullptr; + R_TRY(os::MapProcessMemory(std::addressof(mapped_memory), context->GetProcessHandle(), code_address, code_size, ro::impl::GenerateSecureRandom)); + + /* Clear the memory. */ + std::memset(mapped_memory, 0, code_size); + + /* Unmap the code region. */ + os::UnmapProcessMemory(mapped_memory, context->GetProcessHandle(), code_address, code_size); + } /* Unmap. */ const NroInfo nro_backup = *nro_info; diff --git a/stratosphere/ro/source/ro_ro_service.cpp b/stratosphere/ro/source/ro_ro_service.cpp index ec309fb63..e25c326da 100644 --- a/stratosphere/ro/source/ro_ro_service.cpp +++ b/stratosphere/ro/source/ro_ro_service.cpp @@ -60,7 +60,7 @@ namespace ams::ro { R_RETURN(impl::RegisterProcess(std::addressof(m_context_id), std::move(process_h), client_pid.GetValue())); } - Result RoService::RegisterProcessModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h) { + Result RoService::RegisterModuleInfoWithUserProcessHandle(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h) { /* Validate the process. */ R_TRY(impl::ValidateProcess(m_context_id, client_pid.GetValue())); diff --git a/stratosphere/ro/source/ro_ro_service.hpp b/stratosphere/ro/source/ro_ro_service.hpp index a97a9fe15..db5d2f24b 100644 --- a/stratosphere/ro/source/ro_ro_service.hpp +++ b/stratosphere/ro/source/ro_ro_service.hpp @@ -38,7 +38,7 @@ namespace ams::ro { Result RegisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size); Result UnregisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address); Result RegisterProcessHandle(const sf::ClientProcessId &client_pid, sf::CopyHandle &&process_h); - Result RegisterProcessModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h); + Result RegisterModuleInfoWithUserProcessHandle(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle &&process_h); }; static_assert(ro::impl::IsIRoInterface); From 02ce3bc38502f9102207fc5f88a100a2cddb764a Mon Sep 17 00:00:00 2001 From: Lazy-Coder-03 Date: Mon, 21 Sep 2026 13:04:35 +0530 Subject: [PATCH 39/52] kern: only check thread ids pointer when count is nonzero --- libraries/libmesosphere/source/svc/kern_svc_debug.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp index 39db3775b..3eb0958c1 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp @@ -141,11 +141,10 @@ namespace ams::kern::svc { /* Verify that the number of thread ids is valid. */ R_UNLESS((0 <= num_thread_ids && num_thread_ids <= MaximumDebuggableThreadCount), svc::ResultOutOfRange()); - R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_thread_ids.GetUnsafePointer()), num_thread_ids * sizeof(uint64_t)), svc::ResultInvalidPointer()); - /* Copy the threads from userspace. */ uint64_t thread_ids[MaximumDebuggableThreadCount]; if (num_thread_ids > 0) { + R_UNLESS(GetCurrentProcess().GetPageTable().IsSafeUserPointer(KProcessAddress(user_thread_ids.GetUnsafePointer()), num_thread_ids * sizeof(uint64_t)), svc::ResultInvalidPointer()); R_TRY(user_thread_ids.CopyArrayTo(thread_ids, num_thread_ids)); } From 1de771e2646bcff50e48a66a432e01de2b639efd Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 21 Sep 2026 21:20:13 +0100 Subject: [PATCH 40/52] os: ShadowStack is a forbidden region --- .../os/impl/os_address_space_allocator.hpp | 2 +- .../os_aslr_space_manager_impl.os.horizon.hpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libraries/libstratosphere/source/os/impl/os_address_space_allocator.hpp b/libraries/libstratosphere/source/os/impl/os_address_space_allocator.hpp index d0a9f77d5..de7515fd9 100644 --- a/libraries/libstratosphere/source/os/impl/os_address_space_allocator.hpp +++ b/libraries/libstratosphere/source/os/impl/os_address_space_allocator.hpp @@ -33,7 +33,7 @@ namespace ams::os::impl { using AddressType = AddressType_; using SizeType = SizeType_; private: - static constexpr size_t MaxForbiddenRegions = 2; + static constexpr size_t MaxForbiddenRegions = 3; private: InternalCriticalSection m_critical_section; AddressType m_start_page; diff --git a/libraries/libstratosphere/source/os/impl/os_aslr_space_manager_impl.os.horizon.hpp b/libraries/libstratosphere/source/os/impl/os_aslr_space_manager_impl.os.horizon.hpp index 0e4305493..198d68d0b 100644 --- a/libraries/libstratosphere/source/os/impl/os_aslr_space_manager_impl.os.horizon.hpp +++ b/libraries/libstratosphere/source/os/impl/os_aslr_space_manager_impl.os.horizon.hpp @@ -30,7 +30,7 @@ namespace ams::os::impl { static constexpr u64 AslrBase64Bit = 0x0008000000ul; static constexpr u64 AslrSize64Bit = 0x7FF8000000ul; - static constexpr size_t ForbiddenRegionCount = 2; + static constexpr size_t ForbiddenRegionCount = 3; private: static u64 GetAslrInfo(os::NativeHandle process_handle, svc::InfoType type) { u64 value; @@ -75,6 +75,14 @@ namespace ams::os::impl { static u64 GetAliasSpaceSize(os::NativeHandle process_handle = svc::PseudoHandle::CurrentProcess) { return GetAslrInfo(process_handle, svc::InfoType_AliasRegionSize); } + + static u64 GetShadowStackSpaceBeginAddress(os::NativeHandle process_handle = svc::PseudoHandle::CurrentProcess) { + return GetAslrInfo(process_handle, svc::InfoType_ShadowStackRegionAddress); + } + + static u64 GetShadowStackSpaceSize(os::NativeHandle process_handle = svc::PseudoHandle::CurrentProcess) { + return GetAslrInfo(process_handle, svc::InfoType_ShadowStackRegionSize); + } static u64 GetAslrSpaceBeginAddress(os::NativeHandle process_handle = svc::PseudoHandle::CurrentProcess) { return GetAslrInfo(process_handle, svc::InfoType_AslrRegionAddress); @@ -87,6 +95,14 @@ namespace ams::os::impl { void InitializeForbiddenRegions(os::NativeHandle process_handle) { m_forbidden_regions[0] = { .address = GetHeapSpaceBeginAddress(process_handle), .size = GetHeapSpaceSize(process_handle) }; m_forbidden_regions[1] = { .address = GetAliasSpaceBeginAddress(process_handle), .size = GetAliasSpaceSize(process_handle) }; + /* 23.0.0+ added ShadowStack to the forbidden region list. */ + /* Unconditionally create the region, but set it's size to 0 on < 23.0.0. */ + /* This should be fine because the address space allocator discards 0 sized regions without changing the final forbidden region count. */ + if (hos::GetVersion() >= hos::Version_23_0_0) { + m_forbidden_regions[2] = { .address = GetShadowStackSpaceBeginAddress(process_handle), .size = GetShadowStackSpaceSize(process_handle) }; + } else { + m_forbidden_regions[2] = { .address = 0, .size = 0 }; + } } }; From 82f15b6e5d74cfe0ce40cc179a1bd237fa7b4463 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 21 Sep 2026 21:33:12 +0100 Subject: [PATCH 41/52] pm: NotifyBootFinished no longer changes program verification --- .../pm/source/impl/pm_process_manager.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index dc1fbbdf2..95922c979 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -480,13 +480,16 @@ namespace ams::pm::impl { Result NotifyBootFinished() { AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_has_boot_finished, false); if (!s_has_boot_finished) { - /* Set program verification disabled, if we should. */ - /* NOTE: Nintendo does not check the result of this. */ - if (spl::IsDisabledProgramVerification()) { - if (hos::GetVersion() >= hos::Version_10_0_0) { - ldr::pm::SetEnabledProgramVerification(false); - } else { - fsprSetEnabledProgramVerification(false); + /* 23.0.0+ removed this and all usage of spl from the pm sysmodule, both in normal and safe mode FIRM. */ + if (hos::GetVersion() < hos::Version_23_0_0) { + /* Set program verification disabled, if we should. */ + /* NOTE: Nintendo does not check the result of this. */ + if (spl::IsDisabledProgramVerification()) { + if (hos::GetVersion() >= hos::Version_10_0_0) { + ldr::pm::SetEnabledProgramVerification(false); + } else { + fsprSetEnabledProgramVerification(false); + } } } From 21f16ff938ffaf2b655cc00c18b961d717362d5d Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 21 Sep 2026 23:10:09 +0100 Subject: [PATCH 42/52] boot: add missing 18.0.0 change and new 23.0.0 change --- stratosphere/boot/source/boot_check_battery.cpp | 11 ++++++++++- stratosphere/boot/source/boot_pmic_driver.cpp | 13 ++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/stratosphere/boot/source/boot_check_battery.cpp b/stratosphere/boot/source/boot_check_battery.cpp index 33f2396f5..07fea7065 100644 --- a/stratosphere/boot/source/boot_check_battery.cpp +++ b/stratosphere/boot/source/boot_check_battery.cpp @@ -466,12 +466,21 @@ namespace ams::boot { boot::ShutdownSystem(); } } + + /* On 18.0.0+ i2c shutdown is unconditionally disabled here. */ + if (hos::GetVersion() >= hos::Version_18_0_0) { + if (R_FAILED(battery_driver.SetI2cShutdownEnabled(false))) { + boot::ShutdownSystem(); + } + } /* Get the boot reason. */ const auto boot_reason = boot::GetBootReason(); /* Initialize the charger driver. */ - if (R_FAILED(charger_driver.Initialize(boot_reason != spl::BootReason_RtcAlarm2))) + if (R_FAILED(charger_driver.Initialize(boot_reason != spl::BootReason_RtcAlarm2))) { + boot::ShutdownSystem(); + } /* Check that the charger input limit is greater than 150 milli-amps. */ { diff --git a/stratosphere/boot/source/boot_pmic_driver.cpp b/stratosphere/boot/source/boot_pmic_driver.cpp index 893726de7..2c3d80daf 100644 --- a/stratosphere/boot/source/boot_pmic_driver.cpp +++ b/stratosphere/boot/source/boot_pmic_driver.cpp @@ -74,11 +74,14 @@ namespace ams::boot { u8 on_off_1_val = 0; R_ABORT_UNLESS(ReadI2cRegister(m_i2c_session, std::addressof(on_off_1_val), sizeof(on_off_1_val), std::addressof(on_off_1_addr), sizeof(on_off_1_addr))); on_off_1_val |= 0x80; - - /* Finalize the battery on non-Calcio. */ - if (spl::GetHardwareType() != spl::HardwareType::Calcio) { - BatteryDriver battery_driver; - this->FinalizeBattery(battery_driver); + + /* 23.0.0+ no longer finalizes the battery on any hardware type. */ + if (hos::GetVersion() < hos::Version_23_0_0) { + /* Finalize the battery on non-Calcio. */ + if (spl::GetHardwareType() != spl::HardwareType::Calcio) { + BatteryDriver battery_driver; + this->FinalizeBattery(battery_driver); + } } /* Actually write the value to trigger shutdown/reset. */ From 2d0fc65fd8d1bde6224efc67aaebc8c39672caaf Mon Sep 17 00:00:00 2001 From: hexkyz Date: Wed, 23 Sep 2026 00:02:33 +0100 Subject: [PATCH 43/52] kern: implement and comment missing 23.0.0 changes --- .../include/mesosphere/kern_k_process.hpp | 14 +++++-- .../mesosphere/kern_k_target_system.hpp | 3 ++ .../source/arch/arm64/kern_cpu.cpp | 2 + .../arch/arm64/kern_exception_handlers.cpp | 4 +- .../nintendo/nx/kern_k_system_control.cpp | 5 ++- .../board/nintendo/nx/kern_secure_monitor.cpp | 2 + .../source/kern_k_debug_base.cpp | 2 +- .../libmesosphere/source/kern_k_process.cpp | 8 ++-- .../source/kern_k_session_request.cpp | 2 + .../source/svc/kern_svc_exception.cpp | 2 +- .../source/svc/kern_svc_process.cpp | 41 +++++++++++++++---- .../svc/kern_svc_secure_monitor_call.cpp | 2 + .../include/vapours/svc/svc_types_common.hpp | 1 + 13 files changed, 68 insertions(+), 20 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 4a45ade8a..dcc66f7d5 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -113,6 +113,7 @@ namespace ams::kern { u64 m_running_thread_idle_counts[cpu::NumCores]; u64 m_running_thread_switch_counts[cpu::NumCores]; KThread *m_pinned_threads[cpu::NumCores]; + s64 m_exit_tag; util::Atomic m_cpu_time; util::Atomic m_num_process_switches; util::Atomic m_num_thread_switches; @@ -142,11 +143,11 @@ namespace ams::kern { m_pinned_threads[core_id] = nullptr; } public: - explicit KProcess() : m_is_initialized(false) { /* ... */ } + explicit KProcess() : m_is_initialized(false), m_exit_tag(-1ll) { /* ... */ } Result Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal); Result Initialize(const ams::svc::CreateProcessParameter ¶ms, svc::KUserPointer caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); - void Exit(); + void Exit(s64 exit_tag); constexpr const char *GetName() const { return m_name; } @@ -155,10 +156,13 @@ namespace ams::kern { constexpr u64 GetProcessId() const { return m_process_id; } constexpr State GetState() const { return m_state; } + + constexpr s64 GetExitTag() const { return m_exit_tag; } constexpr u64 GetCoreMask() const { return m_capabilities.GetCoreMask(); } constexpr u64 GetPhysicalCoreMask() const { return m_capabilities.GetPhysicalCoreMask(); } constexpr u64 GetPriorityMask() const { return m_capabilities.GetPriorityMask(); } + constexpr u32 GetIntendedKernelMajorVersion() const { return m_capabilities.GetIntendedKernelMajorVersion(); } constexpr s32 GetIdealCoreId() const { return m_ideal_core_id; } constexpr void SetIdealCoreId(s32 core_id) { m_ideal_core_id = core_id; } @@ -184,7 +188,7 @@ namespace ams::kern { constexpr bool IsSuspended() const { return m_is_suspended; } constexpr void SetSuspended(bool suspended) { m_is_suspended = suspended; } - Result Terminate(); + Result Terminate(s64 exit_tag); constexpr bool IsTerminated() const { return m_state == State_Terminated; @@ -410,6 +414,10 @@ namespace ams::kern { this->NotifyAvailable(); } } + + void SetExitTag(s64 exit_tag) { + m_exit_tag = exit_tag; + } ALWAYS_INLINE Result InitializeHandleTable(s32 size) { /* Try to initialize the handle table. */ diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp index 949fd45ba..09cbac7b7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp @@ -26,6 +26,7 @@ namespace ams::kern { private: struct KTargetSystemData { bool is_not_debug_mode; + bool is_not_debug_mode2; bool disable_debug_logging; bool disable_user_exception_handlers; bool disable_debug_memory_fill; @@ -37,6 +38,7 @@ namespace ams::kern { static inline constinit bool s_is_uninitialized = true; static inline constinit const volatile KTargetSystemData s_data = { .is_not_debug_mode = false, + .is_not_debug_mode2 = false, .disable_debug_logging = false, .disable_user_exception_handlers = false, .disable_debug_memory_fill = false, @@ -48,6 +50,7 @@ namespace ams::kern { static ALWAYS_INLINE void SetInitialized() { s_is_uninitialized = false; } public: static ALWAYS_INLINE bool IsDebugMode() { return !(s_is_uninitialized | s_data.is_not_debug_mode); } + static ALWAYS_INLINE bool IsDebugMode2() { return !(s_is_uninitialized | s_data.is_not_debug_mode2); } static ALWAYS_INLINE bool IsDebugLoggingEnabled() { return !(s_is_uninitialized | s_data.disable_debug_logging); } static ALWAYS_INLINE bool IsUserExceptionHandlersEnabled() { return !(s_is_uninitialized | s_data.disable_user_exception_handlers); } static ALWAYS_INLINE bool IsDebugMemoryFillEnabled() { return !(s_is_uninitialized | s_data.disable_debug_memory_fill); } diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index 4839349da..36d7f9b2a 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -220,6 +220,8 @@ namespace ams::kern::arch::arm64::cpu { virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override { MESOSPHERE_UNUSED(interrupt_id); + /* TODO: 23.0.0+ now yields here while m_target_cores doesn't have the current core id bit set. */ + /* Evaluate if we should do the same. */ this->ProcessOperation(); m_target_cores &= ~(1ul << GetCurrentCoreId()); return nullptr; diff --git a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp index 712ac7bd7..bfa6165a0 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp @@ -381,7 +381,7 @@ namespace ams::kern::arch::arm64 { } /* Exit the current process. */ - cur_process.Exit(); + cur_process.Exit(-1ll); } } @@ -548,7 +548,7 @@ namespace ams::kern::arch::arm64 { MESOSPHERE_EXCEPTION_LOG("Exception occurred. "); /* Exit the current process. */ - GetCurrentProcess().Exit(); + GetCurrentProcess().Exit(-1ll); } /* NOTE: This function is called from ASM. */ diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index 2cc6f0f81..20aa5eaa2 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -411,7 +411,10 @@ namespace ams::kern::board::nintendo::nx { { /* Set whether we're in debug mode. */ { - ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode); + ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode); + + /* TODO: 23.0.0+ split debug mode into 2 fields. Implement this properly for better accuracy. */ + ts->is_not_debug_mode2 = ts->is_not_debug_mode; /* If we're not in debug mode, we don't want to initialize uart logging. */ ts->disable_debug_logging = ts->is_not_debug_mode; diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp index d55eb2c70..bd603f9e4 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp @@ -223,6 +223,8 @@ namespace ams::kern::board::nintendo::nx::smc { KScopedInterruptDisable di; /* Ensure we successfully show the error. */ + /* NOTE: On 23.0.0+ the SMC result is discarded. */ + /* The function now ends with an unconditional infinite loop and interrupts are never restored. */ MESOSPHERE_ABORT_UNLESS(ShowErrorImpl(color)); } diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 7150c8a4e..3e71fde77 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -417,7 +417,7 @@ namespace ams::kern { /* Terminate the process. */ /* NOTE: This result is seemingly-intentionally not checked by Nintendo. */ - static_cast(target->Terminate()); + static_cast(target->Terminate(-1ll)); R_SUCCEED(); } diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 0bdcaab85..35648a37a 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -465,7 +465,7 @@ namespace ams::kern { } } - void KProcess::Exit() { + void KProcess::Exit(s64 exit_tag) { MESOSPHERE_ASSERT_THIS(); /* Determine whether we need to start terminating. */ @@ -480,6 +480,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(m_state != State_Terminated); if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_DebugBreak) { this->ChangeState(State_Terminating); + this->SetExitTag(exit_tag); needs_terminate = true; } } @@ -500,7 +501,7 @@ namespace ams::kern { MESOSPHERE_PANIC("Thread survived call to exit"); } - Result KProcess::Terminate() { + Result KProcess::Terminate(s64 exit_tag) { MESOSPHERE_ASSERT_THIS(); /* Determine whether we need to start terminating */ @@ -516,6 +517,7 @@ namespace ams::kern { if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_Crashed || m_state == State_DebugBreak) { this->ChangeState(State_Terminating); + this->SetExitTag(exit_tag); needs_terminate = true; } } @@ -783,7 +785,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(m_num_running_threads.Load() > 0); if (const auto prev = m_num_running_threads--; prev == 1) { - static_cast(this->Terminate()); + static_cast(this->Terminate(-1ll)); } } diff --git a/libraries/libmesosphere/source/kern_k_session_request.cpp b/libraries/libmesosphere/source/kern_k_session_request.cpp index a40611949..12acaee0e 100644 --- a/libraries/libmesosphere/source/kern_k_session_request.cpp +++ b/libraries/libmesosphere/source/kern_k_session_request.cpp @@ -28,6 +28,8 @@ namespace ams::kern { } else { /* Allocate dynamic mappings as necessary. */ if (m_dynamic_mappings == nullptr) { + /* 23.0.0+ now checks for IsDynamicResourceLimitsEnabled before allocating from slab heap. */ + R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), svc::ResultOutOfMemory()); m_dynamic_mappings = DynamicMappings::Allocate(); R_UNLESS(m_dynamic_mappings != nullptr, svc::ResultOutOfMemory()); } diff --git a/libraries/libmesosphere/source/svc/kern_svc_exception.cpp b/libraries/libmesosphere/source/svc/kern_svc_exception.cpp index 667646455..797b0d979 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_exception.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_exception.cpp @@ -70,7 +70,7 @@ namespace ams::kern::svc { } /* Exit the current process. */ - GetCurrentProcess().Exit(); + GetCurrentProcess().Exit(-1ll); } } diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 982719d41..83e2dc3e7 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -25,8 +25,9 @@ namespace ams::kern::svc { return (0 <= core_id && core_id < static_cast(cpu::NumVirtualCores)); } - void ExitProcess() { - GetCurrentProcess().Exit(); + void ExitProcess(int64_t exit_tag) { + const uint32_t intended_kernel_major_version = GetCurrentProcess().GetIntendedKernelMajorVersion(); + GetCurrentProcess().Exit(intended_kernel_major_version <= 26 ? -1ll : exit_tag); MESOSPHERE_PANIC("Process survived call to exit"); } @@ -357,7 +358,7 @@ namespace ams::kern::svc { R_RETURN(process->Run(priority, static_cast(aligned_stack_size))); } - Result TerminateProcess(ams::svc::Handle process_handle) { + Result TerminateProcess(ams::svc::Handle process_handle, int64_t exit_tag) { /* Get the target process. */ KProcess *process = GetCurrentProcess().GetHandleTable().GetObject(process_handle).ReleasePointerUnsafe(); R_UNLESS(process != nullptr, svc::ResultInvalidHandle()); @@ -367,13 +368,13 @@ namespace ams::kern::svc { ON_SCOPE_EXIT { process->Close(); }; /* Terminate the process. */ - R_TRY(process->Terminate()); + R_TRY(process->Terminate(exit_tag)); } else { /* We're terminating ourselves. Close our reference immediately. */ process->Close(); /* Exit. */ - ExitProcess(); + ExitProcess(exit_tag); } R_SUCCEED(); @@ -411,6 +412,20 @@ namespace ams::kern::svc { } } break; + case ams::svc::ProcessInfoType_Unknown1: + { + /* TODO: 23.0.0+ added a new process info type. Figure out what this is. */ + /* For now just call it an exit tag since it's only set during Exit or Terminate. */ + int64_t exit_tag; + { + KScopedLightLock proc_lk(process->GetStateLock()); + + exit_tag = process->GetExitTag(); + } + + *out = exit_tag; + } + break; default: R_THROW(svc::ResultInvalidEnumValue()); } @@ -423,7 +438,9 @@ namespace ams::kern::svc { /* ============================= 64 ABI ============================= */ void ExitProcess64() { - return ExitProcess(); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + return ExitProcess(-1ll); } Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) { @@ -443,7 +460,9 @@ namespace ams::kern::svc { } Result TerminateProcess64(ams::svc::Handle process_handle) { - R_RETURN(TerminateProcess(process_handle)); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + R_RETURN(TerminateProcess(process_handle, -1ll)); } Result GetProcessInfo64(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) { @@ -453,7 +472,9 @@ namespace ams::kern::svc { /* ============================= 64From32 ABI ============================= */ void ExitProcess64From32() { - return ExitProcess(); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + return ExitProcess(-1ll); } Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) { @@ -473,7 +494,9 @@ namespace ams::kern::svc { } Result TerminateProcess64From32(ams::svc::Handle process_handle) { - R_RETURN(TerminateProcess(process_handle)); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + R_RETURN(TerminateProcess(process_handle, -1ll)); } Result GetProcessInfo64From32(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) { diff --git a/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp b/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp index 9300a576d..8723b7da7 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp @@ -28,6 +28,8 @@ namespace ams::kern::svc { /* ============================= 64 ABI ============================= */ void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) { + /* TODO: 23.0.0+ added a second argument to CallSecureMonitorFromUser. */ + /* On NX, CallSecureMonitor64 always passes 0 for this argument. */ KSystemControl::CallSecureMonitorFromUser(args); } diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 96a18a721..52e105ed3 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -388,6 +388,7 @@ namespace ams::svc { /* Process types. */ enum ProcessInfoType : u32 { ProcessInfoType_ProcessState = 0, + ProcessInfoType_Unknown1 = 1, }; enum ProcessState : u32 { From 44d9649c6d615c1d51ef682d52e7c066e8009e07 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Wed, 23 Sep 2026 20:42:15 +0100 Subject: [PATCH 44/52] ams: use R_DISCARD everywhere --- .../kvdb/kvdb_memory_key_value_store.hpp | 4 +- .../diag_print_debug_string.os.horizon.cpp | 2 +- .../erpt/srv/erpt_srv_fs_info.os.horizon.cpp | 40 +++++++++---------- .../source/erpt/srv/erpt_srv_main.cpp | 2 +- .../nintendo/nx/impl/i2c_bus_accessor.cpp | 16 ++++---- .../source/kvdb/kvdb_file_key_value_store.cpp | 2 +- .../libstratosphere/source/lm/lm_api.cpp | 2 +- .../lr/lr_location_resolver_manager_impl.cpp | 2 +- .../source/ncm/ncm_content_manager_impl.cpp | 16 ++++---- .../source/ncm/ncm_content_storage_impl.cpp | 2 +- .../source/ncm/ncm_extended_data_mapper.hpp | 2 +- .../source/ncm/ncm_install_task_base.cpp | 26 ++++++------ .../source/ncm/ncm_install_task_data.cpp | 2 +- .../ncm/ncm_package_system_downgrade_task.cpp | 2 +- .../ncm/ncm_package_system_update_task.cpp | 10 ++--- .../source/ncm/ncm_placeholder_accessor.cpp | 2 +- .../ncm_submission_package_install_task.cpp | 2 +- .../source/os/impl/os_vamm_manager.cpp | 2 +- .../source/pgl/srv/pgl_srv_api.cpp | 4 +- .../source/pgl/srv/pgl_srv_shell.cpp | 8 ++-- .../nintendo/nx/powctl_battery_driver.cpp | 2 +- .../nintendo/nx/powctl_charger_driver.cpp | 2 +- .../nintendo/nx/impl/pwm_pwm_driver_impl.cpp | 10 ++--- .../libstratosphere/source/scs/scs_shell.cpp | 4 +- .../impl/settings_key_value_store.cpp | 4 +- .../source/spl/impl/spl_api_impl.cpp | 4 +- .../srv/sprofile_srv_profile_manager.cpp | 2 +- .../libstratosphere/source/usb/usb_device.cpp | 8 ++-- .../sdmmc/impl/sdmmc_device_detector.cpp | 4 +- ...mmc_sdmmc_controller.board.nintendo_nx.cpp | 2 +- .../source/tio_file_server_processor.cpp | 2 +- .../source/amsmitm_initialization.cpp | 12 +++--- .../source/amsmitm_prodinfo_utils.cpp | 2 +- .../source/dns_mitm/dnsmitm_debug.cpp | 4 +- .../dns_mitm/dnsmitm_host_redirection.cpp | 6 +-- .../source/dns_mitm/dnsmitm_module.cpp | 2 +- .../source/fs_mitm/fs_mitm_service.cpp | 2 +- .../source/set_mitm/set_mitm_service.cpp | 4 +- .../boot/source/boot_check_battery.cpp | 2 +- stratosphere/boot/source/boot_display.cpp | 6 +-- stratosphere/boot/source/boot_pmic_driver.cpp | 2 +- .../creport/source/creport_crash_report.cpp | 8 ++-- stratosphere/creport/source/creport_main.cpp | 2 +- .../creport/source/creport_scoped_file.hpp | 4 +- .../source/dmnt2_breakpoint_manager.cpp | 2 +- .../source/dmnt2_breakpoint_manager_base.cpp | 2 +- .../dmnt.gen2/source/dmnt2_debug_process.cpp | 8 ++-- .../source/dmnt2_gdb_server_impl.cpp | 24 +++++------ .../source/dmnt2_hardware_breakpoint.cpp | 2 +- .../dmnt/source/cheat/impl/dmnt_cheat_api.cpp | 10 ++--- .../dmnt/source/cheat/impl/dmnt_cheat_vm.cpp | 24 +++++------ stratosphere/erpt/source/erpt_main.cpp | 6 +-- stratosphere/fatal/source/fatal_repair.cpp | 4 +- .../fatal/source/fatal_task_error_report.cpp | 2 +- stratosphere/htc/source/htc_main.cpp | 6 +-- .../loader/source/ldr_argument_store.hpp | 2 +- .../loader/source/ldr_process_creation.cpp | 4 +- .../pm/source/impl/pm_process_info.cpp | 4 +- .../pm/source/impl/pm_process_manager.cpp | 4 +- .../pm/source/impl/pm_process_tracker.cpp | 2 +- stratosphere/pm/source/pm_main.cpp | 4 +- .../ro/source/impl/ro_service_impl.cpp | 4 +- stratosphere/spl/source/spl_main.cpp | 2 +- .../spl/source/spl_secure_monitor_manager.cpp | 2 +- .../haze/include/haze/console_main_loop.hpp | 4 +- 65 files changed, 185 insertions(+), 185 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp index 0b09098d5..567afd8ce 100644 --- a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp +++ b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp @@ -489,7 +489,7 @@ namespace ams::kvdb { private: Result SaveArchiveToFile(const char *path, const void *buf, size_t size) { /* Try to delete the archive, but allow deletion failure. */ - fs::DeleteFile(path); + R_DISCARD(fs::DeleteFile(path)); /* Create new archive. */ R_TRY(fs::CreateFile(path, size)); @@ -514,7 +514,7 @@ namespace ams::kvdb { R_TRY(SaveArchiveToFile(m_temp_path.Get(), buffer.Get(), buffer.GetSize())); /* Try to delete the saved archive, but allow deletion failure. */ - fs::DeleteFile(m_path.Get()); + R_DISCARD(fs::DeleteFile(m_path.Get())); /* Rename the path. */ R_TRY(fs::RenameFile(m_temp_path.Get(), m_path.Get())); diff --git a/libraries/libstratosphere/source/diag/impl/diag_print_debug_string.os.horizon.cpp b/libraries/libstratosphere/source/diag/impl/diag_print_debug_string.os.horizon.cpp index 55bbcb931..deb5fe51f 100644 --- a/libraries/libstratosphere/source/diag/impl/diag_print_debug_string.os.horizon.cpp +++ b/libraries/libstratosphere/source/diag/impl/diag_print_debug_string.os.horizon.cpp @@ -22,7 +22,7 @@ namespace ams::diag::impl { AMS_AUDIT(msg != nullptr || size == 0); if (size != 0) { - svc::OutputDebugString(msg, size); + R_DISCARD(svc::OutputDebugString(msg, size)); } } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp index dda71d939..49aeb27ee 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_fs_info.os.horizon.cpp @@ -499,26 +499,26 @@ namespace ams::erpt::srv { } void ClearFsInfo() { - Context::ClearContext(CategoryId_NANDTypeInfo); - Context::ClearContext(CategoryId_NANDSpeedModeInfo); - Context::ClearContext(CategoryId_NANDExtendedCsd); - Context::ClearContext(CategoryId_NANDPatrolInfo); - Context::ClearContext(CategoryId_NANDErrorInfo); - Context::ClearContext(CategoryId_NANDDriverLog); - Context::ClearContext(CategoryId_MicroSDTypeInfo); - Context::ClearContext(CategoryId_MicroSDSpeedModeInfo); - Context::ClearContext(CategoryId_SdCardSizeSpec); - Context::ClearContext(CategoryId_SdCardActivationInfo); - Context::ClearContext(CategoryId_SdCardErrorInfo); - Context::ClearContext(CategoryId_SdCardDriverLog); - Context::ClearContext(CategoryId_GameCardCIDInfo); - Context::ClearContext(CategoryId_GameCardErrorInfo); - Context::ClearContext(CategoryId_GameCardDetailedErrorInfo); - Context::ClearContext(CategoryId_GameCardLogInfo); - Context::ClearContext(CategoryId_FsProxyErrorInfo); - Context::ClearContext(CategoryId_FsProxyErrorInfo2); - Context::ClearContext(CategoryId_FsProxyErrorInfo3); - Context::ClearContext(CategoryId_FsMemoryInfo); + R_DISCARD(Context::ClearContext(CategoryId_NANDTypeInfo)); + R_DISCARD(Context::ClearContext(CategoryId_NANDSpeedModeInfo)); + R_DISCARD(Context::ClearContext(CategoryId_NANDExtendedCsd)); + R_DISCARD(Context::ClearContext(CategoryId_NANDPatrolInfo)); + R_DISCARD(Context::ClearContext(CategoryId_NANDErrorInfo)); + R_DISCARD(Context::ClearContext(CategoryId_NANDDriverLog)); + R_DISCARD(Context::ClearContext(CategoryId_MicroSDTypeInfo)); + R_DISCARD(Context::ClearContext(CategoryId_MicroSDSpeedModeInfo)); + R_DISCARD(Context::ClearContext(CategoryId_SdCardSizeSpec)); + R_DISCARD(Context::ClearContext(CategoryId_SdCardActivationInfo)); + R_DISCARD(Context::ClearContext(CategoryId_SdCardErrorInfo)); + R_DISCARD(Context::ClearContext(CategoryId_SdCardDriverLog)); + R_DISCARD(Context::ClearContext(CategoryId_GameCardCIDInfo)); + R_DISCARD(Context::ClearContext(CategoryId_GameCardErrorInfo)); + R_DISCARD(Context::ClearContext(CategoryId_GameCardDetailedErrorInfo)); + R_DISCARD(Context::ClearContext(CategoryId_GameCardLogInfo)); + R_DISCARD(Context::ClearContext(CategoryId_FsProxyErrorInfo)); + R_DISCARD(Context::ClearContext(CategoryId_FsProxyErrorInfo2)); + R_DISCARD(Context::ClearContext(CategoryId_FsProxyErrorInfo3)); + R_DISCARD(Context::ClearContext(CategoryId_FsMemoryInfo)); } } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp index 54754cee0..9ecabaf51 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp @@ -195,7 +195,7 @@ namespace ams::erpt::srv { } } else{ /* Pre 21.0.0, Nintendo just calls restore and ignores the result. */ - Journal::Restore(); + R_DISCARD(Journal::Restore()); } Reporter::UpdatePowerOnTime(); diff --git a/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/impl/i2c_bus_accessor.cpp b/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/impl/i2c_bus_accessor.cpp index a59c6d65d..50a204e42 100644 --- a/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/impl/i2c_bus_accessor.cpp +++ b/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/impl/i2c_bus_accessor.cpp @@ -114,7 +114,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { /* If we have a regulator session, set voltage to 2.9V. */ if (m_has_regulator_session) { /* NOTE: Nintendo does not check the result, here. */ - regulator::SetVoltageValue(std::addressof(m_regulator_session), 2'900'000u); + R_DISCARD(regulator::SetVoltageValue(std::addressof(m_regulator_session), 2'900'000u)); } /* Initialize clock/reset library. */ @@ -130,7 +130,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session)); /* NOTE: Nintendo does not check the result of this call. */ - regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true); + R_DISCARD(regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true)); /* If we enabled voltage, delay to give our enable time to take. */ if (!was_enabled) { @@ -163,7 +163,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { /* If we have a regulator session, disable voltage. */ if (m_has_regulator_session) { /* NOTE: Nintendo does not check the result of this call. */ - regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false); + R_DISCARD(regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false)); } /* Finalize the clock/reset library. */ @@ -233,7 +233,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { /* Disable voltage. */ if (m_has_regulator_session) { - regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false); + R_DISCARD(regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false)); } } @@ -272,7 +272,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session)); /* NOTE: Nintendo does not check the result of this call. */ - regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true); + R_DISCARD(regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true)); /* If we enabled voltage, delay to give our enable time to take. */ if (!was_enabled) { @@ -337,7 +337,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { this->SetPacketModeRegisters(); /* Flush fifos. */ - this->FlushFifos(); + R_DISCARD(this->FlushFifos()); } Result I2cBusAccessor::Send(const u8 *src, size_t src_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) { @@ -516,7 +516,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { const u32 slave_addr = ((static_cast(slave_address) & 0x7F) << 1) | (is_read ? 1 : 0); /* Flush fifos. */ - this->FlushFifos(); + R_DISCARD(this->FlushFifos()); /* Enqueue the first header word. */ reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_ENUM (HEADER_WORD0_PROT_HDR_SZ, 1_WORD), @@ -765,7 +765,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl { this->SetPacketModeRegisters(); /* Flush fifos. */ - this->FlushFifos(); + R_DISCARD(this->FlushFifos()); } } R_END_TRY_CATCH_WITH_ABORT_UNLESS; } diff --git a/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp b/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp index 955ae0ef0..2e72aaf26 100644 --- a/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp +++ b/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp @@ -273,7 +273,7 @@ namespace ams::kvdb { /* Delete the file, if it exists. Don't check result, since it's okay if it's already deleted. */ auto key_path = this->GetPath(key, key_size); - fs::DeleteFile(key_path); + R_DISCARD(fs::DeleteFile(key_path)); /* Create the new value file. */ R_TRY(fs::CreateFile(key_path, value_size)); diff --git a/libraries/libstratosphere/source/lm/lm_api.cpp b/libraries/libstratosphere/source/lm/lm_api.cpp index ee4a22e75..15bf66e10 100644 --- a/libraries/libstratosphere/source/lm/lm_api.cpp +++ b/libraries/libstratosphere/source/lm/lm_api.cpp @@ -115,7 +115,7 @@ namespace ams::lm { } void SetDestination(u32 destination) { - g_logger->SetDestination(destination); + R_DISCARD(g_logger->SetDestination(destination)); } } diff --git a/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp b/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp index a7925fa93..c60acdcb5 100644 --- a/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp +++ b/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp @@ -88,7 +88,7 @@ namespace ams::lr { /* Refresh the resolver. */ if (storage_id != ncm::StorageId::Host) { - (*resolver)->Refresh(); + R_DISCARD((*resolver)->Refresh()); } R_SUCCEED(); diff --git a/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp index dded90f31..6007b894a 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp @@ -274,7 +274,7 @@ namespace ams::ncm { if (root.content_storage != nullptr) { /* N doesn't bother checking the result of this. */ - root.content_storage->DisableForcibly(); + R_DISCARD(root.content_storage->DisableForcibly()); root.content_storage = nullptr; if (root.storage_id == StorageId::Host) { @@ -514,7 +514,7 @@ namespace ams::ncm { if (root.content_meta_database != nullptr) { /* N doesn't bother checking the result of this. */ - root.content_meta_database->DisableForcibly(); + R_DISCARD(root.content_meta_database->DisableForcibly()); root.content_meta_database = nullptr; root.kvs = util::nullopt; @@ -618,12 +618,12 @@ namespace ams::ncm { /* Disable and unmount all content storage roots. */ for (size_t i = 0; i < m_num_integrated_content_storage_entries; ++i) { - this->InactivateContentStorage(m_integrated_content_storage_roots[i].m_config->storage_id); + R_DISCARD(this->InactivateContentStorage(m_integrated_content_storage_roots[i].m_config->storage_id)); } /* Disable and unmount all content meta database roots. */ for (size_t i = 0; i < m_num_integrated_content_meta_entries; ++i) { - this->InactivateContentMetaDatabase(m_integrated_content_meta_database_roots[i].m_config->storage_id); + R_DISCARD(this->InactivateContentMetaDatabase(m_integrated_content_meta_database_roots[i].m_config->storage_id)); } } @@ -796,7 +796,7 @@ namespace ams::ncm { Result ContentManagerImpl::BuildContentMetaDatabaseImpl(StorageId storage_id) { /* Temporarily activate the database. */ R_TRY(this->ActivateContentMetaDatabase(storage_id)); - ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); }; + ON_SCOPE_EXIT { R_DISCARD(this->InactivateContentMetaDatabase(storage_id)); }; /* Open the content meta database and storage. */ ContentMetaDatabase meta_db; @@ -848,7 +848,7 @@ namespace ams::ncm { if (R_FAILED(this->ActivateContentMetaDatabase(StorageId::BuiltInSystem))) { return true; } - ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(StorageId::BuiltInSystem); }; + ON_SCOPE_EXIT { R_DISCARD(this->InactivateContentMetaDatabase(StorageId::BuiltInSystem)); }; /* Open the content meta db. */ ContentMetaDatabase meta_db; @@ -976,7 +976,7 @@ namespace ams::ncm { /* or an empty kvs, both of which we can fix by performing a rebuild. */ if (this->IsNeedRebuildSystemContentMetaDatabase()) { /* Clean up the system content meta database, to ensure creation can succeed. */ - this->CleanupContentMetaDatabase(StorageId::BuiltInSystem); + R_DISCARD(this->CleanupContentMetaDatabase(StorageId::BuiltInSystem)); /* Create the content meta database. */ R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem)); @@ -1005,7 +1005,7 @@ namespace ams::ncm { /* NOTE: Nintendo does not check this succeeds, and it does on older system versions. */ /* We will not check the error, either, even though this kind of defeats the call's purpose. */ if (hos::GetVersion() >= hos::Version_2_0_0) { - EnsureBuiltInSystemSaveDataFlags(); + R_DISCARD(EnsureBuiltInSystemSaveDataFlags()); } /* Activate the content meta database. */ diff --git a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp index db0387503..cc31c7299 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp @@ -510,7 +510,7 @@ namespace ams::ncm { PlaceHolderAccessor::MakeBaseDirectoryPath(std::addressof(placeholder_dir), m_root_path); /* Cleanup the placeholder base directory. */ - CleanDirectoryRecursively(placeholder_dir); + R_DISCARD(CleanDirectoryRecursively(placeholder_dir)); R_SUCCEED(); } diff --git a/libraries/libstratosphere/source/ncm/ncm_extended_data_mapper.hpp b/libraries/libstratosphere/source/ncm/ncm_extended_data_mapper.hpp index 633ffd809..a4bf6f2bc 100644 --- a/libraries/libstratosphere/source/ncm/ncm_extended_data_mapper.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_extended_data_mapper.hpp @@ -47,7 +47,7 @@ namespace ams::ncm { void Finalize() { /* If we're unused and mapped, we should unmap. */ if (!m_is_using && m_is_mapped) { - this->Unmap(); + R_DISCARD(this->Unmap()); } } private: diff --git a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp index 231d18064..fc1785705 100644 --- a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp @@ -189,7 +189,7 @@ namespace ams::ncm { /* Cleanup the content meta. */ /* N doesn't check the result of this. */ - this->CleanupOne(content_meta); + R_DISCARD(this->CleanupOne(content_meta)); } /* Cleanup the data and progress. */ @@ -215,7 +215,7 @@ namespace ams::ncm { /* Delete placeholders for Prepared or Installed content infos. */ if (content_info->install_state == InstallState::Prepared || content_info->install_state == InstallState::Installed) { - content_storage.DeletePlaceHolder(content_info->placeholder_id); + R_DISCARD(content_storage.DeletePlaceHolder(content_info->placeholder_id)); } } @@ -344,7 +344,7 @@ namespace ams::ncm { /* Write all prepared content infos. */ { /* If we fail while writing, update (but don't check the result). */ - ON_RESULT_FAILURE { m_data->Update(content_meta, i); }; + ON_RESULT_FAILURE { R_DISCARD(m_data->Update(content_meta, i)); }; /* Create a writer. */ const auto writer = content_meta.GetWriter(); @@ -449,7 +449,7 @@ namespace ams::ncm { /* Commit the current meta. */ { /* Ensure that if something goes wrong during commit, we still try to update. */ - ON_RESULT_FAILURE { m_data->Update(content_meta, i); }; + ON_RESULT_FAILURE { R_DISCARD(m_data->Update(content_meta, i)); }; /* Open a writer. */ const auto writer = content_meta.GetWriter(); @@ -636,7 +636,7 @@ namespace ams::ncm { /* Update the data (and check result) when we are done. */ { - ON_RESULT_FAILURE { m_data->Update(content_meta, i); }; + ON_RESULT_FAILURE { R_DISCARD(m_data->Update(content_meta, i)); }; /* Automatically choose a suitable storage id. */ auto reader = content_meta.GetReader(); @@ -713,7 +713,7 @@ namespace ams::ncm { /* Create the placeholder. */ R_TRY(storage->CreatePlaceHolder(placeholder_id, meta_info.content_id, meta_info.content_size)); - ON_RESULT_FAILURE { storage->DeletePlaceHolder(placeholder_id); }; + ON_RESULT_FAILURE { R_DISCARD(storage->DeletePlaceHolder(placeholder_id)); }; /* Output install content info. */ *out_install_content_info = this->MakeInstallContentInfoFrom(meta_info, placeholder_id, is_temporary); @@ -740,7 +740,7 @@ namespace ams::ncm { content_storage.GetPlaceHolderPath(std::addressof(path), content_info.GetPlaceHolderId()); /* If we fail, delete the placeholder. */ - ON_RESULT_FAILURE { content_storage.DeletePlaceHolder(content_info.GetPlaceHolderId()); }; + ON_RESULT_FAILURE { R_DISCARD(content_storage.DeletePlaceHolder(content_info.GetPlaceHolderId())); }; /* Create a new temporary InstallContentInfo if relevant. */ const bool is_temporary = content_info.is_temporary; @@ -775,7 +775,7 @@ namespace ams::ncm { /* If the placeholder is temporary, delete it. */ if (is_temporary) { - content_storage.DeletePlaceHolder(content_info.GetPlaceHolderId()); + R_DISCARD(content_storage.DeletePlaceHolder(content_info.GetPlaceHolderId())); } R_SUCCEED(); @@ -793,7 +793,7 @@ namespace ams::ncm { reader.ConvertToInstallContentMeta(tmp_buffer.Get(), tmp_buffer.GetSize(), InstallContentInfo::Make(ContentInfo::Make(content_id, size, ContentInfo::DefaultContentAttributes, ContentType::Meta), meta_type)); /* Push the content meta. */ - m_data->Push(tmp_buffer.Get(), tmp_buffer.GetSize()); + R_DISCARD(m_data->Push(tmp_buffer.Get(), tmp_buffer.GetSize())); R_SUCCEED(); } @@ -807,7 +807,7 @@ namespace ams::ncm { Result InstallTaskBase::PrepareSystemUpdateDependency() { /* Cleanup on failure. */ - ON_RESULT_FAILURE { this->Cleanup(); }; + ON_RESULT_FAILURE { R_DISCARD(this->Cleanup()); }; /* Count the number of content meta entries. */ s32 count; @@ -1066,7 +1066,7 @@ namespace ams::ncm { void InstallTaskBase::SetLastResult(Result last_result) { std::scoped_lock lk(m_progress_mutex); - m_data->SetLastResult(last_result); + R_DISCARD(m_data->SetLastResult(last_result)); m_progress.SetLastResult(last_result); } @@ -1183,7 +1183,7 @@ namespace ams::ncm { R_TRY(ReadVariationContentMetaInfoList(out_count, out_meta_infos, path, attr, m_firmware_variation_id)); /* Delete the placeholder. */ - content_storage.DeletePlaceHolder(placeholder_id); + R_DISCARD(content_storage.DeletePlaceHolder(placeholder_id)); R_SUCCEED(); } @@ -1275,7 +1275,7 @@ namespace ams::ncm { void InstallTaskBase::SetProgressState(InstallProgressState state) { std::scoped_lock lk(m_progress_mutex); - m_data->SetState(state); + R_DISCARD(m_data->SetState(state)); m_progress.state = state; } diff --git a/libraries/libstratosphere/source/ncm/ncm_install_task_data.cpp b/libraries/libstratosphere/source/ncm/ncm_install_task_data.cpp index 362876163..307c63d13 100644 --- a/libraries/libstratosphere/source/ncm/ncm_install_task_data.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_install_task_data.cpp @@ -357,7 +357,7 @@ namespace ams::ncm { } /* NOTE: Nintendo doesn't check that this operation succeeds. */ - install_task_data.Push(content_meta.data.get(), content_meta.size); + R_DISCARD(install_task_data.Push(content_meta.data.get(), content_meta.size)); } /* Change from our current data to the new data. */ diff --git a/libraries/libstratosphere/source/ncm/ncm_package_system_downgrade_task.cpp b/libraries/libstratosphere/source/ncm/ncm_package_system_downgrade_task.cpp index f8abab57b..259c99315 100644 --- a/libraries/libstratosphere/source/ncm/ncm_package_system_downgrade_task.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_package_system_downgrade_task.cpp @@ -53,7 +53,7 @@ namespace ams::ncm { /* Remove matching keys. */ for (auto i = 0; i < count.total; i++) { - meta_db.Remove(keys[i]); + R_DISCARD(meta_db.Remove(keys[i])); } } } diff --git a/libraries/libstratosphere/source/ncm/ncm_package_system_update_task.cpp b/libraries/libstratosphere/source/ncm/ncm_package_system_update_task.cpp index 5332d7e60..2684b98ac 100644 --- a/libraries/libstratosphere/source/ncm/ncm_package_system_update_task.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_package_system_update_task.cpp @@ -19,14 +19,14 @@ namespace ams::ncm { PackageSystemUpdateTask::~PackageSystemUpdateTask() { if (m_context_path.GetLength() > 0) { - fs::DeleteFile(m_context_path); + R_DISCARD(fs::DeleteFile(m_context_path)); } this->Inactivate(); } void PackageSystemUpdateTask::Inactivate() { if (m_gamecard_content_meta_database_active) { - InactivateContentMetaDatabase(StorageId::GameCard); + R_DISCARD(InactivateContentMetaDatabase(StorageId::GameCard)); m_gamecard_content_meta_database_active = false; } } @@ -41,7 +41,7 @@ namespace ams::ncm { auto meta_db_guard = SCOPE_GUARD { this->Inactivate(); }; /* Open the game card content meta database. */ - OpenContentMetaDatabase(std::addressof(m_package_db), StorageId::GameCard); + R_DISCARD(OpenContentMetaDatabase(std::addressof(m_package_db), StorageId::GameCard)); ContentMetaDatabaseBuilder builder(std::addressof(m_package_db)); @@ -50,9 +50,9 @@ namespace ams::ncm { R_TRY(builder.BuildFromPackage(package_root)); /* Create a new context file. */ - fs::DeleteFile(context_path); + R_DISCARD(fs::DeleteFile(context_path)); R_TRY(FileInstallTaskData::Create(context_path, GameCardMaxContentMetaCount)); - auto context_guard = SCOPE_GUARD { fs::DeleteFile(context_path); }; + auto context_guard = SCOPE_GUARD { R_DISCARD(fs::DeleteFile(context_path)); }; /* Initialize data. */ R_TRY(m_data.Initialize(context_path)); diff --git a/libraries/libstratosphere/source/ncm/ncm_placeholder_accessor.cpp b/libraries/libstratosphere/source/ncm/ncm_placeholder_accessor.cpp index 4b392c218..b4e360204 100644 --- a/libraries/libstratosphere/source/ncm/ncm_placeholder_accessor.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_placeholder_accessor.cpp @@ -115,7 +115,7 @@ namespace ams::ncm { void PlaceHolderAccessor::Invalidate(CacheEntry *entry) { /* Flush and close the cached entry's file. */ if (entry != nullptr) { - fs::FlushFile(entry->handle); + R_DISCARD(fs::FlushFile(entry->handle)); fs::CloseFile(entry->handle); entry->id = InvalidPlaceHolderId; } diff --git a/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp b/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp index 6e1be6f24..a9e587e33 100644 --- a/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_submission_package_install_task.cpp @@ -69,7 +69,7 @@ namespace ams::ncm { R_TRY(m_impl->Initialize()); /* Initialize parent. N doesn't check the result. */ - PackageInstallTask::Initialize(impl::GetRootDirectoryPath(m_impl->GetMountName()).str, storage_id, buffer, buffer_size, ignore_ticket); + R_DISCARD(PackageInstallTask::Initialize(impl::GetRootDirectoryPath(m_impl->GetMountName()).str, storage_id, buffer, buffer_size, ignore_ticket)); R_SUCCEED(); } diff --git a/libraries/libstratosphere/source/os/impl/os_vamm_manager.cpp b/libraries/libstratosphere/source/os/impl/os_vamm_manager.cpp index 7bdfbb2da..ebd8fa719 100644 --- a/libraries/libstratosphere/source/os/impl/os_vamm_manager.cpp +++ b/libraries/libstratosphere/source/os/impl/os_vamm_manager.cpp @@ -107,7 +107,7 @@ namespace ams::os::impl { public: DynamicUnitHeap(uintptr_t address, size_t size, size_t unit_size) : m_start(address), m_end(address + size) { /* Allocate the start of our buffer. */ - VammManagerImpl::AllocatePhysicalMemoryImpl(m_start, PhysicalMemoryUnitSize); + R_DISCARD(VammManagerImpl::AllocatePhysicalMemoryImpl(m_start, PhysicalMemoryUnitSize)); /* Set our current limit. */ m_limit = m_start + PhysicalMemoryUnitSize; diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_api.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_api.cpp index 77c4580db..2d0a058db 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_api.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_api.cpp @@ -161,7 +161,7 @@ namespace ams::pgl::srv { const size_t sz = settings::fwdbg::GetSettingsItemValue(std::addressof(enable_application_extra_thread), sizeof(enable_application_extra_thread), "application_extra_thread", "enable_application_extra_thread"); if (sz == sizeof(enable_application_extra_thread) && enable_application_extra_thread != 0) { /* NOTE: Nintendo does not check that this succeeds. */ - pm::shell::BoostApplicationThreadResourceLimit(); + R_DISCARD(pm::shell::BoostApplicationThreadResourceLimit()); } } @@ -171,7 +171,7 @@ namespace ams::pgl::srv { const size_t sz = settings::fwdbg::GetSettingsItemValue(std::addressof(enable_system_extra_thread), sizeof(enable_system_extra_thread), "application_extra_thread", "enable_system_extra_thread"); if (sz == sizeof(enable_system_extra_thread) && enable_system_extra_thread != 0) { /* NOTE: Nintendo does not check that this succeeds. */ - pm::shell::BoostSystemThreadResourceLimit(); + R_DISCARD(pm::shell::BoostSystemThreadResourceLimit()); } } diff --git a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp index 2fff47715..76c5c217a 100644 --- a/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp +++ b/libraries/libstratosphere/source/pgl/srv/pgl_srv_shell.cpp @@ -173,7 +173,7 @@ namespace ams::pgl::srv { } void TriggerSnapShotDumper(os::ProcessId process_id) { - TriggerSnapShotDumper(process_id, GetSnapShotDumpType(), nullptr); + R_DISCARD(TriggerSnapShotDumper(process_id, GetSnapShotDumpType(), nullptr)); } s32 GetCrashReportDetailedArgument(u32 data_flags) { @@ -195,8 +195,8 @@ namespace ams::pgl::srv { void TriggerCrashReport(os::ProcessId process_id) { /* If the program that crashed is creport, we should just terminate both processes and return. */ if (process_id == g_creport_process_id) { - TerminateProcess(g_crashed_process_id); - TerminateProcess(g_creport_process_id); + R_DISCARD(TerminateProcess(g_crashed_process_id)); + R_DISCARD(TerminateProcess(g_creport_process_id)); g_crashed_process_id = os::InvalidProcessId; g_creport_process_id = os::InvalidProcessId; return; @@ -244,7 +244,7 @@ namespace ams::pgl::srv { if (data != nullptr) { TriggerSnapShotDumper(process_id); } else { - TerminateProcess(process_id); + R_DISCARD(TerminateProcess(process_id)); } } else { /* Otherwise, we want to launch creport. */ diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp index 2b4330080..f72a3bad9 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp @@ -38,7 +38,7 @@ namespace ams::powctl::impl::board::nintendo::nx { BatteryDevice::BatteryDevice(bool ev) : m_use_event_handler(ev), m_event_handler() { if (m_use_event_handler) { /* Create the system event. */ - os::CreateSystemEvent(std::addressof(m_system_event), os::EventClearMode_ManualClear, true); + R_DISCARD(os::CreateSystemEvent(std::addressof(m_system_event), os::EventClearMode_ManualClear, true)); /* Create the handler. */ m_event_handler.emplace(this); diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp index 0cf1a6209..2995772b6 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp @@ -36,7 +36,7 @@ namespace ams::powctl::impl::board::nintendo::nx { ChargerDevice::ChargerDevice(bool ev) : m_gpio_pad_session(), m_watchdog_timer_enabled(false), m_watchdog_timer_timeout(0), m_use_event_handler(ev), m_event_handler() { if (m_use_event_handler) { /* Create the system event. */ - os::CreateSystemEvent(std::addressof(m_system_event), os::EventClearMode_ManualClear, true); + R_DISCARD(os::CreateSystemEvent(std::addressof(m_system_event), os::EventClearMode_ManualClear, true)); /* Create the handler. */ m_event_handler.emplace(this); diff --git a/libraries/libstratosphere/source/pwm/driver/board/nintendo/nx/impl/pwm_pwm_driver_impl.cpp b/libraries/libstratosphere/source/pwm/driver/board/nintendo/nx/impl/pwm_pwm_driver_impl.cpp index cc4049e1e..956116890 100644 --- a/libraries/libstratosphere/source/pwm/driver/board/nintendo/nx/impl/pwm_pwm_driver_impl.cpp +++ b/libraries/libstratosphere/source/pwm/driver/board/nintendo/nx/impl/pwm_pwm_driver_impl.cpp @@ -51,8 +51,8 @@ namespace ams::pwm::driver::board::nintendo::nx::impl { void PwmDriverImpl::PowerOff() { /* Disable clock and hold pwm in reset. */ /* NOTE: Nintendo does not check this succeeds. */ - pcv::SetClockEnabled(pcv::Module_Pwm, false); - pcv::SetReset(pcv::Module_Pwm, true); + R_DISCARD(pcv::SetClockEnabled(pcv::Module_Pwm, false)); + R_DISCARD(pcv::SetReset(pcv::Module_Pwm, true)); /* Finalize pcv driver. */ pcv::Finalize(); @@ -78,9 +78,9 @@ namespace ams::pwm::driver::board::nintendo::nx::impl { /* Configure initial settings. */ /* NOTE: None of these results are checked. */ - this->SetEnabled(device, false); - this->SetScale(device, 0.0); - this->SetPeriod(device, DefaultChannelPeriod); + R_DISCARD(this->SetEnabled(device, false)); + R_DISCARD(this->SetScale(device, 0.0)); + R_DISCARD(this->SetPeriod(device, DefaultChannelPeriod)); R_SUCCEED(); } diff --git a/libraries/libstratosphere/source/scs/scs_shell.cpp b/libraries/libstratosphere/source/scs/scs_shell.cpp index 89794ce61..9a1cd336b 100644 --- a/libraries/libstratosphere/source/scs/scs_shell.cpp +++ b/libraries/libstratosphere/source/scs/scs_shell.cpp @@ -344,7 +344,7 @@ namespace ams::scs { void FlushProgramArgument(ncm::ProgramId program_id) { /* Ensure there are no arguments for the program. */ - ldr::SetProgramArgument(program_id, "", 1); + R_DISCARD(ldr::SetProgramArgument(program_id, "", 1)); } } @@ -382,7 +382,7 @@ namespace ams::scs { Result LaunchProgram(os::ProcessId *out, const ncm::ProgramLocation &loc, const void *args, size_t args_size, u32 process_flags) { /* Set up the arguments. */ - PrepareToLaunchProgram(loc.program_id, args, args_size); + R_DISCARD(PrepareToLaunchProgram(loc.program_id, args, args_size)); /* Ensure arguments are managed correctly. */ ON_SCOPE_EXIT { FlushProgramArgument(loc.program_id); }; diff --git a/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp b/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp index d15e42c19..e49211e7d 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp +++ b/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp @@ -1167,7 +1167,7 @@ namespace ams::settings::impl { map_value.current_value_size = prev_value_size; map_value.current_value = prev_value; - SaveKeyValueStoreMap(*map); + R_DISCARD(SaveKeyValueStoreMap(*map)); }; /* Attempt to save the key value store map. */ @@ -1239,7 +1239,7 @@ namespace ams::settings::impl { std::swap(map_value.current_value_size, value_size); std::swap(map_value.current_value, value_buffer); - SaveKeyValueStoreMap(*map); + R_DISCARD(SaveKeyValueStoreMap(*map)); }; /* Attempt to save the key value store map. */ diff --git a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp index 93821f85b..820050397 100644 --- a/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp +++ b/libraries/libstratosphere/source/spl/impl/spl_api_impl.cpp @@ -178,7 +178,7 @@ namespace ams::spl::impl { } ~ScopedAesKeySlot() { if (m_allocated) { - DeallocateAesKeySlot(m_slot_index); + R_DISCARD(DeallocateAesKeySlot(m_slot_index)); } } @@ -226,7 +226,7 @@ namespace ams::spl::impl { void InitializeAsyncOperation() { #if defined(ATMOSPHERE_OS_HORIZON) u64 interrupt_number; - impl::GetConfig(std::addressof(interrupt_number), ConfigItem::SecurityEngineInterruptNumber); + R_DISCARD(impl::GetConfig(std::addressof(interrupt_number), ConfigItem::SecurityEngineInterruptNumber)); g_interrupt_name = static_cast(interrupt_number); os::InitializeInterruptEvent(std::addressof(g_interrupt), g_interrupt_name, os::EventClearMode_AutoClear); diff --git a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp index 3e2d11e9e..cdd2036f6 100644 --- a/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp +++ b/libraries/libstratosphere/source/sprofile/srv/sprofile_srv_profile_manager.cpp @@ -148,7 +148,7 @@ namespace ams::sprofile::srv { R_UNLESS(!m_profile_importer.has_value(), sprofile::ResultInvalidState()); /* Try to load profile metadata. NOTE: result is not checked, it is okay if this fails. */ - this->LoadPrimaryMetadataImpl(); + R_DISCARD(this->LoadPrimaryMetadataImpl()); /* Create importer. */ m_profile_importer.emplace(m_profile_metadata); diff --git a/libraries/libstratosphere/source/usb/usb_device.cpp b/libraries/libstratosphere/source/usb/usb_device.cpp index 15a01d111..491bed2b3 100644 --- a/libraries/libstratosphere/source/usb/usb_device.cpp +++ b/libraries/libstratosphere/source/usb/usb_device.cpp @@ -254,7 +254,7 @@ namespace ams::usb { R_TRY(m_client->AddInterface(this, std::addressof(m_interface), m_interface_num)); /* Ensure we cleanup if we fail after this. */ - auto intf_guard = SCOPE_GUARD { m_client->DeleteInterface(m_interface_num); m_interface = nullptr; }; + auto intf_guard = SCOPE_GUARD { R_DISCARD(m_client->DeleteInterface(m_interface_num)); m_interface = nullptr; }; /* Get events. */ sf::NativeHandle setup_event_handle; @@ -313,7 +313,7 @@ namespace ams::usb { os::DestroySystemEvent(std::addressof(m_ctrl_out_completion_event)); /* Delete ourselves from our cleint. */ - m_client->DeleteInterface(m_interface_num); + R_DISCARD(m_client->DeleteInterface(m_interface_num)); /* Destroy our service. */ m_interface = nullptr; @@ -643,7 +643,7 @@ namespace ams::usb { m_address = bEndpointAddress; /* Ensure we clean up if we fail after this. */ - auto ep_guard = SCOPE_GUARD { m_interface->DeleteEndpoint(m_address); m_endpoint = nullptr; }; + auto ep_guard = SCOPE_GUARD { R_DISCARD(m_interface->DeleteEndpoint(m_address)); m_endpoint = nullptr; }; /* Get completion event. */ sf::NativeHandle event_handle; @@ -672,7 +672,7 @@ namespace ams::usb { R_UNLESS(m_is_initialized, usb::ResultNotInitialized()); /* Cancel any pending transactions. */ - m_endpoint->Cancel(); + R_DISCARD(m_endpoint->Cancel()); /* Wait for us to be at one reference count. */ while (m_reference_count > 1) { diff --git a/libraries/libvapours/source/sdmmc/impl/sdmmc_device_detector.cpp b/libraries/libvapours/source/sdmmc/impl/sdmmc_device_detector.cpp index 48b9a25fc..7fb7210e0 100644 --- a/libraries/libvapours/source/sdmmc/impl/sdmmc_device_detector.cpp +++ b/libraries/libvapours/source/sdmmc/impl/sdmmc_device_detector.cpp @@ -61,7 +61,7 @@ namespace ams::sdmmc::impl { gpio::Initialize(); /* Open and configure the pad session. */ - gpio::OpenSession(std::addressof(m_gpio_pad_session), m_gpio_device_code); + R_DISCARD(gpio::OpenSession(std::addressof(m_gpio_pad_session), m_gpio_device_code)); gpio::SetDirection(std::addressof(m_gpio_pad_session), gpio::Direction_Input); gpio::SetDebounceTime(std::addressof(m_gpio_pad_session), m_gpio_debounce_ms); gpio::SetDebounceEnabled(std::addressof(m_gpio_pad_session), true); @@ -200,7 +200,7 @@ namespace ams::sdmmc::impl { os::InitializeEvent(std::addressof(m_detector_thread_end_event), false, os::EventClearMode_ManualClear); /* Create and start the detector thread. */ - os::CreateThread(std::addressof(m_detector_thread), DetectorThreadEntry, this, m_detector_thread_stack, sizeof(m_detector_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(sdmmc, DeviceDetector)); + R_DISCARD(os::CreateThread(std::addressof(m_detector_thread), DetectorThreadEntry, this, m_detector_thread_stack, sizeof(m_detector_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(sdmmc, DeviceDetector))); os::SetThreadNamePointer(std::addressof(m_detector_thread), AMS_GET_SYSTEM_THREAD_NAME(sdmmc, DeviceDetector)); os::StartThread(std::addressof(m_detector_thread)); } diff --git a/libraries/libvapours/source/sdmmc/impl/sdmmc_sdmmc_controller.board.nintendo_nx.cpp b/libraries/libvapours/source/sdmmc/impl/sdmmc_sdmmc_controller.board.nintendo_nx.cpp index c3d7a3766..66a9a1806 100644 --- a/libraries/libvapours/source/sdmmc/impl/sdmmc_sdmmc_controller.board.nintendo_nx.cpp +++ b/libraries/libvapours/source/sdmmc/impl/sdmmc_sdmmc_controller.board.nintendo_nx.cpp @@ -500,7 +500,7 @@ namespace ams::sdmmc::impl { this->ClearInterrupt(); R_SUCCEED(); } else if (sdmmc::ResultWaitInterruptSoftwareTimeout::Includes(result)) { - SdHostStandardController::AbortTransaction(); + R_DISCARD(SdHostStandardController::AbortTransaction()); R_THROW(sdmmc::ResultIssueTuningCommandSoftwareTimeout()); } else { R_RETURN(result); diff --git a/stratosphere/TioServer/source/tio_file_server_processor.cpp b/stratosphere/TioServer/source/tio_file_server_processor.cpp index 7a1f6e3bb..318fd2936 100644 --- a/stratosphere/TioServer/source/tio_file_server_processor.cpp +++ b/stratosphere/TioServer/source/tio_file_server_processor.cpp @@ -679,7 +679,7 @@ namespace ams::tio { /* NOTE: Nintendo does not check the output of this call. */ s64 read_count = 0; - fs::ReadDirectory(std::addressof(read_count), reinterpret_cast(body), handle, cur); + R_DISCARD(fs::ReadDirectory(std::addressof(read_count), reinterpret_cast(body), handle, cur)); /* Send the current entries. */ const ssize_t cur_size = read_count * sizeof(fs::DirectoryEntry); diff --git a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp index e9979ce52..386048c73 100644 --- a/stratosphere/ams_mitm/source/amsmitm_initialization.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_initialization.cpp @@ -89,7 +89,7 @@ namespace ams::mitm { void CreateAutomaticBackups() { /* Create a backup directory, if one doesn't exist. */ - mitm::fs::CreateAtmosphereSdDirectory("/automatic_backups"); + R_DISCARD(mitm::fs::CreateAtmosphereSdDirectory("/automatic_backups")); /* Initialize PRODINFO and get a reference for the device. */ char device_reference[0x40] = {}; @@ -127,7 +127,7 @@ namespace ams::mitm { char bis_keys_backup_name[ams::fs::EntryNameLengthMax + 1]; GetBackupFileName(bis_keys_backup_name, sizeof(bis_keys_backup_name), device_reference, "BISKEYS.bin"); - mitm::fs::CreateAtmosphereSdFile(bis_keys_backup_name, sizeof(bis_keys), ams::fs::CreateOption_None); + R_DISCARD(mitm::fs::CreateAtmosphereSdFile(bis_keys_backup_name, sizeof(bis_keys), ams::fs::CreateOption_None)); R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(g_bis_key_file), bis_keys_backup_name, ams::fs::OpenMode_ReadWrite)); R_ABORT_UNLESS(fsFileSetSize(std::addressof(g_bis_key_file), sizeof(bis_keys))); R_ABORT_UNLESS(fsFileWrite(std::addressof(g_bis_key_file), 0, bis_keys, sizeof(bis_keys), FsWriteOption_Flush)); @@ -153,11 +153,11 @@ namespace ams::mitm { mitm::fs::OpenGlobalSdCardFileSystem(); /* Mount the sd card at a convenient mountpoint. */ - ams::fs::MountSdCard(ams::fs::impl::SdCardFileSystemMountName); + R_DISCARD(ams::fs::MountSdCard(ams::fs::impl::SdCardFileSystemMountName)); /* Initialize the reboot manager (load a payload off the SD). */ /* Discard result, since it doesn't need to succeed. */ - mitm::bpc::LoadRebootPayload(); + R_DISCARD(mitm::bpc::LoadRebootPayload()); /* Backup Calibration Binary and BIS keys. */ CreateAutomaticBackups(); @@ -167,7 +167,7 @@ namespace ams::mitm { if (const char *emummc_file_path = emummc::GetFilePath(); emummc_file_path != nullptr) { char emummc_path[ams::fs::EntryNameLengthMax + 1]; util::SNPrintf(emummc_path, sizeof(emummc_path), "%s/eMMC", emummc_file_path); - mitm::fs::OpenSdFile(std::addressof(g_emummc_file), emummc_path, ams::fs::OpenMode_Read); + R_DISCARD(mitm::fs::OpenSdFile(std::addressof(g_emummc_file), emummc_path, ams::fs::OpenMode_Read)); } /* NOTE: due to an Atmosphere bug, NS accesses to the Nintendo dir accessed /Nintendo/Nintendo */ @@ -185,7 +185,7 @@ namespace ams::mitm { /* Ensure Contents directory exists for normal emummc. */ /* NOTE: Allowed to fail on already-exists. */ util::SNPrintf(emummc_path, sizeof(emummc_path), "%s:/%s/Contents", ams::fs::impl::SdCardFileSystemMountName, emummc::GetNintendoDirPath()); - ams::fs::CreateDirectory(emummc_path); + R_DISCARD(ams::fs::CreateDirectory(emummc_path)); /* Fix Contents/private */ util::SNPrintf(emummc_path, sizeof(emummc_path), "%s:/%s/Contents/private", ams::fs::impl::SdCardFileSystemMountName, emummc::GetNintendoDirPath()); diff --git a/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp b/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp index 8722877fd..1e419f8f8 100644 --- a/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_prodinfo_utils.cpp @@ -436,7 +436,7 @@ namespace ams::mitm { GetBackupFileName(backup_fn, sizeof(backup_fn), info); /* Create the file, in case it does not exist. */ - mitm::fs::CreateAtmosphereSdFile(backup_fn, sizeof(CalibrationInfo), ams::fs::CreateOption_None); + R_DISCARD(mitm::fs::CreateAtmosphereSdFile(backup_fn, sizeof(CalibrationInfo), ams::fs::CreateOption_None)); /* Open the file. */ FsFile libnx_file; diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp index 477ac2f98..2c1672a25 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp @@ -40,10 +40,10 @@ namespace ams::mitm::socket::resolver { if (g_log_enabled) { /* Create the logs directory. */ - mitm::fs::CreateAtmosphereSdDirectory("/logs"); + R_DISCARD(mitm::fs::CreateAtmosphereSdDirectory("/logs")); /* Create the log file. */ - mitm::fs::CreateAtmosphereSdFile("/logs/dns_mitm_debug.log", 0, ams::fs::CreateOption_None); + R_DISCARD(mitm::fs::CreateAtmosphereSdFile("/logs/dns_mitm_debug.log", 0, ams::fs::CreateOption_None)); /* Open the log file. */ R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(g_log_file), "/logs/dns_mitm_debug.log", ams::fs::OpenMode_ReadWrite | ams::fs::OpenMode_AllowAppend)); diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp index ea6f1eb09..d7364fa60 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp @@ -313,8 +313,8 @@ namespace ams::mitm::socket::resolver { /* Open log file. */ ::FsFile log_file; - mitm::fs::DeleteAtmosphereSdFile("/logs/dns_mitm_startup.log"); - mitm::fs::CreateAtmosphereSdDirectory("/logs"); + R_DISCARD(mitm::fs::DeleteAtmosphereSdFile("/logs/dns_mitm_startup.log")); + R_DISCARD(mitm::fs::CreateAtmosphereSdDirectory("/logs")); R_ABORT_UNLESS(mitm::fs::CreateAtmosphereSdFile("/logs/dns_mitm_startup.log", 0, ams::fs::CreateOption_None)); R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(log_file), "/logs/dns_mitm_startup.log", ams::fs::OpenMode_ReadWrite | ams::fs::OpenMode_AllowAppend)); ON_SCOPE_EXIT { ::fsFileClose(std::addressof(log_file)); }; @@ -325,7 +325,7 @@ namespace ams::mitm::socket::resolver { if (!mitm::fs::HasAtmosphereSdFile("/hosts/default.txt")) { Log(log_file, "Creating /hosts/default.txt because it does not exist.\n"); - mitm::fs::CreateAtmosphereSdDirectory("/hosts"); + R_DISCARD(mitm::fs::CreateAtmosphereSdDirectory("/hosts")); R_ABORT_UNLESS(mitm::fs::CreateAtmosphereSdFile("/hosts/default.txt", sizeof(DefaultHostsFile) - 1, ams::fs::CreateOption_None)); ::FsFile default_file; diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp index 004c3a1c4..5d185cc23 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp @@ -131,7 +131,7 @@ namespace ams::mitm::socket::resolver { } /* Initialize the socket allocator. */ - ams::socket::InitializeAllocatorForInternal(g_resolver_allocator_buffer, sizeof(g_resolver_allocator_buffer)); + R_DISCARD(ams::socket::InitializeAllocatorForInternal(g_resolver_allocator_buffer, sizeof(g_resolver_allocator_buffer))); /* Initialize debug. */ resolver::InitializeDebug(ShouldEnableDebugLog()); diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp index f82a6e806..adaad71e2 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp @@ -262,7 +262,7 @@ namespace ams::mitm::fs { constexpr const fs::Path root_path = fs::MakeConstantPath("/"); u8 savedata_copy_buffer[2_KB]; - fssystem::CopyDirectoryRecursively(dirsave_ifs.get(), save_ifs.get(), root_path, root_path, std::addressof(work_entry), savedata_copy_buffer, sizeof(savedata_copy_buffer)); + R_DISCARD(fssystem::CopyDirectoryRecursively(dirsave_ifs.get(), save_ifs.get(), root_path, root_path, std::addressof(work_entry), savedata_copy_buffer, sizeof(savedata_copy_buffer))); } /* Set output. */ diff --git a/stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp b/stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp index 0915a10ab..eacadd8b4 100644 --- a/stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp @@ -90,7 +90,7 @@ namespace ams::mitm::settings { } Result SetMitmService::GetLanguageCode(sf::Out out) { - this->EnsureLocale(); + R_DISCARD(this->EnsureLocale()); /* If there's no override locale, just use the actual one. */ if (AMS_UNLIKELY(!m_is_valid_language)) { @@ -109,7 +109,7 @@ namespace ams::mitm::settings { } Result SetMitmService::GetRegionCode(sf::Out out) { - this->EnsureLocale(); + R_DISCARD(this->EnsureLocale()); /* If there's no override locale, just use the actual one. */ if (AMS_UNLIKELY(!m_is_valid_region)) { diff --git a/stratosphere/boot/source/boot_check_battery.cpp b/stratosphere/boot/source/boot_check_battery.cpp index 07fea7065..d6e3ef332 100644 --- a/stratosphere/boot/source/boot_check_battery.cpp +++ b/stratosphere/boot/source/boot_check_battery.cpp @@ -490,7 +490,7 @@ namespace ams::boot { } if (input_current_limit_ma <= 150) { - charger_driver.SetChargerConfiguration(powctl::ChargerConfiguration_ChargeDisable); + R_DISCARD(charger_driver.SetChargerConfiguration(powctl::ChargerConfiguration_ChargeDisable)); boot::ShutdownSystem(); } } diff --git a/stratosphere/boot/source/boot_display.cpp b/stratosphere/boot/source/boot_display.cpp index 52470c972..ee6fdc80a 100644 --- a/stratosphere/boot/source/boot_display.cpp +++ b/stratosphere/boot/source/boot_display.cpp @@ -262,10 +262,10 @@ namespace ams::boot { R_ABORT_UNLESS(i2c::driver::OpenSession(std::addressof(i2c_session), i2c::DeviceCode_Max77620Pmic)); if (g_soc_type == spl::SocType_Mariko) { - WriteI2cRegister(i2c_session, 0x18, 0x3A); - WriteI2cRegister(i2c_session, 0x1F, 0x71); + R_DISCARD(WriteI2cRegister(i2c_session, 0x18, 0x3A)); + R_DISCARD(WriteI2cRegister(i2c_session, 0x1F, 0x71)); } - WriteI2cRegister(i2c_session, 0x23, 0xD0); + R_DISCARD(WriteI2cRegister(i2c_session, 0x23, 0xD0)); i2c::driver::CloseSession(i2c_session); } diff --git a/stratosphere/boot/source/boot_pmic_driver.cpp b/stratosphere/boot/source/boot_pmic_driver.cpp index 2c3d80daf..eb86a0734 100644 --- a/stratosphere/boot/source/boot_pmic_driver.cpp +++ b/stratosphere/boot/source/boot_pmic_driver.cpp @@ -119,7 +119,7 @@ namespace ams::boot { desired_shutdown_enabled &= use_desired_shutdown; if (shutdown_enabled != desired_shutdown_enabled) { - battery_driver.SetI2cShutdownEnabled(desired_shutdown_enabled); + R_DISCARD(battery_driver.SetI2cShutdownEnabled(desired_shutdown_enabled)); } } diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index fec6cbc67..6afb794c9 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -53,8 +53,8 @@ namespace ams::creport { } void TryCreateReportDirectories() { - fs::EnsureDirectory("sdmc:/atmosphere/crash_reports/dumps"); - fs::EnsureDirectory("sdmc:/atmosphere/fatal_reports/dumps"); + R_DISCARD(fs::EnsureDirectory("sdmc:/atmosphere/crash_reports/dumps")); + R_DISCARD(fs::EnsureDirectory("sdmc:/atmosphere/fatal_reports/dumps")); } constexpr const char *GetDebugExceptionString(const svc::DebugException type) { @@ -244,7 +244,7 @@ namespace ams::creport { m_result = creport::ResultUserBreak(); /* Try to parse out the user break result. */ if (hos::GetVersion() >= hos::Version_5_0_0) { - svc::ReadDebugProcessMemory(reinterpret_cast(std::addressof(m_result)), m_debug_handle, d.info.exception.specific.user_break.address, sizeof(m_result)); + R_DISCARD(svc::ReadDebugProcessMemory(reinterpret_cast(std::addressof(m_result)), m_debug_handle, d.info.exception.specific.user_break.address, sizeof(m_result))); } break; case svc::DebugException_UndefinedSystemCall: @@ -289,7 +289,7 @@ namespace ams::creport { } /* Read the dying message. */ - svc::ReadDebugProcessMemory(reinterpret_cast(m_dying_message), m_debug_handle, m_dying_message_address, m_dying_message_size); + R_DISCARD(svc::ReadDebugProcessMemory(reinterpret_cast(m_dying_message), m_debug_handle, m_dying_message_address, m_dying_message_size)); } void CrashReport::SaveReport(bool enable_screenshot) { diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index 5e5d38e09..8bcfccec7 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -123,7 +123,7 @@ namespace ams { if (R_SUCCEEDED(pgl::Initialize())) { ON_SCOPE_EXIT { pgl::Finalize(); }; - pgl::TerminateProcess(crashed_pid); + R_DISCARD(pgl::TerminateProcess(crashed_pid)); } } else { /* Use ns to terminate. */ diff --git a/stratosphere/creport/source/creport_scoped_file.hpp b/stratosphere/creport/source/creport_scoped_file.hpp index 5adcbeb09..dcdd1d773 100644 --- a/stratosphere/creport/source/creport_scoped_file.hpp +++ b/stratosphere/creport/source/creport_scoped_file.hpp @@ -38,9 +38,9 @@ namespace ams::creport { ~ScopedFile() { if (m_opened) { if (m_cache != nullptr) { - this->TryWriteCache(); + R_DISCARD(this->TryWriteCache()); } - fs::FlushFile(m_file); + R_DISCARD(fs::FlushFile(m_file)); fs::CloseFile(m_file); } } diff --git a/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager.cpp b/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager.cpp index 956226448..99dc434d4 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager.cpp @@ -29,7 +29,7 @@ namespace ams::dmnt { for (size_t i = 0; (bp = static_cast(this->GetBreakPoint(i))) != nullptr; ++i) { if (bp->m_in_use && bp->m_is_step) { AMS_DMNT2_GDB_LOG_DEBUG("BreakPointManager::ClearStep %p 0x%lx (idx=%zu)\n", bp, bp->m_address, i); - bp->Clear(m_debug_process); + R_DISCARD(bp->Clear(m_debug_process)); } } } diff --git a/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager_base.cpp b/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager_base.cpp index 0819798e3..43022b8b0 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager_base.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_breakpoint_manager_base.cpp @@ -28,7 +28,7 @@ namespace ams::dmnt { BreakPointBase *bp = nullptr; for (size_t i = 0; (bp = static_cast(this->GetBreakPoint(i))) != nullptr; ++i) { if (bp->m_in_use) { - bp->Clear(m_debug_process); + R_DISCARD(bp->Clear(m_debug_process)); } } } diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp index 4f25c1f5e..e94ca9731 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp @@ -44,7 +44,7 @@ namespace ams::dmnt { /* Get our process id. */ u64 pid_value = 0; - svc::GetProcessId(std::addressof(pid_value), m_debug_handle); + R_DISCARD(svc::GetProcessId(std::addressof(pid_value), m_debug_handle)); m_process_id = { pid_value }; @@ -413,7 +413,7 @@ namespace ams::dmnt { /* Get the instruction where we were. */ u32 insn = 0; - this->ReadMemory(std::addressof(insn), pc, sizeof(insn)); + R_DISCARD(this->ReadMemory(std::addressof(insn), pc, sizeof(insn))); /* Handle by architecture. */ bool is_call = false; @@ -471,7 +471,7 @@ namespace ams::dmnt { } Result DebugProcess::ClearBreakPoint(uintptr_t address, size_t size) { - m_software_breakpoints.ClearBreakPoint(address, size); + R_DISCARD(m_software_breakpoints.ClearBreakPoint(address, size)); R_SUCCEED(); } @@ -480,7 +480,7 @@ namespace ams::dmnt { } Result DebugProcess::ClearHardwareBreakPoint(uintptr_t address, size_t size) { - m_hardware_breakpoints.ClearBreakPoint(address, size); + R_DISCARD(m_hardware_breakpoints.ClearBreakPoint(address, size)); R_SUCCEED(); } diff --git a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp index 757a237a8..83c2489cb 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp @@ -1030,7 +1030,7 @@ namespace ams::dmnt { const auto reason = info.break_reason & ~svc::BreakReason_NotificationOnlyFlag; if (reason == svc::BreakReason_PostLoadDll || reason == svc::BreakReason_PostUnloadDll) { /* Re-collect the process's modules. */ - m_debug_process.CollectModules(); + R_DISCARD(m_debug_process.CollectModules()); } if (m_debug_process.GetOverrideStatus().IsHbl() && reason == svc::BreakReason_PostLoadDll) { @@ -1049,7 +1049,7 @@ namespace ams::dmnt { } /* This was just a notification, so we should continue. */ - m_debug_process.Continue(); + R_DISCARD(m_debug_process.Continue()); continue; } @@ -1064,7 +1064,7 @@ namespace ams::dmnt { if (!is_svc_break) { AMS_DMNT2_GDB_LOG_ERROR("UserBreak from non-SvcBreak (%08x)\n", insn); - m_debug_process.Continue(); + R_DISCARD(m_debug_process.Continue()); continue; } } @@ -1194,7 +1194,7 @@ namespace ams::dmnt { AMS_DMNT2_GDB_LOG_DEBUG("CreateThread %lx\n", thread_id); if (m_debug_process.IsValid()) { - m_debug_process.Continue(); + R_DISCARD(m_debug_process.Continue()); } else { AppendReplyFormat(reply_cur, reply_end, "W00"); } @@ -1205,7 +1205,7 @@ namespace ams::dmnt { AMS_DMNT2_GDB_LOG_DEBUG("ExitThread %lx\n", thread_id); if (m_debug_process.IsValid()) { - m_debug_process.Continue(); + R_DISCARD(m_debug_process.Continue()); } else { AppendReplyFormat(reply_cur, reply_end, "W00"); } @@ -1227,7 +1227,7 @@ namespace ams::dmnt { break; default: AMS_DMNT2_GDB_LOG_DEBUG("Unhandled ProcessEvent %u %lx\n", static_cast(d.type), thread_id); - m_debug_process.Continue(); + R_DISCARD(m_debug_process.Continue()); break; } @@ -1235,7 +1235,7 @@ namespace ams::dmnt { bool do_break; this->SendPacket(std::addressof(do_break), send_buffer); if (do_break) { - m_debug_process.Break(); + R_DISCARD(m_debug_process.Break()); } } } @@ -1250,7 +1250,7 @@ namespace ams::dmnt { /* Get the thread context. */ svc::ThreadContext thread_context = {}; - m_debug_process.GetThreadContext(std::addressof(thread_context), thread_id, svc::ThreadContextFlag_General | svc::ThreadContextFlag_Control); + R_DISCARD(m_debug_process.GetThreadContext(std::addressof(thread_context), thread_id, svc::ThreadContextFlag_General | svc::ThreadContextFlag_Control)); /* Add important registers. */ /* TODO: aarch32 */ @@ -1280,7 +1280,7 @@ namespace ams::dmnt { /* Add the thread core. */ { u32 core = 0; - m_debug_process.GetThreadCurrentCore(std::addressof(core), thread_id); + R_DISCARD(m_debug_process.GetThreadCurrentCore(std::addressof(core), thread_id)); AppendReplyFormat(m_reply_cur, m_reply_end, ";core:%u;", core); } @@ -1305,7 +1305,7 @@ namespace ams::dmnt { /* If we should, break the process. */ if (do_break) { - m_debug_process.Break(); + R_DISCARD(m_debug_process.Break()); } } } @@ -1721,7 +1721,7 @@ namespace ams::dmnt { } void GdbServerImpl::k() { - m_debug_process.Terminate(); + R_DISCARD(m_debug_process.Terminate()); m_killed = true; } @@ -2369,7 +2369,7 @@ namespace ams::dmnt { /* Get the thread core. */ u32 core = 0; - m_debug_process.GetThreadCurrentCore(std::addressof(core), thread_ids[i]); + R_DISCARD(m_debug_process.GetThreadCurrentCore(std::addressof(core), thread_ids[i])); /* Get the thread name. */ char name[os::ThreadNameLengthMax + 1]; diff --git a/stratosphere/dmnt.gen2/source/dmnt2_hardware_breakpoint.cpp b/stratosphere/dmnt.gen2/source/dmnt2_hardware_breakpoint.cpp index 563918825..5d9079b4c 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_hardware_breakpoint.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_hardware_breakpoint.cpp @@ -197,7 +197,7 @@ namespace ams::dmnt { g_last_bp_ctx_register = g_last_bp_register; for (int i = g_last_bp_ctx_register; i >= static_cast(svc::HardwareBreakPointRegisterName_I0); --i) { const Result result = svc::SetHardwareBreakPoint(static_cast(i), dbgbcr, svc::PseudoHandle::CurrentProcess); - svc::SetHardwareBreakPoint(static_cast(i), 0, 0); + R_DISCARD(svc::SetHardwareBreakPoint(static_cast(i), 0, 0)); if (R_FAILED(result)) { if (!svc::ResultInvalidHandle::Includes(result)) { diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp index 627c56bdd..521461c89 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp @@ -346,7 +346,7 @@ namespace ams::dmnt::cheat::impl { Result ResumeCheatProcessUnsafe() { m_broken_unsafe = false; m_unsafe_break_event.Signal(); - dmnt::cheat::impl::ContinueCheatProcess(this->GetCheatProcessHandle()); + R_DISCARD(dmnt::cheat::impl::ContinueCheatProcess(this->GetCheatProcessHandle())); R_SUCCEED(); } @@ -682,7 +682,7 @@ namespace ams::dmnt::cheat::impl { while (true) { eventLoadRemote(std::addressof(hook), manager->HookToCreateApplicationProcess(), true); if (R_SUCCEEDED(eventWait(std::addressof(hook), std::numeric_limits::max()))) { - manager->AttachToApplicationProcess(true); + R_DISCARD(manager->AttachToApplicationProcess(true)); } eventClose(std::addressof(hook)); } @@ -760,7 +760,7 @@ namespace ams::dmnt::cheat::impl { const auto &value = entry.GetValue(); /* Use Write SVC directly, to avoid the usual frozen address update logic. */ - svc::WriteDebugProcessMemory(manager->GetCheatProcessHandle(), reinterpret_cast(std::addressof(value.value)), address, value.width); + R_DISCARD(svc::WriteDebugProcessMemory(manager->GetCheatProcessHandle(), reinterpret_cast(std::addressof(value.value)), address, value.width)); } } } @@ -1146,8 +1146,8 @@ namespace ams::dmnt::cheat::impl { { char path[fs::EntryNameLengthMax + 1]; util::SNPrintf(path, sizeof(path), "sdmc:/atmosphere/contents/%016lx/cheats/toggles.txt", program_id.value); - fs::DeleteFile(path); - fs::CreateFile(path, 0); + R_DISCARD(fs::DeleteFile(path)); + R_DISCARD(fs::CreateFile(path, 0)); if (R_FAILED(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend))) { return; } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp index c1ecfb675..11b25b3a2 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_vm.cpp @@ -21,7 +21,7 @@ namespace ams::dmnt::cheat::impl { void CheatVirtualMachine::DebugLog(u32 log_id, u64 value) { /* Just unconditionally try to create the log folder. */ - fs::EnsureDirectory("sdmc:/atmosphere/cheat_vm_logs"); + R_DISCARD(fs::EnsureDirectory("sdmc:/atmosphere/cheat_vm_logs")); fs::FileHandle log_file; { @@ -40,7 +40,7 @@ namespace ams::dmnt::cheat::impl { char log_value[18]; util::SNPrintf(log_value, sizeof(log_value), "%016lx\n", value); - fs::WriteFile(log_file, log_offset, log_value, std::strlen(log_value), fs::WriteOption::Flush); + R_DISCARD(fs::WriteFile(log_file, log_offset, log_value, std::strlen(log_value), fs::WriteOption::Flush)); } void CheatVirtualMachine::OpenDebugLogFile() { @@ -796,7 +796,7 @@ namespace ams::dmnt::cheat::impl { u64 kHeld = 0; /* Get Keys held. */ - hid::GetKeysHeld(std::addressof(kHeld)); + R_DISCARD(hid::GetKeysHeld(std::addressof(kHeld))); this->OpenDebugLogFile(); ON_SCOPE_EXIT { this->CloseDebugLogFile(); }; @@ -838,7 +838,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.store_static.bit_width); + R_DISCARD(dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.store_static.bit_width)); break; } } @@ -853,7 +853,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(src_address, std::addressof(src_value), cur_opcode.begin_cond.bit_width); + R_DISCARD(dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(src_address, std::addressof(src_value), cur_opcode.begin_cond.bit_width)); break; } /* Check against condition. */ @@ -933,7 +933,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(src_address, std::addressof(m_registers[cur_opcode.ldr_memory.reg_index]), cur_opcode.ldr_memory.bit_width); + R_DISCARD(dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(src_address, std::addressof(m_registers[cur_opcode.ldr_memory.reg_index]), cur_opcode.ldr_memory.bit_width)); break; } } @@ -952,7 +952,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.str_static.bit_width); + R_DISCARD(dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.str_static.bit_width)); break; } /* Increment register if relevant. */ @@ -1143,7 +1143,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.str_register.bit_width); + R_DISCARD(dmnt::cheat::impl::WriteCheatProcessMemoryUnsafe(dst_address, std::addressof(dst_value), cur_opcode.str_register.bit_width)); break; } @@ -1214,7 +1214,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(cond_address, std::addressof(cond_value), cur_opcode.begin_reg_cond.bit_width); + R_DISCARD(dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(cond_address, std::addressof(cond_value), cur_opcode.begin_reg_cond.bit_width)); break; } } @@ -1309,10 +1309,10 @@ namespace ams::dmnt::cheat::impl { } break; case CheatVmOpcodeType_PauseProcess: - dmnt::cheat::impl::PauseCheatProcessUnsafe(); + R_DISCARD(dmnt::cheat::impl::PauseCheatProcessUnsafe()); break; case CheatVmOpcodeType_ResumeProcess: - dmnt::cheat::impl::ResumeCheatProcessUnsafe(); + R_DISCARD(dmnt::cheat::impl::ResumeCheatProcessUnsafe()); break; case CheatVmOpcodeType_DebugLog: { @@ -1356,7 +1356,7 @@ namespace ams::dmnt::cheat::impl { case 2: case 4: case 8: - dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(val_address, std::addressof(log_value), cur_opcode.debug_log.bit_width); + R_DISCARD(dmnt::cheat::impl::ReadCheatProcessMemoryUnsafe(val_address, std::addressof(log_value), cur_opcode.debug_log.bit_width)); break; } } diff --git a/stratosphere/erpt/source/erpt_main.cpp b/stratosphere/erpt/source/erpt_main.cpp index 93096dbcb..9e9f289ad 100644 --- a/stratosphere/erpt/source/erpt_main.cpp +++ b/stratosphere/erpt/source/erpt_main.cpp @@ -62,9 +62,9 @@ namespace ams { { u8 disable_report_cleanup = 0; if (settings::fwdbg::GetSettingsItemValue(std::addressof(disable_report_cleanup), sizeof(disable_report_cleanup), "erpt", "disable_automatic_report_cleanup") == sizeof(disable_report_cleanup)) { - erpt::srv::SetEnabledAutomaticReportCleanup(disable_report_cleanup == 0); + R_DISCARD(erpt::srv::SetEnabledAutomaticReportCleanup(disable_report_cleanup == 0)); } else { - erpt::srv::SetEnabledAutomaticReportCleanup(true); + R_DISCARD(erpt::srv::SetEnabledAutomaticReportCleanup(true)); } } @@ -72,7 +72,7 @@ namespace ams { R_ABORT_UNLESS(erpt::srv::Initialize(erpt::g_memory_heap, erpt::MemoryHeapSize)); /* Atmosphere always wants to redirect new reports to the SD card, to prevent them from being logged. */ - erpt::srv::SetRedirectNewReportsToSdCard(true); + R_DISCARD(erpt::srv::SetRedirectNewReportsToSdCard(true)); /* Configure the serial number, OS version, product model, and region. */ { diff --git a/stratosphere/fatal/source/fatal_repair.cpp b/stratosphere/fatal/source/fatal_repair.cpp index 201ec4ba4..f2054b421 100644 --- a/stratosphere/fatal/source/fatal_repair.cpp +++ b/stratosphere/fatal/source/fatal_repair.cpp @@ -105,11 +105,11 @@ namespace ams::fatal::srv { void CheckRepairStatus() { if (IsInRepairWithoutVolHeld()) { - ThrowFatalForSelf(ResultInRepairWithoutVolHeld()); + R_DISCARD(ThrowFatalForSelf(ResultInRepairWithoutVolHeld())); } if (IsInRepairWithoutTimeReviserCartridge()) { - ThrowFatalForSelf(ResultInRepairWithoutTimeReviserCartridge()); + R_DISCARD(ThrowFatalForSelf(ResultInRepairWithoutTimeReviserCartridge())); } } diff --git a/stratosphere/fatal/source/fatal_task_error_report.cpp b/stratosphere/fatal/source/fatal_task_error_report.cpp index cac9db288..9e69c79f3 100644 --- a/stratosphere/fatal/source/fatal_task_error_report.cpp +++ b/stratosphere/fatal/source/fatal_task_error_report.cpp @@ -24,7 +24,7 @@ namespace ams::fatal::srv { /* Helpers. */ void TryEnsureReportDirectories() { - fs::EnsureDirectory("sdmc:/atmosphere/fatal_reports/dumps"); + R_DISCARD(fs::EnsureDirectory("sdmc:/atmosphere/fatal_reports/dumps")); } bool TryGetCurrentTimestamp(u64 *out) { diff --git a/stratosphere/htc/source/htc_main.cpp b/stratosphere/htc/source/htc_main.cpp index 5477bc113..5c54d5f3e 100644 --- a/stratosphere/htc/source/htc_main.cpp +++ b/stratosphere/htc/source/htc_main.cpp @@ -177,7 +177,7 @@ namespace ams { /* Create the htc misc ipc thread. */ os::ThreadType htc_ipc_thread; - os::CreateThread(std::addressof(htc_ipc_thread), htc::HtcIpcThreadFunction, nullptr, htc::g_htc_ipc_thread_stack, sizeof(htc::g_htc_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcIpc)); + R_DISCARD(os::CreateThread(std::addressof(htc_ipc_thread), htc::HtcIpcThreadFunction, nullptr, htc::g_htc_ipc_thread_stack, sizeof(htc::g_htc_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcIpc))); os::SetThreadNamePointer(std::addressof(htc_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcIpc)); /* Initialize the htcfs server. */ @@ -186,7 +186,7 @@ namespace ams { /* Create the htcfs ipc thread. */ os::ThreadType htcfs_ipc_thread; - os::CreateThread(std::addressof(htcfs_ipc_thread), htc::HtcfsIpcThreadFunction, nullptr, htc::g_htcfs_ipc_thread_stack, sizeof(htc::g_htcfs_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcfsIpc)); + R_DISCARD(os::CreateThread(std::addressof(htcfs_ipc_thread), htc::HtcfsIpcThreadFunction, nullptr, htc::g_htcfs_ipc_thread_stack, sizeof(htc::g_htcfs_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcfsIpc))); os::SetThreadNamePointer(std::addressof(htcfs_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcfsIpc)); /* Initialize the htcs server. */ @@ -196,7 +196,7 @@ namespace ams { /* Create the htcs ipc threads. */ os::ThreadType htcs_ipc_threads[htc::NumHtcsIpcThreads]; for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) { - os::CreateThread(std::addressof(htcs_ipc_threads[i]), htc::HtcsIpcThreadFunction, nullptr, htc::g_htcs_ipc_thread_stack[i], sizeof(htc::g_htcs_ipc_thread_stack[i]), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcsIpc)); + R_DISCARD(os::CreateThread(std::addressof(htcs_ipc_threads[i]), htc::HtcsIpcThreadFunction, nullptr, htc::g_htcs_ipc_thread_stack[i], sizeof(htc::g_htcs_ipc_thread_stack[i]), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcsIpc))); os::SetThreadNamePointer(std::addressof(htcs_ipc_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcsIpc)); } diff --git a/stratosphere/loader/source/ldr_argument_store.hpp b/stratosphere/loader/source/ldr_argument_store.hpp index cc7bee4b8..6a417971c 100644 --- a/stratosphere/loader/source/ldr_argument_store.hpp +++ b/stratosphere/loader/source/ldr_argument_store.hpp @@ -33,7 +33,7 @@ namespace ams::ldr { Entry m_argument_map[ArgumentMapCount]; public: constexpr ArgumentStore() : m_argument_map{} { - this->Flush(); + R_DISCARD(this->Flush()); } public: const Entry *Get(ncm::ProgramId program_id); diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 9b8386081..8ba4fac2a 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -812,7 +812,7 @@ namespace ams::ldr { /* Set the output handle, and ensure that if we fail after this point we clean it up. */ out->process_handle = process_handle; out->code_address = param.code_address; - ON_RESULT_FAILURE { svc::CloseHandle(process_handle); }; + ON_RESULT_FAILURE { R_DISCARD(svc::CloseHandle(process_handle)); }; /* Load all auto load modules. */ R_RETURN(LoadAutoLoadModules(out, ctx, argument)); @@ -882,7 +882,7 @@ namespace ams::ldr { /* If we're overriding for HBL, perform HTML document redirection. */ if (override_status.IsHbl()) { /* Don't validate result, failure is okay. */ - RedirectHtmlDocumentPathForHbl(loc); + R_DISCARD(RedirectHtmlDocumentPathForHbl(loc)); } /* Clear the external code for the program. */ diff --git a/stratosphere/pm/source/impl/pm_process_info.cpp b/stratosphere/pm/source/impl/pm_process_info.cpp index d472803dc..1c51e3f10 100644 --- a/stratosphere/pm/source/impl/pm_process_info.cpp +++ b/stratosphere/pm/source/impl/pm_process_info.cpp @@ -89,8 +89,8 @@ namespace ams::pm::impl { if (m_handle != os::InvalidNativeHandle) { /* Unregister the process. */ fsprUnregisterProgram(m_process_id.value); - sm::manager::UnregisterProcess(m_process_id); - ldr::pm::UnpinProgram(m_pin_id); + R_DISCARD(sm::manager::UnregisterProcess(m_process_id)); + R_DISCARD(ldr::pm::UnpinProgram(m_pin_id)); /* Close the process's handle. */ os::CloseNativeHandle(m_handle); diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index 95922c979..5bd14732c 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -142,7 +142,7 @@ namespace ams::pm::impl { R_TRY(ldr::pm::AtmospherePinProgram(std::addressof(pin_id), fixed_location, override_status)); /* If we fail after now, unpin. */ - ON_RESULT_FAILURE { ldr::pm::UnpinProgram(pin_id); }; + ON_RESULT_FAILURE { R_DISCARD(ldr::pm::UnpinProgram(pin_id)); }; /* Ensure we can talk to mitm services. */ { @@ -486,7 +486,7 @@ namespace ams::pm::impl { /* NOTE: Nintendo does not check the result of this. */ if (spl::IsDisabledProgramVerification()) { if (hos::GetVersion() >= hos::Version_10_0_0) { - ldr::pm::SetEnabledProgramVerification(false); + R_DISCARD(ldr::pm::SetEnabledProgramVerification(false)); } else { fsprSetEnabledProgramVerification(false); } diff --git a/stratosphere/pm/source/impl/pm_process_tracker.cpp b/stratosphere/pm/source/impl/pm_process_tracker.cpp index 5d1c3b418..8f436f00f 100644 --- a/stratosphere/pm/source/impl/pm_process_tracker.cpp +++ b/stratosphere/pm/source/impl/pm_process_tracker.cpp @@ -94,7 +94,7 @@ namespace ams::pm::impl { auto list = GetProcessList(); /* Reset the process's signal. */ - svc::ResetSignal(process_info->GetHandle()); + R_DISCARD(svc::ResetSignal(process_info->GetHandle())); /* Update the process's state. */ const svc::ProcessState old_state = process_info->GetState(); diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 5bef871c7..a4925ef67 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -54,8 +54,8 @@ namespace ams { void RegisterPrivilegedProcess(os::ProcessId process_id, ncm::ProgramId program_id) { fsprUnregisterProgram(process_id.value); fsprRegisterProgram(process_id.value, process_id.value, NcmStorageId_BuiltInSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl), 0); - sm::manager::UnregisterProcess(process_id); - sm::manager::RegisterProcess(process_id, program_id, cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl)); + R_DISCARD(sm::manager::UnregisterProcess(process_id)); + R_DISCARD(sm::manager::RegisterProcess(process_id, program_id, cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl))); } void RegisterPrivilegedProcesses() { diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index 6beff3c8f..a10c81b93 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -116,7 +116,7 @@ namespace ams::ro::impl { if (m_process_handle != os::InvalidNativeHandle) { for (size_t i = 0; i < MaxNrrInfos; i++) { if (m_nrr_in_use[i]) { - UnmapNrr(m_process_handle, m_nrr_infos[i].mapped_header, m_nrr_infos[i].nrr_heap_address, m_nrr_infos[i].nrr_heap_size, m_nrr_infos[i].mapped_code_address); + R_DISCARD(UnmapNrr(m_process_handle, m_nrr_infos[i].mapped_header, m_nrr_infos[i].nrr_heap_address, m_nrr_infos[i].nrr_heap_size, m_nrr_infos[i].mapped_code_address)); } } os::CloseNativeHandle(m_process_handle); @@ -659,7 +659,7 @@ namespace ams::ro::impl { /* Map the NRO. */ R_TRY(MapNro(std::addressof(nro_info->base_address), context->GetProcessHandle(), nro_address, nro_size, bss_address, bss_size)); - ON_RESULT_FAILURE { UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size); }; + ON_RESULT_FAILURE { R_DISCARD(UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size)); }; /* Parse the NRO. */ u64 rx_size = 0, ro_size = 0, rw_size = 0; diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp index a6e1134a1..b9d2491d5 100644 --- a/stratosphere/spl/source/spl_main.cpp +++ b/stratosphere/spl/source/spl_main.cpp @@ -147,7 +147,7 @@ namespace ams { R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Ssl, SslServiceName, SslMaxSessions)); R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Es, EsServiceName, EsMaxSessions)); if (fw_ver >= hos::Version_5_0_0) { - g_server_manager.RegisterServer(PortIndex_Manu, ManuServiceName, ManuMaxSessions); + R_DISCARD(g_server_manager.RegisterServer(PortIndex_Manu, ManuServiceName, ManuMaxSessions)); } } diff --git a/stratosphere/spl/source/spl_secure_monitor_manager.cpp b/stratosphere/spl/source/spl_secure_monitor_manager.cpp index c31bae8bf..39ed37b3e 100644 --- a/stratosphere/spl/source/spl_secure_monitor_manager.cpp +++ b/stratosphere/spl/source/spl_secure_monitor_manager.cpp @@ -164,7 +164,7 @@ namespace ams::spl { for (auto i = 0; i < impl::AesKeySlotCount; ++i) { if (m_aes_keyslot_owners[i] == owner) { m_aes_keyslot_owners[i] = nullptr; - impl::DeallocateAesKeySlot(impl::AesKeySlotMin + i); + R_DISCARD(impl::DeallocateAesKeySlot(impl::AesKeySlotMin + i)); } } } diff --git a/troposphere/haze/include/haze/console_main_loop.hpp b/troposphere/haze/include/haze/console_main_loop.hpp index 184c36fc6..ce54bad69 100644 --- a/troposphere/haze/include/haze/console_main_loop.hpp +++ b/troposphere/haze/include/haze/console_main_loop.hpp @@ -214,8 +214,8 @@ namespace haze { event_reactor.SetResult(ResultSuccess()); /* Configure the PTP responder and console main loop. */ - ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap)); - console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap)); + R_DISCARD(ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap))); + R_DISCARD(console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap))); /* Ensure we maintain a clean state on exit. */ ON_SCOPE_EXIT { From 58f2b963d556f71240c8f38c0184ea06c7e7c757 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 24 Sep 2026 01:18:59 +0100 Subject: [PATCH 45/52] ro: implement NRO decompression and fix bugs --- .../stratosphere/util/util_compression.hpp | 1 + .../source/util/util_compression_lz4.cpp | 148 +++++++++++++++++- .../ro/source/impl/ro_service_impl.cpp | 60 ++++++- 3 files changed, 200 insertions(+), 9 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp b/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp index 543503d65..4a11dec61 100644 --- a/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp +++ b/libraries/libstratosphere/include/stratosphere/util/util_compression.hpp @@ -28,6 +28,7 @@ namespace ams::util { /* Decompression utilities. */ int DecompressLZ4(void *dst, size_t dst_size, const void *src, size_t src_size); + int DecompressLZ4Frame(size_t* out_size, void *dst, size_t dst_size, const void *src, size_t src_size, void *src_work, size_t src_work_size, void *dst_work, size_t dst_work_size); size_t DecompressZstd(void *dst, size_t dst_size, const void *src, size_t src_size); size_t DecompressZstdWithBic(void *dst, size_t dst_size, const void *src, size_t src_size); bool DecompressZstdWithBic(void* workspace, size_t workspace_size, void *dst, size_t dst_size, size_t expected_dec_size, const void *src, size_t src_size); diff --git a/libraries/libstratosphere/source/util/util_compression_lz4.cpp b/libraries/libstratosphere/source/util/util_compression_lz4.cpp index f56904f71..05b1dfa76 100644 --- a/libraries/libstratosphere/source/util/util_compression_lz4.cpp +++ b/libraries/libstratosphere/source/util/util_compression_lz4.cpp @@ -35,5 +35,151 @@ namespace ams::util { /* This is just a thin wrapper around LZ4. */ return LZ4_decompress_safe(reinterpret_cast(src), reinterpret_cast(dst), static_cast(src_size), static_cast(dst_size)); } - + + /* TODO: This was added for ro in 23.0.0+, but it's unclear if this is even part of the util namespace. */ + /* It's similar to the official lz4frame code, but has additional constraints and uses static work buffers. */ + /* Evaluate if we should use lz4frame instead and implement matching frame compression. */ + int DecompressLZ4Frame(size_t* out_size, void *dst, size_t dst_size, const void *src, size_t src_size, void *src_work, size_t src_work_size, void *dst_work, size_t dst_work_size) { + /* Destination buffer must be behind source buffer. */ + if (dst > src) { + std::memset(dst, 0, dst_size); + return -1; + } + + const char *src_end = static_cast(src) + src_size; + const char *dst_end = static_cast(dst) + dst_size; + + if ((src_end != dst_end) || (src_work_size != 0x10000) || (dst_work_size != 0x10000)) { + std::memset(dst, 0, dst_size); + return -1; + } + + if (src_size < 7) { + std::memset(dst, 0, dst_size); + return -2; + } + + const uint32_t magic = *reinterpret_cast(src); + const uint8_t flg = *reinterpret_cast(src) + 4; + const uint8_t bd = *reinterpret_cast(src) + 5; + const uint8_t header_checksum = *reinterpret_cast(src) + 6; + + /* Check for LZ4F_MAGICNUMBER, validate flags and block size. */ + if ((magic != 0x184D2204) || ((flg & 1) != 0) || (flg != 0x60) || (bd != 0x40)) { + std::memset(dst, 0, dst_size); + return -2; + } + + /* TODO: Implement header checksum validation. This requires xxhash, do we want to have xxhash in util? */ + AMS_UNUSED(header_checksum); + + uint32_t src_pos = 7; /* Skip the header. */ + uint32_t dst_pos = 0; + + /* Destination size is too small. */ + if (dst_size < src_pos) { + std::memset(dst, 0, dst_size); + return -2; + } + + while (true) { + /* Not enough space left. */ + if ((dst_size - src_pos) < 4) { + std::memset(dst, 0, dst_size); + return -4; + } + + const char* src_data_block = reinterpret_cast(src) + src_pos; + char* dst_data_block = reinterpret_cast(dst) + dst_pos; + + const uint32_t block_header = *reinterpret_cast(src_data_block); + + /* We've reached the end. */ + if (!block_header) { + break; + } + + const uint32_t block_size = block_header & 0x7FFFFFFF; + + /* Block size is invalid. */ + if (block_size > 0x10000) { + std::memset(dst, 0, dst_size); + return -3; + } + + /* Advance the data block. */ + src_data_block += sizeof(block_header); + + /* Block size is invalid. */ + if ((dst_end - src_data_block) < block_size) { + std::memset(dst, 0, dst_size); + return -4; + } + + /* Copy the data block to the source work buffer. */ + std::memcpy(static_cast(src_work), src_data_block, block_size); + + if ((block_header & 0x80000000) != 0) { + /* Block size is invalid. */ + if ((dst_end - dst_data_block) < block_size) { + std::memset(dst, 0, dst_size); + return -4; + } + + dst_pos += block_size; + src_pos += block_size; + + /* Destination is overrunning source. */ + if (dst_pos > src_pos) { + std::memset(dst, 0, dst_size); + return -5; + } + + /* This is a raw block, copy it. */ + std::memmove(dst_data_block, src_data_block, block_size); + } else { + /* This is a compressed block, decompress it. */ + int decompressed_size = LZ4_decompress_safe(reinterpret_cast(src_work), reinterpret_cast(dst_work), static_cast(src_work_size), static_cast(dst_work_size)); + + /* Decompressed size is invalid. */ + if (decompressed_size < 1) { + std::memset(dst, 0, dst_size); + return -3; + } + + /* Decompressed size is invalid. */ + if ((dst_end - dst_data_block) < decompressed_size) { + std::memset(dst, 0, dst_size); + return -4; + } + + dst_pos += decompressed_size; + src_pos += block_size; + + /* Destination is overrunning source. */ + if (dst_pos > src_pos) { + std::memset(dst, 0, dst_size); + return -5; + } + + /* Copy the decompressed data back. */ + std::memcpy(dst_data_block, static_cast(dst_work), decompressed_size); + } + + /* We've exceeded the destination's size. */ + if (src_pos >= dst_size) { + std::memset(dst, 0, dst_size); + return -2; + } + } + + /* We didn't consume all data. */ + if (src_pos != src_size) { + std::memset(dst, 0, dst_size); + return -2; + } + + *out_size = dst_pos; + return 0; + } } \ No newline at end of file diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index a10c81b93..63b93d8f8 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -94,6 +94,8 @@ namespace ams::ro::impl { os::NativeHandle m_process_handle = os::InvalidNativeHandle; os::ProcessId m_process_id = os::InvalidProcessId; bool m_in_use{}; + u8 m_decompression_src_work_buffer[0x10000]{}; + u8 m_decompression_dst_work_buffer[0x10000]{}; public: constexpr ProcessContext() = default; @@ -108,6 +110,9 @@ namespace ams::ro::impl { m_process_handle = process_handle; m_process_id = process_id; m_in_use = true; + + std::memset(m_decompression_src_work_buffer, 0, sizeof(m_decompression_src_work_buffer)); + std::memset(m_decompression_dst_work_buffer, 0, sizeof(m_decompression_dst_work_buffer)); } void Finalize() { @@ -259,7 +264,7 @@ namespace ams::ro::impl { R_THROW(ro::ResultNotAuthorized()); } - Result ValidateNro(NroHeader **out_header, AdditionalNroHeaderInfo **out_additional_header_info, void *out_additional_header_hash, u8 *mapped_memory, u64 expected_nro_size, u64 expected_bss_size) { + Result ValidateNro(NroHeader **out_header, AdditionalNroHeaderInfo *out_additional_header_info, void *out_additional_header_hash, u8 *mapped_memory, u64 expected_nro_size, u64 expected_bss_size) { /* Validate header. */ NroHeader *header = reinterpret_cast(mapped_memory); R_UNLESS(header->IsMagicValid(), ro::ResultInvalidNro()); @@ -348,11 +353,11 @@ namespace ams::ro::impl { R_UNLESS(util::AlignUp(compressed_size, os::MemoryPageSize) == expected_nro_size, ro::ResultInvalidNro()); /* Copy the additional header info to output. This is AdditionalNroHeader minus the hash. */ - std::memcpy(out_additional_header_info, additional_header, sizeof(*additional_header) - hash_size); + std::memcpy(reinterpret_cast(out_additional_header_info), additional_header, sizeof(AdditionalNroHeader) - hash_size); } else { /* Explicitly clear additional header hash and info. */ std::memset(out_additional_header_hash, 0, crypto::Sha256Generator::HashSize); - std::memset(out_additional_header_info, 0, sizeof(AdditionalNroHeaderInfo)); + std::memset(reinterpret_cast(out_additional_header_info), 0, sizeof(AdditionalNroHeaderInfo)); } /* Copy the header to output. */ @@ -361,9 +366,48 @@ namespace ams::ro::impl { } Result DecompressNro(u8 *mapped_nro, u64 expected_nro_size, const NroHeader *nro_header, u32 compressed_size) { - /* TODO */ - AMS_UNUSED(mapped_nro, expected_nro_size, nro_header, compressed_size); - R_SUCCEED(); + /* Read sizes from header. */ + const u64 rw_ofs = nro_header->GetRwOffset(); + const u64 rw_size = nro_header->GetRwSize(); + const u64 bss_size = nro_header->GetBssSize(); + + /* Divide the mapped NRO into regions devised for the decompression. */ + u8 *nro_aligned_start = static_cast(mapped_nro + 0x1000); + const u8 *nro_expected_end = static_cast(mapped_nro + expected_nro_size); + const u64 nro_src_buffer_size = compressed_size - 0x1000; + u8 *nro_src_buffer = static_cast(mapped_nro + expected_nro_size - nro_src_buffer_size); + const u64 nro_dst_buffer_size = expected_nro_size - 0xC00; + u8 *nro_dst_buffer = static_cast(mapped_nro + 0xC00); + + /* Copy to source buffer. */ + std::memmove(nro_src_buffer, nro_aligned_start, nro_src_buffer_size); + + /* Decompress. */ + u64 decompressed_size = 0; + R_UNLESS(util::DecompressLZ4Frame(std::addressof(decompressed_size), nro_dst_buffer, nro_dst_buffer_size, nro_src_buffer, nro_src_buffer_size, m_decompression_src_work_buffer, sizeof(m_decompression_src_work_buffer), m_decompression_dst_work_buffer, sizeof(m_decompression_dst_work_buffer)), ro::ResultInvalidNro()); + + /* Find the BSS. */ + u8 *nro_expected_bss_start = static_cast(mapped_nro + rw_ofs + rw_size); + const u8 *nro_expected_bss_end = static_cast(nro_expected_bss_start + bss_size); + const u8 *nro_bss_start = static_cast(nro_expected_bss_start - 0x400); + const u8 *nro_decompressed_end = static_cast(nro_dst_buffer + decompressed_size); + + /* The decompressed data must end at the expected BSS start. */ + if (nro_decompressed_end == nro_bss_start) { + /* Copy the decompressed data back to the mapped NRO memory. */ + std::memmove(nro_aligned_start, nro_dst_buffer, decompressed_size); + std::memset(nro_dst_buffer, 0, 0x400); + + /* Check the BSS ends where it's supposed, initialize it and then succeed. */ + if (nro_expected_bss_end == nro_expected_end) { + std::memset(nro_expected_bss_start, 0, bss_size); + R_SUCCEED(); + } + } + + /* Clear the decompressed data buffer in case of error. */ + std::memset(nro_dst_buffer, 0, nro_dst_buffer_size); + R_THROW(ro::ResultInvalidNro()); } Result CheckAdditionalHeaderHash(const u8 *mapped_nro, const void *additional_nro_header_hash, size_t additional_nro_header_hash_size, u64 rw_ofs, u64 rw_size) { @@ -391,13 +435,13 @@ namespace ams::ro::impl { /* ValidateNro */ NroHeader *nro_header = nullptr; - AdditionalNroHeaderInfo *additional_nro_header_info = nullptr; + AdditionalNroHeaderInfo additional_nro_header_info; u8 additional_nro_header_hash[crypto::Sha256Generator::HashSize]; R_TRY(this->ValidateNro(std::addressof(nro_header), std::addressof(additional_nro_header_info), std::addressof(additional_nro_header_hash), static_cast(mapped_memory), expected_nro_size, expected_bss_size)); /* DecompressNro */ if (nro_header->IsCompress()) { - R_TRY(this->DecompressNro(static_cast(mapped_memory), expected_nro_size, nro_header, additional_nro_header_info->compressed_size)); + R_TRY(this->DecompressNro(static_cast(mapped_memory), expected_nro_size, nro_header, additional_nro_header_info.compressed_size)); /* CheckAdditionalHeaderHash */ if (nro_header->GetAdditionalHeaderOffset() != 0) { From 2ae182bd5d6289f9d933e9782e144235ed56de1b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Fri, 25 Sep 2026 01:33:40 +0100 Subject: [PATCH 46/52] ro: add missing fixes --- .../source/util/util_compression_lz4.cpp | 48 +++++++++-------- .../ro/source/impl/ro_service_impl.cpp | 54 +++++++++++-------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/libraries/libstratosphere/source/util/util_compression_lz4.cpp b/libraries/libstratosphere/source/util/util_compression_lz4.cpp index 05b1dfa76..46950e180 100644 --- a/libraries/libstratosphere/source/util/util_compression_lz4.cpp +++ b/libraries/libstratosphere/source/util/util_compression_lz4.cpp @@ -40,29 +40,31 @@ namespace ams::util { /* It's similar to the official lz4frame code, but has additional constraints and uses static work buffers. */ /* Evaluate if we should use lz4frame instead and implement matching frame compression. */ int DecompressLZ4Frame(size_t* out_size, void *dst, size_t dst_size, const void *src, size_t src_size, void *src_work, size_t src_work_size, void *dst_work, size_t dst_work_size) { + const u8 *src_buffer = reinterpret_cast(src); + u8 *dst_buffer = reinterpret_cast(dst); + /* Destination buffer must be behind source buffer. */ - if (dst > src) { + if (dst_buffer > src_buffer) { std::memset(dst, 0, dst_size); return -1; } - const char *src_end = static_cast(src) + src_size; - const char *dst_end = static_cast(dst) + dst_size; - - if ((src_end != dst_end) || (src_work_size != 0x10000) || (dst_work_size != 0x10000)) { + /* Size checks. */ + if (((src_buffer + src_size) != (dst_buffer + dst_size)) || (src_work_size != 0x10000) || (dst_work_size != 0x10000)) { std::memset(dst, 0, dst_size); return -1; } + /* Source size must at least include one frame header. */ if (src_size < 7) { std::memset(dst, 0, dst_size); return -2; } - const uint32_t magic = *reinterpret_cast(src); - const uint8_t flg = *reinterpret_cast(src) + 4; - const uint8_t bd = *reinterpret_cast(src) + 5; - const uint8_t header_checksum = *reinterpret_cast(src) + 6; + const u32 magic = *reinterpret_cast(src_buffer); + const u8 flg = src_buffer[4]; + const u8 bd = src_buffer[5]; + const u8 header_checksum = src_buffer[6]; /* Check for LZ4F_MAGICNUMBER, validate flags and block size. */ if ((magic != 0x184D2204) || ((flg & 1) != 0) || (flg != 0x60) || (bd != 0x40)) { @@ -73,8 +75,8 @@ namespace ams::util { /* TODO: Implement header checksum validation. This requires xxhash, do we want to have xxhash in util? */ AMS_UNUSED(header_checksum); - uint32_t src_pos = 7; /* Skip the header. */ - uint32_t dst_pos = 0; + u32 src_pos = 7; /* Skip the header. */ + u32 dst_pos = 0; /* Destination size is too small. */ if (dst_size < src_pos) { @@ -89,17 +91,17 @@ namespace ams::util { return -4; } - const char* src_data_block = reinterpret_cast(src) + src_pos; - char* dst_data_block = reinterpret_cast(dst) + dst_pos; + src_buffer += src_pos; + dst_buffer += dst_pos; - const uint32_t block_header = *reinterpret_cast(src_data_block); + const u32 block_header = *reinterpret_cast(src_buffer); /* We've reached the end. */ if (!block_header) { break; } - const uint32_t block_size = block_header & 0x7FFFFFFF; + const u32 block_size = block_header & 0x7FFFFFFF; /* Block size is invalid. */ if (block_size > 0x10000) { @@ -108,20 +110,20 @@ namespace ams::util { } /* Advance the data block. */ - src_data_block += sizeof(block_header); + src_buffer += sizeof(block_header); /* Block size is invalid. */ - if ((dst_end - src_data_block) < block_size) { + if (((dst_buffer + dst_size) - src_buffer) < block_size) { std::memset(dst, 0, dst_size); return -4; } /* Copy the data block to the source work buffer. */ - std::memcpy(static_cast(src_work), src_data_block, block_size); + std::memcpy(static_cast(src_work), src_buffer, block_size); if ((block_header & 0x80000000) != 0) { /* Block size is invalid. */ - if ((dst_end - dst_data_block) < block_size) { + if (dst_size < block_size) { std::memset(dst, 0, dst_size); return -4; } @@ -136,10 +138,10 @@ namespace ams::util { } /* This is a raw block, copy it. */ - std::memmove(dst_data_block, src_data_block, block_size); + std::memmove(dst_buffer, src_buffer, block_size); } else { /* This is a compressed block, decompress it. */ - int decompressed_size = LZ4_decompress_safe(reinterpret_cast(src_work), reinterpret_cast(dst_work), static_cast(src_work_size), static_cast(dst_work_size)); + int decompressed_size = LZ4_decompress_safe(reinterpret_cast(src_work), reinterpret_cast(dst_work), static_cast(block_size), 0x10000); /* Decompressed size is invalid. */ if (decompressed_size < 1) { @@ -148,7 +150,7 @@ namespace ams::util { } /* Decompressed size is invalid. */ - if ((dst_end - dst_data_block) < decompressed_size) { + if (dst_size < static_cast(decompressed_size)) { std::memset(dst, 0, dst_size); return -4; } @@ -163,7 +165,7 @@ namespace ams::util { } /* Copy the decompressed data back. */ - std::memcpy(dst_data_block, static_cast(dst_work), decompressed_size); + std::memcpy(dst_buffer, static_cast(dst_work), decompressed_size); } /* We've exceeded the destination's size. */ diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index 63b93d8f8..ef1a6afb1 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -134,8 +134,11 @@ namespace ams::ro::impl { m_process_handle = os::InvalidNativeHandle; m_process_id = os::InvalidProcessId; - + m_in_use = false; + + std::memset(m_decompression_src_work_buffer, 0, sizeof(m_decompression_src_work_buffer)); + std::memset(m_decompression_dst_work_buffer, 0, sizeof(m_decompression_dst_work_buffer)); } os::NativeHandle GetProcessHandle() const { @@ -365,7 +368,7 @@ namespace ams::ro::impl { R_SUCCEED(); } - Result DecompressNro(u8 *mapped_nro, u64 expected_nro_size, const NroHeader *nro_header, u32 compressed_size) { + Result DecompressNro(u8 *mapped_nro, u64 total_size, const NroHeader *nro_header, u32 compressed_size) { /* Read sizes from header. */ const u64 rw_ofs = nro_header->GetRwOffset(); const u64 rw_size = nro_header->GetRwSize(); @@ -373,10 +376,10 @@ namespace ams::ro::impl { /* Divide the mapped NRO into regions devised for the decompression. */ u8 *nro_aligned_start = static_cast(mapped_nro + 0x1000); - const u8 *nro_expected_end = static_cast(mapped_nro + expected_nro_size); + const u8 *nro_expected_end = static_cast(mapped_nro + total_size); const u64 nro_src_buffer_size = compressed_size - 0x1000; - u8 *nro_src_buffer = static_cast(mapped_nro + expected_nro_size - nro_src_buffer_size); - const u64 nro_dst_buffer_size = expected_nro_size - 0xC00; + u8 *nro_src_buffer = static_cast(mapped_nro + total_size - nro_src_buffer_size); + const u64 nro_dst_buffer_size = total_size - 0xC00; u8 *nro_dst_buffer = static_cast(mapped_nro + 0xC00); /* Copy to source buffer. */ @@ -384,7 +387,7 @@ namespace ams::ro::impl { /* Decompress. */ u64 decompressed_size = 0; - R_UNLESS(util::DecompressLZ4Frame(std::addressof(decompressed_size), nro_dst_buffer, nro_dst_buffer_size, nro_src_buffer, nro_src_buffer_size, m_decompression_src_work_buffer, sizeof(m_decompression_src_work_buffer), m_decompression_dst_work_buffer, sizeof(m_decompression_dst_work_buffer)), ro::ResultInvalidNro()); + R_UNLESS(util::DecompressLZ4Frame(std::addressof(decompressed_size), nro_dst_buffer, nro_dst_buffer_size, nro_src_buffer, nro_src_buffer_size, m_decompression_src_work_buffer, sizeof(m_decompression_src_work_buffer), m_decompression_dst_work_buffer, sizeof(m_decompression_dst_work_buffer)) == 0, ro::ResultInvalidNro()); /* Find the BSS. */ u8 *nro_expected_bss_start = static_cast(mapped_nro + rw_ofs + rw_size); @@ -423,15 +426,15 @@ namespace ams::ro::impl { R_SUCCEED(); } - Result ParseNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, bool *out_aligned_header, bool *out_is_compress, u64 base_address, u64 expected_nro_size, u64 expected_bss_size) { + Result ParseNro(ModuleId *out_module_id, u64 *out_rx_size, u64 *out_ro_size, u64 *out_rw_size, u64 *out_bss_size, bool *out_aligned_header, bool *out_is_compress, u64 base_address, u64 total_size, u64 expected_nro_size, u64 expected_bss_size) { /* Map the NRO. */ void *mapped_memory = nullptr; - R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, expected_nro_size, ro::impl::GenerateSecureRandom)) { + R_TRY_CATCH(os::MapProcessMemory(std::addressof(mapped_memory), m_process_handle, base_address, total_size, ro::impl::GenerateSecureRandom)) { R_CONVERT(os::ResultOutOfAddressSpace, ro::ResultOutOfAddressSpace()) } R_END_TRY_CATCH; - + /* When we're done, unmap the memory. */ - ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, m_process_handle, base_address, expected_nro_size); }; + ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, m_process_handle, base_address, total_size); }; /* ValidateNro */ NroHeader *nro_header = nullptr; @@ -441,7 +444,7 @@ namespace ams::ro::impl { /* DecompressNro */ if (nro_header->IsCompress()) { - R_TRY(this->DecompressNro(static_cast(mapped_memory), expected_nro_size, nro_header, additional_nro_header_info.compressed_size)); + R_TRY(this->DecompressNro(static_cast(mapped_memory), total_size, nro_header, additional_nro_header_info.compressed_size)); /* CheckAdditionalHeaderHash */ if (nro_header->GetAdditionalHeaderOffset() != 0) { @@ -458,6 +461,7 @@ namespace ams::ro::impl { *out_rx_size = nro_header->GetTextSize(); *out_ro_size = nro_header->GetRoSize(); *out_rw_size = nro_header->GetRwSize(); + *out_bss_size = nro_header->GetBssSize(); *out_aligned_header = nro_header->IsAlignedHeader(); *out_is_compress = nro_header->IsCompress(); R_SUCCEED(); @@ -706,28 +710,28 @@ namespace ams::ro::impl { ON_RESULT_FAILURE { R_DISCARD(UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size)); }; /* Parse the NRO. */ - u64 rx_size = 0, ro_size = 0, rw_size = 0; - bool aligned_header = false; - bool is_compress = false; - R_TRY(context->ParseNro(std::addressof(nro_info->module_id), std::addressof(rx_size), std::addressof(ro_size), std::addressof(rw_size), std::addressof(aligned_header), std::addressof(is_compress), nro_info->base_address, nro_size, bss_size)); + u64 nro_rx_size = 0, nro_ro_size = 0, nro_rw_size = 0, nro_bss_size = 0; + bool nro_aligned_header = false; + bool nro_is_compress = false; + R_TRY(context->ParseNro(std::addressof(nro_info->module_id), std::addressof(nro_rx_size), std::addressof(nro_ro_size), std::addressof(nro_rw_size), std::addressof(nro_bss_size), std::addressof(nro_aligned_header), std::addressof(nro_is_compress), nro_info->base_address, total_size, nro_size, bss_size)); /* Set NRO perms. */ - R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, rx_size, ro_size, rw_size + bss_size, aligned_header)); - + R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, nro_rx_size, nro_ro_size, nro_rw_size + nro_bss_size, nro_aligned_header)); + context->SetNroInfoInUse(nro_info, true); nro_info->nro_heap_address = nro_address; nro_info->nro_heap_size = nro_size; nro_info->bss_heap_address = bss_address; nro_info->bss_heap_size = bss_size; if (hos::GetVersion() >= hos::Version_23_0_0) { - nro_info->code_size = rx_size; - nro_info->ro_size = ro_size; + nro_info->code_size = nro_rx_size; + nro_info->ro_size = nro_ro_size; } else { - nro_info->code_size = rx_size + ro_size; + nro_info->code_size = nro_rx_size + nro_ro_size; nro_info->ro_size = 0; } - nro_info->rw_size = rw_size; - nro_info->is_compress = is_compress; + nro_info->rw_size = nro_rw_size; + nro_info->is_compress = nro_is_compress; *out_address = nro_info->base_address; R_SUCCEED(); } @@ -770,7 +774,11 @@ namespace ams::ro::impl { context->SetNroInfoInUse(nro_info, false); std::memset(nro_info, 0, sizeof(*nro_info)); } - R_RETURN(UnmapNro(context->GetProcessHandle(), nro_backup.base_address, nro_backup.nro_heap_address, nro_backup.code_size + nro_backup.rw_size, nro_backup.bss_heap_address, nro_backup.bss_heap_size)); + if (hos::GetVersion() >= hos::Version_23_0_0) { + R_RETURN(UnmapNro(context->GetProcessHandle(), nro_backup.base_address, nro_backup.nro_heap_address, nro_backup.nro_heap_size, nro_backup.bss_heap_address, nro_backup.bss_heap_size)); + } else { + R_RETURN(UnmapNro(context->GetProcessHandle(), nro_backup.base_address, nro_backup.nro_heap_address, nro_backup.code_size + nro_backup.rw_size, nro_backup.bss_heap_address, nro_backup.bss_heap_size)); + } } /* Debug service implementations. */ From 59e7786a4598c524bb04cbca41e3c06ed6dea61d Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 27 Sep 2026 01:35:29 +0100 Subject: [PATCH 47/52] web: introduce browser memory patching With 23.0.0 we have even less memory available which is causing the browser (openWeb) and eshop (systemWeb) applets to crash immediately. While the amount of memory required by the browser applets didn't change this time, just implementing 23.0.0 changes was enough to push it over the limit. Instead of reducing the memory available to us even further, this convoluted set of patches attempts to reclaim around 9 MB of unused browser memory. --- .../nintendo/nx/kern_k_system_control.cpp | 7 ++- .../source/ldr_embedded_web_patches.inc | 61 +++++++++++++++++++ stratosphere/loader/source/ldr_patcher.cpp | 13 ++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 stratosphere/loader/source/ldr_embedded_web_patches.inc diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index 20aa5eaa2..de463ce6b 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -357,7 +357,12 @@ namespace ams::kern::board::nintendo::nx { /* Return (possibly) adjusted size. */ /* NOTE: On 20.0.0+ (and even more-so 21.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. */ - if (kern::GetTargetFirmware() >= ams::TargetFirmware_21_0_0) { + /* NOTE: On 23.0.0+ we are patching memory allocation for each browser applet since there are only 3 of them now. */ + /* Given that the root "Reserved" region is 0x43E000 bytes and the "ReservedTbd" subregion is 0x540000 bytes, we can safely reclaim 9MB.*/ + if (kern::GetTargetFirmware() >= ams::TargetFirmware_23_0_0) { + constexpr size_t ExtraSystemMemoryForAtmosphere_23_0_0 = 16_MB; + return base_pool_size - ExtraSystemMemoryForAtmosphere_23_0_0 - KTraceBufferSize; + } else if (kern::GetTargetFirmware() >= ams::TargetFirmware_21_0_0) { constexpr size_t ExtraSystemMemoryForAtmosphere_21_0_0 = 7_MB; return base_pool_size - ExtraSystemMemoryForAtmosphere_21_0_0 - KTraceBufferSize; } else if (kern::GetTargetFirmware() >= ams::TargetFirmware_20_0_0) { diff --git a/stratosphere/loader/source/ldr_embedded_web_patches.inc b/stratosphere/loader/source/ldr_embedded_web_patches.inc new file mode 100644 index 000000000..825123005 --- /dev/null +++ b/stratosphere/loader/source/ldr_embedded_web_patches.inc @@ -0,0 +1,61 @@ +/* + * 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 . + */ + +/* Breakdown of each patch in order: */ +/* #1 - Patch the 0xDEEF000 size check branch to NOP. */ +/* #2 - Change the root heap "Reserved" region allocation size from 0x43E000 to 0. */ +/* #3 - Change the root heap "Scene" size from 0x4580000 to 0x4040000. */ +/* #4 - Change the scene heap "ReservedTbd" region allocation size from 0x540000 to 0. */ +/* #5 - Patch the linking of "ReservedTbd" to the parent heap with a NOP. */ +/* #6 - Patch the initial memory block allocation size from 0xB400000 to 0xAC00000. */ +/* #7 - Patch the initial memory block initialization size from 0xB400000 to 0xAC00000. */ +constexpr inline const EmbeddedPatchEntry SystemWebMemoryPatches_23_0_0[] = { + { 0x861DD4, "\x1F\x20\x03\xD5", 4 }, + { 0x861E80, "\x02\x00\x80\x52", 4 }, + { 0x861E6C, "\x82\x80\xA0\x52", 4 }, + { 0x8C1718, "\x02\x00\x80\x52", 4 }, + { 0x8C172C, "\x1F\x20\x03\xD5", 4 }, + { 0x861D44, "\x01\x58\xA1\x52", 4 }, + { 0x861D5C, "\x03\x58\xA1\x52", 4 }, +}; + +constexpr inline const EmbeddedPatchEntry OpenWebMemoryPatches_23_0_0[] = { + { 0x828DBC, "\x1F\x20\x03\xD5", 4 }, + { 0x828E68, "\x02\x00\x80\x52", 4 }, + { 0x828E54, "\x82\x80\xA0\x52", 4 }, + { 0x74C564, "\x02\x00\x80\x52", 4 }, + { 0x74C578, "\x1F\x20\x03\xD5", 4 }, + { 0x828D2C, "\x01\x58\xA1\x52", 4 }, + { 0x828D44, "\x03\x58\xA1\x52", 4 }, +}; + +constexpr inline const EmbeddedPatchEntry OfflineWebMemoryPatches_23_0_0[] = { + { 0x130698, "\x1F\x20\x03\xD5", 4 }, + { 0x130744, "\x02\x00\x80\x52", 4 }, + { 0x130730, "\x82\x80\xA0\x52", 4 }, + { 0x4D728, "\x02\x00\x80\x52", 4 }, + { 0x4D738, "\x1F\x20\x03\xD5", 4 }, + { 0x130614, "\x01\x58\xA1\x52", 4 }, + { 0x130624, "\x02\x58\xA1\x52", 4 }, +}; + +constexpr inline const EmbeddedPatch WebMemoryPatches[] = { + { ParseModuleId("97BF9C2D43EB002FB5B3578E7714F428104ED596"), util::size(SystemWebMemoryPatches_23_0_0), SystemWebMemoryPatches_23_0_0 }, /* 23.0.0 */ + + { ParseModuleId("1470453424A9CDE689BE6DA86457ED1C79F5F403"), util::size(OpenWebMemoryPatches_23_0_0), OpenWebMemoryPatches_23_0_0 }, /* 23.0.0 */ + + { ParseModuleId("86DAFFA68DA38660317018ADC7AD415BCCDDC583"), util::size(OfflineWebMemoryPatches_23_0_0), OfflineWebMemoryPatches_23_0_0 }, /* 23.0.0 */ +}; diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index c78b3919b..a6776b691 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -109,6 +109,7 @@ namespace ams::ldr { #include "ldr_embedded_usb_patches.inc" #include "ldr_embedded_am_patches.inc" + #include "ldr_embedded_web_patches.inc" } @@ -153,6 +154,18 @@ namespace ams::ldr { } } } + + /* TODO: Remove this if/when a cleaner solution is figured out. */ + for (const auto &patch : WebMemoryPatches) { + if (std::memcmp(std::addressof(patch.module_id), std::addressof(module_id), sizeof(module_id)) == 0) { + for (size_t i = 0; i < patch.num_entries; ++i) { + const auto &entry = patch.entries[i]; + if (entry.offset + entry.size <= mapped_size) { + std::memcpy(reinterpret_cast(mapped_nso + entry.offset), entry.data, entry.size); + } + } + } + } } } \ No newline at end of file From 7dd677158484008afe50dcecfd7a190d2e8b3397 Mon Sep 17 00:00:00 2001 From: borntohonk <6264306+borntohonk@users.noreply.github.com> Date: Sun, 27 Sep 2026 11:30:35 +0200 Subject: [PATCH 48/52] ncm: add OpenWeb and SystemWeb applet ids --- .../ncm/ncm_system_content_meta_id.hpp | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_system_content_meta_id.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_system_content_meta_id.hpp index f6cfc77a0..930d44e00 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_system_content_meta_id.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_system_content_meta_id.hpp @@ -398,6 +398,9 @@ namespace ams::ncm { static const SystemAppletId Story; + static const SystemAppletId SystemWeb; + static const SystemAppletId OpenWeb; + static const SystemAppletId End; }; @@ -433,6 +436,9 @@ namespace ams::ncm { inline constexpr const SystemAppletId SystemAppletId::Story = { 0x0100000000001020ul }; + inline constexpr const SystemAppletId SystemAppletId::SystemWeb = { 0x0100000000001042ul }; + inline constexpr const SystemAppletId SystemAppletId::OpenWeb = { 0x0100000000001043ul }; + inline constexpr const SystemAppletId SystemAppletId::End = { 0x0100000000001FFFul }; inline constexpr bool IsSystemAppletId(const ProgramId &program_id) { @@ -500,6 +506,8 @@ namespace ams::ncm { static const LibraryAppletId LoginShare; static const LibraryAppletId WifiWebAuth; static const LibraryAppletId MyPage; + static const LibraryAppletId SystemWeb; + static const LibraryAppletId OpenWeb; }; @@ -515,6 +523,8 @@ namespace ams::ncm { inline constexpr const LibraryAppletId LibraryAppletId::LoginShare = { SystemAppletId::LoginShare.value }; inline constexpr const LibraryAppletId LibraryAppletId::WifiWebAuth = { SystemAppletId::WifiWebAuth.value }; inline constexpr const LibraryAppletId LibraryAppletId::MyPage = { SystemAppletId::MyPage.value }; + inline constexpr const LibraryAppletId LibraryAppletId::SystemWeb = { SystemAppletId::SystemWeb.value }; + inline constexpr const LibraryAppletId LibraryAppletId::OpenWeb = { SystemAppletId::OpenWeb.value }; inline constexpr bool IsLibraryAppletId(const ProgramId &id) { return id == LibraryAppletId::Auth || @@ -528,7 +538,9 @@ namespace ams::ncm { id == LibraryAppletId::OfflineWeb || id == LibraryAppletId::LoginShare || id == LibraryAppletId::WifiWebAuth || - id == LibraryAppletId::MyPage; + id == LibraryAppletId::MyPage || + id == LibraryAppletId::SystemWeb || + id == LibraryAppletId::OpenWeb; } inline constexpr bool IsLibraryAppletId(const LibraryAppletId &) { @@ -558,6 +570,8 @@ namespace ams::ncm { static const WebAppletId OfflineWeb; static const WebAppletId LoginShare; static const WebAppletId WifiWebAuth; + static const WebAppletId SystemWeb; + static const WebAppletId OpenWeb; }; inline constexpr const WebAppletId WebAppletId::Web = { LibraryAppletId::Web.value }; @@ -565,13 +579,17 @@ namespace ams::ncm { inline constexpr const WebAppletId WebAppletId::OfflineWeb = { LibraryAppletId::OfflineWeb.value }; inline constexpr const WebAppletId WebAppletId::LoginShare = { LibraryAppletId::LoginShare.value }; inline constexpr const WebAppletId WebAppletId::WifiWebAuth = { LibraryAppletId::WifiWebAuth.value }; + inline constexpr const WebAppletId WebAppletId::SystemWeb = { LibraryAppletId::SystemWeb.value }; + inline constexpr const WebAppletId WebAppletId::OpenWeb = { LibraryAppletId::OpenWeb.value }; inline constexpr bool IsWebAppletId(const ProgramId &id) { return id == WebAppletId::Web || id == WebAppletId::Shop || id == WebAppletId::OfflineWeb || id == WebAppletId::LoginShare || - id == WebAppletId::WifiWebAuth; + id == WebAppletId::WifiWebAuth || + id == WebAppletId::SystemWeb || + id == WebAppletId::OpenWeb; } inline constexpr bool IsWebAppletId(const WebAppletId &) { From a1a98862900cd02bf37dc7b27630220369ca63ad Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 27 Sep 2026 22:09:31 +0100 Subject: [PATCH 49/52] ro/util: last round of fixes, now fully matches official behavior --- .../source/util/util_compression_lz4.cpp | 88 ++++++++++--------- .../ro/source/impl/ro_service_impl.cpp | 8 +- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/libraries/libstratosphere/source/util/util_compression_lz4.cpp b/libraries/libstratosphere/source/util/util_compression_lz4.cpp index 46950e180..97f3f6034 100644 --- a/libraries/libstratosphere/source/util/util_compression_lz4.cpp +++ b/libraries/libstratosphere/source/util/util_compression_lz4.cpp @@ -45,19 +45,24 @@ namespace ams::util { /* Destination buffer must be behind source buffer. */ if (dst_buffer > src_buffer) { - std::memset(dst, 0, dst_size); + std::memset(dst_buffer, 0, dst_size); return -1; } + const u8 *src_buffer_start = src_buffer; + const u8 *src_buffer_end = src_buffer + src_size; + const u8 *dst_buffer_start = dst_buffer; + const u8 *dst_buffer_end = dst_buffer + dst_size; + /* Size checks. */ - if (((src_buffer + src_size) != (dst_buffer + dst_size)) || (src_work_size != 0x10000) || (dst_work_size != 0x10000)) { - std::memset(dst, 0, dst_size); + if ((src_buffer_end != dst_buffer_end) || (src_work_size != 0x10000) || (dst_work_size != 0x10000)) { + std::memset(dst_buffer, 0, dst_size); return -1; } /* Source size must at least include one frame header. */ if (src_size < 7) { - std::memset(dst, 0, dst_size); + std::memset(dst_buffer, 0, dst_size); return -2; } @@ -68,34 +73,34 @@ namespace ams::util { /* Check for LZ4F_MAGICNUMBER, validate flags and block size. */ if ((magic != 0x184D2204) || ((flg & 1) != 0) || (flg != 0x60) || (bd != 0x40)) { - std::memset(dst, 0, dst_size); + std::memset(dst_buffer, 0, dst_size); return -2; } /* TODO: Implement header checksum validation. This requires xxhash, do we want to have xxhash in util? */ AMS_UNUSED(header_checksum); - u32 src_pos = 7; /* Skip the header. */ - u32 dst_pos = 0; + /* Skip the frame header. */ + src_buffer += 7; - /* Destination size is too small. */ - if (dst_size < src_pos) { - std::memset(dst, 0, dst_size); + /* Destination is too small. */ + if (src_buffer >= dst_buffer_end) { + std::memset(dst_buffer, 0, dst_size); return -2; } while (true) { /* Not enough space left. */ - if ((dst_size - src_pos) < 4) { - std::memset(dst, 0, dst_size); + if ((dst_buffer_end - src_buffer) < 4) { + std::memset(dst_buffer, 0, dst_size); return -4; } - src_buffer += src_pos; - dst_buffer += dst_pos; - const u32 block_header = *reinterpret_cast(src_buffer); + /* Advance the block. */ + src_buffer += sizeof(block_header); + /* We've reached the end. */ if (!block_header) { break; @@ -105,16 +110,13 @@ namespace ams::util { /* Block size is invalid. */ if (block_size > 0x10000) { - std::memset(dst, 0, dst_size); + std::memset(dst_buffer, 0, dst_size); return -3; } - /* Advance the data block. */ - src_buffer += sizeof(block_header); - /* Block size is invalid. */ - if (((dst_buffer + dst_size) - src_buffer) < block_size) { - std::memset(dst, 0, dst_size); + if ((dst_buffer_end - src_buffer) < block_size) { + std::memset(dst_buffer, 0, dst_size); return -4; } @@ -123,65 +125,67 @@ namespace ams::util { if ((block_header & 0x80000000) != 0) { /* Block size is invalid. */ - if (dst_size < block_size) { - std::memset(dst, 0, dst_size); + if ((dst_buffer_end - dst_buffer) < block_size) { + std::memset(dst_buffer, 0, dst_size); return -4; } - dst_pos += block_size; - src_pos += block_size; - /* Destination is overrunning source. */ - if (dst_pos > src_pos) { - std::memset(dst, 0, dst_size); + if ((dst_buffer + block_size) > (src_buffer + block_size)) { + std::memset(dst_buffer, 0, dst_size); return -5; } /* This is a raw block, copy it. */ - std::memmove(dst_buffer, src_buffer, block_size); + std::memmove(dst_buffer, src_buffer, block_size); + + /* Advance buffers. */ + dst_buffer += block_size; + src_buffer += block_size; } else { /* This is a compressed block, decompress it. */ int decompressed_size = LZ4_decompress_safe(reinterpret_cast(src_work), reinterpret_cast(dst_work), static_cast(block_size), 0x10000); /* Decompressed size is invalid. */ if (decompressed_size < 1) { - std::memset(dst, 0, dst_size); + std::memset(dst_buffer, 0, dst_size); return -3; } /* Decompressed size is invalid. */ - if (dst_size < static_cast(decompressed_size)) { - std::memset(dst, 0, dst_size); + if (static_cast(dst_buffer_end - dst_buffer) < static_cast(decompressed_size)) { + std::memset(dst_buffer, 0, dst_size); return -4; } - dst_pos += decompressed_size; - src_pos += block_size; - /* Destination is overrunning source. */ - if (dst_pos > src_pos) { - std::memset(dst, 0, dst_size); + if ((dst_buffer + decompressed_size) > (src_buffer + block_size)) { + std::memset(dst_buffer, 0, dst_size); return -5; } /* Copy the decompressed data back. */ std::memcpy(dst_buffer, static_cast(dst_work), decompressed_size); + + /* Advance buffers. */ + dst_buffer += decompressed_size; + src_buffer += block_size; } /* We've exceeded the destination's size. */ - if (src_pos >= dst_size) { - std::memset(dst, 0, dst_size); + if (src_buffer >= dst_buffer_end) { + std::memset(dst_buffer, 0, dst_size); return -2; } } /* We didn't consume all data. */ - if (src_pos != src_size) { - std::memset(dst, 0, dst_size); + if (static_cast(src_buffer - src_buffer_start) != src_size) { + std::memset(dst_buffer, 0, dst_size); return -2; } - *out_size = dst_pos; + *out_size = dst_buffer - dst_buffer_start; return 0; } } \ No newline at end of file diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp index ef1a6afb1..e8c0b45c7 100644 --- a/stratosphere/ro/source/impl/ro_service_impl.cpp +++ b/stratosphere/ro/source/impl/ro_service_impl.cpp @@ -449,6 +449,7 @@ namespace ams::ro::impl { /* CheckAdditionalHeaderHash */ if (nro_header->GetAdditionalHeaderOffset() != 0) { R_TRY(this->CheckAdditionalHeaderHash(static_cast(mapped_memory), std::addressof(additional_nro_header_hash), sizeof(additional_nro_header_hash), nro_header->GetRwOffset(), nro_header->GetRwSize())); + ON_RESULT_FAILURE { std::memset(static_cast(mapped_memory) + 0x1000, 0, total_size - 0x1000); }; } } @@ -707,16 +708,17 @@ namespace ams::ro::impl { /* Map the NRO. */ R_TRY(MapNro(std::addressof(nro_info->base_address), context->GetProcessHandle(), nro_address, nro_size, bss_address, bss_size)); - ON_RESULT_FAILURE { R_DISCARD(UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size)); }; - + /* Parse the NRO. */ u64 nro_rx_size = 0, nro_ro_size = 0, nro_rw_size = 0, nro_bss_size = 0; bool nro_aligned_header = false; bool nro_is_compress = false; R_TRY(context->ParseNro(std::addressof(nro_info->module_id), std::addressof(nro_rx_size), std::addressof(nro_ro_size), std::addressof(nro_rw_size), std::addressof(nro_bss_size), std::addressof(nro_aligned_header), std::addressof(nro_is_compress), nro_info->base_address, total_size, nro_size, bss_size)); - + ON_RESULT_FAILURE { R_DISCARD(UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size)); }; + /* Set NRO perms. */ R_TRY(SetNroPerms(context->GetProcessHandle(), nro_info->base_address, nro_rx_size, nro_ro_size, nro_rw_size + nro_bss_size, nro_aligned_header)); + ON_RESULT_FAILURE_2 { if (!nro_is_compress) { R_DISCARD(UnmapNro(context->GetProcessHandle(), nro_info->base_address, nro_address, nro_size, bss_address, bss_size)); } }; context->SetNroInfoInUse(nro_info, true); nro_info->nro_heap_address = nro_address; From 7442487ace6b79ddddf2cd0007b8dade8150bf5c Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 27 Sep 2026 23:10:27 +0100 Subject: [PATCH 50/52] docs: add changelog for 1.12.0 --- docs/changelog.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index c1b43d17b..a5aa53a87 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,36 @@ # Changelog +## 1.12.0 ++ Support was added for 23.0.0. ++ Special thanks to @alula for handling the implementation of several kernel changes. + + The console should boot and atmosphère should be fully functional. + + **Please note**: As a result of changes made to nintendo's software in 23.0.0, there is even less memory available for custom system modules. + + The amount of memory we can steal from the applet pool has been reduced beyond 7MB and we can no longer launch browser applets (e.g.: eshop) without crashing. + + To compensate for this, a set of patches for the browser applets has been introduced. + + Thanks to the redesign of the browser applets in 22.0.0 there are only 3 applets we need to worry about: systemWeb, openWeb and LibAppletOff. + + With the added burden of maintaining patches for these applets, we can reclaim around 9MB of reserved memory by patching out their allocations. + + This memory is provably unused and stealing it should not affect the browser applets in any way as the applets themselves tag it as reserved and never access it. + + As a result, the memory available for custom system modules has been experimentally increased to 16MB. + + Preliminary testing has seemingly shown no downsides to the overall functioning of the OS and the browser applets in particular. + + Nonetheless, please report any issues you may face to ensure no edge cases have been missed and to determine if the memory amount needs to be adjusted. + + These patches may be deprecated at any point in the future if a better solution is devised. + + `exosphère` was updated to reflect the latest official secure monitor behavior. + + A new ConfigItem was added to the secure monitor for the first time since firmware 5.0.0. + + `mesosphère` was updated to reflect the latest official kernel behavior. + + The kernel now supports a 42bit wide address space. + + A new memory region dubbed ShadowStack has been introduced. + + Kernel RNG was changed to CTR-DRBG. + + `boot` was updated to reflect the latest official behavior and to implement a previously missing change. + + The way battery i2c shutdown was being enabled changed in firmware 18.0.0 and we missed it. + + It is possible this might have been related to a known battery draining issue reported to have started around firmware 18.0.0. Further testing will be needed to confirm. + + `loader` was updated to reflect the latest official behavior. + + `erpt` was updated to reflect the latest official behavior. + + `pgl` was updated to reflect the latest official behavior. + + `ro` was updated to reflect the latest official behavior. + + NROs can now be lz4 frame compressed. ++ ZBIC compresison/decompression has been properly implemented. Applications using it should now launch and work properly. ++ A dockerfile has been added to atmosphère (thanks @alula). ++ R_DISCARD macro has been adopted across the entire codebase where applicable. This finishes the work started in version 1.10.0 and eliminates the nodiscard warnings during compilation. ++ General system stability improvements to enhance the user's experience. ## 1.11.2 + Basic support was added for 22.5.0. + Atmosphère was updated to use GCC 16/newlib (latest devkitA64/devkitARM releases). From c68e08a101353a89777eb118d6bd21d1dba98ce5 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 27 Sep 2026 23:12:36 +0100 Subject: [PATCH 51/52] git subrepo push emummc subrepo: subdir: "emummc" merged: "5b966b6f3" upstream: origin: "https://github.com/m4xw/emummc" branch: "develop" commit: "5b966b6f3" git-subrepo: version: "0.4.9" origin: "???" commit: "???" --- emummc/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/emummc/.gitrepo b/emummc/.gitrepo index 503f95eb1..eea652603 100644 --- a/emummc/.gitrepo +++ b/emummc/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/m4xw/emummc branch = develop - commit = f6b3a28ecea9834f96151a526de66abd11033b70 - parent = 1478f3443e8f04534edac8c15bf2d504663d0384 + commit = 5b966b6f3f83349ec65066a1877f7f948b48d08c + parent = 7442487ace6b79ddddf2cd0007b8dade8150bf5c method = merge cmdver = 0.4.9 From 28d6a2e11f2640077bbb8a9fbd463d3fa12b6984 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 27 Sep 2026 23:13:40 +0100 Subject: [PATCH 52/52] git subrepo push libraries subrepo: subdir: "libraries" merged: "aae2da015" upstream: origin: "https://github.com/Atmosphere-NX/Atmosphere-libs" branch: "master" commit: "aae2da015" git-subrepo: version: "0.4.9" origin: "???" commit: "???" --- libraries/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/.gitrepo b/libraries/.gitrepo index 5efbca955..56e7c065d 100644 --- a/libraries/.gitrepo +++ b/libraries/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/Atmosphere-NX/Atmosphere-libs branch = master - commit = edb2cca26f658ef7863eb4c349399d273aab4fae - parent = f7d46d38fafa114d7c784dbdc24d9382a0a0ba32 + commit = aae2da0155a490abd3bfd17a70ccd16bb73c916a + parent = c68e08a101353a89777eb118d6bd21d1dba98ce5 method = merge cmdver = 0.4.9