Compare commits

...

9 Commits
0.9.3 ... 0.9.4

Author SHA1 Message Date
Michael Scire
c62c4846fc Bump version to 0.9.4. 2019-09-14 10:43:39 -07:00
Michael Scire
8db5b01507 hbl_html: enforce line ending = lf (fixes broken whitelist) 2019-09-14 10:43:39 -07:00
Michael Scire
a6e405c988 ldr: fix hbl_html redirection invocation 2019-09-14 10:43:39 -07:00
Michael Scire
6613fda4b1 ams_mitm: add temporary hid mitm on 9.x for compat 2019-09-14 10:43:39 -07:00
Michael Scire
a18a6e87df git subrepo pull emummc
subrepo:
  subdir:   "emummc"
  merged:   "5f5817e6"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "5f5817e6"
git-subrepo:
  version:  "0.4.0"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5d6aba9"
2019-09-14 10:43:39 -07:00
Michael Scire
93d83c5bb9 ams: initial support for 9.0.0 2019-09-14 10:43:39 -07:00
Michael Scire
6ee8720028 boot: fix pinmux init off-by-one 2019-08-29 00:18:40 -07:00
Michael Scire
600d68bd1a ams_mitm: fix bis key generation for newer hardware 2019-08-29 00:14:23 -07:00
hexkyz
0c3a294cbe Minor information update regarding previously unknown mysteries 2019-08-22 20:52:40 +01:00
62 changed files with 925 additions and 156 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
common/defaults/hbl_html/accessible-urls/accessible-urls.txt text eol=lf

View File

@@ -27,11 +27,12 @@
#define ATMOSPHERE_TARGET_FIRMWARE_700 8 #define ATMOSPHERE_TARGET_FIRMWARE_700 8
#define ATMOSPHERE_TARGET_FIRMWARE_800 9 #define ATMOSPHERE_TARGET_FIRMWARE_800 9
#define ATMOSPHERE_TARGET_FIRMWARE_810 10 #define ATMOSPHERE_TARGET_FIRMWARE_810 10
#define ATMOSPHERE_TARGET_FIRMWARE_900 11
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_810 #define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_900
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_810 #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_900
/* TODO: What should this be, for release? */ /* TODO: What should this be, for release? */
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT

View File

@@ -19,10 +19,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
#define ATMOSPHERE_RELEASE_VERSION_MINOR 9 #define ATMOSPHERE_RELEASE_VERSION_MINOR 9
#define ATMOSPHERE_RELEASE_VERSION_MICRO 3 #define ATMOSPHERE_RELEASE_VERSION_MICRO 4
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 9
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0
#endif #endif

View File

@@ -1,4 +1,23 @@
# Changelog # Changelog
## 0.9.4
+ Support was added for 9.0.0.
+ **Please note**: 9.0.0 made a number of changes that may cause some issues with homebrew. Details:
+ 9.0.0 changed HID in a way that causes libnx to be unable to detect button input.
+ Homebrew should be recompiled with newest libnx to fix this.
+ Atmosphere now provides a temporary hid-mitm that will cause homebrew to continue to work as expected.
+ This mitm will be removed in a future Atmosphere revision once homebrew has been updated, to allow users to use a custom hid mitm again if they desire.
+ 9.0.0 introduced an dependency in FS on the USB system module in order to launch the SD card.
+ This means the USB system module must now be launched before the SD card is initialized.
+ Correspondingly, the USB system module can no longer be IPS patched, and its settings cannot be reliably mitm'd.
+ We know this is frustrating, so we'll be looking into whether there is some way of addressing this in the future.
+ An off-by-one error was fixed in `boot` system module's pinmux initialization.
+ This could theoretically have caused issues with HdmiCec communication.
+ No users reported issues, so it's unclear if this was a problem in practice.
+ A bug was fixed that could cause webapplet launching homebrew to improperly set the accessible url whitelist.
+ BIS key generation has been fixed for newer hardware.
+ Newer hardware uses new, per-firmware device key to generate BIS keys instead of the first device key, so previously the wrong keys were generated as backup.
+ This only affects units manufactured after ~5.0.0.
+ General system stability improvements to enhance the user's experience.
## 0.9.3 ## 0.9.3
+ Thanks to hexkyz, fusee's boot sequence has been greatly optimized. + Thanks to hexkyz, fusee's boot sequence has been greatly optimized.
+ Memory training is now managed by a separate binary (`fusee-mtc`, loaded by fusee-primary before fusee-secondary). + Memory training is now managed by a separate binary (`fusee-mtc`, loaded by fusee-primary before fusee-secondary).

View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/m4xw/emuMMC remote = https://github.com/m4xw/emuMMC
branch = develop branch = develop
commit = 5f51fa3b81d2b14b348f6e8579454007019fc7a6 commit = 5f5817e646d4c800ae4bd6db4a57eee6bde62eed
parent = e871a754a87631c3036ca985ff1c223e00ef4dda parent = 68091a28a23836032c98396259f7ee4796b312f9
method = rebase method = rebase
cmdver = 0.4.0 cmdver = 0.4.0

View File

@@ -2,7 +2,7 @@
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** *A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
### Supported Horizon Versions ### Supported Horizon Versions
**1.0.0 - 8.1.0** **1.0.0 - 9.0.0**
## Features ## Features
* Arbitrary SDMMC backend selection * Arbitrary SDMMC backend selection

View File

@@ -41,6 +41,8 @@
#include "offsets/800_exfat.h" #include "offsets/800_exfat.h"
#include "offsets/810.h" #include "offsets/810.h"
#include "offsets/810_exfat.h" #include "offsets/810_exfat.h"
#include "offsets/900.h"
#include "offsets/900_exfat.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -92,6 +94,8 @@ DEFINE_OFFSET_STRUCT(_800);
DEFINE_OFFSET_STRUCT(_800_EXFAT); DEFINE_OFFSET_STRUCT(_800_EXFAT);
DEFINE_OFFSET_STRUCT(_810); DEFINE_OFFSET_STRUCT(_810);
DEFINE_OFFSET_STRUCT(_810_EXFAT); DEFINE_OFFSET_STRUCT(_810_EXFAT);
DEFINE_OFFSET_STRUCT(_900);
DEFINE_OFFSET_STRUCT(_900_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) { const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) { switch (version) {
@@ -145,6 +149,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_810)); return &(GET_OFFSET_STRUCT_NAME(_810));
case FS_VER_8_1_0_EXFAT: case FS_VER_8_1_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_810_EXFAT)); return &(GET_OFFSET_STRUCT_NAME(_810_EXFAT));
case FS_VER_9_0_0:
return &(GET_OFFSET_STRUCT_NAME(_900));
case FS_VER_9_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_900_EXFAT));
default: default:
fatal_abort(Fatal_UnknownVersion); fatal_abort(Fatal_UnknownVersion);
} }

View File

@@ -59,6 +59,9 @@ enum FS_VER
FS_VER_8_1_0, FS_VER_8_1_0,
FS_VER_8_1_0_EXFAT, FS_VER_8_1_0_EXFAT,
FS_VER_9_0_0,
FS_VER_9_0_0_EXFAT,
FS_VER_MAX, FS_VER_MAX,
}; };

View 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_900_H__
#define __FS_900_H__
// Accessor vtable getters
#define FS_OFFSET_900_SDMMC_ACCESSOR_GC 0x1430F0
#define FS_OFFSET_900_SDMMC_ACCESSOR_SD 0x141200
#define FS_OFFSET_900_SDMMC_ACCESSOR_NAND 0x13C080
// Hooks
#define FS_OFFSET_900_SDMMC_WRAPPER_READ 0x1377E0
#define FS_OFFSET_900_SDMMC_WRAPPER_WRITE 0x1378C0
#define FS_OFFSET_900_RTLD 0x454
#define FS_OFFSET_900_RTLD_DESTINATION 0x9C
#define FS_OFFSET_900_CLKRST_SET_MIN_V_CLK_RATE 0x136A00
// Misc funcs
#define FS_OFFSET_900_LOCK_MUTEX 0x25280
#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
// Misc Data
#define FS_OFFSET_900_SD_MUTEX 0xE1D3E8
#define FS_OFFSET_900_NAND_MUTEX 0xE18258
#define FS_OFFSET_900_ACTIVE_PARTITION 0xE18298
#define FS_OFFSET_900_SDMMC_DAS_HANDLE 0xDFEFA0
// NOPs
#define FS_OFFSET_900_SD_DAS_INIT 0x1472BC
// Nintendo Paths
#define FS_OFFSET_900_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00068A60, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070A40, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081CB4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081EF4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008211C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_900_H__

