Compare commits
219 Commits
1.9.0-prer
...
1.12.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec9b500c67 | ||
|
|
31d5beb756 | ||
|
|
efc4e5e87b | ||
|
|
28d6a2e11f | ||
|
|
c68e08a101 | ||
|
|
7442487ace | ||
|
|
a1a9886290 | ||
|
|
afb0cda7f3 | ||
|
|
7dd6771584 | ||
|
|
59e7786a45 | ||
|
|
2ae182bd5d | ||
|
|
788546f476 | ||
|
|
e872f5b566 | ||
|
|
56cb82aa44 | ||
|
|
58f2b963d5 | ||
|
|
44d9649c6d | ||
|
|
2d0fc65fd8 | ||
|
|
21f16ff938 | ||
|
|
82f15b6e5d | ||
|
|
1de771e264 | ||
|
|
02ce3bc385 | ||
|
|
0411dbfdda | ||
|
|
56d301ef5c | ||
|
|
1748644f81 | ||
|
|
f62bc71ea4 | ||
|
|
518e494744 | ||
|
|
1d6e593aba | ||
|
|
866c831f7a | ||
|
|
85f119a5c4 | ||
|
|
3cfac4c2d8 | ||
|
|
4e917d700f | ||
|
|
f40b85cd5d | ||
|
|
af14725916 | ||
|
|
1d308207f7 | ||
|
|
8ad3efdd79 | ||
|
|
ab1e8a3e32 | ||
|
|
9b4e4a2190 | ||
|
|
ff09b598d5 | ||
|
|
6acbabeb72 | ||
|
|
98d64c28d8 | ||
|
|
7cc625946e | ||
|
|
afff8cbf16 | ||
|
|
b7048ec595 | ||
|
|
092f451c33 | ||
|
|
49b12237e8 | ||
|
|
dbfe192b2f | ||
|
|
7e58f5fbae | ||
|
|
289ba7104e | ||
|
|
0f15010ba5 | ||
|
|
e6a3d71692 | ||
|
|
819da013ed | ||
|
|
3d8caba822 | ||
|
|
aad15daad6 | ||
|
|
22bbe413c6 | ||
|
|
85aea12e53 | ||
|
|
8ec1288bd6 | ||
|
|
bce987792d | ||
|
|
3d3f0c2daf | ||
|
|
6e6af69424 | ||
|
|
332926fc17 | ||
|
|
cb4b882e3b | ||
|
|
f7d46d38fa | ||
|
|
e468f59c9d | ||
| 26b1ec7ca8 | |||
|
|
b05166d502 | ||
|
|
3ace80cc7b | ||
|
|
10722de8b9 | ||
|
|
59846adcb7 | ||
|
|
94e62a7b1b | ||
|
|
fbeea26919 | ||
|
|
38251801df | ||
|
|
7b6ee4916e | ||
|
|
556e628478 | ||
|
|
5388824be1 | ||
|
|
974a1025b8 | ||
|
|
9d21cfca4c | ||
|
|
1478f3443e | ||
|
|
f527e7fc48 | ||
|
|
7dccf3bffa | ||
|
|
4ea042510b | ||
|
|
d97f520058 | ||
|
|
3a3a2ca99b | ||
|
|
fcd46b4419 | ||
|
|
c046eeacdd | ||
|
|
4181169f80 | ||
|
|
47cfe05bb0 | ||
|
|
c497ffda75 | ||
|
|
15c434f185 | ||
|
|
7d38bf16cd | ||
| 5cb085b00c | |||
|
|
2c7e2bfaae | ||
|
|
e655fd4b01 | ||
|
|
022000f668 | ||
|
|
d04c20a049 | ||
|
|
252f8685b4 | ||
|
|
020ed307b1 | ||
|
|
d9e1d799ab | ||
|
|
80bd459516 | ||
|
|
931e3c37fd | ||
|
|
4b4db91341 | ||
|
|
e3fc339fe5 | ||
|
|
a051c3c723 | ||
|
|
9a1ea02c8c | ||
|
|
bae1ad22ec | ||
|
|
cd1503a9ca | ||
|
|
72e3b0dd34 | ||
|
|
ac120cf84b | ||
|
|
97ffad2ab6 | ||
|
|
c8d68a3a8a | ||
|
|
8987d642d1 | ||
|
|
7ffb1da2ac | ||
|
|
5c426bf90d | ||
|
|
31ca20f3b7 | ||
|
|
174da786e4 | ||
|
|
93a82c0441 | ||
|
|
082115187a | ||
|
|
db388385b0 | ||
|
|
4a8f7628c2 | ||
|
|
9d16ee6a74 | ||
|
|
3b9ee08c69 | ||
|
|
2694f31eb3 | ||
|
|
f3f1fa46ed | ||
|
|
8a7c2872c3 | ||
|
|
6acdc05c89 | ||
|
|
32bb6b17ab | ||
|
|
27455329b3 | ||
|
|
7d334f09ee | ||
|
|
8c0ff851f2 | ||
|
|
b108318996 | ||
|
|
5dfdc6e8b0 | ||
|
|
14e63cb04c | ||
|
|
5dd9816e3c | ||
|
|
5a5d9b206b | ||
|
|
49e2330ed8 | ||
|
|
1847db06f8 | ||
|
|
f028802fb8 | ||
|
|
b29dbeae3d | ||
|
|
4e653f67e5 | ||
|
|
a985bdb1d4 | ||
|
|
5b0a4830d4 | ||
|
|
26990b3be9 | ||
|
|
76bceffbd5 | ||
|
|
0ee6277be9 | ||
|
|
9cc82c6f80 | ||
|
|
6b831406d6 | ||
|
|
23ebd4d677 | ||
|
|
00f987dd38 | ||
|
|
f8a5a6c015 | ||
|
|
61ac03e22d | ||
|
|
208b60696c | ||
|
|
dfb936ed11 | ||
|
|
5056ab21af | ||
|
|
eb34f9789c | ||
|
|
1e88f37892 | ||
|
|
cd72f9f33e | ||
|
|
21c0f75a29 | ||
|
|
3cb5d5f957 | ||
|
|
00d1cdb533 | ||
|
|
d9fc6e99eb | ||
|
|
c08a13a546 | ||
|
|
b5b6189c85 | ||
|
|
28a378ca0d | ||
|
|
540d00e097 | ||
|
|
bfe98bc5b8 | ||
|
|
4928bcb003 | ||
|
|
d61ee942d9 | ||
|
|
f59e6a936b | ||
|
|
129c61c256 | ||
|
|
db71eefd9f | ||
|
|
4b32a2b964 | ||
|
|
0fb9481e59 | ||
|
|
c05d91f44a | ||
|
|
e1d82a13f3 | ||
|
|
4f1201a022 | ||
|
|
4201bbff63 | ||
|
|
94c36a3255 | ||
|
|
6b0ef21b83 | ||
|
|
ac382f69e7 | ||
|
|
2a44550dbe | ||
|
|
3bc1951820 | ||
|
|
418fde40a8 | ||
|
|
e36051359c | ||
|
|
18bb1fdea0 | ||
|
|
c8e39a54d2 | ||
|
|
11a46e4579 | ||
|
|
652519da2e | ||
|
|
de9b02007b | ||
|
|
982f0e4fd4 | ||
|
|
d7936d3fa4 | ||
|
|
1c0ea680b6 | ||
|
|
b8ed942ae4 | ||
|
|
98bc030b37 | ||
|
|
081e76a2b5 | ||
|
|
e8de1e3c34 | ||
|
|
41b28bb0c4 | ||
|
|
3197b1e25b | ||
|
|
822cbbbc8b | ||
|
|
4237f52ee2 | ||
|
|
8b8e4438e8 | ||
|
|
debfff9f62 | ||
|
|
c77acb32be | ||
|
|
af859d9e65 | ||
|
|
a487efad6b | ||
|
|
7e0eb10e32 | ||
|
|
4a3e2b5c57 | ||
|
|
d8a37b4b71 | ||
|
|
b11850b3a3 | ||
|
|
77603bf7e5 | ||
|
|
6b01ebca9e | ||
|
|
17be65b4b9 | ||
|
|
409c3cf9e1 | ||
|
|
f4e1d0bf9f | ||
|
|
ae65b5df0c | ||
|
|
0a299a3d40 | ||
|
|
801438953d | ||
|
|
3fbc59cce1 | ||
|
|
f646d9c8f9 | ||
|
|
69cc653e7f | ||
|
|
6da88f8f3e |
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"]
|
||||
4
Makefile
4
Makefile
@@ -13,6 +13,10 @@ $(strip $1):
|
||||
@echo "Building $(strip $1)"
|
||||
@$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
|
||||
|
||||
dist-no-debug-$(strip $1):
|
||||
@echo "Building $(strip $1)"
|
||||
@$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk dist-no-debug ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
|
||||
|
||||
clean-$(strip $1):
|
||||
@echo "Cleaning $(strip $1)"
|
||||
@$$(MAKE) -f $(CURRENT_DIRECTORY)/atmosphere.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||

