Merge upstream Atmosphere-NX/Atmosphere master
This commit is contained in:
80
Dockerfile
Normal file
80
Dockerfile
Normal file
@@ -0,0 +1,80 @@
|
||||
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=146c3d1446d35546943c7b6cfcd479bc1f5e9b67
|
||||
# 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) && \
|
||||
# cd nx && \
|
||||
# make 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"]
|
||||
@@ -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).
|
||||
|
||||
4
emummc/.gitrepo
vendored
4
emummc/.gitrepo
vendored
@@ -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
|
||||
|
||||
2
emummc/README.md
vendored
2
emummc/README.md
vendored
@@ -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
|
||||
|
||||
8
emummc/source/FS/FS_offsets.c
vendored
8
emummc/source/FS/FS_offsets.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
3
emummc/source/FS/FS_versions.h
vendored
3
emummc/source/FS/FS_versions.h
vendored
@@ -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,
|
||||
};
|
||||
|
||||
59
emummc/source/FS/offsets/2300.h
vendored
Normal file
59
emummc/source/FS/offsets/2300.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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__
|
||||
59
emummc/source/FS/offsets/2300_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2300_exfat.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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__
|
||||
@@ -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. */
|
||||
.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. */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace ams::secmon::smc {
|
||||
RegulatorType = 15,
|
||||
DeviceUniqueKeyGeneration = 16,
|
||||
Package2Hash = 17,
|
||||
Unknown18 = 18,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
|
||||
@@ -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] = {};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -308,6 +311,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 +739,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;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = d3083af1827cd6ca2a96feb9316eb85cd01bae1f
|
||||
parent = 974a1025b834136134e8133d8db23f69cb5ae0be
|
||||
commit = aae2da0155a490abd3bfd17a70ccd16bb73c916a
|
||||
parent = c68e08a101353a89777eb118d6bd21d1dba98ce5
|
||||
method = merge
|
||||
cmdver = 0.4.9
|
||||
|
||||
@@ -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<BootConfigData>::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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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'>;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <mesosphere/kern_k_page_table_base.hpp>
|
||||
#include <mesosphere/kern_k_page_group.hpp>
|
||||
#include <mesosphere/kern_k_page_table_manager.hpp>
|
||||
#include <mesosphere/init/kern_init_slab_setup.hpp>
|
||||
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
@@ -94,10 +95,10 @@ namespace ams::kern::arch::arm64 {
|
||||
return KPageTable::GetBlockSize(static_cast<KPageTable::BlockType>(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 +189,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);
|
||||
@@ -198,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) {
|
||||
|
||||
@@ -28,10 +28,15 @@ 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));
|
||||
}
|
||||
|
||||
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,19 +307,25 @@ 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(); }
|
||||
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); }
|
||||
|
||||
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(); }
|
||||
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 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(); }
|
||||
|
||||
|
||||
@@ -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<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion39Size) {
|
||||
if (const uintptr_t src_uptr = reinterpret_cast<uintptr_t>(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion42Size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -18,6 +18,25 @@
|
||||
#include <mesosphere/kern_k_slab_heap.hpp>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -211,15 +214,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 +368,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:
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -150,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<ams::svc::CreateProcessFlag>(as_type & ams::svc::CreateProcessFlag_AddressSpaceMask)) {
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
|
||||
static constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessParameterFlag as_type) {
|
||||
switch (static_cast<ams::svc::CreateProcessParameterFlag>(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();
|
||||
}
|
||||
@@ -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<KProcessAddress>), m_address_space_end(Null<KProcessAddress>),
|
||||
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_starts{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_region_ends{Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>, Null<KProcessAddress>},
|
||||
m_current_heap_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>),
|
||||
m_alias_code_region_end(Null<KProcessAddress>), m_code_region_start(Null<KProcessAddress>), m_code_region_end(Null<KProcessAddress>),
|
||||
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::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();
|
||||
|
||||
@@ -247,6 +248,22 @@ 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 {
|
||||
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 {
|
||||
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 +507,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; }
|
||||
|
||||
|
||||
@@ -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<s64> m_cpu_time;
|
||||
util::Atomic<s64> m_num_process_switches;
|
||||
util::Atomic<s64> 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<const u32 *> 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,19 +156,22 @@ 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; }
|
||||
|
||||
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; }
|
||||
|
||||
@@ -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;
|
||||
@@ -215,6 +219,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; }
|
||||
@@ -409,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. */
|
||||
|
||||
@@ -37,13 +37,12 @@ namespace ams::kern {
|
||||
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;
|
||||
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 +65,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 +77,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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
@@ -341,18 +344,19 @@ 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<KThread, KWorkerTask>(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<KProcessAddress>}, m_parent{},
|
||||
m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, 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<KProcessAddress>}, m_tls_heap_address{}, m_shadow_stack_address{Null<KProcessAddress>}, 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{},
|
||||
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{}
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -683,6 +687,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? */
|
||||
|
||||
@@ -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
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
@@ -379,7 +381,7 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
/* Exit the current process. */
|
||||
cur_process.Exit();
|
||||
cur_process.Exit(-1ll);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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:
|
||||
{
|
||||
@@ -545,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. */
|
||||
@@ -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;
|
||||
|
||||
@@ -125,10 +125,10 @@ 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) {
|
||||
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));
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
@@ -363,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) {
|
||||
@@ -417,7 +416,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;
|
||||
@@ -477,9 +479,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 +526,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() {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -30,30 +30,36 @@ 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) {
|
||||
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::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) {
|
||||
@@ -66,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);
|
||||
@@ -82,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:
|
||||
|
||||
@@ -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;
|
||||
@@ -417,7 +417,7 @@ namespace ams::kern {
|
||||
|
||||
/* Terminate the process. */
|
||||
/* NOTE: This result is seemingly-intentionally not checked by Nintendo. */
|
||||
static_cast<void>(target->Terminate());
|
||||
static_cast<void>(target->Terminate(-1ll));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -214,28 +214,28 @@ 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 */
|
||||
/* 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 uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_type, out->code_num_pages);
|
||||
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(out->flags), as_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<ams::svc::CreateProcessParameterFlag>(out->flags), as_type, out->code_num_pages);
|
||||
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(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));
|
||||
|
||||
@@ -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::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);
|
||||
@@ -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;
|
||||
|
||||
@@ -179,10 +179,10 @@ 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<size_t>(1) << m_address_space_width) / 8;
|
||||
m_alias_region_extra_size = (static_cast<size_t>(1) << address_space_width) / 8;
|
||||
|
||||
alias_region_size += m_alias_region_extra_size;
|
||||
}
|
||||
@@ -208,9 +208,12 @@ namespace ams::kern {
|
||||
after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge);
|
||||
}
|
||||
|
||||
m_region_starts[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
m_region_ends[RegionType_ShadowStack] = Null<KProcessAddress>;
|
||||
|
||||
/* 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;
|
||||
@@ -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::CreateProcessParameterFlag_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) {
|
||||
@@ -347,151 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < m_region_starts[j + 1] || m_region_ends[j + 1] - 1 < m_region_starts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -561,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:
|
||||
@@ -596,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:
|
||||
@@ -622,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:
|
||||
@@ -645,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1997,15 +1915,15 @@ namespace ams::kern {
|
||||
.m_address = GetInteger(m_address_space_end),
|
||||
.m_size = 0 - GetInteger(m_address_space_end),
|
||||
.m_state = static_cast<KMemoryState>(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;
|
||||
|
||||
@@ -3287,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. */
|
||||
{
|
||||
@@ -3436,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. */
|
||||
{
|
||||
|
||||
@@ -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<ams::svc::CreateProcessFlag>(m_flags), KAddressSpaceInfo::Type_Heap);
|
||||
m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(m_flags), KAddressSpaceInfo::Type_Heap);
|
||||
|
||||
/* Generate random entropy. */
|
||||
KSystemControl::GenerateRandom(m_entropy, util::size(m_entropy));
|
||||
@@ -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::CreateProcessParameterFlag_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. */
|
||||
@@ -279,7 +284,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 +298,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<ams::svc::CreateProcessFlag>(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<ams::svc::CreateProcessParameterFlag>(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(); };
|
||||
|
||||
@@ -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::CreateProcessParameterFlag_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;
|
||||
@@ -358,7 +368,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 +382,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<ams::svc::CreateProcessFlag>(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<ams::svc::CreateProcessParameterFlag>(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 +402,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));
|
||||
}
|
||||
|
||||
@@ -455,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. */
|
||||
@@ -470,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;
|
||||
}
|
||||
}
|
||||
@@ -490,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 */
|
||||
@@ -506,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;
|
||||
}
|
||||
}
|
||||
@@ -773,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<void>(this->Terminate());
|
||||
static_cast<void>(this->Terminate(-1ll));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +982,9 @@ namespace ams::kern {
|
||||
/* Initialize the thread. */
|
||||
R_TRY(KThread::InitializeUserThread(main_thread, reinterpret_cast<KThreadFunction>(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();
|
||||
@@ -1189,7 +1204,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
@@ -44,16 +46,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() {
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mesosphere.hpp>
|
||||
#include <vapours/crypto/crypto_aes_encryptor.hpp>
|
||||
#include <vapours/crypto/impl/crypto_ctr_drbg.hpp>
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
#include <mesosphere/arch/arm64/kern_secure_monitor_base.hpp>
|
||||
#endif
|
||||
@@ -27,6 +29,41 @@ 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();
|
||||
}
|
||||
};
|
||||
|
||||
using RandomGenerator = ::ams::crypto::impl::CtrDrbg<::ams::crypto::AesEncryptor128, 16, false>;
|
||||
|
||||
constexpr size_t RandomGeneratorOutputSize = 8 * RandomGenerator::OutSize;
|
||||
constexpr u32 RandomGeneratorOutputCount = RandomGeneratorOutputSize / sizeof(u32);
|
||||
|
||||
constinit util::TypedStorage<RandomGenerator> 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;
|
||||
|
||||
void GenerateRandomSeed(void *dst, size_t size) {
|
||||
KSystemControl::GenerateRandomBytesForUninitialized(dst, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialization. */
|
||||
size_t KSystemControlBase::Init::GetRealMemorySize() {
|
||||
return ams::kern::MainMemorySize;
|
||||
@@ -102,25 +139,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<const u32*>(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<const u32*>(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 +160,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<const u32*>(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();
|
||||
@@ -170,6 +197,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));
|
||||
@@ -206,13 +240,77 @@ 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 == RandomGenerator::SeedSize);
|
||||
|
||||
KScopedFpuEnable fp_enabled;
|
||||
|
||||
/* 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);
|
||||
|
||||
s_random_remaining = 0;
|
||||
}
|
||||
|
||||
void KSystemControlBase::ReseedRandomGeneratorInternal() {
|
||||
KScopedFpuEnable fp_enabled;
|
||||
|
||||
/* Pull fresh entropy, then derive a new state from it. */
|
||||
u8 seed[RandomGenerator::SeedSize];
|
||||
GenerateRandomSeed(seed, sizeof(seed));
|
||||
util::GetReference(s_random_generator).Reseed(seed, sizeof(seed), nullptr, 0);
|
||||
|
||||
s_random_remaining = 0;
|
||||
}
|
||||
|
||||
u32 KSystemControlBase::GenerateRandomU32() {
|
||||
if (s_random_remaining == 0) {
|
||||
KScopedFpuEnable fp_enabled;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
s_random_remaining = RandomGeneratorOutputCount;
|
||||
}
|
||||
|
||||
/* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */
|
||||
const size_t index = RandomGeneratorOutputCount - s_random_remaining;
|
||||
u32 value;
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,14 +318,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<u64>::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<u8 *>(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() {
|
||||
|
||||
@@ -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<KProcessAddress>;
|
||||
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->GetCreateProcessParameterFlags() & ams::svc::CreateProcessParameterFlag_EnableShadowStack) {
|
||||
/* Allocate the backing page. */
|
||||
KPageBuffer *page = KPageBuffer::AllocateChecked<PageSize>();
|
||||
if (page == nullptr) {
|
||||
owner->DeleteThreadLocalRegion(m_tls_address);
|
||||
m_tls_address = Null<KProcessAddress>;
|
||||
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<KProcessAddress>;
|
||||
};
|
||||
|
||||
/* 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<KProcessAddress>) {
|
||||
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<KProcessAddress>) {
|
||||
m_parent->DeleteThreadLocalRegion(m_tls_address);
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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<void *>(address), size));
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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<KDebug>(debug_handle);
|
||||
R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle());
|
||||
@@ -142,6 +144,7 @@ namespace ams::kern::svc {
|
||||
/* 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));
|
||||
}
|
||||
|
||||
@@ -172,6 +175,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 +198,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 +250,8 @@ namespace ams::kern::svc {
|
||||
|
||||
template<typename T>
|
||||
Result QueryDebugProcessMemory(KUserPointer<T *> 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));
|
||||
@@ -429,6 +438,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());
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace ams::kern::svc {
|
||||
}
|
||||
|
||||
/* Exit the current process. */
|
||||
GetCurrentProcess().Exit();
|
||||
GetCurrentProcess().Exit(-1ll);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -21,11 +21,22 @@ namespace ams::kern::svc {
|
||||
|
||||
namespace {
|
||||
|
||||
static Result GetPortName(char (&name)[KObjectName::NameLengthMax], KUserPointer<const char *> 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<const char *> 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<const char *> 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());
|
||||
|
||||
@@ -25,8 +25,9 @@ namespace ams::kern::svc {
|
||||
return (0 <= core_id && core_id < static_cast<int32_t>(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");
|
||||
}
|
||||
|
||||
@@ -79,13 +80,47 @@ 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. */
|
||||
R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count));
|
||||
}
|
||||
|
||||
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::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);
|
||||
|
||||
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<const uint32_t *> user_caps, int32_t num_caps) {
|
||||
/* Validate the capabilities pointer. */
|
||||
R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer());
|
||||
@@ -94,14 +129,17 @@ namespace ams::kern::svc {
|
||||
R_UNLESS(((num_caps * sizeof(u32)) / sizeof(u32)) == static_cast<size_t>(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. */
|
||||
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::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());
|
||||
}
|
||||
@@ -110,34 +148,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<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(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<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapSmall);
|
||||
map_end = map_start + map_size;
|
||||
}
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
|
||||
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<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit, code_size);
|
||||
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Map39Bit);
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size);
|
||||
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_MapHuge);
|
||||
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessFlag>(params.flags), KAddressSpaceInfo::Type_Heap);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast<ams::svc::CreateProcessParameterFlag>(params.flags), KAddressSpaceInfo::Type_Heap);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -146,11 +185,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());
|
||||
@@ -166,10 +205,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());
|
||||
@@ -205,8 +244,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. */
|
||||
@@ -215,8 +254,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<ams::svc::CreateProcessParameterFlag>(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. */
|
||||
@@ -232,19 +271,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<KMemoryManager::Pool>(KSystemControl::GetCreateProcessMemoryPool());
|
||||
@@ -319,7 +358,7 @@ namespace ams::kern::svc {
|
||||
R_RETURN(process->Run(priority, static_cast<size_t>(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<KProcess>(process_handle).ReleasePointerUnsafe();
|
||||
R_UNLESS(process != nullptr, svc::ResultInvalidHandle());
|
||||
@@ -329,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();
|
||||
@@ -373,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());
|
||||
}
|
||||
@@ -385,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) {
|
||||
@@ -405,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) {
|
||||
@@ -415,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) {
|
||||
@@ -435,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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace ams::kern::svc {
|
||||
|
||||
template<typename T>
|
||||
Result QueryProcessMemory(KUserPointer<T *> 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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -204,6 +204,8 @@ namespace ams::kern::svc {
|
||||
/* Get the thread from its handle. */
|
||||
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(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. */
|
||||
|
||||
@@ -31,10 +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_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
|
||||
};
|
||||
|
||||
|
||||
@@ -195,6 +195,8 @@
|
||||
HANDLER(PscTransitionStateInfo, 154 ) \
|
||||
HANDLER(FsProxyErrorInfo3, 155 ) \
|
||||
HANDLER(BluetoothErrorInfo, 156 ) \
|
||||
HANDLER(SystemConfigInfo, 157 ) \
|
||||
HANDLER(ClockContextInfo, 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, 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 ) \
|
||||
@@ -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, 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 ) \
|
||||
@@ -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, SystemConfigInfo, 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, 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, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
|
||||
HANDLER(NotificationSoundFlag, 80, NotificationInfo, 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, SleepInfo, FieldType_String, FieldFlag_None ) \
|
||||
HANDLER(ConsoleModeTimeToScreenSleep, 86, SleepInfo, FieldType_String, FieldFlag_None ) \
|
||||
HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SleepInfo, 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 ) \
|
||||
@@ -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, 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 ) \
|
||||
@@ -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, 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 ) \
|
||||
@@ -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, 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 ) \
|
||||
@@ -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 ) \
|
||||
|
||||
@@ -272,5 +272,14 @@ namespace ams::erpt {
|
||||
char product_model[16];
|
||||
const char *region;
|
||||
};
|
||||
|
||||
struct SubmitAttachmentOptionFlag {
|
||||
using Lz4Compression = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>::Flag<0>;
|
||||
using Unknown0x10000 = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>::Flag<16>; /* TODO: Figure out what this is. Always forced to 1. */
|
||||
};
|
||||
|
||||
using SubmitAttachmentOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), SubmitAttachmentOptionFlag>;
|
||||
static_assert(util::is_pod<SubmitAttachmentOptionFlagSet>::value);
|
||||
static_assert(sizeof(SubmitAttachmentOptionFlagSet) == sizeof(u32));
|
||||
|
||||
}
|
||||
|
||||
@@ -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<erpt::AttachmentId> 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<erpt::AttachmentId> 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<erpt::AttachmentId> 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<erpt::AttachmentId> 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<erpt::AttachmentId> 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) \
|
||||
|
||||
@@ -21,17 +21,17 @@
|
||||
#include <stratosphere/gpio/gpio_select_pad_name.hpp>
|
||||
#include <stratosphere/gpio/sf/gpio_sf_i_pad_session.hpp>
|
||||
|
||||
#define AMS_GPIO_I_MANAGER_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, s32 pad_descriptor), (out, pad_descriptor) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSession, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTest, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActive, (ams::sf::Out<bool> 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<gpio::WakeBitFlag> 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<ams::sf::SharedPointer<gpio::sf::IPadSession>> 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<bool> 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<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, s32 pad_descriptor), (out, pad_descriptor)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenSessionDeprecated, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenSessionForTestDeprecated, (ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, gpio::GpioPadName pad_name), (out, pad_name)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, IsWakeEventActiveDeprecated, (ams::sf::Out<bool> 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<gpio::WakeBitFlag> 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<ams::sf::SharedPointer<gpio::sf::IPadSession>> 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<bool> 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)
|
||||
|
||||
@@ -18,24 +18,28 @@
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/gpio/gpio_types.hpp>
|
||||
|
||||
#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<gpio::Direction> 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<gpio::InterruptMode> 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<bool> out), (out) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> 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<gpio::GpioValue> 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<bool> 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<s32> 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<gpio::GpioValue> 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<gpio::Direction> 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<gpio::InterruptMode> 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<bool> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, GetInterruptStatus, (ams::sf::Out<gpio::InterruptStatus> 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<gpio::GpioValue> 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<bool> 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<s32> 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<gpio::GpioValue> 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<bool> out), (out), hos::Version_23_0_0)
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::gpio::sf, IPadSession, AMS_GPIO_I_PAD_SESSION_INTERFACE_INFO, 0x7448A8A7)
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
#include <stratosphere/i2c/i2c_select_device_name.hpp>
|
||||
#include <stratosphere/i2c/sf/i2c_sf_i_session.hpp>
|
||||
|
||||
#define AMS_I2C_I_MANAGER_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenSessionForDev, (ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> 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<ams::sf::SharedPointer<i2c::sf::ISession>> out, i2c::I2cDevice device), (out, device) ) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out<bool> 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<bool> 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<ams::sf::SharedPointer<i2c::sf::ISession>> 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<ams::sf::SharedPointer<i2c::sf::ISession>> 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<ams::sf::SharedPointer<i2c::sf::ISession>> out, i2c::I2cDevice device), (out, device)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, HasDevice, (ams::sf::Out<bool> 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<bool> 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<ams::sf::SharedPointer<i2c::sf::ISession>> 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)
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/i2c/i2c_types.hpp>
|
||||
|
||||
#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<i2c::I2cCommand> &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<i2c::I2cCommand> &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<i2c::I2cCommand> &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<i2c::I2cCommand> &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)
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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,37 +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 AddressSpaceType {
|
||||
AddressSpaceType_32Bit = 0,
|
||||
AddressSpaceType_64BitDeprecated = 1,
|
||||
AddressSpaceType_32BitWithoutAlias = 2,
|
||||
AddressSpaceType_64Bit = 3,
|
||||
enum MetaFlag1 {
|
||||
MetaFlag1_EnableShadowStack = (1 << 0),
|
||||
};
|
||||
|
||||
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(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 reserved_0D;
|
||||
u8 flags0;
|
||||
u8 flags1;
|
||||
u8 main_thread_priority;
|
||||
u8 default_cpu_id;
|
||||
u8 reserved_10[4];
|
||||
|
||||
@@ -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 &) {
|
||||
|
||||
@@ -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<pgl::sf::IEventObserver> 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<typename... Args>
|
||||
explicit EventObserverByTipc(Args &&... args) : m_tipc_interface(std::forward<Args>(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<pm::ProcessEventInfo>(out)));
|
||||
virtual Result GetShellEventInfo(pm::ProcessEventInfo *out) override {
|
||||
R_RETURN(m_tipc_interface.GetShellEventInfo(ams::tipc::Out<pm::ProcessEventInfo>(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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ namespace ams::pgl {
|
||||
Full = 2,
|
||||
};
|
||||
|
||||
/* TODO: Is this really nn::ncm::Content<Something>Info? */
|
||||
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<ContentMetaInfo>::value);
|
||||
static_assert(sizeof(ProgramLaunchProperty) == 0x10 && util::is_pod<ProgramLaunchProperty>::value);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <stratosphere/pgl/pgl_types.hpp>
|
||||
|
||||
#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<pm::ProcessEventInfo> 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<pm::ProcessEventInfo> out), (out))
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::pgl::sf, IEventObserver, AMS_PGL_SF_I_EVENT_OBSERVER_INTERFACE_INFO, 0x00000000);
|
||||
|
||||
|
||||
@@ -25,16 +25,15 @@
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::sf::Out<os::ProcessId> 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<os::ProcessId> 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<pgl::ContentMetaInfo> out, const ams::sf::InBuffer &content_path), (out, content_path)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::sf::Out<os::ProcessId> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, GetProgramLaunchPropertyFromHost, (ams::sf::Out<pgl::ProgramLaunchProperty> out, const ams::sf::InBuffer &content_path), (out, content_path)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::sf::Out<os::ProcessId> 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<bool> out, os::ProcessId process_id), (out, process_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, Result, IsRunningProcess, (ams::sf::Out<bool> 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<bool> 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<os::ProcessId> 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<ams::sf::SharedPointer<pgl::sf::IEventObserver>> 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<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 21, Result, Command21NotImplemented, (ams::sf::Out<u64> 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);
|
||||
|
||||
@@ -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<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags);
|
||||
Result TerminateProcess(os::ProcessId process_id);
|
||||
Result LaunchProgramFromHost(ams::sf::Out<os::ProcessId> out, const ams::sf::InBuffer &content_path, u32 pm_flags);
|
||||
Result GetHostContentMetaInfo(ams::sf::Out<pgl::ContentMetaInfo> out, const ams::sf::InBuffer &content_path);
|
||||
Result GetApplicationProcessId(ams::sf::Out<os::ProcessId> out);
|
||||
Result GetProgramLaunchPropertyFromHost(ams::sf::Out<pgl::ProgramLaunchProperty> out, const ams::sf::InBuffer &content_path);
|
||||
Result GetRunningApplicationProcessId(ams::sf::Out<os::ProcessId> out);
|
||||
Result BoostSystemMemoryResourceLimit(u64 size);
|
||||
Result IsProcessTracked(ams::sf::Out<bool> out, os::ProcessId process_id);
|
||||
Result IsRunningProcess(ams::sf::Out<bool> out, os::ProcessId process_id);
|
||||
Result EnableApplicationCrashReport(bool enabled);
|
||||
Result IsApplicationCrashReportEnabled(ams::sf::Out<bool> out);
|
||||
Result EnableApplicationAllThreadDumpOnCrash(bool enabled);
|
||||
Result GetProcessId(ams::sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
|
||||
Result TriggerApplicationSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg);
|
||||
|
||||
Result GetShellEventObserver(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out);
|
||||
Result TriggerSnapShotDumper(SnapShotDumpType dump_type, const ams::sf::InBuffer &arg);
|
||||
Result CreateShellEvent(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out);
|
||||
Result Command21NotImplemented(ams::sf::Out<u64> out, u32 in, const ams::sf::InBuffer &buf1, const ams::sf::InBuffer &buf2);
|
||||
};
|
||||
static_assert(pgl::sf::IsIShellInterface<ShellInterfaceCmif>);
|
||||
@@ -81,15 +80,16 @@ namespace ams::pgl::srv {
|
||||
Result LaunchProgram(ams::tipc::Out<os::ProcessId> out, const ncm::ProgramLocation loc, u32 pm_flags, u8 pgl_flags);
|
||||
Result TerminateProcess(os::ProcessId process_id);
|
||||
Result LaunchProgramFromHost(ams::tipc::Out<os::ProcessId> out, const ams::tipc::InBuffer content_path, u32 pm_flags);
|
||||
Result GetHostContentMetaInfo(ams::tipc::Out<pgl::ContentMetaInfo> out, const ams::tipc::InBuffer content_path);
|
||||
Result GetApplicationProcessId(ams::tipc::Out<os::ProcessId> out);
|
||||
Result GetProgramLaunchPropertyFromHost(ams::tipc::Out<pgl::ProgramLaunchProperty> out, const ams::tipc::InBuffer content_path);
|
||||
Result GetRunningApplicationProcessId(ams::tipc::Out<os::ProcessId> out);
|
||||
Result BoostSystemMemoryResourceLimit(u64 size);
|
||||
Result IsProcessTracked(ams::tipc::Out<bool> out, os::ProcessId process_id);
|
||||
Result IsRunningProcess(ams::tipc::Out<bool> out, os::ProcessId process_id);
|
||||
Result EnableApplicationCrashReport(bool enabled);
|
||||
Result IsApplicationCrashReportEnabled(ams::tipc::Out<bool> out);
|
||||
Result EnableApplicationAllThreadDumpOnCrash(bool enabled);
|
||||
Result GetProcessId(ams::tipc::Out<os::ProcessId> 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<ShellInterfaceTipc>);
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include <stratosphere/pgl/pgl_types.hpp>
|
||||
|
||||
#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<pm::ProcessEventInfo> 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<pm::ProcessEventInfo> out), (out))
|
||||
|
||||
AMS_TIPC_DEFINE_INTERFACE(ams::pgl::tipc, IEventObserver, AMS_PGL_TIPC_I_EVENT_OBSERVER_INTERFACE_INFO);
|
||||
|
||||
|
||||
@@ -22,17 +22,19 @@
|
||||
#include <stratosphere/pgl/pgl_types.hpp>
|
||||
#include <stratosphere/pgl/tipc/pgl_tipc_i_event_observer.hpp>
|
||||
|
||||
#define AMS_PGL_TIPC_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \
|
||||
AMS_TIPC_METHOD_INFO(C, H, 0, Result, LaunchProgram, (ams::tipc::Out<os::ProcessId> 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<os::ProcessId> 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<pgl::ContentMetaInfo> out, const ams::tipc::InBuffer content_path), (out, content_path)) \
|
||||
AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (ams::tipc::Out<os::ProcessId> 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<bool> 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<bool> 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<os::ProcessId> 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<os::ProcessId> 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<pgl::ProgramLaunchProperty> out, const ams::tipc::InBuffer content_path), (out, content_path)) \
|
||||
AMS_TIPC_METHOD_INFO(C, H, 5, Result, GetRunningApplicationProcessId, (ams::tipc::Out<os::ProcessId> 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<bool> 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<bool> out), (out)) \
|
||||
AMS_TIPC_METHOD_INFO(C, H, 10, Result, EnableApplicationAllThreadDumpOnCrash, (bool enabled), (enabled)) \
|
||||
AMS_TIPC_METHOD_INFO(C, H, 11, Result, GetProcessId, (ams::tipc::Out<os::ProcessId> 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);
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
#include <stratosphere/ro/ro_types.hpp>
|
||||
#include <stratosphere/sf.hpp>
|
||||
|
||||
#define AMS_RO_I_RO_INTERFACE_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, MapManualLoadModuleMemory, (sf::Out<u64> 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<u64> 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)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/ncm/ncm_ids.hpp>
|
||||
#include <stratosphere/rocrt/rocrt.hpp>
|
||||
|
||||
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!");
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -89,6 +89,12 @@ namespace ams::spl {
|
||||
return ::ams::spl::GetConfigBool(::ams::spl::ConfigItem::ExosphereForceEnableUsb30);
|
||||
}
|
||||
|
||||
inline std::pair<u8, u32> GetLogConfiguration() {
|
||||
u64 v;
|
||||
R_ABORT_UNLESS(::ams::spl::GetConfig(std::addressof(v), ::ams::spl::ConfigItem::ExosphereLogConfiguration));
|
||||
return std::make_pair(static_cast<u8>(v >> 32), static_cast<u32>(v));
|
||||
}
|
||||
|
||||
Result SetBootReason(BootReasonValue boot_reason);
|
||||
Result GetBootReason(BootReasonValue *out);
|
||||
|
||||
|
||||
@@ -230,6 +230,7 @@ namespace ams::spl {
|
||||
RegulatorType = 15,
|
||||
DeviceUniqueKeyGeneration = 16,
|
||||
Package2Hash = 17,
|
||||
Unknown18 = 18,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
|
||||
@@ -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<Identifier>::value);
|
||||
static_assert(sizeof(HashKey) == 7);
|
||||
static_assert(util::is_pod<HashKey>::value);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,9 +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_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 ||
|
||||
@@ -166,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../spl/impl/spl_ctr_drbg.hpp"
|
||||
#include <vapours/crypto/impl/crypto_ctr_drbg.hpp>
|
||||
#include <sys/random.h>
|
||||
|
||||
namespace ams::crypto {
|
||||
|
||||
namespace {
|
||||
|
||||
using Drbg = ::ams::spl::impl::CtrDrbg<crypto::AesEncryptor128, crypto::AesEncryptor128::KeySize, false>;
|
||||
using Drbg = ::ams::crypto::impl::CtrDrbg<crypto::AesEncryptor128, crypto::AesEncryptor128::KeySize, false>;
|
||||
|
||||
constinit util::TypedStorage<Drbg> g_drbg = {};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,9 +73,30 @@ namespace ams::erpt::srv {
|
||||
/* We succeeded. */
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SubmitAttachmentImpl(ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data, bool lz4_compression, bool unk) {
|
||||
const char *name = reinterpret_cast<const char *>(attachment_name.GetPointer());
|
||||
const u8 *data = reinterpret_cast<const u8 *>(attachment_data.GetPointer());
|
||||
|
||||
const u32 name_size = static_cast<u32>(attachment_name.GetSize());
|
||||
const u32 data_size = static_cast<u32>(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. */
|
||||
AMS_UNUSED(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<const ContextEntry *>( ctx_buffer.GetPointer());
|
||||
const u8 *data = reinterpret_cast<const u8 *>(data_buffer.GetPointer());
|
||||
@@ -213,27 +234,14 @@ namespace ams::erpt::srv {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ContextImpl::SubmitAttachment(ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) {
|
||||
const char *name = reinterpret_cast<const char *>(attachment_name.GetPointer());
|
||||
const u8 *data = reinterpret_cast<const u8 *>(attachment_data.GetPointer());
|
||||
|
||||
const u32 name_size = static_cast<u32>(attachment_name.GetSize());
|
||||
const u32 data_size = static_cast<u32>(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<AttachmentId> 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<AttachmentId> 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<AttachmentId> 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<SubmitAttachmentOptionFlag::Lz4Compression>(), flags.Test<SubmitAttachmentOptionFlag::Unknown0x10000>()));
|
||||
}
|
||||
|
||||
Result ContextImpl::RegisterRunningApplet(ncm::ProgramId program_id) {
|
||||
R_RETURN(Reporter::RegisterRunningApplet(program_id));
|
||||
|
||||
@@ -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<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data);
|
||||
Result SubmitAttachmentDeprecated(ams::sf::Out<AttachmentId> 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<AttachmentId> 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<AttachmentId> 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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace ams::erpt::srv {
|
||||
static Result SetOwner(AttachmentId attachment_id, ReportId report_id);
|
||||
static Result StoreRecord(JournalRecord<AttachmentInfo> *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 {
|
||||
|
||||
@@ -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. */
|
||||
AMS_UNUSED(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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user