View 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_900_EXFAT_H__
#define __FS_900_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_GC 0x1430F0
#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_SD 0x141200
#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_NAND 0x13C080
// Hooks
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_READ 0x1377E0
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_WRITE 0x1378C0
#define FS_OFFSET_900_EXFAT_RTLD 0x454
#define FS_OFFSET_900_EXFAT_RTLD_DESTINATION 0x9C
#define FS_OFFSET_900_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x136A00
// Misc funcs
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
// Misc Data
#define FS_OFFSET_900_EXFAT_SD_MUTEX 0xE2B3E8
#define FS_OFFSET_900_EXFAT_NAND_MUTEX 0xE26258
#define FS_OFFSET_900_EXFAT_ACTIVE_PARTITION 0xE26298
#define FS_OFFSET_900_EXFAT_SDMMC_DAS_HANDLE 0xE0CFA0
// NOPs
#define FS_OFFSET_900_EXFAT_SD_DAS_INIT 0x1472BC
// Nintendo Paths
#define FS_OFFSET_900_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00068A60, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070A40, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081CB4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00081EF4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008211C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_900_EXFAT_H__

View File

@@ -15,13 +15,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include "fatal.h" #include "fatal.h"
void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason) void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason)
{ {
atmosphere_fatal_error_ctx error_ctx;
memset(&error_ctx, 0, sizeof(atmosphere_fatal_error_ctx));
// Basic error storage for Atmosphere
// TODO: Maybe include a small reboot2payload stub?
error_ctx.magic = ATMOSPHERE_REBOOT_TO_FATAL_MAGIC;
error_ctx.title_id = 0x0100000000000000; // FS
error_ctx.error_desc = abortReason;
// Copy fatal context
smcCopyToIram(ATMOSPHERE_FATAL_ERROR_ADDR, &error_ctx, sizeof(atmosphere_fatal_error_ctx));
// Reboot to RCM // Reboot to RCM
smcRebootToRcm(); smcRebootToRcm();
while(true) while (true)
; // Should never be reached ; // Should never be reached
} }

View File

@@ -18,7 +18,8 @@
#pragma once #pragma once
#include "../nx/smc.h" #include "../nx/smc.h"
enum FatalReason { enum FatalReason
{
Fatal_InitMMC = 0, Fatal_InitMMC = 0,
Fatal_InitSD, Fatal_InitSD,
Fatal_InvalidAccessor, Fatal_InvalidAccessor,
@@ -32,4 +33,45 @@ enum FatalReason {
Fatal_Max Fatal_Max
}; };
#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
/* Atmosphere reboot-to-fatal-error. */
typedef struct
{
uint32_t magic;
uint32_t error_desc;
uint64_t title_id;
union {
uint64_t gprs[32];
struct
{
uint64_t _gprs[29];
uint64_t fp;
uint64_t lr;
uint64_t sp;
};
};
uint64_t pc;
uint64_t module_base;
uint32_t pstate;
uint32_t afsr0;
uint32_t afsr1;
uint32_t esr;
uint64_t far;
uint64_t report_identifier; /* Normally just system tick. */
uint64_t stack_trace_size;
uint64_t stack_dump_size;
uint64_t stack_trace[AMS_FATAL_ERROR_MAX_STACKTRACE];
uint8_t stack_dump[AMS_FATAL_ERROR_MAX_STACKDUMP];
} atmosphere_fatal_error_ctx;
/* "AFE1" */
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x31454641
/* "AFE0" */
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0 0x30454641
#define ATMOSPHERE_FATAL_ERROR_ADDR 0x4003E000
#define ATMOSPHERE_FATAL_ERROR_CONTEXT ((volatile atmosphere_fatal_error_ctx *)(ATMOSPHERE_FATAL_ERROR_ADDR))
void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason); void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason);

View File

@@ -35,6 +35,14 @@
#define MC_SMMU_PTB_DATA 0x20 #define MC_SMMU_PTB_DATA 0x20
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_PPCS1_ASID 0x298 #define MC_SMMU_PPCS1_ASID 0x298

View File

