mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-02-05 15:02:49 +00:00
Compare commits
No commits in common. "197ffa1dbc58b7ee41ef65a219ee94fa0e50707d" and "5c6362c56df47a5cc893bc03f117815047ab92d3" have entirely different histories.
197ffa1dbc
...
5c6362c56d
18 changed files with 239 additions and 289 deletions
|
@ -170,17 +170,9 @@ namespace ams::kern::arch::arm64 {
|
||||||
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetTestTableMask() const { return (m_attributes & ExtensionFlag_TestTableMask); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (m_attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
constexpr ALWAYS_INLINE bool IsBlock() const { return (m_attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
||||||
constexpr ALWAYS_INLINE bool IsPage() const { return (m_attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_TestTableMask; }
|
|
||||||
constexpr ALWAYS_INLINE bool IsTable() const { return (m_attributes & ExtensionFlag_TestTableMask) == 2; }
|
constexpr ALWAYS_INLINE bool IsTable() const { return (m_attributes & ExtensionFlag_TestTableMask) == 2; }
|
||||||
constexpr ALWAYS_INLINE bool IsEmpty() const { return (m_attributes & ExtensionFlag_TestTableMask) == 0; }
|
constexpr ALWAYS_INLINE bool IsEmpty() const { return (m_attributes & ExtensionFlag_TestTableMask) == 0; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE KPhysicalAddress GetTable() const { return this->SelectBits(12, 36); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsMappedTable() const { return this->GetBits(0, 2) == 3; }
|
|
||||||
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 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; }
|
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
||||||
|
@ -204,13 +196,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
return (m_attributes & BaseMaskForMerge) == attr;
|
return (m_attributes & BaseMaskForMerge) == attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafe() const {
|
|
||||||
return m_attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
||||||
return m_attributes;
|
return m_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
||||||
return m_attributes;
|
return m_attributes;
|
||||||
|
|
|
@ -37,17 +37,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
constexpr bool IsTailMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
constexpr bool IsTailMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EntryLevel : u32 {
|
|
||||||
EntryLevel_L3 = 0,
|
|
||||||
EntryLevel_L2 = 1,
|
|
||||||
EntryLevel_L1 = 2,
|
|
||||||
EntryLevel_Count = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TraversalContext {
|
struct TraversalContext {
|
||||||
const PageTableEntry *level_entries[EntryLevel_Count];
|
const L1PageTableEntry *l1_entry;
|
||||||
EntryLevel level;
|
const L2PageTableEntry *l2_entry;
|
||||||
bool is_contiguous;
|
const L3PageTableEntry *l3_entry;
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
static constexpr size_t PageBits = util::CountTrailingZeros(PageSize);
|
static constexpr size_t PageBits = util::CountTrailingZeros(PageSize);
|
||||||
|
@ -60,26 +53,16 @@ namespace ams::kern::arch::arm64 {
|
||||||
return (value >> Offset) & ((1ul << Count) - 1);
|
return (value >> Offset) & ((1ul << Count) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE u64 GetBits(u64 value, size_t offset, size_t count) {
|
|
||||||
return (value >> offset) & ((1ul << count) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t Offset, size_t Count>
|
template<size_t Offset, size_t Count>
|
||||||
static constexpr ALWAYS_INLINE u64 SelectBits(u64 value) {
|
constexpr ALWAYS_INLINE u64 SelectBits(u64 value) {
|
||||||
return value & (((1ul << Count) - 1) << Offset);
|
return value & (((1ul << Count) - 1) << Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE u64 SelectBits(u64 value, size_t offset, size_t count) {
|
|
||||||
return value & (((1ul << count) - 1) << offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL0Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 0), LevelBits>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL0Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 0), LevelBits>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL1Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 1), LevelBits>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL1Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 1), LevelBits>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL2Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 2), LevelBits>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL2Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 2), LevelBits>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL3Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 3), LevelBits>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL3Index(KProcessAddress addr) { return GetBits<PageBits + LevelBits * (NumLevels - 3), LevelBits>(GetInteger(addr)); }
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetLevelIndex(KProcessAddress addr, EntryLevel level) { return GetBits(GetInteger(addr), PageBits + LevelBits * level, LevelBits); }
|
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL1Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 1)>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL1Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 1)>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL2Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 2)>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL2Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 2)>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetL3Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 3)>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetL3Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 3)>(GetInteger(addr)); }
|
||||||
|
@ -87,16 +70,13 @@ namespace ams::kern::arch::arm64 {
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetContiguousL2Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 2) + 4>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetContiguousL2Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 2) + 4>(GetInteger(addr)); }
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetContiguousL3Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 3) + 4>(GetInteger(addr)); }
|
static constexpr ALWAYS_INLINE uintptr_t GetContiguousL3Offset(KProcessAddress addr) { return GetBits<0, PageBits + LevelBits * (NumLevels - 3) + 4>(GetInteger(addr)); }
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetBlock(const PageTableEntry *pte, EntryLevel level) { return SelectBits(pte->GetRawAttributesUnsafe(), PageBits + LevelBits * level, LevelBits * (NumLevels + 1 - level)); }
|
|
||||||
static constexpr ALWAYS_INLINE uintptr_t GetOffset(KProcessAddress addr, EntryLevel level) { return GetBits(GetInteger(addr), 0, PageBits + LevelBits * level); }
|
|
||||||
|
|
||||||
static ALWAYS_INLINE KVirtualAddress GetPageTableVirtualAddress(KPhysicalAddress addr) {
|
static ALWAYS_INLINE KVirtualAddress GetPageTableVirtualAddress(KPhysicalAddress addr) {
|
||||||
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ALWAYS_INLINE bool ExtractL1Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L1PageTableEntry *l1_entry, KProcessAddress virt_addr) const;
|
ALWAYS_INLINE bool ExtractL1Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L1PageTableEntry *l1_entry, KProcessAddress virt_addr) const;
|
||||||
//ALWAYS_INLINE bool ExtractL2Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L2PageTableEntry *l2_entry, KProcessAddress virt_addr) const;
|
ALWAYS_INLINE bool ExtractL2Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L2PageTableEntry *l2_entry, KProcessAddress virt_addr) const;
|
||||||
//ALWAYS_INLINE bool ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const;
|
ALWAYS_INLINE bool ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const;
|
||||||
private:
|
private:
|
||||||
L1PageTableEntry *m_table;
|
L1PageTableEntry *m_table;
|
||||||
bool m_is_kernel;
|
bool m_is_kernel;
|
||||||
|
|
|
@ -33,98 +33,103 @@ namespace ams::kern::arch::arm64 {
|
||||||
return m_table;
|
return m_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool KPageTableImpl::ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const {
|
bool KPageTableImpl::ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const {
|
||||||
// /* Set the L3 entry. */
|
/* Set the L3 entry. */
|
||||||
// out_context->l3_entry = l3_entry;
|
out_context->l3_entry = l3_entry;
|
||||||
//
|
|
||||||
// if (l3_entry->IsBlock()) {
|
if (l3_entry->IsBlock()) {
|
||||||
// /* Set the output entry. */
|
/* Set the output entry. */
|
||||||
// out_entry->phys_addr = l3_entry->GetBlock() + (virt_addr & (L3BlockSize - 1));
|
out_entry->phys_addr = l3_entry->GetBlock() + (virt_addr & (L3BlockSize - 1));
|
||||||
// if (l3_entry->IsContiguous()) {
|
if (l3_entry->IsContiguous()) {
|
||||||
// out_entry->block_size = L3ContiguousBlockSize;
|
out_entry->block_size = L3ContiguousBlockSize;
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->block_size = L3BlockSize;
|
out_entry->block_size = L3BlockSize;
|
||||||
// }
|
}
|
||||||
// out_entry->sw_reserved_bits = l3_entry->GetSoftwareReservedBits();
|
out_entry->sw_reserved_bits = l3_entry->GetSoftwareReservedBits();
|
||||||
// out_entry->attr = 0;
|
out_entry->attr = 0;
|
||||||
//
|
|
||||||
// return true;
|
return true;
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->phys_addr = Null<KPhysicalAddress>;
|
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||||
// out_entry->block_size = L3BlockSize;
|
out_entry->block_size = L3BlockSize;
|
||||||
// out_entry->sw_reserved_bits = 0;
|
out_entry->sw_reserved_bits = 0;
|
||||||
// out_entry->attr = 0;
|
out_entry->attr = 0;
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// bool KPageTableImpl::ExtractL2Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L2PageTableEntry *l2_entry, KProcessAddress virt_addr) const {
|
bool KPageTableImpl::ExtractL2Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L2PageTableEntry *l2_entry, KProcessAddress virt_addr) const {
|
||||||
// /* Set the L2 entry. */
|
/* Set the L2 entry. */
|
||||||
// out_context->l2_entry = l2_entry;
|
out_context->l2_entry = l2_entry;
|
||||||
//
|
|
||||||
// if (l2_entry->IsBlock()) {
|
if (l2_entry->IsBlock()) {
|
||||||
// /* Set the output entry. */
|
/* Set the output entry. */
|
||||||
// out_entry->phys_addr = l2_entry->GetBlock() + (virt_addr & (L2BlockSize - 1));
|
out_entry->phys_addr = l2_entry->GetBlock() + (virt_addr & (L2BlockSize - 1));
|
||||||
// if (l2_entry->IsContiguous()) {
|
if (l2_entry->IsContiguous()) {
|
||||||
// out_entry->block_size = L2ContiguousBlockSize;
|
out_entry->block_size = L2ContiguousBlockSize;
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->block_size = L2BlockSize;
|
out_entry->block_size = L2BlockSize;
|
||||||
// }
|
}
|
||||||
// out_entry->sw_reserved_bits = l2_entry->GetSoftwareReservedBits();
|
out_entry->sw_reserved_bits = l2_entry->GetSoftwareReservedBits();
|
||||||
// out_entry->attr = 0;
|
out_entry->attr = 0;
|
||||||
//
|
|
||||||
// /* Set the output context. */
|
/* Set the output context. */
|
||||||
// out_context->l3_entry = nullptr;
|
out_context->l3_entry = nullptr;
|
||||||
// return true;
|
return true;
|
||||||
// } else if (l2_entry->IsTable()) {
|
} else if (l2_entry->IsTable()) {
|
||||||
// return this->ExtractL3Entry(out_entry, out_context, this->GetL3EntryFromTable(GetPageTableVirtualAddress(l2_entry->GetTable()), virt_addr), virt_addr);
|
return this->ExtractL3Entry(out_entry, out_context, this->GetL3EntryFromTable(GetPageTableVirtualAddress(l2_entry->GetTable()), virt_addr), virt_addr);
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->phys_addr = Null<KPhysicalAddress>;
|
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||||
// out_entry->block_size = L2BlockSize;
|
out_entry->block_size = L2BlockSize;
|
||||||
// out_entry->sw_reserved_bits = 0;
|
out_entry->sw_reserved_bits = 0;
|
||||||
// out_entry->attr = 0;
|
out_entry->attr = 0;
|
||||||
//
|
|
||||||
// out_context->l3_entry = nullptr;
|
out_context->l3_entry = nullptr;
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// bool KPageTableImpl::ExtractL1Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L1PageTableEntry *l1_entry, KProcessAddress virt_addr) const {
|
bool KPageTableImpl::ExtractL1Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L1PageTableEntry *l1_entry, KProcessAddress virt_addr) const {
|
||||||
// /* Set the L1 entry. */
|
/* Set the L1 entry. */
|
||||||
// out_context->level_entries[EntryLevel_L1] = l1_entry;
|
out_context->l1_entry = l1_entry;
|
||||||
//
|
|
||||||
// if (l1_entry->IsBlock()) {
|
if (l1_entry->IsBlock()) {
|
||||||
// /* Set the output entry. */
|
/* Set the output entry. */
|
||||||
// out_entry->phys_addr = l1_entry->GetBlock() + (virt_addr & (L1BlockSize - 1));
|
out_entry->phys_addr = l1_entry->GetBlock() + (virt_addr & (L1BlockSize - 1));
|
||||||
// if (l1_entry->IsContiguous()) {
|
if (l1_entry->IsContiguous()) {
|
||||||
// out_entry->block_size = L1ContiguousBlockSize;
|
out_entry->block_size = L1ContiguousBlockSize;
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->block_size = L1BlockSize;
|
out_entry->block_size = L1BlockSize;
|
||||||
// }
|
}
|
||||||
// out_entry->sw_reserved_bits = l1_entry->GetSoftwareReservedBits();
|
out_entry->sw_reserved_bits = l1_entry->GetSoftwareReservedBits();
|
||||||
//
|
|
||||||
// /* Set the output context. */
|
/* Set the output context. */
|
||||||
// out_context->l2_entry = nullptr;
|
out_context->l2_entry = nullptr;
|
||||||
// out_context->l3_entry = nullptr;
|
out_context->l3_entry = nullptr;
|
||||||
// return true;
|
return true;
|
||||||
// } else if (l1_entry->IsTable()) {
|
} else if (l1_entry->IsTable()) {
|
||||||
// return this->ExtractL2Entry(out_entry, out_context, this->GetL2EntryFromTable(GetPageTableVirtualAddress(l1_entry->GetTable()), virt_addr), virt_addr);
|
return this->ExtractL2Entry(out_entry, out_context, this->GetL2EntryFromTable(GetPageTableVirtualAddress(l1_entry->GetTable()), virt_addr), virt_addr);
|
||||||
// } else {
|
} else {
|
||||||
// out_entry->phys_addr = Null<KPhysicalAddress>;
|
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||||
// out_entry->block_size = L1BlockSize;
|
out_entry->block_size = L1BlockSize;
|
||||||
// out_entry->sw_reserved_bits = 0;
|
out_entry->sw_reserved_bits = 0;
|
||||||
// out_entry->attr = 0;
|
out_entry->attr = 0;
|
||||||
//
|
|
||||||
// out_context->l2_entry = nullptr;
|
out_context->l2_entry = nullptr;
|
||||||
// out_context->l3_entry = nullptr;
|
out_context->l3_entry = nullptr;
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
bool KPageTableImpl::BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const {
|
bool KPageTableImpl::BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const {
|
||||||
/* Setup invalid defaults. */
|
/* Setup invalid defaults. */
|
||||||
*out_entry = {};
|
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||||
*out_context = {};
|
out_entry->block_size = L1BlockSize;
|
||||||
|
out_entry->sw_reserved_bits = 0;
|
||||||
|
out_entry->attr = 0;
|
||||||
|
out_context->l1_entry = m_table + m_num_entries;
|
||||||
|
out_context->l2_entry = nullptr;
|
||||||
|
out_context->l3_entry = nullptr;
|
||||||
|
|
||||||
/* Validate that we can read the actual entry. */
|
/* Validate that we can read the actual entry. */
|
||||||
const size_t l0_index = GetL0Index(address);
|
const size_t l0_index = GetL0Index(address);
|
||||||
|
@ -141,79 +146,125 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the L1 entry, and check if it's a table. */
|
/* Extract the entry. */
|
||||||
out_context->level_entries[EntryLevel_L1] = this->GetL1Entry(address);
|
const bool valid = this->ExtractL1Entry(out_entry, out_context, this->GetL1Entry(address), address);
|
||||||
if (out_context->level_entries[EntryLevel_L1]->IsMappedTable()) {
|
|
||||||
/* Get the L2 entry, and check if it's a table. */
|
|
||||||
out_context->level_entries[EntryLevel_L2] = this->GetL2EntryFromTable(GetPageTableVirtualAddress(out_context->level_entries[EntryLevel_L1]->GetTable()), address);
|
|
||||||
if (out_context->level_entries[EntryLevel_L2]->IsMappedTable()) {
|
|
||||||
/* Get the L3 entry. */
|
|
||||||
out_context->level_entries[EntryLevel_L3] = this->GetL3EntryFromTable(GetPageTableVirtualAddress(out_context->level_entries[EntryLevel_L2]->GetTable()), address);
|
|
||||||
|
|
||||||
/* It's either a page or not. */
|
/* Update the context for next traversal. */
|
||||||
out_context->level = EntryLevel_L3;
|
switch (out_entry->block_size) {
|
||||||
} else {
|
case L1ContiguousBlockSize:
|
||||||
/* Not a L2 table, so possibly an L2 block. */
|
out_context->l1_entry += (L1ContiguousBlockSize / L1BlockSize) - GetContiguousL1Offset(address) / L1BlockSize;
|
||||||
out_context->level = EntryLevel_L2;
|
break;
|
||||||
}
|
case L1BlockSize:
|
||||||
} else {
|
out_context->l1_entry += 1;
|
||||||
/* Not a L1 table, so possibly an L1 block. */
|
break;
|
||||||
out_context->level = EntryLevel_L1;
|
case L2ContiguousBlockSize:
|
||||||
|
out_context->l1_entry += 1;
|
||||||
|
out_context->l2_entry += (L2ContiguousBlockSize / L2BlockSize) - GetContiguousL2Offset(address) / L2BlockSize;
|
||||||
|
break;
|
||||||
|
case L2BlockSize:
|
||||||
|
out_context->l1_entry += 1;
|
||||||
|
out_context->l2_entry += 1;
|
||||||
|
break;
|
||||||
|
case L3ContiguousBlockSize:
|
||||||
|
out_context->l1_entry += 1;
|
||||||
|
out_context->l2_entry += 1;
|
||||||
|
out_context->l3_entry += (L3ContiguousBlockSize / L3BlockSize) - GetContiguousL3Offset(address) / L3BlockSize;
|
||||||
|
break;
|
||||||
|
case L3BlockSize:
|
||||||
|
out_context->l1_entry += 1;
|
||||||
|
out_context->l2_entry += 1;
|
||||||
|
out_context->l3_entry += 1;
|
||||||
|
break;
|
||||||
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine other fields. */
|
return valid;
|
||||||
const auto *pte = out_context->level_entries[out_context->level];
|
|
||||||
|
|
||||||
out_context->is_contiguous = pte->IsContiguous();
|
|
||||||
|
|
||||||
out_entry->sw_reserved_bits = pte->GetSoftwareReservedBits();
|
|
||||||
out_entry->attr = 0;
|
|
||||||
out_entry->phys_addr = this->GetBlock(pte, out_context->level) + this->GetOffset(address, out_context->level);
|
|
||||||
out_entry->block_size = static_cast<size_t>(1) << (PageBits + LevelBits * out_context->level + 4 * out_context->is_contiguous);
|
|
||||||
|
|
||||||
return out_context->level == EntryLevel_L3 ? pte->IsPage() : pte->IsBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KPageTableImpl::ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const {
|
bool KPageTableImpl::ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const {
|
||||||
/* Advance entry. */
|
bool valid = false;
|
||||||
|
|
||||||
auto *cur_pte = context->level_entries[context->level];
|
/* Check if we're not at the end of an L3 table. */
|
||||||
auto *next_pte = reinterpret_cast<PageTableEntry *>(context->is_contiguous ? util::AlignDown(reinterpret_cast<uintptr_t>(cur_pte), 0x10 * sizeof(PageTableEntry)) + 0x10 * sizeof(PageTableEntry) : reinterpret_cast<uintptr_t>(cur_pte) + sizeof(PageTableEntry));
|
if (!util::IsAligned(reinterpret_cast<uintptr_t>(context->l3_entry), PageSize)) {
|
||||||
|
valid = this->ExtractL3Entry(out_entry, context, context->l3_entry, Null<KProcessAddress>);
|
||||||
|
|
||||||
/* Set the pte. */
|
switch (out_entry->block_size) {
|
||||||
context->level_entries[context->level] = next_pte;
|
case L3ContiguousBlockSize:
|
||||||
|
context->l3_entry += (L3ContiguousBlockSize / L3BlockSize);
|
||||||
|
break;
|
||||||
|
case L3BlockSize:
|
||||||
|
context->l3_entry += 1;
|
||||||
|
break;
|
||||||
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
} else if (!util::IsAligned(reinterpret_cast<uintptr_t>(context->l2_entry), PageSize)) {
|
||||||
|
/* We're not at the end of an L2 table. */
|
||||||
|
valid = this->ExtractL2Entry(out_entry, context, context->l2_entry, Null<KProcessAddress>);
|
||||||
|
|
||||||
/* Advance appropriately. */
|
switch (out_entry->block_size) {
|
||||||
while (context->level < EntryLevel_L1 && util::IsAligned(reinterpret_cast<uintptr_t>(context->level_entries[context->level]), PageSize)) {
|
case L2ContiguousBlockSize:
|
||||||
/* Advance the above table by one entry. */
|
context->l2_entry += (L2ContiguousBlockSize / L2BlockSize);
|
||||||
context->level_entries[context->level + 1]++;
|
break;
|
||||||
context->level = static_cast<EntryLevel>(util::ToUnderlying(context->level) + 1);
|
case L2BlockSize:
|
||||||
}
|
context->l2_entry += 1;
|
||||||
|
break;
|
||||||
/* Check if we've hit the end of the L1 table. */
|
case L3ContiguousBlockSize:
|
||||||
if (context->level == EntryLevel_L1) {
|
context->l2_entry += 1;
|
||||||
if (context->level_entries[EntryLevel_L1] - static_cast<const PageTableEntry *>(m_table) >= m_num_entries) {
|
context->l3_entry += (L3ContiguousBlockSize / L3BlockSize);
|
||||||
*context = {};
|
break;
|
||||||
*out_entry = {};
|
case L3BlockSize:
|
||||||
|
context->l2_entry += 1;
|
||||||
|
context->l3_entry += 1;
|
||||||
|
break;
|
||||||
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* We need to update the l1 entry. */
|
||||||
|
const size_t l1_index = context->l1_entry - m_table;
|
||||||
|
if (l1_index < m_num_entries) {
|
||||||
|
valid = this->ExtractL1Entry(out_entry, context, context->l1_entry, Null<KProcessAddress>);
|
||||||
|
} else {
|
||||||
|
/* Invalid, end traversal. */
|
||||||
|
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||||
|
out_entry->block_size = L1BlockSize;
|
||||||
|
out_entry->sw_reserved_bits = 0;
|
||||||
|
out_entry->attr = 0;
|
||||||
|
context->l1_entry = m_table + m_num_entries;
|
||||||
|
context->l2_entry = nullptr;
|
||||||
|
context->l3_entry = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (out_entry->block_size) {
|
||||||
|
case L1ContiguousBlockSize:
|
||||||
|
context->l1_entry += (L1ContiguousBlockSize / L1BlockSize);
|
||||||
|
break;
|
||||||
|
case L1BlockSize:
|
||||||
|
context->l1_entry += 1;
|
||||||
|
break;
|
||||||
|
case L2ContiguousBlockSize:
|
||||||
|
context->l1_entry += 1;
|
||||||
|
context->l2_entry += (L2ContiguousBlockSize / L2BlockSize);
|
||||||
|
break;
|
||||||
|
case L2BlockSize:
|
||||||
|
context->l1_entry += 1;
|
||||||
|
context->l2_entry += 1;
|
||||||
|
break;
|
||||||
|
case L3ContiguousBlockSize:
|
||||||
|
context->l1_entry += 1;
|
||||||
|
context->l2_entry += 1;
|
||||||
|
context->l3_entry += (L3ContiguousBlockSize / L3BlockSize);
|
||||||
|
break;
|
||||||
|
case L3BlockSize:
|
||||||
|
context->l1_entry += 1;
|
||||||
|
context->l2_entry += 1;
|
||||||
|
context->l3_entry += 1;
|
||||||
|
break;
|
||||||
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may have advanced to a new table, and if we have we should descend. */
|
return valid;
|
||||||
while (context->level > EntryLevel_L3 && context->level_entries[context->level]->IsMappedTable()) {
|
|
||||||
context->level_entries[context->level - 1] = GetPointer<PageTableEntry>(GetPageTableVirtualAddress(context->level_entries[context->level]->GetTable()));
|
|
||||||
context->level = static_cast<EntryLevel>(util::ToUnderlying(context->level) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto *pte = context->level_entries[context->level];
|
|
||||||
|
|
||||||
context->is_contiguous = pte->IsContiguous();
|
|
||||||
|
|
||||||
out_entry->sw_reserved_bits = pte->GetSoftwareReservedBits();
|
|
||||||
out_entry->attr = 0;
|
|
||||||
out_entry->phys_addr = this->GetBlock(pte, context->level);
|
|
||||||
out_entry->block_size = static_cast<size_t>(1) << (PageBits + LevelBits * context->level + 4 * context->is_contiguous);
|
|
||||||
return context->level == EntryLevel_L3 ? pte->IsPage() : pte->IsBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KPageTableImpl::GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
bool KPageTableImpl::GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||||
|
@ -232,27 +283,32 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the L1 entry, and check if it's a table. */
|
/* Try to get from l1 table. */
|
||||||
const PageTableEntry *pte = this->GetL1Entry(address);
|
const L1PageTableEntry *l1_entry = this->GetL1Entry(address);
|
||||||
EntryLevel level = EntryLevel_L1;
|
if (l1_entry->IsBlock()) {
|
||||||
if (pte->IsMappedTable()) {
|
*out = l1_entry->GetBlock() + GetL1Offset(address);
|
||||||
/* Get the L2 entry, and check if it's a table. */
|
return true;
|
||||||
pte = this->GetL2EntryFromTable(GetPageTableVirtualAddress(pte->GetTable()), address);
|
} else if (!l1_entry->IsTable()) {
|
||||||
level = EntryLevel_L2;
|
return false;
|
||||||
if (pte->IsMappedTable()) {
|
|
||||||
pte = this->GetL3EntryFromTable(GetPageTableVirtualAddress(pte->GetTable()), address);
|
|
||||||
level = EntryLevel_L3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_block = level == EntryLevel_L3 ? pte->IsPage() : pte->IsBlock();
|
/* Try to get from l2 table. */
|
||||||
if (is_block) {
|
const L2PageTableEntry *l2_entry = this->GetL2Entry(l1_entry, address);
|
||||||
*out = this->GetBlock(pte, level) + this->GetOffset(address, level);
|
if (l2_entry->IsBlock()) {
|
||||||
} else {
|
*out = l2_entry->GetBlock() + GetL2Offset(address);
|
||||||
*out = Null<KPhysicalAddress>;
|
return true;
|
||||||
|
} else if (!l2_entry->IsTable()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_block;
|
/* Try to get from l3 table. */
|
||||||
|
const L3PageTableEntry *l3_entry = this->GetL3Entry(l2_entry, address);
|
||||||
|
if (l3_entry->IsBlock()) {
|
||||||
|
*out = l3_entry->GetBlock() + GetL3Offset(address);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KPageTableImpl::Dump(uintptr_t start, size_t size) const {
|
void KPageTableImpl::Dump(uintptr_t start, size_t size) const {
|
||||||
|
|
|
@ -84,7 +84,6 @@ namespace ams::hos {
|
||||||
Version_17_0_1 = ::ams::TargetFirmware_17_0_1,
|
Version_17_0_1 = ::ams::TargetFirmware_17_0_1,
|
||||||
Version_18_0_0 = ::ams::TargetFirmware_18_0_0,
|
Version_18_0_0 = ::ams::TargetFirmware_18_0_0,
|
||||||
Version_18_1_0 = ::ams::TargetFirmware_18_1_0,
|
Version_18_1_0 = ::ams::TargetFirmware_18_1_0,
|
||||||
Version_19_0_0 = ::ams::TargetFirmware_19_0_0,
|
|
||||||
|
|
||||||
Version_Current = ::ams::TargetFirmware_Current,
|
Version_Current = ::ams::TargetFirmware_Current,
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,9 @@ namespace ams::ldr {
|
||||||
u32 aci_sac_size;
|
u32 aci_sac_size;
|
||||||
u32 acid_fac_size;
|
u32 acid_fac_size;
|
||||||
u32 aci_fah_size;
|
u32 aci_fah_size;
|
||||||
u8 unused_20[0x10];
|
|
||||||
u8 ac_buffer[0x3E0];
|
u8 ac_buffer[0x3E0];
|
||||||
};
|
};
|
||||||
static_assert(util::is_pod<ProgramInfo>::value && sizeof(ProgramInfo) == 0x410, "ProgramInfo definition!");
|
static_assert(util::is_pod<ProgramInfo>::value && sizeof(ProgramInfo) == 0x400, "ProgramInfo definition!");
|
||||||
|
|
||||||
enum ProgramInfoFlag {
|
enum ProgramInfoFlag {
|
||||||
ProgramInfoFlag_SystemModule = (0 << 0),
|
ProgramInfoFlag_SystemModule = (0 << 0),
|
||||||
|
|
|
@ -19,10 +19,8 @@
|
||||||
#include <stratosphere/pm/pm_types.hpp>
|
#include <stratosphere/pm/pm_types.hpp>
|
||||||
#include <stratosphere/sf.hpp>
|
#include <stratosphere/sf.hpp>
|
||||||
|
|
||||||
#define AMS_PM_I_BOOT_MODE_INTERFACE_INTERFACE_INFO(C, H) \
|
#define AMS_PM_I_BOOT_MODE_INTERFACE_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 0, void, GetBootMode, (sf::Out<u32> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 0, void, GetBootMode, (sf::Out<u32> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 1, void, SetMaintenanceBoot, (), ()) \
|
AMS_SF_METHOD_INFO(C, H, 1, void, SetMaintenanceBoot, (), ())
|
||||||
AMS_SF_METHOD_INFO(C, H, 2, void, GetUnknown, (sf::Out<u32> out), (out)) \
|
|
||||||
AMS_SF_METHOD_INFO(C, H, 3, Result, SetUnknown, (u32 val), (val))
|
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IBootModeInterface, AMS_PM_I_BOOT_MODE_INTERFACE_INTERFACE_INFO, 0x96D01649)
|
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IBootModeInterface, AMS_PM_I_BOOT_MODE_INTERFACE_INTERFACE_INFO, 0x96D01649)
|
||||||
|
|
|
@ -24,7 +24,6 @@ namespace ams::ldr::pm {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProgramInfo(ProgramInfo *out, const ncm::ProgramLocation &loc) {
|
Result GetProgramInfo(ProgramInfo *out, const ncm::ProgramLocation &loc) {
|
||||||
static_assert(sizeof(*out) == sizeof(LoaderProgramInfo));
|
|
||||||
R_RETURN(ldrPmGetProgramInfo(reinterpret_cast<const NcmProgramLocation *>(std::addressof(loc)), reinterpret_cast<LoaderProgramInfo *>(out)));
|
R_RETURN(ldrPmGetProgramInfo(reinterpret_cast<const NcmProgramLocation *>(std::addressof(loc)), reinterpret_cast<LoaderProgramInfo *>(out)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +42,6 @@ namespace ams::ldr::pm {
|
||||||
|
|
||||||
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
|
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
|
||||||
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus), "CfgOverrideStatus definition!");
|
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus), "CfgOverrideStatus definition!");
|
||||||
static_assert(sizeof(*out) == sizeof(LoaderProgramInfo));
|
|
||||||
R_RETURN(ldrPmAtmosphereGetProgramInfo(reinterpret_cast<LoaderProgramInfo *>(out), reinterpret_cast<CfgOverrideStatus *>(out_status), reinterpret_cast<const NcmProgramLocation *>(std::addressof(loc))));
|
R_RETURN(ldrPmAtmosphereGetProgramInfo(reinterpret_cast<LoaderProgramInfo *>(out), reinterpret_cast<CfgOverrideStatus *>(out_status), reinterpret_cast<const NcmProgramLocation *>(std::addressof(loc))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,5 @@ namespace ams::pm {
|
||||||
R_DEFINE_ERROR_RESULT(DebugHookInUse, 4);
|
R_DEFINE_ERROR_RESULT(DebugHookInUse, 4);
|
||||||
R_DEFINE_ERROR_RESULT(ApplicationRunning, 5);
|
R_DEFINE_ERROR_RESULT(ApplicationRunning, 5);
|
||||||
R_DEFINE_ERROR_RESULT(InvalidSize, 6);
|
R_DEFINE_ERROR_RESULT(InvalidSize, 6);
|
||||||
R_DEFINE_ERROR_RESULT(Unknown7, 7);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,29 +48,6 @@ static Result _nsGetApplicationContentPath(Service *s, void* out, size_t out_siz
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _nsGetApplicationContentPath2(Service *s, void* out_path, size_t out_size, u64* out_program_id, u8 *out_attr, u64 app_id, NcmContentType content_type) {
|
|
||||||
const struct {
|
|
||||||
u8 content_type;
|
|
||||||
u64 app_id;
|
|
||||||
} in = { content_type, app_id };
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u8 attr;
|
|
||||||
u64 program_id;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(s, 2524, in, out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { out_path, out_size } },
|
|
||||||
);
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
*out_program_id = out.program_id;
|
|
||||||
*out_attr = out.attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result _nsResolveApplicationContentPath(Service* s, u64 app_id, NcmContentType content_type) {
|
static Result _nsResolveApplicationContentPath(Service* s, u64 app_id, NcmContentType content_type) {
|
||||||
const struct {
|
const struct {
|
||||||
u8 content_type;
|
u8 content_type;
|
||||||
|
@ -116,10 +93,6 @@ Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_pr
|
||||||
return _nsGetRunningApplicationProgramId(&doc->s, out_program_id, app_id);
|
return _nsGetRunningApplicationProgramId(&doc->s, out_program_id, app_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nswebGetApplicationContentPath2(NsDocumentInterface* doc, void* out, size_t out_size, u64* out_program_id, u8 *out_attr, u64 app_id, NcmContentType content_type) {
|
|
||||||
return _nsGetApplicationContentPath2(&doc->s, out, out_size, out_program_id, out_attr, app_id, content_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsDocumentInterfaceClose(NsDocumentInterface* doc) {
|
void nsDocumentInterfaceClose(NsDocumentInterface* doc) {
|
||||||
serviceClose(&doc->s);
|
serviceClose(&doc->s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_program_id, u6
|
||||||
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u8 *out_attr, u64 app_id, NcmContentType content_type);
|
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u8 *out_attr, u64 app_id, NcmContentType content_type);
|
||||||
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type);
|
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type);
|
||||||
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id);
|
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id);
|
||||||
Result nswebGetApplicationContentPath2(NsDocumentInterface* doc, void* out, size_t out_size, u64* out_program_id, u8 *out_attr, u64 app_id, NcmContentType content_type);
|
|
||||||
|
|
||||||
void nsDocumentInterfaceClose(NsDocumentInterface* doc);
|
void nsDocumentInterfaceClose(NsDocumentInterface* doc);
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,6 @@ namespace ams::mitm::ns {
|
||||||
R_RETURN(nswebGetRunningApplicationProgramId(m_srv.get(), reinterpret_cast<u64 *>(out.GetPointer()), static_cast<u64>(application_id)));
|
R_RETURN(nswebGetRunningApplicationProgramId(m_srv.get(), reinterpret_cast<u64 *>(out.GetPointer()), static_cast<u64>(application_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result NsDocumentService::GetApplicationContentPath2(const sf::OutBuffer &out_path, sf::Out<ncm::ProgramId> out_program_id, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type) {
|
|
||||||
static_assert(sizeof(*out_attr.GetPointer()) == sizeof(u8));
|
|
||||||
R_RETURN(nswebGetApplicationContentPath2(m_srv.get(), out_path.GetPointer(), out_path.GetSize(), reinterpret_cast<u64 *>(out_program_id.GetPointer()), reinterpret_cast<u8 *>(out_attr.GetPointer()), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result NsWebMitmService::GetDocumentInterface(sf::Out<sf::SharedPointer<impl::IDocumentInterface>> out) {
|
Result NsWebMitmService::GetDocumentInterface(sf::Out<sf::SharedPointer<impl::IDocumentInterface>> out) {
|
||||||
/* Open a document interface. */
|
/* Open a document interface. */
|
||||||
NsDocumentInterface doc;
|
NsDocumentInterface doc;
|
||||||
|
|
|
@ -18,11 +18,10 @@
|
||||||
|
|
||||||
#include "ns_shim.h"
|
#include "ns_shim.h"
|
||||||
|
|
||||||
#define AMS_NS_DOCUMENT_MITM_INTERFACE_INFO(C, H) \
|
#define AMS_NS_DOCUMENT_MITM_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 21, Result, GetApplicationContentPath, (const sf::OutBuffer &out_path, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type), (out_path, out_attr, application_id, content_type)) \
|
AMS_SF_METHOD_INFO(C, H, 21, Result, GetApplicationContentPath, (const sf::OutBuffer &out_path, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type), (out_path, out_attr, application_id, content_type)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 23, Result, ResolveApplicationContentPath, (ncm::ProgramId application_id, u8 content_type), (application_id, content_type)) \
|
AMS_SF_METHOD_INFO(C, H, 23, Result, ResolveApplicationContentPath, (ncm::ProgramId application_id, u8 content_type), (application_id, content_type)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 92, Result, GetRunningApplicationProgramId, (sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id), (out, application_id), hos::Version_6_0_0) \
|
AMS_SF_METHOD_INFO(C, H, 92, Result, GetRunningApplicationProgramId, (sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id), (out, application_id), hos::Version_6_0_0)
|
||||||
AMS_SF_METHOD_INFO(C, H, 2524, Result, GetApplicationContentPath2, (const sf::OutBuffer &out_path, sf::Out<ncm::ProgramId> out_program_id, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type), (out_path, out_program_id, out_attr, application_id, content_type), hos::Version_19_0_0)
|
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::mitm::ns::impl, IDocumentInterface, AMS_NS_DOCUMENT_MITM_INTERFACE_INFO, 0x0F9B1C00)
|
AMS_SF_DEFINE_INTERFACE(ams::mitm::ns::impl, IDocumentInterface, AMS_NS_DOCUMENT_MITM_INTERFACE_INFO, 0x0F9B1C00)
|
||||||
|
|
||||||
|
@ -48,7 +47,6 @@ namespace ams::mitm::ns {
|
||||||
Result GetApplicationContentPath(const sf::OutBuffer &out_path, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type);
|
Result GetApplicationContentPath(const sf::OutBuffer &out_path, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type);
|
||||||
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
|
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
|
||||||
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
|
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
|
||||||
Result GetApplicationContentPath2(const sf::OutBuffer &out_path, sf::Out<ncm::ProgramId> out_program_id, sf::Out<ams::fs::ContentAttributes> out_attr, ncm::ProgramId application_id, u8 content_type);
|
|
||||||
};
|
};
|
||||||
static_assert(impl::IsIDocumentInterface<NsDocumentService>);
|
static_assert(impl::IsIDocumentInterface<NsDocumentService>);
|
||||||
|
|
||||||
|
|
|
@ -425,20 +425,6 @@ namespace ams::ldr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixDebugCapabilityForHbl(util::BitPack32 *kac, size_t count) {
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
|
||||||
const auto cap = kac[i];
|
|
||||||
switch (GetCapabilityId(cap)) {
|
|
||||||
case CapabilityId::DebugFlags:
|
|
||||||
/* 19.0.0+ disallows more than one flag set; we are always DebugMode for kernel, so ForceDebug is the most powerful/flexible flag to set. */
|
|
||||||
kac[i] = CapabilityDebugFlags::Encode(false, false, true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PreProcessCapability(util::BitPack32 *kac, size_t count) {
|
void PreProcessCapability(util::BitPack32 *kac, size_t count) {
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
const auto cap = kac[i];
|
const auto cap = kac[i];
|
||||||
|
|
|
@ -23,8 +23,6 @@ namespace ams::ldr {
|
||||||
u16 MakeProgramInfoFlag(const util::BitPack32 *kac, size_t count);
|
u16 MakeProgramInfoFlag(const util::BitPack32 *kac, size_t count);
|
||||||
void UpdateProgramInfoFlag(u16 flags, util::BitPack32 *kac, size_t count);
|
void UpdateProgramInfoFlag(u16 flags, util::BitPack32 *kac, size_t count);
|
||||||
|
|
||||||
void FixDebugCapabilityForHbl(util::BitPack32 *kac, size_t count);
|
|
||||||
|
|
||||||
void PreProcessCapability(util::BitPack32 *kac, size_t count);
|
void PreProcessCapability(util::BitPack32 *kac, size_t count);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace ams {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct ServerOptions {
|
struct ServerOptions {
|
||||||
static constexpr size_t PointerBufferSize = 0x420;
|
static constexpr size_t PointerBufferSize = 0x400;
|
||||||
static constexpr size_t MaxDomains = 0;
|
static constexpr size_t MaxDomains = 0;
|
||||||
static constexpr size_t MaxDomainObjects = 0;
|
static constexpr size_t MaxDomainObjects = 0;
|
||||||
static constexpr bool CanDeferInvokeRequest = false;
|
static constexpr bool CanDeferInvokeRequest = false;
|
||||||
|
|
|
@ -252,10 +252,6 @@ namespace ams::ldr {
|
||||||
meta->npdm->main_thread_priority = HblMainThreadPriorityApplet;
|
meta->npdm->main_thread_priority = HblMainThreadPriorityApplet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix the debug capabilities, to prevent needing a hbl recompilation. */
|
|
||||||
FixDebugCapabilityForHbl(static_cast<util::BitPack32 *>(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32));
|
|
||||||
FixDebugCapabilityForHbl(static_cast<util::BitPack32 *>(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32));
|
|
||||||
} else if (hos::GetVersion() >= hos::Version_10_0_0) {
|
} else if (hos::GetVersion() >= hos::Version_10_0_0) {
|
||||||
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
||||||
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace ams::pm {
|
||||||
|
|
||||||
/* Global bootmode. */
|
/* Global bootmode. */
|
||||||
constinit BootMode g_boot_mode = BootMode::Normal;
|
constinit BootMode g_boot_mode = BootMode::Normal;
|
||||||
constinit u32 g_unknown = 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,14 +47,4 @@ namespace ams::pm {
|
||||||
pm::bm::SetMaintenanceBoot();
|
pm::bm::SetMaintenanceBoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BootModeService::GetUnknown(sf::Out<u32> out) {
|
|
||||||
out.SetValue(g_unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result BootModeService::SetUnknown(u32 val) {
|
|
||||||
R_UNLESS(val <= 3, pm::ResultUnknown7());
|
|
||||||
g_unknown = val;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ namespace ams::pm {
|
||||||
public:
|
public:
|
||||||
void GetBootMode(sf::Out<u32> out);
|
void GetBootMode(sf::Out<u32> out);
|
||||||
void SetMaintenanceBoot();
|
void SetMaintenanceBoot();
|
||||||
void GetUnknown(sf::Out<u32> out);
|
|
||||||
Result SetUnknown(u32 val);
|
|
||||||
};
|
};
|
||||||
static_assert(pm::impl::IsIBootModeInterface<BootModeService>);
|
static_assert(pm::impl::IsIBootModeInterface<BootModeService>);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue