Compare commits

..

41 Commits

Author SHA1 Message Date
Michael Scire
39c201e37f git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "bb7678691"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "bb7678691"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-06-10 22:19:29 -07:00
Michael Scire
ab5cc75684 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "f23f943d4"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "f23f943d4"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-06-10 22:18:44 -07:00
Michael Scire
1e3349e99a emummc: update readme 2024-06-10 22:18:04 -07:00
Michael Scire
76628e273a ams: bump to 1.7.1 (support for 18.1.0) 2024-06-10 22:17:23 -07:00
Michael Scire
257ac2bd33 emummc: update to support 18.1.0 2024-06-10 22:16:24 -07:00
Michael Scire
9eb92f37db git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "d58ff30a1"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "d58ff30a1"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-06-05 11:29:13 -07:00
Michael Scire
5b135d12ca libstrat: fix more gnu++23 errors 2024-06-05 11:28:29 -07:00
Michael Scire
c41a6b80d7 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "087f68257"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "087f68257"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-06-05 09:22:53 -07:00
Michael Scire
05fde7b764 ams: may as well test removal of CRTP from Result 2024-06-01 22:36:37 -07:00
Michael Scire
1609f804f2 ams: build with -std=gnu++23 2024-06-01 22:36:37 -07:00
Michael Scire
f35c94810c ams: fix compilation with gcc 14 (closes #2330) 2024-06-01 22:36:37 -07:00
Michael Scire
548b48b2a6 loader: update to reflect latest 18.0.0 changes
well, this sure is late, whoops
2024-05-27 15:43:58 -07:00
Michael Scire
35d93a7c41 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "fadec2981"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "fadec2981"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-03-29 03:20:12 -07:00
Michael Scire
410f23035e docs: update changelog for 1.7.0 2024-03-29 03:19:17 -07:00
Michael Scire
29cc13543a kern: fix using memory config for half-of-true-size 2024-03-29 03:18:20 -07:00
Michael Scire
31ad4eec1d git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "832b24426"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "832b24426"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-03-29 02:57:53 -07:00
Michael Scire
3ccb0ae02b git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "8b85add71"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "8b85add71"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2024-03-29 02:56:10 -07:00
Michael Scire
4f7db6e60e docs: add changelog for 1.7.0 2024-03-29 02:54:40 -07:00
Michael Scire
a325e18cb5 loader: add usb3 patches for 18.0.0 2024-03-29 02:41:14 -07:00
Michael Scire
af41272591 spl: add support for new spl:es command 33 2024-03-29 02:41:14 -07:00
Michael Scire
551821e7e2 erpt: actually support non-sequential ids, nintendo why 2024-03-29 02:41:14 -07:00
Michael Scire
b081762657 emummc: update for 18.0.0 2024-03-29 02:41:14 -07:00
Michael Scire
d2c2a94c5e erpt: add new IDs/categories 2024-03-29 02:41:14 -07:00
Michael Scire
4ff9278d11 jpegdec: stop bundling (TODO post-prerelease) 2024-03-29 02:41:14 -07:00
Michael Scire
21c85c6a4f exo/fusee: apparently 18.0.0 did not burn a fuse 2024-03-29 02:41:14 -07:00
Michael Scire
05090005b7 svc: advertise support for 18.3.0.0 2024-03-29 02:41:14 -07:00
Michael Scire
c0487ad384 kern: fix whoops in new page table logic 2024-03-29 02:41:14 -07:00
Michael Scire
ecbe5cd406 kern: refactor smc helpers to share more common logic 2024-03-29 02:41:14 -07:00
Michael Scire
4fe139ea52 kern: return ExceptionType_UnalignedData on data abort caused by alignment fault 2024-03-29 02:41:14 -07:00
Michael Scire
6922eae3e7 kern: add KPageGroup::CopyRangeTo 2024-03-29 02:41:14 -07:00
Michael Scire
952188fc73 kern: implement new attr tracking for memory range/traversal context 2024-03-29 02:41:14 -07:00
Michael Scire
c0a4fc30a8 kern: simplify size calculations in KPageTableBase::Read/WriteDebugIoMemory 2024-03-29 02:41:14 -07:00
Michael Scire
0b04c89a84 kern: pass properties directly to KPageTableBase::AllocateAndMapPagesImpl 2024-03-29 02:41:14 -07:00
Michael Scire
217dd1260a kern: take alignment argument in KMemoryManager::AllocateAndOpen 2024-03-29 02:41:14 -07:00
Michael Scire
8aa62a54d8 kern/os: support CreateProcessFlag_EnableAliasRegionExtraSize 2024-03-29 02:41:14 -07:00
Michael Scire
25bae14064 kern: revise KPageTableBase region layout logic to match 18.0.0 changes 2024-03-29 02:41:14 -07:00
Michael Scire
900913fe3b kern: fix longstanding bug in ConvertToKMemoryPermission 2024-03-29 02:41:14 -07:00
Michael Scire
7562f807fd kern: pass kernel base from KernelLdr to Kernel 2024-03-29 02:41:14 -07:00
Michael Scire
cf5895e04f kern: use userspace access instructions to read from tlr 2024-03-29 02:41:14 -07:00
Michael Scire
1f37fbed1d fusee/exo/ams: update with new keydata/version enums 2024-03-29 02:41:14 -07:00
JerryWn
9701d5b2ab readme: fix broken discord icon 2024-03-20 03:04:29 -07:00
44 changed files with 455 additions and 161 deletions

View File

@@ -3,7 +3,7 @@
=====
![License](https://img.shields.io/badge/License-GPLv2-blue.svg)
[![Chat on Discord](https://camo.githubusercontent.com/b4175720ede4f2621aa066ffbabb70ae30044679/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d446973636f72642d627269676874677265656e2e737667)](https://discordapp.com/invite/ZdqEhed)
[![Chat on Discord](https://img.shields.io/badge/Discord-5865f2?logo=discord&logoColor=white)](https://discordapp.com/invite/ZdqEhed)
Atmosphère is a work-in-progress customized firmware for the Nintendo Switch.

View File

@@ -1,4 +1,32 @@
# Changelog
## 1.7.1
+ Support was added for 18.1.0.
+ Atmosphère was updated to use GCC 14/newlib (latest devkitA64/devkitARM releases).
+ Further changes were for 18.0.0:
+ `loader` was updated to reflect the latest official behavior.
+ General system stability improvements to enhance the user's experience.
## 1.7.0
+ Basic support was added for 18.0.0.
+ The console should boot and atmosphère should be fully functional. However, not all modules have been fully updated to reflect the latest changes.
+ There shouldn't be anything user visible resulting from this, but it will be addressed in a future atmosphère update, once I am not traveling so much.
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `spl` was updated to reflect the latest official behavior.
+ `fusee`'s no longer supports applying IPS patches to KIPs.
+ The only KIPs that are ever present are a) atmosphère modules, b) custom system modules, or c) FS.
+ The IPS subsystem was originally designed to make nogc patches work for FS, but these are now internal, and it appears the literal only kip patches that exist are for piracy.
+ I could not find any kip patches posted anywhere made for any other purpose.
+ It fundamentally does not make sense to slow down boot for every normal user for a feature that has no actual use-case, especially when `fusee` seeks to be a minimal bootloader.
+ Minor improvements were made to atmosphere's gdbstub, including:
+ Support was added for QStartNoAckMode.
+ An issue was fixed that could cause a fatal error when creating too many breakpoints.
+ A number of minor issues were fixed and improvements were made, including:
+ `pt-BR` (`PortugueseBr`) is now accepted as a valid language when overriding game locales.
+ A bug was fixed that could cause atmosphere to incorrectly serialize output object IDs over IPC when using domain objects.
+ A bug was fixed in `pm`'s resource limit boost logic that could potentially cause legitimate boosts to fail in certain circumstances.
+ `loader`/`ro` will now throw a fatal error when using invalid IPS patches that go out of bounds, instead of corrupting memory.
+ Support was fixed for booting using a memory configuration of half of the true available memory (e.g. forcing a 4GB configuration on an 8GB board).
+ General system stability improvements to enhance the user's experience.
## 1.6.2
+ Support was finished for 17.0.0.
+ `erpt` was updated to support the latest official behavior.

4
emummc/.gitrepo vendored
View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emummc
branch = develop
commit = 9513a5412057b1f1bc44ed8e717c57c726763a88
parent = e4d08ae0c5342cdb0875d164522a63ec9d233052
commit = f23f943d4092ca9490dbcebbdd117abc3740abcf
parent = 1e3349e99a023517269b3fc1bc32fd84e5b3caa9
method = merge
cmdver = 0.4.1

2
emummc/README.md vendored
View File

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

View File

@@ -71,6 +71,8 @@
#include "offsets/1700_exfat.h"
#include "offsets/1800.h"
#include "offsets/1800_exfat.h"
#include "offsets/1810.h"
#include "offsets/1810_exfat.h"
#include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -153,6 +155,8 @@ DEFINE_OFFSET_STRUCT(_1700);
DEFINE_OFFSET_STRUCT(_1700_EXFAT);
DEFINE_OFFSET_STRUCT(_1800);
DEFINE_OFFSET_STRUCT(_1800_EXFAT);
DEFINE_OFFSET_STRUCT(_1810);
DEFINE_OFFSET_STRUCT(_1810_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) {
@@ -266,6 +270,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1800));
case FS_VER_18_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1800_EXFAT));
case FS_VER_18_1_0:
return &(GET_OFFSET_STRUCT_NAME(_1810));
case FS_VER_18_1_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1810_EXFAT));
default:
fatal_abort(Fatal_UnknownVersion);
}