@@ -85,6 +85,9 @@ void bootup_misc_mmio(void) {
setup_dram_magic_numbers(); setup_dram_magic_numbers();
} }
/* On 9.0.0+, Nintendo writes random values to context save scratch here, and locks the SRK scratch. */
/* There's no real need for us to do this, so we won't. */
/* Mark TMR5, TMR6, TMR7, TMR8, WDT0, WDT1, WDT2 and WDT3 as secure. */ /* Mark TMR5, TMR6, TMR7, TMR8, WDT0, WDT1, WDT2 and WDT3 as secure. */
SHARED_TIMER_SECURE_CFG_0 = 0xF1E0; SHARED_TIMER_SECURE_CFG_0 = 0xF1E0;
@@ -140,28 +143,26 @@ void bootup_misc_mmio(void) {
APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = sec_disable_2; APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = sec_disable_2;
} }
/* Reset Translation Enable Registers. */ /* Reset Translation Enable registers. */
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF;
/* TODO: What are these MC reg writes? */ /* Set SMMU ASID security registers. */
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) {
MAKE_MC_REG(0x038) = 0xE; MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0xE;
} else { } else {
MAKE_MC_REG(0x038) = 0x0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY) = 0x0;
} }
MAKE_MC_REG(0x03C) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_1) = 0;
MAKE_MC_REG(MC_SMMU_ASID_SECURITY_2) = 0;
/* MISC registers. */ MAKE_MC_REG(MC_SMMU_ASID_SECURITY_3) = 0;
MAKE_MC_REG(0x9E0) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_4) = 0;
MAKE_MC_REG(0x9E4) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_5) = 0;
MAKE_MC_REG(0x9E8) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_6) = 0;
MAKE_MC_REG(0x9EC) = 0; MAKE_MC_REG(MC_SMMU_ASID_SECURITY_7) = 0;
MAKE_MC_REG(0x9F0) = 0;
MAKE_MC_REG(0x9F4) = 0;
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) {
MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0;

View File

@@ -74,7 +74,7 @@ void i2c_init(I2CDevice id) {
/* Wait a while until BUS_CLEAR_DONE is set. */ /* Wait a while until BUS_CLEAR_DONE is set. */
for (unsigned int i = 0; i < 10; i++) { for (unsigned int i = 0; i < 10; i++) {
wait(20000); wait(25);
if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
break; break;
} }

View File

@@ -43,6 +43,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] =
{0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */
{0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 07 encrypted with Master key 08. */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 07 encrypted with Master key 08. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 08 encrypted with Master key 09. */
}; };
/* Retail unit keys. */ /* Retail unit keys. */
@@ -57,6 +58,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
{0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */
{0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */
{0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */ {0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */
{0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80}, /* Master key 08 encrypted with Master key 09. */
}; };
bool check_mkey_revision(unsigned int revision, bool is_retail) { bool check_mkey_revision(unsigned int revision, bool is_retail) {

View File

@@ -19,8 +19,8 @@
/* This is glue code to enable master key support across versions. */ /* This is glue code to enable master key support across versions. */
/* TODO: Update to 0xA on release of new master key. */ /* TODO: Update to 0xB on release of new master key. */
#define MASTERKEY_REVISION_MAX 0x9 #define MASTERKEY_REVISION_MAX 0xA
#define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_100_230 0x00
#define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_300 0x01
@@ -29,8 +29,9 @@
#define MASTERKEY_REVISION_500_510 0x04 #define MASTERKEY_REVISION_500_510 0x04
#define MASTERKEY_REVISION_600_610 0x05 #define MASTERKEY_REVISION_600_610 0x05
#define MASTERKEY_REVISION_620 0x06 #define MASTERKEY_REVISION_620 0x06
#define MASTERKEY_REVISION_700_800 0x07 #define MASTERKEY_REVISION_700_800 0x07
#define MASTERKEY_REVISION_810_CURRENT 0x08 #define MASTERKEY_REVISION_810 0x08
#define MASTERKEY_REVISION_900_CURRENT 0x09
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)

View File

@@ -40,6 +40,14 @@ static inline uintptr_t get_mc_base(void) {
#define MC_SMMU_PTB_DATA 0x20 #define MC_SMMU_PTB_DATA 0x20
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_PPCS1_ASID 0x298 #define MC_SMMU_PPCS1_ASID 0x298

View File

@@ -43,7 +43,8 @@ static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10]
{0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */ {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */
{0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */ {0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */
{0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */ {0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 8.1.0 New Device Key Source to be added on next change-of-keys. */ {0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, /* 8.1.0 New Device Key Source. */
{0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49}, /* 9.0.0 New Device Key Source. */
}; };
static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
@@ -52,7 +53,8 @@ static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x
{0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */ {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */
{0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */ {0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */
{0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */ {0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 8.1.0 New Device Key Source to be added on next change-of-keys. */ {0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D}, /* 8.1.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.0.0 New Device Keygen Source to be added on next change-of-keys. */
}; };
static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
@@ -61,7 +63,8 @@ static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS
{0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */ {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */
{0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */ {0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */
{0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */ {0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 8.1.0 New Device Key Source to be added on next change-of-keys. */ {0x94, 0xD6, 0xA8, 0xC0, 0x95, 0xAF, 0xD0, 0xA6, 0x27, 0x53, 0x5E, 0xE5, 0x8E, 0x70, 0x1F, 0x87}, /* 8.1.0 New Device Keygen Source. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.0.0 New Device Keygen Source to be added on next change-of-keys. */
}; };
static void derive_new_device_keys(unsigned int keygen_keyslot) { static void derive_new_device_keys(unsigned int keygen_keyslot) {
@@ -141,6 +144,7 @@ static void setup_se(void) {
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
break; break;
} }
@@ -330,7 +334,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
/* Perform version checks. */ /* Perform version checks. */
/* We will be compatible with all package2s released before current, but not newer ones. */ /* 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_810_CURRENT) { if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_900_CURRENT) {
return true; return true;
} }
@@ -456,6 +460,7 @@ static void copy_warmboot_bin_to_dram() {
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
warmboot_src = (uint8_t *)0x4003E000; warmboot_src = (uint8_t *)0x4003E000;
break; break;
} }
@@ -532,6 +537,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
MAKE_REG32(PMC_BASE + 0x360) = 0x14A; MAKE_REG32(PMC_BASE + 0x360) = 0x14A;
break; break;
case ATMOSPHERE_TARGET_FIRMWARE_900:
MAKE_REG32(PMC_BASE + 0x360) = 0x16B;
break;
} }
} }

View File

@@ -71,7 +71,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
#define PACKAGE2_MAXVER_600_610 0x8 #define PACKAGE2_MAXVER_600_610 0x8
#define PACKAGE2_MAXVER_620 0x9 #define PACKAGE2_MAXVER_620 0x9
#define PACKAGE2_MAXVER_700_800 0xA #define PACKAGE2_MAXVER_700_800 0xA
#define PACKAGE2_MAXVER_810_CURRENT 0xB #define PACKAGE2_MAXVER_810 0xB
#define PACKAGE2_MAXVER_900_CURRENT 0xC
#define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_100 0x3
#define PACKAGE2_MINVER_200 0x4 #define PACKAGE2_MINVER_200 0x4
@@ -82,7 +83,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
#define PACKAGE2_MINVER_600_610 0x9 #define PACKAGE2_MINVER_600_610 0x9
#define PACKAGE2_MINVER_620 0xA #define PACKAGE2_MINVER_620 0xA
#define PACKAGE2_MINVER_700_800 0xB #define PACKAGE2_MINVER_700_800 0xB
#define PACKAGE2_MINVER_810_CURRENT 0xC #define PACKAGE2_MINVER_810 0xC
#define PACKAGE2_MINVER_900_CURRENT 0xD
typedef struct { typedef struct {
union { union {

View File

@@ -77,6 +77,7 @@ static void enable_lp0_wake_events(void) {
static void notify_pmic_shutdown(void) { static void notify_pmic_shutdown(void) {
clkrst_reboot(CARDEVICE_I2C5); clkrst_reboot(CARDEVICE_I2C5);
i2c_init(I2C_5);
if (fuse_get_bootrom_patch_version() >= 0x7F) { if (fuse_get_bootrom_patch_version() >= 0x7F) {
i2c_send_pmic_cpu_shutdown_cmd(); i2c_send_pmic_cpu_shutdown_cmd();
} }

View File

@@ -186,6 +186,7 @@ void set_version_specific_smcs(void) {
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
/* No more LoadSecureExpModKey. */ /* No more LoadSecureExpModKey. */
g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xE].handler = NULL;
g_smc_user_table[0xC].id = 0xC300D60C; g_smc_user_table[0xC].id = 0xC300D60C;

View File

@@ -53,6 +53,7 @@ static bool is_user_keyslot_valid(unsigned int keyslot) {
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
default: default:
return keyslot <= 5; return keyslot <= 5;
} }

View File

@@ -37,6 +37,13 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294

View File

@@ -37,6 +37,13 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294

View File

@@ -76,6 +76,9 @@ typedef enum {
FS_VER_8_1_0, FS_VER_8_1_0,
FS_VER_8_1_0_EXFAT, FS_VER_8_1_0_EXFAT,
FS_VER_9_0_0,
FS_VER_9_0_0_EXFAT,
FS_VER_MAX, FS_VER_MAX,
} emummc_fs_ver_t; } emummc_fs_ver_t;

View File

@@ -411,6 +411,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
"\x6B\x09\xB6\x7B\x29\xC0\x20\x24", /* FS_VER_8_1_0 */ "\x6B\x09\xB6\x7B\x29\xC0\x20\x24", /* FS_VER_8_1_0 */
"\xB4\xCA\xE1\xF2\x49\x65\xD9\x2E", /* FS_VER_8_1_0_EXFAT */ "\xB4\xCA\xE1\xF2\x49\x65\xD9\x2E", /* FS_VER_8_1_0_EXFAT */
"\x46\x87\x40\x76\x1E\x19\x3E\xB7", /* FS_VER_9_0_0 */
"\x7C\x95\x13\x76\xE5\xC1\x2D\xF8", /* FS_VER_9_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) { kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {

View File

@@ -425,12 +425,68 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(800, proc_id_send)[] = {0xA9BF
static const uint8_t MAKE_KERNEL_PATTERN_NAME(800, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11}; static const uint8_t MAKE_KERNEL_PATTERN_NAME(800, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11};
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; static const instruction_t MAKE_KERNEL_PATCH_NAME(800, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
/*
stp x10, x11, [sp, #-0x10]!
ldr x11, [sp, #0x68]
mov w10, w22
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, [x23]
ldr x8, [x8, #0x38]
mov x0, x23
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(900, proc_id_send)[] = {0xE8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x17, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
/*
stp x10, x11, [sp, #-0x10]!
ldr x11, [sp, #0x90]
mov w10, w23
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, [x27]
ldr x8, [x8, #0x38]
mov x0, x27
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(900, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x17, 0x2A, 0xF7, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
/* svcControlCodeMemory Patches */ /* svcControlCodeMemory Patches */
/* b.eq -> nop */ /* b.eq -> nop */
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP}; static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP};
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP}; static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP};
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP}; static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP};
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP}; 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};
/* Hook Definitions. */ /* Hook Definitions. */
static const kernel_patch_t g_kernel_patches_100[] = { static const kernel_patch_t g_kernel_patches_100[] = {
@@ -592,6 +648,7 @@ static const kernel_patch_t g_kernel_patches_700[] = {
.patch_offset = 0x3C6E0, .patch_offset = 0x3C6E0,
} }
}; };
static const kernel_patch_t g_kernel_patches_800[] = { static const kernel_patch_t g_kernel_patches_800[] = {
{ /* Send Message Process ID Patch. */ { /* Send Message Process ID Patch. */
.pattern_size = 0x1C, .pattern_size = 0x1C,
@@ -616,6 +673,30 @@ static const kernel_patch_t g_kernel_patches_800[] = {
} }
}; };
static const kernel_patch_t g_kernel_patches_900[] = {
{ /* Send Message Process ID Patch. */
.pattern_size = 0x1C,
.pattern = MAKE_KERNEL_PATTERN_NAME(900, proc_id_send),
.pattern_hook_offset = 0x0,
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(900, proc_id_send))/sizeof(instruction_t),
.branch_back_offset = 0x10,
.payload = MAKE_KERNEL_PATCH_NAME(900, proc_id_send)
},
{ /* Receive Message Process ID Patch. */
.pattern_size = 0x1C,
.pattern = MAKE_KERNEL_PATTERN_NAME(900, proc_id_recv),
.pattern_hook_offset = 0x0,
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(900, proc_id_recv))/sizeof(instruction_t),
.branch_back_offset = 0x10,
.payload = MAKE_KERNEL_PATCH_NAME(900, proc_id_recv)
},
{ /* svcControlCodeMemory Patch. */
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory))/sizeof(instruction_t),
.payload = MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory),
.patch_offset = 0x43DFC,
}
};
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers, #define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
/* Kernel Infos. */ /* Kernel Infos. */
@@ -673,6 +754,15 @@ static const kernel_info_t g_kernel_infos[] = {
.embedded_ini_ptr = 0x168, .embedded_ini_ptr = 0x168,
.free_code_space_offset = 0x607F0, .free_code_space_offset = 0x607F0,
KERNEL_PATCHES(800) KERNEL_PATCHES(800)
},
{ /* 9.0.0. */
.hash = {0xD7, 0x95, 0x65, 0x3A, 0x49, 0x4C, 0x5A, 0x9E, 0x2E, 0x04, 0xD6, 0x30, 0x7D, 0x79, 0xE1, 0xEE, 0x10, 0x2B, 0x30, 0xE0, 0x3E, 0xDD, 0x9F, 0xB3, 0x8A, 0x3C, 0x5E, 0xD3, 0x9B, 0x30, 0x11, 0x9B},
.hash_offset = 0x1C0,
.hash_size = 0x90000 - 0x1C0,
.embedded_ini_offset = 0x90000,
.embedded_ini_ptr = 0x180,
.free_code_space_offset = 0x65780,
KERNEL_PATCHES(900)
} }
}; };

