Compare commits

..

No commits in common. "master" and "1.8.0-prerelease" have entirely different histories.

32 changed files with 112 additions and 500 deletions

View file

@ -49,7 +49,7 @@ Code type 0x0 allows writing a static value to a memory address.
`0TMR00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
+ T: Width of memory write (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ R: Register to use as an offset from memory region base.
+ A: Immediate offset to use from memory region base.
+ V: Value to write.
@ -62,13 +62,11 @@ Code type 0x1 performs a comparison of the contents of memory to a static value.
If the condition is not met, all instructions until the appropriate End or Else conditional block terminator are skipped.
#### Encoding
`1TMCXrAA AAAAAAAA VVVVVVVV (VVVVVVVV)`
`1TMC00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ M: Memory region to read from (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative).
+ T: Width of memory write (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ C: Condition to use, see below.
+ X: Operand Type, see below.
+ r: Offset Register (operand types 1).
+ A: Immediate offset to use from memory region base.
+ V: Value to compare to.
@ -80,9 +78,6 @@ If the condition is not met, all instructions until the appropriate End or Else
+ 5: ==
+ 6: !=
#### Operand Type
+ 0: Memory Base + Relative Offset
+ 1: Memory Base + Offset Register + Relative Offset
---
### Code Type 0x2: End Conditional Block
@ -131,7 +126,7 @@ Code type 0x5 allows loading a value from memory into a register, either using a
`5TMR00AA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ R: Register to load value into.
+ A: Immediate offset to use from memory region base.
@ -142,22 +137,6 @@ Code type 0x5 allows loading a value from memory into a register, either using a
+ R: Register to load value into. (This register is also used as the base memory address).
+ A: Immediate offset to use from register R.
#### Load from Register Address Encoding
`5T0R2SAA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ R: Register to load value into.
+ S: Register to use as the base memory address.
+ A: Immediate offset to use from register R.
#### Load From Fixed Address Encoding with offset register
`5TMR3SAA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative).
+ R: Register to load value into.
+ S: Register to use as offset register.
+ A: Immediate offset to use from memory region base.
---
### Code Type 0x6: Store Static Value to Register Memory Address
@ -271,10 +250,7 @@ Code type 0x9 allows performing arithmetic on registers.
+ 7: Logical Not (discards right-hand operand)
+ 8: Logical Xor
+ 9: None/Move (discards right-hand operand)
+ 10: Float Addition, T==4 single T==8 double
+ 11: Float Subtraction, T==4 single T==8 double
+ 12: Float Multiplication, T==4 single T==8 double
+ 13: Float Division, T==4 single T==8 double
---
### Code Type 0xA: Store Register to Memory Address
@ -404,61 +380,6 @@ Code type 0xC3 reads or writes a static register with a given register.
---
### Code Type 0xC4: Begin Extended Keypress Conditional Block
Code type 0xC4 enters or skips a conditional block based on whether a key combination is pressed.
#### Encoding
`C4r00000 kkkkkkkk kkkkkkkk`
+ r: Auto-repeat, see below.
+ kkkkkkkkkk: Keypad mask to check against output of `hidKeysDown()`.
Note that for multiple button combinations, the bitmasks should be OR'd together.
#### Auto-repeat
+ 0: The conditional block executes only once when the keypad mask matches. The mask must stop matching to reset for the next trigger.
+ 1: The conditional block executes as long as the keypad mask matches.
#### Keypad Values
Note: This is the direct output of `hidKeysDown()`.
+ 000000001: A
+ 000000002: B
+ 000000004: X
+ 000000008: Y
+ 000000010: Left Stick Pressed
+ 000000020: Right Stick Pressed
+ 000000040: L
+ 000000080: R
+ 000000100: ZL
+ 000000200: ZR
+ 000000400: Plus
+ 000000800: Minus
+ 000001000: Left
+ 000002000: Up
+ 000004000: Right
+ 000008000: Down
+ 000010000: Left Stick Left
+ 000020000: Left Stick Up
+ 000040000: Left Stick Right
+ 000080000: Left Stick Down
+ 000100000: Right Stick Left
+ 000200000: Right Stick Up
+ 000400000: Right Stick Right
+ 000800000: Right Stick Down
+ 001000000: SL Left Joy-Con
+ 002000000: SR Left Joy-Con
+ 004000000: SL Right Joy-Con
+ 008000000: SR Right Joy-Con
+ 010000000: Top button on Poké Ball Plus (Palma) controller
+ 020000000: Verification
+ 040000000: B button on Left NES/HVC controller in Handheld mode
+ 080000000: Left C button in N64 controller
+ 100000000: Up C button in N64 controller
+ 200000000: Right C button in N64 controller
+ 400000000: Down C button in N64 controller
### Code Type 0xF0: Double Extended-Width Instruction
Code Type 0xF0 signals to the VM to treat the upper three nybbles of the first dword as instruction type, instead of just the upper nybble.

View file

@ -110,7 +110,7 @@ namespace ams::kern::arch::arm64::init {
L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr);
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
if (l1_entry->IsMappedBlock() || l1_entry->IsMappedEmpty()) {
if (l1_entry->IsMappedBlock() || l1_entry->IsEmpty()) {
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= L1BlockSize);
virt_addr += L1BlockSize;
@ -126,7 +126,7 @@ namespace ams::kern::arch::arm64::init {
/* Table, so check if we're mapped in L2. */
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
if (l2_entry->IsMappedBlock() || l2_entry->IsMappedEmpty()) {
if (l2_entry->IsMappedBlock() || l2_entry->IsEmpty()) {
const size_t advance_size = (l2_entry->IsMappedBlock() && l2_entry->IsContiguous()) ? L2ContiguousBlockSize : L2BlockSize;
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
@ -144,7 +144,7 @@ namespace ams::kern::arch::arm64::init {
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
/* L3 must be block or empty. */
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsMappedBlock() || l3_entry->IsMappedEmpty());
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsMappedBlock() || l3_entry->IsEmpty());
const size_t advance_size = (l3_entry->IsMappedBlock() && l3_entry->IsContiguous()) ? L3ContiguousBlockSize : L3BlockSize;
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
@ -164,7 +164,7 @@ namespace ams::kern::arch::arm64::init {
L1PageTableEntry *l1_entry = this->GetL1Entry(virt_addr);
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
if (l1_entry->IsMappedBlock() || l1_entry->IsMappedEmpty()) {
if (l1_entry->IsMappedBlock() || l1_entry->IsEmpty()) {
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= L1BlockSize);
if (l1_entry->IsMappedBlock() && block_size == L1BlockSize) {
@ -182,7 +182,7 @@ namespace ams::kern::arch::arm64::init {
/* Table, so check if we're mapped in L2. */
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
if (l2_entry->IsMappedBlock() || l2_entry->IsMappedEmpty()) {
if (l2_entry->IsMappedBlock() || l2_entry->IsEmpty()) {
const size_t advance_size = (l2_entry->IsMappedBlock() && l2_entry->IsContiguous()) ? L2ContiguousBlockSize : L2BlockSize;
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
@ -202,7 +202,7 @@ namespace ams::kern::arch::arm64::init {
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
/* L3 must be block or empty. */
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsMappedBlock() || l3_entry->IsMappedEmpty());
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsMappedBlock() || l3_entry->IsEmpty());
const size_t advance_size = (l3_entry->IsMappedBlock() && l3_entry->IsContiguous()) ? L3ContiguousBlockSize : L3BlockSize;
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));

View file

@ -122,7 +122,7 @@ namespace ams::kern::arch::arm64 {
/* Construct a new attribute. */
constexpr explicit ALWAYS_INLINE PageTableEntry(Permission perm, PageAttribute p_a, Shareable share, MappingFlag m)
: m_attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share) | static_cast<u64>(m))
: m_attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share) | static_cast<u64>(ExtensionFlag_Valid) | static_cast<u64>(m))
{
/* ... */
}
@ -205,7 +205,6 @@ namespace ams::kern::arch::arm64 {
constexpr ALWAYS_INLINE bool IsMappedBlock() const { return this->GetBits(0, 2) == 1; }
constexpr ALWAYS_INLINE bool IsMappedTable() const { return this->GetBits(0, 2) == 3; }
constexpr ALWAYS_INLINE bool IsMappedEmpty() const { return this->GetBits(0, 2) == 0; }
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 0; }
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }

View file

@ -21,6 +21,12 @@ namespace ams::kern::arch::arm64 {
m_table = static_cast<L1PageTableEntry *>(tb);
m_is_kernel = true;
m_num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
}
void KPageTableImpl::InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end) {
m_table = static_cast<L1PageTableEntry *>(tb);
m_is_kernel = false;
m_num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
/* Page table entries created by KInitialPageTable need to be iterated and modified to ensure KPageTable invariants. */
PageTableEntry *level_entries[EntryLevel_Count] = { nullptr, nullptr, m_table };
@ -62,6 +68,7 @@ namespace ams::kern::arch::arm64 {
/* Advance. */
while (true) {
/* Advance to the next entry at the current level. */
++level_entries[level];
if (!util::IsAligned(reinterpret_cast<uintptr_t>(++level_entries[level]), PageSize)) {
break;
}
@ -76,12 +83,6 @@ namespace ams::kern::arch::arm64 {
}
}
void KPageTableImpl::InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end) {
m_table = static_cast<L1PageTableEntry *>(tb);
m_is_kernel = false;
m_num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
}
L1PageTableEntry *KPageTableImpl::Finalize() {
return m_table;
}

View file

@ -1214,7 +1214,7 @@ namespace ams::kern::board::nintendo::nx {
for (size_t i = 0; i < map_count; ++i) {
/* Get the physical address. */
const KPhysicalAddress phys_addr = l2[l2_index + i].GetPhysicalAddress();
MESOSPHERE_ASSERT(phys_addr == Null<KPhysicalAddress> || IsHeapPhysicalAddress(phys_addr));
MESOSPHERE_ASSERT(IsHeapPhysicalAddress(phys_addr));
/* Fully invalidate the entry. */
l2[l2_index + i].Invalidate();

View file

@ -95,7 +95,7 @@ namespace ams::impl {
AMS_DEFINE_SYSTEM_THREAD(16, creport, Main);
/* ro. */
AMS_DEFINE_SYSTEM_THREAD(21, ro, Main);
AMS_DEFINE_SYSTEM_THREAD(16, ro, Main);
/* gpio. */
AMS_DEFINE_SYSTEM_THREAD(-12, gpio, InterruptHandler);

View file

@ -50,7 +50,7 @@ namespace ams::ddsf {
}
void DetachDevice() {
/* AMS_ASSERT(this->IsOpen()); */
AMS_ASSERT(this->IsOpen());
m_device = nullptr;
m_access_mode = AccessMode_None;
AMS_ASSERT(!this->IsOpen());

View file

@ -16,7 +16,7 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssystem/fssystem_nca_file_system_driver.hpp>
#include <stratosphere/ncm/ncm_content_meta_platform.hpp>
#include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::fssystem {
@ -26,10 +26,10 @@ namespace ams::fssystem {
void InvalidateHardwareAesKey();
bool IsValidSignatureKeyGeneration(ncm::ContentMetaPlatform platform, size_t key_generation);
bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation);
const u8 *GetAcidSignatureKeyModulus(ncm::ContentMetaPlatform platform, bool prod, size_t key_generation, bool unk_unused);
size_t GetAcidSignatureKeyModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused);
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();

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,7 +19,7 @@
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/ncm/ncm_program_location.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
#include <stratosphere/ncm/ncm_content_meta_platform.hpp>
#include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::ldr {

View file

@ -154,14 +154,12 @@ spl_secure_monitor_api.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/l
fs_id_string_impl.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/include
ifeq ($(ATMOSPHERE_OS_NAME),windows)
# Audit builds fail when these have lto disabled.
# Noting 10/29/24:
# In member function '__ct ':
# internal compiler error: in binds_to_current_def_p, at symtab.cc:2589
os_%.o: CXXFLAGS += -fno-lto
fssystem_%.o: CXXFLAGS += -fno-lto
fssrv_%.o: CXXFLAGS += -fno-lto
fs_%.o: CXXFLAGS += -fno-lto
# I do not remember why these had fno-lto, but it appears to
# work without no-lto (2023/03/09), so I am disabling these. I may regret this later.
#os_%.o: CXXFLAGS += -fno-lto
#fssystem_%.o: CXXFLAGS += -fno-lto
#fssrv_%.o: CXXFLAGS += -fno-lto
#fs_%.o: CXXFLAGS += -fno-lto
endif
#---------------------------------------------------------------------------------

View file

@ -20,7 +20,7 @@ namespace ams::diag {
namespace impl {
constexpr inline size_t DebugPrintBufferLength = 0x100;
constexpr inline size_t DebugPrintBufferLength = 0x80;
}

View file

@ -537,8 +537,6 @@ namespace ams::erpt::srv {
/* NOTE: Nintendo ignores the result of this call. */
SubmitFsInfo();
}
#else
AMS_UNUSED(flags);
#endif

View file

@ -297,20 +297,20 @@ namespace ams::fssystem {
}
}
bool IsValidSignatureKeyGeneration(ncm::ContentMetaPlatform platform, size_t key_generation) {
bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation) {
switch (platform) {
case ncm::ContentMetaPlatform::Nx:
case ldr::PlatformId_Nx:
return key_generation <= NxAcidSignatureKeyGenerationMax;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
const u8 *GetAcidSignatureKeyModulus(ncm::ContentMetaPlatform platform, bool prod, size_t key_generation, bool unk_unused) {
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 ncm::ContentMetaPlatform::Nx:
case ldr::PlatformId_Nx:
{
const size_t used_keygen = (key_generation % (NxAcidSignatureKeyGenerationMax + 1));
return prod ? NxAcidSignatureKeyModulusProd[used_keygen] : NxAcidSignatureKeyModulusDev[used_keygen];
@ -319,11 +319,11 @@ namespace ams::fssystem {
}
}
size_t GetAcidSignatureKeyModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused) {
size_t GetAcidSignatureKeyModulusSize(ldr::PlatformId platform, bool unk_unused) {
AMS_UNUSED(unk_unused);
switch (platform) {
case ncm::ContentMetaPlatform::Nx:
case ldr::PlatformId_Nx:
return NxAcidSignatureKeyModulusSize;
AMS_UNREACHABLE_DEFAULT_CASE();
}

View file

@ -1346,7 +1346,7 @@ namespace ams::fssystem {
R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result);
/* Check if we tried to open a directory. */
fs::DirectoryEntryType type{};
fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type is anything other than directory, perform generic result conversion. */
@ -1459,7 +1459,7 @@ namespace ams::fssystem {
R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxFilePathLength, 0, false));
/* Check that the old path is a file. */
fs::DirectoryEntryType type{};
fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get()));
R_UNLESS(type == fs::DirectoryEntryType_File, fs::ResultPathNotFound());
@ -1509,7 +1509,7 @@ namespace ams::fssystem {
R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxDirectoryPathLength, 0, false));
/* Check that the old path is a file. */
fs::DirectoryEntryType type{};
fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get()));
R_UNLESS(type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound());
@ -1577,7 +1577,7 @@ namespace ams::fssystem {
R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result);
/* Check if we tried to open a directory. */
fs::DirectoryEntryType type{};
fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type isn't file, return path not found. */
@ -1623,7 +1623,7 @@ namespace ams::fssystem {
ON_RESULT_FAILURE { ::CloseHandle(dir_handle); };
/* Check that we tried to open a directory. */
fs::DirectoryEntryType type{};
fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type isn't directory, return path not found. */

View file

@ -22,7 +22,7 @@ namespace ams::powctl {
namespace {
impl::SessionImpl &GetOpenSessionImpl(Session &session) {
/* AMS_ASSERT(session.has_session); */
AMS_ASSERT(session.has_session);
auto &impl = GetReference(session.impl_storage);
AMS_ASSERT(impl.IsOpen());
return impl;

View file

@ -22,7 +22,7 @@ namespace ams::powctl {
namespace {
impl::SessionImpl &GetOpenSessionImpl(Session &session) {
/* AMS_ASSERT(session.has_session); */
AMS_ASSERT(session.has_session);
auto &impl = GetReference(session.impl_storage);
AMS_ASSERT(impl.IsOpen());
return impl;

View file

@ -19,7 +19,7 @@
namespace ams {
constexpr inline size_t DefaultAlignment = /*alignof(max_align_t)*/ 0x8;
constexpr inline size_t DefaultAlignment = alignof(max_align_t);
using AllocateFunction = void *(*)(size_t);
using AllocateFunctionWithUserData = void *(*)(size_t, void *);

View file

@ -30,7 +30,6 @@
#include <vapours/crypto/crypto_aes_ctr_encryptor_decryptor.hpp>
#include <vapours/crypto/crypto_aes_xts_encryptor_decryptor.hpp>
#include <vapours/crypto/crypto_aes_gcm_encryptor.hpp>
#include <vapours/crypto/crypto_aes_128_cmac_generator.hpp>
#include <vapours/crypto/crypto_rsa_pkcs1_sha256_verifier.hpp>
#include <vapours/crypto/crypto_rsa_pss_sha256_verifier.hpp>
#include <vapours/crypto/crypto_rsa_oaep_sha256_decoder.hpp>

View file

@ -1,61 +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/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/crypto_aes_encryptor.hpp>
#include <vapours/crypto/crypto_cmac_generator.hpp>
namespace ams::crypto {
class Aes128CmacGenerator {
NON_COPYABLE(Aes128CmacGenerator);
NON_MOVEABLE(Aes128CmacGenerator);
public:
static constexpr size_t MacSize = AesEncryptor128::BlockSize;
private:
AesEncryptor128 m_aes;
CmacGenerator<AesEncryptor128> m_cmac_generator;
public:
Aes128CmacGenerator() { /* ... */ }
void Initialize(const void *key, size_t key_size) {
AMS_ASSERT(key_size == AesEncryptor128::KeySize);
m_aes.Initialize(key, key_size);
m_cmac_generator.Initialize(std::addressof(m_aes));
}
void Update(const void *data, size_t size) {
m_cmac_generator.Update(data, size);
}
void GetMac(void *dst, size_t size) {
m_cmac_generator.GetMac(dst, size);
}
};
ALWAYS_INLINE void GenerateAes128Cmac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
Aes128CmacGenerator cmac_generator;
cmac_generator.Initialize(key, key_size);
cmac_generator.Update(data, data_size);
cmac_generator.GetMac(dst, dst_size);
}
}

View file

@ -1,51 +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/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_cmac_impl.hpp>
namespace ams::crypto {
template<typename BlockCipher>
class CmacGenerator {
NON_COPYABLE(CmacGenerator);
NON_MOVEABLE(CmacGenerator);
private:
using Impl = impl::CmacImpl<BlockCipher>;
public:
static constexpr size_t MacSize = BlockCipher::BlockSize;
private:
Impl m_impl;
public:
CmacGenerator() { /* ... */ }
void Initialize(const BlockCipher *cipher) {
return m_impl.Initialize(cipher);
}
void Update(const void *data, size_t size) {
return m_impl.Update(data, size);
}
void GetMac(void *dst, size_t dst_size) {
return m_impl.GetMac(dst, dst_size);
}
};
}

View file

@ -1,128 +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/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_hash_function.hpp>
#include <vapours/crypto/impl/crypto_cbc_mac_impl.hpp>
#include <vapours/crypto/crypto_memory_clear.hpp>
namespace ams::crypto::impl {
template<typename BlockCipher>
class CmacImpl {
NON_COPYABLE(CmacImpl);
NON_MOVEABLE(CmacImpl);
public:
static constexpr size_t BlockSize = BlockCipher::BlockSize;
static constexpr size_t MacSize = BlockSize;
static_assert(BlockSize == 0x10); /* TODO: Should this be supported? */
private:
enum State {
State_None = 0,
State_Initialized = 1,
State_Done = 2,
};
private:
CbcMacImpl m_cbc_mac_impl;
u8 m_sub_key[BlockSize];
State m_state;
public:
CmacImpl() : m_state(State_None) { /* ... */ }
~CmacImpl() {
/* Clear everything. */
ClearMemory(this, sizeof(*this));
}
void Initialize(const BlockCipher *cipher);
void Update(const void *data, size_t data_size);
void GetMac(void *dst, size_t dst_size);
private:
static void MultiplyOneOverGF128(u8 *data) {
/* Determine the carry bit. */
const u8 carry = data[0] & 0x80;
/* Shift all bytes by one bit. */
for (size_t i = 0; i < BlockSize - 1; ++i) {
data[i] = (data[i] << 1) | (data[i + 1] >> 7);
}
data[BlockSize - 1] <<= 1;
/* Adjust based on carry. */
if (carry) {
data[BlockSize - 1] ^= 0x87;
}
}
};
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::Initialize(const BlockCipher *cipher) {
/* Clear the key storage. */
std::memset(m_sub_key, 0, sizeof(m_sub_key));
/* Set the key storage. */
cipher->EncryptBlock(m_sub_key, BlockSize, m_sub_key, BlockSize);
MultiplyOneOverGF128(m_sub_key);
/* Initialize the cbc-mac impl. */
m_cbc_mac_impl.Initialize(cipher);
/* Mark initialized. */
m_state = State_Initialized;
}
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::Update(const void *data, size_t data_size) {
AMS_ASSERT(m_state == State_Initialized);
m_cbc_mac_impl.template Update<BlockCipher>(data, data_size);
}
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::GetMac(void *dst, size_t dst_size) {
AMS_ASSERT(m_state == State_Initialized || m_state == State_Done);
AMS_ASSERT(dst_size >= MacSize);
AMS_UNUSED(dst_size);
/* If we're not already finalized, get the final mac. */
if (m_state == State_Initialized) {
/* Process padding as needed. */
if (m_cbc_mac_impl.GetBufferedDataSize() != BlockSize) {
/* Determine the remaining size. */
const size_t remaining = BlockSize - m_cbc_mac_impl.GetBufferedDataSize();
/* Update with padding. */
static constexpr u8 s_padding[BlockSize] = { 0x80, /* ... */ };
m_cbc_mac_impl.template Update<BlockCipher>(s_padding, remaining);
/* Update our subkey. */
MultiplyOneOverGF128(m_sub_key);
}
/* Mask the subkey. */
m_cbc_mac_impl.MaskBufferedData(m_sub_key, BlockSize);
/* Set our state as done. */
m_state = State_Done;
}
/* Get the mac. */
m_cbc_mac_impl.GetMac(dst, dst_size);
}
}

View file

@ -49,7 +49,7 @@ namespace ams::kern::init::loader {
constinit void *g_final_state[2];
void RelocateKernelPhysically(uintptr_t &base_address, KernelLayout *&layout, const uintptr_t &ini_base_address) {
void RelocateKernelPhysically(uintptr_t &base_address, KernelLayout *&layout) {
/* Adjust layout to be correct. */
{
const ptrdiff_t layout_offset = reinterpret_cast<uintptr_t>(layout) - base_address;
@ -74,12 +74,6 @@ namespace ams::kern::init::loader {
const uintptr_t diff = GetInteger(correct_base) - base_address;
const size_t size = layout->rw_end_offset;
/* Check that the new kernel doesn't overlap with us. */
MESOSPHERE_INIT_ABORT_UNLESS((GetInteger(correct_base) >= reinterpret_cast<uintptr_t>(__bin_end__)) || (GetInteger(correct_base) + size <= reinterpret_cast<uintptr_t>(__bin_start__)));
/* Check that the new kernel doesn't overlap with the initial process binary. */
MESOSPHERE_INIT_ABORT_UNLESS((ini_base_address + InitialProcessBinarySizeMax <= GetInteger(correct_base)) || (GetInteger(correct_base) + size <= ini_base_address));
/* Conversion from KPhysicalAddress to void * is safe here, because MMU is not set up yet. */
std::memmove(reinterpret_cast<void *>(GetInteger(correct_base)), reinterpret_cast<void *>(base_address), size);
base_address += diff;
@ -96,11 +90,11 @@ namespace ams::kern::init::loader {
constexpr PageTableEntry KernelLdrRWXIdentityAttribute(PageTableEntry::Permission_KernelRWX, PageTableEntry::PageAttribute_NormalMemory, PageTableEntry::Shareable_InnerShareable, PageTableEntry::MappingFlag_Mapped);
const uintptr_t kernel_ldr_base = util::AlignDown(reinterpret_cast<uintptr_t>(__bin_start__), PageSize);
const uintptr_t kernel_ldr_size = util::AlignUp(reinterpret_cast<uintptr_t>(__bin_end__), PageSize) - kernel_ldr_base;
init_pt.Map(kernel_ldr_base, kernel_ldr_size, kernel_ldr_base, KernelLdrRWXIdentityAttribute, allocator, 0);
init_pt.Map(kernel_ldr_base, kernel_ldr_size, kernel_ldr_base, KernelRWXIdentityAttribute, allocator, 0);
/* Map in the page table region as RW- for ourselves. */
constexpr PageTableEntry PageTableRegionRWAttribute(PageTableEntry::Permission_KernelRW, PageTableEntry::PageAttribute_NormalMemory, PageTableEntry::Shareable_InnerShareable, PageTableEntry::MappingFlag_Mapped);
init_pt.Map(page_table_region, page_table_region_size, page_table_region, PageTableRegionRWAttribute, allocator, 0);
init_pt.Map(page_table_region, page_table_region_size, page_table_region, KernelRWXIdentityAttribute, allocator, 0);
/* Place the L1 table addresses in the relevant system registers. */
cpu::SetTtbr0El1(init_pt.GetTtbr0L1TableAddress());
@ -171,7 +165,7 @@ namespace ams::kern::init::loader {
uintptr_t Main(uintptr_t base_address, KernelLayout *layout, uintptr_t ini_base_address) {
/* Relocate the kernel to the correct physical base address. */
/* Base address and layout are passed by reference and modified. */
RelocateKernelPhysically(base_address, layout, ini_base_address);
RelocateKernelPhysically(base_address, layout);
/* Validate kernel layout. */
const uintptr_t rx_offset = layout->rx_offset;
@ -235,9 +229,6 @@ namespace ams::kern::init::loader {
/* Setup initial identity mapping. TTBR1 table passed by reference. */
SetupInitialIdentityMapping(init_pt, base_address, bss_end_offset, resource_end_address, InitialPageTableRegionSizeMax, g_initial_page_allocator, reinterpret_cast<KernelSystemRegisters *>(base_address + sysreg_offset));
/* NOTE: On 19.0.0+, Nintendo calls an unknown function here on init_pt and g_initial_page_allocator. */
/* This is stubbed in prod KernelLdr. */
/* Generate a random slide for the kernel's base address. */
const KVirtualAddress virtual_base_address = GetRandomKernelBaseAddress(init_pt, base_address, bss_end_offset);

View file

@ -108,8 +108,6 @@ namespace ams::dmnt::cheat::impl {
this->LogToDebugFile("Bit Width: %x\n", opcode->begin_cond.bit_width);
this->LogToDebugFile("Mem Type: %x\n", opcode->begin_cond.mem_type);
this->LogToDebugFile("Cond Type: %x\n", opcode->begin_cond.cond_type);
this->LogToDebugFile("Inc Ofs reg: %d\n", opcode->begin_cond.include_ofs_reg);
this->LogToDebugFile("Ofs Reg Idx: %x\n", opcode->begin_cond.ofs_reg_index);
this->LogToDebugFile("Rel Addr: %lx\n", opcode->begin_cond.rel_address);
this->LogToDebugFile("Value: %lx\n", opcode->begin_cond.value.bit64);
break;
@ -160,11 +158,6 @@ namespace ams::dmnt::cheat::impl {
this->LogToDebugFile("Opcode: Begin Keypress Conditional\n");
this->LogToDebugFile("Key Mask: %x\n", opcode->begin_keypress_cond.key_mask);
break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
this->LogToDebugFile("Opcode: Begin Extended Keypress Conditional\n");
this->LogToDebugFile("Key Mask: %x\n", opcode->begin_ext_keypress_cond.key_mask);
this->LogToDebugFile("Auto Repeat: %d\n", opcode->begin_ext_keypress_cond.auto_repeat);
break;
case CheatVmOpcodeType_PerformArithmeticRegister:
this->LogToDebugFile("Opcode: Perform Register Arithmetic\n");
this->LogToDebugFile("Bit Width: %x\n", opcode->perform_math_reg.bit_width);
@ -365,7 +358,6 @@ namespace ams::dmnt::cheat::impl {
switch (opcode.opcode) {
case CheatVmOpcodeType_BeginConditionalBlock:
case CheatVmOpcodeType_BeginKeypressConditionalBlock:
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
case CheatVmOpcodeType_BeginRegisterConditionalBlock:
opcode.begin_conditional_block = true;
break;
@ -395,8 +387,6 @@ namespace ams::dmnt::cheat::impl {
opcode.begin_cond.bit_width = (first_dword >> 24) & 0xF;
opcode.begin_cond.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF);
opcode.begin_cond.cond_type = (ConditionalComparisonType)((first_dword >> 16) & 0xF);
opcode.begin_cond.include_ofs_reg = ((first_dword >> 12) & 0xF) != 0;
opcode.begin_cond.ofs_reg_index = ((first_dword >> 8) & 0xF);
opcode.begin_cond.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
opcode.begin_cond.value = GetNextVmInt(opcode.begin_cond.bit_width);
}
@ -437,8 +427,7 @@ namespace ams::dmnt::cheat::impl {
opcode.ldr_memory.bit_width = (first_dword >> 24) & 0xF;
opcode.ldr_memory.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF);
opcode.ldr_memory.reg_index = ((first_dword >> 16) & 0xF);
opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF);
opcode.ldr_memory.offset_register = ((first_dword >> 8) & 0xF);
opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) != 0;
opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
}
break;
@ -471,14 +460,6 @@ namespace ams::dmnt::cheat::impl {
opcode.begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF;
}
break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
{
/* C4r00000 kkkkkkkk kkkkkkkk */
/* Read additional words. */
opcode.begin_ext_keypress_cond.key_mask = (u64)GetNextDword() << 32ul | (u64)GetNextDword();
opcode.begin_ext_keypress_cond.auto_repeat = ((first_dword >> 20) & 0xF) != 0;
}
break;
case CheatVmOpcodeType_PerformArithmeticRegister:
{
/* 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) */
@ -753,8 +734,6 @@ namespace ams::dmnt::cheat::impl {
return metadata->alias_extents.base + rel_address;
case MemoryAccessType_Aslr:
return metadata->aslr_extents.base + rel_address;
case MemoryAccessType_NonRelative:
return rel_address;
}
}
@ -790,7 +769,6 @@ namespace ams::dmnt::cheat::impl {
return true;
}
static u64 s_keyold = 0;
void CheatVirtualMachine::Execute(const CheatProcessMetadata *metadata) {
CheatVmOpcode cur_opcode;
u64 kHeld = 0;
@ -846,7 +824,7 @@ namespace ams::dmnt::cheat::impl {
case CheatVmOpcodeType_BeginConditionalBlock:
{
/* Read value from memory. */
u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, (cur_opcode.begin_cond.include_ofs_reg) ? m_registers[cur_opcode.begin_cond.ofs_reg_index] + cur_opcode.begin_cond.rel_address : cur_opcode.begin_cond.rel_address);
u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, cur_opcode.begin_cond.rel_address);
u64 src_value = 0;
switch (cur_opcode.store_static.bit_width) {
case 1:
@ -918,12 +896,8 @@ namespace ams::dmnt::cheat::impl {
{
/* Choose source address. */
u64 src_address;
if (cur_opcode.ldr_memory.load_from_reg == 1) {
if (cur_opcode.ldr_memory.load_from_reg) {
src_address = m_registers[cur_opcode.ldr_memory.reg_index] + cur_opcode.ldr_memory.rel_address;
} else if (cur_opcode.ldr_memory.load_from_reg == 2) {
src_address = m_registers[cur_opcode.ldr_memory.offset_register] + cur_opcode.ldr_memory.rel_address;
} else if (cur_opcode.ldr_memory.load_from_reg == 3) {
src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, m_registers[cur_opcode.ldr_memory.offset_register] + cur_opcode.ldr_memory.rel_address);
} else {
src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, cur_opcode.ldr_memory.rel_address);
}
@ -1008,18 +982,6 @@ namespace ams::dmnt::cheat::impl {
this->SkipConditionalBlock(true);
}
break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
/* Check for keypress. */
if (!cur_opcode.begin_ext_keypress_cond.auto_repeat) {
if ((cur_opcode.begin_ext_keypress_cond.key_mask & kHeld) != (cur_opcode.begin_ext_keypress_cond.key_mask) || (cur_opcode.begin_ext_keypress_cond.key_mask & s_keyold) == (cur_opcode.begin_ext_keypress_cond.key_mask)) {
/* Keys not pressed. Skip conditional block. */
this->SkipConditionalBlock(true);
}
} else if ((cur_opcode.begin_ext_keypress_cond.key_mask & kHeld) != cur_opcode.begin_ext_keypress_cond.key_mask) {
/* Keys not pressed. Skip conditional block. */
this->SkipConditionalBlock(true);
}
break;
case CheatVmOpcodeType_PerformArithmeticRegister:
{
const u64 operand_1_value = m_registers[cur_opcode.perform_math_reg.src_reg_1_index];
@ -1060,34 +1022,6 @@ namespace ams::dmnt::cheat::impl {
case RegisterArithmeticType_None:
res_val = operand_1_value;
break;
case RegisterArithmeticType_FloatAddition:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) + std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) + std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatSubtraction:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) - std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) - std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatMultiplication:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) * std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) * std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatDivision:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) / std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) / std::bit_cast<double>(operand_2_value));
}
break;
}
@ -1370,7 +1304,6 @@ namespace ams::dmnt::cheat::impl {
break;
}
}
s_keyold = kHeld;
}
}

View file

@ -43,7 +43,6 @@ namespace ams::dmnt::cheat::impl {
CheatVmOpcodeType_SaveRestoreRegister = 0xC1,
CheatVmOpcodeType_SaveRestoreRegisterMask = 0xC2,
CheatVmOpcodeType_ReadWriteStaticRegister = 0xC3,
CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock = 0xC4,
/* This is a meta entry, and not a real opcode. */
/* This is to facilitate multi-nybble instruction decoding. */
@ -60,7 +59,6 @@ namespace ams::dmnt::cheat::impl {
MemoryAccessType_Heap = 1,
MemoryAccessType_Alias = 2,
MemoryAccessType_Aslr = 3,
MemoryAccessType_NonRelative = 4,
};
enum ConditionalComparisonType : u32 {
@ -86,10 +84,6 @@ namespace ams::dmnt::cheat::impl {
RegisterArithmeticType_LogicalXor = 8,
RegisterArithmeticType_None = 9,
RegisterArithmeticType_FloatAddition = 10,
RegisterArithmeticType_FloatSubtraction = 11,
RegisterArithmeticType_FloatMultiplication = 12,
RegisterArithmeticType_FloatDivision = 13,
};
enum StoreRegisterOffsetType : u32 {
@ -144,8 +138,6 @@ namespace ams::dmnt::cheat::impl {
u32 bit_width;
MemoryAccessType mem_type;
ConditionalComparisonType cond_type;
bool include_ofs_reg;
u32 ofs_reg_index;
u64 rel_address;
VmInt value;
};
@ -169,8 +161,7 @@ namespace ams::dmnt::cheat::impl {
u32 bit_width;
MemoryAccessType mem_type;
u32 reg_index;
u8 load_from_reg;
u8 offset_register;
bool load_from_reg;
u64 rel_address;
};
@ -194,11 +185,6 @@ namespace ams::dmnt::cheat::impl {
u32 key_mask;
};
struct BeginExtendedKeypressConditionalOpcode {
u64 key_mask;
bool auto_repeat;
};
struct PerformArithmeticRegisterOpcode {
u32 bit_width;
RegisterArithmeticType math_type;
@ -273,7 +259,6 @@ namespace ams::dmnt::cheat::impl {
StoreStaticToAddressOpcode str_static;
PerformArithmeticStaticOpcode perform_math_static;
BeginKeypressConditionalOpcode begin_keypress_cond;
BeginExtendedKeypressConditionalOpcode begin_ext_keypress_cond;
PerformArithmeticRegisterOpcode perform_math_reg;
StoreRegisterToAddressOpcode str_register;
BeginRegisterConditionalOpcode begin_reg_cond;

View file

@ -25,11 +25,11 @@ namespace ams::ldr {
}
/* ScopedCodeMount functionality. */
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform 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) {
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, ncm::ContentMetaPlatform 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) {
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);
}
@ -46,7 +46,7 @@ namespace ams::ldr {
}
}
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) {
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, PlatformId platform) {
/* Capture override status, if necessary. */
this->EnsureOverrideStatus(loc);
AMS_ABORT_UNLESS(m_has_status);
@ -83,7 +83,7 @@ namespace ams::ldr {
}
/* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) {
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);
@ -166,9 +166,9 @@ namespace ams::ldr {
R_SUCCEED();
}
fs::ContentAttributes GetPlatformContentAttributes(ncm::ContentMetaPlatform platform) {
fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform) {
switch (platform) {
case ncm::ContentMetaPlatform::Nx:
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, ncm::ContentMetaPlatform platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, ncm::ContentMetaPlatform platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, PlatformId platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, PlatformId platform);
~ScopedCodeMount();
Result GetResult() const {
@ -59,7 +59,7 @@ namespace ams::ldr {
return m_base_code_verification_data;
}
private:
Result Initialize(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform);
Result Initialize(const ncm::ProgramLocation &loc, PlatformId platform);
void EnsureOverrideStatus(const ncm::ProgramLocation &loc);
};
@ -76,10 +76,10 @@ namespace ams::ldr {
#define ENCODE_CMPT_PATH(relative) "cmpt:" relative
/* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform);
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(ncm::ContentMetaPlatform platform);
fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform);
}

View file

@ -27,11 +27,11 @@ namespace ams::ldr {
constinit ArgumentStore g_argument_store;
bool IsValidPlatform(ncm::ContentMetaPlatform platform) {
return platform == ncm::ContentMetaPlatform::Nx;
bool IsValidPlatform(PlatformId platform) {
return platform == PlatformId_Nx;
}
Result CreateProcessByPlatform(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit, ncm::ContentMetaPlatform platform) {
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());
@ -49,7 +49,7 @@ namespace ams::ldr {
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, ncm::ContentMetaPlatform 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());
@ -88,11 +88,11 @@ namespace ams::ldr {
Result LoaderService::CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit) {
R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, ncm::ContentMetaPlatform::Nx));
R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, PlatformId_Nx));
}
Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, ncm::ContentMetaPlatform::Nx));
R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, PlatformId_Nx));
}
Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {

View file

@ -103,15 +103,15 @@ namespace ams::ldr {
R_SUCCEED();
}
const u8 *GetAcidSignatureModulus(ncm::ContentMetaPlatform platform, u8 key_generation, bool unk_unused) {
const u8 *GetAcidSignatureModulus(PlatformId platform, u8 key_generation, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused);
}
size_t GetAcidSignatureModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused) {
size_t GetAcidSignatureModulusSize(PlatformId platform, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused);
}
Result ValidateAcidSignature(Meta *meta, ncm::ContentMetaPlatform platform, bool 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;
@ -190,7 +190,7 @@ namespace ams::ldr {
}
/* API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
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 = {};
@ -282,7 +282,7 @@ namespace ams::ldr {
R_SUCCEED();
}
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
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, platform, false));
}

View file

@ -36,8 +36,8 @@ namespace ams::ldr {
};
/* Meta API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused);
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform);
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

@ -664,7 +664,7 @@ 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, ncm::ContentMetaPlatform 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, PlatformId platform) {
/* Mount code. */
AMS_UNUSED(path);
ScopedCodeMount mount(loc, override_status, platform);
@ -720,7 +720,7 @@ namespace ams::ldr {
R_SUCCEED();
}
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, ncm::ContentMetaPlatform platform) {
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform) {
Meta meta;
/* Load Meta. */

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, ncm::ContentMetaPlatform platform);
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, ncm::ContentMetaPlatform 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, 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);