Compare commits

..

22 Commits

Author SHA1 Message Date
Michael Scire
0cd3d29770 loader: add usb3 patches for 18.0.0 2024-03-28 09:55:38 -07:00
Michael Scire
f860590d5f spl: add support for new spl:es command 33 2024-03-28 04:43:07 -07:00
Michael Scire
e6cf70a18a erpt: actually support non-sequential ids, nintendo why 2024-03-28 04:36:14 -07:00
Michael Scire
b4d453882d emummc: update for 18.0.0 2024-03-28 04:33:44 -07:00
Michael Scire
05df389d30 erpt: add new IDs/categories 2024-03-28 03:51:10 -07:00
Michael Scire
23d6014f91 jpegdec: stop bundling (TODO post-prerelease) 2024-03-28 03:46:41 -07:00
Michael Scire
496f8bf45e exo/fusee: apparently 18.0.0 did not burn a fuse 2024-03-28 03:45:07 -07:00
Michael Scire
4974a98ec6 svc: advertise support for 18.3.0.0 2024-03-28 03:44:31 -07:00
Michael Scire
1f44a9c4bf kern: fix whoops in new page table logic 2024-03-28 03:43:22 -07:00
Michael Scire
6113ffa191 kern: refactor smc helpers to share more common logic 2024-03-28 03:42:37 -07:00
Michael Scire
48e86f0406 kern: return ExceptionType_UnalignedData on data abort caused by alignment fault 2024-03-28 02:52:32 -07:00
Michael Scire
bf3203da0f kern: add KPageGroup::CopyRangeTo 2024-03-28 02:50:37 -07:00
Michael Scire
af7a200865 kern: implement new attr tracking for memory range/traversal context 2024-03-28 02:30:24 -07:00
Michael Scire
cfb12deb51 kern: simplify size calculations in KPageTableBase::Read/WriteDebugIoMemory 2024-03-28 02:22:19 -07:00
Michael Scire
4aac5f0082 kern: pass properties directly to KPageTableBase::AllocateAndMapPagesImpl 2024-03-28 02:19:45 -07:00
Michael Scire
f5a9d1d6e8 kern: take alignment argument in KMemoryManager::AllocateAndOpen 2024-03-28 02:17:38 -07:00
Michael Scire
5e63792a67 kern/os: support CreateProcessFlag_EnableAliasRegionExtraSize 2024-03-28 02:07:04 -07:00
Michael Scire
8cacb07d5f kern: revise KPageTableBase region layout logic to match 18.0.0 changes 2024-03-28 01:47:36 -07:00
Michael Scire
4301e948cc kern: fix longstanding bug in ConvertToKMemoryPermission 2024-03-28 00:25:48 -07:00
Michael Scire
c331216f99 kern: pass kernel base from KernelLdr to Kernel 2024-03-28 00:24:45 -07:00
Michael Scire
b12e89d0a9 kern: use userspace access instructions to read from tlr 2024-03-28 00:18:31 -07:00
Michael Scire
83b3b09e73 fusee/exo/ams: update with new keydata/version enums 2024-03-27 18:48:49 -07:00
44 changed files with 161 additions and 455 deletions

View File

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

View File

@@ -1,32 +1,4 @@
# 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 = f23f943d4092ca9490dbcebbdd117abc3740abcf
parent = 1e3349e99a023517269b3fc1bc32fd84e5b3caa9
commit = 9513a5412057b1f1bc44ed8e717c57c726763a88
parent = e4d08ae0c5342cdb0875d164522a63ec9d233052
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.1.0**
**1.0.0 - 18.0.0**
## Features
* Arbitrary SDMMC backend selection

View File

@@ -71,8 +71,6 @@
#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
@@ -155,8 +153,6 @@ 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) {
@@ -270,10 +266,6 @@ 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,9 +104,6 @@ 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,
};

View File