View File

@@ -154,7 +154,9 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
desired_keyblob = MASTERKEY_REVISION_700_800; desired_keyblob = MASTERKEY_REVISION_700_800;
break; break;
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
desired_keyblob = MASTERKEY_REVISION_810_CURRENT; desired_keyblob = MASTERKEY_REVISION_810;
case ATMOSPHERE_TARGET_FIRMWARE_900:
desired_keyblob = MASTERKEY_REVISION_900_CURRENT;
break; break;
default: default:
fatal_error("Unknown target firmware: %02x!", target_firmware); fatal_error("Unknown target firmware: %02x!", target_firmware);
@@ -230,6 +232,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810: case ATMOSPHERE_TARGET_FIRMWARE_810:
case ATMOSPHERE_TARGET_FIRMWARE_900:
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);

View File

@@ -40,6 +40,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] =
{0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */
{0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 07 encrypted with Master key 08. */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 07 encrypted with Master key 08. */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 08 encrypted with Master key 09. */
}; };
/* Retail unit keys. */ /* Retail unit keys. */
@@ -54,6 +55,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
{0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */
{0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */
{0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */ {0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */
{0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80}, /* Master key 08 encrypted with Master key 09. */
}; };
static bool check_mkey_revision(unsigned int revision, bool is_retail) { static bool check_mkey_revision(unsigned int revision, bool is_retail) {

View File

@@ -19,8 +19,8 @@
/* This is glue code to enable master key support across versions. */ /* This is glue code to enable master key support across versions. */
/* TODO: Update to 0xA on release of new master key. */ /* TODO: Update to 0xB on release of new master key. */
#define MASTERKEY_REVISION_MAX 0x9 #define MASTERKEY_REVISION_MAX 0xA
#define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_100_230 0x00
#define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_300 0x01
@@ -30,7 +30,8 @@
#define MASTERKEY_REVISION_600_610 0x05 #define MASTERKEY_REVISION_600_610 0x05
#define MASTERKEY_REVISION_620 0x06 #define MASTERKEY_REVISION_620 0x06
#define MASTERKEY_REVISION_700_800 0x07 #define MASTERKEY_REVISION_700_800 0x07
#define MASTERKEY_REVISION_810_CURRENT 0x08 #define MASTERKEY_REVISION_810 0x08
#define MASTERKEY_REVISION_900_CURRENT 0x09
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)

View File

@@ -37,6 +37,13 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294

View File

@@ -208,11 +208,13 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
} }
case 0x0F: /* 7.0.0 - 7.0.1 */ case 0x0F: /* 7.0.0 - 7.0.1 */
return ATMOSPHERE_TARGET_FIRMWARE_700; return ATMOSPHERE_TARGET_FIRMWARE_700;
case 0x10: { /* 8.0.0 - 8.1.0 */ case 0x10: { /* 8.0.0 - 9.0.0 */
if (memcmp(package1loader_header->build_timestamp, "20190314", 8) == 0) { if (memcmp(package1loader_header->build_timestamp, "20190314", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_800; return ATMOSPHERE_TARGET_FIRMWARE_800;
} else if (memcmp(package1loader_header->build_timestamp, "20190531", 8) == 0) { } else if (memcmp(package1loader_header->build_timestamp, "20190531", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_810; return ATMOSPHERE_TARGET_FIRMWARE_810;
} else if (memcmp(package1loader_header->build_timestamp, "20190809", 8) == 0) {
return ATMOSPHERE_TARGET_FIRMWARE_900;
} else { } else {
fatal_error("[NXBOOT] Unable to identify package1!\n"); fatal_error("[NXBOOT] Unable to identify package1!\n");
} }
@@ -360,6 +362,10 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) { if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) {
kip_patches_set_enable_nogc(); kip_patches_set_enable_nogc();
} }
/* Check if the fuses are < 9.0.0, but firmware is >= 9.0.0 */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_900 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) {
kip_patches_set_enable_nogc();
}
} }
} }

View File