View File

@@ -104,6 +104,9 @@ enum FS_VER
FS_VER_18_0_0,
FS_VER_18_0_0_EXFAT,
FS_VER_18_1_0,
FS_VER_18_1_0_EXFAT,
FS_VER_MAX,
};

59
emummc/source/FS/offsets/1810.h vendored Normal file
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_1810_H__
#define __FS_1810_H__
// Accessor vtable getters
#define FS_OFFSET_1810_SDMMC_ACCESSOR_GC 0x18AB00
#define FS_OFFSET_1810_SDMMC_ACCESSOR_SD 0x18C800
#define FS_OFFSET_1810_SDMMC_ACCESSOR_NAND 0x18AFE0
// Hooks
#define FS_OFFSET_1810_SDMMC_WRAPPER_READ 0x186A50
#define FS_OFFSET_1810_SDMMC_WRAPPER_WRITE 0x186AB0
#define FS_OFFSET_1810_RTLD 0x2A3A4
#define FS_OFFSET_1810_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x44)))
#define FS_OFFSET_1810_CLKRST_SET_MIN_V_CLK_RATE 0x1A77D0
// Misc funcs
#define FS_OFFSET_1810_LOCK_MUTEX 0x17FCC0
#define FS_OFFSET_1810_UNLOCK_MUTEX 0x17FD10
#define FS_OFFSET_1810_SDMMC_WRAPPER_CONTROLLER_OPEN 0x186A10
#define FS_OFFSET_1810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x186A30
// Misc Data
#define FS_OFFSET_1810_SD_MUTEX 0xFD13F0
#define FS_OFFSET_1810_NAND_MUTEX 0xFCCB28
#define FS_OFFSET_1810_ACTIVE_PARTITION 0xFCCB68
#define FS_OFFSET_1810_SDMMC_DAS_HANDLE 0xFB1950
// NOPs
#define FS_OFFSET_1810_SD_DAS_INIT 0x28F24
// Nintendo Paths
#define FS_OFFSET_1810_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00068B08, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000758DC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007C77C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000905C4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1810_H__

59
emummc/source/FS/offsets/1810_exfat.h vendored Normal file
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_1810_EXFAT_H__
#define __FS_1810_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1810_EXFAT_SDMMC_ACCESSOR_GC 0x195B90
#define FS_OFFSET_1810_EXFAT_SDMMC_ACCESSOR_SD 0x197890
#define FS_OFFSET_1810_EXFAT_SDMMC_ACCESSOR_NAND 0x196070
// Hooks
#define FS_OFFSET_1810_EXFAT_SDMMC_WRAPPER_READ 0x191AE0
#define FS_OFFSET_1810_EXFAT_SDMMC_WRAPPER_WRITE 0x191B40
#define FS_OFFSET_1810_EXFAT_RTLD 0x2A3A4
#define FS_OFFSET_1810_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x44)))
#define FS_OFFSET_1810_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1B2860
// Misc funcs
#define FS_OFFSET_1810_EXFAT_LOCK_MUTEX 0x18AD50
#define FS_OFFSET_1810_EXFAT_UNLOCK_MUTEX 0x18ADA0
#define FS_OFFSET_1810_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x191AA0
#define FS_OFFSET_1810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x191AC0
// Misc Data
#define FS_OFFSET_1810_EXFAT_SD_MUTEX 0xFE33F0
#define FS_OFFSET_1810_EXFAT_NAND_MUTEX 0xFDEB28
#define FS_OFFSET_1810_EXFAT_ACTIVE_PARTITION 0xFDEB68
#define FS_OFFSET_1810_EXFAT_SDMMC_DAS_HANDLE 0xFBE950
// NOPs
#define FS_OFFSET_1810_EXFAT_SD_DAS_INIT 0x28F24
// Nintendo Paths
#define FS_OFFSET_1810_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00068B08, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x000758DC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007C77C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000905C4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1810_EXFAT_H__