|
||||
[](https://discordapp.com/invite/ZdqEhed)
|
||||

|
||||
|
||||
Atmosphère is a work-in-progress customized firmware for the Nintendo Switch.
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ dist: dist-no-debug
|
||||
cp $(CURRENT_DIRECTORY)/troposphere/daybreak/daybreak.elf $(DIST_DIR)/daybreak.elf
|
||||
cp $(CURRENT_DIRECTORY)/troposphere/haze/haze.elf $(DIST_DIR)/haze.elf
|
||||
cp $(CURRENT_DIRECTORY)/troposphere/reboot_to_payload/reboot_to_payload.elf $(DIST_DIR)/reboot_to_payload.elf
|
||||
cd $(DIST_DIR); zip -r ../atmosphere-$(ATMOSPHERE_VERSION)-debug.zip ./*; cd ../;
|
||||
cd $(DIST_DIR); zip -1 -r ../atmosphere-$(ATMOSPHERE_VERSION)-debug.zip ./*; cd ../;
|
||||
rm -rf $(DIST_DIR)
|
||||
|
||||
dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
@@ -107,7 +107,7 @@ dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
cp stratosphere/dmnt.gen2/$(ATMOSPHERE_OUT_DIR)/dmnt.gen2.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d609/exefs.nsp
|
||||
cp stratosphere/TioServer/$(ATMOSPHERE_OUT_DIR)/TioServer.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/010000000000d623/exefs.nsp
|
||||
cp stratosphere/memlet/$(ATMOSPHERE_OUT_DIR)/memlet.nsp $(DIST_DIR)/stratosphere_romfs/atmosphere/contents/0100000000000421/exefs.nsp
|
||||
@build_romfs $(DIST_DIR)/stratosphere_romfs $(DIST_DIR)/atmosphere/stratosphere.romfs
|
||||
@PATH="$(DEVKITPRO)/tools/bin:$$PATH" build_romfs $(DIST_DIR)/stratosphere_romfs $(DIST_DIR)/atmosphere/stratosphere.romfs
|
||||
rm -r $(DIST_DIR)/stratosphere_romfs
|
||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro $(DIST_DIR)/switch/reboot_to_payload.nro
|
||||
cp troposphere/daybreak/daybreak.nro $(DIST_DIR)/switch/daybreak.nro
|
||||
@@ -117,7 +117,7 @@ dist-no-debug: package3 $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
cp fusee/$(ATMOSPHERE_BOOT_OUT_DIR)/fusee.bin $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)/fusee.bin
|
||||
|
||||
package3: emummc fusee stratosphere mesosphere exosphere troposphere
|
||||
@python fusee/build_package3.py $(CURRENT_DIRECTORY) $(ATMOSPHERE_OUT_DIR) $(ATMOSPHERE_BOOT_OUT_DIR) $(ATMOSPHERE_GIT_HASH) $(ATMOSPHERE_MAJOR_VERSION) $(ATMOSPHERE_MINOR_VERSION) $(ATMOSPHERE_MICRO_VERSION) 0 $(ATMOSPHERE_SUPPORTED_HOS_MAJOR_VERSION) $(ATMOSPHERE_SUPPORTED_HOS_MINOR_VERSION) $(ATMOSPHERE_SUPPORTED_HOS_MICRO_VERSION) 0
|
||||
$(SILENTCMD)$(PYTHON) fusee/build_package3.py $(CURRENT_DIRECTORY) $(ATMOSPHERE_OUT_DIR) $(ATMOSPHERE_BOOT_OUT_DIR) $(ATMOSPHERE_GIT_HASH) $(ATMOSPHERE_MAJOR_VERSION) $(ATMOSPHERE_MINOR_VERSION) $(ATMOSPHERE_MICRO_VERSION) 0 $(ATMOSPHERE_SUPPORTED_HOS_MAJOR_VERSION) $(ATMOSPHERE_SUPPORTED_HOS_MINOR_VERSION) $(ATMOSPHERE_SUPPORTED_HOS_MICRO_VERSION) 0
|
||||
@echo "Built package3!"
|
||||
|
||||
emummc:
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
# Desc: Controls whether userland has access to the PMU registers.
|
||||
# NOTE: It is unknown what effects this has on official code.
|
||||
|
||||
# Key: enable_mem_mode, default: 0.
|
||||
# Desc: Controls whether boot config memory mode is taken into account
|
||||
# for retail units. This does not affect development units.
|
||||
# NOTE: On retail units max ram size is capped to 4GB.
|
||||
# Enabling this will use the boot config memory mode parameter,
|
||||
# which by default is auto and size gets set based on physical size.
|
||||
|
||||
# Key: blank_prodinfo_sysmmc, default: 0.
|
||||
# Desc: Controls whether PRODINFO should be blanked in sysmmc.
|
||||
# This will cause the system to see dummied out keys and
|
||||
@@ -51,6 +58,7 @@ debugmode=1
|
||||
debugmode_user=0
|
||||
disable_user_exception_handlers=0
|
||||
enable_user_pmu_access=0
|
||||
enable_mem_mode=0
|
||||
blank_prodinfo_sysmmc=0
|
||||
blank_prodinfo_emummc=0
|
||||
allow_writing_to_cal_sysmmc=0
|
||||
|
||||
@@ -1,4 +1,113 @@
|
||||
# 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).
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.11.1
|
||||
+ Basic support was added for 22.1.0.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.11.0
|
||||
+ Support was added for 22.0.0.
|
||||
+ Special thanks to @alula for handling a large chunk of the necessary kernel, loader and erpt changes.
|
||||
+ The console should boot and atmosphère should be fully functional.
|
||||
+ **Please note**: A change in how applications/applets' lifespan is managed broke the homebrew ecosystem.
|
||||
+ All applications and applets are expected to perform a clean exit by calling the relevant IPC commands.
|
||||
+ Homebrew compiled with libnx and hbmenu itself explicitly avoid exiting so it can keep using the same process.
|
||||
+ Properly fixing this would require a re-design of how homebrew is launched and terminated.
|
||||
+ As a temporary solution, patches to the `am` sysmodule are now included which allow restoring the previous behavior and regain homebrew compatibility without any further changes.
|
||||
+ Nonetheless, please report any issues you may face when testing homebrew to ensure no edge cases have been missed.
|
||||
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ `loader` was updated to reflect the latest official behavior.
|
||||
+ `erpt` was updated to reflect the latest official behavior.
|
||||
+ `pgl` was updated to fix a few issues.
|
||||
+ Support was added for memory modes above 4GB (thanks @CTCaer).
|
||||
+ A build time option to configure Joy-Con rails as UART for debugging was added (thanks @alula).
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.10.2
|
||||
+ Basic support was added for 21.2.0.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.10.1
|
||||
+ Basic support was added for 21.1.0.
|
||||
+ A bug was fixed that caused some games (e.g. Tomb Raider definitive edition) to fail to launch.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.10.0
|
||||
+ Basic support was added for 21.0.0.
|
||||
+ The console should boot and atmosphère should be fully functional.
|
||||
+ **Please note**: All homebrew software may need to be re-compiled with the latest libnx (>= 4.10.0), or else it may crash/experience memory corruption.
|
||||
+ Nintendo broke the userland<->kernel TLS ABI in 21.0.0, by writing to previously reserved space.
|
||||
+ Homebrew used this reserved space for its TLS slots, which means any homebrew software using TLS slots will experience memory corruption when running under Atmosphere 1.10.0.
|
||||
+ This doesn't appear to impact everything, but a large portion of tested homebrew crashes (often on exit), and so will need re-compile for the new ABI.
|
||||
+ For those technically inclined, while TLS slots are rarely used by developers, they're used to implement features like e.g. C++ exceptions under the hood, and so anything using those crashes, etc.
|
||||
+ To help make this transition easier, hbmenu now shows a warning when selecting homebrew compiled with an older, incompatible ABI version.
|
||||
+ I apologize for the hassle in general.
|
||||
+ libnx has been updated so that its reserved space matches Nintendo's now -- this particular issue can never occur again, even if Nintendo touches more reserved space.
|
||||
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ `loader` was updated to reflect the latest official behavior.
|
||||
+ `pm` 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.
|
||||
+ `fatal` was updated to reflect the latest official behavior.
|
||||
+ Support was added for launching another game-which-has-too-many-files with romfs mods.
|
||||
+ I rely on user reports for adding support/fixing these, and some of these games can be pretty obscure!
|
||||
+ If you are affected by this, you will see "Data abort (0x101)" when trying to launch the game with mods.
|
||||
+ Please reach out to `sciresm` on discord if this occurs to share your error report binary.
|
||||
+ Although some games may be impossible to fix, I believe I can get almost everything working, so please let me try to help you (and improve atmosphère's support!) if you run into this!
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.5
|
||||
+ Basic support was added for 20.5.0.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.4
|
||||
+ Basic support was added for 20.4.0.
|
||||
+ An issue was fixed in `exosphère`'s register accessilibity tables (thanks @CTCaer).
|
||||
+ I believe this had no impact on official code, though it would have prevented some homebrew from interacting correctly with the MC0/MC1 registers.
|
||||
+ An issue was fixed that could cause a deadlock when building multiple romfs images simultaneously (thanks @Ereza).
|
||||
+ This fixes support for certain mods, e.g. system language translations overriding content for both overlayDisp and qlaunch.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.3
|
||||
+ Basic support was added for 20.3.0.
|
||||
+ Compatibility was fixed for loading mods with KOTOR 2 (star wars).
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.2
|
||||
+ Basic support was added for 20.2.0.
|
||||
+ USB 3.0 support force-enable was fixed for 20.1.0+.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.1
|
||||
+ Basic support was added for 20.1.0.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 1.9.0
|
||||
+ Basic support was added for 20.0.0.
|
||||
+ The console should boot and atmosphère should be fully functional. However, not all modules have been fully updated to reflect the latest changes.
|
||||
|
||||
@@ -423,41 +423,41 @@ Note that for multiple button combinations, the bitmasks should be OR'd together
|
||||
#### Keypad Values
|
||||
Note: This is the direct output of `hidKeysDown()`.
|
||||
|
||||
+ 000000001: A
|
||||
+ 000000002: B
|
||||
+ 000000004: X
|
||||
+ 000000008: Y
|
||||
+ 000000010: Left Stick Pressed
|
||||
+ 000000020: Right Stick Pressed
|
||||
+ 000000040: L
|
||||
+ 000000080: R
|
||||
+ 000000100: ZL
|
||||
+ 000000200: ZR
|
||||
+ 000000400: Plus
|
||||
+ 000000800: Minus
|
||||
+ 000001000: Left
|
||||
+ 000002000: Up
|
||||
+ 000004000: Right
|
||||
+ 000008000: Down
|
||||
+ 000010000: Left Stick Left
|
||||
+ 000020000: Left Stick Up
|
||||
+ 000040000: Left Stick Right
|
||||
+ 000080000: Left Stick Down
|
||||
+ 000100000: Right Stick Left
|
||||
+ 000200000: Right Stick Up
|
||||
+ 000400000: Right Stick Right
|
||||
+ 000800000: Right Stick Down
|
||||
+ 001000000: SL Left Joy-Con
|
||||
+ 002000000: SR Left Joy-Con
|
||||
+ 004000000: SL Right Joy-Con
|
||||
+ 008000000: SR Right Joy-Con
|
||||
+ 010000000: Top button on Poké Ball Plus (Palma) controller
|
||||
+ 020000000: Verification
|
||||
+ 040000000: B button on Left NES/HVC controller in Handheld mode
|
||||
+ 080000000: Left C button in N64 controller
|
||||
+ 100000000: Up C button in N64 controller
|
||||
+ 200000000: Right C button in N64 controller
|
||||
+ 400000000: Down C button in N64 controller
|
||||
+ 00000000 00000001: A
|
||||
+ 00000000 00000002: B
|
||||
+ 00000000 00000004: X
|
||||
+ 00000000 00000008: Y
|
||||
+ 00000000 00000010: Left Stick Pressed
|
||||
+ 00000000 00000020: Right Stick Pressed
|
||||
+ 00000000 00000040: L
|
||||
+ 00000000 00000080: R
|
||||
+ 00000000 00000100: ZL
|
||||
+ 00000000 00000200: ZR
|
||||
+ 00000000 00000400: Plus
|
||||
+ 00000000 00000800: Minus
|
||||
+ 00000000 00001000: Left
|
||||
+ 00000000 00002000: Up
|
||||
+ 00000000 00004000: Right
|
||||
+ 00000000 00008000: Down
|
||||
+ 00000000 00010000: Left Stick Left
|
||||
+ 00000000 00020000: Left Stick Up
|
||||
+ 00000000 00040000: Left Stick Right
|
||||
+ 00000000 00080000: Left Stick Down
|
||||
+ 00000000 00100000: Right Stick Left
|
||||
+ 00000000 00200000: Right Stick Up
|
||||
+ 00000000 00400000: Right Stick Right
|
||||
+ 00000000 00800000: Right Stick Down
|
||||
+ 00000000 01000000: SL Left Joy-Con
|
||||
+ 00000000 02000000: SR Left Joy-Con
|
||||
+ 00000000 04000000: SL Right Joy-Con
|
||||
+ 00000000 08000000: SR Right Joy-Con
|
||||
+ 00000000 10000000: Top button on Poké Ball Plus (Palma) controller
|
||||
+ 00000000 20000000: Verification
|
||||
+ 00000000 40000000: B button on Left NES/HVC controller in Handheld mode
|
||||
+ 00000000 80000000: Left C button in N64 controller
|
||||
+ 00000001 00000000: Up C button in N64 controller
|
||||
+ 00000002 00000000: Right C button in N64 controller
|
||||
+ 00000004 00000000: Down C button in N64 controller
|
||||
|
||||
### Code Type 0xF0: Double Extended-Width Instruction
|
||||
Code Type 0xF0 signals to the VM to treat the upper three nybbles of the first dword as instruction type, instead of just the upper nybble.
|
||||
|
||||
6
emummc/.gitrepo
vendored
6
emummc/.gitrepo
vendored
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/m4xw/emummc
|
||||
branch = develop
|
||||
commit = 7522f1f6054a71bdff5beadee0302cead1235be3
|
||||
parent = 0e2ef545f947d24c6add254874ab493ba84bbdc9
|
||||
commit = 5b966b6f3f83349ec65066a1877f7f948b48d08c
|
||||
parent = 7442487ace6b79ddddf2cd0007b8dade8150bf5c
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
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 - 20.0.0**
|
||||
**1.0.0 - 23.0.0**
|
||||
|
||||
## Features
|
||||
* Arbitrary SDMMC backend selection
|
||||
|
||||
48
emummc/source/FS/FS_offsets.c
vendored
48
emummc/source/FS/FS_offsets.c
vendored
@@ -77,6 +77,18 @@
|
||||
#include "offsets/1900_exfat.h"
|
||||
#include "offsets/2000.h"
|
||||
#include "offsets/2000_exfat.h"
|
||||
#include "offsets/2010.h"
|
||||
#include "offsets/2010_exfat.h"
|
||||
#include "offsets/2100.h"
|
||||
#include "offsets/2100_exfat.h"
|
||||
#include "offsets/2120.h"
|
||||
#include "offsets/2120_exfat.h"
|
||||
#include "offsets/2200.h"
|
||||
#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
|
||||
@@ -165,6 +177,18 @@ DEFINE_OFFSET_STRUCT(_1900);
|
||||
DEFINE_OFFSET_STRUCT(_1900_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_2000);
|
||||
DEFINE_OFFSET_STRUCT(_2000_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_2010);
|
||||
DEFINE_OFFSET_STRUCT(_2010_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_2100);
|
||||
DEFINE_OFFSET_STRUCT(_2100_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_2120);
|
||||
DEFINE_OFFSET_STRUCT(_2120_EXFAT);
|
||||
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) {
|
||||
@@ -290,6 +314,30 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2000));
|
||||
case FS_VER_20_0_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2000_EXFAT));
|
||||
case FS_VER_20_1_0:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2010));
|
||||
case FS_VER_20_1_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2010_EXFAT));
|
||||
case FS_VER_21_0_0:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2100));
|
||||
case FS_VER_21_0_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2100_EXFAT));
|
||||
case FS_VER_21_2_0:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2120));
|
||||
case FS_VER_21_2_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2120_EXFAT));
|
||||
case FS_VER_22_0_0:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2200));
|
||||
case FS_VER_22_0_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_2200_EXFAT));
|
||||
case FS_VER_22_5_0:
|
||||
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);
|
||||
}
|
||||
|
||||
18
emummc/source/FS/FS_versions.h
vendored
18
emummc/source/FS/FS_versions.h
vendored
@@ -113,6 +113,24 @@ enum FS_VER
|
||||
FS_VER_20_0_0,
|
||||
FS_VER_20_0_0_EXFAT,
|
||||
|
||||
FS_VER_20_1_0,
|
||||
FS_VER_20_1_0_EXFAT,
|
||||
|
||||
FS_VER_21_0_0,
|
||||
FS_VER_21_0_0_EXFAT,
|
||||
|
||||
FS_VER_21_2_0,
|
||||
FS_VER_21_2_0_EXFAT,
|
||||
|
||||
FS_VER_22_0_0,
|
||||
FS_VER_22_0_0_EXFAT,
|
||||
|
||||
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/2010.h
vendored
Normal file
59
emummc/source/FS/offsets/2010.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_2010_H__
|
||||
#define __FS_2010_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2010_SDMMC_ACCESSOR_GC 0x1A7DB0
|
||||
#define FS_OFFSET_2010_SDMMC_ACCESSOR_SD 0x1AA130
|
||||
#define FS_OFFSET_2010_SDMMC_ACCESSOR_NAND 0x1A8560
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2010_SDMMC_WRAPPER_READ 0x1A3C20
|
||||
#define FS_OFFSET_2010_SDMMC_WRAPPER_WRITE 0x1A3C80
|
||||
#define FS_OFFSET_2010_RTLD 0x2B594
|
||||
#define FS_OFFSET_2010_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2010_CLKRST_SET_MIN_V_CLK_RATE 0x1C6150
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2010_LOCK_MUTEX 0x19CD80
|
||||
#define FS_OFFSET_2010_UNLOCK_MUTEX 0x19CDD0
|
||||
|
||||
#define FS_OFFSET_2010_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1A3BE0
|
||||
#define FS_OFFSET_2010_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1A3C00
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2010_SD_MUTEX 0xFF5408
|
||||
#define FS_OFFSET_2010_NAND_MUTEX 0xFF0CF0
|
||||
#define FS_OFFSET_2010_ACTIVE_PARTITION 0xFF0D30
|
||||
#define FS_OFFSET_2010_SDMMC_DAS_HANDLE 0xFD2B08
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2010_SD_DAS_INIT 0x289F4
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2010_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0006DB14, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0007CE1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x00084A08, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0009AE48, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2010_H__
|
||||
59
emummc/source/FS/offsets/2010_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2010_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_2010_EXFAT_H__
|
||||
#define __FS_2010_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_ACCESSOR_GC 0x1B36D0
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_ACCESSOR_SD 0x1B5A50
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_ACCESSOR_NAND 0x1B3E80
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_WRAPPER_READ 0x1AF540
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_WRAPPER_WRITE 0x1AF5A0
|
||||
#define FS_OFFSET_2010_EXFAT_RTLD 0x2B594
|
||||
#define FS_OFFSET_2010_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2010_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1D1A70
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2010_EXFAT_LOCK_MUTEX 0x1A86A0
|
||||
#define FS_OFFSET_2010_EXFAT_UNLOCK_MUTEX 0x1A86F0
|
||||
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AF500
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AF520
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2010_EXFAT_SD_MUTEX 0x1006408
|
||||
#define FS_OFFSET_2010_EXFAT_NAND_MUTEX 0x1001CF0
|
||||
#define FS_OFFSET_2010_EXFAT_ACTIVE_PARTITION 0x1001D30
|
||||
#define FS_OFFSET_2010_EXFAT_SDMMC_DAS_HANDLE 0xFDFB08
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2010_EXFAT_SD_DAS_INIT 0x289F4
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2010_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0006DB14, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0007CE1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x00084A08, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0009AE48, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2010_EXFAT_H__
|
||||
59
emummc/source/FS/offsets/2100.h
vendored
Normal file
59
emummc/source/FS/offsets/2100.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_2100_H__
|
||||
#define __FS_2100_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2100_SDMMC_ACCESSOR_GC 0x1AC970
|
||||
#define FS_OFFSET_2100_SDMMC_ACCESSOR_SD 0x1AE980
|
||||
#define FS_OFFSET_2100_SDMMC_ACCESSOR_NAND 0x1ACFA0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2100_SDMMC_WRAPPER_READ 0x1A8850
|
||||
#define FS_OFFSET_2100_SDMMC_WRAPPER_WRITE 0x1A88B0
|
||||
#define FS_OFFSET_2100_RTLD 0x2E1C0
|
||||
#define FS_OFFSET_2100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2100_CLKRST_SET_MIN_V_CLK_RATE 0x1CB9B0
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2100_LOCK_MUTEX 0x1A17D0
|
||||
#define FS_OFFSET_2100_UNLOCK_MUTEX 0x1A1830
|
||||
|
||||
#define FS_OFFSET_2100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1A8810
|
||||
#define FS_OFFSET_2100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1A8830
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2100_SD_MUTEX 0xFEE408
|
||||
#define FS_OFFSET_2100_NAND_MUTEX 0xFE9CF0
|
||||
#define FS_OFFSET_2100_ACTIVE_PARTITION 0xFE9D30
|
||||
#define FS_OFFSET_2100_SDMMC_DAS_HANDLE 0xFCBB18
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2100_SD_DAS_INIT 0x2B5C8
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2100_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2100_H__
|
||||
59
emummc/source/FS/offsets/2100_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2100_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_2100_EXFAT_EXFAT_H__
|
||||
#define __FS_2100_EXFAT_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_GC 0x1B7AD0
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_SD 0x1B9AE0
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_ACCESSOR_NAND 0x1B8100
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_READ 0x1B39B0
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_WRITE 0x1B3A10
|
||||
#define FS_OFFSET_2100_EXFAT_RTLD 0x2E1C0
|
||||
#define FS_OFFSET_2100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1D6B10
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2100_EXFAT_LOCK_MUTEX 0x1AC930
|
||||
#define FS_OFFSET_2100_EXFAT_UNLOCK_MUTEX 0x1AC990
|
||||
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B3970
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B3990
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2100_EXFAT_SD_MUTEX 0xFFF408
|
||||
#define FS_OFFSET_2100_EXFAT_NAND_MUTEX 0xFFACF0
|
||||
#define FS_OFFSET_2100_EXFAT_ACTIVE_PARTITION 0xFFAD30
|
||||
#define FS_OFFSET_2100_EXFAT_SDMMC_DAS_HANDLE 0xFD8B18
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2100_EXFAT_SD_DAS_INIT 0x2B5C8
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2100_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2100_EXFAT_EXFAT_H__
|
||||
59
emummc/source/FS/offsets/2120.h
vendored
Normal file
59
emummc/source/FS/offsets/2120.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_2120_H__
|
||||
#define __FS_2120_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2120_SDMMC_ACCESSOR_GC 0x1AC970
|
||||
#define FS_OFFSET_2120_SDMMC_ACCESSOR_SD 0x1AE980
|
||||
#define FS_OFFSET_2120_SDMMC_ACCESSOR_NAND 0x1ACFA0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2120_SDMMC_WRAPPER_READ 0x1A8850
|
||||
#define FS_OFFSET_2120_SDMMC_WRAPPER_WRITE 0x1A88B0
|
||||
#define FS_OFFSET_2120_RTLD 0x2E1C0
|
||||
#define FS_OFFSET_2120_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2120_CLKRST_SET_MIN_V_CLK_RATE 0x1CB9B0
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2120_LOCK_MUTEX 0x1A17D0
|
||||
#define FS_OFFSET_2120_UNLOCK_MUTEX 0x1A1830
|
||||
|
||||
#define FS_OFFSET_2120_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1A8810
|
||||
#define FS_OFFSET_2120_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1A8830
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2120_SD_MUTEX 0xFEE408
|
||||
#define FS_OFFSET_2120_NAND_MUTEX 0xFE9CF0
|
||||
#define FS_OFFSET_2120_ACTIVE_PARTITION 0xFE9D30
|
||||
#define FS_OFFSET_2120_SDMMC_DAS_HANDLE 0xFCBB18
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2120_SD_DAS_INIT 0x2B5C8
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2120_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2120_H__
|
||||
59
emummc/source/FS/offsets/2120_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2120_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_2120_EXFAT_EXFAT_H__
|
||||
#define __FS_2120_EXFAT_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_GC 0x1B7AD0
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_SD 0x1B9AE0
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_ACCESSOR_NAND 0x1B8100
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_READ 0x1B39B0
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_WRITE 0x1B3A10
|
||||
#define FS_OFFSET_2120_EXFAT_RTLD 0x2E1C0
|
||||
#define FS_OFFSET_2120_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2120_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1D6B10
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2120_EXFAT_LOCK_MUTEX 0x1AC930
|
||||
#define FS_OFFSET_2120_EXFAT_UNLOCK_MUTEX 0x1AC990
|
||||
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B3970
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B3990
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2120_EXFAT_SD_MUTEX 0xFFF408
|
||||
#define FS_OFFSET_2120_EXFAT_NAND_MUTEX 0xFFACF0
|
||||
#define FS_OFFSET_2120_EXFAT_ACTIVE_PARTITION 0xFFAD30
|
||||
#define FS_OFFSET_2120_EXFAT_SDMMC_DAS_HANDLE 0xFD8B18
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2120_EXFAT_SD_DAS_INIT 0x2B5C8
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2120_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000718CC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000824F4, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008AF18, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A0B8C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2120_EXFAT_EXFAT_H__
|
||||
59
emummc/source/FS/offsets/2200.h
vendored
Normal file
59
emummc/source/FS/offsets/2200.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_2200_H__
|
||||
#define __FS_2200_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2200_SDMMC_ACCESSOR_GC 0x1B01C0
|
||||
#define FS_OFFSET_2200_SDMMC_ACCESSOR_SD 0x1B21C0
|
||||
#define FS_OFFSET_2200_SDMMC_ACCESSOR_NAND 0x1B07F0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2200_SDMMC_WRAPPER_READ 0x1AC0F0
|
||||
#define FS_OFFSET_2200_SDMMC_WRAPPER_WRITE 0x1AC150
|
||||
#define FS_OFFSET_2200_RTLD 0x2DED0
|
||||
#define FS_OFFSET_2200_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2200_LOCK_MUTEX 0x1A4EF0
|
||||
#define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40
|
||||
|
||||
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0
|
||||
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AC0D0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2200_SD_MUTEX 0xFF1408
|
||||
#define FS_OFFSET_2200_NAND_MUTEX 0xFECD00
|
||||
#define FS_OFFSET_2200_ACTIVE_PARTITION 0xFECD40
|
||||
#define FS_OFFSET_2200_SDMMC_DAS_HANDLE 0xFCEB98
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2200_SD_DAS_INIT 0x2B438
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2200_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2200_H__
|
||||
59
emummc/source/FS/offsets/2200_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2200_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_2200_EXFAT_H__
|
||||
#define __FS_2200_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_GC 0x1BB3B0
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_SD 0x1BD3B0
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_ACCESSOR_NAND 0x1BB9E0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_READ 0x1B72E0
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_WRITE 0x1B7340
|
||||
#define FS_OFFSET_2200_EXFAT_RTLD 0x2DED0
|
||||
#define FS_OFFSET_2200_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2200_EXFAT_LOCK_MUTEX 0x1B00E0
|
||||
#define FS_OFFSET_2200_EXFAT_UNLOCK_MUTEX 0x1B0130
|
||||
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B72C0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2200_EXFAT_SD_MUTEX 0x1002408
|
||||
#define FS_OFFSET_2200_EXFAT_NAND_MUTEX 0xFFDD00
|
||||
#define FS_OFFSET_2200_EXFAT_ACTIVE_PARTITION 0xFFDD40
|
||||
#define FS_OFFSET_2200_EXFAT_SDMMC_DAS_HANDLE 0xFDBB98
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2200_EXFAT_SD_DAS_INIT 0x2B438
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2200_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2200_EXFAT_H__
|
||||
59
emummc/source/FS/offsets/2250.h
vendored
Normal file
59
emummc/source/FS/offsets/2250.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_2250_H__
|
||||
#define __FS_2250_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2250_SDMMC_ACCESSOR_GC 0x1B01C0
|
||||
#define FS_OFFSET_2250_SDMMC_ACCESSOR_SD 0x1B21C0
|
||||
#define FS_OFFSET_2250_SDMMC_ACCESSOR_NAND 0x1B07F0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2250_SDMMC_WRAPPER_READ 0x1AC0F0
|
||||
#define FS_OFFSET_2250_SDMMC_WRAPPER_WRITE 0x1AC150
|
||||
#define FS_OFFSET_2250_RTLD 0x2DED0
|
||||
#define FS_OFFSET_2250_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2250_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2250_LOCK_MUTEX 0x1A4EF0
|
||||
#define FS_OFFSET_2250_UNLOCK_MUTEX 0x1A4F40
|
||||
|
||||
#define FS_OFFSET_2250_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0
|
||||
#define FS_OFFSET_2250_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1AC0D0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2250_SD_MUTEX 0xFF1408
|
||||
#define FS_OFFSET_2250_NAND_MUTEX 0xFECD00
|
||||
#define FS_OFFSET_2250_ACTIVE_PARTITION 0xFECD40
|
||||
#define FS_OFFSET_2250_SDMMC_DAS_HANDLE 0xFCEB98
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2250_SD_DAS_INIT 0x2B438
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2250_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2250_H__
|
||||
59
emummc/source/FS/offsets/2250_exfat.h
vendored
Normal file
59
emummc/source/FS/offsets/2250_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_2250_EXFAT_H__
|
||||
#define __FS_2250_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_GC 0x1BB3B0
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_SD 0x1BD3B0
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_ACCESSOR_NAND 0x1BB9E0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_READ 0x1B72E0
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_WRITE 0x1B7340
|
||||
#define FS_OFFSET_2250_EXFAT_RTLD 0x2DED0
|
||||
#define FS_OFFSET_2250_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x4C)))
|
||||
|
||||
#define FS_OFFSET_2250_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_2250_EXFAT_LOCK_MUTEX 0x1B00E0
|
||||
#define FS_OFFSET_2250_EXFAT_UNLOCK_MUTEX 0x1B0130
|
||||
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1B72C0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_2250_EXFAT_SD_MUTEX 0x1002408
|
||||
#define FS_OFFSET_2250_EXFAT_NAND_MUTEX 0xFFDD00
|
||||
#define FS_OFFSET_2250_EXFAT_ACTIVE_PARTITION 0xFFDD40
|
||||
#define FS_OFFSET_2250_EXFAT_SDMMC_DAS_HANDLE 0xFDBB98
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_2250_EXFAT_SD_DAS_INIT 0x2B438
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_2250_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x000715EC, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00082E64, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x0008B888, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x000A1B1C, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_2250_EXFAT_H__
|
||||
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__
|
||||
@@ -70,6 +70,6 @@ clean:
|
||||
@$(MAKE) --no-print-directory -C $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere -f $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/libexosphere.mk clean
|
||||
@$(MAKE) --no-print-directory -C $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere -f $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/libexosphere.mk clean ATMOSPHERE_CPU="$(strip $(ATMOSPHERE_BOOT_CPU))"
|
||||
@rm -fr $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
@for i in $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||
@for i in $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR); do [ -d $$i ] && rmdir $$i 2>/dev/null || true; done
|
||||
|
||||
.PHONY: all clean check_lib check_boot_lib check_loader_stub check_program check_mariko_fatal check_warmboot
|
||||
@@ -119,7 +119,7 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
$(OUTPUT).lz4 : $(OUTPUT).bin
|
||||
@python $(CURRENT_DIRECTORY)/split_program.py $(OUTPUT).bin $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
$(SILENTCMD)$(PYTHON) $(CURRENT_DIRECTORY)/split_program.py $(OUTPUT).bin $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
|
||||
@@ -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 0x8C, 0x2E, 0xC1, 0x1C, 0xA0, 0x28, 0x35, 0xFC, 0x9A, 0x9F, 0x1D, 0x9B, 0x4E, 0xDF, 0x1E, 0x03
|
||||
.byte 0x2B, 0xCD, 0xE7, 0xA4, 0x93, 0x12, 0x0A, 0x72, 0x64, 0x2B, 0x9E, 0xA4, 0xC2, 0x9F, 0xED, 0x13
|
||||
|
||||
/* Mariko Production Master Kek Source. */
|
||||
.byte 0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A
|
||||
.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. */
|
||||
@@ -111,6 +111,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
|
||||
.byte 0x0C, 0x75, 0x39, 0x15, 0x53, 0xEA, 0x81, 0x11, 0xA3, 0xE0, 0xDC, 0x3D, 0x0E, 0x76, 0xC6, 0xB8 /* Master key 10 encrypted with Master key 11. */
|
||||
.byte 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 /* Master key 11 encrypted with Master key 12. */
|
||||
.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. */
|
||||
@@ -133,6 +136,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
|
||||
.byte 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 /* Master key 10 encrypted with Master key 11. */
|
||||
.byte 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 /* Master key 11 encrypted with Master key 12. */
|
||||
.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. */
|
||||
@@ -152,6 +158,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
|
||||
.byte 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 /* 18.0.0 Device Master Key Source Source. */
|
||||
.byte 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 /* 19.0.0 Device Master Key Source Source. */
|
||||
.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. */
|
||||
@@ -171,6 +180,9 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
|
||||
.byte 0x3B, 0x00, 0x89, 0xD7, 0xA9, 0x9E, 0xB7, 0x70, 0x86, 0x00, 0xC3, 0x49, 0x52, 0x8C, 0xA4, 0xAF /* 18.0.0 Device Master Kek Source. */
|
||||
.byte 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 /* 19.0.0 Device Master Kek Source. */
|
||||
.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. */
|
||||
@@ -189,4 +201,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
|
||||
.byte 0x21, 0xD6, 0x35, 0xF1, 0x0F, 0x7A, 0xF0, 0x5D, 0xDF, 0x79, 0x1C, 0x7A, 0xE4, 0x32, 0x82, 0x9E /* 17.0.0 Device Master Kek Source. */
|
||||
.byte 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B /* 18.0.0 Device Master Kek Source. */
|
||||
.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 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 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 == 20);
|
||||
static_assert(pkg1::KeyGeneration_Count == 23);
|
||||
if (key_generation >= pkg1::KeyGeneration_Count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -132,10 +132,13 @@ namespace ams::secmon::smc {
|
||||
}
|
||||
|
||||
u32 GetMemoryMode() {
|
||||
/* Unless development function is enabled, we're 4 GB. */
|
||||
/* Unless development function or forced boot config memory size is enabled, we're 4 GB. */
|
||||
u32 memory_mode = pkg1::MemoryMode_4GB;
|
||||
|
||||
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) {
|
||||
const auto &bcd = GetBootConfig().data;
|
||||
const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
|
||||
|
||||
if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
|
||||
memory_mode = GetMemoryMode(bcd.GetMemoryMode());
|
||||
}
|
||||
|
||||
@@ -146,17 +149,19 @@ namespace ams::secmon::smc {
|
||||
pkg1::MemorySize memory_size = pkg1::MemorySize_4GB;
|
||||
util::BitPack32 value = {};
|
||||
|
||||
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) {
|
||||
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
|
||||
const auto &bcd = GetBootConfig().data;
|
||||
const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
|
||||
|
||||
if (bcd.IsDevelopmentFunctionEnabled()) {
|
||||
value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1());
|
||||
value.Set<KernelConfiguration::Flags0>(bcd.GetKernelFlags0());
|
||||
}
|
||||
|
||||
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
|
||||
if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
|
||||
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
|
||||
}
|
||||
|
||||
/* Exosphere extensions. */
|
||||
const auto &sc = GetSecmonConfiguration();
|
||||
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
|
||||
|
||||
if (!sc.DisableUserModeExceptionHandlers()) {
|
||||
value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true);
|
||||
@@ -169,6 +174,27 @@ namespace ams::secmon::smc {
|
||||
return value.value;
|
||||
}
|
||||
|
||||
fuse::DramId GetDramIdAdjusted() {
|
||||
const auto dram_id = fuse::GetDramId();
|
||||
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count);
|
||||
|
||||
const auto fuse_mem_size = DramIdToMemorySize[dram_id];
|
||||
const auto phys_mem_size = GetPhysicalMemorySize();
|
||||
|
||||
AMS_ABORT_UNLESS(fuse_mem_size <= phys_mem_size);
|
||||
|
||||
if (fuse_mem_size == phys_mem_size) {
|
||||
return dram_id;
|
||||
}
|
||||
|
||||
/* Adjust Dram ID to match density/ranks. */
|
||||
if (GetSocType() == fuse::SocType_Erista) {
|
||||
return fuse::DramId_IcosaSamsung6GB;
|
||||
} else { /* fuse::SocType_Mariko */
|
||||
return fuse::DramId_IowaSamsung1y8GBX;
|
||||
}
|
||||
}
|
||||
|
||||
constinit u64 g_payload_address = 0;
|
||||
constinit bool g_set_true_target_firmware = false;
|
||||
|
||||
@@ -178,7 +204,7 @@ namespace ams::secmon::smc {
|
||||
args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled();
|
||||
break;
|
||||
case ConfigItem::DramId:
|
||||
args.r[1] = fuse::GetDramId();
|
||||
args.r[1] = GetDramIdAdjusted(); /* Nintendo: fuse::GetDramId() */
|
||||
break;
|
||||
case ConfigItem::SecurityEngineInterruptNumber:
|
||||
args.r[1] = SecurityEngineUserInterruptId;
|
||||
@@ -245,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) {
|
||||
@@ -471,9 +500,18 @@ namespace ams::secmon::smc {
|
||||
|
||||
/* For exosphere's usage. */
|
||||
pkg1::MemorySize GetPhysicalMemorySize() {
|
||||
const auto dram_id = fuse::GetDramId();
|
||||
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count);
|
||||
return DramIdToMemorySize[dram_id];
|
||||
const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
|
||||
const u32 mem_size = reg::Read(MC + MC_EMEM_CFG) & 0x3FFF;
|
||||
|
||||
switch (mem_size >> 10) {
|
||||
case 4:
|
||||
default:
|
||||
return pkg1::MemorySize_4GB;
|
||||
case 6:
|
||||
return pkg1::MemorySize_6GB;
|
||||
case 8:
|
||||
return pkg1::MemorySize_8GB;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace ams::secmon::smc {
|
||||
RegulatorType = 15,
|
||||
DeviceUniqueKeyGeneration = 16,
|
||||
Package2Hash = 17,
|
||||
Unknown18 = 18,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
|
||||
@@ -101,10 +101,10 @@ namespace ams::secmon::smc {
|
||||
#include "secmon_define_mc01_access_table.inc"
|
||||
|
||||
constexpr const AccessTableEntry AccessTables[] = {
|
||||
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
|
||||
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
|
||||
{ Mc01AccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
|
||||
{ Mc01AccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
|
||||
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
|
||||
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
|
||||
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
|
||||
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
|
||||
};
|
||||
|
||||
constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) {
|
||||
|
||||
@@ -43,6 +43,6 @@ clean:
|
||||
@$(MAKE) --no-print-directory -C $(CURRENT_DIRECTORY)/loader_stub -f $(CURRENT_DIRECTORY)/loader_stub/loader_stub.mk clean
|
||||
@$(MAKE) --no-print-directory -C $(CURRENT_DIRECTORY)/program -f $(CURRENT_DIRECTORY)/program/program.mk clean
|
||||
@rm -fr $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR)
|
||||
@for i in $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||
@for i in $(CURRENT_DIRECTORY)/$(ATMOSPHERE_OUT_DIR); do [ -d $$i ] && rmdir $$i 2>/dev/null || true; done
|
||||
|
||||
.PHONY: all clean check_lib check_loader_stub check_program
|
||||
@@ -84,7 +84,7 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
$(OUTPUT).lz4 : $(OUTPUT).bin
|
||||
@python $(CURRENT_DIRECTORY)/lz4_compress.py $(OUTPUT).bin $(OUTPUT).lz4
|
||||
$(SILENTCMD)$(PYTHON) $(CURRENT_DIRECTORY)/lz4_compress.py $(OUTPUT).bin $(OUTPUT).lz4
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
|
||||
@@ -602,7 +602,7 @@ namespace ams::nxboot {
|
||||
Print("\n");
|
||||
|
||||
if (R_SUCCEEDED(save_result)) {
|
||||
Print("Report saved to /atmosphere/fatal_errors/report_%016" PRIx64 ".bin", f_ctx->report_identifier);
|
||||
Print("Report saved to /atmosphere/fatal_errors/report_%016" PRIx64 ".bin\n", f_ctx->report_identifier);
|
||||
} else {
|
||||
Print("Failed to save report to the SD card! (%08" PRIx32 ")\n", save_result.GetValue());
|
||||
}
|
||||
|
||||
@@ -23,17 +23,17 @@ namespace ams::nxboot {
|
||||
|
||||
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = {
|
||||
/* TODO: Update on next change of keys. */
|
||||
0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A
|
||||
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. */
|
||||
0x8C, 0x2E, 0xC1, 0x1C, 0xA0, 0x28, 0x35, 0xFC, 0x9A, 0x9F, 0x1D, 0x9B, 0x4E, 0xDF, 0x1E, 0x03
|
||||
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. */
|
||||
0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8
|
||||
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] = {
|
||||
@@ -74,6 +74,9 @@ namespace ams::nxboot {
|
||||
{ 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 }, /* 18.0.0 Device Master Key Source Source. */
|
||||
{ 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 }, /* 19.0.0 Device Master Key Source Source. */
|
||||
{ 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] = {
|
||||
@@ -94,6 +97,9 @@ namespace ams::nxboot {
|
||||
{ 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B }, /* 18.0.0 Device Master Kek Source. */
|
||||
{ 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F }, /* 19.0.0 Device Master Kek Source. */
|
||||
{ 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] = {
|
||||
@@ -114,6 +120,9 @@ namespace ams::nxboot {
|
||||
{ 0x3B, 0x00, 0x89, 0xD7, 0xA9, 0x9E, 0xB7, 0x70, 0x86, 0x00, 0xC3, 0x49, 0x52, 0x8C, 0xA4, 0xAF }, /* 18.0.0 Device Master Kek Source. */
|
||||
{ 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 }, /* 19.0.0 Device Master Kek Source. */
|
||||
{ 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] = {
|
||||
@@ -137,6 +146,9 @@ namespace ams::nxboot {
|
||||
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 }, /* Master key 10 encrypted with Master key 11. */
|
||||
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 }, /* Master key 11 encrypted with Master key 12. */
|
||||
{ 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] = {
|
||||
@@ -160,6 +172,9 @@ namespace ams::nxboot {
|
||||
{ 0x0C, 0x75, 0x39, 0x15, 0x53, 0xEA, 0x81, 0x11, 0xA3, 0xE0, 0xDC, 0x3D, 0x0E, 0x76, 0xC6, 0xB8 }, /* Master key 10 encrypted with Master key 11. */
|
||||
{ 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 }, /* Master key 11 encrypted with Master key 12. */
|
||||
{ 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 == 20);
|
||||
static_assert(pkg1::KeyGeneration_Count == 23);
|
||||
if (key_generation >= pkg1::KeyGeneration_Count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -265,6 +265,12 @@ namespace ams::nxboot {
|
||||
return ams::TargetFirmware_19_0_0;
|
||||
} else if (std::memcmp(package1 + 0x10, "20250206", 8) == 0) {
|
||||
return ams::TargetFirmware_20_0_0;
|
||||
} else if (std::memcmp(package1 + 0x10, "20251009", 8) == 0) {
|
||||
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:
|
||||
@@ -409,8 +415,9 @@ namespace ams::nxboot {
|
||||
/* If we should, save the current warmboot firmware. */
|
||||
UpdateWarmbootPath(expected_fuses);
|
||||
if (!IsFileExist(warmboot_path)) {
|
||||
fs::CreateDirectory("sdmc:/warmboot_mariko");
|
||||
fs::CreateFile(warmboot_path, warmboot_src_size);
|
||||
/* Try to create the directory/file, allowing them to fail (if already exist). */
|
||||
static_cast<void>(fs::CreateDirectory("sdmc:/warmboot_mariko"));
|
||||
static_cast<void>(fs::CreateFile(warmboot_path, warmboot_src_size));
|
||||
|
||||
Result result;
|
||||
fs::FileHandle file;
|
||||
@@ -540,6 +547,12 @@ namespace ams::nxboot {
|
||||
} else {
|
||||
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess;
|
||||
}
|
||||
} else if (std::strcmp(entry.key, "enable_mem_mode") == 0) {
|
||||
if (entry.value[0] == '1') {
|
||||
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
|
||||
} else {
|
||||
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
|
||||
}
|
||||
} else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) {
|
||||
if (!emummc_enabled) {
|
||||
if (entry.value[0] == '1') {
|
||||
|
||||
@@ -183,6 +183,24 @@ namespace ams::nxboot {
|
||||
FsVersion_20_0_0,
|
||||
FsVersion_20_0_0_Exfat,
|
||||
|
||||
FsVersion_20_1_0,
|
||||
FsVersion_20_1_0_Exfat,
|
||||
|
||||
FsVersion_21_0_0,
|
||||
FsVersion_21_0_0_Exfat,
|
||||
|
||||
FsVersion_21_2_0,
|
||||
FsVersion_21_2_0_Exfat,
|
||||
|
||||
FsVersion_22_0_0,
|
||||
FsVersion_22_0_0_Exfat,
|
||||
|
||||
FsVersion_22_5_0,
|
||||
FsVersion_22_5_0_Exfat,
|
||||
|
||||
FsVersion_23_0_0,
|
||||
FsVersion_23_0_0_Exfat,
|
||||
|
||||
FsVersion_Count,
|
||||
};
|
||||
|
||||
@@ -278,6 +296,24 @@ namespace ams::nxboot {
|
||||
|
||||
{ 0x63, 0x54, 0x96, 0x9E, 0x60, 0xA7, 0x97, 0x7B }, /* FsVersion_20_0_0 */
|
||||
{ 0x47, 0x41, 0x07, 0x10, 0x65, 0x4F, 0xA4, 0x3F }, /* FsVersion_20_0_0_Exfat */
|
||||
|
||||
{ 0xED, 0x34, 0xB4, 0x50, 0x58, 0x4A, 0x5B, 0x43 }, /* FsVersion_20_1_0 */
|
||||
{ 0xA5, 0x1A, 0xA4, 0x92, 0x6C, 0x41, 0x87, 0x59 }, /* FsVersion_20_1_0_Exfat */
|
||||
|
||||
{ 0xEE, 0x4B, 0x30, 0x12, 0xA6, 0x84, 0x02, 0x25 }, /* FsVersion_21_0_0 */
|
||||
{ 0x6E, 0x2B, 0xD9, 0xBA, 0xA3, 0xB9, 0x10, 0xF1 }, /* FsVersion_21_0_0_Exfat */
|
||||
|
||||
{ 0xAF, 0x1D, 0xBD, 0xC7, 0x82, 0x98, 0x3C, 0xBD }, /* FsVersion_21_2_0 */
|
||||
{ 0x56, 0x25, 0x17, 0xA1, 0x92, 0xC3, 0xC8, 0xF0 }, /* FsVersion_21_2_0_Exfat */
|
||||
|
||||
{ 0xB7, 0xA2, 0x97, 0x39, 0xB7, 0xED, 0xDE, 0xFC }, /* FsVersion_22_0_0 */
|
||||
{ 0xFB, 0x0B, 0x68, 0xDB, 0x24, 0x03, 0xD1, 0x19 }, /* FsVersion_22_0_0_Exfat */
|
||||
|
||||
{ 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) {
|
||||
@@ -668,15 +704,51 @@ namespace ams::nxboot {
|
||||
AddPatch(fs_meta, 0x17A9A0, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_20_0_0:
|
||||
case FsVersion_20_1_0:
|
||||
AddPatch(fs_meta, 0x1A7E25, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x1A8025, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x17C250, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_20_0_0_Exfat:
|
||||
case FsVersion_20_1_0_Exfat:
|
||||
AddPatch(fs_meta, 0x1B3745, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x1B3945, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x187B70, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_21_0_0:
|
||||
case FsVersion_21_2_0:
|
||||
AddPatch(fs_meta, 0x1AC9ED, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x1ACA05, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x17FBE0, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_21_0_0_Exfat:
|
||||
case FsVersion_21_2_0_Exfat:
|
||||
AddPatch(fs_meta, 0x1B7B4D, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x1B7B65, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x18AD40, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_22_0_0:
|
||||
case FsVersion_22_5_0:
|
||||
AddPatch(fs_meta, 0x1B023D, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x1B0255, NogcPatch0, sizeof(NogcPatch0));
|
||||
AddPatch(fs_meta, 0x183060, NogcPatch1, sizeof(NogcPatch1));
|
||||
break;
|
||||
case FsVersion_22_0_0_Exfat:
|
||||
case FsVersion_22_5_0_Exfat:
|
||||
AddPatch(fs_meta, 0x1BB42D, NogcPatch0, sizeof(NogcPatch0));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1355,6 +1355,9 @@ namespace ams::nxboot {
|
||||
uint32_t emc_zcal_wait_cnt_new = dst_timing->burst_regs.emc_zcal_wait_cnt;
|
||||
emc_zcal_wait_cnt_old &= ~0x7ff;
|
||||
emc_zcal_wait_cnt_new &= ~0x7ff;
|
||||
|
||||
/* TODO: Unused variable. */
|
||||
AMS_UNUSED(emc_zcal_wait_cnt_old);
|
||||
|
||||
if (dram_type == DRAM_TYPE_LPDDR4) {
|
||||
zq_wait_long = std::max<u32>(1, util::DivideUp(1000000, destination_clock_period));
|
||||
|
||||
BIN
img/np++.png
Normal file
BIN
img/np++.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = 9e8cbe3faa4604e9ae162546d13a74755ce30667
|
||||
parent = 4d4f0ba96876d20e505c7aa11c9bf215f276dd8b
|
||||
commit = aae2da0155a490abd3bfd17a70ccd16bb73c916a
|
||||
parent = c68e08a101353a89777eb118d6bd21d1dba98ce5
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
cmdver = 0.4.9
|
||||
|
||||
@@ -297,6 +297,23 @@ FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arc
|
||||
|
||||
ATMOSPHERE_GCH_IDENTIFIER := $(ATMOSPHERE_FULL_NAME)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Python. The scripts should work with Python 2 or 3, but 2 is preferred.
|
||||
#---------------------------------------------------------------------------------
|
||||
PYTHON = $(shell command -v python >/dev/null && echo python || echo python3)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Export MAKE:
|
||||
# GCC's LTO driver invokes Make internally. This invocation respects both $(MAKE)
|
||||
# and $(MAKEFLAGS), but only if they're in the environment. By default, MAKEFLAGS
|
||||
# is in the environment while MAKE isn't, so GCC will always use the default
|
||||
# `make` command, yet it inherits MAKEFLAGS from the copy of Make the user
|
||||
# invoked, which might have incompatible flags. In practice this is an issue on
|
||||
# macOS when running e.g. `gmake -j32 -Otarget`. This behavior is arguably a bug
|
||||
# in GCC and/or Make, but we can work around it by exporting MAKE.
|
||||
#---------------------------------------------------------------------------------
|
||||
export MAKE
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Rules for compiling pre-compiled headers
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
@@ -26,7 +26,7 @@ ATMOSPHERE_OPTIMIZATION_FLAG := -O2
|
||||
endif
|
||||
|
||||
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||
export SETTINGS = $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -Wno-missing-field-initializers
|
||||
export SETTINGS = $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -Wno-missing-field-initializers -Wno-error=unused-result
|
||||
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||
export ASFLAGS = $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -40,6 +40,9 @@ namespace ams::pkg1 {
|
||||
KeyGeneration_18_0_0 = 0x11,
|
||||
KeyGeneration_19_0_0 = 0x12,
|
||||
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'>;
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace ams::secmon {
|
||||
SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5),
|
||||
SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6),
|
||||
SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7),
|
||||
SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled = (1u << 8),
|
||||
|
||||
SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel,
|
||||
};
|
||||
@@ -103,6 +104,7 @@ namespace ams::secmon {
|
||||
constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; }
|
||||
constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; }
|
||||
constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; }
|
||||
constexpr bool IsBootConfigMemoryModeEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled) != 0; }
|
||||
|
||||
constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); }
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ clean:
|
||||
@echo clean $(ATMOSPHERE_BUILD_NAME) ...
|
||||
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_OUT_DIR)
|
||||
@rm -fr $(foreach hdr,$(GCH_DIRS),$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
|
||||
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir $$i 2>/dev/null || true; done
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
@@ -177,6 +177,9 @@ namespace ams::fuse {
|
||||
}
|
||||
|
||||
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
|
||||
TargetFirmware_23_0_0,
|
||||
TargetFirmware_22_0_0,
|
||||
TargetFirmware_21_0_0,
|
||||
TargetFirmware_20_0_0,
|
||||
TargetFirmware_19_0_0,
|
||||
TargetFirmware_17_0_0,
|
||||
|
||||
@@ -104,7 +104,10 @@ namespace ams::se {
|
||||
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 0) : 0;
|
||||
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 1) : 0;
|
||||
value |= ((flags & KeySlotLockFlags_KeyRead) == 0) ? (1u << 2) : 0;
|
||||
|
||||
|
||||
/* TODO: Unused variable. */
|
||||
AMS_UNUSED(value);
|
||||
|
||||
reg::Write(SE->SE_RSA_KEYTABLE_ACCESS[slot], SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYREAD, (flags & KeySlotLockFlags_KeyRead) != 0, DISABLE, ENABLE),
|
||||
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUPDATE, (flags & KeySlotLockFlags_KeyWrite) != 0, DISABLE, ENABLE),
|
||||
SE_REG_BITS_ENUM_SEL(RSA_KEYTABLE_ACCESS_KEYUSE, (flags & KeySlotLockFlags_KeyUse) != 0, DISABLE, ENABLE));
|
||||
|
||||
@@ -116,7 +116,9 @@ namespace ams::kern::arch::arm {
|
||||
u32 ipriorityr[NumLocalInterrupts / 4];
|
||||
u32 itargetsr[NumLocalInterrupts / 4];
|
||||
u32 icfgr[NumLocalInterrupts / 16];
|
||||
u32 spendsgir[4];
|
||||
};
|
||||
static_assert(sizeof(LocalState{}.spendsgir) == sizeof(GicDistributor{}.spendsgir));
|
||||
|
||||
struct GlobalState {
|
||||
u32 isenabler[NumGlobalInterrupts / 32];
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -83,9 +83,9 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
NOINLINE Result BindHandler(KInterruptHandler *handler, s32 irq, s32 core_id, s32 priority, bool manual_clear, bool level);
|
||||
NOINLINE Result UnbindHandler(s32 irq, s32 core);
|
||||
NOINLINE void UnbindHandler(s32 irq, s32 core);
|
||||
|
||||
NOINLINE Result ClearInterrupt(s32 irq, s32 core_id);
|
||||
NOINLINE void ClearInterrupt(s32 irq, s32 core_id);
|
||||
|
||||
ALWAYS_INLINE void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
|
||||
m_interrupt_controller.SendInterProcessorInterrupt(irq, core_mask);
|
||||
@@ -99,10 +99,10 @@ namespace ams::kern::arch::arm64 {
|
||||
private:
|
||||
Result BindGlobal(KInterruptHandler *handler, s32 irq, s32 core_id, s32 priority, bool manual_clear, bool level);
|
||||
Result BindLocal(KInterruptHandler *handler, s32 irq, s32 priority, bool manual_clear);
|
||||
Result UnbindGlobal(s32 irq);
|
||||
Result UnbindLocal(s32 irq);
|
||||
Result ClearGlobal(s32 irq);
|
||||
Result ClearLocal(s32 irq);
|
||||
void UnbindGlobal(s32 irq);
|
||||
void UnbindLocal(s32 irq);
|
||||
void ClearGlobal(s32 irq);
|
||||
void ClearLocal(s32 irq);
|
||||
private:
|
||||
[[nodiscard]] static ALWAYS_INLINE u32 GetInterruptsEnabledState() {
|
||||
u64 intr_state;
|
||||
|
||||
@@ -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);
|
||||
@@ -197,9 +204,9 @@ namespace ams::kern::arch::arm64 {
|
||||
cpu::SwitchProcess(s_ttbr0_entries[proc_idx + 1], proc_id);
|
||||
}
|
||||
|
||||
NOINLINE Result 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);
|
||||
Result Finalize();
|
||||
NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
||||
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) {
|
||||
/* Note the update. */
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace ams::kern::arch::arm64 {
|
||||
constexpr explicit KThreadContext(util::ConstantInitializeTag) : m_callee_saved(), m_lr(), m_sp(), m_fpcr(), m_fpsr(), m_callee_saved_fpu(), m_locked() { /* ... */ }
|
||||
explicit KThreadContext() { /* ... */ }
|
||||
|
||||
Result Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
|
||||
void Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
|
||||
|
||||
void SetArguments(uintptr_t arg0, uintptr_t arg1);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace ams::kern::arch::arm64 {
|
||||
static bool CopyMemoryToUser(void *dst, const void *src, size_t size);
|
||||
static bool CopyMemoryToUserAligned32Bit(void *dst, const void *src, size_t size);
|
||||
static bool CopyMemoryToUserAligned64Bit(void *dst, const void *src, size_t size);
|
||||
static bool CopyMemoryToUserSize32Bit(void *dst, const void *src);
|
||||
static bool CopyMemoryToUserSize32Bit(void *dst, u32 value);
|
||||
static s32 CopyStringToUser(void *dst, const void *src, size_t size);
|
||||
|
||||
static bool UpdateLockAtomic(u32 *out, u32 *address, u32 if_zero, u32 new_orr_mask);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ namespace ams::kern::arch::arm64 {
|
||||
return Impl::CopyMemoryToUserAligned64Bit(dst, src, size);
|
||||
}
|
||||
|
||||
static bool CopyMemoryToUserSize32Bit(void *dst, const void *src) {
|
||||
return Impl::CopyMemoryToUserSize32Bit(dst, src);
|
||||
static bool CopyMemoryToUserSize32Bit(void *dst, u32 value) {
|
||||
return Impl::CopyMemoryToUserSize32Bit(dst, value);
|
||||
}
|
||||
|
||||
static s32 CopyStringToUser(void *dst, const void *src, size_t size) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -47,13 +47,6 @@
|
||||
/* re-enabled by toggling this define. */
|
||||
//#define MESOSPHERE_ENABLE_PROCESS_CREATION_TIME
|
||||
|
||||
/* NOTE: This enables fast class token storage using a class member. */
|
||||
/* This saves a virtual call when doing KAutoObject->DynCast<>(), */
|
||||
/* at the cost of storing class tokens inside the class object. */
|
||||
/* However, as of (10/16/2021) KAutoObject has an unused class member */
|
||||
/* of the right side, and so this does not actually cost any space. */
|
||||
#define MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST
|
||||
|
||||
/* NOTE: This enables usage of KDebug handles as parameter for svc::GetInfo */
|
||||
/* calls which require a process parameter. This enables a debugger to obtain */
|
||||
/* address space/layout information, for example. However, it changes abi, and so */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -121,14 +121,9 @@ namespace ams::kern {
|
||||
private:
|
||||
KAutoObject *m_next_closed_object;
|
||||
ReferenceCount m_ref_count;
|
||||
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||
ClassTokenType m_class_token;
|
||||
#endif
|
||||
public:
|
||||
constexpr ALWAYS_INLINE explicit KAutoObject(util::ConstantInitializeTag) : m_next_closed_object(nullptr), m_ref_count(0)
|
||||
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||
, m_class_token(0)
|
||||
#endif
|
||||
constexpr ALWAYS_INLINE explicit KAutoObject(util::ConstantInitializeTag) : m_next_closed_object(nullptr), m_ref_count(0), m_class_token(0)
|
||||
{
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
}
|
||||
@@ -151,19 +146,11 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) const {
|
||||
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken());
|
||||
#else
|
||||
return this->GetTypeObj().IsDerivedFrom(rhs);
|
||||
#endif
|
||||
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsDerivedFrom(const KAutoObject &rhs) const {
|
||||
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token);
|
||||
#else
|
||||
return this->IsDerivedFrom(rhs.GetTypeObj());
|
||||
#endif
|
||||
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
@@ -218,12 +205,10 @@ namespace ams::kern {
|
||||
KAutoObject &auto_object = *static_cast<KAutoObject *>(obj);
|
||||
|
||||
/* If we should, set our class token. */
|
||||
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||
{
|
||||
constexpr auto Token = Derived::GetStaticTypeObj().GetClassToken();
|
||||
auto_object.m_class_token = Token;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize reference count to 1. */
|
||||
auto_object.m_ref_count = 1;
|
||||
|
||||
@@ -93,9 +93,9 @@ namespace ams::kern {
|
||||
static Result ProcessDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
|
||||
public:
|
||||
static Result OnDebugEvent(ams::svc::DebugEvent event, const uintptr_t *params, size_t num_params);
|
||||
static Result OnExitProcess(KProcess *process);
|
||||
static Result OnTerminateProcess(KProcess *process);
|
||||
static Result OnExitThread(KThread *thread);
|
||||
static void OnExitProcess(KProcess *process);
|
||||
static void OnTerminateProcess(KProcess *process);
|
||||
static void OnExitThread(KThread *thread);
|
||||
static KEventInfo *CreateDebugEvent(ams::svc::DebugEvent event, u64 thread_id, const uintptr_t *params, size_t num_params);
|
||||
};
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace ams::kern {
|
||||
|
||||
KReadableEvent &GetReadableEvent() { return m_readable_event; }
|
||||
|
||||
Result Signal();
|
||||
Result Clear();
|
||||
void Signal();
|
||||
void Clear();
|
||||
|
||||
ALWAYS_INLINE void OnReadableEventDestroyed() { m_readable_event_destroyed = true; }
|
||||
};
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace ams::kern {
|
||||
constexpr ALWAYS_INLINE size_t GetCount() const { return m_count; }
|
||||
constexpr ALWAYS_INLINE size_t GetMaxCount() const { return m_max_count; }
|
||||
|
||||
MESOSPHERE_NOINLINE_IF_DEBUG Result Finalize();
|
||||
MESOSPHERE_NOINLINE_IF_DEBUG void Finalize();
|
||||
MESOSPHERE_NOINLINE_IF_DEBUG bool Remove(ams::svc::Handle handle);
|
||||
|
||||
template<typename T = KAutoObject>
|
||||
|
||||
@@ -38,13 +38,11 @@ namespace ams::kern {
|
||||
|
||||
Result Reset();
|
||||
|
||||
Result Clear() {
|
||||
void Clear() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Try to perform a reset, succeeding unconditionally. */
|
||||
this->Reset();
|
||||
|
||||
R_SUCCEED();
|
||||
/* Try to perform a reset, ignoring whether it succeeds. */
|
||||
static_cast<void>(this->Reset());
|
||||
}
|
||||
|
||||
bool IsInitialized() const { return m_is_initialized; }
|
||||
|
||||
@@ -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,10 +197,10 @@ 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;
|
||||
bool m_allowed_exec_device_mapping;
|
||||
KMemoryBlockSlabManager *m_memory_block_slab_manager;
|
||||
KBlockInfoManager *m_block_info_manager;
|
||||
KResourceLimit *m_resource_limit;
|
||||
@@ -211,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_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 Result 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();
|
||||
|
||||
@@ -246,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);
|
||||
@@ -489,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; }
|
||||
|
||||
@@ -520,6 +540,8 @@ namespace ams::kern {
|
||||
size_t GetAliasCodeDataSize() const;
|
||||
|
||||
u32 GetAllocateOption() const { return m_allocate_option; }
|
||||
|
||||
void AllowDeviceMappingOfExecPages() { m_allowed_exec_device_mapping = true; }
|
||||
public:
|
||||
static ALWAYS_INLINE KVirtualAddress GetLinearMappedVirtualAddress(KPhysicalAddress addr) {
|
||||
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
||||
|
||||
@@ -102,8 +102,8 @@ namespace ams::kern {
|
||||
IoRegionList m_io_region_list;
|
||||
bool m_is_suspended;
|
||||
bool m_is_immortal;
|
||||
bool m_is_jit_debug;
|
||||
bool m_is_handle_table_initialized;
|
||||
bool m_is_jit_debug;
|
||||
ams::svc::DebugEvent m_jit_debug_event_type;
|
||||
ams::svc::DebugException m_jit_debug_exception_type;
|
||||
uintptr_t m_jit_debug_params[4];
|
||||
@@ -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; }
|
||||
@@ -269,7 +274,7 @@ namespace ams::kern {
|
||||
void RemoveIoRegion(KIoRegion *io_region);
|
||||
|
||||
Result CreateThreadLocalRegion(KProcessAddress *out);
|
||||
Result DeleteThreadLocalRegion(KProcessAddress addr);
|
||||
void DeleteThreadLocalRegion(KProcessAddress addr);
|
||||
void *GetThreadLocalRegionPointer(KProcessAddress addr);
|
||||
|
||||
constexpr KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; }
|
||||
@@ -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. */
|
||||
|
||||
@@ -35,16 +35,14 @@ namespace ams::kern {
|
||||
|
||||
constexpr KEvent *GetParent() const { return m_parent; }
|
||||
|
||||
Result Signal();
|
||||
void Signal();
|
||||
Result Reset();
|
||||
|
||||
Result Clear() {
|
||||
void Clear() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Try to perform a reset, succeeding unconditionally. */
|
||||
this->Reset();
|
||||
|
||||
R_SUCCEED();
|
||||
/* Try to perform a reset, ignoring whether it succeeds. */
|
||||
static_cast<void>(this->Reset());
|
||||
}
|
||||
|
||||
virtual bool IsSignaled() const override;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -105,7 +106,7 @@ namespace ams::kern {
|
||||
util::Atomic<u8> dpc_flags;
|
||||
u8 current_svc_id;
|
||||
u8 reserved_2c;
|
||||
u8 exception_flags;
|
||||
util::Atomic<u8> exception_flags;
|
||||
bool is_pinned;
|
||||
u8 reserved_2f;
|
||||
u8 reserved_30[0x10];
|
||||
@@ -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{}
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -417,17 +421,17 @@ namespace ams::kern {
|
||||
private:
|
||||
ALWAYS_INLINE void SetExceptionFlag(ExceptionFlag flag) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
this->GetStackParameters().exception_flags |= flag;
|
||||
this->GetStackParameters().exception_flags.FetchOr<std::memory_order_relaxed>(flag);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void ClearExceptionFlag(ExceptionFlag flag) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
this->GetStackParameters().exception_flags &= ~flag;
|
||||
this->GetStackParameters().exception_flags.FetchAnd<std::memory_order_relaxed>(~flag);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsExceptionFlagSet(ExceptionFlag flag) const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
return this->GetStackParameters().exception_flags & flag;
|
||||
return this->GetStackParameters().exception_flags.Load<std::memory_order_relaxed>() & flag;
|
||||
}
|
||||
public:
|
||||
/* ALWAYS_INLINE void SetCallingSvc() { return this->SetExceptionFlag(ExceptionFlag_IsCallingSvc); } */
|
||||
@@ -523,7 +527,7 @@ namespace ams::kern {
|
||||
Result GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
Result SetCoreMask(int32_t ideal_core, u64 affinity_mask);
|
||||
|
||||
Result GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
void GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
|
||||
constexpr ThreadState GetState() const { return static_cast<ThreadState>(m_thread_state & ThreadState_Mask); }
|
||||
constexpr ThreadState GetRawState() const { return m_thread_state; }
|
||||
@@ -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? */
|
||||
@@ -717,7 +724,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void SetBasePriority(s32 priority);
|
||||
Result SetPriorityToIdle();
|
||||
void SetPriorityToIdle();
|
||||
|
||||
Result Run();
|
||||
void Exit();
|
||||
@@ -725,7 +732,7 @@ namespace ams::kern {
|
||||
Result Terminate();
|
||||
ThreadState RequestTerminate();
|
||||
|
||||
Result Sleep(s64 timeout);
|
||||
void Sleep(s64 timeout);
|
||||
|
||||
ALWAYS_INLINE void *GetStackTop() const { return reinterpret_cast<StackParameters *>(m_kernel_stack_top) - 1; }
|
||||
ALWAYS_INLINE void *GetKernelStackTop() const { return m_kernel_stack_top; }
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ams::kern {
|
||||
}
|
||||
public:
|
||||
Result Initialize(KProcess *process);
|
||||
Result Finalize();
|
||||
void Finalize();
|
||||
|
||||
KProcessAddress Reserve();
|
||||
void Release(KProcessAddress addr);
|
||||
|
||||
@@ -86,7 +86,7 @@ clean:
|
||||
@echo clean $(ATMOSPHERE_BUILD_NAME) ...
|
||||
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_OUT_DIR)
|
||||
@rm -fr $(foreach hdr,$(GCH_DIRS),$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
|
||||
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
|
||||
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir $$i 2>/dev/null || true; done
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@@ -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
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace ams::kern::arch::arm {
|
||||
constexpr size_t Offset = 0;
|
||||
state->icfgr[i] = m_gicd->icfgr[i + Offset];
|
||||
}
|
||||
|
||||
/* Save spendsgir. */
|
||||
for (size_t i = 0; i < util::size(state->spendsgir); ++i) {
|
||||
state->spendsgir[i] = m_gicd->spendsgir[i];
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::SaveGlobal(GlobalState *state) const {
|
||||
@@ -168,6 +173,11 @@ namespace ams::kern::arch::arm {
|
||||
m_gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
m_gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
}
|
||||
|
||||
/* Restore spendsgir. */
|
||||
for (size_t i = 0; i < util::size(state->spendsgir); ++i) {
|
||||
m_gicd->spendsgir[i] = state->spendsgir[i];
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::RestoreGlobal(const GlobalState *state) const {
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
class KCoreBarrierInterruptHandler : public KInterruptHandler {
|
||||
private:
|
||||
util::Atomic<u64> m_target_cores;
|
||||
KSpinLock m_lock;
|
||||
KLightLock m_lock;
|
||||
public:
|
||||
constexpr KCoreBarrierInterruptHandler() : KInterruptHandler(), m_target_cores(0), m_lock() { /* ... */ }
|
||||
|
||||
@@ -123,11 +123,8 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
}
|
||||
|
||||
void SynchronizeCores(u64 core_mask) {
|
||||
/* Disable dispatch while we synchronize. */
|
||||
KScopedDisableDispatch dd;
|
||||
|
||||
/* Acquire exclusive access to ourselves. */
|
||||
KScopedSpinLock lk(m_lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* If necessary, force synchronization with other cores. */
|
||||
if (const u64 other_cores_mask = core_mask & ~(1ul << GetCurrentCoreId()); other_cores_mask != 0) {
|
||||
@@ -218,11 +215,13 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
KThread::Register(new_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
new_thread->Run();
|
||||
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -511,16 +510,16 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
g_cache_operation_handler.Initialize(core_id);
|
||||
|
||||
/* Bind all handlers to the relevant interrupts. */
|
||||
Kernel::GetInterruptManager().BindHandler(std::addressof(g_cache_operation_handler), KInterruptName_CacheOperation, core_id, KInterruptController::PriorityLevel_High, false, false);
|
||||
Kernel::GetInterruptManager().BindHandler(std::addressof(g_thread_termination_handler), KInterruptName_ThreadTerminate, core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
|
||||
Kernel::GetInterruptManager().BindHandler(std::addressof(g_core_barrier_handler), KInterruptName_CoreBarrier, core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_cache_operation_handler), KInterruptName_CacheOperation, core_id, KInterruptController::PriorityLevel_High, false, false));
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_thread_termination_handler), KInterruptName_ThreadTerminate, core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_core_barrier_handler), KInterruptName_CoreBarrier, core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
|
||||
|
||||
/* If we should, enable user access to the performance counter registers. */
|
||||
if (KTargetSystem::IsUserPmuAccessEnabled()) { SetPmUserEnrEl0(1ul); }
|
||||
|
||||
/* If we should, enable the kernel performance counter interrupt handler. */
|
||||
#if defined(MESOSPHERE_ENABLE_PERFORMANCE_COUNTER)
|
||||
Kernel::GetInterruptManager().BindHandler(std::addressof(g_performance_counter_handler[core_id]), KInterruptName_PerformanceCounter, core_id, KInterruptController::PriorityLevel_Timer, false, false);
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_performance_counter_handler[core_id]), KInterruptName_PerformanceCounter, core_id, KInterruptController::PriorityLevel_Timer, false, false));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
|
||||
m_maximum_time = static_cast<s64>(std::min<u64>(std::numeric_limits<s64>::max(), cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor().GetCompareValue()));
|
||||
|
||||
/* Bind the interrupt task for this core. */
|
||||
Kernel::GetInterruptManager().BindHandler(this, KInterruptName_NonSecurePhysicalTimer, GetCurrentCoreId(), KInterruptController::PriorityLevel_Timer, true, true);
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(this, KInterruptName_NonSecurePhysicalTimer, GetCurrentCoreId(), KInterruptController::PriorityLevel_Timer, true, true));
|
||||
}
|
||||
|
||||
void KHardwareTimer::Finalize() {
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace ams::kern::arch::arm64 {
|
||||
if (entry.handler != nullptr) {
|
||||
/* Set manual clear needed if relevant. */
|
||||
if (entry.manually_cleared) {
|
||||
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
m_interrupt_controller.Disable(irq);
|
||||
entry.needs_clear = true;
|
||||
}
|
||||
|
||||
@@ -242,40 +242,40 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
}
|
||||
|
||||
Result KInterruptManager::UnbindHandler(s32 irq, s32 core_id) {
|
||||
void KInterruptManager::UnbindHandler(s32 irq, s32 core_id) {
|
||||
MESOSPHERE_UNUSED(core_id);
|
||||
|
||||
R_UNLESS(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq), svc::ResultOutOfRange());
|
||||
MESOSPHERE_ASSERT(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq));
|
||||
|
||||
|
||||
if (KInterruptController::IsGlobal(irq)) {
|
||||
KScopedInterruptDisable di;
|
||||
|
||||
KScopedSpinLock lk(this->GetGlobalInterruptLock());
|
||||
R_RETURN(this->UnbindGlobal(irq));
|
||||
} else {
|
||||
return this->UnbindGlobal(irq);
|
||||
} else if (KInterruptController::IsLocal(irq)) {
|
||||
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
|
||||
|
||||
KScopedInterruptDisable di;
|
||||
R_RETURN(this->UnbindLocal(irq));
|
||||
return this->UnbindLocal(irq);
|
||||
}
|
||||
}
|
||||
|
||||
Result KInterruptManager::ClearInterrupt(s32 irq, s32 core_id) {
|
||||
void KInterruptManager::ClearInterrupt(s32 irq, s32 core_id) {
|
||||
MESOSPHERE_UNUSED(core_id);
|
||||
|
||||
R_UNLESS(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq), svc::ResultOutOfRange());
|
||||
MESOSPHERE_ASSERT(KInterruptController::IsGlobal(irq) || KInterruptController::IsLocal(irq));
|
||||
|
||||
|
||||
if (KInterruptController::IsGlobal(irq)) {
|
||||
KScopedInterruptDisable di;
|
||||
KScopedSpinLock lk(this->GetGlobalInterruptLock());
|
||||
R_RETURN(this->ClearGlobal(irq));
|
||||
} else {
|
||||
return this->ClearGlobal(irq);
|
||||
} else if (KInterruptController::IsLocal(irq)) {
|
||||
MESOSPHERE_ASSERT(core_id == GetCurrentCoreId());
|
||||
|
||||
KScopedInterruptDisable di;
|
||||
R_RETURN(this->ClearLocal(irq));
|
||||
return this->ClearLocal(irq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ namespace ams::kern::arch::arm64 {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KInterruptManager::UnbindGlobal(s32 irq) {
|
||||
void KInterruptManager::UnbindGlobal(s32 irq) {
|
||||
for (size_t core_id = 0; core_id < cpu::NumCores; core_id++) {
|
||||
m_interrupt_controller.ClearTarget(irq, static_cast<s32>(core_id));
|
||||
}
|
||||
@@ -340,50 +340,35 @@ namespace ams::kern::arch::arm64 {
|
||||
m_interrupt_controller.Disable(irq);
|
||||
|
||||
GetGlobalInterruptEntry(irq).handler = nullptr;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KInterruptManager::UnbindLocal(s32 irq) {
|
||||
auto &entry = this->GetLocalInterruptEntry(irq);
|
||||
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
|
||||
|
||||
void KInterruptManager::UnbindLocal(s32 irq) {
|
||||
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
m_interrupt_controller.Disable(irq);
|
||||
|
||||
entry.handler = nullptr;
|
||||
|
||||
R_SUCCEED();
|
||||
this->GetLocalInterruptEntry(irq).handler = nullptr;
|
||||
}
|
||||
|
||||
Result KInterruptManager::ClearGlobal(s32 irq) {
|
||||
/* We can't clear an entry with no handler. */
|
||||
void KInterruptManager::ClearGlobal(s32 irq) {
|
||||
/* Get the entry. */
|
||||
auto &entry = GetGlobalInterruptEntry(irq);
|
||||
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
|
||||
|
||||
/* If auto-cleared, we can succeed immediately. */
|
||||
R_SUCCEED_IF(!entry.manually_cleared);
|
||||
R_SUCCEED_IF(!entry.needs_clear);
|
||||
|
||||
/* Clear and enable. */
|
||||
entry.needs_clear = false;
|
||||
m_interrupt_controller.Enable(irq);
|
||||
R_SUCCEED();
|
||||
/* If not auto-cleared, clear and enable. */
|
||||
if (entry.manually_cleared && entry.needs_clear) {
|
||||
entry.needs_clear = false;
|
||||
m_interrupt_controller.Enable(irq);
|
||||
}
|
||||
}
|
||||
|
||||
Result KInterruptManager::ClearLocal(s32 irq) {
|
||||
/* We can't clear an entry with no handler. */
|
||||
void KInterruptManager::ClearLocal(s32 irq) {
|
||||
/* Get the entry. */
|
||||
auto &entry = this->GetLocalInterruptEntry(irq);
|
||||
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
|
||||
|
||||
/* If auto-cleared, we can succeed immediately. */
|
||||
R_SUCCEED_IF(!entry.manually_cleared);
|
||||
R_SUCCEED_IF(!entry.needs_clear);
|
||||
|
||||
/* Clear and set priority. */
|
||||
entry.needs_clear = false;
|
||||
m_interrupt_controller.SetPriorityLevel(irq, entry.priority);
|
||||
R_SUCCEED();
|
||||
/* If not auto-cleared, clear and enable. */
|
||||
if (entry.manually_cleared && entry.needs_clear) {
|
||||
entry.needs_clear = false;
|
||||
m_interrupt_controller.Enable(irq);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -119,18 +119,16 @@ namespace ams::kern::arch::arm64 {
|
||||
MESOSPHERE_UNUSED(core_id);
|
||||
}
|
||||
|
||||
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
void KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
/* Initialize basic fields. */
|
||||
m_asid = 0;
|
||||
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
|
||||
|
||||
/* Initialize the base page table. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(KPageTableBase::InitializeForKernel(true, table, start, end));
|
||||
|
||||
R_SUCCEED();
|
||||
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));
|
||||
@@ -146,14 +144,14 @@ 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();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KPageTable::Finalize() {
|
||||
void KPageTable::Finalize() {
|
||||
/* Only process tables should be finalized. */
|
||||
MESOSPHERE_ASSERT(!this->IsKernel());
|
||||
|
||||
@@ -271,8 +269,6 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Perform inherited finalization. */
|
||||
KPageTableBase::Finalize();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KPageTable::OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) {
|
||||
@@ -733,6 +729,9 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
}
|
||||
MESOSPHERE_ASSERT(mapped_pages == num_pages);
|
||||
|
||||
/* TODO: Unused variable. */
|
||||
AMS_UNUSED(mapped_pages);
|
||||
|
||||
/* Perform what coalescing we can. */
|
||||
this->MergePages(orig_virt_addr, num_pages, page_list);
|
||||
@@ -942,7 +941,7 @@ namespace ams::kern::arch::arm64 {
|
||||
/* If we should flush entries, do so. */
|
||||
if ((apply_option & ApplyOption_FlushDataCache) != 0) {
|
||||
if (IsHeapPhysicalAddress(next_entry.phys_addr)) {
|
||||
cpu::FlushDataCache(GetVoidPointer(GetHeapVirtualAddress(next_entry.phys_addr)), next_entry.block_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(GetVoidPointer(GetHeapVirtualAddress(next_entry.phys_addr)), next_entry.block_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ams::kern::arch::arm64 {
|
||||
KScopedInterruptEnable ei;
|
||||
|
||||
const uintptr_t params[2] = { GetCurrentThread().GetId(), GetInteger(GetCurrentThread().GetThreadLocalRegionAddress()) };
|
||||
KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, params, util::size(params));
|
||||
static_cast<void>(KDebug::OnDebugEvent(ams::svc::DebugEvent_CreateThread, params, util::size(params)));
|
||||
}
|
||||
|
||||
/* Handle any pending dpc. */
|
||||
@@ -116,7 +116,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
}
|
||||
|
||||
Result KThreadContext::Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main) {
|
||||
void KThreadContext::Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main) {
|
||||
MESOSPHERE_ASSERT(k_sp != Null<KVirtualAddress>);
|
||||
|
||||
/* Ensure that the stack pointers are aligned. */
|
||||
@@ -157,8 +157,6 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* Lock the context, if we're a main thread. */
|
||||
m_locked = is_main;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void KThreadContext::SetArguments(uintptr_t arg0, uintptr_t arg1) {
|
||||
|
||||
@@ -306,15 +306,14 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl28CopyMemoryToUserAligned64BitEPvPK
|
||||
mov x0, #1
|
||||
ret
|
||||
|
||||
/* ams::kern::arch::arm64::UserspaceAccess::Impl::CopyMemoryToUserSize32Bit(void *dst, const void *src) */
|
||||
.section .text._ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv, "ax", %progbits
|
||||
.global _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv
|
||||
.type _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv, %function
|
||||
/* ams::kern::arch::arm64::UserspaceAccess::Impl::CopyMemoryToUserSize32Bit(void *dst, u32 value) */
|
||||
.section .text._ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj, "ax", %progbits
|
||||
.global _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj
|
||||
.type _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj, %function
|
||||
.balign 0x10
|
||||
_ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvPKv:
|
||||
/* Just load and store a u32. */
|
||||
ldr w2, [x1]
|
||||
sttr w2, [x0]
|
||||
_ZN3ams4kern4arch5arm6415UserspaceAccess4Impl25CopyMemoryToUserSize32BitEPvj:
|
||||
/* Just store a u32. */
|
||||
sttr w1, [x0]
|
||||
|
||||
/* We're done. */
|
||||
mov x0, #1
|
||||
@@ -683,7 +682,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory32BitEPvPKvm:
|
||||
mov x30, x10
|
||||
|
||||
/* Write the word to io. */
|
||||
sttr w9, [x5]
|
||||
sttr w9, [x4]
|
||||
dsb sy
|
||||
|
||||
2: /* Continue. */
|
||||
@@ -728,7 +727,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl18WriteIoMemory16BitEPvPKvm:
|
||||
mov x30, x10
|
||||
|
||||
/* Write the word to io. */
|
||||
sttrh w9, [x5]
|
||||
sttrh w9, [x4]
|
||||
dsb sy
|
||||
|
||||
2: /* Continue. */
|
||||
@@ -773,7 +772,7 @@ _ZN3ams4kern4arch5arm6415UserspaceAccess4Impl17WriteIoMemory8BitEPvPKvm:
|
||||
mov x30, x10
|
||||
|
||||
/* Write the word to io. */
|
||||
sttrb w9, [x5]
|
||||
sttrb w9, [x4]
|
||||
dsb sy
|
||||
|
||||
2: /* Continue. */
|
||||
|
||||
@@ -660,8 +660,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
ptm.Open(table_virt_addr, 1);
|
||||
|
||||
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
|
||||
/* NOTE: Nintendo does not check the result of StoreDataCache. */
|
||||
cpu::StoreDataCache(GetVoidPointer(table_virt_addr), PageDirectorySize);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_virt_addr), PageDirectorySize));
|
||||
g_reserved_table_phys_addr = table_phys_addr;
|
||||
|
||||
/* Reserve an asid to correspond to no device. */
|
||||
@@ -710,7 +709,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Install interrupt handler. */
|
||||
#if defined(MESOSPHERE_ENABLE_MEMORY_CONTROLLER_INTERRUPT)
|
||||
{
|
||||
Kernel::GetInterruptManager().BindHandler(std::addressof(g_mc_interrupt_task), KInterruptName_MemoryController, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, true);
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(std::addressof(g_mc_interrupt_task), KInterruptName_MemoryController, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, true));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -806,7 +805,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
MESOSPHERE_ASSERT(IsValidPhysicalAddress(GetPageTablePhysicalAddress(table_vaddr)));
|
||||
|
||||
ptm.Open(table_vaddr, 1);
|
||||
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize));
|
||||
m_tables[i] = table_vaddr;
|
||||
}
|
||||
|
||||
@@ -1042,7 +1041,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
if (l2_index == 0 && util::IsAligned(GetInteger(phys_addr), DeviceLargePageSize) && remaining >= DeviceLargePageSize) {
|
||||
/* Set the large page. */
|
||||
l1[l1_index].SetLargePage(read, write, true, phys_addr);
|
||||
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
@@ -1062,11 +1061,11 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const KVirtualAddress table_vaddr = ptm.Allocate();
|
||||
R_UNLESS(table_vaddr != Null<KVirtualAddress>, svc::ResultOutOfMemory());
|
||||
MESOSPHERE_ASSERT(IsValidPhysicalAddress(GetPageTablePhysicalAddress(table_vaddr)));
|
||||
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageTableSize);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageTableSize));
|
||||
|
||||
/* Set the l1 table. */
|
||||
l1[l1_index].SetTable(true, true, true, GetPageTablePhysicalAddress(table_vaddr));
|
||||
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
@@ -1093,7 +1092,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Add a reference to the l2 page (from the l2 entry page). */
|
||||
ptm.Open(KVirtualAddress(l2), 1);
|
||||
}
|
||||
cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry)));
|
||||
|
||||
/* Invalidate the page table cache. */
|
||||
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
|
||||
@@ -1199,7 +1198,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
++num_closed;
|
||||
}
|
||||
}
|
||||
cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry)));
|
||||
|
||||
/* Invalidate the page table cache. */
|
||||
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
|
||||
@@ -1243,7 +1242,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
if (ptm.Close(KVirtualAddress(l2), num_closed)) {
|
||||
/* Invalidate the l1 entry. */
|
||||
l1[l1_index].Invalidate();
|
||||
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
@@ -1266,7 +1265,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Invalidate the entry. */
|
||||
l1[l1_index].Invalidate();
|
||||
cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry)));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
|
||||
@@ -441,7 +441,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
KThread::Register(new_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
new_thread->Run();
|
||||
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,6 +524,14 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Ensure that all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Wait 100us before continuing. */
|
||||
{
|
||||
const s64 timeout = KHardwareTimer::GetTick() + ams::svc::Tick(TimeSpan::FromMicroSeconds(100));
|
||||
while (KHardwareTimer::GetTick() < timeout) {
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the interrupt manager's state. */
|
||||
Kernel::GetInterruptManager().Save(core_id);
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -361,10 +355,23 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}();
|
||||
|
||||
/* Return (possibly) adjusted size. */
|
||||
/* NOTE: On 20.0.0+ the browser requires much more memory in the applet pool in order to function. */
|
||||
/* 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. */
|
||||
const size_t ExtraSystemMemoryForAtmosphere = kern::GetTargetFirmware() >= ams::TargetFirmware_20_0_0 ? 14_MB : 40_MB;
|
||||
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
|
||||
/* 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) {
|
||||
constexpr size_t ExtraSystemMemoryForAtmosphere_20_0_0 = 14_MB;
|
||||
return base_pool_size - ExtraSystemMemoryForAtmosphere_20_0_0 - KTraceBufferSize;
|
||||
} else {
|
||||
constexpr size_t ExtraSystemMemoryForAtmosphere = 40_MB;
|
||||
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() {
|
||||
@@ -409,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;
|
||||
@@ -469,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. */
|
||||
@@ -516,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 {
|
||||
|
||||
@@ -140,14 +140,12 @@ namespace ams::kern {
|
||||
|
||||
/* Add the previously reserved pages. */
|
||||
if (src_pool == dst_pool && binary_pages != 0) {
|
||||
/* NOTE: Nintendo does not check the result of this operation. */
|
||||
pg.AddBlock(KMemoryLayout::GetLinearPhysicalAddress(data), binary_pages);
|
||||
MESOSPHERE_R_ABORT_UNLESS(pg.AddBlock(KMemoryLayout::GetLinearPhysicalAddress(data), binary_pages));
|
||||
}
|
||||
|
||||
/* Add the previously unreserved pages. */
|
||||
for (const auto &block : unreserve_pg) {
|
||||
/* NOTE: Nintendo does not check the result of this operation. */
|
||||
pg.AddBlock(block.GetAddress(), block.GetNumPages());
|
||||
MESOSPHERE_R_ABORT_UNLESS(pg.AddBlock(block.GetAddress(), block.GetNumPages()));
|
||||
}
|
||||
}
|
||||
MESOSPHERE_ABORT_UNLESS(pg.GetNumPages() == static_cast<size_t>(params.code_num_pages));
|
||||
@@ -287,7 +285,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(expected_size != 0);
|
||||
|
||||
/* Ensure that the size we need to reserve is as we expect it to be. */
|
||||
const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize);
|
||||
const u32 total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize);
|
||||
MESOSPHERE_ABORT_UNLESS(total_size == expected_size);
|
||||
MESOSPHERE_ABORT_UNLESS(total_size <= InitialProcessBinarySizeMax);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ams::kern {
|
||||
/* Clear and store cache. */
|
||||
void * const block_address = GetVoidPointer(KMemoryLayout::GetLinearVirtualAddress(block.GetAddress()));
|
||||
std::memset(block_address, 0xFF, block.GetSize());
|
||||
cpu::StoreDataCache(block_address, block.GetSize());
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(block_address, block.GetSize()));
|
||||
}
|
||||
|
||||
/* Set remaining tracking members. */
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace ams::kern {
|
||||
return UserspaceAccess::CopyMemoryFromUserSize32Bit(out, GetVoidPointer(address));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool WriteToUser(KProcessAddress address, const u32 *p) {
|
||||
return UserspaceAccess::CopyMemoryToUserSize32Bit(GetVoidPointer(address), p);
|
||||
ALWAYS_INLINE bool WriteToUser(KProcessAddress address, u32 val) {
|
||||
return UserspaceAccess::CopyMemoryToUserSize32Bit(GetVoidPointer(address), val);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool UpdateLockAtomic(u32 *out, KProcessAddress address, u32 if_zero, u32 new_orr_mask) {
|
||||
@@ -94,7 +94,7 @@ namespace ams::kern {
|
||||
|
||||
/* Write the value to userspace. */
|
||||
Result result;
|
||||
if (AMS_LIKELY(WriteToUser(addr, std::addressof(next_value)))) {
|
||||
if (AMS_LIKELY(WriteToUser(addr, next_value))) {
|
||||
result = ResultSuccess();
|
||||
} else {
|
||||
result = svc::ResultInvalidCurrentMemory();
|
||||
@@ -210,8 +210,8 @@ namespace ams::kern {
|
||||
|
||||
/* If we have no waiters, clear the has waiter flag. */
|
||||
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||
const u32 has_waiter_flag = 0;
|
||||
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
||||
constexpr u32 HasNoWaiterFlag = 0;
|
||||
WriteToUser(cv_key, HasNoWaiterFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,13 +252,13 @@ namespace ams::kern {
|
||||
|
||||
/* Write to the cv key. */
|
||||
{
|
||||
const u32 has_waiter_flag = 1;
|
||||
WriteToUser(key, std::addressof(has_waiter_flag));
|
||||
constexpr u32 HasWaiterFlag = 1;
|
||||
WriteToUser(key, HasWaiterFlag);
|
||||
cpu::DataMemoryBarrierInnerShareable();
|
||||
}
|
||||
|
||||
/* Write the value to userspace. */
|
||||
if (!WriteToUser(addr, std::addressof(next_value))) {
|
||||
if (!WriteToUser(addr, next_value)) {
|
||||
slp.CancelSleep();
|
||||
R_THROW(svc::ResultInvalidCurrentMemory());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -416,7 +416,8 @@ namespace ams::kern {
|
||||
KProcess * const target = this->GetProcessUnsafe();
|
||||
|
||||
/* Terminate the process. */
|
||||
target->Terminate();
|
||||
/* NOTE: This result is seemingly-intentionally not checked by Nintendo. */
|
||||
static_cast<void>(target->Terminate(-1ll));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -755,11 +756,13 @@ namespace ams::kern {
|
||||
case ams::svc::DebugException_UndefinedSystemCall:
|
||||
{
|
||||
MESOSPHERE_ASSERT(num_params >= 3);
|
||||
|
||||
info->info.exception.exception_address = params[1];
|
||||
|
||||
info->info.exception.exception_data_count = 1;
|
||||
info->info.exception.exception_data[0] = params[2];
|
||||
|
||||
/* Keep the compiler happy, even though the assert has us covered. */
|
||||
if (num_params >= 3) {
|
||||
info->info.exception.exception_address = params[1];
|
||||
info->info.exception.exception_data_count = 1;
|
||||
info->info.exception.exception_data[0] = params[2];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ams::svc::DebugException_DebuggerAttached:
|
||||
@@ -772,9 +775,12 @@ namespace ams::kern {
|
||||
case ams::svc::DebugException_UserBreak:
|
||||
{
|
||||
MESOSPHERE_ASSERT(num_params >= 2);
|
||||
|
||||
info->info.exception.exception_address = params[1];
|
||||
|
||||
|
||||
/* Keep the compiler happy, even though the assert has us covered. */
|
||||
if (num_params >= 2) {
|
||||
info->info.exception.exception_address = params[1];
|
||||
}
|
||||
|
||||
info->info.exception.exception_data_count = 0;
|
||||
for (size_t i = 2; i < num_params; ++i) {
|
||||
info->info.exception.exception_data[info->info.exception.exception_data_count++] = params[i];
|
||||
@@ -804,8 +810,11 @@ namespace ams::kern {
|
||||
default:
|
||||
{
|
||||
MESOSPHERE_ASSERT(num_params >= 2);
|
||||
|
||||
info->info.exception.exception_address = params[1];
|
||||
|
||||
/* Keep the compiler happy, even though the assert has us covered. */
|
||||
if (num_params >= 2) {
|
||||
info->info.exception.exception_address = params[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -875,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));
|
||||
@@ -1133,7 +1142,7 @@ namespace ams::kern {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KDebugBase::OnExitProcess(KProcess *process) {
|
||||
void KDebugBase::OnExitProcess(KProcess *process) {
|
||||
MESOSPHERE_ASSERT(process != nullptr);
|
||||
|
||||
/* Check if we're attached to a debugger. */
|
||||
@@ -1148,11 +1157,9 @@ namespace ams::kern {
|
||||
debug->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KDebugBase::OnTerminateProcess(KProcess *process) {
|
||||
void KDebugBase::OnTerminateProcess(KProcess *process) {
|
||||
MESOSPHERE_ASSERT(process != nullptr);
|
||||
|
||||
/* Check if we're attached to a debugger. */
|
||||
@@ -1167,21 +1174,17 @@ namespace ams::kern {
|
||||
debug->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KDebugBase::OnExitThread(KThread *thread) {
|
||||
void KDebugBase::OnExitThread(KThread *thread) {
|
||||
MESOSPHERE_ASSERT(thread != nullptr);
|
||||
|
||||
/* Check if we're attached to a debugger. */
|
||||
if (KProcess *process = thread->GetOwnerProcess(); process != nullptr && process->IsAttachedToDebugger()) {
|
||||
/* If we are, submit the event. */
|
||||
const uintptr_t params[2] = { thread->GetId(), static_cast<uintptr_t>(thread->IsTerminationRequested() ? ams::svc::ThreadExitReason_TerminateThread : ams::svc::ThreadExitReason_ExitThread) };
|
||||
R_TRY(OnDebugEvent(ams::svc::DebugEvent_ExitThread, params, util::size(params)));
|
||||
static_cast<void>(OnDebugEvent(ams::svc::DebugEvent_ExitThread, params, util::size(params)));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace ams::kern {
|
||||
KThread::Register(new_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
new_thread->Run();
|
||||
MESOSPHERE_R_ABORT_UNLESS(new_thread->Run());
|
||||
}
|
||||
|
||||
void KDpcManager::HandleDpc() {
|
||||
|
||||
@@ -38,20 +38,20 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
}
|
||||
|
||||
Result KEvent::Signal() {
|
||||
void KEvent::Signal() {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
R_SUCCEED_IF(m_readable_event_destroyed);
|
||||
|
||||
R_RETURN(m_readable_event.Signal());
|
||||
if (!m_readable_event_destroyed) {
|
||||
m_readable_event.Signal();
|
||||
}
|
||||
}
|
||||
|
||||
Result KEvent::Clear() {
|
||||
void KEvent::Clear() {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
R_SUCCEED_IF(m_readable_event_destroyed);
|
||||
|
||||
R_RETURN(m_readable_event.Clear());
|
||||
if (!m_readable_event_destroyed) {
|
||||
m_readable_event.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void KEvent::PostDestroy(uintptr_t arg) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
Result KHandleTable::Finalize() {
|
||||
void KHandleTable::Finalize() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Get the table and clear our record of it. */
|
||||
@@ -35,8 +35,6 @@ namespace ams::kern {
|
||||
obj->Close();
|
||||
}
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
bool KHandleTable::Remove(ams::svc::Handle handle) {
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
Result 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;
|
||||
@@ -130,10 +130,10 @@ namespace ams::kern {
|
||||
m_impl.InitializeForKernel(table, start, end);
|
||||
|
||||
/* Initialize our memory block manager. */
|
||||
R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
|
||||
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,13 @@ 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;
|
||||
m_is_kernel = false;
|
||||
@@ -236,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) {
|
||||
@@ -346,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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -560,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:
|
||||
@@ -595,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:
|
||||
@@ -621,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:
|
||||
@@ -644,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1792,7 +1711,7 @@ namespace ams::kern {
|
||||
/* Ensure cache coherency, if we're setting pages as executable. */
|
||||
if (is_x) {
|
||||
for (const auto &block : pg) {
|
||||
cpu::StoreDataCache(GetVoidPointer(GetHeapVirtualAddress(block.GetAddress())), block.GetSize());
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetHeapVirtualAddress(block.GetAddress())), block.GetSize()));
|
||||
}
|
||||
cpu::InvalidateEntireInstructionCache();
|
||||
}
|
||||
@@ -1996,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;
|
||||
|
||||
@@ -2665,8 +2584,7 @@ namespace ams::kern {
|
||||
|
||||
/* Invalidate the block. */
|
||||
if (cur_size > 0) {
|
||||
/* NOTE: Nintendo does not check the result of invalidation. */
|
||||
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
|
||||
}
|
||||
|
||||
/* Advance. */
|
||||
@@ -2689,8 +2607,7 @@ namespace ams::kern {
|
||||
|
||||
/* Invalidate the last block. */
|
||||
if (cur_size > 0) {
|
||||
/* NOTE: Nintendo does not check the result of invalidation. */
|
||||
cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::InvalidateDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@@ -2768,7 +2685,7 @@ namespace ams::kern {
|
||||
if (cur_size >= sizeof(u32)) {
|
||||
const size_t copy_size = util::AlignDown(cur_size, sizeof(u32));
|
||||
const void * copy_src = GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr));
|
||||
cpu::FlushDataCache(copy_src, copy_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(copy_src, copy_size));
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryToUserAligned32Bit(buffer, copy_src, copy_size), svc::ResultInvalidPointer());
|
||||
buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + copy_size);
|
||||
cur_addr += copy_size;
|
||||
@@ -2778,7 +2695,7 @@ namespace ams::kern {
|
||||
/* Copy remaining data. */
|
||||
if (cur_size > 0) {
|
||||
const void * copy_src = GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr));
|
||||
cpu::FlushDataCache(copy_src, cur_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::FlushDataCache(copy_src, cur_size));
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryToUser(buffer, copy_src, cur_size), svc::ResultInvalidPointer());
|
||||
}
|
||||
|
||||
@@ -2853,7 +2770,7 @@ namespace ams::kern {
|
||||
if (cur_size >= sizeof(u32)) {
|
||||
const size_t copy_size = util::AlignDown(cur_size, sizeof(u32));
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryFromUserAligned32Bit(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), buffer, copy_size), svc::ResultInvalidCurrentMemory());
|
||||
cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), copy_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), copy_size));
|
||||
|
||||
buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + copy_size);
|
||||
cur_addr += copy_size;
|
||||
@@ -2863,7 +2780,7 @@ namespace ams::kern {
|
||||
/* Copy remaining data. */
|
||||
if (cur_size > 0) {
|
||||
R_UNLESS(UserspaceAccess::CopyMemoryFromUser(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), buffer, cur_size), svc::ResultInvalidCurrentMemory());
|
||||
cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size);
|
||||
MESOSPHERE_R_ABORT_UNLESS(cpu::StoreDataCache(GetVoidPointer(GetLinearMappedVirtualAddress(cur_addr)), cur_size));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@@ -3079,7 +2996,9 @@ namespace ams::kern {
|
||||
const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap) | (check_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_None);
|
||||
size_t num_allocator_blocks;
|
||||
KMemoryState old_state;
|
||||
R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
|
||||
const KMemoryPermission perm_mask = static_cast<KMemoryPermission>(perm | (m_allowed_exec_device_mapping ? KMemoryPermission_None : KMemoryPermission_UserExecute));
|
||||
|
||||
R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm_mask, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
|
||||
|
||||
/* Create an update allocator. */
|
||||
Result allocator_result;
|
||||
@@ -3286,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. */
|
||||
{
|
||||
@@ -3435,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. */
|
||||
{
|
||||
|
||||
@@ -185,6 +185,11 @@ namespace ams::kern {
|
||||
/* Validate that the intended kernel version isn't too high for us to support. */
|
||||
R_UNLESS(m_capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination());
|
||||
|
||||
/* Enable mapping device pages as executable on legacy processes. */
|
||||
if (m_capabilities.GetIntendedKernelMajorVersion() < 26) {
|
||||
m_page_table.GetBasePageTable().AllowDeviceMappingOfExecPages();
|
||||
}
|
||||
|
||||
/* Create and clear the process local region. */
|
||||
R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address)));
|
||||
m_plr_heap_address = this->GetThreadLocalRegionPointer(m_plr_address);
|
||||
@@ -205,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)
|
||||
@@ -221,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));
|
||||
@@ -259,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. */
|
||||
@@ -274,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;
|
||||
@@ -288,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(); };
|
||||
|
||||
@@ -327,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;
|
||||
@@ -353,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;
|
||||
@@ -367,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(); };
|
||||
|
||||
@@ -387,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));
|
||||
}
|
||||
|
||||
@@ -404,7 +419,7 @@ namespace ams::kern {
|
||||
|
||||
void KProcess::DoWorkerTaskImpl() {
|
||||
/* Terminate child threads. */
|
||||
TerminateChildren(this, nullptr);
|
||||
MESOSPHERE_R_ABORT_UNLESS(TerminateChildren(this, nullptr));
|
||||
|
||||
/* Finalize the handle table, if we're not immortal. */
|
||||
if (!m_is_immortal && m_is_handle_table_initialized) {
|
||||
@@ -420,7 +435,7 @@ namespace ams::kern {
|
||||
|
||||
Result KProcess::StartTermination() {
|
||||
/* Finalize the handle table when we're done, if the process isn't immortal. */
|
||||
ON_SCOPE_EXIT {
|
||||
ON_RESULT_SUCCESS {
|
||||
if (!m_is_immortal) {
|
||||
this->FinalizeHandleTable();
|
||||
}
|
||||
@@ -450,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. */
|
||||
@@ -465,13 +480,14 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we need to start termination, do so. */
|
||||
if (needs_terminate) {
|
||||
this->StartTermination();
|
||||
static_cast<void>(this->StartTermination());
|
||||
|
||||
/* Note for debug that we're exiting the process. */
|
||||
MESOSPHERE_LOG("KProcess::Exit() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
@@ -485,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 */
|
||||
@@ -501,29 +517,33 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we need to terminate, do so. */
|
||||
if (needs_terminate) {
|
||||
/* Start termination. */
|
||||
if (R_SUCCEEDED(this->StartTermination())) {
|
||||
/* Note for debug that we're terminating the process. */
|
||||
MESOSPHERE_LOG("KProcess::Terminate() OK pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Call the debug callback. */
|
||||
KDebug::OnTerminateProcess(this);
|
||||
|
||||
/* Finish termination. */
|
||||
this->FinishTermination();
|
||||
} else {
|
||||
/* If we fail to terminate, register as a worker task. */
|
||||
ON_RESULT_FAILURE {
|
||||
/* Note for debug that we're terminating the process. */
|
||||
MESOSPHERE_LOG("KProcess::Terminate() FAIL pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Register the process as a work task. */
|
||||
KWorkerTaskManager::AddTask(KWorkerTaskManager::WorkerType_ExitProcess, this);
|
||||
}
|
||||
};
|
||||
|
||||
/* Start termination. */
|
||||
R_TRY(this->StartTermination());
|
||||
|
||||
/* Note for debug that we're terminating the process. */
|
||||
MESOSPHERE_LOG("KProcess::Terminate() OK pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Call the debug callback. */
|
||||
KDebug::OnTerminateProcess(this);
|
||||
|
||||
/* Finish termination. */
|
||||
this->FinishTermination();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@@ -666,7 +686,7 @@ namespace ams::kern {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
|
||||
void KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
|
||||
KThreadLocalPage *page_to_free = nullptr;
|
||||
|
||||
/* Release the region. */
|
||||
@@ -678,7 +698,7 @@ namespace ams::kern {
|
||||
if (it == m_partially_used_tlp_tree.end()) {
|
||||
/* If we don't find it, it has to be in the fully used list. */
|
||||
it = m_fully_used_tlp_tree.find_key(util::AlignDown(GetInteger(addr), PageSize));
|
||||
R_UNLESS(it != m_fully_used_tlp_tree.end(), svc::ResultInvalidAddress());
|
||||
MESOSPHERE_ABORT_UNLESS(it != m_fully_used_tlp_tree.end());
|
||||
|
||||
/* Release the region. */
|
||||
it->Release(addr);
|
||||
@@ -710,8 +730,6 @@ namespace ams::kern {
|
||||
|
||||
KThreadLocalPage::Free(page_to_free);
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void *KProcess::GetThreadLocalRegionPointer(KProcessAddress addr) {
|
||||
@@ -767,7 +785,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(m_num_running_threads.Load() > 0);
|
||||
|
||||
if (const auto prev = m_num_running_threads--; prev == 1) {
|
||||
this->Terminate();
|
||||
static_cast<void>(this->Terminate(-1ll));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,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();
|
||||
@@ -975,6 +996,9 @@ namespace ams::kern {
|
||||
/* Set the thread arguments. */
|
||||
main_thread->GetContext().SetArguments(0, thread_handle);
|
||||
|
||||
/* Pass the thread handle to the thread local region. */
|
||||
static_cast<ams::svc::ThreadLocalRegion *>(main_thread->GetThreadLocalRegionHeapAddress())->thread_handle = thread_handle;
|
||||
|
||||
/* Update our state. */
|
||||
this->ChangeState((state == State_Created) ? State_Running : State_RunningAttached);
|
||||
ON_RESULT_FAILURE_2 { this->ChangeState(state); };
|
||||
@@ -1180,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
Result KReadableEvent::Signal() {
|
||||
void KReadableEvent::Signal() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedSchedulerLock lk;
|
||||
@@ -55,8 +55,6 @@ namespace ams::kern {
|
||||
m_is_signaled = true;
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KReadableEvent::Reset() {
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Bind interrupt handler. */
|
||||
Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptHandler(), KInterruptName_Scheduler, m_core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptHandler(), KInterruptName_Scheduler, m_core_id, KInterruptController::PriorityLevel_Scheduler, false, false));
|
||||
|
||||
/* Set the current thread. */
|
||||
m_current_thread = GetCurrentThreadPointer();
|
||||
@@ -270,7 +270,13 @@ namespace ams::kern {
|
||||
m_current_thread = next_thread;
|
||||
|
||||
/* Set the new Thread Local region. */
|
||||
cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress()));
|
||||
const auto tls_address = GetInteger(next_thread->GetThreadLocalRegionAddress());
|
||||
cpu::SwitchThreadLocalRegion(tls_address);
|
||||
|
||||
/* Update the thread's cpu time differential in TLS, if relevant. */
|
||||
if (tls_address != 0) {
|
||||
static_cast<ams::svc::ThreadLocalRegion *>(next_thread->GetThreadLocalRegionHeapAddress())->thread_cpu_time = next_thread->GetCpuTime() - cur_tick;
|
||||
}
|
||||
}
|
||||
|
||||
void KScheduler::ClearPreviousThread(KThread *thread) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user