@@ -1,59 +0,0 @@
/*
* 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__

View File

@@ -1,59 +0,0 @@
/*
* 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,9 +174,6 @@ namespace ams::nxboot {
FsVersion_18_0_0,
FsVersion_18_0_0_Exfat,
FsVersion_18_1_0,
FsVersion_18_1_0_Exfat,
FsVersion_Count,
};
@@ -263,9 +260,6 @@ 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,16 +1002,14 @@ 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 << Shift) & Mask); \
cur_reg_value |= ((src_value << (DstLow - SrcLow)) & Mask); \
} else { \
cur_reg_value |= ((src_value >> Shift) & Mask); \
cur_reg_value |= ((src_value >> (SrcLow - DstLow)) & Mask); \
} \
} \
}

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = bb767869105d0eb5c38425f54bf20614639a078d
parent = ab5cc7568430e2c1b3fa1be6be104b7c5f71eb32
commit = bfc55834869fe24f8d94550bc6909a65ae7d35c2
parent = 742fd16080bce8cd664d6244304a771f82e8aa04
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++23 -Wno-invalid-offsetof
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20 -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,7 +16,6 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssystem/fssystem_nca_file_system_driver.hpp>
#include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::fssystem {
@@ -26,13 +25,10 @@ namespace ams::fssystem {
void InvalidateHardwareAesKey();
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 *GetAcidSignatureKeyModulus(bool prod, size_t key_generation);
const u8 *GetAcidSignatureKeyPublicExponent();
constexpr inline size_t AcidSignatureKeyModulusSize = NcaCryptoConfiguration::Rsa2048KeyModulusSize;
constexpr inline size_t AcidSignatureKeyPublicExponentSize = NcaCryptoConfiguration::Rsa2048KeyPublicExponentSize;
}

View File

@@ -83,7 +83,6 @@ 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

@@ -1,27 +0,0 @@
/*
* 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,7 +19,6 @@
#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 {
@@ -225,7 +224,6 @@ 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(false, "Invalid BufferTransferMode");
static_assert(TransferMode != TransferMode, "Invalid BufferTransferMode");
}
}();

View File

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

View File

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

View File

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

View File

@@ -23,8 +23,8 @@ namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
namespace {
alignas(0x10) constinit std::byte g_fsp_service_object_buffer[0x80] = {};
alignas(0x10) constinit std::byte g_fsp_ldr_service_object_buffer[0x80] = {};
constinit std::aligned_storage_t<0x80> g_fsp_service_object_buffer;
constinit std::aligned_storage_t<0x80> g_fsp_ldr_service_object_buffer;
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 {
alignas(0x10) constinit std::byte g_static_buffer_for_program_info_for_initial_process[0x80] = {};
constinit std::aligned_storage<0x80>::type g_static_buffer_for_program_info_for_initial_process = {};
template<typename T>
class StaticAllocatorForProgramInfoForInitialProcess : public std::allocator<T> {

View File

@@ -22,11 +22,9 @@ namespace ams::fssystem {
constexpr inline const size_t KeySize = crypto::AesDecryptor128::KeySize;
constexpr inline const size_t NxAcidSignatureKeyGenerationMax = 1;
constexpr inline const size_t AcidSignatureKeyGenerationMax = 1;
constexpr inline const size_t NxAcidSignatureKeyModulusSize = NcaCryptoConfiguration::Rsa2048KeyModulusSize;
constexpr inline const u8 NxAcidSignatureKeyModulusDev[NxAcidSignatureKeyGenerationMax + 1][NxAcidSignatureKeyModulusSize] = {
constexpr inline const u8 AcidSignatureKeyModulusDev[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
{
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,
@@ -65,7 +63,7 @@ namespace ams::fssystem {
}
};
constexpr inline const u8 NxAcidSignatureKeyModulusProd[NxAcidSignatureKeyGenerationMax + 1][NxAcidSignatureKeyModulusSize] = {
constexpr inline const u8 AcidSignatureKeyModulusProd[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
{
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,
@@ -104,7 +102,7 @@ namespace ams::fssystem {
}
};
static_assert(sizeof(NxAcidSignatureKeyModulusProd) == sizeof(NxAcidSignatureKeyModulusDev));
static_assert(sizeof(AcidSignatureKeyModulusProd) == sizeof(AcidSignatureKeyModulusDev));
constexpr inline const u8 AcidSignatureKeyPublicExponent[] = {
0x01, 0x00, 0x01
@@ -297,36 +295,10 @@ namespace ams::fssystem {
}
}
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 *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];
}
const u8 *GetAcidSignatureKeyPublicExponent() {

View File

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

View File

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

View File

@@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 7
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
#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 1
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0

View File

@@ -81,9 +81,8 @@
#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_1_0
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_18_0_0
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@@ -157,7 +156,6 @@ 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,8 +34,6 @@ 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,13 +85,14 @@ 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(this auto const &self) { return ResultTraits::GetModuleFromValue(self.GetValue()); }
constexpr ALWAYS_INLINE BaseType GetDescription(this auto const &self) { return ResultTraits::GetDescriptionFromValue(self.GetValue()); }
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()); }
};
class ResultInternalAccessor;
@@ -100,10 +101,10 @@ namespace ams {
class ResultSuccess;
class Result final : public result::impl::ResultBase {
class Result final : public result::impl::ResultBase<Result> {
friend class result::impl::ResultInternalAccessor;
public:
using Base = typename result::impl::ResultBase;
using Base = typename result::impl::ResultBase<Result>;
private:
typename Base::BaseType m_value;
private:
@@ -156,9 +157,9 @@ namespace ams {
}
class ResultSuccess final : public result::impl::ResultBase {
class ResultSuccess final : public result::impl::ResultBase<ResultSuccess> {
public:
using Base = typename result::impl::ResultBase;
using Base = typename result::impl::ResultBase<ResultSuccess>;
public:
constexpr ALWAYS_INLINE operator Result() const { return result::impl::MakeResult(Base::SuccessValue); }
static constexpr ALWAYS_INLINE bool CanAccept(Result result) { return result.IsSuccess(); }
@@ -188,9 +189,9 @@ namespace ams {
namespace result::impl {
template<ResultTraits::BaseType _Module, ResultTraits::BaseType _Description>
class ResultErrorBase : public ResultBase {
class ResultErrorBase : public ResultBase<ResultErrorBase<_Module, _Description>> {
public:
using Base = typename result::impl::ResultBase;
using Base = typename result::impl::ResultBase<ResultErrorBase<_Module, _Description>>;
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(false, "Invalid Size");
static_assert(Size != 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(false, "Invalid Size");
static_assert(Size != 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(false, "Invalid Size");
static_assert(Size != 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(false, "Invalid Size");
static_assert(Size != 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(false, "Invalid CodeGenerationKind");
static_assert(CodeGenKind != CodeGenKind, "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(false, "Invalid CodeGenerationKind");
static_assert(CodeGenKind != CodeGenKind, "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(false, "Unknown MetaOperationKind"); }
else { static_assert(Kind != Kind, "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(false, "Invalid memory order");
static_assert(Order != Order, "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(false, "Invalid memory order");
static_assert(Order != Order, "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 {
alignas(Align) std::byte _storage[Size];
typename std::aligned_storage<Size, Align>::type _storage;
};
template<typename T>

View File

@@ -25,12 +25,12 @@ namespace ams::ldr {
}
/* ScopedCodeMount functionality. */
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) : 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, 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(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() {
@@ -46,28 +46,25 @@ namespace ams::ldr {
}
}
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, PlatformId platform) {
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc) {
/* 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, platform));
/* Get the content attributes. */
const auto content_attributes = GetPlatformContentAttributes(platform);
R_TRY(GetProgramPath(content_path, sizeof(content_path), loc));
/* Mount the atmosphere code file system. */
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()));
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()));
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, content_attributes, loc.program_id));
R_TRY(fs::MountCodeForAtmosphere(std::addressof(m_sd_or_base_code_verification_data), SdOrCodeMountName, content_path, fs::ContentAttributes_None, 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, content_attributes, loc.program_id))) {
if (R_SUCCEEDED(fs::MountCode(std::addressof(m_base_code_verification_data), CodeMountName, content_path, fs::ContentAttributes_None, loc.program_id))) {
m_mounted_code = true;
}
@@ -83,7 +80,7 @@ namespace ams::ldr {
}
/* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, PlatformId platform) {
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc) {
/* Check for storage id none. */
if (static_cast<ncm::StorageId>(loc.storage_id) == ncm::StorageId::None) {
std::memset(out_path, 0, out_size);
@@ -91,10 +88,6 @@ 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. */
@@ -166,12 +159,4 @@ 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, PlatformId platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, PlatformId platform);
ScopedCodeMount(const ncm::ProgramLocation &loc);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
~ScopedCodeMount();
Result GetResult() const {
@@ -59,27 +59,21 @@ namespace ams::ldr {
return m_base_code_verification_data;
}
private:
Result Initialize(const ncm::ProgramLocation &loc, PlatformId platform);
Result Initialize(const ncm::ProgramLocation &loc);
void EnsureOverrideStatus(const ncm::ProgramLocation &loc);
};
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";
constexpr inline const char * const AtmosphereCodeMountName = "ams-code";
constexpr inline const char * const SdOrCodeMountName = "sd-code";
constexpr inline const char * const CodeMountName = "code";
#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, PlatformId platform);
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc);
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,72 +27,56 @@ 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) {
R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, PlatformId_Nx));
/* 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));
}
Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, PlatformId_Nx));
/* 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();
}
Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {

View File

@@ -55,8 +55,21 @@ namespace ams::ldr {
R_UNLESS(npdm->magic == Npdm::Magic, ldr::ResultInvalidMeta());
/* Validate flags. */
constexpr u32 InvalidMetaFlagMask = 0x80000000;
R_UNLESS(!(npdm->flags & InvalidMetaFlagMask), ldr::ResultInvalidMeta());
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());
/* Validate Acid extents. */
R_TRY(ValidateSubregion(sizeof(Npdm), size, npdm->acid_offset, npdm->acid_size, sizeof(Acid)));
@@ -77,8 +90,8 @@ namespace ams::ldr {
}
/* Validate that the acid version is correct. */
constexpr u8 SupportedSdkMajorVersion = ams::svc::ConvertToSdkMajorVersion(ams::svc::SupportedKernelMajorVersion);
if (acid->unknown_209 < SupportedSdkMajorVersion) {
constexpr u8 MinimumValueForAcid209 = 14; /* TODO: What is the actual meaning of this value? */
if (acid->unknown_209 < MinimumValueForAcid209) {
R_UNLESS(acid->version == 0, ldr::ResultInvalidMeta());
R_UNLESS(acid->unknown_209 == 0, ldr::ResultInvalidMeta());
}
@@ -103,30 +116,22 @@ namespace ams::ldr {
R_SUCCEED();
}
const u8 *GetAcidSignatureModulus(PlatformId platform, u8 key_generation, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused);
const u8 *GetAcidSignatureModulus(u32 key_generation) {
return fssystem::GetAcidSignatureKeyModulus(!IsDevelopmentForAcidSignatureCheck(), key_generation);
}
size_t GetAcidSignatureModulusSize(PlatformId platform, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused);
}
Result ValidateAcidSignature(Meta *meta, PlatformId platform, bool unk_unused) {
Result ValidateAcidSignature(Meta *meta) {
/* 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(platform, signature_key_generation, unk_unused);
const size_t mod_size = GetAcidSignatureModulusSize(platform, unk_unused);
const u8 *mod = GetAcidSignatureModulus(meta->npdm->signature_key_generation);
const size_t mod_size = fssystem::AcidSignatureKeyModulusSize;
const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent();
const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize;
const u8 *msg = meta->acid->modulus;
@@ -190,10 +195,7 @@ namespace ams::ldr {
}
/* API. */
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 = {};
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
/* Try to load meta from file. */
fs::FileHandle file;
R_TRY(fs::OpenFile(std::addressof(file), AtmosphereMetaPath, fs::OpenMode_Read));
@@ -259,7 +261,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), platform, unk_unused));
R_TRY(ValidateAcidSignature(std::addressof(g_original_meta_cache.meta)));
meta->modulus = g_original_meta_cache.meta.modulus;
meta->check_verification_data = g_original_meta_cache.meta.check_verification_data;
}
@@ -278,9 +280,9 @@ namespace ams::ldr {
R_SUCCEED();
}
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform) {
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
if (g_cached_program_id != loc.program_id || g_cached_override_status != status) {
R_RETURN(LoadMeta(out_meta, loc, status, platform, false));
R_RETURN(LoadMeta(out_meta, loc, status));
}
*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, PlatformId platform, bool unk_unused);
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform);
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);
void InvalidateMetaCache();
}

View File

@@ -34,43 +34,23 @@ namespace ams::ldr {
enum NsoIndex {
Nso_Rtld = 0,
Nso_Main = 1,
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_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_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"),
@@ -380,11 +360,6 @@ 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();
}
@@ -664,15 +639,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, PlatformId platform) {
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) {
/* Mount code. */
AMS_UNUSED(path);
ScopedCodeMount mount(loc, override_status, platform);
ScopedCodeMount mount(loc, override_status);
R_TRY(mount.GetResult());
/* Load meta, possibly from cache. */
Meta meta;
R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status, platform));
R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status));
/* Validate meta. */
R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData()));
@@ -720,16 +695,16 @@ namespace ams::ldr {
R_SUCCEED();
}
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform) {
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path) {
Meta meta;
/* Load Meta. */
{
AMS_UNUSED(path);
ScopedCodeMount mount(loc, platform);
ScopedCodeMount mount(loc);
R_TRY(mount.GetResult());
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), platform, false));
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus()));
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, PlatformId platform);
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform);
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 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++23 -fno-exceptions -fno-rtti
CXXFLAGS := $(CFLAGS) -std=gnu++20 -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++23
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++20
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)