View File

@@ -174,6 +174,9 @@ namespace ams::nxboot {
FsVersion_18_0_0,
FsVersion_18_0_0_Exfat,
FsVersion_18_1_0,
FsVersion_18_1_0_Exfat,
FsVersion_Count,
};
@@ -260,6 +263,9 @@ namespace ams::nxboot {
{ 0x79, 0x5F, 0x5A, 0x5E, 0xB0, 0xC6, 0x77, 0x9E }, /* FsVersion_18_0_0 */
{ 0x1E, 0x2C, 0x64, 0xB1, 0xCC, 0xE2, 0x78, 0x24 }, /* FsVersion_18_0_0_Exfat */
{ 0xA3, 0x39, 0xF0, 0x1C, 0x95, 0xBF, 0xA7, 0x68 }, /* FsVersion_18_1_0 */
{ 0x20, 0x4C, 0xBA, 0x86, 0xDE, 0x08, 0x44, 0x6A }, /* FsVersion_18_1_0_Exfat */
};
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {

View File

@@ -1002,14 +1002,16 @@ namespace ams::nxboot {
\
constexpr u32 SrcLow = RANGE_LOW(SRC_RANGE); \
constexpr u32 DstLow = RANGE_LOW(DST_RANGE); \
constexpr auto Shift = (SrcLow < DstLow) ? (DstLow - SrcLow) \
: (SrcLow - DstLow); \
\
cur_reg_value &= ~Mask; \
if constexpr (SrcLow == DstLow) { \
cur_reg_value |= (src_value & Mask); \
} else if constexpr (SrcLow < DstLow) { \
cur_reg_value |= ((src_value << (DstLow - SrcLow)) & Mask); \
cur_reg_value |= ((src_value << Shift) & Mask); \
} else { \
cur_reg_value |= ((src_value >> (SrcLow - DstLow)) & Mask); \
cur_reg_value |= ((src_value >> Shift) & Mask); \
} \
} \
}

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = bfc55834869fe24f8d94550bc6909a65ae7d35c2
parent = 742fd16080bce8cd664d6244304a771f82e8aa04
commit = bb767869105d0eb5c38425f54bf20614639a078d
parent = ab5cc7568430e2c1b3fa1be6be104b7c5f71eb32
method = merge
cmdver = 0.4.1

View File

@@ -44,7 +44,7 @@ else ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export ATMOSPHERE_CFLAGS += -Wno-c99-designator -Wno-gnu-alignof-expression -Wno-unused-private-field
endif
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20 -Wno-invalid-offsetof
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++23 -Wno-invalid-offsetof
export ATMOSPHERE_ASFLAGS :=

View File