@@ -232,7 +232,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
/* Perform version checks. */ /* Perform version checks. */
/* We will be compatible with all package2s released before current, but not newer ones. */ /* 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_810_CURRENT) { if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_900_CURRENT) {
return true; return true;
} }

View File

@@ -37,7 +37,8 @@
#define PACKAGE2_MAXVER_600_610 0x8 #define PACKAGE2_MAXVER_600_610 0x8
#define PACKAGE2_MAXVER_620 0x9 #define PACKAGE2_MAXVER_620 0x9
#define PACKAGE2_MAXVER_700_800 0xA #define PACKAGE2_MAXVER_700_800 0xA
#define PACKAGE2_MAXVER_810_CURRENT 0xB #define PACKAGE2_MAXVER_810 0xB
#define PACKAGE2_MAXVER_900_CURRENT 0xC
#define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_100 0x3
#define PACKAGE2_MINVER_200 0x4 #define PACKAGE2_MINVER_200 0x4
@@ -48,7 +49,8 @@
#define PACKAGE2_MINVER_600_610 0x9 #define PACKAGE2_MINVER_600_610 0x9
#define PACKAGE2_MINVER_620 0xA #define PACKAGE2_MINVER_620 0xA
#define PACKAGE2_MINVER_700_800 0xB #define PACKAGE2_MINVER_700_800 0xB
#define PACKAGE2_MINVER_810_CURRENT 0xC #define PACKAGE2_MINVER_810 0xC
#define PACKAGE2_MINVER_900_CURRENT 0xD
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))

View File

@@ -37,6 +37,13 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294

View File

@@ -47,19 +47,26 @@ static const uint8_t AL16 zeroes[0x10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
/* Note: 9.0.0 did not change the TSEC firmware. Thus, the root key is the same. */
/* To avoid distribution of more and more sept binaries, we will simply derive the 9.0.0 master key */
/* on 8.1.0 and 9.0.0. Exosphere supports this already with no issues. */
static const uint8_t AL16 master_kek_seeds[DERIVATION_ID_MAX][0x10] = { static const uint8_t AL16 master_kek_seeds[DERIVATION_ID_MAX][0x10] = {
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, {0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C},
{0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, /* 8.1.0: {0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, */
{0x1A, 0xEC, 0x11, 0x82, 0x2B, 0x32, 0x38, 0x7A, 0x2B, 0xED, 0xBA, 0x01, 0x47, 0x7E, 0x3B, 0x67},
}; };
static const uint8_t AL16 master_devkey_seeds[DERIVATION_ID_MAX][0x10] = { static const uint8_t AL16 master_devkey_seeds[DERIVATION_ID_MAX][0x10] = {
{0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, {0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D},
{0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, /* 8.1.0: {0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, */
{0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49},
}; };
static const uint8_t AL16 master_devkey_vectors[DERIVATION_ID_MAX][0x10] = { static const uint8_t AL16 master_devkey_vectors[DERIVATION_ID_MAX][0x10] = {
{0xD8, 0xD3, 0x67, 0x4F, 0xF3, 0xA2, 0xA4, 0x4E, 0xE4, 0x04, 0x37, 0xC2, 0xD9, 0xCF, 0x41, 0x6F}, {0xD8, 0xD3, 0x67, 0x4F, 0xF3, 0xA2, 0xA4, 0x4E, 0xE4, 0x04, 0x37, 0xC2, 0xD9, 0xCF, 0x41, 0x6F},
{0x72, 0xD0, 0xAD, 0xEB, 0xE1, 0xF6, 0x35, 0x90, 0xB4, 0x43, 0xCC, 0x4B, 0xC4, 0xDC, 0x88, 0x0A}, /* 8.1.0: {0x72, 0xD0, 0xAD, 0xEB, 0xE1, 0xF6, 0x35, 0x90, 0xB4, 0x43, 0xCC, 0x4B, 0xC4, 0xDC, 0x88, 0x0A}, */
{0x8B, 0xD6, 0x13, 0x2F, 0xC3, 0x4D, 0x53, 0x2D, 0x10, 0xA1, 0x63, 0x85, 0x49, 0x2B, 0xCF, 0x3F},
}; };
void derive_keys(void) { void derive_keys(void) {

View File

@@ -37,6 +37,13 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c #define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294

View File

@@ -26,7 +26,7 @@ endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR)) TARGET := $(notdir $(CURDIR))
BUILD := build BUILD := build
SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm source/ns_mitm SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm source/ns_mitm source/hid_mitm
DATA := data DATA := data
INCLUDES := include ../../common/include INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src

View File

@@ -25,6 +25,7 @@
#include "set_mitm/setmitm_main.hpp" #include "set_mitm/setmitm_main.hpp"
#include "bpc_mitm/bpcmitm_main.hpp" #include "bpc_mitm/bpcmitm_main.hpp"
#include "ns_mitm/nsmitm_main.hpp" #include "ns_mitm/nsmitm_main.hpp"
#include "hid_mitm/hidmitm_main.hpp"
static HosThread g_module_threads[MitmModuleId_Count]; static HosThread g_module_threads[MitmModuleId_Count];
@@ -37,6 +38,7 @@ static const struct {
{ &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */ { &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */
{ &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */ { &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */
{ &NsMitmMain, NsMitmPriority, NsMitmStackSize }, /* NsMitm */ { &NsMitmMain, NsMitmPriority, NsMitmStackSize }, /* NsMitm */
{ &HidMitmMain, HidMitmPriority, HidMitmStackSize }, /* HidMitm */
}; };
void LaunchAllMitmModules() { void LaunchAllMitmModules() {

View File

@@ -21,6 +21,7 @@ enum MitmModuleId : u32 {
MitmModuleId_SetMitm = 1, MitmModuleId_SetMitm = 1,
MitmModuleId_BpcMitm = 2, MitmModuleId_BpcMitm = 2,
MitmModuleId_NsMitm = 3, MitmModuleId_NsMitm = 3,
MitmModuleId_HidMitm = 4,
/* Always keep this at the end. */ /* Always keep this at the end. */
MitmModuleId_Count, MitmModuleId_Count,

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2019 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/>.
*/
#include <switch.h>
#include <stratosphere.hpp>
#include "hid_shim.h"
#include "hid_mitm_service.hpp"
void HidMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
/* Nothing to do here */
}
Result HidMitmService::SetSupportedNpadStyleSet(u64 applet_resource_user_id, u32 style_set, PidDescriptor pid_desc) {
const HidControllerType new_style_set = static_cast<HidControllerType>(style_set | TYPE_SYSTEM | TYPE_SYSTEM_EXT);
return hidSetSupportedNpadStyleSetFwd(this->forward_service.get(), this->process_id, applet_resource_user_id, new_style_set);;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2018-2019 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 <switch.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
class HidMitmService : public IMitmServiceObject {
private:
enum class CommandId {
SetSupportedNpadStyleSet = 100,
};
public:
HidMitmService(std::shared_ptr<Service> s, u64 pid, sts::ncm::TitleId tid) : IMitmServiceObject(s, pid, tid) {
/* ... */
}
static bool ShouldMitm(u64 pid, sts::ncm::TitleId tid) {
/* TODO: Consider removing in Atmosphere 0.10.0/1.0.0. */
/* We will mitm:
* - hbl, to help homebrew not need to be recompiled.
*/
return Utils::IsHblTid(static_cast<u64>(tid));
}
static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);
protected:
/* Overridden commands. */
Result SetSupportedNpadStyleSet(u64 applet_resource_user_id, u32 style_set, PidDescriptor pid_desc);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(HidMitmService, SetSupportedNpadStyleSet),
};
};

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018-2019 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/>.
*/
#include <string.h>
#include <switch.h>
#include "hid_shim.h"
/* Command forwarders. */
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 type;
u64 AppletResourceUserId;
} *raw;
ipcSendPid(&c);
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 100;
raw->type = type;
raw->AppletResourceUserId = aruid;
/* Override Process ID. */
{
u32 *cmd_buf = (u32 *)armGetTls();
cmd_buf[3] = (u32)(process_id >> 0);
cmd_buf[4] = (u32)((process_id >> 32) & 0xFFFF) | 0xFFFE0000ul;
}
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}

View File

@@ -0,0 +1,19 @@
/**
* @file hid_shim.h
* @brief Human Interface Devices Services (hid) IPC wrapper.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Command forwarders. */
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2019 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/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <malloc.h>
#include <switch.h>
#include <atmosphere.h>
#include <stratosphere.hpp>
#include "hidmitm_main.hpp"
#include "hid_mitm_service.hpp"
#include "../utils.hpp"
struct HidMitmManagerOptions {
static const size_t PointerBufferSize = 0x200;
static const size_t MaxDomains = 0x0;
static const size_t MaxDomainObjects = 0x0;
};
using HidMitmManager = WaitableManager<HidMitmManagerOptions>;
void HidMitmMain(void *arg) {
/* This is only necessary on 9.x+ */
if (GetRuntimeFirmwareVersion() < FirmwareVersion_900) {
return;
}
/* Ensure we can talk to HID. */
Utils::WaitHidAvailable();
/* Create server manager */
static auto s_server_manager = HidMitmManager(1);
/* Create hid mitm. */
/* Note: official HID passes 100 as sessions, despite this being > 0x40. */
AddMitmServerToManager<HidMitmService>(&s_server_manager, "hid", 100);
/* Loop forever, servicing our services. */
s_server_manager.Process();
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2018-2019 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 <switch.h>
constexpr u32 HidMitmPriority = 47;
constexpr u32 HidMitmStackSize = 0x8000;
void HidMitmMain(void *arg);

View File

@@ -29,7 +29,7 @@
#include "bpc_mitm/bpcmitm_reboot_manager.hpp" #include "bpc_mitm/bpcmitm_reboot_manager.hpp"
static FsFileSystem g_sd_filesystem = {0}; static FsFileSystem g_sd_filesystem = {0};
static HosSignal g_sd_signal; static HosSignal g_sd_signal, g_hid_signal;
static std::vector<u64> g_mitm_flagged_tids; static std::vector<u64> g_mitm_flagged_tids;
static std::vector<u64> g_disable_mitm_flagged_tids; static std::vector<u64> g_disable_mitm_flagged_tids;
@@ -85,7 +85,7 @@ void Utils::InitializeThreadFunc(void *args) {
/* Get required services. */ /* Get required services. */
DoWithSmSession([&]() { DoWithSmSession([&]() {
Handle tmp_hnd = 0; Handle tmp_hnd = 0;
static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"}; static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:m"};
for (unsigned int i = 0; i < sts::util::size(required_active_services); i++) { for (unsigned int i = 0; i < sts::util::size(required_active_services); i++) {
R_ASSERT(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i]))); R_ASSERT(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])));
svcCloseHandle(tmp_hnd); svcCloseHandle(tmp_hnd);
@@ -148,6 +148,11 @@ void Utils::InitializeThreadFunc(void *args) {
/* Automatically backup BIS keys. */ /* Automatically backup BIS keys. */
{ {
u64 key_generation = 0;
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
R_ASSERT(splGetConfig(SplConfigItem_NewKeyGeneration, &key_generation));
}
static constexpr u8 const BisKeySources[4][2][0x10] = { static constexpr u8 const BisKeySources[4][2][0x10] = {
{ {
{0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48}, {0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48},
@@ -172,7 +177,7 @@ void Utils::InitializeThreadFunc(void *args) {
for (size_t partition = 0; partition < 4; partition++) { for (size_t partition = 0; partition < 4; partition++) {
if (partition == 0) { if (partition == 0) {
for (size_t i = 0; i < 2; i++) { for (size_t i = 0; i < 2; i++) {
R_ASSERT(splFsGenerateSpecificAesKey(BisKeySources[partition][i], 0, i, bis_keys[partition][i])); R_ASSERT(splFsGenerateSpecificAesKey(BisKeySources[partition][i], key_generation, i, bis_keys[partition][i]));
} }
} else { } else {
static constexpr u8 const BisKekSource[0x10] = { static constexpr u8 const BisKekSource[0x10] = {
@@ -182,7 +187,7 @@ void Utils::InitializeThreadFunc(void *args) {
const u32 option = (partition == 3 && sts::spl::IsRecoveryBoot()) ? 0x4 : 0x1; const u32 option = (partition == 3 && sts::spl::IsRecoveryBoot()) ? 0x4 : 0x1;
u8 access_key[0x10]; u8 access_key[0x10];
R_ASSERT(splCryptoGenerateAesKek(BisKekSource, 0, option, access_key)); R_ASSERT(splCryptoGenerateAesKek(BisKekSource, key_generation, option, access_key));
for (size_t i = 0; i < 2; i++) { for (size_t i = 0; i < 2; i++) {
R_ASSERT(splCryptoGenerateAesKey(access_key, BisKeySources[partition][i], bis_keys[partition][i])); R_ASSERT(splCryptoGenerateAesKey(access_key, BisKeySources[partition][i], bis_keys[partition][i]));
} }
@@ -294,6 +299,9 @@ void Utils::InitializeThreadFunc(void *args) {
svcSleepThread(1000000ULL); svcSleepThread(1000000ULL);
} }
} }
/* Signal to waiters that we are ready. */
g_hid_signal.Signal();
} }
bool Utils::IsSdInitialized() { bool Utils::IsSdInitialized() {
@@ -308,6 +316,10 @@ bool Utils::IsHidAvailable() {
return g_has_hid_session; return g_has_hid_session;
} }
void Utils::WaitHidAvailable() {
g_hid_signal.Wait();
}
Result Utils::OpenSdFile(const char *fn, int flags, FsFile *out) { Result Utils::OpenSdFile(const char *fn, int flags, FsFile *out) {
if (!IsSdInitialized()) { if (!IsSdInitialized()) {
return ResultFsSdCardNotPresent; return ResultFsSdCardNotPresent;

View File

@@ -108,6 +108,7 @@ class Utils {
static bool IsHidAvailable(); static bool IsHidAvailable();
static void WaitHidAvailable();
static Result GetKeysHeld(u64 *keys); static Result GetKeysHeld(u64 *keys);
static OverrideKey GetTitleOverrideKey(u64 tid); static OverrideKey GetTitleOverrideKey(u64 tid);

View File

@@ -301,6 +301,11 @@ namespace sts::boot {
host_response[i] = reg::Read(g_dsi_regs + sizeof(u32) * DSI_RD_DATA); host_response[i] = reg::Read(g_dsi_regs + sizeof(u32) * DSI_RD_DATA);
} }
/* The last word from host response is:
Bits 0-7: FAB
Bits 8-15: REV
Bits 16-23: Minor REV
*/
if ((host_response[2] & 0xFF) == 0x10) { if ((host_response[2] & 0xFF) == 0x10) {
g_lcd_vendor = 0; g_lcd_vendor = 0;
} else { } else {
@@ -311,7 +316,7 @@ namespace sts::boot {
/* LCD vendor specific configuration. */ /* LCD vendor specific configuration. */
switch (g_lcd_vendor) { switch (g_lcd_vendor) {
case 0xF30: /* TODO: What's this? */ case 0xF30: /* AUO first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
svcSleepThread(180'000'000ul); svcSleepThread(180'000'000ul);
@@ -327,7 +332,7 @@ namespace sts::boot {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break; break;
case 0xF20: /* TODO: What's this? */ case 0xF20: /* Innolux first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
svcSleepThread(180'000'000ul); svcSleepThread(180'000'000ul);
@@ -347,6 +352,7 @@ namespace sts::boot {
DO_DSI_SLEEP_OR_REGISTER_WRITES(DisplayConfigJdiSpecificInit01); DO_DSI_SLEEP_OR_REGISTER_WRITES(DisplayConfigJdiSpecificInit01);
break; break;
default: default:
/* Innolux and AUO second revision screens. */
if ((g_lcd_vendor | 0x10) == 0x1030) { if ((g_lcd_vendor | 0x10) == 0x1030) {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
@@ -445,11 +451,11 @@ namespace sts::boot {
case 0x10: /* Japan Display Inc screens. */ case 0x10: /* Japan Display Inc screens. */
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigJdiSpecificFini01); DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigJdiSpecificFini01);
break; break;
case 0xF30: /* TODO: What's this? */ case 0xF30: /* AUO first revision screens. */
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigF30SpecificFini01); DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigAuoRev1SpecificFini01);
svcSleepThread(5'000'000ul); svcSleepThread(5'000'000ul);
break; break;
case 0x1020: /* TODO: What's this? */ case 0x1020: /* Innolux second revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
@@ -461,7 +467,7 @@ namespace sts::boot {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
svcSleepThread(5'000'000ul); svcSleepThread(5'000'000ul);
break; break;
case 0x1030: /* TODO: What's this? */ case 0x1030: /* AUO second revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9); reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST); reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);

View File

@@ -624,7 +624,7 @@ constexpr RegisterWrite DisplayConfigJdiSpecificFini01[] = {
{sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST}, {sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST},
}; };
constexpr RegisterWrite DisplayConfigF30SpecificFini01[] = { constexpr RegisterWrite DisplayConfigAuoRev1SpecificFini01[] = {
{sizeof(u32) * DSI_WR_DATA, 0x439}, {sizeof(u32) * DSI_WR_DATA, 0x439},
{sizeof(u32) * DSI_WR_DATA, 0x9483FFB9}, {sizeof(u32) * DSI_WR_DATA, 0x9483FFB9},
{sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST}, {sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST},

View File

@@ -107,8 +107,6 @@ void __appExit(void) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
consoleDebugInit(debugDevice_SVC);
/* Change voltage from 3.3v to 1.8v for select devices. */ /* Change voltage from 3.3v to 1.8v for select devices. */
boot::ChangeGpioVoltageTo1_8v(); boot::ChangeGpioVoltageTo1_8v();

View File

@@ -70,7 +70,7 @@ namespace sts::pinmux {
std::abort(); std::abort();
} }
for (size_t i = 0; i < num_configs - 1; i++) { for (size_t i = 0; i < num_configs; i++) {
UpdatePad(configs[i].name, configs[i].val, configs[i].mask); UpdatePad(configs[i].name, configs[i].val, configs[i].mask);
} }

View File

@@ -27,7 +27,8 @@ enum FirmwareVersion : u32 {
FirmwareVersion_700 = 6, FirmwareVersion_700 = 6,
FirmwareVersion_800 = 7, FirmwareVersion_800 = 7,
FirmwareVersion_810 = 8, FirmwareVersion_810 = 8,
FirmwareVersion_Current = FirmwareVersion_810, FirmwareVersion_900 = 9,
FirmwareVersion_Current = FirmwareVersion_900,
FirmwareVersion_Max = 32, FirmwareVersion_Max = 32,
}; };
@@ -42,6 +43,7 @@ enum AtmosphereTargetFirmware : u32 {
AtmosphereTargetFirmware_700 = 8, AtmosphereTargetFirmware_700 = 8,
AtmosphereTargetFirmware_800 = 9, AtmosphereTargetFirmware_800 = 9,
AtmosphereTargetFirmware_810 = 10, AtmosphereTargetFirmware_810 = 10,
AtmosphereTargetFirmware_900 = 11,
}; };
FirmwareVersion GetRuntimeFirmwareVersion(); FirmwareVersion GetRuntimeFirmwareVersion();

View File

@@ -110,6 +110,7 @@ namespace sts::ncm {
static const TitleId Olsc; static const TitleId Olsc;
static const TitleId Dt; static const TitleId Dt;
static const TitleId Nd; static const TitleId Nd;
static const TitleId Ngct;
static const TitleId SystemEnd; static const TitleId SystemEnd;
@@ -279,6 +280,7 @@ namespace sts::ncm {
inline constexpr const TitleId TitleId::Olsc = { 0x010000000000003Eul }; inline constexpr const TitleId TitleId::Olsc = { 0x010000000000003Eul };
inline constexpr const TitleId TitleId::Dt = { 0x010000000000003Ful }; inline constexpr const TitleId TitleId::Dt = { 0x010000000000003Ful };
inline constexpr const TitleId TitleId::Nd = { 0x0100000000000040ul }; inline constexpr const TitleId TitleId::Nd = { 0x0100000000000040ul };
inline constexpr const TitleId TitleId::Ngct = { 0x0100000000000041ul };
inline constexpr const TitleId TitleId::SystemEnd = { 0x01000000000007FFul }; inline constexpr const TitleId TitleId::SystemEnd = { 0x01000000000007FFul };

View File

@@ -28,7 +28,7 @@ namespace sts::cfg {
sm::ServiceName::Encode("pcv"), sm::ServiceName::Encode("pcv"),
sm::ServiceName::Encode("gpio"), sm::ServiceName::Encode("gpio"),
sm::ServiceName::Encode("pinmux"), sm::ServiceName::Encode("pinmux"),
sm::ServiceName::Encode("psc:c") sm::ServiceName::Encode("psc:m"),
}; };
constexpr size_t NumRequiredServicesForSdCardAccess = util::size(RequiredServicesForSdCardAccess); constexpr size_t NumRequiredServicesForSdCardAccess = util::size(RequiredServicesForSdCardAccess);
@@ -46,6 +46,7 @@ namespace sts::cfg {
return ResultFsSdCardNotPresent; return ResultFsSdCardNotPresent;
} }
} }
R_ASSERT(fsMountSdcard(&g_sd_card_filesystem)); R_ASSERT(fsMountSdcard(&g_sd_card_filesystem));
g_sd_card_initialized = true; g_sd_card_initialized = true;
return ResultSuccess; return ResultSuccess;

View File

@@ -76,6 +76,9 @@ static void _CacheValues(void)
case AtmosphereTargetFirmware_810: case AtmosphereTargetFirmware_810:
g_firmware_version = FirmwareVersion_810; g_firmware_version = FirmwareVersion_810;
break; break;
case AtmosphereTargetFirmware_900:
g_firmware_version = FirmwareVersion_900;
break;
default: default:
std::abort(); std::abort();
break; break;
@@ -139,6 +142,11 @@ void SetFirmwareVersionForLibnx() {
minor = 1; minor = 1;
micro = 0; micro = 0;
break; break;
case FirmwareVersion_900:
major = 9;
minor = 0;
micro = 0;
break;
default: default:
std::abort(); std::abort();
break; break;

View File

@@ -334,7 +334,7 @@ namespace sts::ldr {
/* We just need to set this to any valid NCA path. Let's use the executable path. */ /* We just need to set this to any valid NCA path. Let's use the executable path. */
R_TRY(lrLrResolveProgramPath(&lr, static_cast<u64>(loc.title_id), path)); R_TRY(lrLrResolveProgramPath(&lr, static_cast<u64>(loc.title_id), path));
R_TRY(lrLrRedirectApplicationHtmlDocumentPath(&lr, static_cast<u64>(loc.title_id), path)); R_TRY(lrLrRedirectApplicationHtmlDocumentPath(&lr, static_cast<u64>(loc.title_id), static_cast<u64>(loc.title_id), path));
return ResultSuccess; return ResultSuccess;
} }

View File

@@ -102,6 +102,136 @@ namespace sts::ldr {
bool g_has_nso[Nso_Count]; bool g_has_nso[Nso_Count];
NsoHeader g_nso_headers[Nso_Count]; NsoHeader g_nso_headers[Nso_Count];
/* Anti-downgrade. */
struct MinimumTitleVersion {
ncm::TitleId title_id;
u32 version;
};
constexpr u32 MakeSystemVersion(u32 major, u32 minor, u32 micro) {
return (major << 26) | (minor << 20) | (micro << 16);
}
constexpr MinimumTitleVersion g_MinimumTitleVersions810[] = {
{ncm::TitleId::Settings, 1},
{ncm::TitleId::Bus, 1},
{ncm::TitleId::Audio, 1},
{ncm::TitleId::NvServices, 1},
{ncm::TitleId::Ns, 1},
{ncm::TitleId::Ssl, 1},
{ncm::TitleId::Es, 1},
{ncm::TitleId::Creport, 1},
{ncm::TitleId::Ro, 1},
};
constexpr size_t g_MinimumTitleVersionsCount810 = util::size(g_MinimumTitleVersions810);
constexpr MinimumTitleVersion g_MinimumTitleVersions900[] = {
/* All non-Development System Modules. */
{ncm::TitleId::Usb, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Tma, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Boot2, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Settings, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Bus, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Bluetooth, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Bcat, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Dmnt, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Friends, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Nifm, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Ptm, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Shell, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::BsdSockets, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Hid, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Audio, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::LogManager, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Wlan, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Cs, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Ldn, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::NvServices, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Pcv, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Ppc, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::NvnFlinger, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Pcie, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Account, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Ns, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Nfc, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Psc, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::CapSrv, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Am, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Ssl, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Nim, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Cec, MakeSystemVersion(9, 0, 0)}, */
/* {ncm::TitleId::Tspm, MakeSystemVersion(9, 0, 0)}, */
/* {ncm::TitleId::Spl, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Lbl, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Btm, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Erpt, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Time, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Vi, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Pctl, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Npns, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Eupld, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Glue, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Eclct, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Es, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Fatal, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Grc, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Creport, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Ro, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Profiler, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Sdb, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Migration, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Jit, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::JpegDec, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::SafeMode, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::Olsc, MakeSystemVersion(9, 0, 0)},
/* {ncm::TitleId::Dt, MakeSystemVersion(9, 0, 0)}, */
/* {ncm::TitleId::Nd, MakeSystemVersion(9, 0, 0)}, */
{ncm::TitleId::Ngct, MakeSystemVersion(9, 0, 0)},
/* All Web Applets. */
{ncm::TitleId::AppletWeb, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::AppletShop, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::AppletOfflineWeb, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::AppletLoginShare, MakeSystemVersion(9, 0, 0)},
{ncm::TitleId::AppletWifiWebAuth, MakeSystemVersion(9, 0, 0)},
};
constexpr size_t g_MinimumTitleVersionsCount900 = util::size(g_MinimumTitleVersions900);
Result ValidateTitleVersion(ncm::TitleId title_id, u32 version) {
if (GetRuntimeFirmwareVersion() < FirmwareVersion_810) {
return ResultSuccess;
} else {
#ifdef LDR_VALIDATE_PROCESS_VERSION
const MinimumTitleVersion *entries = nullptr;
size_t num_entries = 0;
switch (GetRuntimeFirmwareVersion()) {
case FirmwareVersion_810:
entries = g_MinimumTitleVersions810;
num_entries = g_MinimumTitleVersionsCount810;
break;
case FirmwareVersion_900:
entries = g_MinimumTitleVersions900;
num_entries = g_MinimumTitleVersionsCount900;
break;
default:
entries = nullptr;
num_entries = 0;
break;
}
for (size_t i = 0; i < num_entries; i++) {
if (entries[i].title_id == title_id && entries[i].version > version) {
return ResultLoaderInvalidVersion;
}
}
return ResultSuccess;
#else
return ResultSuccess;
#endif
}
}
/* Helpers. */ /* Helpers. */
Result GetProgramInfoFromMeta(ProgramInfo *out, const Meta *meta) { Result GetProgramInfoFromMeta(ProgramInfo *out, const Meta *meta) {
/* Copy basic info. */ /* Copy basic info. */
@@ -115,7 +245,7 @@ namespace sts::ldr {
#define COPY_ACCESS_CONTROL(source, which) \ #define COPY_ACCESS_CONTROL(source, which) \
({ \ ({ \
const size_t size = meta->source->which##_size; \ const size_t size = meta->source->which##_size; \
if (offset + size >= sizeof(out->ac_buffer)) { \ if (offset + size > sizeof(out->ac_buffer)) { \
return ResultLoaderInternalError; \ return ResultLoaderInternalError; \
} \ } \
out->source##_##which##_size = size; \ out->source##_##which##_size = size; \
@@ -151,35 +281,6 @@ namespace sts::ldr {
return static_cast<Acid::PoolPartition>((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift); return static_cast<Acid::PoolPartition>((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift);
} }
constexpr bool IsDisallowedVersion810(const ncm::TitleId title_id, const u32 version) {
return version == 0 &&
(title_id == ncm::TitleId::Settings ||
title_id == ncm::TitleId::Bus ||
title_id == ncm::TitleId::Audio ||
title_id == ncm::TitleId::NvServices ||
title_id == ncm::TitleId::Ns ||
title_id == ncm::TitleId::Ssl ||
title_id == ncm::TitleId::Es ||
title_id == ncm::TitleId::Creport ||
title_id == ncm::TitleId::Ro);
}
Result ValidateTitleVersion(ncm::TitleId title_id, u32 version) {
if (GetRuntimeFirmwareVersion() < FirmwareVersion_810) {
return ResultSuccess;
} else {
#ifdef LDR_VALIDATE_PROCESS_VERSION
if (IsDisallowedVersion810(title_id, version)) {
return ResultLoaderInvalidVersion;
} else {
return ResultSuccess;
}
#else
return ResultSuccess;
#endif
}
}
Result LoadNsoHeaders(ncm::TitleId title_id, NsoHeader *nso_headers, bool *has_nso) { Result LoadNsoHeaders(ncm::TitleId title_id, NsoHeader *nso_headers, bool *has_nso) {
/* Clear NSOs. */ /* Clear NSOs. */
std::memset(nso_headers, 0, sizeof(*nso_headers) * Nso_Count); std::memset(nso_headers, 0, sizeof(*nso_headers) * Nso_Count);

View File

@@ -35,11 +35,11 @@ namespace sts::boot2 {
ncm::TitleId::Bus, /* bus */ ncm::TitleId::Bus, /* bus */
ncm::TitleId::Settings, /* settings */ ncm::TitleId::Settings, /* settings */
ncm::TitleId::Pcv, /* pcv */ ncm::TitleId::Pcv, /* pcv */
ncm::TitleId::Usb, /* usb */
}; };
constexpr size_t NumPreSdCardLaunchPrograms = util::size(PreSdCardLaunchPrograms); constexpr size_t NumPreSdCardLaunchPrograms = util::size(PreSdCardLaunchPrograms);
constexpr ncm::TitleId AdditionalLaunchPrograms[] = { constexpr ncm::TitleId AdditionalLaunchPrograms[] = {
ncm::TitleId::Usb, /* usb */
ncm::TitleId::Tma, /* tma */ ncm::TitleId::Tma, /* tma */
ncm::TitleId::Am, /* am */ ncm::TitleId::Am, /* am */
ncm::TitleId::NvServices, /* nvservices */ ncm::TitleId::NvServices, /* nvservices */
@@ -80,11 +80,11 @@ namespace sts::boot2 {
ncm::TitleId::Migration, /* migration */ ncm::TitleId::Migration, /* migration */
ncm::TitleId::Grc, /* grc */ ncm::TitleId::Grc, /* grc */
ncm::TitleId::Olsc, /* olsc */ ncm::TitleId::Olsc, /* olsc */
ncm::TitleId::Ngct, /* ngct */
}; };
constexpr size_t NumAdditionalLaunchPrograms = util::size(AdditionalLaunchPrograms); constexpr size_t NumAdditionalLaunchPrograms = util::size(AdditionalLaunchPrograms);
constexpr ncm::TitleId AdditionalMaintenanceLaunchPrograms[] = { constexpr ncm::TitleId AdditionalMaintenanceLaunchPrograms[] = {
ncm::TitleId::Usb, /* usb */
ncm::TitleId::Tma, /* tma */ ncm::TitleId::Tma, /* tma */
ncm::TitleId::Am, /* am */ ncm::TitleId::Am, /* am */
ncm::TitleId::NvServices, /* nvservices */ ncm::TitleId::NvServices, /* nvservices */
@@ -121,6 +121,7 @@ namespace sts::boot2 {
ncm::TitleId::Migration, /* migration */ ncm::TitleId::Migration, /* migration */
ncm::TitleId::Grc, /* grc */ ncm::TitleId::Grc, /* grc */
ncm::TitleId::Olsc, /* olsc */ ncm::TitleId::Olsc, /* olsc */
ncm::TitleId::Ngct, /* ngct */
}; };
constexpr size_t NumAdditionalMaintenanceLaunchPrograms = util::size(AdditionalMaintenanceLaunchPrograms); constexpr size_t NumAdditionalMaintenanceLaunchPrograms = util::size(AdditionalMaintenanceLaunchPrograms);
@@ -156,6 +157,7 @@ namespace sts::boot2 {
break; break;
} }
if (out_process_id) { if (out_process_id) {
*out_process_id = process_id; *out_process_id = process_id;
} }