Compare commits
160 Commits
hid_refact
...
accurate_d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9377be2525 | ||
|
|
30336362f4 | ||
|
|
24111d46a1 | ||
|
|
f2a6a4a6e6 | ||
|
|
6633af769e | ||
|
|
131c8609c8 | ||
|
|
30e70e20d8 | ||
|
|
a26e8ac54f | ||
|
|
8bfda27e0e | ||
|
|
0c9cb830f7 | ||
|
|
ee1b638dde | ||
|
|
9826358533 | ||
|
|
113ab8439d | ||
|
|
60c888126b | ||
|
|
d7b14f48d2 | ||
|
|
1085ccbe60 | ||
|
|
8b61537aa3 | ||
|
|
968f50bc07 | ||
|
|
0bf2ade76f | ||
|
|
35a6705d55 | ||
|
|
b8471bcd4e | ||
|
|
f7e83a72a9 | ||
|
|
f6b847177a | ||
|
|
a6d40e85f1 | ||
|
|
6a81206373 | ||
|
|
4be5733c8e | ||
|
|
8dcb07152e | ||
|
|
3b5dff0f83 | ||
|
|
1ca373cd71 | ||
|
|
4ff026224e | ||
|
|
2c39efea4c | ||
|
|
16cd1141d1 | ||
|
|
4b71e3a87e | ||
|
|
d090a7886d | ||
|
|
9a6cca7499 | ||
|
|
1ec2c0c2cb | ||
|
|
569e1bc650 | ||
|
|
652e9bf9e8 | ||
|
|
ca2cc5e179 | ||
|
|
17c8c390fc | ||
|
|
d8ae1d873c | ||
|
|
63e3c02688 | ||
|
|
14a415c4b2 | ||
|
|
734122f20a | ||
|
|
7fb902d8fb | ||
|
|
be8473cf65 | ||
|
|
6df26d674c | ||
|
|
1a6e003a5d | ||
|
|
0acd79c8c2 | ||
|
|
8a4bf6a0a8 | ||
|
|
af259eabda | ||
|
|
16e2f46aed | ||
|
|
bcc7eed037 | ||
|
|
abd7ad2720 | ||
|
|
58c3c8c19a | ||
|
|
f62330c73b | ||
|
|
2de85c633a | ||
|
|
121c981bb4 | ||
|
|
15396dbbc2 | ||
|
|
9ca1d3a7f7 | ||
|
|
32803d9920 | ||
|
|
5ef93778f6 | ||
|
|
7548940efa | ||
|
|
bf55776241 | ||
|
|
73167448cc | ||
|
|
c45088d1cd | ||
|
|
7336dc2b7a | ||
|
|
d2f48d5e36 | ||
|
|
422e9434d8 | ||
|
|
2b93bbd9ee | ||
|
|
021b29d2db | ||
|
|
6da28f4a27 | ||
|
|
bba99d49da | ||
|
|
e760a9d4b0 | ||
|
|
ee91f3fde0 | ||
|
|
f72475872a | ||
|
|
199a9aec8b | ||
|
|
1b83f5169a | ||
|
|
7bb77f44af | ||
|
|
801ce24622 | ||
|
|
1d778b2dc8 | ||
|
|
7c9608021d | ||
|
|
b8fbd0baff | ||
|
|
525da05629 | ||
|
|
2e9db4d113 | ||
|
|
4f1a4e7499 | ||
|
|
972283032a | ||
|
|
57f935391d | ||
|
|
4804e1e1e0 | ||
|
|
4ae74b9b4e | ||
|
|
726d7b6e4d | ||
|
|
390bdc7b6b | ||
|
|
2d8acf9c64 | ||
|
|
9743f63f0d | ||
|
|
ccd2798ae2 | ||
|
|
f3dbab4876 | ||
|
|
41a53075e5 | ||
|
|
ab8de72db0 | ||
|
|
331fa1d00d | ||
|
|
fd745ab2d3 | ||
|
|
972b396f61 | ||
|
|
3c8e7de915 | ||
|
|
1b164613a6 | ||
|
|
3d4ab95ab2 | ||
|
|
152def19c0 | ||
|
|
63974d9bce | ||
|
|
2b483866c7 | ||
|
|
7e1da15f6e | ||
|
|
0a1465f198 | ||
|
|
748893fe77 | ||
|
|
1ca64cf2a1 | ||
|
|
aac8af8bf5 | ||
|
|
5da6b60008 | ||
|
|
e400e2afc7 | ||
|
|
56c6e4244a | ||
|
|
c8ebd7eea0 | ||
|
|
550f5690bf | ||
|
|
28f9b534b6 | ||
|
|
3fd59b61bc | ||
|
|
f86059de70 | ||
|
|
a03ee7b148 | ||
|
|
8b2ed36698 | ||
|
|
1852fe8612 | ||
|
|
b60054dba1 | ||
|
|
c7f37f81ee | ||
|
|
19a279ce45 | ||
|
|
783f1077be | ||
|
|
b0debd72a7 | ||
|
|
24d545701c | ||
|
|
aae565629e | ||
|
|
bee629b8ad | ||
|
|
5cb237d030 | ||
|
|
a4e09fc6c4 | ||
|
|
73d9d5ff47 | ||
|
|
08cfee54fa | ||
|
|
7b279ab863 | ||
|
|
6a85f7225d | ||
|
|
f469dfbeb3 | ||
|
|
cc11d452e5 | ||
|
|
3bce008170 | ||
|
|
3383509da6 | ||
|
|
281dcf232a | ||
|
|
71a2fe1bb6 | ||
|
|
4a216dc928 | ||
|
|
18099e19b1 | ||
|
|
a0a45853dd | ||
|
|
fe9a4cd2fc | ||
|
|
88a66c89e2 | ||
|
|
93128b6b17 | ||
|
|
db2de8ef31 | ||
|
|
05832cec73 | ||
|
|
632c8984c8 | ||
|
|
694e3b579e | ||
|
|
20eba0dc98 | ||
|
|
730ef6d6db | ||
|
|
7cb24713ab | ||
|
|
a685842804 | ||
|
|
ad6dd60474 | ||
|
|
05af215191 | ||
|
|
e06b73aafa |
9
Makefile
9
Makefile
@@ -78,7 +78,7 @@ dist-no-debug: all
|
||||
cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc
|
||||
cp sept/sept-secondary/sept-secondary_dev_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_00.enc
|
||||
cp sept/sept-secondary/sept-secondary_dev_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_01.enc
|
||||
cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config/BCT.ini
|
||||
cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config_templates/BCT.ini
|
||||
cp config_templates/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini
|
||||
cp config_templates/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini
|
||||
cp config_templates/exosphere.ini atmosphere-$(AMSVER)/atmosphere/config_templates/exosphere.ini
|
||||
@@ -141,15 +141,16 @@ dist: dist-no-debug
|
||||
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
|
||||
cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.elf
|
||||
cp stratosphere/eclct.stub/eclct.stub.elf atmosphere-$(AMSVER)-debug/eclct.stub.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/fatal/fatal.elf atmosphere-$(AMSVER)-debug/fatal.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/loader/loader.elf atmosphere-$(AMSVER)-debug/loader.elf
|
||||
cp stratosphere/ncm/ncm.elf atmosphere-$(AMSVER)-debug/ncm.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp stratosphere/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf
|
||||
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
||||
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf
|
||||
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||
rm -r atmosphere-$(AMSVER)-debug
|
||||
|
||||
@@ -35,6 +35,17 @@
|
||||
# mmc space, encrypted to prevent detection. This backup can be used
|
||||
# to prevent unrecoverable edits in emergencies.
|
||||
|
||||
# Key: log_port, default: 0.
|
||||
# Desc: Controls what uart port exosphere will set up for logging.
|
||||
# NOTE: 0 = UART-A, 1 = UART-B, 2 = UART-C, 3 = UART-D
|
||||
|
||||
# Key: log_baud_rate, default: 115200
|
||||
# Desc: Controls the baud rate exosphere will set up for logging.
|
||||
# NOTE: 0 is treated as equivalent to 115200.
|
||||
|
||||
# Key: log_inverted, default: 0.
|
||||
# Desc: Controls whether the logging uart port is inverted.
|
||||
|
||||
[exosphere]
|
||||
debugmode=1
|
||||
debugmode_user=0
|
||||
@@ -43,3 +54,6 @@ enable_user_pmu_access=0
|
||||
blank_prodinfo_sysmmc=0
|
||||
blank_prodinfo_emummc=0
|
||||
allow_writing_to_cal_sysmmc=0
|
||||
log_port=0
|
||||
log_baud_rate=115200
|
||||
log_inverted=0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -38,6 +38,10 @@
|
||||
; Please note this setting may be removed in a
|
||||
; future release of Atmosphere.
|
||||
; enable_deprecated_hid_mitm = u8!0x0
|
||||
; Controls whether am sees system settings "DebugModeFlag" as
|
||||
; enabled or disabled.
|
||||
; 0 = Disabled (not debug mode), 1 = Enabled (debug mode)
|
||||
; enable_am_debug_mode = u8!0x0
|
||||
[hbloader]
|
||||
; Controls the size of the homebrew heap when running as applet.
|
||||
; If set to zero, all available applet memory is used as heap.
|
||||
|
||||
@@ -1,4 +1,63 @@
|
||||
# Changelog
|
||||
## 0.16.2
|
||||
+ Atmosphère release zips no longer bundle BCT.ini, instead relying on defaults in code.
|
||||
+ This means atmosphere updates should no longer overwrite any user configuration at all.
|
||||
+ If you wish to modify BCT.ini config, copy the template from /config_templates/ as with other configuration.
|
||||
+ `pgl` and `creport` were further updated to reflect differences in official behavior in 11.0.0.
|
||||
+ An issue was fixed that caused creport to be launched multiple times on process crash.
|
||||
+ This fixes the "duplicate reports" issue that sometimes plagued people.
|
||||
+ A new system setting (`atmosphere!enable_am_debug_mode`) configuring am to use debug mode.
|
||||
+ If you are not a developer or don't see a clear use for this, leave it configured to the default (off).
|
||||
+ Reboot to payload NRO was updated to fix support with certain payloads.
|
||||
+ Support was fixed for atmosphere's extension to support homebrew use of new (8.0.0+) kernel mappings.
|
||||
+ In particular, when running tracing debug builds of `mesosphère`, hbloader now has access to the kernel trace buffer.
|
||||
+ Several issues were fixed, and usability and stability were improved.
|
||||
## 0.16.1
|
||||
+ Support was added for 11.0.1.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ A new svc::InfoType added in 11.0.0 was implemented (it wasn't discovered before 0.16.0 released).
|
||||
+ The new Control Flow Integrity (CFI) logic added in 11.0.0 kernel was implemented.
|
||||
+ `fs` logic was refactored and cleaned up to reflect some newer sysmodule behavioral and structural changes.
|
||||
+ `exosphère` was updated to allow dynamic control of what uart port is used for logging.
|
||||
+ This can be controlled by editing the `log_port`, `log_baud_rate`, and `log_inverted` fields in `exosphere.ini`.
|
||||
+ `mesosphère` was updated to improve debugging capabilities.
|
||||
+ This is still a work in progress, but developers may be interested.
|
||||
+ A bug was fixed that caused `fatal` to fatal error if the fatal process was already being debugged.
|
||||
+ Several issues were fixed, and usability and stability were improved.
|
||||
## 0.16.0
|
||||
+ Support was added for 11.0.0.
|
||||
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ `loader`, `sm`, `boot`, `pgl` were updated to reflect the latest official behaviors.
|
||||
+ **Please Note**: 11.0.0 implements an opt-in version of the atmosphère `sm` extension that allows for closing session without unregistering services.
|
||||
+ Correspondingly, the extension will be deprecated in favor of the new official opt-in command. In 0.17.0, it will be removed entirely.
|
||||
+ If your custom system module relies on this extension (however unlikely that seems to me), please update it accordingly.
|
||||
+ `erpt` was partially updated to provide compatibility with 11.0.0.
|
||||
+ The latest firmware attaches additional fields and context information to logs.
|
||||
+ A future atmosphère update will implement this logic, so that users who are interested can also get the new information when examining their logs.
|
||||
+ **Please Note**: 11.0.0 introduced breaking changes to the `usb` system module's `usb:ds` API.
|
||||
+ Homebrew which uses the `usb:ds` service should rebuild with the latest libnx version to support running on 11.0.0.
|
||||
+ The `boot` system module was rewritten to reflect the huge driver changes introduced in 8.0.0.
|
||||
+ This includes a number of improvements to both logo display and battery management logic.
|
||||
+ Support was added for configuring the address space width for `hbl`.
|
||||
+ The `hbl_config!override_address_space_(#)` and `hbl_config!override_any_app_address_space` can now be set to `39_bit`, `36_bit`, or `32_bit` to control the address space for hbl on a per-override basis.
|
||||
+ If a configuration has not been set, hbl will now default to 39-bit address space.
|
||||
+ Previously, a legacy 36-bit address space was always used to maintain compatibility with 1.0.0.
|
||||
+ A new loader extension was added to support 39-bit whenever possible (including mesosphere-on-1.0.0), with fallback to 36-bit when unavailable.
|
||||
+ Support was added to a number of components for running on Mariko hardware.
|
||||
+ The `boot` system module can now safely be run on mariko hardware, performing correct hardware initialization.
|
||||
+ Daybreak (and generally, system update logic) were updated to be usable on Mariko.
|
||||
+ Boot0 protection/management logic was updated to perform correct actions on Mariko.
|
||||
+ Reboot to payload does not and cannot work on Mariko. Correspondingly, A "fatal error" handler was written, to display and save fatal errors from within TrustZone.
|
||||
+ **Please Note:** Atmosphere is still not properly usable on Mariko hardware.
|
||||
+ In particular, wake-from-sleep will not properly function (the magic numbers aren't set correctly), among a few other minor issues.
|
||||
+ `exosphère` received support for building under debug configuration.
|
||||
+ A small (otherwise unused) portion of IRAM is now reserved for debug-only exosphere code (this region is unused/untouched under release config).
|
||||
+ This enables logging (including printf) to uart from the secure monitor, for those interested.
|
||||
+ A number of bugs were fixed, including:
|
||||
+ Minor issues in a number of filesystem related code were fixed.
|
||||
+ An issue was fixed that could cause NCM to abort on consoles which came with 3.0.x and were never updated.
|
||||
+ Several issues were fixed, and usability and stability were improved.
|
||||
## 0.15.0
|
||||
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
|
||||
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/m4xw/emuMMC
|
||||
branch = develop
|
||||
commit = 25075973d31a5be6f2e769f1ea0fff44daf0cdfa
|
||||
parent = 8ba513fefbcfd8278a433090e59017963ba9887f
|
||||
commit = 5eed18eb527bbaa63aee5323c26de5b0cca6d28e
|
||||
parent = 021b29d2dbc8ed0469bc822393e58c9f0d174d57
|
||||
method = rebase
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
||||
|
||||
### Supported Horizon Versions
|
||||
**1.0.0 - 10.0.0**
|
||||
**1.0.0 - 11.0.0**
|
||||
|
||||
## Features
|
||||
* Arbitrary SDMMC backend selection
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include "offsets/1000_exfat.h"
|
||||
#include "offsets/1020.h"
|
||||
#include "offsets/1020_exfat.h"
|
||||
#include "offsets/1100.h"
|
||||
#include "offsets/1100_exfat.h"
|
||||
#include "../utils/fatal.h"
|
||||
|
||||
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
||||
@@ -69,6 +71,7 @@ static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \
|
||||
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
|
||||
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
|
||||
.sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \
|
||||
.sdmmc_accessor_controller_open = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_OPEN, \
|
||||
.sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \
|
||||
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
|
||||
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
|
||||
@@ -108,6 +111,8 @@ DEFINE_OFFSET_STRUCT(_1000);
|
||||
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_1020);
|
||||
DEFINE_OFFSET_STRUCT(_1020_EXFAT);
|
||||
DEFINE_OFFSET_STRUCT(_1100);
|
||||
DEFINE_OFFSET_STRUCT(_1100_EXFAT);
|
||||
|
||||
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||
switch (version) {
|
||||
@@ -177,6 +182,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||
return &(GET_OFFSET_STRUCT_NAME(_1020));
|
||||
case FS_VER_10_2_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
|
||||
case FS_VER_11_0_0:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_1100));
|
||||
case FS_VER_11_0_0_EXFAT:
|
||||
return &(GET_OFFSET_STRUCT_NAME(_1100_EXFAT));
|
||||
default:
|
||||
fatal_abort(Fatal_UnknownVersion);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct {
|
||||
// Misc funcs
|
||||
uintptr_t lock_mutex;
|
||||
uintptr_t unlock_mutex;
|
||||
uintptr_t sdmmc_accessor_controller_open;
|
||||
uintptr_t sdmmc_accessor_controller_close;
|
||||
// Misc data
|
||||
uintptr_t sd_mutex;
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef struct sdmmc_accessor_vt
|
||||
void *dtor;
|
||||
void *map_device_addr_space;
|
||||
void *unmap_device_addr_space;
|
||||
void *controller_open;
|
||||
uint64_t (*sdmmc_accessor_controller_open)(void *);
|
||||
uint64_t (*sdmmc_accessor_controller_close)(void *);
|
||||
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
|
||||
// More not included because we don't use it.
|
||||
|
||||
@@ -71,6 +71,9 @@ enum FS_VER
|
||||
FS_VER_10_2_0,
|
||||
FS_VER_10_2_0_EXFAT,
|
||||
|
||||
FS_VER_11_0_0,
|
||||
FS_VER_11_0_0_EXFAT,
|
||||
|
||||
FS_VER_MAX,
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_100_LOCK_MUTEX 0x2884
|
||||
#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0
|
||||
|
||||
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||
|
||||
// Misc Data
|
||||
|
||||
59
emummc/source/FS/offsets/1100.h
Normal file
59
emummc/source/FS/offsets/1100.h
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_1100_H__
|
||||
#define __FS_1100_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_1100_SDMMC_ACCESSOR_GC 0x156D90
|
||||
#define FS_OFFSET_1100_SDMMC_ACCESSOR_SD 0x154F40
|
||||
#define FS_OFFSET_1100_SDMMC_ACCESSOR_NAND 0x1500F0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_READ 0x14B990
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_WRITE 0x14BA70
|
||||
#define FS_OFFSET_1100_RTLD 0x688
|
||||
#define FS_OFFSET_1100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
|
||||
|
||||
#define FS_OFFSET_1100_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_1100_LOCK_MUTEX 0x28FF0
|
||||
#define FS_OFFSET_1100_UNLOCK_MUTEX 0x29040
|
||||
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_1100_SD_MUTEX 0xE323E8
|
||||
#define FS_OFFSET_1100_NAND_MUTEX 0xE2D338
|
||||
#define FS_OFFSET_1100_ACTIVE_PARTITION 0xE2D378
|
||||
#define FS_OFFSET_1100_SDMMC_DAS_HANDLE 0xE15D40
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_1100_SD_DAS_INIT 0x273B4
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_1100_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_1100_H__
|
||||
59
emummc/source/FS/offsets/1100_exfat.h
Normal file
59
emummc/source/FS/offsets/1100_exfat.h
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_1100_EXFAT_H__
|
||||
#define __FS_1100_EXFAT_H__
|
||||
|
||||
// Accessor vtable getters
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_GC 0x156D90
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_SD 0x154F40
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_NAND 0x1500F0
|
||||
|
||||
// Hooks
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_READ 0x14B990
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_WRITE 0x14BA70
|
||||
#define FS_OFFSET_1100_EXFAT_RTLD 0x688
|
||||
#define FS_OFFSET_1100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
|
||||
|
||||
#define FS_OFFSET_1100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
|
||||
|
||||
// Misc funcs
|
||||
#define FS_OFFSET_1100_EXFAT_LOCK_MUTEX 0x28FF0
|
||||
#define FS_OFFSET_1100_EXFAT_UNLOCK_MUTEX 0x29040
|
||||
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_1100_EXFAT_SD_MUTEX 0xE403E8
|
||||
#define FS_OFFSET_1100_EXFAT_NAND_MUTEX 0xE3B338
|
||||
#define FS_OFFSET_1100_EXFAT_ACTIVE_PARTITION 0xE3B378
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_DAS_HANDLE 0xE23D40
|
||||
|
||||
// NOPs
|
||||
#define FS_OFFSET_1100_EXFAT_SD_DAS_INIT 0x273B4
|
||||
|
||||
// Nintendo Paths
|
||||
#define FS_OFFSET_1100_EXFAT_NINTENDO_PATHS \
|
||||
{ \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
|
||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||
}
|
||||
|
||||
#endif // __FS_1100_EXFAT_H__
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_200_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_210_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC
|
||||
#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638
|
||||
|
||||
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
|
||||
#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638
|
||||
|
||||
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_301_LOCK_MUTEX 0x3638
|
||||
#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4
|
||||
|
||||
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
|
||||
#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4
|
||||
|
||||
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_410_SD_MUTEX 0xE80268
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_500_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_510_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
|
||||
#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310
|
||||
|
||||
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
|
||||
#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10
|
||||
|
||||
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90
|
||||
#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0
|
||||
|
||||
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
|
||||
#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090
|
||||
|
||||
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
|
||||
#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720
|
||||
|
||||
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
|
||||
#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0
|
||||
|
||||
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
|
||||
#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720
|
||||
|
||||
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
|
||||
#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0
|
||||
|
||||
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_900_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_910_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -271,7 +271,7 @@ int sdmmc_nand_get_active_partition_index()
|
||||
|
||||
static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned int num_sectors, bool is_write)
|
||||
{
|
||||
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD))
|
||||
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw))
|
||||
{
|
||||
// raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset.
|
||||
sector += emuMMC_ctx.EMMC_StoragePartitionOffset;
|
||||
@@ -318,6 +318,31 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
|
||||
return res;
|
||||
}
|
||||
|
||||
// Controller open wrapper
|
||||
uint64_t sdmmc_wrapper_controller_open(int mmc_id)
|
||||
{
|
||||
uint64_t result;
|
||||
sdmmc_accessor_t *_this;
|
||||
_this = sdmmc_accessor_get(mmc_id);
|
||||
|
||||
if (_this != NULL)
|
||||
{
|
||||
// Lock eMMC xfer while SD card is being initialized by FS.
|
||||
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
|
||||
mutex_lock_handler(FS_SDMMC_EMMC); // Recursive Mutex, handler will lock SD as well if custom_driver
|
||||
|
||||
result = _this->vtab->sdmmc_accessor_controller_open(_this);
|
||||
|
||||
// Unlock eMMC.
|
||||
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
|
||||
mutex_unlock_handler(FS_SDMMC_EMMC);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fatal_abort(Fatal_OpenAccessor);
|
||||
}
|
||||
|
||||
// Controller close wrapper
|
||||
uint64_t sdmmc_wrapper_controller_close(int mmc_id)
|
||||
{
|
||||
@@ -389,7 +414,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
||||
if (first_sd_read)
|
||||
{
|
||||
first_sd_read = false;
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||
{
|
||||
// Because some SD cards have issues with emuMMC's driver
|
||||
// we currently swap to FS's driver after first SD read
|
||||
@@ -400,7 +425,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
||||
}
|
||||
}
|
||||
|
||||
// Call hekates driver.
|
||||
// Call hekate's driver.
|
||||
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
|
||||
{
|
||||
mutex_unlock_handler(mmc_id);
|
||||
|
||||
@@ -52,6 +52,7 @@ void mutex_lock_handler(int mmc_id);
|
||||
void mutex_unlock_handler(int mmc_id);
|
||||
|
||||
// Hooks
|
||||
uint64_t sdmmc_wrapper_controller_open(int mmc_id);
|
||||
uint64_t sdmmc_wrapper_controller_close(int mmc_id);
|
||||
uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors);
|
||||
uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize);
|
||||
|
||||
@@ -30,7 +30,7 @@ enum emuMMC_Type
|
||||
emuMMC_EMMC = 0,
|
||||
|
||||
// SD Device raw
|
||||
emuMMC_SD,
|
||||
emuMMC_SD_Raw,
|
||||
// SD Device File
|
||||
emuMMC_SD_File,
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ volatile __attribute__((aligned(0x1000))) emuMMC_ctx_t emuMMC_ctx = {
|
||||
.fs_ver = FS_VER_MAX,
|
||||
|
||||
// SD Default Metadata
|
||||
.SD_Type = emuMMC_SD,
|
||||
.SD_Type = emuMMC_SD_Raw,
|
||||
.SD_StoragePartitionOffset = 0,
|
||||
|
||||
// EMMC Default Metadata
|
||||
@@ -285,6 +285,9 @@ void setup_hooks(void)
|
||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
|
||||
// sdmmc_wrapper_write hook
|
||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write);
|
||||
// sdmmc_wrapper_controller_open hook
|
||||
if (fs_offsets->sdmmc_accessor_controller_open)
|
||||
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_open, sdmmc_wrapper_controller_open);
|
||||
// sdmmc_wrapper_controller_close hook
|
||||
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
|
||||
|
||||
@@ -346,7 +349,7 @@ static void load_emummc_ctx(void)
|
||||
emuMMC_ctx.id = config.base_cfg.id;
|
||||
emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type;
|
||||
emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version;
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||
{
|
||||
emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ $(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/l
|
||||
|
||||
program.lz4.o: program_lz4.h
|
||||
|
||||
program.lz4.o program_lz4.h: $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4
|
||||
program_lz4.h: $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4
|
||||
@echo $(notdir $<)
|
||||
@rm -rf tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
|
||||
@mkdir -p tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace ams::secmon::fatal {
|
||||
}
|
||||
}
|
||||
|
||||
void EnableBacklightForVendor2050ForHardwareTypeFive(int brightness) {
|
||||
void EnableBacklightForVendor2050ForAula(int brightness) {
|
||||
/* Enable FRAME_END_INT */
|
||||
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_ENABLE, 2);
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace ams::secmon::fatal {
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
|
||||
if (fuse::GetHardwareType() == fuse::HardwareType_Five) {
|
||||
if (fuse::GetHardwareType() == fuse::HardwareType_Aula) {
|
||||
/* Configure LCD backlight. */
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x4);
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x4);
|
||||
@@ -384,7 +384,7 @@ namespace ams::secmon::fatal {
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
|
||||
if (hw_type == fuse::HardwareType_Five) {
|
||||
if (hw_type == fuse::HardwareType_Aula) {
|
||||
/* Configure LCD backlight. */
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x4);
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x4);
|
||||
@@ -429,7 +429,7 @@ namespace ams::secmon::fatal {
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
|
||||
util::WaitMicroSeconds(60'000ul);
|
||||
|
||||
if (hw_type == fuse::HardwareType_Five) {
|
||||
if (hw_type == fuse::HardwareType_Aula) {
|
||||
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x40103);
|
||||
} else {
|
||||
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x50204);
|
||||
@@ -593,7 +593,7 @@ namespace ams::secmon::fatal {
|
||||
/* Enable backlight. */
|
||||
constexpr auto DisplayBrightness = 100;
|
||||
if (GetLcdVendor() == 0x2050) {
|
||||
EnableBacklightForVendor2050ForHardwareTypeFive(DisplayBrightness);
|
||||
EnableBacklightForVendor2050ForAula(DisplayBrightness);
|
||||
} else {
|
||||
EnableBacklightForGeneric(DisplayBrightness);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace ams::secmon::boot {
|
||||
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
|
||||
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
|
||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
|
||||
|
||||
/* TODO: Fix to ensure correct scratch contents on mariko, as otherwise wb is broken. */
|
||||
AMS_ABORT_UNLESS(fuse::GetSocType() != fuse::SocType_Mariko);
|
||||
}
|
||||
|
||||
/* This function derives the master kek and device keys using the tsec root key. */
|
||||
|
||||
@@ -409,8 +409,8 @@ namespace ams::secmon {
|
||||
reg0 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, CEC, ENABLE));
|
||||
}
|
||||
|
||||
/* Icosa, Iowa, and Five all set I2C4 to be secure. */
|
||||
if (hw_type == fuse::HardwareType_Icosa && hw_type == fuse::HardwareType_Iowa && hw_type == fuse::HardwareType_Five) {
|
||||
/* Icosa, Iowa, and Aula all set I2C4 to be secure. */
|
||||
if (hw_type == fuse::HardwareType_Icosa && hw_type == fuse::HardwareType_Iowa && hw_type == fuse::HardwareType_Aula) {
|
||||
reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, I2C4, ENABLE));
|
||||
|
||||
}
|
||||
@@ -960,7 +960,7 @@ namespace ams::secmon {
|
||||
}
|
||||
|
||||
void SetupLogForBoot() {
|
||||
log::Initialize();
|
||||
log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate(), secmon::GetLogFlags());
|
||||
log::SendText("OHAYO\n", 6);
|
||||
log::Flush();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_IcosaSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaMicron4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_AulaHynix1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
|
||||
[fuse::DramId_CopperHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperMicron4GB] = pkg1::MemorySize_4GB,
|
||||
@@ -66,9 +66,13 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBY] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y8GBY] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBA] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_AulaSamsung1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_AulaSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_AulaMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_AulaSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
};
|
||||
|
||||
constexpr const pkg1::MemoryMode MemoryModes[] = {
|
||||
@@ -278,6 +282,10 @@ namespace ams::secmon::smc {
|
||||
return SmcResult::NotInitialized;
|
||||
}
|
||||
break;
|
||||
case ConfigItem::ExosphereLogConfiguration:
|
||||
/* Get the log configuration. */
|
||||
args.r[1] = (static_cast<u64>(static_cast<u8>(secmon::GetLogPort())) << 32) | static_cast<u64>(secmon::GetLogBaudRate());
|
||||
break;
|
||||
default:
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
|
||||
@@ -40,15 +40,16 @@ namespace ams::secmon::smc {
|
||||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
};
|
||||
|
||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||
|
||||
@@ -409,6 +409,7 @@ namespace ams::secmon::smc {
|
||||
/* NOTE: Nintendo only does this on dev, but we will always do it. */
|
||||
if (true /* !pkg1::IsProduction() */) {
|
||||
log::SendText("OYASUMI\n", 8);
|
||||
log::Flush();
|
||||
}
|
||||
|
||||
/* If we're on erista, configure the bootrom to allow our custom warmboot firmware. */
|
||||
|
||||
@@ -37,24 +37,25 @@ static char g_bct0_buffer[BCTO_MAX_SIZE];
|
||||
|
||||
#define CONFIG_LOG_LEVEL_KEY "log_level"
|
||||
|
||||
#define DEFAULT_BCT0 \
|
||||
"BCT0\n"\
|
||||
"[stage1]\n"\
|
||||
"stage2_path = atmosphere/fusee-secondary.bin\n"\
|
||||
"stage2_mtc_path = atmosphere/fusee-mtc.bin\n"\
|
||||
"stage2_addr = 0xF0000000\n"\
|
||||
"stage2_entrypoint = 0xF0000000\n"\
|
||||
"[exosphere]\n"\
|
||||
"debugmode = 1\n"\
|
||||
"debugmode_user = 0\n"\
|
||||
"disable_user_exception_handlers = 0\n"\
|
||||
"[stratosphere]\n"
|
||||
static const char *get_default_bct0(void) {
|
||||
return "BCT0\n"
|
||||
"[stage1]\n"
|
||||
"stage2_path = atmosphere/fusee-secondary.bin\n"
|
||||
"stage2_mtc_path = atmosphere/fusee-mtc.bin\n"
|
||||
"stage2_addr = 0xF0000000\n"
|
||||
"stage2_entrypoint = 0xF0000000\n"
|
||||
"\n"
|
||||
"[stratosphere]\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
static const char *load_config(void) {
|
||||
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "atmosphere/config/BCT.ini")) {
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n");
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n");
|
||||
memcpy(g_bct0_buffer, DEFAULT_BCT0, sizeof(DEFAULT_BCT0));
|
||||
|
||||
const char * const default_bct0 = get_default_bct0();
|
||||
memcpy(g_bct0_buffer, default_bct0, strlen(default_bct0));
|
||||
}
|
||||
|
||||
if (memcmp(g_bct0_buffer, "BCT0", 4) != 0) {
|
||||
|
||||
@@ -217,7 +217,7 @@ sept_primary.bin.o sept_primary_bin.h: sept-primary.bin
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary_00.enc.o sept_secondary_00.h: sept-secondary_00.enc
|
||||
sept_secondary_00.enc.o sept_secondary_00_enc.h: sept-secondary_00.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
@@ -88,6 +88,9 @@ typedef enum {
|
||||
FS_VER_10_2_0,
|
||||
FS_VER_10_2_0_EXFAT,
|
||||
|
||||
FS_VER_11_0_0,
|
||||
FS_VER_11_0_0_EXFAT,
|
||||
|
||||
FS_VER_MAX,
|
||||
} emummc_fs_ver_t;
|
||||
|
||||
|
||||
@@ -34,11 +34,17 @@
|
||||
#define EXOSPHERE_FLAG_BLANK_PRODINFO (1 << 5u)
|
||||
#define EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC (1 << 6u)
|
||||
|
||||
#define EXOSPHERE_LOG_FLAG_INVERTED (1 << 0u)
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t target_firmware;
|
||||
uint32_t flags;
|
||||
uint32_t reserved[5];
|
||||
uint32_t flags[2];
|
||||
uint16_t lcd_vendor;
|
||||
uint8_t log_port;
|
||||
uint8_t log_flags;
|
||||
uint32_t log_baud_rate;
|
||||
uint32_t reserved1[2];
|
||||
exo_emummc_config_t emummc_cfg;
|
||||
} exosphere_config_t;
|
||||
|
||||
@@ -54,6 +60,9 @@ _Static_assert(sizeof(exosphere_config_t) == 0x20 + sizeof(exo_emummc_config_t),
|
||||
#define EXOSPHERE_BLANK_PRODINFO_SYSMMC_KEY "blank_prodinfo_sysmmc"
|
||||
#define EXOSPHERE_BLANK_PRODINFO_EMUMMC_KEY "blank_prodinfo_emummc"
|
||||
#define EXOSPHERE_ALLOW_WRITING_TO_CAL_SYSMMC_KEY "allow_writing_to_cal_sysmmc"
|
||||
#define EXOSPHERE_LOG_PORT_KEY "log_port"
|
||||
#define EXOSPHERE_LOG_BAUD_RATE_KEY "log_baud_rate"
|
||||
#define EXOSPHERE_LOG_INVERTED_KEY "log_inverted"
|
||||
|
||||
typedef struct {
|
||||
int debugmode;
|
||||
@@ -63,6 +72,9 @@ typedef struct {
|
||||
int blank_prodinfo_sysmmc;
|
||||
int blank_prodinfo_emummc;
|
||||
int allow_writing_to_cal_sysmmc;
|
||||
int log_port;
|
||||
int log_baud_rate;
|
||||
int log_inverted;
|
||||
} exosphere_parse_cfg_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -423,6 +423,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
|
||||
|
||||
"\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", /* FS_VER_10_2_0 */
|
||||
"\x16\x0D\x3E\x10\x4E\xAD\x61\x76", /* FS_VER_10_2_0_EXFAT */
|
||||
|
||||
"\xE3\x99\x15\x6E\x84\x4E\xB0\xAA", /* FS_VER_11_0_0 */
|
||||
"\x0B\xA1\x5B\xB3\x04\xB5\x05\x63", /* FS_VER_11_0_0_EXFAT */
|
||||
};
|
||||
|
||||
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
||||
|
||||
@@ -541,6 +541,60 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_send)[] = {0xA9B
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1000, proc_id_recv)[] = {0x88, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1C, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x87, 0x40, 0xF9, 0x08, 0x49, 0x3A, 0x8B, 0x09, 0xFC, 0x60, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x80]
|
||||
mov w10, #3
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x21]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x21
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send)[] = {0xE0, 0x03, 0x15, 0xAA, 0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0x88, 0x4A, 0x3C, 0x8B, 0x09, 0xFC, 0x60, 0xD3, 0x00, 0x25, 0x00, 0x29};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9BF2FEA, 0xF94043EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0xE0]
|
||||
mov w10, #3
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x24]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x24
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x7F, 0x40, 0xF9, 0x09, 0xFC, 0x60, 0xD3, 0xEA, 0x5B, 0x40, 0xF9};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)[] = {0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/* svcControlCodeMemory Patches */
|
||||
/* b.eq -> nop */
|
||||
@@ -550,6 +604,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory)[] = {MAKE_NOP};
|
||||
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, system_memory_increase)[] = {0x52A3C008}; /* MOV W8, #0x1E000000 */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
||||
@@ -557,6 +612,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(700, system_memory_increase)[
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase)[] = {0x52A3B015}; /* MOV W21, #0x1D800000 */
|
||||
|
||||
/* Hook Definitions. */
|
||||
static const kernel_patch_t g_kernel_patches_100[] = {
|
||||
@@ -821,6 +877,64 @@ static const kernel_patch_t g_kernel_patches_1000[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const kernel_patch_t g_kernel_patches_1100[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory),
|
||||
.patch_offset = 0x2FCE0,
|
||||
},
|
||||
{ /* System Memory Increase Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase),
|
||||
.patch_offset = 0x490C4,
|
||||
}
|
||||
};
|
||||
|
||||
static const kernel_patch_t g_kernel_patches_1101[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory),
|
||||
.patch_offset = 0x2FD04,
|
||||
},
|
||||
{ /* System Memory Increase Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase),
|
||||
.patch_offset = 0x490C4,
|
||||
}
|
||||
};
|
||||
|
||||
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
||||
|
||||
/* Kernel Infos. */
|
||||
@@ -906,6 +1020,24 @@ static const kernel_info_t g_kernel_infos[] = {
|
||||
.embedded_ini_ptr = 0x178,
|
||||
.free_code_space_offset = 0x67790,
|
||||
KERNEL_PATCHES(1000)
|
||||
},
|
||||
{ /* 11.0.0. */
|
||||
.hash = {0xC2, 0x0E, 0xB3, 0x1B, 0xBF, 0x0B, 0x82, 0xF3, 0x3D, 0xFD, 0x47, 0x04, 0xB4, 0x44, 0x38, 0x47, 0x64, 0xAB, 0xD8, 0x70, 0x2F, 0x0E, 0x0C, 0x37, 0x82, 0x28, 0x02, 0x24, 0xB8, 0x6E, 0xCE, 0x05, },
|
||||
.hash_offset = 0x1C4,
|
||||
.hash_size = 0x69000 - 0x1C4,
|
||||
.embedded_ini_offset = 0x69000,
|
||||
.embedded_ini_ptr = 0x180,
|
||||
.free_code_space_offset = 0x49EE8,
|
||||
KERNEL_PATCHES(1100)
|
||||
},
|
||||
{ /* 11.0.1. */
|
||||
.hash = {0x68, 0xB9, 0x72, 0xB7, 0x97, 0x55, 0x87, 0x5E, 0x24, 0x95, 0x8D, 0x99, 0x0A, 0x77, 0xAB, 0xF1, 0xC5, 0xC1, 0x32, 0x80, 0x67, 0xF0, 0xA2, 0xEC, 0x9C, 0xEF, 0xC3, 0x22, 0xE3, 0x42, 0xC0, 0x4D, },
|
||||
.hash_offset = 0x1C4,
|
||||
.hash_size = 0x69000 - 0x1C4,
|
||||
.embedded_ini_offset = 0x69000,
|
||||
.embedded_ini_ptr = 0x180,
|
||||
.free_code_space_offset = 0x49EE8,
|
||||
KERNEL_PATCHES(1101)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -967,13 +1099,6 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
||||
}
|
||||
|
||||
if (kernel_info->embedded_ini_offset != 0) {
|
||||
/* Copy in our kernel loader. */
|
||||
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
|
||||
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
|
||||
|
||||
/* Update size. */
|
||||
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
||||
|
||||
/* Set output INI ptr. */
|
||||
*out_ini1 = (void *)((uintptr_t)_kernel + kernel_info->embedded_ini_offset);
|
||||
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)*kernel_size;
|
||||
@@ -1003,7 +1128,7 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
||||
|
||||
uint8_t *pattern_loc = search_pattern(kernel, *kernel_size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||
if (pattern_loc == NULL) {
|
||||
/* TODO: Should we print an error/abort here? */
|
||||
fatal_error("kernel_patcher: failed to identify patch location!\n");
|
||||
continue;
|
||||
}
|
||||
/* Patch kernel to branch to our hook at the desired place. */
|
||||
|
||||
@@ -70,6 +70,18 @@ static void exit_callback(int rc) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_default_bct0(void) {
|
||||
return "BCT0\n"
|
||||
"[stage1]\n"
|
||||
"stage2_path = atmosphere/fusee-secondary.bin\n"
|
||||
"stage2_mtc_path = atmosphere/fusee-mtc.bin\n"
|
||||
"stage2_addr = 0xF0000000\n"
|
||||
"stage2_entrypoint = 0xF0000000\n"
|
||||
"\n"
|
||||
"[stratosphere]\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
/* Allow for main(int argc, void **argv) signature. */
|
||||
#pragma GCC diagnostic ignored "-Wmain"
|
||||
|
||||
@@ -102,7 +114,8 @@ int main(int argc, void **argv) {
|
||||
if (strcmp(g_stage2_args->bct0, "") == 0) {
|
||||
uint32_t bct_tmp_buf[sizeof(g_stage2_args->bct0) / sizeof(uint32_t)] = {0};
|
||||
if (!read_from_file(bct_tmp_buf, sizeof(bct_tmp_buf) - 1, "atmosphere/config/BCT.ini")) {
|
||||
fatal_error("Failed to read BCT0 from SD!\n");
|
||||
const char * const default_bct0 = get_default_bct0();
|
||||
memcpy(bct_tmp_buf, default_bct0, strlen(default_bct0));
|
||||
}
|
||||
memcpy(g_stage2_args->bct0, bct_tmp_buf, sizeof(bct_tmp_buf));
|
||||
}
|
||||
|
||||
@@ -196,6 +196,27 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na
|
||||
} else if (tmp == 0) {
|
||||
parse_cfg->allow_writing_to_cal_sysmmc = 0;
|
||||
}
|
||||
} else if (strcmp(name, EXOSPHERE_LOG_PORT_KEY) == 0) {
|
||||
sscanf(value, "%d", &tmp);
|
||||
if (0 <= tmp && tmp < 4) {
|
||||
parse_cfg->log_port = tmp;
|
||||
} else {
|
||||
parse_cfg->log_port = 0;
|
||||
}
|
||||
} else if (strcmp(name, EXOSPHERE_LOG_BAUD_RATE_KEY) == 0) {
|
||||
sscanf(value, "%d", &tmp);
|
||||
if (tmp > 0) {
|
||||
parse_cfg->log_baud_rate = tmp;
|
||||
} else {
|
||||
parse_cfg->log_baud_rate = 115200;
|
||||
}
|
||||
} else if (strcmp(name, EXOSPHERE_LOG_INVERTED_KEY) == 0) {
|
||||
sscanf(value, "%d", &tmp);
|
||||
if (tmp == 1) {
|
||||
parse_cfg->log_inverted = 1;
|
||||
} else if (tmp == 0) {
|
||||
parse_cfg->log_inverted = 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -239,7 +260,10 @@ static bool is_nca_present(const char *nca_name) {
|
||||
static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
|
||||
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
|
||||
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_11_0_0) {
|
||||
CHECK_NCA("56211c7a5ed20a5332f5cdda67121e37", 11_0_1);
|
||||
CHECK_NCA("594c90bcdbcccad6b062eadba0cd0e7e", 11_0_0);
|
||||
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
|
||||
CHECK_NCA("26325de4db3909e0ef2379787c7e671d", 10_2_0);
|
||||
CHECK_NCA("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
|
||||
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
|
||||
@@ -337,6 +361,8 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_9_1_0;
|
||||
} else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) {
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_10_0_0;
|
||||
} else if (memcmp(package1loader_header->build_timestamp, "20201030", 8) == 0) {
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_11_0_0;
|
||||
} else {
|
||||
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
||||
}
|
||||
@@ -460,9 +486,9 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
|
||||
const bool is_emummc = exo_emummc_cfg->base_cfg.magic == MAGIC_EMUMMC_CONFIG && exo_emummc_cfg->base_cfg.type != EMUMMC_TYPE_NONE;
|
||||
|
||||
if (keygen_type) {
|
||||
exo_cfg.flags = EXOSPHERE_FLAG_PERFORM_620_KEYGEN;
|
||||
exo_cfg.flags[0] = EXOSPHERE_FLAG_PERFORM_620_KEYGEN;
|
||||
} else {
|
||||
exo_cfg.flags = 0;
|
||||
exo_cfg.flags[0] = 0;
|
||||
}
|
||||
|
||||
/* Setup exosphere parse configuration with defaults. */
|
||||
@@ -474,6 +500,9 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
|
||||
.blank_prodinfo_sysmmc = 0,
|
||||
.blank_prodinfo_emummc = 0,
|
||||
.allow_writing_to_cal_sysmmc = 0,
|
||||
.log_port = 0,
|
||||
.log_baud_rate = 115200,
|
||||
.log_inverted = 0,
|
||||
};
|
||||
|
||||
/* If we have an ini to read, parse it. */
|
||||
@@ -486,13 +515,17 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
|
||||
free(exosphere_ini);
|
||||
|
||||
/* Apply parse config. */
|
||||
if (parse_cfg.debugmode) exo_cfg.flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV;
|
||||
if (parse_cfg.debugmode_user) exo_cfg.flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_USER;
|
||||
if (parse_cfg.disable_user_exception_handlers) exo_cfg.flags |= EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS;
|
||||
if (parse_cfg.enable_user_pmu_access) exo_cfg.flags |= EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS;
|
||||
if (parse_cfg.blank_prodinfo_sysmmc && !is_emummc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO;
|
||||
if (parse_cfg.blank_prodinfo_emummc && is_emummc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO;
|
||||
if (parse_cfg.allow_writing_to_cal_sysmmc) exo_cfg.flags |= EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC;
|
||||
if (parse_cfg.debugmode) exo_cfg.flags[0] |= EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV;
|
||||
if (parse_cfg.debugmode_user) exo_cfg.flags[0] |= EXOSPHERE_FLAG_IS_DEBUGMODE_USER;
|
||||
if (parse_cfg.disable_user_exception_handlers) exo_cfg.flags[0] |= EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS;
|
||||
if (parse_cfg.enable_user_pmu_access) exo_cfg.flags[0] |= EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS;
|
||||
if (parse_cfg.blank_prodinfo_sysmmc && !is_emummc) exo_cfg.flags[0] |= EXOSPHERE_FLAG_BLANK_PRODINFO;
|
||||
if (parse_cfg.blank_prodinfo_emummc && is_emummc) exo_cfg.flags[0] |= EXOSPHERE_FLAG_BLANK_PRODINFO;
|
||||
if (parse_cfg.allow_writing_to_cal_sysmmc) exo_cfg.flags[0] |= EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC;
|
||||
|
||||
exo_cfg.log_port = parse_cfg.log_port;
|
||||
exo_cfg.log_baud_rate = parse_cfg.log_baud_rate;
|
||||
if (parse_cfg.log_inverted) exo_cfg.log_flags |= EXOSPHERE_LOG_FLAG_INVERTED;
|
||||
|
||||
if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) {
|
||||
fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n");
|
||||
@@ -521,6 +554,10 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) {
|
||||
kip_patches_set_enable_nogc();
|
||||
}
|
||||
/* Check if the fuses are < 11.0.0, but firmware is >= 11.0.0 */
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_11_0_0 && !(fuse_get_reserved_odm(7) & ~0x00001FFF)) {
|
||||
kip_patches_set_enable_nogc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
|
||||
|
||||
/* Perform version checks. */
|
||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1000_CURRENT) {
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1100_CURRENT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
#define PACKAGE2_MAXVER_810 0xB
|
||||
#define PACKAGE2_MAXVER_900 0xC
|
||||
#define PACKAGE2_MAXVER_910_920 0xD
|
||||
#define PACKAGE2_MAXVER_1000_CURRENT 0xE
|
||||
#define PACKAGE2_MAXVER_1000 0xE
|
||||
#define PACKAGE2_MAXVER_1100_CURRENT 0xF
|
||||
|
||||
#define PACKAGE2_MINVER_100 0x3
|
||||
#define PACKAGE2_MINVER_200 0x4
|
||||
@@ -54,7 +55,8 @@
|
||||
#define PACKAGE2_MINVER_810 0xC
|
||||
#define PACKAGE2_MINVER_900 0xD
|
||||
#define PACKAGE2_MINVER_910_920 0xE
|
||||
#define PACKAGE2_MINVER_1000_CURRENT 0xF
|
||||
#define PACKAGE2_MINVER_1000 0xF
|
||||
#define PACKAGE2_MINVER_1100_CURRENT 0x10
|
||||
|
||||
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||
commit = b05ba02f044beb03b3e228a660c0c28d0b1efe0d
|
||||
parent = f2a6a4a6e60bfe0dea11ba3a0ff56c95a5871a6c
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -108,15 +108,17 @@ BUILD := build
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1/os $1/cpu $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
|
||||
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1/os $1/cpu $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(filter-out $d,$(call GENERAL_SOURCE_DIRS,$d)) $d,))
|
||||
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/$3/.*),$1/$2/$3 $(call DIR_WILDCARD,$1/$2/$3),$(if $(wildcard $1/$2/generic/.*), $1/$2/generic $(call DIR_WILDCARD,$1/$2/generic),))
|
||||
UNFILTERED_SOURCE_DIRS=$1 $(foreach d,$(wildcard $1/*),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
|
||||
|
||||
ALL_SOURCE_DIRS=$(call GENERAL_SOURCE_DIRS,$1) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$1,arch,$(ATMOSPHERE_ARCH_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$1,board,$(ATMOSPHERE_BOARD_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$1,os,$(ATMOSPHERE_OS_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$1,cpu,$(ATMOSPHERE_ARCH_DIR)/$(ATMOSPHERE_CPU_DIR))
|
||||
ALL_SOURCE_DIRS=$(foreach d,$(call GENERAL_SOURCE_DIRS,$1), \
|
||||
$d \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$d,arch,$(ATMOSPHERE_ARCH_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$d,board,$(ATMOSPHERE_BOARD_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$d,os,$(ATMOSPHERE_OS_DIR)) \
|
||||
$(call SPECIFIC_SOURCE_DIRS,$d,cpu,$(ATMOSPHERE_ARCH_DIR)/$(ATMOSPHERE_CPU_DIR)) \
|
||||
)
|
||||
|
||||
SOURCES ?= $(call ALL_SOURCE_DIRS,source)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace ams::fuse {
|
||||
HardwareType_Hoag = 2,
|
||||
HardwareType_Iowa = 3,
|
||||
HardwareType_Calcio = 4,
|
||||
HardwareType_Five = 5,
|
||||
HardwareType_Aula = 5,
|
||||
|
||||
HardwareType_Undefined = 0xF,
|
||||
};
|
||||
@@ -51,7 +51,7 @@ namespace ams::fuse {
|
||||
DramId_IcosaSamsung4GB = 0,
|
||||
DramId_IcosaHynix4GB = 1,
|
||||
DramId_IcosaMicron4GB = 2,
|
||||
DramId_CopperSamsung4GB = 3,
|
||||
DramId_AulaHynix1y4GB = 3,
|
||||
DramId_IcosaSamsung6GB = 4,
|
||||
DramId_CopperHynix4GB = 5,
|
||||
DramId_CopperMicron4GB = 6,
|
||||
@@ -70,9 +70,13 @@ namespace ams::fuse {
|
||||
DramId_HoagSamsung1y4GBX = 19,
|
||||
DramId_IowaSamsung1y4GBY = 20,
|
||||
DramId_IowaSamsung1y8GBY = 21,
|
||||
DramId_IowaSamsung1y4GBA = 22,
|
||||
DramId_FiveSamsung1y8GBX = 23,
|
||||
DramId_FiveSamsung1y4GBX = 24,
|
||||
DramId_AulaSamsung1y4GB = 22,
|
||||
DramId_HoagSamsung1y8GBX = 23,
|
||||
DramId_AulaSamsung1y4GBX = 24,
|
||||
DramId_IowaMicron1y4GB = 25,
|
||||
DramId_HoagMicron1y4GB = 26,
|
||||
DramId_AulaMicron1y4GB = 27,
|
||||
DramId_AulaSamsung1y8GBX = 28,
|
||||
|
||||
DramId_Count,
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace ams::log {
|
||||
#endif
|
||||
|
||||
void Initialize();
|
||||
void Initialize(uart::Port port, u32 baud_rate, u32 flags);
|
||||
void Finalize();
|
||||
|
||||
void Printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
@@ -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 0x10 in Nintendo's code. */
|
||||
constexpr inline int CurrentBootloaderVersion = 0xD;
|
||||
constexpr inline int CurrentBootloaderVersion = 0xE;
|
||||
|
||||
struct Package2Meta {
|
||||
using Magic = util::FourCC<'P','K','2','1'>;
|
||||
|
||||
@@ -116,6 +116,18 @@ namespace ams::secmon {
|
||||
return GetSecmonConfiguration().GetLcdVendor();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE uart::Port GetLogPort() {
|
||||
return GetSecmonConfiguration().GetLogPort();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u8 GetLogFlags() {
|
||||
return GetSecmonConfiguration().GetLogFlags();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u32 GetLogBaudRate() {
|
||||
return GetSecmonConfiguration().GetLogBaudRate();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool IsProduction() {
|
||||
return GetSecmonConfiguration().IsProduction();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <exosphere/fuse.hpp>
|
||||
#include <exosphere/uart.hpp>
|
||||
#include <exosphere/secmon/secmon_emummc_context.hpp>
|
||||
|
||||
namespace ams::secmon {
|
||||
@@ -39,8 +40,10 @@ namespace ams::secmon {
|
||||
ams::TargetFirmware target_firmware;
|
||||
u32 flags[2];
|
||||
u16 lcd_vendor;
|
||||
u16 reserved0;
|
||||
u32 reserved1[3];
|
||||
u8 log_port;
|
||||
u8 log_flags;
|
||||
u32 log_baud_rate;
|
||||
u32 reserved1[2];
|
||||
EmummcConfiguration emummc_cfg;
|
||||
|
||||
constexpr bool IsValid() const { return this->magic == Magic; }
|
||||
@@ -54,17 +57,22 @@ namespace ams::secmon {
|
||||
u8 hardware_type;
|
||||
u8 soc_type;
|
||||
u8 hardware_state;
|
||||
u8 pad_0B[1];
|
||||
u8 log_port;
|
||||
u32 flags[2];
|
||||
u16 lcd_vendor;
|
||||
u16 reserved0;
|
||||
u32 reserved1[(0x80 - 0x18) / sizeof(u32)];
|
||||
u8 log_flags;
|
||||
u8 reserved0;
|
||||
u32 log_baud_rate;
|
||||
u32 reserved1[(0x80 - 0x1C) / sizeof(u32)];
|
||||
|
||||
constexpr void CopyFrom(const SecureMonitorStorageConfiguration &storage) {
|
||||
this->target_firmware = storage.target_firmware;
|
||||
this->flags[0] = storage.flags[0];
|
||||
this->flags[1] = storage.flags[1];
|
||||
this->lcd_vendor = storage.lcd_vendor;
|
||||
this->log_port = storage.log_port;
|
||||
this->log_flags = storage.log_flags;
|
||||
this->log_baud_rate = storage.log_baud_rate != 0 ? storage.log_baud_rate : 115200;
|
||||
}
|
||||
|
||||
void SetFuseInfo() {
|
||||
@@ -78,9 +86,13 @@ namespace ams::secmon {
|
||||
constexpr fuse::HardwareType GetHardwareType() const { return static_cast<fuse::HardwareType>(this->hardware_type); }
|
||||
constexpr fuse::SocType GetSocType() const { return static_cast<fuse::SocType>(this->soc_type); }
|
||||
constexpr fuse::HardwareState GetHardwareState() const { return static_cast<fuse::HardwareState>(this->hardware_state); }
|
||||
constexpr uart::Port GetLogPort() const { return static_cast<uart::Port>(this->log_port); }
|
||||
constexpr u8 GetLogFlags() const { return this->log_flags; }
|
||||
|
||||
constexpr u16 GetLcdVendor() const { return this->lcd_vendor; }
|
||||
|
||||
constexpr u32 GetLogBaudRate() const { return this->log_baud_rate; }
|
||||
|
||||
constexpr bool IsProduction() const { return this->GetHardwareState() != fuse::HardwareState_Development; }
|
||||
|
||||
constexpr bool IsDevelopmentFunctionEnabledForKernel() const { return (this->flags[0] & SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel) != 0; }
|
||||
@@ -101,10 +113,12 @@ namespace ams::secmon {
|
||||
.hardware_type = {},
|
||||
.soc_type = {},
|
||||
.hardware_state = {},
|
||||
.pad_0B = {},
|
||||
.log_port = uart::Port_ReservedDebug,
|
||||
.flags = { SecureMonitorConfigurationFlag_Default, SecureMonitorConfigurationFlag_None },
|
||||
.lcd_vendor = {},
|
||||
.log_flags = {},
|
||||
.reserved0 = {},
|
||||
.log_baud_rate = 115200,
|
||||
.reserved1 = {},
|
||||
};
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace ams::fuse {
|
||||
}
|
||||
|
||||
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
|
||||
TargetFirmware_11_0_0,
|
||||
TargetFirmware_10_0_0,
|
||||
TargetFirmware_9_1_0,
|
||||
TargetFirmware_9_0_0,
|
||||
@@ -207,7 +208,7 @@ namespace ams::fuse {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_10_0_0) == 13);
|
||||
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_11_0_0) == 14);
|
||||
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_1_0_0) == 1);
|
||||
static_assert(GetExpectedFuseVersionImpl(static_cast<TargetFirmware>(0)) == 0);
|
||||
|
||||
@@ -315,7 +316,7 @@ namespace ams::fuse {
|
||||
case 0x02: return (true /* TODO: GetSocType() == SocType_Mariko */) ? HardwareType_Calcio : HardwareType_Copper;
|
||||
case 0x04: return HardwareType_Iowa;
|
||||
case 0x08: return HardwareType_Hoag;
|
||||
case 0x10: return HardwareType_Five;
|
||||
case 0x10: return HardwareType_Aula;
|
||||
default: return HardwareType_Undefined;
|
||||
}
|
||||
}
|
||||
@@ -370,7 +371,7 @@ namespace ams::fuse {
|
||||
case HardwareType_Iowa:
|
||||
case HardwareType_Hoag:
|
||||
case HardwareType_Calcio:
|
||||
case HardwareType_Five:
|
||||
case HardwareType_Aula:
|
||||
return SocType_Mariko;
|
||||
default:
|
||||
return SocType_Undefined;
|
||||
|
||||
@@ -19,58 +19,46 @@ namespace ams::log {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline uart::Port UartLogPort = uart::Port_ReservedDebug;
|
||||
constexpr inline int UartBaudRate = 115200;
|
||||
constexpr inline uart::Port DefaultLogPort = uart::Port_ReservedDebug;
|
||||
constexpr inline u32 DefaultLogFlags = static_cast<u32>(uart::Flag_None);
|
||||
constexpr inline int DefaultBaudRate = 115200;
|
||||
constinit uart::Port g_log_port = DefaultLogPort;
|
||||
constinit bool g_initialized_uart = false;
|
||||
|
||||
constexpr inline u32 UartPortFlags = [] {
|
||||
if constexpr (UartLogPort == uart::Port_ReservedDebug) {
|
||||
/* Logging to the debug port. */
|
||||
/* Don't invert transactions. */
|
||||
return uart::Flag_None;
|
||||
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
|
||||
/* Logging to left joy-con (e.g. with Joyless). */
|
||||
/* Invert transactions. */
|
||||
return uart::Flag_Inverted;
|
||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
||||
/* Logging to right joy-con (e.g. with Joyless). */
|
||||
/* Invert transactions. */
|
||||
return uart::Flag_Inverted;
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}();
|
||||
ALWAYS_INLINE void SetupUartClock(uart::Port port) {
|
||||
/* The debug port must always be set up, for compatibility with official hos. */
|
||||
pinmux::SetupUartA();
|
||||
clkrst::EnableUartAClock();
|
||||
|
||||
ALWAYS_INLINE void SetupUart() {
|
||||
if constexpr (UartLogPort == uart::Port_ReservedDebug) {
|
||||
/* Logging to the debug port. */
|
||||
pinmux::SetupUartA();
|
||||
clkrst::EnableUartAClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
|
||||
/* If logging to a joy-con port, configure appropriately. */
|
||||
if (port == uart::Port_LeftJoyCon) {
|
||||
/* Logging to left joy-con (e.g. with Joyless). */
|
||||
static_assert(uart::Port_LeftJoyCon == uart::Port_C);
|
||||
pinmux::SetupUartC();
|
||||
clkrst::EnableUartCClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
||||
} else if (port == uart::Port_RightJoyCon) {
|
||||
/* Logging to right joy-con (e.g. with Joyless). */
|
||||
static_assert(uart::Port_RightJoyCon == uart::Port_B);
|
||||
pinmux::SetupUartB();
|
||||
clkrst::EnableUartBClock();
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
return Initialize(DefaultLogPort, DefaultBaudRate, DefaultLogFlags);
|
||||
}
|
||||
|
||||
void Initialize(uart::Port port, u32 baud_rate, u32 flags) {
|
||||
/* Initialize pinmux and clock for the target uart port. */
|
||||
SetupUart();
|
||||
SetupUartClock(port);
|
||||
|
||||
/* Initialize the target uart port. */
|
||||
uart::Initialize(UartLogPort, UartBaudRate, UartPortFlags);
|
||||
uart::Initialize(port, baud_rate, flags);
|
||||
|
||||
/* Note that we've initialized. */
|
||||
g_log_port = port;
|
||||
g_initialized_uart = true;
|
||||
}
|
||||
|
||||
@@ -84,7 +72,7 @@ namespace ams::log {
|
||||
const auto len = util::TVSNPrintf(log_buf, sizeof(log_buf), fmt, vl);
|
||||
|
||||
if (g_initialized_uart) {
|
||||
uart::SendText(UartLogPort, log_buf, len);
|
||||
uart::SendText(g_log_port, log_buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +103,13 @@ namespace ams::log {
|
||||
|
||||
void SendText(const void *text, size_t size) {
|
||||
if (g_initialized_uart) {
|
||||
uart::SendText(UartLogPort, text, size);
|
||||
uart::SendText(g_log_port, text, size);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
if (g_initialized_uart) {
|
||||
uart::WaitFlush(UartLogPort);
|
||||
uart::WaitFlush(g_log_port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
SOURCES += $(call ALL_SOURCE_DIRS,../libvapours/source)
|
||||
SOURCES += $(foreach v,$(call ALL_SOURCE_DIRS,../libvapours/source),$(if $(findstring ../libvapours/source/sdmmc,$v),,$v))
|
||||
|
||||
LIBS :=
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
#include <mesosphere/kern_k_spin_lock.hpp>
|
||||
#include <mesosphere/kern_k_memory_manager.hpp>
|
||||
#include <mesosphere/kern_k_interrupt_task_manager.hpp>
|
||||
#include <mesosphere/kern_k_core_local_region.hpp>
|
||||
#include <mesosphere/kern_k_slab_heap.hpp>
|
||||
#include <mesosphere/kern_k_light_lock.hpp>
|
||||
#include <mesosphere/kern_k_dpc_manager.hpp>
|
||||
#include <mesosphere/kern_kernel.hpp>
|
||||
#include <mesosphere/kern_k_page_table_manager.hpp>
|
||||
#include <mesosphere/kern_select_page_table.hpp>
|
||||
#include <mesosphere/kern_k_dump_object.hpp>
|
||||
|
||||
/* Miscellaneous objects. */
|
||||
#include <mesosphere/kern_k_shared_memory_info.hpp>
|
||||
@@ -78,7 +78,8 @@
|
||||
#include <mesosphere/kern_select_debug.hpp>
|
||||
#include <mesosphere/kern_k_process.hpp>
|
||||
#include <mesosphere/kern_k_resource_limit.hpp>
|
||||
#include <mesosphere/kern_k_synchronization.hpp>
|
||||
#include <mesosphere/kern_k_alpha.hpp>
|
||||
#include <mesosphere/kern_k_beta.hpp>
|
||||
|
||||
/* More Miscellaneous objects. */
|
||||
#include <mesosphere/kern_k_object_name.hpp>
|
||||
|
||||
@@ -135,10 +135,10 @@ namespace ams::kern::arch::arm {
|
||||
private:
|
||||
static inline u32 s_mask[cpu::NumCores];
|
||||
private:
|
||||
volatile GicDistributor *gicd;
|
||||
volatile GicCpuInterface *gicc;
|
||||
volatile GicDistributor *m_gicd;
|
||||
volatile GicCpuInterface *m_gicc;
|
||||
public:
|
||||
constexpr KInterruptController() : gicd(nullptr), gicc(nullptr) { /* ... */ }
|
||||
constexpr KInterruptController() : m_gicd(nullptr), m_gicc(nullptr) { /* ... */ }
|
||||
|
||||
void Initialize(s32 core_id);
|
||||
void Finalize(s32 core_id);
|
||||
@@ -149,7 +149,7 @@ namespace ams::kern::arch::arm {
|
||||
void RestoreGlobal(const GlobalState *state) const;
|
||||
public:
|
||||
u32 GetIrq() const {
|
||||
return this->gicc->iar;
|
||||
return m_gicc->iar;
|
||||
}
|
||||
|
||||
static constexpr s32 ConvertRawIrq(u32 irq) {
|
||||
@@ -157,69 +157,69 @@ namespace ams::kern::arch::arm {
|
||||
}
|
||||
|
||||
void Enable(s32 irq) const {
|
||||
this->gicd->isenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
m_gicd->isenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
}
|
||||
|
||||
void Disable(s32 irq) const {
|
||||
this->gicd->icenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
m_gicd->icenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
}
|
||||
|
||||
void Clear(s32 irq) const {
|
||||
this->gicd->icpendr[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
m_gicd->icpendr[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
|
||||
}
|
||||
|
||||
void SetTarget(s32 irq, s32 core_id) const {
|
||||
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] | GetGicMask(core_id);
|
||||
m_gicd->itargetsr.bytes[irq] = m_gicd->itargetsr.bytes[irq] | GetGicMask(core_id);
|
||||
}
|
||||
|
||||
void ClearTarget(s32 irq, s32 core_id) const {
|
||||
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] & ~GetGicMask(core_id);
|
||||
m_gicd->itargetsr.bytes[irq] = m_gicd->itargetsr.bytes[irq] & ~GetGicMask(core_id);
|
||||
}
|
||||
|
||||
void SetPriorityLevel(s32 irq, s32 level) const {
|
||||
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
|
||||
this->gicd->ipriorityr.bytes[irq] = ToGicPriorityValue(level);
|
||||
m_gicd->ipriorityr.bytes[irq] = ToGicPriorityValue(level);
|
||||
}
|
||||
|
||||
s32 GetPriorityLevel(s32 irq) const {
|
||||
return FromGicPriorityValue(this->gicd->ipriorityr.bytes[irq]);
|
||||
return FromGicPriorityValue(m_gicd->ipriorityr.bytes[irq]);
|
||||
}
|
||||
|
||||
void SetPriorityLevel(s32 level) const {
|
||||
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
|
||||
this->gicc->pmr = ToGicPriorityValue(level);
|
||||
m_gicc->pmr = ToGicPriorityValue(level);
|
||||
}
|
||||
|
||||
void SetEdge(s32 irq) const {
|
||||
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
|
||||
u32 cfg = m_gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
|
||||
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
|
||||
cfg |= (0x2 << (2 * (irq % (BITSIZEOF(u32) / 2))));
|
||||
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
|
||||
m_gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
|
||||
}
|
||||
|
||||
void SetLevel(s32 irq) const {
|
||||
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
|
||||
u32 cfg = m_gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
|
||||
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
|
||||
cfg |= (0x0 << (2 * (irq % (BITSIZEOF(u32) / 2))));
|
||||
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
|
||||
m_gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
|
||||
}
|
||||
|
||||
void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
|
||||
MESOSPHERE_ASSERT(IsSoftware(irq));
|
||||
this->gicd->sgir = GetCpuTargetListMask(irq, core_mask);
|
||||
m_gicd->sgir = GetCpuTargetListMask(irq, core_mask);
|
||||
}
|
||||
|
||||
void SendInterProcessorInterrupt(s32 irq) {
|
||||
MESOSPHERE_ASSERT(IsSoftware(irq));
|
||||
this->gicd->sgir = GicDistributor::SgirTargetListFilter_Others | irq;
|
||||
m_gicd->sgir = GicDistributor::SgirTargetListFilter_Others | irq;
|
||||
}
|
||||
|
||||
void EndOfInterrupt(u32 irq) const {
|
||||
this->gicc->eoir = irq;
|
||||
m_gicc->eoir = irq;
|
||||
}
|
||||
|
||||
bool IsInterruptDefined(s32 irq) const {
|
||||
const s32 num_interrupts = std::min(32 + 32 * (this->gicd->typer & 0x1F), static_cast<u32>(NumInterrupts));
|
||||
const s32 num_interrupts = std::min(32 + 32 * (m_gicd->typer & 0x1F), static_cast<u32>(NumInterrupts));
|
||||
return (0 <= irq && irq < num_interrupts);
|
||||
}
|
||||
public:
|
||||
@@ -270,7 +270,7 @@ namespace ams::kern::arch::arm {
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetGicMask(s32 core_id) const {
|
||||
s_mask[core_id] = this->gicd->itargetsr.bytes[0];
|
||||
s_mask[core_id] = m_gicd->itargetsr.bytes[0];
|
||||
}
|
||||
|
||||
NOINLINE void SetupInterruptLines(s32 core_id) const;
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace ams::kern::init {
|
||||
u64 entrypoint;
|
||||
u64 argument;
|
||||
u64 setup_function;
|
||||
u64 exception_stack;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -44,16 +44,16 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
struct NoClear{};
|
||||
private:
|
||||
KPhysicalAddress l1_table;
|
||||
KPhysicalAddress m_l1_table;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KInitialPageTable(KPhysicalAddress l1, NoClear) : l1_table(l1) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KInitialPageTable(KPhysicalAddress l1, NoClear) : m_l1_table(l1) { /* ... */ }
|
||||
|
||||
constexpr ALWAYS_INLINE KInitialPageTable(KPhysicalAddress l1) : KInitialPageTable(l1, NoClear{}) {
|
||||
ClearNewPageTable(this->l1_table);
|
||||
ClearNewPageTable(m_l1_table);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetL1TableAddress() const {
|
||||
return GetInteger(this->l1_table);
|
||||
return GetInteger(m_l1_table);
|
||||
}
|
||||
private:
|
||||
static constexpr ALWAYS_INLINE L1PageTableEntry *GetL1Entry(KPhysicalAddress _l1_table, KVirtualAddress address) {
|
||||
@@ -83,7 +83,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
||||
size_t count = 0;
|
||||
while (virt_addr < end_virt_addr) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
|
||||
if (l1_entry->IsBlock() || l1_entry->IsEmpty()) {
|
||||
@@ -137,7 +137,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
||||
size_t count = 0;
|
||||
while (virt_addr < end_virt_addr) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
|
||||
if (l1_entry->IsBlock() || l1_entry->IsEmpty()) {
|
||||
@@ -194,7 +194,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
}
|
||||
|
||||
PageTableEntry *GetMappingEntry(KVirtualAddress virt_addr, size_t block_size) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
if (l1_entry->IsBlock()) {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(block_size == L1BlockSize);
|
||||
@@ -301,11 +301,11 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
/* Iteratively map pages until the requested region is mapped. */
|
||||
while (size > 0) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* Can we make an L1 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && size >= L1BlockSize) {
|
||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L1BlockSize;
|
||||
@@ -327,7 +327,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
/* Can we make a contiguous L2 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && size >= L2ContiguousBlockSize) {
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, true);
|
||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, true);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
@@ -339,7 +339,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
/* Can we make an L2 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L2BlockSize) && util::IsAligned(GetInteger(phys_addr), L2BlockSize) && size >= L2BlockSize) {
|
||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
@@ -361,7 +361,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
/* Can we make a contiguous L3 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && size >= L3ContiguousBlockSize) {
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, true);
|
||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, true);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L3BlockSize;
|
||||
@@ -372,7 +372,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
}
|
||||
|
||||
/* Make an L3 block. */
|
||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
virt_addr += L3BlockSize;
|
||||
phys_addr += L3BlockSize;
|
||||
@@ -382,7 +382,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
KPhysicalAddress GetPhysicalAddress(KVirtualAddress virt_addr) const {
|
||||
/* Get the L1 entry. */
|
||||
const L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
const L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
if (l1_entry->IsBlock()) {
|
||||
return l1_entry->GetBlock() + (GetInteger(virt_addr) & (L1BlockSize - 1));
|
||||
@@ -444,7 +444,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
};
|
||||
|
||||
while (virt_addr < end_virt_addr) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* If an L1 block is mapped, update. */
|
||||
if (l1_entry->IsBlock()) {
|
||||
@@ -485,7 +485,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
||||
while (virt_addr < end_virt_addr) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* If an L1 block is mapped, the address isn't free. */
|
||||
if (l1_entry->IsBlock()) {
|
||||
@@ -534,7 +534,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
/* Iteratively reprotect pages until the requested region is reprotected. */
|
||||
while (size > 0) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(m_l1_table, virt_addr);
|
||||
|
||||
/* Check if an L1 block is present. */
|
||||
if (l1_entry->IsBlock()) {
|
||||
@@ -542,7 +542,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
const KPhysicalAddress block = l1_entry->GetBlock();
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L1BlockSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||
|
||||
/* Invalidate the existing L1 block. */
|
||||
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
|
||||
@@ -550,7 +550,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L1 block. */
|
||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
|
||||
virt_addr += L1BlockSize;
|
||||
size -= L1BlockSize;
|
||||
@@ -573,7 +573,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
/* Invalidate the existing contiguous L2 block. */
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
/* Ensure that the entry is valid. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, true));
|
||||
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
|
||||
}
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
@@ -581,7 +581,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
/* Create a new contiguous L2 block. */
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, block + L2BlockSize * i, attr_after, true);
|
||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, block + L2BlockSize * i, attr_after, PageTableEntry::SoftwareReservedBit_None, true);
|
||||
}
|
||||
|
||||
virt_addr += L2ContiguousBlockSize;
|
||||
@@ -591,7 +591,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L2BlockSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||
|
||||
/* Invalidate the existing L2 block. */
|
||||
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
|
||||
@@ -599,7 +599,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L2 block. */
|
||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
size -= L2BlockSize;
|
||||
@@ -625,7 +625,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
/* Invalidate the existing contiguous L3 block. */
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
/* Ensure that the entry is valid. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, true));
|
||||
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
|
||||
}
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
@@ -633,7 +633,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
|
||||
/* Create a new contiguous L3 block. */
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, block + L3BlockSize * i, attr_after, true);
|
||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, block + L3BlockSize * i, attr_after, PageTableEntry::SoftwareReservedBit_None, true);
|
||||
}
|
||||
|
||||
virt_addr += L3ContiguousBlockSize;
|
||||
@@ -643,7 +643,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L3BlockSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||
|
||||
/* Invalidate the existing L3 block. */
|
||||
*static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry;
|
||||
@@ -651,7 +651,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L3 block. */
|
||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||
|
||||
virt_addr += L3BlockSize;
|
||||
size -= L3BlockSize;
|
||||
@@ -668,6 +668,7 @@ namespace ams::kern::arch::arm64::init {
|
||||
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
||||
cpu::StoreEntireCacheForInit();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -679,43 +680,38 @@ namespace ams::kern::arch::arm64::init {
|
||||
uintptr_t free_bitmap;
|
||||
};
|
||||
private:
|
||||
State state;
|
||||
State m_state;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KInitialPageAllocator() : state{} { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KInitialPageAllocator() : m_state{} { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE void Initialize(uintptr_t address) {
|
||||
this->state.next_address = address + BITSIZEOF(this->state.free_bitmap) * PageSize;
|
||||
this->state.free_bitmap = ~uintptr_t();
|
||||
m_state.next_address = address + BITSIZEOF(m_state.free_bitmap) * PageSize;
|
||||
m_state.free_bitmap = ~uintptr_t();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) {
|
||||
if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
|
||||
this->state = *reinterpret_cast<State *>(state_val);
|
||||
} else {
|
||||
this->state.next_address = state_val;
|
||||
this->state.free_bitmap = 0;
|
||||
}
|
||||
m_state = *reinterpret_cast<State *>(state_val);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void GetFinalState(State *out) {
|
||||
*out = this->state;
|
||||
this->state = {};
|
||||
*out = m_state;
|
||||
m_state = {};
|
||||
}
|
||||
public:
|
||||
virtual KPhysicalAddress Allocate() override {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(this->state.next_address != Null<uintptr_t>);
|
||||
uintptr_t allocated = this->state.next_address;
|
||||
if (this->state.free_bitmap != 0) {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(m_state.next_address != Null<uintptr_t>);
|
||||
uintptr_t allocated = m_state.next_address;
|
||||
if (m_state.free_bitmap != 0) {
|
||||
u64 index;
|
||||
uintptr_t mask;
|
||||
do {
|
||||
index = KSystemControl::Init::GenerateRandomRange(0, BITSIZEOF(this->state.free_bitmap) - 1);
|
||||
index = KSystemControl::Init::GenerateRandomRange(0, BITSIZEOF(m_state.free_bitmap) - 1);
|
||||
mask = (static_cast<uintptr_t>(1) << index);
|
||||
} while ((this->state.free_bitmap & mask) == 0);
|
||||
this->state.free_bitmap &= ~mask;
|
||||
allocated = this->state.next_address - ((BITSIZEOF(this->state.free_bitmap) - index) * PageSize);
|
||||
} while ((m_state.free_bitmap & mask) == 0);
|
||||
m_state.free_bitmap &= ~mask;
|
||||
allocated = m_state.next_address - ((BITSIZEOF(m_state.free_bitmap) - index) * PageSize);
|
||||
} else {
|
||||
this->state.next_address += PageSize;
|
||||
m_state.next_address += PageSize;
|
||||
}
|
||||
|
||||
ClearPhysicalMemory(allocated, PageSize);
|
||||
|
||||
@@ -220,16 +220,19 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
DataSynchronizationBarrier();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE uintptr_t GetCoreLocalRegionAddress() {
|
||||
ALWAYS_INLINE uintptr_t GetCurrentThreadPointerValue() {
|
||||
register uintptr_t x18 asm("x18");
|
||||
__asm__ __volatile__("" : [x18]"=r"(x18));
|
||||
return x18;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetCoreLocalRegionAddress(uintptr_t value) {
|
||||
ALWAYS_INLINE void SetCurrentThreadPointerValue(uintptr_t value) {
|
||||
register uintptr_t x18 asm("x18") = value;
|
||||
__asm__ __volatile__("":: [x18]"r"(x18));
|
||||
SetTpidrEl1(value);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetExceptionThreadStackTop(uintptr_t top) {
|
||||
SetTpidrEl1(top);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SwitchThreadLocalRegion(uintptr_t tlr) {
|
||||
|
||||
@@ -135,36 +135,36 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
NON_COPYABLE(GenericRegisterAccessorBase);
|
||||
NON_MOVEABLE(GenericRegisterAccessorBase);
|
||||
private:
|
||||
u64 value;
|
||||
u64 m_value;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE GenericRegisterAccessorBase(u64 v) : value(v) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE GenericRegisterAccessorBase(u64 v) : m_value(v) { /* ... */ }
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u64 GetValue() const {
|
||||
return this->value;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
|
||||
return (this->value >> offset) & ((1ul << count) - 1);
|
||||
return (m_value >> offset) & ((1ul << count) - 1);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBits(size_t offset, size_t count, u64 value) {
|
||||
const u64 mask = ((1ul << count) - 1) << offset;
|
||||
this->value &= ~mask;
|
||||
this->value |= (value & (mask >> offset)) << offset;
|
||||
m_value &= ~mask;
|
||||
m_value |= (value & (mask >> offset)) << offset;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBitsDirect(size_t offset, size_t count, u64 value) {
|
||||
const u64 mask = ((1ul << count) - 1) << offset;
|
||||
this->value &= ~mask;
|
||||
this->value |= (value & mask);
|
||||
m_value &= ~mask;
|
||||
m_value |= (value & mask);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBit(size_t offset, bool enabled) {
|
||||
const u64 mask = 1ul << offset;
|
||||
if (enabled) {
|
||||
this->value |= mask;
|
||||
m_value |= mask;
|
||||
} else {
|
||||
this->value &= ~mask;
|
||||
m_value &= ~mask;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace ams::kern::arch::arm64 {
|
||||
static uintptr_t GetProgramCounter(const KThread &thread);
|
||||
static void SetPreviousProgramCounter();
|
||||
|
||||
static void PrintRegister(KThread *thread = nullptr);
|
||||
static void PrintBacktrace(KThread *thread = nullptr);
|
||||
|
||||
static Result BreakIfAttached(ams::svc::BreakReason break_reason, uintptr_t address, size_t size);
|
||||
static Result SetHardwareBreakPoint(ams::svc::HardwareBreakPointRegisterName name, u64 flags, u64 value);
|
||||
|
||||
@@ -61,8 +64,6 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: This is a placeholder definition. */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -19,18 +19,14 @@
|
||||
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class KHardwareTimerInterruptTask;
|
||||
|
||||
}
|
||||
|
||||
class KHardwareTimer : public KHardwareTimerBase {
|
||||
class KHardwareTimer : public KInterruptTask, public KHardwareTimerBase {
|
||||
private:
|
||||
s64 m_maximum_time;
|
||||
public:
|
||||
constexpr KHardwareTimer() : KHardwareTimerBase() { /* ... */ }
|
||||
constexpr KHardwareTimer() : KInterruptTask(), KHardwareTimerBase(), m_maximum_time(std::numeric_limits<s64>::max()) { /* ... */ }
|
||||
public:
|
||||
/* Public API. */
|
||||
NOINLINE void Initialize(s32 core_id);
|
||||
NOINLINE void Initialize();
|
||||
NOINLINE void Finalize();
|
||||
|
||||
static s64 GetTick() {
|
||||
@@ -42,13 +38,12 @@ namespace ams::kern::arch::arm64 {
|
||||
KScopedSpinLock lk(this->GetLock());
|
||||
|
||||
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
||||
SetCompareValue(task_time);
|
||||
EnableInterrupt();
|
||||
if (task_time <= m_maximum_time) {
|
||||
SetCompareValue(task_time);
|
||||
EnableInterrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
friend class impl::KHardwareTimerInterruptTask;
|
||||
NOINLINE void DoInterruptTask();
|
||||
private:
|
||||
/* Hardware register accessors. */
|
||||
static ALWAYS_INLINE void InitializeGlobalTimer() {
|
||||
@@ -88,7 +83,13 @@ namespace ams::kern::arch::arm64 {
|
||||
static ALWAYS_INLINE void SetCompareValue(s64 value) {
|
||||
cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor(0).SetCompareValue(static_cast<u64>(value)).Store();
|
||||
}
|
||||
public:
|
||||
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
|
||||
MESOSPHERE_UNUSED(interrupt_id);
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void DoTask() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,23 +47,23 @@ namespace ams::kern::arch::arm64 {
|
||||
constexpr KGlobalInterruptEntry() : handler(nullptr), manually_cleared(false), needs_clear(false) { /* ... */ }
|
||||
};
|
||||
private:
|
||||
static KSpinLock s_lock;
|
||||
static std::array<KGlobalInterruptEntry, KInterruptController::NumGlobalInterrupts> s_global_interrupts;
|
||||
static KInterruptController::GlobalState s_global_state;
|
||||
static bool s_global_state_saved;
|
||||
KCoreLocalInterruptEntry m_core_local_interrupts[cpu::NumCores][KInterruptController::NumLocalInterrupts]{};
|
||||
KInterruptController m_interrupt_controller{};
|
||||
KInterruptController::LocalState m_local_states[cpu::NumCores]{};
|
||||
bool m_local_state_saved[cpu::NumCores]{};
|
||||
mutable KSpinLock m_global_interrupt_lock{};
|
||||
KGlobalInterruptEntry m_global_interrupts[KInterruptController::NumGlobalInterrupts]{};
|
||||
KInterruptController::GlobalState m_global_state{};
|
||||
bool m_global_state_saved{};
|
||||
private:
|
||||
KCoreLocalInterruptEntry core_local_interrupts[KInterruptController::NumLocalInterrupts];
|
||||
KInterruptController interrupt_controller;
|
||||
KInterruptController::LocalState local_state;
|
||||
bool local_state_saved;
|
||||
private:
|
||||
static ALWAYS_INLINE KSpinLock &GetLock() { return s_lock; }
|
||||
static ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return s_global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
|
||||
ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return this->core_local_interrupts[KInterruptController::GetLocalInterruptIndex(irq)]; }
|
||||
ALWAYS_INLINE KSpinLock &GetGlobalInterruptLock() const { return m_global_interrupt_lock; }
|
||||
ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return m_global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
|
||||
ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return m_core_local_interrupts[GetCurrentCoreId()][KInterruptController::GetLocalInterruptIndex(irq)]; }
|
||||
|
||||
bool OnHandleInterrupt();
|
||||
public:
|
||||
constexpr KInterruptManager() : core_local_interrupts(), interrupt_controller(), local_state(), local_state_saved(false) { /* ... */ }
|
||||
constexpr KInterruptManager() = default;
|
||||
|
||||
NOINLINE void Initialize(s32 core_id);
|
||||
NOINLINE void Finalize(s32 core_id);
|
||||
|
||||
@@ -71,15 +71,15 @@ namespace ams::kern::arch::arm64 {
|
||||
NOINLINE void Restore(s32 core_id);
|
||||
|
||||
bool IsInterruptDefined(s32 irq) const {
|
||||
return this->interrupt_controller.IsInterruptDefined(irq);
|
||||
return m_interrupt_controller.IsInterruptDefined(irq);
|
||||
}
|
||||
|
||||
bool IsGlobal(s32 irq) const {
|
||||
return this->interrupt_controller.IsGlobal(irq);
|
||||
return m_interrupt_controller.IsGlobal(irq);
|
||||
}
|
||||
|
||||
bool IsLocal(s32 irq) const {
|
||||
return this->interrupt_controller.IsLocal(irq);
|
||||
return m_interrupt_controller.IsLocal(irq);
|
||||
}
|
||||
|
||||
NOINLINE Result BindHandler(KInterruptHandler *handler, s32 irq, s32 core_id, s32 priority, bool manual_clear, bool level);
|
||||
@@ -89,11 +89,11 @@ namespace ams::kern::arch::arm64 {
|
||||
NOINLINE Result ClearInterrupt(s32 irq, s32 core_id);
|
||||
|
||||
ALWAYS_INLINE void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
|
||||
this->interrupt_controller.SendInterProcessorInterrupt(irq, core_mask);
|
||||
m_interrupt_controller.SendInterProcessorInterrupt(irq, core_mask);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SendInterProcessorInterrupt(s32 irq) {
|
||||
this->interrupt_controller.SendInterProcessorInterrupt(irq);
|
||||
m_interrupt_controller.SendInterProcessorInterrupt(irq);
|
||||
}
|
||||
|
||||
static void HandleInterrupt(bool user_mode);
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace ams::kern::arch::arm64 {
|
||||
KInterruptName_VirtualMaintenance = 25,
|
||||
KInterruptName_HypervisorTimer = 26,
|
||||
KInterruptName_VirtualTimer = 27,
|
||||
KInterruptName_LegacyNFiq = 38,
|
||||
KInterruptName_LegacyNFiq = 28,
|
||||
KInterruptName_SecurePhysicalTimer = 29,
|
||||
KInterruptName_NonSecurePhysicalTimer = 30,
|
||||
KInterruptName_LegacyNIrq = 31,
|
||||
|
||||
@@ -92,15 +92,15 @@ namespace ams::kern::arch::arm64 {
|
||||
return KPageTable::GetBlockSize(static_cast<KPageTable::BlockType>(KPageTable::GetBlockType(alignment) + 1));
|
||||
}
|
||||
private:
|
||||
KPageTableManager *manager;
|
||||
u64 ttbr;
|
||||
u8 asid;
|
||||
KPageTableManager *m_manager;
|
||||
u64 m_ttbr;
|
||||
u8 m_asid;
|
||||
protected:
|
||||
virtual Result Operate(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) override;
|
||||
virtual Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) override;
|
||||
virtual void FinalizeUpdate(PageLinkedList *page_list) override;
|
||||
|
||||
KPageTableManager &GetPageTableManager() const { return *this->manager; }
|
||||
KPageTableManager &GetPageTableManager() const { return *m_manager; }
|
||||
private:
|
||||
constexpr PageTableEntry GetEntryTemplate(const KPageProperties properties) const {
|
||||
/* Set basic attributes. */
|
||||
@@ -134,9 +134,6 @@ namespace ams::kern::arch::arm64 {
|
||||
entry.SetUserExecuteNever(true);
|
||||
}
|
||||
|
||||
/* Set can be contiguous. */
|
||||
entry.SetContiguousAllowed(!properties.non_contiguous);
|
||||
|
||||
/* Set AP[1] based on perm. */
|
||||
switch (properties.perm & KMemoryPermission_UserReadWrite) {
|
||||
case KMemoryPermission_UserReadWrite:
|
||||
@@ -169,29 +166,29 @@ namespace ams::kern::arch::arm64 {
|
||||
return entry;
|
||||
}
|
||||
public:
|
||||
constexpr KPageTable() : KPageTableBase(), manager(), ttbr(), asid() { /* ... */ }
|
||||
constexpr KPageTable() : KPageTableBase(), m_manager(), m_ttbr(), m_asid() { /* ... */ }
|
||||
|
||||
static NOINLINE void Initialize(s32 core_id);
|
||||
|
||||
ALWAYS_INLINE void Activate(u32 proc_id) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
cpu::SwitchProcess(this->ttbr, proc_id);
|
||||
cpu::SwitchProcess(m_ttbr, proc_id);
|
||||
}
|
||||
|
||||
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
||||
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager);
|
||||
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager);
|
||||
Result Finalize();
|
||||
private:
|
||||
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapL2Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapL3Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapL2Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapL3Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||
|
||||
Result Unmap(KProcessAddress virt_addr, size_t num_pages, PageLinkedList *page_list, bool force, bool reuse_ll);
|
||||
|
||||
Result Map(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, size_t page_size, PageLinkedList *page_list, bool reuse_ll) {
|
||||
Result Map(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, size_t page_size, PageLinkedList *page_list, bool reuse_ll) {
|
||||
switch (page_size) {
|
||||
case L1BlockSize:
|
||||
return this->MapL1Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
||||
return this->MapL1Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||
case L2ContiguousBlockSize:
|
||||
entry_template.SetContiguous(true);
|
||||
[[fallthrough]];
|
||||
@@ -199,25 +196,25 @@ namespace ams::kern::arch::arm64 {
|
||||
case L2TegraSmmuBlockSize:
|
||||
#endif
|
||||
case L2BlockSize:
|
||||
return this->MapL2Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
||||
return this->MapL2Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||
case L3ContiguousBlockSize:
|
||||
entry_template.SetContiguous(true);
|
||||
[[fallthrough]];
|
||||
case L3BlockSize:
|
||||
return this->MapL3Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
||||
return this->MapL3Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||
|
||||
bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list);
|
||||
|
||||
ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
||||
|
||||
Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll);
|
||||
Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll);
|
||||
|
||||
static void PteDataSynchronizationBarrier() {
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
@@ -228,7 +225,7 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
void OnTableUpdated() const {
|
||||
cpu::InvalidateTlbByAsid(this->asid);
|
||||
cpu::InvalidateTlbByAsid(m_asid);
|
||||
}
|
||||
|
||||
void OnKernelTableUpdated() const {
|
||||
|
||||
@@ -69,9 +69,23 @@ namespace ams::kern::arch::arm64 {
|
||||
MappingFlag_Mapped = (1 << 0),
|
||||
};
|
||||
|
||||
enum SoftwareReservedBit : u8 {
|
||||
SoftwareReservedBit_None = 0,
|
||||
SoftwareReservedBit_DisableMergeHead = (1u << 0),
|
||||
SoftwareReservedBit_DisableMergeHeadAndBody = (1u << 1),
|
||||
SoftwareReservedBit_DisableMergeHeadTail = (1u << 2),
|
||||
SoftwareReservedBit_Valid = (1u << 3),
|
||||
};
|
||||
|
||||
static constexpr ALWAYS_INLINE std::underlying_type<SoftwareReservedBit>::type EncodeSoftwareReservedBits(bool head, bool head_body, bool tail) {
|
||||
return (head ? SoftwareReservedBit_DisableMergeHead : SoftwareReservedBit_None) | (head_body ? SoftwareReservedBit_DisableMergeHeadAndBody : SoftwareReservedBit_None) | (tail ? SoftwareReservedBit_DisableMergeHeadTail : SoftwareReservedBit_None);
|
||||
}
|
||||
|
||||
enum ExtensionFlag : u64 {
|
||||
ExtensionFlag_NotContiguous = (1ul << 55),
|
||||
ExtensionFlag_Valid = (1ul << 56),
|
||||
ExtensionFlag_DisableMergeHead = (static_cast<u64>(SoftwareReservedBit_DisableMergeHead) << 55),
|
||||
ExtensionFlag_DisableMergeHeadAndBody = (static_cast<u64>(SoftwareReservedBit_DisableMergeHeadAndBody) << 55),
|
||||
ExtensionFlag_DisableMergeTail = (static_cast<u64>(SoftwareReservedBit_DisableMergeHeadTail) << 55),
|
||||
ExtensionFlag_Valid = (static_cast<u64>(SoftwareReservedBit_Valid) << 55),
|
||||
|
||||
ExtensionFlag_ValidAndMapped = (ExtensionFlag_Valid | MappingFlag_Mapped),
|
||||
ExtensionFlag_TestTableMask = (ExtensionFlag_Valid | (1ul << 1)),
|
||||
@@ -91,70 +105,73 @@ namespace ams::kern::arch::arm64 {
|
||||
ContigType_Contiguous = (0x1ul << 52),
|
||||
};
|
||||
protected:
|
||||
u64 attributes;
|
||||
u64 m_attributes;
|
||||
public:
|
||||
/* Take in a raw attribute. */
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry() : attributes() { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(u64 attr) : attributes(attr) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry() : m_attributes() { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(u64 attr) : m_attributes(attr) { /* ... */ }
|
||||
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(InvalidTag) : attributes(0) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(InvalidTag) : m_attributes(0) { /* ... */ }
|
||||
|
||||
/* Extend a previous attribute. */
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(const PageTableEntry &rhs, u64 new_attr) : attributes(rhs.attributes | new_attr) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(const PageTableEntry &rhs, u64 new_attr) : m_attributes(rhs.m_attributes | new_attr) { /* ... */ }
|
||||
|
||||
/* Construct a new attribute. */
|
||||
constexpr explicit ALWAYS_INLINE PageTableEntry(Permission perm, PageAttribute p_a, Shareable share, MappingFlag m)
|
||||
: attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share) | static_cast<u64>(ExtensionFlag_Valid) | static_cast<u64>(m))
|
||||
: m_attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share) | static_cast<u64>(ExtensionFlag_Valid) | static_cast<u64>(m))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
|
||||
return (this->attributes >> offset) & ((1ul << count) - 1);
|
||||
return (m_attributes >> offset) & ((1ul << count) - 1);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 SelectBits(size_t offset, size_t count) const {
|
||||
return this->attributes & (((1ul << count) - 1) << offset);
|
||||
return m_attributes & (((1ul << count) - 1) << offset);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBits(size_t offset, size_t count, u64 value) {
|
||||
const u64 mask = ((1ul << count) - 1) << offset;
|
||||
this->attributes &= ~mask;
|
||||
this->attributes |= (value & (mask >> offset)) << offset;
|
||||
m_attributes &= ~mask;
|
||||
m_attributes |= (value & (mask >> offset)) << offset;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBitsDirect(size_t offset, size_t count, u64 value) {
|
||||
const u64 mask = ((1ul << count) - 1) << offset;
|
||||
this->attributes &= ~mask;
|
||||
this->attributes |= (value & mask);
|
||||
m_attributes &= ~mask;
|
||||
m_attributes |= (value & mask);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void SetBit(size_t offset, bool enabled) {
|
||||
const u64 mask = 1ul << offset;
|
||||
if (enabled) {
|
||||
this->attributes |= mask;
|
||||
m_attributes |= mask;
|
||||
} else {
|
||||
this->attributes &= ~mask;
|
||||
m_attributes &= ~mask;
|
||||
}
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE bool IsContiguousAllowed() const { return this->GetBits(55, 1) == 0; }
|
||||
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; }
|
||||
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); }
|
||||
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); }
|
||||
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); }
|
||||
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (this->attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
||||
constexpr ALWAYS_INLINE bool IsTable() const { return (this->attributes & ExtensionFlag_TestTableMask) == 2; }
|
||||
constexpr ALWAYS_INLINE bool IsEmpty() const { return (this->attributes & ExtensionFlag_TestTableMask) == 0; }
|
||||
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE u8 GetSoftwareReservedBits() const { return this->GetBits(55, 3); }
|
||||
constexpr ALWAYS_INLINE bool IsHeadMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHead) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsHeadAndBodyMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHeadAndBody) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsTailMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsHeadOrHeadAndBodyMergeDisabled() const { return (this->GetSoftwareReservedBits() & (SoftwareReservedBit_DisableMergeHead | SoftwareReservedBit_DisableMergeHeadAndBody)) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; }
|
||||
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); }
|
||||
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); }
|
||||
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); }
|
||||
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (m_attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
||||
constexpr ALWAYS_INLINE bool IsTable() const { return (m_attributes & ExtensionFlag_TestTableMask) == 2; }
|
||||
constexpr ALWAYS_INLINE bool IsEmpty() const { return (m_attributes & ExtensionFlag_TestTableMask) == 0; }
|
||||
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 0; }
|
||||
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetContiguousAllowed(bool en) { this->SetBit(55, !en); return *this; }
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetPrivilegedExecuteNever(bool en) { this->SetBit(53, en); return *this; }
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetContiguous(bool en) { this->SetBit(52, en); return *this; }
|
||||
@@ -166,22 +183,23 @@ namespace ams::kern::arch::arm64 {
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetPageAttribute(PageAttribute a) { this->SetBitsDirect(2, 3, a); return *this; }
|
||||
constexpr ALWAYS_INLINE decltype(auto) SetMapped(bool m) { static_assert(static_cast<u64>(MappingFlag_Mapped == (1 << 0))); this->SetBit(0, m); return *this; }
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplate() const {
|
||||
constexpr u64 Mask = (0xFFF0000000000FFFul & ~u64((0x1ul << 52) | ExtensionFlag_TestTableMask));
|
||||
return this->attributes & Mask;
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplateForMerge() const {
|
||||
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||
return m_attributes & BaseMask;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool Is(u64 attr) const {
|
||||
return this->attributes == attr;
|
||||
constexpr ALWAYS_INLINE bool IsForMerge(u64 attr) const {
|
||||
constexpr u64 BaseMaskForMerge = ~static_cast<u64>(ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail);
|
||||
return (m_attributes & BaseMaskForMerge) == attr;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
||||
return this->attributes;
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
||||
return this->attributes;
|
||||
return m_attributes;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -207,8 +225,8 @@ namespace ams::kern::arch::arm64 {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr explicit ALWAYS_INLINE L1PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||
constexpr explicit ALWAYS_INLINE L1PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -230,9 +248,26 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2BlockMask(size_t idx) {
|
||||
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||
if (idx == 0) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < L2ContiguousBlockSize / L2BlockSize) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < (L1BlockSize - L2ContiguousBlockSize) / L2BlockSize) {
|
||||
return BaseMask;
|
||||
} else {
|
||||
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2Block(size_t idx) const {
|
||||
return m_attributes & GetEntryTemplateForL2BlockMask(idx);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L1PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
return L1PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,8 +287,8 @@ namespace ams::kern::arch::arm64 {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr explicit ALWAYS_INLINE L2PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||
constexpr explicit ALWAYS_INLINE L2PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -275,9 +310,41 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2BlockMask(size_t idx) {
|
||||
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||
if (idx == 0) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < (L2ContiguousBlockSize / L2BlockSize) - 1) {
|
||||
return BaseMask;
|
||||
} else {
|
||||
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2Block(size_t idx) const {
|
||||
return m_attributes & GetEntryTemplateForL2BlockMask(idx);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3BlockMask(size_t idx) {
|
||||
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||
if (idx == 0) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < L3ContiguousBlockSize / L3BlockSize) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < (L2BlockSize - L3ContiguousBlockSize) / L3BlockSize) {
|
||||
return BaseMask;
|
||||
} else {
|
||||
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3Block(size_t idx) const {
|
||||
return m_attributes & GetEntryTemplateForL3BlockMask(idx);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L2PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
return L2PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -285,8 +352,8 @@ namespace ams::kern::arch::arm64 {
|
||||
public:
|
||||
constexpr explicit ALWAYS_INLINE L3PageTableEntry(InvalidTag) : PageTableEntry(InvalidTag{}) { /* ... */ }
|
||||
|
||||
constexpr explicit ALWAYS_INLINE L3PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | static_cast<u64>(ExtensionFlag_TestTableMask))
|
||||
constexpr explicit ALWAYS_INLINE L3PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | static_cast<u64>(ExtensionFlag_TestTableMask))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -297,9 +364,24 @@ namespace ams::kern::arch::arm64 {
|
||||
return this->SelectBits(12, 36);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3BlockMask(size_t idx) {
|
||||
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||
if (idx == 0) {
|
||||
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||
} else if (idx < (L3ContiguousBlockSize / L3BlockSize) - 1) {
|
||||
return BaseMask;
|
||||
} else {
|
||||
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3Block(size_t idx) const {
|
||||
return m_attributes & GetEntryTemplateForL3BlockMask(idx);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L3PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
return L3PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ namespace ams::kern::arch::arm64 {
|
||||
struct TraversalEntry {
|
||||
KPhysicalAddress phys_addr;
|
||||
size_t block_size;
|
||||
u8 sw_reserved_bits;
|
||||
|
||||
constexpr bool IsHeadMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHead) != 0; }
|
||||
constexpr bool IsHeadAndBodyMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadAndBody) != 0; }
|
||||
constexpr bool IsTailMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
||||
};
|
||||
|
||||
struct TraversalContext {
|
||||
@@ -72,16 +77,16 @@ namespace ams::kern::arch::arm64 {
|
||||
ALWAYS_INLINE bool ExtractL2Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L2PageTableEntry *l2_entry, KProcessAddress virt_addr) const;
|
||||
ALWAYS_INLINE bool ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const;
|
||||
private:
|
||||
L1PageTableEntry *table;
|
||||
bool is_kernel;
|
||||
u32 num_entries;
|
||||
L1PageTableEntry *m_table;
|
||||
bool m_is_kernel;
|
||||
u32 m_num_entries;
|
||||
public:
|
||||
ALWAYS_INLINE KVirtualAddress GetTableEntry(KVirtualAddress table, size_t index) const {
|
||||
return table + index * sizeof(PageTableEntry);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE L1PageTableEntry *GetL1Entry(KProcessAddress address) const {
|
||||
return GetPointer<L1PageTableEntry>(GetTableEntry(KVirtualAddress(this->table), GetL1Index(address) & (this->num_entries - 1)));
|
||||
return GetPointer<L1PageTableEntry>(GetTableEntry(KVirtualAddress(m_table), GetL1Index(address) & (m_num_entries - 1)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE L2PageTableEntry *GetL2EntryFromTable(KVirtualAddress table, KProcessAddress address) const {
|
||||
@@ -100,13 +105,14 @@ namespace ams::kern::arch::arm64 {
|
||||
return GetL3EntryFromTable(KMemoryLayout::GetLinearVirtualAddress(entry->GetTable()), address);
|
||||
}
|
||||
public:
|
||||
constexpr KPageTableImpl() : table(), is_kernel(), num_entries() { /* ... */ }
|
||||
constexpr KPageTableImpl() : m_table(), m_is_kernel(), m_num_entries() { /* ... */ }
|
||||
|
||||
NOINLINE void InitializeForKernel(void *tb, KVirtualAddress start, KVirtualAddress end);
|
||||
NOINLINE void InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end);
|
||||
L1PageTableEntry *Finalize();
|
||||
|
||||
void Dump(uintptr_t start, size_t size) const;
|
||||
size_t CountPageTables() const;
|
||||
|
||||
bool BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const;
|
||||
bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const;
|
||||
|
||||
@@ -21,256 +21,274 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
class KProcessPageTable {
|
||||
private:
|
||||
KPageTable page_table;
|
||||
KPageTable m_page_table;
|
||||
public:
|
||||
constexpr KProcessPageTable() : page_table() { /* ... */ }
|
||||
constexpr KProcessPageTable() : m_page_table() { /* ... */ }
|
||||
|
||||
void Activate(u64 id) {
|
||||
/* Activate the page table with the specified contextidr. */
|
||||
this->page_table.Activate(id);
|
||||
m_page_table.Activate(id);
|
||||
}
|
||||
|
||||
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
||||
return this->page_table.InitializeForProcess(id, as_type, enable_aslr, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
||||
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
||||
return m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
||||
}
|
||||
|
||||
void Finalize() { this->page_table.Finalize(); }
|
||||
void Finalize() { m_page_table.Finalize(); }
|
||||
|
||||
Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm) {
|
||||
return this->page_table.SetMemoryPermission(addr, size, perm);
|
||||
return m_page_table.SetMemoryPermission(addr, size, perm);
|
||||
}
|
||||
|
||||
Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm) {
|
||||
return this->page_table.SetProcessMemoryPermission(addr, size, perm);
|
||||
return m_page_table.SetProcessMemoryPermission(addr, size, perm);
|
||||
}
|
||||
|
||||
Result SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mask, u32 attr) {
|
||||
return this->page_table.SetMemoryAttribute(addr, size, mask, attr);
|
||||
return m_page_table.SetMemoryAttribute(addr, size, mask, attr);
|
||||
}
|
||||
|
||||
Result SetHeapSize(KProcessAddress *out, size_t size) {
|
||||
return this->page_table.SetHeapSize(out, size);
|
||||
return m_page_table.SetHeapSize(out, size);
|
||||
}
|
||||
|
||||
Result SetMaxHeapSize(size_t size) {
|
||||
return this->page_table.SetMaxHeapSize(size);
|
||||
return m_page_table.SetMaxHeapSize(size);
|
||||
}
|
||||
|
||||
Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const {
|
||||
return this->page_table.QueryInfo(out_info, out_page_info, addr);
|
||||
return m_page_table.QueryInfo(out_info, out_page_info, addr);
|
||||
}
|
||||
|
||||
Result QueryPhysicalAddress(ams::svc::PhysicalMemoryInfo *out, KProcessAddress address) const {
|
||||
return this->page_table.QueryPhysicalAddress(out, address);
|
||||
return m_page_table.QueryPhysicalAddress(out, address);
|
||||
}
|
||||
|
||||
Result QueryStaticMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const {
|
||||
return this->page_table.QueryStaticMapping(out, address, size);
|
||||
return m_page_table.QueryStaticMapping(out, address, size);
|
||||
}
|
||||
|
||||
Result QueryIoMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const {
|
||||
return this->page_table.QueryIoMapping(out, address, size);
|
||||
return m_page_table.QueryIoMapping(out, address, size);
|
||||
}
|
||||
|
||||
Result MapMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size) {
|
||||
return this->page_table.MapMemory(dst_address, src_address, size);
|
||||
return m_page_table.MapMemory(dst_address, src_address, size);
|
||||
}
|
||||
|
||||
Result UnmapMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size) {
|
||||
return this->page_table.UnmapMemory(dst_address, src_address, size);
|
||||
return m_page_table.UnmapMemory(dst_address, src_address, size);
|
||||
}
|
||||
|
||||
Result MapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size) {
|
||||
return this->page_table.MapCodeMemory(dst_address, src_address, size);
|
||||
return m_page_table.MapCodeMemory(dst_address, src_address, size);
|
||||
}
|
||||
|
||||
Result UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size) {
|
||||
return this->page_table.UnmapCodeMemory(dst_address, src_address, size);
|
||||
return m_page_table.UnmapCodeMemory(dst_address, src_address, size);
|
||||
}
|
||||
|
||||
Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
||||
return this->page_table.MapIo(phys_addr, size, perm);
|
||||
return m_page_table.MapIo(phys_addr, size, perm);
|
||||
}
|
||||
|
||||
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) {
|
||||
return this->page_table.MapStatic(phys_addr, size, perm);
|
||||
return m_page_table.MapStatic(phys_addr, size, perm);
|
||||
}
|
||||
|
||||
Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) {
|
||||
return this->page_table.MapRegion(region_type, perm);
|
||||
return m_page_table.MapRegion(region_type, perm);
|
||||
}
|
||||
|
||||
Result MapPageGroup(KProcessAddress addr, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPageGroup(addr, pg, state, perm);
|
||||
return m_page_table.MapPageGroup(addr, pg, state, perm);
|
||||
}
|
||||
|
||||
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state) {
|
||||
return this->page_table.UnmapPageGroup(address, pg, state);
|
||||
return m_page_table.UnmapPageGroup(address, pg, state);
|
||||
}
|
||||
|
||||
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPages(out_addr, num_pages, alignment, phys_addr, state, perm);
|
||||
return m_page_table.MapPages(out_addr, num_pages, alignment, phys_addr, state, perm);
|
||||
}
|
||||
|
||||
Result MapPages(KProcessAddress *out_addr, size_t num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPages(out_addr, num_pages, state, perm);
|
||||
return m_page_table.MapPages(out_addr, num_pages, state, perm);
|
||||
}
|
||||
|
||||
Result MapPages(KProcessAddress address, size_t num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPages(address, num_pages, state, perm);
|
||||
return m_page_table.MapPages(address, num_pages, state, perm);
|
||||
}
|
||||
|
||||
Result UnmapPages(KProcessAddress addr, size_t num_pages, KMemoryState state) {
|
||||
return this->page_table.UnmapPages(addr, num_pages, state);
|
||||
return m_page_table.UnmapPages(addr, num_pages, state);
|
||||
}
|
||||
|
||||
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
|
||||
return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||
}
|
||||
|
||||
Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
|
||||
return this->page_table.MakeAndOpenPageGroupContiguous(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||
return m_page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||
}
|
||||
|
||||
Result InvalidateProcessDataCache(KProcessAddress address, size_t size) {
|
||||
return this->page_table.InvalidateProcessDataCache(address, size);
|
||||
return m_page_table.InvalidateProcessDataCache(address, size);
|
||||
}
|
||||
|
||||
Result ReadDebugMemory(void *buffer, KProcessAddress address, size_t size) {
|
||||
return this->page_table.ReadDebugMemory(buffer, address, size);
|
||||
return m_page_table.ReadDebugMemory(buffer, address, size);
|
||||
}
|
||||
|
||||
Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size) {
|
||||
return this->page_table.WriteDebugMemory(address, buffer, size);
|
||||
return m_page_table.WriteDebugMemory(address, buffer, size);
|
||||
}
|
||||
|
||||
Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
|
||||
return this->page_table.LockForDeviceAddressSpace(out, address, size, perm, is_aligned);
|
||||
return m_page_table.LockForDeviceAddressSpace(out, address, size, perm, is_aligned);
|
||||
}
|
||||
|
||||
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) {
|
||||
return this->page_table.UnlockForDeviceAddressSpace(address, size);
|
||||
return m_page_table.UnlockForDeviceAddressSpace(address, size);
|
||||
}
|
||||
|
||||
Result MakePageGroupForUnmapDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size) {
|
||||
return m_page_table.MakePageGroupForUnmapDeviceAddressSpace(out, address, size);
|
||||
}
|
||||
|
||||
Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size, size_t mapped_size) {
|
||||
return m_page_table.UnlockForDeviceAddressSpacePartialMap(address, size, mapped_size);
|
||||
}
|
||||
|
||||
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size) {
|
||||
return this->page_table.LockForIpcUserBuffer(out, address, size);
|
||||
return m_page_table.LockForIpcUserBuffer(out, address, size);
|
||||
}
|
||||
|
||||
Result UnlockForIpcUserBuffer(KProcessAddress address, size_t size) {
|
||||
return this->page_table.UnlockForIpcUserBuffer(address, size);
|
||||
return m_page_table.UnlockForIpcUserBuffer(address, size);
|
||||
}
|
||||
|
||||
Result LockForTransferMemory(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm) {
|
||||
return this->page_table.LockForTransferMemory(out, address, size, perm);
|
||||
return m_page_table.LockForTransferMemory(out, address, size, perm);
|
||||
}
|
||||
|
||||
Result UnlockForTransferMemory(KProcessAddress address, size_t size, const KPageGroup &pg) {
|
||||
return this->page_table.UnlockForTransferMemory(address, size, pg);
|
||||
return m_page_table.UnlockForTransferMemory(address, size, pg);
|
||||
}
|
||||
|
||||
Result LockForCodeMemory(KPageGroup *out, KProcessAddress address, size_t size) {
|
||||
return this->page_table.LockForCodeMemory(out, address, size);
|
||||
return m_page_table.LockForCodeMemory(out, address, size);
|
||||
}
|
||||
|
||||
Result UnlockForCodeMemory(KProcessAddress address, size_t size, const KPageGroup &pg) {
|
||||
return this->page_table.UnlockForCodeMemory(address, size, pg);
|
||||
return m_page_table.UnlockForCodeMemory(address, size, pg);
|
||||
}
|
||||
|
||||
Result 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) {
|
||||
return this->page_table.CopyMemoryFromLinearToUser(dst_addr, size, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
return m_page_table.CopyMemoryFromLinearToUser(dst_addr, size, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
}
|
||||
|
||||
Result CopyMemoryFromLinearToKernel(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) {
|
||||
return this->page_table.CopyMemoryFromLinearToKernel(dst_addr, size, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
return m_page_table.CopyMemoryFromLinearToKernel(dst_addr, size, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
}
|
||||
|
||||
Result 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) {
|
||||
return this->page_table.CopyMemoryFromUserToLinear(dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr);
|
||||
return m_page_table.CopyMemoryFromUserToLinear(dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr);
|
||||
}
|
||||
|
||||
Result CopyMemoryFromKernelToLinear(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) {
|
||||
return this->page_table.CopyMemoryFromKernelToLinear(dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr);
|
||||
return m_page_table.CopyMemoryFromKernelToLinear(dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr);
|
||||
}
|
||||
|
||||
Result CopyMemoryFromHeapToHeap(KProcessPageTable &dst_page_table, 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, u32 src_state_mask, u32 src_state, KMemoryPermission src_test_perm, u32 src_attr_mask, u32 src_attr) {
|
||||
return this->page_table.CopyMemoryFromHeapToHeap(dst_page_table.page_table, dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
return m_page_table.CopyMemoryFromHeapToHeap(dst_page_table.m_page_table, dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
}
|
||||
|
||||
Result CopyMemoryFromHeapToHeapWithoutCheckDestination(KProcessPageTable &dst_page_table, 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, u32 src_state_mask, u32 src_state, KMemoryPermission src_test_perm, u32 src_attr_mask, u32 src_attr) {
|
||||
return this->page_table.CopyMemoryFromHeapToHeapWithoutCheckDestination(dst_page_table.page_table, dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
return m_page_table.CopyMemoryFromHeapToHeapWithoutCheckDestination(dst_page_table.m_page_table, dst_addr, size, dst_state_mask, dst_state, dst_test_perm, dst_attr_mask, dst_attr, src_addr, src_state_mask, src_state, src_test_perm, src_attr_mask, src_attr);
|
||||
}
|
||||
|
||||
Result SetupForIpc(KProcessAddress *out_dst_addr, size_t size, KProcessAddress src_addr, KProcessPageTable &src_page_table, KMemoryPermission test_perm, KMemoryState dst_state, bool send) {
|
||||
return this->page_table.SetupForIpc(out_dst_addr, size, src_addr, src_page_table.page_table, test_perm, dst_state, send);
|
||||
return m_page_table.SetupForIpc(out_dst_addr, size, src_addr, src_page_table.m_page_table, test_perm, dst_state, send);
|
||||
}
|
||||
|
||||
Result CleanupForIpcServer(KProcessAddress address, size_t size, KMemoryState dst_state, KProcess *server_process) {
|
||||
return this->page_table.CleanupForIpcServer(address, size, dst_state, server_process);
|
||||
return m_page_table.CleanupForIpcServer(address, size, dst_state, server_process);
|
||||
}
|
||||
|
||||
Result CleanupForIpcClient(KProcessAddress address, size_t size, KMemoryState dst_state) {
|
||||
return this->page_table.CleanupForIpcClient(address, size, dst_state);
|
||||
return m_page_table.CleanupForIpcClient(address, size, dst_state);
|
||||
}
|
||||
|
||||
Result MapPhysicalMemory(KProcessAddress address, size_t size) {
|
||||
return this->page_table.MapPhysicalMemory(address, size);
|
||||
return m_page_table.MapPhysicalMemory(address, size);
|
||||
}
|
||||
|
||||
Result UnmapPhysicalMemory(KProcessAddress address, size_t size) {
|
||||
return this->page_table.UnmapPhysicalMemory(address, size);
|
||||
return m_page_table.UnmapPhysicalMemory(address, size);
|
||||
}
|
||||
|
||||
Result MapPhysicalMemoryUnsafe(KProcessAddress address, size_t size) {
|
||||
return this->page_table.MapPhysicalMemoryUnsafe(address, size);
|
||||
return m_page_table.MapPhysicalMemoryUnsafe(address, size);
|
||||
}
|
||||
|
||||
Result UnmapPhysicalMemoryUnsafe(KProcessAddress address, size_t size) {
|
||||
return this->page_table.UnmapPhysicalMemoryUnsafe(address, size);
|
||||
}
|
||||
|
||||
void DumpTable() const {
|
||||
return this->page_table.DumpTable();
|
||||
return m_page_table.UnmapPhysicalMemoryUnsafe(address, size);
|
||||
}
|
||||
|
||||
void DumpMemoryBlocks() const {
|
||||
return this->page_table.DumpMemoryBlocks();
|
||||
return m_page_table.DumpMemoryBlocks();
|
||||
}
|
||||
|
||||
void DumpPageTable() const {
|
||||
return m_page_table.DumpPageTable();
|
||||
}
|
||||
|
||||
size_t CountPageTables() const {
|
||||
return m_page_table.CountPageTables();
|
||||
}
|
||||
|
||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||
return this->page_table.GetPhysicalAddress(out, address);
|
||||
return m_page_table.GetPhysicalAddress(out, address);
|
||||
}
|
||||
|
||||
bool Contains(KProcessAddress addr, size_t size) const { return this->page_table.Contains(addr, size); }
|
||||
bool Contains(KProcessAddress addr, size_t size) const { return m_page_table.Contains(addr, size); }
|
||||
|
||||
bool IsInAliasRegion(KProcessAddress addr, size_t size) const { return this->page_table.IsInAliasRegion(addr, size); }
|
||||
bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const { return this->page_table.IsInUnsafeAliasRegion(addr, size); }
|
||||
bool IsInAliasRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInAliasRegion(addr, size); }
|
||||
bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInUnsafeAliasRegion(addr, size); }
|
||||
|
||||
bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return this->page_table.CanContain(addr, size, state); }
|
||||
bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); }
|
||||
|
||||
KProcessAddress GetAddressSpaceStart() const { return this->page_table.GetAddressSpaceStart(); }
|
||||
KProcessAddress GetHeapRegionStart() const { return this->page_table.GetHeapRegionStart(); }
|
||||
KProcessAddress GetAliasRegionStart() const { return this->page_table.GetAliasRegionStart(); }
|
||||
KProcessAddress GetStackRegionStart() const { return this->page_table.GetStackRegionStart(); }
|
||||
KProcessAddress GetKernelMapRegionStart() const { return this->page_table.GetKernelMapRegionStart(); }
|
||||
KProcessAddress GetAliasCodeRegionStart() const { return this->page_table.GetAliasCodeRegionStart(); }
|
||||
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(); }
|
||||
|
||||
size_t GetAddressSpaceSize() const { return this->page_table.GetAddressSpaceSize(); }
|
||||
size_t GetHeapRegionSize() const { return this->page_table.GetHeapRegionSize(); }
|
||||
size_t GetAliasRegionSize() const { return this->page_table.GetAliasRegionSize(); }
|
||||
size_t GetStackRegionSize() const { return this->page_table.GetStackRegionSize(); }
|
||||
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
|
||||
size_t GetAliasCodeRegionSize() const { return this->page_table.GetAliasCodeRegionSize(); }
|
||||
size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); }
|
||||
size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); }
|
||||
size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); }
|
||||
size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); }
|
||||
size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); }
|
||||
size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); }
|
||||
|
||||
size_t GetNormalMemorySize() const { return this->page_table.GetNormalMemorySize(); }
|
||||
size_t GetNormalMemorySize() const { return m_page_table.GetNormalMemorySize(); }
|
||||
|
||||
u32 GetAllocateOption() const { return this->page_table.GetAllocateOption(); }
|
||||
size_t GetCodeSize() const { return m_page_table.GetCodeSize(); }
|
||||
size_t GetCodeDataSize() const { return m_page_table.GetCodeDataSize(); }
|
||||
|
||||
size_t GetAliasCodeSize() const { return m_page_table.GetAliasCodeSize(); }
|
||||
size_t GetAliasCodeDataSize() const { return m_page_table.GetAliasCodeDataSize(); }
|
||||
|
||||
u32 GetAllocateOption() const { return m_page_table.GetAllocateOption(); }
|
||||
|
||||
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
||||
return this->page_table.GetHeapPhysicalAddress(address);
|
||||
return m_page_table.GetHeapPhysicalAddress(address);
|
||||
}
|
||||
|
||||
KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress address) const {
|
||||
return m_page_table.GetHeapVirtualAddress(address);
|
||||
}
|
||||
|
||||
KBlockInfoManager *GetBlockInfoManager() {
|
||||
return this->page_table.GetBlockInfoManager();
|
||||
return m_page_table.GetBlockInfoManager();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,19 +21,19 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
class KNotAlignedSpinLock {
|
||||
private:
|
||||
u32 packed_tickets;
|
||||
u32 m_packed_tickets;
|
||||
public:
|
||||
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
||||
constexpr KNotAlignedSpinLock() : m_packed_tickets(0) { /* ... */ }
|
||||
|
||||
void Lock() {
|
||||
ALWAYS_INLINE void Lock() {
|
||||
u32 tmp0, tmp1, tmp2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" prfm pstl1keep, %[packed_tickets]\n"
|
||||
" prfm pstl1keep, %[m_packed_tickets]\n"
|
||||
"1:\n"
|
||||
" ldaxr %w[tmp0], %[packed_tickets]\n"
|
||||
" ldaxr %w[tmp0], %[m_packed_tickets]\n"
|
||||
" add %w[tmp2], %w[tmp0], #0x10000\n"
|
||||
" stxr %w[tmp1], %w[tmp2], %[packed_tickets]\n"
|
||||
" stxr %w[tmp1], %w[tmp2], %[m_packed_tickets]\n"
|
||||
" cbnz %w[tmp1], 1b\n"
|
||||
" \n"
|
||||
" and %w[tmp1], %w[tmp0], #0xFFFF\n"
|
||||
@@ -42,21 +42,21 @@ namespace ams::kern::arch::arm64 {
|
||||
" sevl\n"
|
||||
"2:\n"
|
||||
" wfe\n"
|
||||
" ldaxrh %w[tmp1], %[packed_tickets]\n"
|
||||
" ldaxrh %w[tmp1], %[m_packed_tickets]\n"
|
||||
" cmp %w[tmp1], %w[tmp0], lsr #16\n"
|
||||
" b.ne 2b\n"
|
||||
"3:\n"
|
||||
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [packed_tickets]"+Q"(this->packed_tickets)
|
||||
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [m_packed_tickets]"+Q"(m_packed_tickets)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
const u32 value = this->packed_tickets + 1;
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
const u32 value = m_packed_tickets + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[packed_tickets]\n"
|
||||
: [packed_tickets]"+Q"(this->packed_tickets)
|
||||
" stlrh %w[value], %[m_packed_tickets]\n"
|
||||
: [m_packed_tickets]"+Q"(m_packed_tickets)
|
||||
: [value]"r"(value)
|
||||
: "memory"
|
||||
);
|
||||
@@ -66,39 +66,39 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
class KAlignedSpinLock {
|
||||
private:
|
||||
alignas(cpu::DataCacheLineSize) u16 current_ticket;
|
||||
alignas(cpu::DataCacheLineSize) u16 next_ticket;
|
||||
alignas(cpu::DataCacheLineSize) u16 m_current_ticket;
|
||||
alignas(cpu::DataCacheLineSize) u16 m_next_ticket;
|
||||
public:
|
||||
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
||||
constexpr KAlignedSpinLock() : m_current_ticket(0), m_next_ticket(0) { /* ... */ }
|
||||
|
||||
void Lock() {
|
||||
ALWAYS_INLINE void Lock() {
|
||||
u32 tmp0, tmp1, got_lock;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" prfm pstl1keep, %[next_ticket]\n"
|
||||
" prfm pstl1keep, %[m_next_ticket]\n"
|
||||
"1:\n"
|
||||
" ldaxrh %w[tmp0], %[next_ticket]\n"
|
||||
" ldaxrh %w[tmp0], %[m_next_ticket]\n"
|
||||
" add %w[tmp1], %w[tmp0], #0x1\n"
|
||||
" stxrh %w[got_lock], %w[tmp1], %[next_ticket]\n"
|
||||
" stxrh %w[got_lock], %w[tmp1], %[m_next_ticket]\n"
|
||||
" cbnz %w[got_lock], 1b\n"
|
||||
" \n"
|
||||
" sevl\n"
|
||||
"2:\n"
|
||||
" wfe\n"
|
||||
" ldaxrh %w[tmp1], %[current_ticket]\n"
|
||||
" ldaxrh %w[tmp1], %[m_current_ticket]\n"
|
||||
" cmp %w[tmp1], %w[tmp0]\n"
|
||||
" b.ne 2b\n"
|
||||
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [got_lock]"=&r"(got_lock), [next_ticket]"+Q"(this->next_ticket)
|
||||
: [current_ticket]"Q"(this->current_ticket)
|
||||
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [got_lock]"=&r"(got_lock), [m_next_ticket]"+Q"(m_next_ticket)
|
||||
: [m_current_ticket]"Q"(m_current_ticket)
|
||||
: "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
const u32 value = this->current_ticket + 1;
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
const u32 value = m_current_ticket + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[current_ticket]\n"
|
||||
: [current_ticket]"+Q"(this->current_ticket)
|
||||
" stlrh %w[value], %[m_current_ticket]\n"
|
||||
: [m_current_ticket]"+Q"(m_current_ticket)
|
||||
: [value]"r"(value)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
@@ -22,16 +22,16 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
class KSupervisorPageTable {
|
||||
private:
|
||||
KPageTable page_table;
|
||||
u64 ttbr0_identity[cpu::NumCores];
|
||||
KPageTable m_page_table;
|
||||
u64 m_ttbr0_identity[cpu::NumCores];
|
||||
public:
|
||||
constexpr KSupervisorPageTable() : page_table(), ttbr0_identity() { /* ... */ }
|
||||
constexpr KSupervisorPageTable() : m_page_table(), m_ttbr0_identity() { /* ... */ }
|
||||
|
||||
NOINLINE void Initialize(s32 core_id);
|
||||
|
||||
void Activate() {
|
||||
/* Activate, using process id = 0xFFFFFFFF */
|
||||
this->page_table.Activate(0xFFFFFFFF);
|
||||
m_page_table.Activate(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void ActivateForInit() {
|
||||
@@ -42,26 +42,38 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPages(out_addr, num_pages, alignment, phys_addr, region_start, region_num_pages, state, perm);
|
||||
return m_page_table.MapPages(out_addr, num_pages, alignment, phys_addr, region_start, region_num_pages, state, perm);
|
||||
}
|
||||
|
||||
Result UnmapPages(KProcessAddress address, size_t num_pages, KMemoryState state) {
|
||||
return this->page_table.UnmapPages(address, num_pages, state);
|
||||
return m_page_table.UnmapPages(address, num_pages, state);
|
||||
}
|
||||
|
||||
Result MapPageGroup(KProcessAddress *out_addr, const KPageGroup &pg, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||
return this->page_table.MapPageGroup(out_addr, pg, region_start, region_num_pages, state, perm);
|
||||
return m_page_table.MapPageGroup(out_addr, pg, region_start, region_num_pages, state, perm);
|
||||
}
|
||||
|
||||
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state) {
|
||||
return this->page_table.UnmapPageGroup(address, pg, state);
|
||||
return m_page_table.UnmapPageGroup(address, pg, state);
|
||||
}
|
||||
|
||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||
return this->page_table.GetPhysicalAddress(out, address);
|
||||
return m_page_table.GetPhysicalAddress(out, address);
|
||||
}
|
||||
|
||||
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; }
|
||||
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return m_ttbr0_identity[core_id]; }
|
||||
|
||||
void DumpMemoryBlocks() const {
|
||||
return m_page_table.DumpMemoryBlocks();
|
||||
}
|
||||
|
||||
void DumpPageTable() const {
|
||||
return m_page_table.DumpPageTable();
|
||||
}
|
||||
|
||||
size_t CountPageTables() const {
|
||||
return m_page_table.CountPageTables();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -45,19 +45,19 @@ namespace ams::kern::arch::arm64 {
|
||||
u64 x28;
|
||||
u64 x29;
|
||||
};
|
||||
} callee_saved;
|
||||
u64 lr;
|
||||
u64 sp;
|
||||
u64 cpacr;
|
||||
u64 fpcr;
|
||||
u64 fpsr;
|
||||
alignas(0x10) u128 fpu_registers[NumFpuRegisters];
|
||||
bool locked;
|
||||
} m_callee_saved;
|
||||
u64 m_lr;
|
||||
u64 m_sp;
|
||||
u64 m_cpacr;
|
||||
u64 m_fpcr;
|
||||
u64 m_fpsr;
|
||||
alignas(0x10) u128 m_fpu_registers[NumFpuRegisters];
|
||||
bool m_locked;
|
||||
private:
|
||||
static void RestoreFpuRegisters64(const KThreadContext &);
|
||||
static void RestoreFpuRegisters32(const KThreadContext &);
|
||||
public:
|
||||
constexpr explicit KThreadContext() : callee_saved(), lr(), sp(), cpacr(), fpcr(), fpsr(), fpu_registers(), locked() { /* ... */ }
|
||||
constexpr explicit KThreadContext() : m_callee_saved(), m_lr(), m_sp(), m_cpacr(), m_fpcr(), m_fpsr(), m_fpu_registers(), m_locked() { /* ... */ }
|
||||
|
||||
Result Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
|
||||
Result Finalize();
|
||||
@@ -66,17 +66,17 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
static void FpuContextSwitchHandler(KThread *thread);
|
||||
|
||||
u32 GetFpcr() const { return this->fpcr; }
|
||||
u32 GetFpsr() const { return this->fpsr; }
|
||||
u32 GetFpcr() const { return m_fpcr; }
|
||||
u32 GetFpsr() const { return m_fpsr; }
|
||||
|
||||
void SetFpcr(u32 v) { this->fpcr = v; }
|
||||
void SetFpsr(u32 v) { this->fpsr = v; }
|
||||
void SetFpcr(u32 v) { m_fpcr = v; }
|
||||
void SetFpsr(u32 v) { m_fpsr = v; }
|
||||
|
||||
void CloneFpuStatus();
|
||||
|
||||
void SetFpuRegisters(const u128 *v, bool is_64_bit);
|
||||
|
||||
const u128 *GetFpuRegisters() const { return this->fpu_registers; }
|
||||
const u128 *GetFpuRegisters() const { return m_fpu_registers; }
|
||||
public:
|
||||
static void OnThreadTerminating(const KThread *thread);
|
||||
};
|
||||
|
||||
@@ -27,14 +27,36 @@ namespace ams::kern::board::generic {
|
||||
public:
|
||||
constexpr KDevicePageTable() { /* ... */ }
|
||||
|
||||
Result ALWAYS_INLINE Initialize(u64 space_address, u64 space_size) { return ams::kern::svc::ResultNotImplemented(); }
|
||||
Result ALWAYS_INLINE Initialize(u64 space_address, u64 space_size) {
|
||||
MESOSPHERE_UNUSED(space_address, space_size);
|
||||
return ams::kern::svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
void ALWAYS_INLINE Finalize() { /* ... */ }
|
||||
|
||||
Result ALWAYS_INLINE Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) { return ams::kern::svc::ResultNotImplemented(); }
|
||||
Result ALWAYS_INLINE Detach(ams::svc::DeviceName device_name) { return ams::kern::svc::ResultNotImplemented(); }
|
||||
Result ALWAYS_INLINE Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) {
|
||||
MESOSPHERE_UNUSED(device_name, space_address, space_size);
|
||||
return ams::kern::svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result ALWAYS_INLINE Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) { return ams::kern::svc::ResultNotImplemented(); }
|
||||
Result ALWAYS_INLINE Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address) { return ams::kern::svc::ResultNotImplemented(); }
|
||||
Result ALWAYS_INLINE Detach(ams::svc::DeviceName device_name) {
|
||||
MESOSPHERE_UNUSED(device_name);
|
||||
return ams::kern::svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result ALWAYS_INLINE Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) {
|
||||
MESOSPHERE_UNUSED(out_mapped_size, pg, device_address, device_perm, refresh_mappings);
|
||||
return ams::kern::svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result ALWAYS_INLINE Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address) {
|
||||
MESOSPHERE_UNUSED(pg, device_address);
|
||||
return ams::kern::svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
void ALWAYS_INLINE Unmap(KDeviceVirtualAddress device_address, size_t size) {
|
||||
MESOSPHERE_UNUSED(device_address, size);
|
||||
}
|
||||
public:
|
||||
static ALWAYS_INLINE void Initialize() { /* ... */ }
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern::board::nintendo::nx::impl::cpu {
|
||||
|
||||
/* Virtual to Physical core map. */
|
||||
constexpr inline const s32 VirtualToPhysicalCoreMap[BITSIZEOF(u64)] = {
|
||||
0, 1, 2, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -27,13 +27,13 @@ namespace ams::kern::board::nintendo::nx {
|
||||
private:
|
||||
static constexpr size_t TableCount = 4;
|
||||
private:
|
||||
KVirtualAddress tables[TableCount];
|
||||
u8 table_asids[TableCount];
|
||||
u64 attached_device;
|
||||
u32 attached_value;
|
||||
u32 detached_value;
|
||||
u32 hs_attached_value;
|
||||
u32 hs_detached_value;
|
||||
KVirtualAddress m_tables[TableCount];
|
||||
u8 m_table_asids[TableCount];
|
||||
u64 m_attached_device;
|
||||
u32 m_attached_value;
|
||||
u32 m_detached_value;
|
||||
u32 m_hs_attached_value;
|
||||
u32 m_hs_detached_value;
|
||||
private:
|
||||
static ALWAYS_INLINE bool IsHeapVirtualAddress(KVirtualAddress addr) {
|
||||
const KMemoryRegion *hint = nullptr;
|
||||
@@ -61,7 +61,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
return KPageTable::GetPageTablePhysicalAddress(addr);
|
||||
}
|
||||
public:
|
||||
constexpr KDevicePageTable() : tables(), table_asids(), attached_device(), attached_value(), detached_value(), hs_attached_value(), hs_detached_value() { /* ... */ }
|
||||
constexpr KDevicePageTable() : m_tables(), m_table_asids(), m_attached_device(), m_attached_value(), m_detached_value(), m_hs_attached_value(), m_hs_detached_value() { /* ... */ }
|
||||
|
||||
Result Initialize(u64 space_address, u64 space_size);
|
||||
void Finalize();
|
||||
@@ -71,6 +71,10 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
Result Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings);
|
||||
Result Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address);
|
||||
|
||||
void Unmap(KDeviceVirtualAddress device_address, size_t size) {
|
||||
return this->UnmapImpl(device_address, size, false);
|
||||
}
|
||||
private:
|
||||
Result MapDevicePage(size_t *out_mapped_size, s32 &num_pt, s32 max_pt, KPhysicalAddress phys_addr, u64 size, KDeviceVirtualAddress address, ams::svc::MemoryPermission device_perm);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
static size_t GetApplicationPoolSize();
|
||||
static size_t GetAppletPoolSize();
|
||||
static size_t GetMinimumNonSecureSystemPoolSize();
|
||||
static u8 GetDebugLogUartPort();
|
||||
|
||||
/* Randomness. */
|
||||
static void GenerateRandomBytes(void *dst, size_t size);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user