@@ -39,7 +39,7 @@ namespace ams::kern {
KPhysicalAddress KSystemControlBase::Init::GetKernelPhysicalBaseAddress(KPhysicalAddress base_address) {
const size_t real_dram_size = KSystemControl::Init::GetRealMemorySize();
const size_t intended_dram_size = KSystemControl::Init::GetIntendedMemorySize();
if (intended_dram_size * 2 < real_dram_size) {
if (intended_dram_size * 2 <= real_dram_size) {
return base_address;
} else {
return base_address + ((real_dram_size - intended_dram_size) / 2);

View File

@@ -16,6 +16,7 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssystem/fssystem_nca_file_system_driver.hpp>
#include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::fssystem {
@@ -25,10 +26,13 @@ namespace ams::fssystem {
void InvalidateHardwareAesKey();
const u8 *GetAcidSignatureKeyModulus(bool prod, size_t key_generation);
bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation);
const u8 *GetAcidSignatureKeyModulus(ldr::PlatformId platform, bool prod, size_t key_generation, bool unk_unused);
size_t GetAcidSignatureKeyModulusSize(ldr::PlatformId platform, bool unk_unused);
const u8 *GetAcidSignatureKeyPublicExponent();
constexpr inline size_t AcidSignatureKeyModulusSize = NcaCryptoConfiguration::Rsa2048KeyModulusSize;
constexpr inline size_t AcidSignatureKeyPublicExponentSize = NcaCryptoConfiguration::Rsa2048KeyPublicExponentSize;
}

View File

@@ -83,6 +83,7 @@ namespace ams::hos {
Version_17_0_0 = ::ams::TargetFirmware_17_0_0,
Version_17_0_1 = ::ams::TargetFirmware_17_0_1,
Version_18_0_0 = ::ams::TargetFirmware_18_0_0,
Version_18_1_0 = ::ams::TargetFirmware_18_1_0,
Version_Current = ::ams::TargetFirmware_Current,

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::ldr {
/* TODO: Is this really a FS type? What namespace does this actually live inside? */
enum PlatformId {
PlatformId_Nx = 0,
};
}

View File

@@ -19,6 +19,7 @@
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/ncm/ncm_program_location.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
#include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::ldr {
@@ -224,6 +225,7 @@ namespace ams::ldr {
MetaFlag_OptimizeMemoryAllocation = (1 << 4),
MetaFlag_DisableDeviceAddressSpaceMerge = (1 << 5),
MetaFlag_EnableAliasRegionExtraSize = (1 << 6),
};
enum AddressSpaceType {

View File

@@ -42,7 +42,7 @@ namespace ams::sf {
} else if constexpr(TransferMode == BufferTransferMode::AutoSelect) {
return SfBufferAttr_HipcAutoSelect;
} else {
static_assert(TransferMode != TransferMode, "Invalid BufferTransferMode");
static_assert(false, "Invalid BufferTransferMode");
}
}();

View File

@@ -29,7 +29,7 @@ namespace ams::sf {
private:
struct Holder {
MemoryResource *allocator;
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
alignas(alignof(T)) std::byte storage[sizeof(T)];
};
public:
void *Allocate(size_t size) {

View File

@@ -57,7 +57,7 @@ namespace ams::sf {
struct Globals {
ExpHeapAllocator allocator;
typename std::aligned_storage<Size == 0 ? 1 : Size>::type buffer;
alignas(0x10) std::byte buffer[Size == 0 ? 1 : Size];
};
static constinit inline Globals _globals = {};

View File

@@ -73,7 +73,7 @@ namespace ams::emummc {
/* Retrieve and cache values. */
{
typename std::aligned_storage<2 * (MaxDirLen + 1), os::MemoryPageSize>::type path_storage;
alignas(os::MemoryPageSize) std::byte path_storage[2 * (MaxDirLen + 1)];
struct {
char file_path[MaxDirLen + 1];

View File

@@ -23,8 +23,8 @@ namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
namespace {
constinit std::aligned_storage_t<0x80> g_fsp_service_object_buffer;
constinit std::aligned_storage_t<0x80> g_fsp_ldr_service_object_buffer;
alignas(0x10) constinit std::byte g_fsp_service_object_buffer[0x80] = {};
alignas(0x10) constinit std::byte g_fsp_ldr_service_object_buffer[0x80] = {};
constinit bool g_use_static_fsp_service_object_buffer = false;
constinit bool g_use_static_fsp_ldr_service_object_buffer = false;

View File

@@ -20,7 +20,7 @@ namespace ams::fssrv::impl {
namespace {
constinit std::aligned_storage<0x80>::type g_static_buffer_for_program_info_for_initial_process = {};
alignas(0x10) constinit std::byte g_static_buffer_for_program_info_for_initial_process[0x80] = {};
template<typename T>
class StaticAllocatorForProgramInfoForInitialProcess : public std::allocator<T> {

View File

@@ -22,9 +22,11 @@ namespace ams::fssystem {
constexpr inline const size_t KeySize = crypto::AesDecryptor128::KeySize;
constexpr inline const size_t AcidSignatureKeyGenerationMax = 1;
constexpr inline const size_t NxAcidSignatureKeyGenerationMax = 1;
constexpr inline const u8 AcidSignatureKeyModulusDev[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
constexpr inline const size_t NxAcidSignatureKeyModulusSize = NcaCryptoConfiguration::Rsa2048KeyModulusSize;
constexpr inline const u8 NxAcidSignatureKeyModulusDev[NxAcidSignatureKeyGenerationMax + 1][NxAcidSignatureKeyModulusSize] = {
{
0xD6, 0x34, 0xA5, 0x78, 0x6C, 0x68, 0xCE, 0x5A, 0xC2, 0x37, 0x17, 0xF3, 0x82, 0x45, 0xC6, 0x89,
0xE1, 0x2D, 0x06, 0x67, 0xBF, 0xB4, 0x06, 0x19, 0x55, 0x6B, 0x27, 0x66, 0x0C, 0xA4, 0xB5, 0x87,
@@ -63,7 +65,7 @@ namespace ams::fssystem {
}
};
constexpr inline const u8 AcidSignatureKeyModulusProd[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
constexpr inline const u8 NxAcidSignatureKeyModulusProd[NxAcidSignatureKeyGenerationMax + 1][NxAcidSignatureKeyModulusSize] = {
{
0xDD, 0xC8, 0xDD, 0xF2, 0x4E, 0x6D, 0xF0, 0xCA, 0x9E, 0xC7, 0x5D, 0xC7, 0x7B, 0xAD, 0xFE, 0x7D,
0x23, 0x89, 0x69, 0xB6, 0xF2, 0x06, 0xA2, 0x02, 0x88, 0xE1, 0x55, 0x91, 0xAB, 0xCB, 0x4D, 0x50,
@@ -102,7 +104,7 @@ namespace ams::fssystem {
}
};
static_assert(sizeof(AcidSignatureKeyModulusProd) == sizeof(AcidSignatureKeyModulusDev));
static_assert(sizeof(NxAcidSignatureKeyModulusProd) == sizeof(NxAcidSignatureKeyModulusDev));
constexpr inline const u8 AcidSignatureKeyPublicExponent[] = {
0x01, 0x00, 0x01
@@ -295,10 +297,36 @@ namespace ams::fssystem {
}
}
const u8 *GetAcidSignatureKeyModulus(bool prod, size_t key_generation) {
AMS_ASSERT(key_generation <= AcidSignatureKeyGenerationMax);
const size_t used_keygen = (key_generation % (AcidSignatureKeyGenerationMax + 1));
return prod ? AcidSignatureKeyModulusProd[used_keygen] : AcidSignatureKeyModulusDev[used_keygen];
bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation) {
switch (platform) {
case ldr::PlatformId_Nx:
return key_generation <= NxAcidSignatureKeyGenerationMax;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
const u8 *GetAcidSignatureKeyModulus(ldr::PlatformId platform, bool prod, size_t key_generation, bool unk_unused) {
AMS_ASSERT(IsValidSignatureKeyGeneration(platform, key_generation));
AMS_UNUSED(unk_unused);
switch (platform) {
case ldr::PlatformId_Nx:
{
const size_t used_keygen = (key_generation % (NxAcidSignatureKeyGenerationMax + 1));
return prod ? NxAcidSignatureKeyModulusProd[used_keygen] : NxAcidSignatureKeyModulusDev[used_keygen];
}
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
size_t GetAcidSignatureKeyModulusSize(ldr::PlatformId platform, bool unk_unused) {
AMS_UNUSED(unk_unused);
switch (platform) {
case ldr::PlatformId_Nx:
return NxAcidSignatureKeyModulusSize;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
const u8 *GetAcidSignatureKeyPublicExponent() {

View File

@@ -41,7 +41,7 @@ namespace ams::htc::server::rpc {
#else
static constexpr size_t MaxTaskSize = 0xE1D8;
#endif
using TaskStorage = typename std::aligned_storage<MaxTaskSize, alignof(void *)>::type;
struct TaskStorage { alignas(alignof(void *)) std::byte _storage[MaxTaskSize]; };
private:
bool m_valid[MaxRpcCount]{};
TaskStorage m_storages[MaxRpcCount]{};

View File

@@ -19,9 +19,13 @@
namespace ams::osdbg::impl {
template<size_t Size, int NumPointers, size_t Alignment>
using AlignedStorageIlp32 = typename std::aligned_storage<Size + NumPointers * sizeof(u32), Alignment>::type;
struct AlignedStorageIlp32 {
alignas(Alignment) std::byte _storage[Size + NumPointers * sizeof(u32)];
};
template<size_t Size, int NumPointers, size_t Alignment>
using AlignedStorageLp64 = typename std::aligned_storage<Size + NumPointers * sizeof(u64), Alignment>::type;
struct AlignedStorageLp64 {
alignas(Alignment) std::byte _storage[Size + NumPointers * sizeof(u64)];
};
}

View File

@@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 7
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 18
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0

View File

@@ -81,8 +81,9 @@
#define ATMOSPHERE_TARGET_FIRMWARE_17_0_0 ATMOSPHERE_TARGET_FIRMWARE(17, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_17_0_1 ATMOSPHERE_TARGET_FIRMWARE(17, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_18_0_0 ATMOSPHERE_TARGET_FIRMWARE(18, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_18_1_0 ATMOSPHERE_TARGET_FIRMWARE(18, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_18_0_0
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_18_1_0
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@@ -156,6 +157,7 @@ namespace ams {
TargetFirmware_17_0_0 = ATMOSPHERE_TARGET_FIRMWARE_17_0_0,
TargetFirmware_17_0_1 = ATMOSPHERE_TARGET_FIRMWARE_17_0_1,
TargetFirmware_18_0_0 = ATMOSPHERE_TARGET_FIRMWARE_18_0_0,
TargetFirmware_18_1_0 = ATMOSPHERE_TARGET_FIRMWARE_18_1_0,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,

View File

@@ -34,6 +34,8 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(InvalidAcidSignature, 11);
R_DEFINE_ERROR_RESULT(InvalidNcaSignature, 12);
R_DEFINE_ERROR_RESULT(InvalidPlatformId, 14);
R_DEFINE_ERROR_RESULT(OutOfAddressSpace, 51);
R_DEFINE_ERROR_RESULT(InvalidNroImage, 52);
R_DEFINE_ERROR_RESULT(InvalidNrrImage, 53);

View File

@@ -85,14 +85,13 @@ namespace ams {
};
/* Use CRTP for Results. */
template<typename Self>
class ResultBase {
public:
using BaseType = typename ResultTraits::BaseType;
static constexpr BaseType SuccessValue = ResultTraits::SuccessValue;
public:
constexpr ALWAYS_INLINE BaseType GetModule() const { return ResultTraits::GetModuleFromValue(static_cast<const Self *>(this)->GetValue()); }
constexpr ALWAYS_INLINE BaseType GetDescription() const { return ResultTraits::GetDescriptionFromValue(static_cast<const Self *>(this)->GetValue()); }
constexpr ALWAYS_INLINE BaseType GetModule(this auto const &self) { return ResultTraits::GetModuleFromValue(self.GetValue()); }
constexpr ALWAYS_INLINE BaseType GetDescription(this auto const &self) { return ResultTraits::GetDescriptionFromValue(self.GetValue()); }
};
class ResultInternalAccessor;
@@ -101,10 +100,10 @@ namespace ams {
class ResultSuccess;
class Result final : public result::impl::ResultBase<Result> {
class Result final : public result::impl::ResultBase {
friend class result::impl::ResultInternalAccessor;
public:
using Base = typename result::impl::ResultBase<Result>;
using Base = typename result::impl::ResultBase;
private:
typename Base::BaseType m_value;
private:
@@ -157,9 +156,9 @@ namespace ams {
}
class ResultSuccess final : public result::impl::ResultBase<ResultSuccess> {
class ResultSuccess final : public result::impl::ResultBase {
public:
using Base = typename result::impl::ResultBase<ResultSuccess>;
using Base = typename result::impl::ResultBase;
public:
constexpr ALWAYS_INLINE operator Result() const { return result::impl::MakeResult(Base::SuccessValue); }
static constexpr ALWAYS_INLINE bool CanAccept(Result result) { return result.IsSuccess(); }
@@ -189,9 +188,9 @@ namespace ams {
namespace result::impl {
template<ResultTraits::BaseType _Module, ResultTraits::BaseType _Description>
class ResultErrorBase : public ResultBase<ResultErrorBase<_Module, _Description>> {
class ResultErrorBase : public ResultBase {
public:
using Base = typename result::impl::ResultBase<ResultErrorBase<_Module, _Description>>;
using Base = typename result::impl::ResultBase;
static constexpr typename Base::BaseType Module = _Module;
static constexpr typename Base::BaseType Description = _Description;
static constexpr typename Base::BaseType Value = ResultTraits::MakeStaticValue<Module, Description>::value;

View File

@@ -201,7 +201,7 @@ namespace ams::svc::codegen::impl {
} else if constexpr (Size == 8) {
__asm__ __volatile__("ldr x%c[r], [sp, %c[offset]]" :: [r]"i"(Reg), [offset]"i"(Offset) : "memory");
} else {
static_assert(Size != Size);
static_assert(false, "Invalid Size");
}
}
@@ -212,7 +212,7 @@ namespace ams::svc::codegen::impl {
} else if constexpr (Size == 8) {
__asm__ __volatile__("ldp x%c[r0], x%c[r1], [sp, %c[offset]]" :: [r0]"i"(Reg0), [r1]"i"(Reg1), [offset]"i"(Offset) : "memory");
} else {
static_assert(Size != Size);
static_assert(false, "Invalid Size");
}
}
@@ -223,7 +223,7 @@ namespace ams::svc::codegen::impl {
} else if constexpr (Size == 8) {
__asm__ __volatile__("str x%c[r], [sp, %c[offset]]" :: [r]"i"(Reg), [offset]"i"(Offset) : "memory");
} else {
static_assert(Size != Size);
static_assert(false, "Invalid Size");
}
}
@@ -234,7 +234,7 @@ namespace ams::svc::codegen::impl {
} else if constexpr (Size == 8) {
__asm__ __volatile__("stp x%c[r0], x%c[r1], [sp, %c[offset]]" :: [r0]"i"(Reg0), [r1]"i"(Reg1), [offset]"i"(Offset) : "memory");
} else {
static_assert(Size != Size);
static_assert(false, "Invalid Size");
}
}

View File

@@ -461,7 +461,7 @@ namespace ams::svc::codegen::impl {
if constexpr (CodeGenKind == CodeGenerationKind::SvcInvocationToKernelProcedure) {
return Operation::ImplType::template CanGenerateCodeForSvcInvocationToKernelProcedure<Operation>(allocator);
} else {
static_assert(CodeGenKind != CodeGenKind, "Invalid CodeGenerationKind");
static_assert(false, "Invalid CodeGenerationKind");
}
}
@@ -474,7 +474,7 @@ namespace ams::svc::codegen::impl {
} else if constexpr (CodeGenKind == CodeGenerationKind::KernelProcedureToSvcInvocation) {
Operation::ImplType::template GenerateCodeForKernelProcedureToSvcInvocation<Operation>(mcg);
} else {
static_assert(CodeGenKind != CodeGenKind, "Invalid CodeGenerationKind");
static_assert(false, "Invalid CodeGenerationKind");
}
}
};

View File

@@ -127,7 +127,7 @@ namespace ams::svc::codegen::impl {
META_CODE_OPERATION_KIND_GENERATE_CODE(Pack)
META_CODE_OPERATION_KIND_GENERATE_CODE(Unpack)
META_CODE_OPERATION_KIND_GENERATE_CODE(LoadStackAddress)
else { static_assert(Kind != Kind, "Unknown MetaOperationKind"); }
else { static_assert(false, "Unknown MetaOperationKind"); }
#undef META_CODE_OPERATION_KIND_GENERATE_CODE
}

View File

@@ -157,7 +157,7 @@ namespace ams::util {
} else if constexpr (Order == std::memory_order_acq_rel || Order == std::memory_order_seq_cst) {
return ::ams::util::impl::LoadAcquireExclusiveForAtomic(p);
} else {
static_assert(Order != Order, "Invalid memory order");
static_assert(false, "Invalid memory order");
}
}
@@ -172,7 +172,7 @@ namespace ams::util {
} else if constexpr (Order == std::memory_order_acq_rel || Order == std::memory_order_seq_cst) {
return ::ams::util::impl::StoreReleaseExclusiveForAtomic(p, s);
} else {
static_assert(Order != Order, "Invalid memory order");
static_assert(false, "Invalid memory order");
}
}

View File

@@ -22,7 +22,7 @@ namespace ams::util {
template<typename T, size_t Size = sizeof(T), size_t Align = alignof(T)>
struct TypedStorage {
typename std::aligned_storage<Size, Align>::type _storage;
alignas(Align) std::byte _storage[Size];
};
template<typename T>

View File

@@ -25,12 +25,12 @@ namespace ams::ldr {
}
/* ScopedCodeMount functionality. */
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc) : m_lk(g_scoped_code_mount_lock), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc);
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, PlatformId platform) : m_lk(g_scoped_code_mount_lock), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc, platform);
}
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o) : m_lk(g_scoped_code_mount_lock), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc);
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o, PlatformId platform) : m_lk(g_scoped_code_mount_lock), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc, platform);
}
ScopedCodeMount::~ScopedCodeMount() {
@@ -46,25 +46,28 @@ namespace ams::ldr {
}
}
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc) {
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, PlatformId platform) {
/* Capture override status, if necessary. */
this->EnsureOverrideStatus(loc);
AMS_ABORT_UNLESS(m_has_status);
/* Get the content path. */
char content_path[fs::EntryNameLengthMax + 1];
R_TRY(GetProgramPath(content_path, sizeof(content_path), loc));
R_TRY(GetProgramPath(content_path, sizeof(content_path), loc, platform));
/* Get the content attributes. */
const auto content_attributes = GetPlatformContentAttributes(platform);
/* Mount the atmosphere code file system. */
R_TRY(fs::MountCodeForAtmosphereWithRedirection(std::addressof(m_ams_code_verification_data), AtmosphereCodeMountName, content_path, fs::ContentAttributes_None, loc.program_id, m_override_status.IsHbl(), m_override_status.IsProgramSpecific()));
R_TRY(fs::MountCodeForAtmosphereWithRedirection(std::addressof(m_ams_code_verification_data), AtmosphereCodeMountName, content_path, content_attributes, loc.program_id, m_override_status.IsHbl(), m_override_status.IsProgramSpecific()));
m_mounted_ams = true;
/* Mount the sd or base code file system. */
R_TRY(fs::MountCodeForAtmosphere(std::addressof(m_sd_or_base_code_verification_data), SdOrCodeMountName, content_path, fs::ContentAttributes_None, loc.program_id));
R_TRY(fs::MountCodeForAtmosphere(std::addressof(m_sd_or_base_code_verification_data), SdOrCodeMountName, content_path, content_attributes, loc.program_id));
m_mounted_sd_or_code = true;
/* Mount the base code file system. */
if (R_SUCCEEDED(fs::MountCode(std::addressof(m_base_code_verification_data), CodeMountName, content_path, fs::ContentAttributes_None, loc.program_id))) {
if (R_SUCCEEDED(fs::MountCode(std::addressof(m_base_code_verification_data), CodeMountName, content_path, content_attributes, loc.program_id))) {
m_mounted_code = true;
}
@@ -80,7 +83,7 @@ namespace ams::ldr {
}
/* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc) {
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, PlatformId platform) {
/* Check for storage id none. */
if (static_cast<ncm::StorageId>(loc.storage_id) == ncm::StorageId::None) {
std::memset(out_path, 0, out_size);
@@ -88,6 +91,10 @@ namespace ams::ldr {
R_SUCCEED();
}
/* Get the content attributes. */
const auto content_attributes = GetPlatformContentAttributes(platform);
AMS_UNUSED(content_attributes);
lr::Path path;
/* Check that path registration is allowable. */
@@ -159,4 +166,12 @@ namespace ams::ldr {
R_SUCCEED();
}
fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform) {
switch (platform) {
case PlatformId_Nx:
return fs::ContentAttributes_None;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}

View File

@@ -34,8 +34,8 @@ namespace ams::ldr {
bool m_mounted_sd_or_code;
bool m_mounted_code;
public:
ScopedCodeMount(const ncm::ProgramLocation &loc);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
ScopedCodeMount(const ncm::ProgramLocation &loc, PlatformId platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, PlatformId platform);
~ScopedCodeMount();
Result GetResult() const {
@@ -59,21 +59,27 @@ namespace ams::ldr {
return m_base_code_verification_data;
}
private:
Result Initialize(const ncm::ProgramLocation &loc);
Result Initialize(const ncm::ProgramLocation &loc, PlatformId platform);
void EnsureOverrideStatus(const ncm::ProgramLocation &loc);
};
constexpr inline const char * const AtmosphereCodeMountName = "ams-code";
constexpr inline const char * const SdOrCodeMountName = "sd-code";
constexpr inline const char * const CodeMountName = "code";
constexpr inline const char * const AtmosphereCodeMountName = "ams-code";
constexpr inline const char * const AtmosphereCompatMountName = "ams-cmpt";
constexpr inline const char * const SdOrCodeMountName = "sd-code";
constexpr inline const char * const CodeMountName = "code";
constexpr inline const char * const CompatMountName = "cmpt";
#define ENCODE_ATMOSPHERE_CODE_PATH(relative) "ams-code:" relative
#define ENCODE_ATMOSPHERE_CMPT_PATH(relative) "ams-cmpt:" relative
#define ENCODE_SD_OR_CODE_PATH(relative) "sd-code:" relative
#define ENCODE_CODE_PATH(relative) "code:" relative
#define ENCODE_CMPT_PATH(relative) "cmpt:" relative
/* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc);
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, PlatformId platform);
Result RedirectProgramPath(const char *path, size_t size, const ncm::ProgramLocation &loc);
Result RedirectHtmlDocumentPathForHbl(const ncm::ProgramLocation &loc);
fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform);
}

View File

@@ -27,56 +27,72 @@ namespace ams::ldr {
constinit ArgumentStore g_argument_store;
bool IsValidPlatform(PlatformId platform) {
return platform == PlatformId_Nx;
}
Result CreateProcessByPlatform(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit, PlatformId platform) {
/* Check that the platform is valid. */
R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId());
/* Get the location and override status. */
ncm::ProgramLocation loc;
cfg::OverrideStatus override_status;
R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), pin_id));
/* Get the program path. */
char path[fs::EntryNameLengthMax];
R_TRY(GetProgramPath(path, sizeof(path), loc, platform));
path[sizeof(path) - 1] = '\x00';
/* Create the process. */
R_RETURN(ldr::CreateProcess(out, pin_id, loc, override_status, path, g_argument_store.Get(loc.program_id), flags, resource_limit, platform));
}
Result GetProgramInfoByPlatform(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, PlatformId platform) {
/* Check that the platform is valid. */
R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId());
/* Zero output. */
std::memset(out, 0, sizeof(*out));
/* Get the program path. */
char path[fs::EntryNameLengthMax];
R_TRY(GetProgramPath(path, sizeof(path), loc, platform));
path[sizeof(path) - 1] = '\x00';
/* Get the program info. */
cfg::OverrideStatus status;
R_TRY(ldr::GetProgramInfo(out, std::addressof(status), loc, path, platform));
if (loc.program_id != out->program_id) {
/* Redirect the program path. */
const ncm::ProgramLocation new_loc = ncm::ProgramLocation::Make(out->program_id, static_cast<ncm::StorageId>(loc.storage_id));
R_TRY(RedirectProgramPath(path, sizeof(path), new_loc));
/* Update the arguments, as needed. */
if (const auto *entry = g_argument_store.Get(loc.program_id); entry != nullptr) {
R_TRY(g_argument_store.Set(new_loc.program_id, entry->argument, entry->argument_size));
}
}
/* If we should, set the output status. */
if (out_status != nullptr) {
*out_status = status;
}
R_SUCCEED();
}
}
Result LoaderService::CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit) {
/* Declare program path, which we'll need later. */
/* Get the location and override status. */
ncm::ProgramLocation loc;
cfg::OverrideStatus override_status;
R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), pin_id));
/* Get the program path. */
char path[fs::EntryNameLengthMax];
R_TRY(GetProgramPath(path, sizeof(path), loc));
path[sizeof(path) - 1] = '\x00';
/* Create the process. */
R_RETURN(ldr::CreateProcess(out, pin_id, loc, override_status, path, g_argument_store.Get(loc.program_id), flags, resource_limit));
R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, PlatformId_Nx));
}
Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
/* Zero output. */
std::memset(out, 0, sizeof(*out));
/* Get the program path. */
char path[fs::EntryNameLengthMax];
R_TRY(GetProgramPath(path, sizeof(path), loc));
path[sizeof(path) - 1] = '\x00';
/* Get the program info. */
cfg::OverrideStatus status;
R_TRY(ldr::GetProgramInfo(out, std::addressof(status), loc, path));
if (loc.program_id != out->program_id) {
/* Redirect the program path. */
const ncm::ProgramLocation new_loc = ncm::ProgramLocation::Make(out->program_id, static_cast<ncm::StorageId>(loc.storage_id));
R_TRY(RedirectProgramPath(path, sizeof(path), new_loc));
/* Update the arguments, as needed. */
if (const auto *entry = g_argument_store.Get(loc.program_id); entry != nullptr) {
R_TRY(this->SetProgramArgument(new_loc.program_id, entry->argument, entry->argument_size));
}
}
/* If we should, set the output status. */
if (out_status != nullptr) {
*out_status = status;
}
R_SUCCEED();
R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, PlatformId_Nx));
}
Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {

View File

@@ -55,21 +55,8 @@ namespace ams::ldr {
R_UNLESS(npdm->magic == Npdm::Magic, ldr::ResultInvalidMeta());
/* Validate flags. */
u32 mask;
if (hos::GetVersion() >= hos::Version_11_0_0) {
/* 11.0.0 added bit 5 = "DisableDeviceAddressSpaceMerge". */
mask = ~0x3F;
} else if (hos::GetVersion() >= hos::Version_7_0_0) {
/* 7.0.0 added bit 4 = "UseOptimizedMemory" */
mask = ~0x1F;
} else {
mask = ~0xF;
}
/* We set the "DisableDeviceAddressSpaceMerge" bit on all versions, so be permissive with it. */
mask &= ~0x20;
R_UNLESS(!(npdm->flags & mask), ldr::ResultInvalidMeta());
constexpr u32 InvalidMetaFlagMask = 0x80000000;
R_UNLESS(!(npdm->flags & InvalidMetaFlagMask), ldr::ResultInvalidMeta());
/* Validate Acid extents. */
R_TRY(ValidateSubregion(sizeof(Npdm), size, npdm->acid_offset, npdm->acid_size, sizeof(Acid)));
@@ -90,8 +77,8 @@ namespace ams::ldr {
}
/* Validate that the acid version is correct. */
constexpr u8 MinimumValueForAcid209 = 14; /* TODO: What is the actual meaning of this value? */
if (acid->unknown_209 < MinimumValueForAcid209) {
constexpr u8 SupportedSdkMajorVersion = ams::svc::ConvertToSdkMajorVersion(ams::svc::SupportedKernelMajorVersion);
if (acid->unknown_209 < SupportedSdkMajorVersion) {
R_UNLESS(acid->version == 0, ldr::ResultInvalidMeta());
R_UNLESS(acid->unknown_209 == 0, ldr::ResultInvalidMeta());
}
@@ -116,22 +103,30 @@ namespace ams::ldr {
R_SUCCEED();
}
const u8 *GetAcidSignatureModulus(u32 key_generation) {
return fssystem::GetAcidSignatureKeyModulus(!IsDevelopmentForAcidSignatureCheck(), key_generation);
const u8 *GetAcidSignatureModulus(PlatformId platform, u8 key_generation, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused);
}
Result ValidateAcidSignature(Meta *meta) {
size_t GetAcidSignatureModulusSize(PlatformId platform, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused);
}
Result ValidateAcidSignature(Meta *meta, PlatformId platform, bool unk_unused) {
/* Loader did not check signatures prior to 10.0.0. */
if (hos::GetVersion() < hos::Version_10_0_0) {
meta->check_verification_data = false;
R_SUCCEED();
}
/* Get the signature key generation. */
const auto signature_key_generation = meta->npdm->signature_key_generation;
R_UNLESS(fssystem::IsValidSignatureKeyGeneration(platform, signature_key_generation), ldr::ResultInvalidMeta());
/* Verify the signature. */
const u8 *sig = meta->acid->signature;
const size_t sig_size = sizeof(meta->acid->signature);
const u8 *mod = GetAcidSignatureModulus(meta->npdm->signature_key_generation);
const size_t mod_size = fssystem::AcidSignatureKeyModulusSize;
const u8 *mod = GetAcidSignatureModulus(platform, signature_key_generation, unk_unused);
const size_t mod_size = GetAcidSignatureModulusSize(platform, unk_unused);
const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent();
const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize;
const u8 *msg = meta->acid->modulus;
@@ -195,7 +190,10 @@ namespace ams::ldr {
}
/* API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform, bool unk_unused) {
/* Set the cached program id back to zero. */
g_cached_program_id = {};
/* Try to load meta from file. */
fs::FileHandle file;
R_TRY(fs::OpenFile(std::addressof(file), AtmosphereMetaPath, fs::OpenMode_Read));
@@ -261,7 +259,7 @@ namespace ams::ldr {
R_TRY(fs::OpenFile(std::addressof(file), BaseMetaPath, fs::OpenMode_Read));
ON_SCOPE_EXIT { fs::CloseFile(file); };
R_TRY(LoadMetaFromFile(file, std::addressof(g_original_meta_cache)));
R_TRY(ValidateAcidSignature(std::addressof(g_original_meta_cache.meta)));
R_TRY(ValidateAcidSignature(std::addressof(g_original_meta_cache.meta), platform, unk_unused));
meta->modulus = g_original_meta_cache.meta.modulus;
meta->check_verification_data = g_original_meta_cache.meta.check_verification_data;
}
@@ -280,9 +278,9 @@ namespace ams::ldr {
R_SUCCEED();
}
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform) {
if (g_cached_program_id != loc.program_id || g_cached_override_status != status) {
R_RETURN(LoadMeta(out_meta, loc, status));
R_RETURN(LoadMeta(out_meta, loc, status, platform, false));
}
*out_meta = g_meta_cache.meta;
R_SUCCEED();

View File

@@ -36,8 +36,8 @@ namespace ams::ldr {
};
/* Meta API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status);
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status);
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform, bool unk_unused);
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform);
void InvalidateMetaCache();
}

View File

@@ -34,23 +34,43 @@ namespace ams::ldr {
enum NsoIndex {
Nso_Rtld = 0,
Nso_Main = 1,
Nso_SubSdk0 = 2,
Nso_SubSdk1 = 3,
Nso_SubSdk2 = 4,
Nso_SubSdk3 = 5,
Nso_SubSdk4 = 6,
Nso_SubSdk5 = 7,
Nso_SubSdk6 = 8,
Nso_SubSdk7 = 9,
Nso_SubSdk8 = 10,
Nso_SubSdk9 = 11,
Nso_Sdk = 12,
Nso_Compat0 = 2,
Nso_Compat1 = 3,
Nso_Compat2 = 4,
Nso_Compat3 = 5,
Nso_Compat4 = 6,
Nso_Compat5 = 7,
Nso_Compat6 = 8,
Nso_Compat7 = 9,
Nso_Compat8 = 10,
Nso_Compat9 = 11,
Nso_SubSdk0 = 12,
Nso_SubSdk1 = 13,
Nso_SubSdk2 = 14,
Nso_SubSdk3 = 15,
Nso_SubSdk4 = 16,
Nso_SubSdk5 = 17,
Nso_SubSdk6 = 18,
Nso_SubSdk7 = 19,
Nso_SubSdk8 = 20,
Nso_SubSdk9 = 21,
Nso_Sdk = 22,
Nso_Count,
};
constexpr inline const char *NsoPaths[Nso_Count] = {
ENCODE_ATMOSPHERE_CODE_PATH("/rtld"),
ENCODE_ATMOSPHERE_CODE_PATH("/main"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat0"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat1"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat2"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat3"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat4"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat5"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat6"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat7"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat8"),
ENCODE_ATMOSPHERE_CMPT_PATH("/compat9"),
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk0"),
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk1"),
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk2"),
@@ -360,6 +380,11 @@ namespace ams::ldr {
flags |= svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge;
}
/* 18.0.0+/meso Set Alias region extra size. */
if (meta_flags & Npdm::MetaFlag_EnableAliasRegionExtraSize) {
flags |= svc::CreateProcessFlag_EnableAliasRegionExtraSize;
}
*out = flags;
R_SUCCEED();
}
@@ -639,15 +664,15 @@ namespace ams::ldr {
}
/* Process Creation API. */
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) {
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, PlatformId platform) {
/* Mount code. */
AMS_UNUSED(path);
ScopedCodeMount mount(loc, override_status);
ScopedCodeMount mount(loc, override_status, platform);
R_TRY(mount.GetResult());
/* Load meta, possibly from cache. */
Meta meta;
R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status));
R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status, platform));
/* Validate meta. */
R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData()));
@@ -695,16 +720,16 @@ namespace ams::ldr {
R_SUCCEED();
}
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path) {
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform) {
Meta meta;
/* Load Meta. */
{
AMS_UNUSED(path);
ScopedCodeMount mount(loc);
ScopedCodeMount mount(loc, platform);
R_TRY(mount.GetResult());
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus()));
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), platform, false));
if (out_status != nullptr) {
*out_status = mount.GetOverrideStatus();
}

View File

@@ -19,8 +19,8 @@
namespace ams::ldr {
/* Process Creation API. */
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit);
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path);
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, PlatformId platform);
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform);
Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
Result UnpinProgram(PinId id);

View File

@@ -61,7 +61,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -std=gnu++20 -fno-exceptions -fno-rtti
CXXFLAGS := $(CFLAGS) -std=gnu++23 -fno-exceptions -fno-rtti
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)

View File

@@ -61,7 +61,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++20
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)