Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e1cf7a7e0 | ||
|
|
6b3bf10e46 | ||
|
|
16a25309d2 | ||
|
|
eca5ac01b8 | ||
|
|
50ea19e7a2 | ||
|
|
823a1f3ea3 | ||
|
|
b73895df0a | ||
|
|
5062329979 | ||
|
|
065485b971 | ||
|
|
6193283f03 | ||
|
|
eb48e7cc59 | ||
|
|
d98490d339 | ||
|
|
b2e86f5a1b | ||
|
|
0e9974e7b3 | ||
|
|
496be5ecd4 | ||
|
|
50a91b1d6e | ||
|
|
f872be67eb | ||
|
|
e04679f05a | ||
|
|
8d1ada2a1b | ||
|
|
a50d6a2696 | ||
|
|
76d72fa946 | ||
|
|
8b19fdfd51 | ||
|
|
612d846132 | ||
|
|
816ce605d3 | ||
|
|
07c95662b1 | ||
|
|
2b930d21fd | ||
|
|
0b52596087 | ||
|
|
e9134d8044 | ||
|
|
33d6dfb6b3 | ||
|
|
6096fa0e45 | ||
|
|
058f265bd6 | ||
|
|
bd4c608b08 | ||
|
|
7fc1e86bf5 | ||
|
|
87ec045a98 | ||
|
|
7502e2174f | ||
|
|
0545eb18c0 | ||
|
|
0c161a4c1b | ||
|
|
3d518759da | ||
|
|
0af2758fde | ||
|
|
9bb5af9823 | ||
|
|
82eab9c8d0 | ||
|
|
3cca3801ca | ||
|
|
03408f404a | ||
|
|
92e7a3ca08 | ||
|
|
b27c7552d2 | ||
|
|
426257d4ae | ||
|
|
7d34d599bb | ||
|
|
067fe2d10f | ||
|
|
4759c2f92c | ||
|
|
ca26d8ce27 | ||
|
|
6c52cc3e26 | ||
|
|
e42d3a3abf | ||
|
|
884844bc23 | ||
|
|
f556db8c89 | ||
|
|
96d15b28c6 | ||
|
|
37f7afb426 | ||
|
|
7dd4e76c1d | ||
|
|
daa0deb1bf | ||
|
|
43bd733f0a | ||
|
|
70367e3e7c | ||
|
|
45f8343659 |
@@ -1,4 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 0.10.5
|
||||||
|
+ Changes were made to the way fs.mitm builds images when providing a layeredfs romfs.
|
||||||
|
+ Building romfs metadata previously had a memory cost of about ~4-5x the file table size.
|
||||||
|
+ This caused games that have particularly enormous file metadata tables (> 4 MB) to exhaust fs.mitm's 16 MB memory pool.
|
||||||
|
+ The code that creates romfs images was thus changed to be significantly more memory efficient, again.
|
||||||
|
+ Memory requirements have been lowered from ~4x file table size to ~2x file table size + 0.5 MB.
|
||||||
|
+ There is a slight speed penalty to this, but testing on Football Manager 2020 only took an extra ~1.5 seconds for the game to boot with many modded files.
|
||||||
|
+ This shouldn't be noticeable thanks to the async changes made in 0.10.2.
|
||||||
|
+ If you encounter a game that exhausts ams.mitm's memory (crashing it) when loading layeredfs mods, please contact SciresM.
|
||||||
|
+ Romfs building can be made even more memory efficient, but unless games show up with even more absurdly huge file tables it seems not worth the speed trade-off.
|
||||||
|
+ A bug was fixed that caused Atmosphere's fatal error context to not dump TLS for certain processes.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
## 0.10.4
|
## 0.10.4
|
||||||
+ With major thanks to @Adubbz for his work, the NCM system module has now been re-implemented.
|
+ With major thanks to @Adubbz for his work, the NCM system module has now been re-implemented.
|
||||||
+ This was a major stepping stone towards the goal of having implementations everything in the Switch's package1/package2 firmware.
|
+ This was a major stepping stone towards the goal of having implementations everything in the Switch's package1/package2 firmware.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||||
branch = master
|
branch = master
|
||||||
commit = a4ce117292cc86e951d82666f4e13bc1dc40443f
|
commit = da6eac986d7f67ca3dcc3a8df0c191ffbea4686f
|
||||||
parent = 95d5375158f6df5376ce876e6ed8c22150ad88ff
|
parent = eb48e7cc5943bd594b3166cb888d3dadb0474107
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ endif
|
|||||||
include $(DEVKITPRO)/devkitA64/base_rules
|
include $(DEVKITPRO)/devkitA64/base_rules
|
||||||
|
|
||||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
|
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
|
||||||
export ATMOSPHERE_SETTINGS += -march=armv8-a -mtp=soft
|
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtp=soft
|
||||||
export ATMOSPHERE_CFLAGS +=
|
export ATMOSPHERE_CFLAGS +=
|
||||||
export ATMOSPHERE_CXXFLAGS +=
|
export ATMOSPHERE_CXXFLAGS +=
|
||||||
export ATMOSPHERE_ASFLAGS +=
|
export ATMOSPHERE_ASFLAGS +=
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE
|
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||||
export SETTINGS = $(ATMOSPHERE_SETTINGS) -O2
|
export SETTINGS = $(ATMOSPHERE_SETTINGS) -O2
|
||||||
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
|
#PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
|
||||||
|
PRECOMPILED_HEADERS :=
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror -fno-non-call-exceptions
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ namespace ams::kern::arch::arm64 {
|
|||||||
return this->page_table.UnmapPages(addr, num_pages, state);
|
return this->page_table.UnmapPages(addr, num_pages, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
|
||||||
|
return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||||
|
}
|
||||||
|
|
||||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||||
return this->page_table.GetPhysicalAddress(out, address);
|
return this->page_table.GetPhysicalAddress(out, address);
|
||||||
}
|
}
|
||||||
@@ -96,12 +100,23 @@ namespace ams::kern::arch::arm64 {
|
|||||||
KProcessAddress GetAliasRegionStart() const { return this->page_table.GetAliasRegionStart(); }
|
KProcessAddress GetAliasRegionStart() const { return this->page_table.GetAliasRegionStart(); }
|
||||||
KProcessAddress GetStackRegionStart() const { return this->page_table.GetStackRegionStart(); }
|
KProcessAddress GetStackRegionStart() const { return this->page_table.GetStackRegionStart(); }
|
||||||
KProcessAddress GetKernelMapRegionStart() const { return this->page_table.GetKernelMapRegionStart(); }
|
KProcessAddress GetKernelMapRegionStart() const { return this->page_table.GetKernelMapRegionStart(); }
|
||||||
|
KProcessAddress GetAliasCodeRegionStart() const { return this->page_table.GetAliasCodeRegionStart(); }
|
||||||
|
|
||||||
size_t GetAddressSpaceSize() const { return this->page_table.GetAddressSpaceSize(); }
|
size_t GetAddressSpaceSize() const { return this->page_table.GetAddressSpaceSize(); }
|
||||||
size_t GetHeapRegionSize() const { return this->page_table.GetHeapRegionSize(); }
|
size_t GetHeapRegionSize() const { return this->page_table.GetHeapRegionSize(); }
|
||||||
size_t GetAliasRegionSize() const { return this->page_table.GetAliasRegionSize(); }
|
size_t GetAliasRegionSize() const { return this->page_table.GetAliasRegionSize(); }
|
||||||
size_t GetStackRegionSize() const { return this->page_table.GetStackRegionSize(); }
|
size_t GetStackRegionSize() const { return this->page_table.GetStackRegionSize(); }
|
||||||
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
|
size_t GetKernelMapRegionSize() const { return this->page_table.GetKernelMapRegionSize(); }
|
||||||
|
size_t GetAliasCodeRegionSize() const { return this->page_table.GetAliasCodeRegionSize(); }
|
||||||
|
|
||||||
|
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
||||||
|
/* TODO: Better way to convert address type? */
|
||||||
|
return this->page_table.GetHeapPhysicalAddress(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
KBlockInfoManager *GetBlockInfoManager() {
|
||||||
|
return this->page_table.GetBlockInfoManager();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
/* Power management. */
|
/* Power management. */
|
||||||
static void SleepSystem();
|
static void SleepSystem();
|
||||||
static NORETURN void StopSystem();
|
static NORETURN void StopSystem();
|
||||||
|
|
||||||
|
/* User access. */
|
||||||
|
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -222,6 +222,8 @@ namespace ams::kern {
|
|||||||
KScopedAutoObject(o).Swap(*this);
|
KScopedAutoObject(o).Swap(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE T *GetPointerUnsafe() { return this->obj; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsNull() const { return this->obj == nullptr; }
|
constexpr ALWAYS_INLINE bool IsNull() const { return this->obj == nullptr; }
|
||||||
constexpr ALWAYS_INLINE bool IsNotNull() const { return this->obj != nullptr; }
|
constexpr ALWAYS_INLINE bool IsNotNull() const { return this->obj != nullptr; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KPort;
|
||||||
|
|
||||||
|
class KClientPort final : public KSynchronizationObject {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject);
|
||||||
|
private:
|
||||||
|
std::atomic<s32> num_sessions;
|
||||||
|
std::atomic<s32> peak_sessions;
|
||||||
|
s32 max_sessions;
|
||||||
|
KPort *parent;
|
||||||
|
public:
|
||||||
|
constexpr KClientPort() : num_sessions(), peak_sessions(), max_sessions(), parent() { /* ... */ }
|
||||||
|
virtual ~KClientPort() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KPort *parent, s32 max_sessions);
|
||||||
|
|
||||||
|
constexpr const KPort *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
bool IsLight() const;
|
||||||
|
|
||||||
|
/* Overridden virtual functions. */
|
||||||
|
virtual void Destroy() override;
|
||||||
|
virtual bool IsSignaled() const override;
|
||||||
|
|
||||||
|
/* TODO: More of KClientPort. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KSession;
|
||||||
|
|
||||||
|
class KClientSession final : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KClientSession, KAutoObject);
|
||||||
|
private:
|
||||||
|
KSession *parent;
|
||||||
|
public:
|
||||||
|
constexpr KClientSession() : parent() { /* ... */ }
|
||||||
|
virtual ~KClientSession() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KSession *parent) {
|
||||||
|
/* Set member variables. */
|
||||||
|
this->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr const KSession *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
/* TODO: More of KClientSession. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -130,11 +130,11 @@ namespace ams::kern {
|
|||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Handle pseudo-handles. */
|
/* Handle pseudo-handles. */
|
||||||
if constexpr (std::is_same<T, KProcess>::value) {
|
if constexpr (std::is_base_of<T, KProcess>::value) {
|
||||||
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
|
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
|
||||||
return GetCurrentProcessPointer();
|
return GetCurrentProcessPointer();
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same<T, KThread>::value) {
|
} else if constexpr (std::is_base_of<T, KThread>::value) {
|
||||||
if (handle == ams::svc::PseudoHandle::CurrentThread) {
|
if (handle == ams::svc::PseudoHandle::CurrentThread) {
|
||||||
return GetCurrentThreadPointer();
|
return GetCurrentThreadPointer();
|
||||||
}
|
}
|
||||||
@@ -156,11 +156,11 @@ namespace ams::kern {
|
|||||||
static_assert(!std::is_base_of<KInterruptEvent, T>::value);
|
static_assert(!std::is_base_of<KInterruptEvent, T>::value);
|
||||||
|
|
||||||
/* Handle pseudo-handles. */
|
/* Handle pseudo-handles. */
|
||||||
if constexpr (std::is_same<T, KProcess>::value) {
|
if constexpr (std::is_base_of<T, KProcess>::value) {
|
||||||
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
|
if (handle == ams::svc::PseudoHandle::CurrentProcess) {
|
||||||
return GetCurrentProcessPointer();
|
return GetCurrentProcessPointer();
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same<T, KThread>::value) {
|
} else if constexpr (std::is_base_of<T, KThread>::value) {
|
||||||
if (handle == ams::svc::PseudoHandle::CurrentThread) {
|
if (handle == ams::svc::PseudoHandle::CurrentThread) {
|
||||||
return GetCurrentThreadPointer();
|
return GetCurrentThreadPointer();
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ namespace ams::kern {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE void Register(ams::svc::Handle handle, T *obj) {
|
ALWAYS_INLINE void Register(ams::svc::Handle handle, T *obj) {
|
||||||
static_assert(std::is_base_of<KAutoObject, T>::value);
|
static_assert(std::is_base_of<KAutoObject, T>::value);
|
||||||
return this->Add(handle, obj, obj->GetTypeObj().GetClassToken());
|
return this->Register(handle, obj, obj->GetTypeObj().GetClassToken());
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
NOINLINE Result Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type);
|
NOINLINE Result Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type);
|
||||||
@@ -278,7 +278,7 @@ namespace ams::kern {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr NOINLINE KAutoObject *GetObjectImpl(ams::svc::Handle handle) const {
|
constexpr ALWAYS_INLINE KAutoObject *GetObjectImpl(ams::svc::Handle handle) const {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Handles must not have reserved bits set. */
|
/* Handles must not have reserved bits set. */
|
||||||
@@ -293,7 +293,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr NOINLINE KAutoObject *GetObjectByIndexImpl(ams::svc::Handle *out_handle, size_t index) const {
|
constexpr ALWAYS_INLINE KAutoObject *GetObjectByIndexImpl(ams::svc::Handle *out_handle, size_t index) const {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
/* Index must be in bounds. */
|
/* Index must be in bounds. */
|
||||||
@@ -310,6 +310,49 @@ namespace ams::kern {
|
|||||||
*out_handle = EncodeHandle(index, entry->GetLinearId());
|
*out_handle = EncodeHandle(index, entry->GetLinearId());
|
||||||
return entry->GetObject();
|
return entry->GetObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE bool GetMultipleObjects(T **out, const ams::svc::Handle *handles, size_t num_handles) const {
|
||||||
|
/* Try to convert and open all the handles. */
|
||||||
|
size_t num_opened;
|
||||||
|
{
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedDisableDispatch dd;
|
||||||
|
KScopedSpinLock lk(this->lock);
|
||||||
|
for (num_opened = 0; num_opened < num_handles; num_opened++) {
|
||||||
|
/* Get the current handle. */
|
||||||
|
const auto cur_handle = handles[num_opened];
|
||||||
|
|
||||||
|
/* Get the object for the current handle. */
|
||||||
|
KAutoObject *cur_object = this->GetObjectImpl(cur_handle);
|
||||||
|
if (AMS_UNLIKELY(cur_object == nullptr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cast the current object to the desired type. */
|
||||||
|
T *cur_t = cur_object->DynamicCast<T*>();
|
||||||
|
if (AMS_UNLIKELY(cur_t == nullptr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open a reference to the current object. */
|
||||||
|
cur_t->Open();
|
||||||
|
out[num_opened] = cur_t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we converted every object, succeed. */
|
||||||
|
if (AMS_LIKELY(num_opened == num_handles)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we didn't convert entry object, close the ones we opened. */
|
||||||
|
for (size_t i = 0; i < num_opened; i++) {
|
||||||
|
out[i]->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KLightSession;
|
||||||
|
|
||||||
|
class KLightClientSession final : public KAutoObjectWithSlabHeapAndContainer<KLightClientSession, KAutoObjectWithList> {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KLightClientSession, KAutoObject);
|
||||||
|
private:
|
||||||
|
KLightSession *parent;
|
||||||
|
public:
|
||||||
|
constexpr KLightClientSession() : parent() { /* ... */ }
|
||||||
|
virtual ~KLightClientSession() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KLightSession *parent) {
|
||||||
|
/* Set member variables. */
|
||||||
|
this->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr const KLightSession *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
/* TODO: More of KLightClientSession. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_k_thread.hpp>
|
||||||
|
#include <mesosphere/kern_k_thread_queue.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KLightSession;
|
||||||
|
|
||||||
|
class KLightServerSession final : public KAutoObjectWithSlabHeapAndContainer<KLightServerSession, KAutoObjectWithList>, public util::IntrusiveListBaseNode<KLightServerSession> {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KLightServerSession, KAutoObject);
|
||||||
|
private:
|
||||||
|
KLightSession *parent;
|
||||||
|
KThreadQueue request_queue;
|
||||||
|
KThreadQueue server_queue;
|
||||||
|
KThread *current_request;
|
||||||
|
KThread *server_thread;
|
||||||
|
public:
|
||||||
|
constexpr KLightServerSession() : parent(), request_queue(), server_queue(), current_request(), server_thread() { /* ... */ }
|
||||||
|
virtual ~KLightServerSession() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KLightSession *parent);
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr const KLightSession *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
/* TODO: More of KLightServerSession. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,14 +16,52 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <mesosphere/kern_common.hpp>
|
#include <mesosphere/kern_common.hpp>
|
||||||
#include <mesosphere/kern_k_synchronization_object.hpp>
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_k_light_server_session.hpp>
|
||||||
|
#include <mesosphere/kern_k_light_client_session.hpp>
|
||||||
#include <mesosphere/kern_slab_helpers.hpp>
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KClientPort;
|
||||||
|
class KProcess;
|
||||||
|
|
||||||
class KLightSession final : public KAutoObjectWithSlabHeapAndContainer<KLightSession, KAutoObjectWithList> {
|
class KLightSession final : public KAutoObjectWithSlabHeapAndContainer<KLightSession, KAutoObjectWithList> {
|
||||||
MESOSPHERE_AUTOOBJECT_TRAITS(KLightSession, KAutoObject);
|
MESOSPHERE_AUTOOBJECT_TRAITS(KLightSession, KAutoObject);
|
||||||
|
private:
|
||||||
|
enum class State : u8 {
|
||||||
|
Invalid = 0,
|
||||||
|
Normal = 1,
|
||||||
|
ClientClosed = 2,
|
||||||
|
ServerClosed = 3,
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
KLightServerSession server;
|
||||||
|
KLightClientSession client;
|
||||||
|
State state;
|
||||||
|
KClientPort *port;
|
||||||
|
uintptr_t name;
|
||||||
|
KProcess *process;
|
||||||
|
bool initialized;
|
||||||
public:
|
public:
|
||||||
|
constexpr KLightSession()
|
||||||
|
: server(), client(), state(State::Invalid), port(), name(), process(), initialized()
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~KLightSession() { /* ... */ }
|
||||||
|
|
||||||
|
virtual bool IsInitialized() const override { return this->initialized; }
|
||||||
|
virtual uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(this->process); }
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg);
|
||||||
|
|
||||||
/* TODO: This is a placeholder definition. */
|
/* TODO: This is a placeholder definition. */
|
||||||
|
|
||||||
|
KLightClientSession &GetClientSession() { return this->client; }
|
||||||
|
KLightServerSession &GetServerSession() { return this->server; }
|
||||||
|
const KLightClientSession &GetClientSession() const { return this->client; }
|
||||||
|
const KLightServerSession &GetServerSession() const { return this->server; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,39 @@ namespace ams::kern {
|
|||||||
|
|
||||||
class KObjectName : public KSlabAllocated<KObjectName>, public util::IntrusiveListBaseNode<KObjectName> {
|
class KObjectName : public KSlabAllocated<KObjectName>, public util::IntrusiveListBaseNode<KObjectName> {
|
||||||
public:
|
public:
|
||||||
/* TODO: This is a placeholder definition. */
|
static constexpr size_t NameLengthMax = 12;
|
||||||
|
|
||||||
|
using List = util::IntrusiveListBaseTraits<KObjectName>::ListType;
|
||||||
|
private:
|
||||||
|
char name[NameLengthMax];
|
||||||
|
KAutoObject *object;
|
||||||
|
public:
|
||||||
|
constexpr KObjectName() : name(), object() { /* ... */ }
|
||||||
|
public:
|
||||||
|
static Result NewFromName(KAutoObject *obj, const char *name);
|
||||||
|
static Result Delete(KAutoObject *obj, const char *name);
|
||||||
|
|
||||||
|
static KScopedAutoObject<KAutoObject> Find(const char *name);
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
static Result Delete(const char *name) {
|
||||||
|
/* Find the object. */
|
||||||
|
KScopedAutoObject obj = Find(name);
|
||||||
|
R_UNLESS(obj.IsNotNull(), svc::ResultNotFound());
|
||||||
|
|
||||||
|
/* Cast the object to the desired type. */
|
||||||
|
Derived *derived = obj->DynamicCast<Derived *>();
|
||||||
|
R_UNLESS(derived != nullptr, svc::ResultNotFound());
|
||||||
|
|
||||||
|
return Delete(obj.GetPointerUnsafe(), name);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static KScopedAutoObject<KAutoObject> FindImpl(const char *name);
|
||||||
|
|
||||||
|
void Initialize(KAutoObject *obj, const char *name);
|
||||||
|
|
||||||
|
bool MatchesName(const char *name) const;
|
||||||
|
KAutoObject *GetObject() const { return this->object; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ namespace ams::kern {
|
|||||||
|
|
||||||
/* Align up the address. */
|
/* Align up the address. */
|
||||||
KVirtualAddress end = addr + size;
|
KVirtualAddress end = addr + size;
|
||||||
const size_t align = (this->next_block_shift != 0) ? (u64(1) << this->next_block_shift) : (this->block_shift);
|
const size_t align = (this->next_block_shift != 0) ? (u64(1) << this->next_block_shift) : (u64(1) << this->block_shift);
|
||||||
addr = util::AlignDown(GetInteger(addr), align);
|
addr = util::AlignDown(GetInteger(addr), align);
|
||||||
end = util::AlignUp(GetInteger(end), align);
|
end = util::AlignUp(GetInteger(end), align);
|
||||||
|
|
||||||
|
|||||||
@@ -191,8 +191,6 @@ namespace ams::kern {
|
|||||||
KPageTableImpl &GetImpl() { return this->impl; }
|
KPageTableImpl &GetImpl() { return this->impl; }
|
||||||
const KPageTableImpl &GetImpl() const { return this->impl; }
|
const KPageTableImpl &GetImpl() const { return this->impl; }
|
||||||
|
|
||||||
KBlockInfoManager *GetBlockInfoManager() const { return this->block_info_manager; }
|
|
||||||
|
|
||||||
bool IsLockedByCurrentThread() const { return this->general_lock.IsLockedByCurrentThread(); }
|
bool IsLockedByCurrentThread() const { return this->general_lock.IsLockedByCurrentThread(); }
|
||||||
|
|
||||||
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) {
|
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) {
|
||||||
@@ -245,6 +243,8 @@ namespace ams::kern {
|
|||||||
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KBlockInfoManager *GetBlockInfoManager() const { return this->block_info_manager; }
|
||||||
|
|
||||||
Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
|
Result SetMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
|
||||||
Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
|
Result SetProcessMemoryPermission(KProcessAddress addr, size_t size, ams::svc::MemoryPermission perm);
|
||||||
Result SetHeapSize(KProcessAddress *out, size_t size);
|
Result SetHeapSize(KProcessAddress *out, size_t size);
|
||||||
@@ -270,18 +270,22 @@ namespace ams::kern {
|
|||||||
Result MapPageGroup(KProcessAddress *out_addr, const KPageGroup &pg, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
|
Result MapPageGroup(KProcessAddress *out_addr, const KPageGroup &pg, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
|
||||||
Result MapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm);
|
Result MapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm);
|
||||||
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state);
|
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state);
|
||||||
|
|
||||||
|
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
||||||
public:
|
public:
|
||||||
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
||||||
KProcessAddress GetHeapRegionStart() const { return this->heap_region_start; }
|
KProcessAddress GetHeapRegionStart() const { return this->heap_region_start; }
|
||||||
KProcessAddress GetAliasRegionStart() const { return this->alias_region_start; }
|
KProcessAddress GetAliasRegionStart() const { return this->alias_region_start; }
|
||||||
KProcessAddress GetStackRegionStart() const { return this->stack_region_start; }
|
KProcessAddress GetStackRegionStart() const { return this->stack_region_start; }
|
||||||
KProcessAddress GetKernelMapRegionStart() const { return this->kernel_map_region_start; }
|
KProcessAddress GetKernelMapRegionStart() const { return this->kernel_map_region_start; }
|
||||||
|
KProcessAddress GetAliasCodeRegionStart() const { return this->alias_code_region_start; }
|
||||||
|
|
||||||
size_t GetAddressSpaceSize() const { return this->address_space_end - this->address_space_start; }
|
size_t GetAddressSpaceSize() const { return this->address_space_end - this->address_space_start; }
|
||||||
size_t GetHeapRegionSize() const { return this->heap_region_end - this->heap_region_start; }
|
size_t GetHeapRegionSize() const { return this->heap_region_end - this->heap_region_start; }
|
||||||
size_t GetAliasRegionSize() const { return this->alias_region_end - this->alias_region_start; }
|
size_t GetAliasRegionSize() const { return this->alias_region_end - this->alias_region_start; }
|
||||||
size_t GetStackRegionSize() const { return this->stack_region_end - this->stack_region_start; }
|
size_t GetStackRegionSize() const { return this->stack_region_end - this->stack_region_start; }
|
||||||
size_t GetKernelMapRegionSize() const { return this->kernel_map_region_end - this->kernel_map_region_start; }
|
size_t GetKernelMapRegionSize() const { return this->kernel_map_region_end - this->kernel_map_region_start; }
|
||||||
|
size_t GetAliasCodeRegionSize() const { return this->alias_code_region_end - this->alias_code_region_start; }
|
||||||
public:
|
public:
|
||||||
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress addr) {
|
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress addr) {
|
||||||
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
return KMemoryLayout::GetLinearVirtualAddress(addr);
|
||||||
|
|||||||
@@ -16,14 +16,46 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <mesosphere/kern_common.hpp>
|
#include <mesosphere/kern_common.hpp>
|
||||||
#include <mesosphere/kern_k_synchronization_object.hpp>
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_k_client_port.hpp>
|
||||||
|
#include <mesosphere/kern_k_server_port.hpp>
|
||||||
#include <mesosphere/kern_slab_helpers.hpp>
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> {
|
class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> {
|
||||||
MESOSPHERE_AUTOOBJECT_TRAITS(KPort, KAutoObject);
|
MESOSPHERE_AUTOOBJECT_TRAITS(KPort, KAutoObject);
|
||||||
|
private:
|
||||||
|
enum class State : u8 {
|
||||||
|
Invalid = 0,
|
||||||
|
Normal = 1,
|
||||||
|
ClientClosed = 2,
|
||||||
|
ServerClosed = 3,
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
KServerPort server;
|
||||||
|
KClientPort client;
|
||||||
|
uintptr_t name;
|
||||||
|
State state;
|
||||||
|
bool is_light;
|
||||||
public:
|
public:
|
||||||
/* TODO: This is a placeholder definition. */
|
constexpr KPort() : server(), client(), name(), state(State::Invalid), is_light() { /* ... */ }
|
||||||
|
virtual ~KPort() { /* ... */ }
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg) { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(s32 max_sessions, bool is_light, uintptr_t name);
|
||||||
|
void OnClientClosed();
|
||||||
|
void OnServerClosed();
|
||||||
|
|
||||||
|
uintptr_t GetName() const { return this->name; }
|
||||||
|
bool IsLight() const { return this->is_light; }
|
||||||
|
|
||||||
|
/* TODO: More of KPort */
|
||||||
|
|
||||||
|
KClientPort &GetClientPort() { return this->client; }
|
||||||
|
KServerPort &GetServerPort() { return this->server; }
|
||||||
|
const KClientPort &GetClientPort() const { return this->client; }
|
||||||
|
const KServerPort &GetServerPort() const { return this->server; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KPort;
|
||||||
|
class KServerSession;
|
||||||
|
class KLightServerSession;
|
||||||
|
|
||||||
|
class KServerPort final : public KSynchronizationObject {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
|
||||||
|
private:
|
||||||
|
using SessionList = util::IntrusiveListBaseTraits<KServerSession>::ListType;
|
||||||
|
using LightSessionList = util::IntrusiveListBaseTraits<KLightServerSession>::ListType;
|
||||||
|
private:
|
||||||
|
SessionList session_list;
|
||||||
|
LightSessionList light_session_list;
|
||||||
|
KPort *parent;
|
||||||
|
public:
|
||||||
|
constexpr KServerPort() : session_list(), light_session_list(), parent() { /* ... */ }
|
||||||
|
virtual ~KServerPort() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KPort *parent);
|
||||||
|
|
||||||
|
constexpr const KPort *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
bool IsLight() const;
|
||||||
|
|
||||||
|
/* Overridden virtual functions. */
|
||||||
|
virtual void Destroy() override;
|
||||||
|
virtual bool IsSignaled() const override;
|
||||||
|
|
||||||
|
/* TODO: More of KClientPort. */
|
||||||
|
private:
|
||||||
|
void CleanupSessions();
|
||||||
|
/* TODO: This is a placeholder definition. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <mesosphere/kern_common.hpp>
|
||||||
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_k_session_request.hpp>
|
||||||
|
#include <mesosphere/kern_k_light_lock.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KSession;
|
||||||
|
|
||||||
|
class KServerSession final : public KSynchronizationObject, public util::IntrusiveListBaseNode<KServerSession> {
|
||||||
|
MESOSPHERE_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject);
|
||||||
|
private:
|
||||||
|
using RequestList = util::IntrusiveListBaseTraits<KSessionRequest>::ListType;
|
||||||
|
private:
|
||||||
|
KSession *parent;
|
||||||
|
RequestList request_list;
|
||||||
|
KSessionRequest *current_request;
|
||||||
|
KLightLock lock;
|
||||||
|
public:
|
||||||
|
constexpr KServerSession() : parent(), request_list(), current_request(), lock() { /* ... */ }
|
||||||
|
virtual ~KServerSession() { /* ... */ }
|
||||||
|
|
||||||
|
void Initialize(KSession *parent);
|
||||||
|
|
||||||
|
constexpr const KSession *GetParent() const { return this->parent; }
|
||||||
|
|
||||||
|
virtual bool IsSignaled() const override { MESOSPHERE_UNIMPLEMENTED(); }
|
||||||
|
|
||||||
|
/* TODO: More of KServerSession. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,14 +16,52 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <mesosphere/kern_common.hpp>
|
#include <mesosphere/kern_common.hpp>
|
||||||
#include <mesosphere/kern_k_synchronization_object.hpp>
|
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||||
|
#include <mesosphere/kern_k_server_session.hpp>
|
||||||
|
#include <mesosphere/kern_k_client_session.hpp>
|
||||||
#include <mesosphere/kern_slab_helpers.hpp>
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KClientPort;
|
||||||
|
class KProcess;
|
||||||
|
|
||||||
class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> {
|
class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> {
|
||||||
MESOSPHERE_AUTOOBJECT_TRAITS(KSession, KAutoObject);
|
MESOSPHERE_AUTOOBJECT_TRAITS(KSession, KAutoObject);
|
||||||
|
private:
|
||||||
|
enum class State : u8 {
|
||||||
|
Invalid = 0,
|
||||||
|
Normal = 1,
|
||||||
|
ClientClosed = 2,
|
||||||
|
ServerClosed = 3,
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
KServerSession server;
|
||||||
|
KClientSession client;
|
||||||
|
State state;
|
||||||
|
KClientPort *port;
|
||||||
|
uintptr_t name;
|
||||||
|
KProcess *process;
|
||||||
|
bool initialized;
|
||||||
public:
|
public:
|
||||||
|
constexpr KSession()
|
||||||
|
: server(), client(), state(State::Invalid), port(), name(), process(), initialized()
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~KSession() { /* ... */ }
|
||||||
|
|
||||||
|
virtual bool IsInitialized() const override { return this->initialized; }
|
||||||
|
virtual uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(this->process); }
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg);
|
||||||
|
|
||||||
/* TODO: This is a placeholder definition. */
|
/* TODO: This is a placeholder definition. */
|
||||||
|
|
||||||
|
KClientSession &GetClientSession() { return this->client; }
|
||||||
|
KServerSession &GetServerSession() { return this->server; }
|
||||||
|
const KClientSession &GetClientSession() const { return this->client; }
|
||||||
|
const KServerSession &GetServerSession() const { return this->server; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace ams::kern {
|
|||||||
#define MESOSPHERE_UNUSED(...) ::ams::kern::UnusedImpl(__VA_ARGS__)
|
#define MESOSPHERE_UNUSED(...) ::ams::kern::UnusedImpl(__VA_ARGS__)
|
||||||
|
|
||||||
#ifdef MESOSPHERE_ENABLE_DEBUG_PRINT
|
#ifdef MESOSPHERE_ENABLE_DEBUG_PRINT
|
||||||
#define MESOSPHERE_PANIC(...) do { ::ams::kern::Panic(__FILE__, __LINE__, __VA_ARGS__); } while(0)
|
#define MESOSPHERE_PANIC(...) do { ::ams::kern::Panic(__FILE__, __LINE__, ## __VA_ARGS__); } while(0)
|
||||||
#else
|
#else
|
||||||
#define MESOSPHERE_PANIC(...) do { MESOSPHERE_UNUSED(__VA_ARGS__); ::ams::kern::Panic(); } while(0)
|
#define MESOSPHERE_PANIC(...) do { MESOSPHERE_UNUSED(__VA_ARGS__); ::ams::kern::Panic(); } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -150,6 +150,15 @@ namespace ams::kern::arch::arm64 {
|
|||||||
HandleUserException(context, esr, far, afsr0, afsr1, data);
|
HandleUserException(context, esr, far, afsr0, afsr1, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
MESOSPHERE_LOG("Unhandled Exception in Supervisor Mode\n");
|
||||||
|
MESOSPHERE_LOG("Current Process = %s\n", GetCurrentProcess().GetName());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 31; i++) {
|
||||||
|
MESOSPHERE_LOG("X[%02zu] = %016lx\n", i, context->x[i]);
|
||||||
|
}
|
||||||
|
MESOSPHERE_LOG("PC = %016lx\n", context->pc);
|
||||||
|
MESOSPHERE_LOG("SP = %016lx\n", context->sp);
|
||||||
|
|
||||||
MESOSPHERE_PANIC("Unhandled Exception in Supervisor Mode\n");
|
MESOSPHERE_PANIC("Unhandled Exception in Supervisor Mode\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -327,4 +327,53 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
while (true) { /* ... */ }
|
while (true) { /* ... */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* User access. */
|
||||||
|
void KSystemControl::CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||||
|
/* Get the function id for the current call. */
|
||||||
|
u64 function_id = args->r[0];
|
||||||
|
|
||||||
|
MESOSPHERE_LOG("CallSecureMonitor(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx);\n", args->r[0], args->r[1], args->r[2], args->r[3], args->r[4], args->r[5], args->r[6], args->r[7]);
|
||||||
|
|
||||||
|
/* We'll need to map in pages if arguments are pointers. Prepare page groups to do so. */
|
||||||
|
auto &page_table = GetCurrentProcess().GetPageTable();
|
||||||
|
auto *bim = page_table.GetBlockInfoManager();
|
||||||
|
|
||||||
|
constexpr size_t MaxMappedRegisters = 7;
|
||||||
|
std::array<KPageGroup, MaxMappedRegisters> page_groups = { KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), KPageGroup(bim), };
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MaxMappedRegisters; i++) {
|
||||||
|
const size_t reg_id = i + 1;
|
||||||
|
if (function_id & (1ul << (8 + reg_id))) {
|
||||||
|
/* Create and open a new page group for the address. */
|
||||||
|
KVirtualAddress virt_addr = args->r[reg_id];
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(page_table.MakeAndOpenPageGroup(std::addressof(page_groups[i]), util::AlignDown(GetInteger(virt_addr), PageSize), 1, KMemoryState_None, KMemoryState_None, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_None, KMemoryAttribute_None))) {
|
||||||
|
/* Translate the virtual address to a physical address. */
|
||||||
|
const auto it = page_groups[i].begin();
|
||||||
|
MESOSPHERE_ASSERT(it != page_groups[i].end());
|
||||||
|
MESOSPHERE_ASSERT(it->GetNumPages() == 1);
|
||||||
|
|
||||||
|
KPhysicalAddress phys_addr = page_table.GetHeapPhysicalAddress(it->GetAddress());
|
||||||
|
|
||||||
|
args->r[reg_id] = GetInteger(phys_addr) | (GetInteger(virt_addr) & (PageSize - 1));
|
||||||
|
MESOSPHERE_LOG("Mapped arg %zu\n", reg_id);
|
||||||
|
} else {
|
||||||
|
/* If we couldn't map, we should clear the address. */
|
||||||
|
MESOSPHERE_LOG("Failed to map arg %zu\n", reg_id);
|
||||||
|
args->r[reg_id] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke the secure monitor. */
|
||||||
|
smc::CallSecureMonitorFromUser(args);
|
||||||
|
|
||||||
|
MESOSPHERE_LOG("Secure Monitor Returned: (%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx);\n", args->r[0], args->r[1], args->r[2], args->r[3], args->r[4], args->r[5], args->r[6], args->r[7]);
|
||||||
|
|
||||||
|
/* Make sure that we close any pages that we opened. */
|
||||||
|
for (size_t i = 0; i < MaxMappedRegisters; i++) {
|
||||||
|
page_groups[i].Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,42 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
args.x[7] = x7;
|
args.x[7] = x7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallUserSecureMonitorFunction(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||||
|
/* Load arguments into registers. */
|
||||||
|
register u64 x0 asm("x0") = args->r[0];
|
||||||
|
register u64 x1 asm("x1") = args->r[1];
|
||||||
|
register u64 x2 asm("x2") = args->r[2];
|
||||||
|
register u64 x3 asm("x3") = args->r[3];
|
||||||
|
register u64 x4 asm("x4") = args->r[4];
|
||||||
|
register u64 x5 asm("x5") = args->r[5];
|
||||||
|
register u64 x6 asm("x6") = args->r[6];
|
||||||
|
register u64 x7 asm("x7") = args->r[7];
|
||||||
|
|
||||||
|
/* Actually make the call. */
|
||||||
|
{
|
||||||
|
/* Disable interrupts while making the call. */
|
||||||
|
KScopedInterruptDisable intr_disable;
|
||||||
|
__asm__ __volatile__("smc #0"
|
||||||
|
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||||
|
:
|
||||||
|
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Restore the CoreLocalRegion into X18. */
|
||||||
|
cpu::SetCoreLocalRegionAddress(cpu::GetTpidrEl1());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store arguments to output. */
|
||||||
|
args->r[0] = x0;
|
||||||
|
args->r[1] = x1;
|
||||||
|
args->r[2] = x2;
|
||||||
|
args->r[3] = x3;
|
||||||
|
args->r[4] = x4;
|
||||||
|
args->r[5] = x5;
|
||||||
|
args->r[6] = x6;
|
||||||
|
args->r[7] = x7;
|
||||||
|
}
|
||||||
|
|
||||||
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
||||||
/* Load arguments into registers. */
|
/* Load arguments into registers. */
|
||||||
register u64 x0 asm("x0") = args.x[0];
|
register u64 x0 asm("x0") = args.x[0];
|
||||||
@@ -188,4 +224,8 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
while (true) { /* ... */ }
|
while (true) { /* ... */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||||
|
CallUserSecureMonitorFunction(args);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -91,6 +91,8 @@ namespace ams::kern::board::nintendo::nx::smc {
|
|||||||
|
|
||||||
void NORETURN Panic(u32 color);
|
void NORETURN Panic(u32 color);
|
||||||
|
|
||||||
|
void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);
|
||||||
|
|
||||||
namespace init {
|
namespace init {
|
||||||
|
|
||||||
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
|
||||||
|
|||||||
46
libraries/libmesosphere/source/kern_k_client_port.cpp
Normal file
46
libraries/libmesosphere/source/kern_k_client_port.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
void KClientPort::Initialize(KPort *parent, s32 max_sessions) {
|
||||||
|
/* Set member variables. */
|
||||||
|
this->num_sessions = 0;
|
||||||
|
this->peak_sessions = 0;
|
||||||
|
this->parent = parent;
|
||||||
|
this->max_sessions = max_sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KClientPort::IsLight() const {
|
||||||
|
return this->GetParent()->IsLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KClientPort::Destroy() {
|
||||||
|
/* Note with our parent that we're closed. */
|
||||||
|
this->parent->OnClientClosed();
|
||||||
|
|
||||||
|
/* Close our reference to our parent. */
|
||||||
|
this->parent->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KClientPort::IsSignaled() const {
|
||||||
|
/* TODO: Check preconditions later. */
|
||||||
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
return this->num_sessions < this->max_sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
107
libraries/libmesosphere/source/kern_k_object_name.cpp
Normal file
107
libraries/libmesosphere/source/kern_k_object_name.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* TODO: C++20 constinit */
|
||||||
|
KLightLock g_object_list_lock;
|
||||||
|
KObjectName::List g_object_list;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void KObjectName::Initialize(KAutoObject *obj, const char *name) {
|
||||||
|
/* Set member variables. */
|
||||||
|
this->object = obj;
|
||||||
|
std::strncpy(this->name, name, sizeof(this->name));
|
||||||
|
this->name[sizeof(this->name) - 1] = '\x00';
|
||||||
|
|
||||||
|
/* Open a reference to the object we hold. */
|
||||||
|
this->object->Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KObjectName::MatchesName(const char *name) const {
|
||||||
|
return std::strncmp(this->name, name, sizeof(this->name)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KObjectName::NewFromName(KAutoObject *obj, const char *name) {
|
||||||
|
/* Create a new object name. */
|
||||||
|
KObjectName *new_name = KObjectName::Allocate();
|
||||||
|
R_UNLESS(new_name != nullptr, svc::ResultOutOfResource());
|
||||||
|
|
||||||
|
/* Initialize the new name. */
|
||||||
|
new_name->Initialize(obj, name);
|
||||||
|
|
||||||
|
/* Check if there's an existing name. */
|
||||||
|
{
|
||||||
|
/* Ensure we have exclusive access to the global list. */
|
||||||
|
KScopedLightLock lk(g_object_list_lock);
|
||||||
|
|
||||||
|
/* If the object doesn't exist, put it into the list. */
|
||||||
|
KScopedAutoObject existing_object = FindImpl(name);
|
||||||
|
if (existing_object.IsNull()) {
|
||||||
|
g_object_list.push_back(*new_name);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The object already exists, which is an error condition. Perform cleanup. */
|
||||||
|
obj->Close();
|
||||||
|
KObjectName::Free(new_name);
|
||||||
|
return svc::ResultInvalidState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result KObjectName::Delete(KAutoObject *obj, const char *compare_name) {
|
||||||
|
/* Ensure we have exclusive access to the global list. */
|
||||||
|
KScopedLightLock lk(g_object_list_lock);
|
||||||
|
|
||||||
|
/* Find a matching entry in the list, and delete it. */
|
||||||
|
for (auto &name : g_object_list) {
|
||||||
|
if (name.MatchesName(compare_name) && obj == name.GetObject()) {
|
||||||
|
/* We found a match, clean up its resources. */
|
||||||
|
obj->Close();
|
||||||
|
g_object_list.erase(g_object_list.iterator_to(name));
|
||||||
|
KObjectName::Free(std::addressof(name));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find the object in the list. */
|
||||||
|
return svc::ResultNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
KScopedAutoObject<KAutoObject> KObjectName::Find(const char *name) {
|
||||||
|
/* Ensure we have exclusive access to the global list. */
|
||||||
|
KScopedLightLock lk(g_object_list_lock);
|
||||||
|
|
||||||
|
return FindImpl(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(const char *compare_name) {
|
||||||
|
/* Try to find a matching object in the global list. */
|
||||||
|
for (const auto &name : g_object_list) {
|
||||||
|
if (name.MatchesName(compare_name)) {
|
||||||
|
return name.GetObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There's no matching entry in the list. */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1020,4 +1020,27 @@ namespace ams::kern {
|
|||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
|
||||||
|
/* Ensure that the page group isn't null. */
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
/* Make sure that the region we're mapping is valid for the table. */
|
||||||
|
const size_t size = num_pages * PageSize;
|
||||||
|
R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory());
|
||||||
|
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
|
||||||
|
/* Check if state allows us to create the group. */
|
||||||
|
R_TRY(this->CheckMemoryState(address, size, state_mask | KMemoryState_FlagReferenceCounted, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr));
|
||||||
|
|
||||||
|
/* Create a new page group for the region. */
|
||||||
|
R_TRY(this->MakePageGroup(*out, address, num_pages));
|
||||||
|
|
||||||
|
/* Open a new reference to the pages in the group. */
|
||||||
|
out->Open();
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
44
libraries/libmesosphere/source/kern_k_port.cpp
Normal file
44
libraries/libmesosphere/source/kern_k_port.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) {
|
||||||
|
/* Open a new reference count to the initialized port. */
|
||||||
|
this->Open();
|
||||||
|
|
||||||
|
/* Create and initialize our server/client pair. */
|
||||||
|
KAutoObject::Create(std::addressof(this->server));
|
||||||
|
KAutoObject::Create(std::addressof(this->client));
|
||||||
|
this->server.Initialize(this);
|
||||||
|
this->client.Initialize(this, max_sessions);
|
||||||
|
|
||||||
|
/* Set our member variables. */
|
||||||
|
this->is_light = is_light;
|
||||||
|
this->name = name;
|
||||||
|
this->state = State::Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPort::OnClientClosed() {
|
||||||
|
MESOSPHERE_UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KPort::OnServerClosed() {
|
||||||
|
MESOSPHERE_UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
96
libraries/libmesosphere/source/kern_k_server_port.cpp
Normal file
96
libraries/libmesosphere/source/kern_k_server_port.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
void KServerPort::Initialize(KPort *parent) {
|
||||||
|
/* Set member variables. */
|
||||||
|
this->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KServerPort::IsLight() const {
|
||||||
|
return this->GetParent()->IsLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KServerPort::CleanupSessions() {
|
||||||
|
/* Ensure our preconditions are met. */
|
||||||
|
MESOSPHERE_ASSERT(this->IsLight() || this->session_list.empty());
|
||||||
|
MESOSPHERE_ASSERT(!this->IsLight() || this->light_session_list.empty());
|
||||||
|
|
||||||
|
/* Cleanup the session list. */
|
||||||
|
while (true) {
|
||||||
|
/* Get the last session in the list */
|
||||||
|
KServerSession *session = nullptr;
|
||||||
|
{
|
||||||
|
KScopedSchedulerLock sl;
|
||||||
|
while (!this->session_list.empty()) {
|
||||||
|
session = std::addressof(this->session_list.front());
|
||||||
|
this->session_list.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the session. */
|
||||||
|
if (session != nullptr) {
|
||||||
|
session->Close();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup the light session list. */
|
||||||
|
while (true) {
|
||||||
|
/* Get the last session in the list */
|
||||||
|
KLightServerSession *session = nullptr;
|
||||||
|
{
|
||||||
|
KScopedSchedulerLock sl;
|
||||||
|
while (!this->light_session_list.empty()) {
|
||||||
|
session = std::addressof(this->light_session_list.front());
|
||||||
|
this->light_session_list.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the session. */
|
||||||
|
if (session != nullptr) {
|
||||||
|
session->Close();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KServerPort::Destroy() {
|
||||||
|
/* Note with our parent that we're closed. */
|
||||||
|
this->parent->OnClientClosed();
|
||||||
|
|
||||||
|
/* Perform necessary cleanup of our session lists. */
|
||||||
|
this->CleanupSessions();
|
||||||
|
|
||||||
|
/* Close our reference to our parent. */
|
||||||
|
this->parent->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KServerPort::IsSignaled() const {
|
||||||
|
/* TODO: Check preconditions later. */
|
||||||
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
if (this->IsLight()) {
|
||||||
|
return !this->light_session_list.empty();
|
||||||
|
} else {
|
||||||
|
return this->session_list.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
libraries/libmesosphere/source/libc/arch/arm64/asmdefs.h
Normal file
31
libraries/libmesosphere/source/libc/arch/arm64/asmdefs.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Macros for asm code.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019, Arm Limited.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASMDEFS_H
|
||||||
|
#define _ASMDEFS_H
|
||||||
|
|
||||||
|
#define ENTRY_ALIGN(name, alignment) \
|
||||||
|
.global name; \
|
||||||
|
.type name,%function; \
|
||||||
|
.align alignment; \
|
||||||
|
name: \
|
||||||
|
.cfi_startproc;
|
||||||
|
|
||||||
|
#define ENTRY(name) ENTRY_ALIGN(name, 6)
|
||||||
|
|
||||||
|
#define ENTRY_ALIAS(name) \
|
||||||
|
.global name; \
|
||||||
|
.type name,%function; \
|
||||||
|
name:
|
||||||
|
|
||||||
|
#define END(name) \
|
||||||
|
.cfi_endproc; \
|
||||||
|
.size name, .-name;
|
||||||
|
|
||||||
|
#define L(l) .L ## l
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/* memcmp - compare memory
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Arm Limited.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Assumptions:
|
||||||
|
*
|
||||||
|
* ARMv8-a, AArch64, unaligned accesses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asmdefs.h"
|
||||||
|
|
||||||
|
/* Parameters and result. */
|
||||||
|
#define src1 x0
|
||||||
|
#define src2 x1
|
||||||
|
#define limit x2
|
||||||
|
#define result w0
|
||||||
|
|
||||||
|
/* Internal variables. */
|
||||||
|
#define data1 x3
|
||||||
|
#define data1w w3
|
||||||
|
#define data1h x4
|
||||||
|
#define data2 x5
|
||||||
|
#define data2w w5
|
||||||
|
#define data2h x6
|
||||||
|
#define tmp1 x7
|
||||||
|
#define tmp2 x8
|
||||||
|
|
||||||
|
ENTRY (memcmp)
|
||||||
|
subs limit, limit, 8
|
||||||
|
b.lo L(less8)
|
||||||
|
|
||||||
|
ldr data1, [src1], 8
|
||||||
|
ldr data2, [src2], 8
|
||||||
|
cmp data1, data2
|
||||||
|
b.ne L(return)
|
||||||
|
|
||||||
|
subs limit, limit, 8
|
||||||
|
b.gt L(more16)
|
||||||
|
|
||||||
|
ldr data1, [src1, limit]
|
||||||
|
ldr data2, [src2, limit]
|
||||||
|
b L(return)
|
||||||
|
|
||||||
|
L(more16):
|
||||||
|
ldr data1, [src1], 8
|
||||||
|
ldr data2, [src2], 8
|
||||||
|
cmp data1, data2
|
||||||
|
bne L(return)
|
||||||
|
|
||||||
|
/* Jump directly to comparing the last 16 bytes for 32 byte (or less)
|
||||||
|
strings. */
|
||||||
|
subs limit, limit, 16
|
||||||
|
b.ls L(last_bytes)
|
||||||
|
|
||||||
|
/* We overlap loads between 0-32 bytes at either side of SRC1 when we
|
||||||
|
try to align, so limit it only to strings larger than 128 bytes. */
|
||||||
|
cmp limit, 96
|
||||||
|
b.ls L(loop16)
|
||||||
|
|
||||||
|
/* Align src1 and adjust src2 with bytes not yet done. */
|
||||||
|
and tmp1, src1, 15
|
||||||
|
add limit, limit, tmp1
|
||||||
|
sub src1, src1, tmp1
|
||||||
|
sub src2, src2, tmp1
|
||||||
|
|
||||||
|
/* Loop performing 16 bytes per iteration using aligned src1.
|
||||||
|
Limit is pre-decremented by 16 and must be larger than zero.
|
||||||
|
Exit if <= 16 bytes left to do or if the data is not equal. */
|
||||||
|
.p2align 4
|
||||||
|
L(loop16):
|
||||||
|
ldp data1, data1h, [src1], 16
|
||||||
|
ldp data2, data2h, [src2], 16
|
||||||
|
subs limit, limit, 16
|
||||||
|
ccmp data1, data2, 0, hi
|
||||||
|
ccmp data1h, data2h, 0, eq
|
||||||
|
b.eq L(loop16)
|
||||||
|
|
||||||
|
cmp data1, data2
|
||||||
|
bne L(return)
|
||||||
|
mov data1, data1h
|
||||||
|
mov data2, data2h
|
||||||
|
cmp data1, data2
|
||||||
|
bne L(return)
|
||||||
|
|
||||||
|
/* Compare last 1-16 bytes using unaligned access. */
|
||||||
|
L(last_bytes):
|
||||||
|
add src1, src1, limit
|
||||||
|
add src2, src2, limit
|
||||||
|
ldp data1, data1h, [src1]
|
||||||
|
ldp data2, data2h, [src2]
|
||||||
|
cmp data1, data2
|
||||||
|
bne L(return)
|
||||||
|
mov data1, data1h
|
||||||
|
mov data2, data2h
|
||||||
|
cmp data1, data2
|
||||||
|
|
||||||
|
/* Compare data bytes and set return value to 0, -1 or 1. */
|
||||||
|
L(return):
|
||||||
|
#ifndef __AARCH64EB__
|
||||||
|
rev data1, data1
|
||||||
|
rev data2, data2
|
||||||
|
#endif
|
||||||
|
cmp data1, data2
|
||||||
|
L(ret_eq):
|
||||||
|
cset result, ne
|
||||||
|
cneg result, result, lo
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
/* Compare up to 8 bytes. Limit is [-8..-1]. */
|
||||||
|
L(less8):
|
||||||
|
adds limit, limit, 4
|
||||||
|
b.lo L(less4)
|
||||||
|
ldr data1w, [src1], 4
|
||||||
|
ldr data2w, [src2], 4
|
||||||
|
cmp data1w, data2w
|
||||||
|
b.ne L(return)
|
||||||
|
sub limit, limit, 4
|
||||||
|
L(less4):
|
||||||
|
adds limit, limit, 4
|
||||||
|
beq L(ret_eq)
|
||||||
|
L(byte_loop):
|
||||||
|
ldrb data1w, [src1], 1
|
||||||
|
ldrb data2w, [src2], 1
|
||||||
|
subs limit, limit, 1
|
||||||
|
ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
|
||||||
|
b.eq L(byte_loop)
|
||||||
|
sub result, data1w, data2w
|
||||||
|
ret
|
||||||
|
|
||||||
|
END (memcmp)
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* memcpy - copy memory area
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012-2020, Arm Limited.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Assumptions:
|
||||||
|
*
|
||||||
|
* ARMv8-a, AArch64, unaligned accesses.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asmdefs.h"
|
||||||
|
|
||||||
|
#define dstin x0
|
||||||
|
#define src x1
|
||||||
|
#define count x2
|
||||||
|
#define dst x3
|
||||||
|
#define srcend x4
|
||||||
|
#define dstend x5
|
||||||
|
#define A_l x6
|
||||||
|
#define A_lw w6
|
||||||
|
#define A_h x7
|
||||||
|
#define B_l x8
|
||||||
|
#define B_lw w8
|
||||||
|
#define B_h x9
|
||||||
|
#define C_l x10
|
||||||
|
#define C_lw w10
|
||||||
|
#define C_h x11
|
||||||
|
#define D_l x12
|
||||||
|
#define D_h x13
|
||||||
|
#define E_l x14
|
||||||
|
#define E_h x15
|
||||||
|
#define F_l x16
|
||||||
|
#define F_h x17
|
||||||
|
#define G_l count
|
||||||
|
#define G_h dst
|
||||||
|
#define H_l src
|
||||||
|
#define H_h srcend
|
||||||
|
#define tmp1 x14
|
||||||
|
|
||||||
|
/* This implementation handles overlaps and supports both memcpy and memmove
|
||||||
|
from a single entry point. It uses unaligned accesses and branchless
|
||||||
|
sequences to keep the code small, simple and improve performance.
|
||||||
|
|
||||||
|
Copies are split into 3 main cases: small copies of up to 32 bytes, medium
|
||||||
|
copies of up to 128 bytes, and large copies. The overhead of the overlap
|
||||||
|
check is negligible since it is only required for large copies.
|
||||||
|
|
||||||
|
Large copies use a software pipelined loop processing 64 bytes per iteration.
|
||||||
|
The destination pointer is 16-byte aligned to minimize unaligned accesses.
|
||||||
|
The loop tail is handled by always copying 64 bytes from the end.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ENTRY (memcpy)
|
||||||
|
ENTRY_ALIAS (memmove)
|
||||||
|
add srcend, src, count
|
||||||
|
add dstend, dstin, count
|
||||||
|
cmp count, 128
|
||||||
|
b.hi L(copy_long)
|
||||||
|
cmp count, 32
|
||||||
|
b.hi L(copy32_128)
|
||||||
|
|
||||||
|
/* Small copies: 0..32 bytes. */
|
||||||
|
cmp count, 16
|
||||||
|
b.lo L(copy16)
|
||||||
|
ldp A_l, A_h, [src]
|
||||||
|
ldp D_l, D_h, [srcend, -16]
|
||||||
|
stp A_l, A_h, [dstin]
|
||||||
|
stp D_l, D_h, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* Copy 8-15 bytes. */
|
||||||
|
L(copy16):
|
||||||
|
tbz count, 3, L(copy8)
|
||||||
|
ldr A_l, [src]
|
||||||
|
ldr A_h, [srcend, -8]
|
||||||
|
str A_l, [dstin]
|
||||||
|
str A_h, [dstend, -8]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 3
|
||||||
|
/* Copy 4-7 bytes. */
|
||||||
|
L(copy8):
|
||||||
|
tbz count, 2, L(copy4)
|
||||||
|
ldr A_lw, [src]
|
||||||
|
ldr B_lw, [srcend, -4]
|
||||||
|
str A_lw, [dstin]
|
||||||
|
str B_lw, [dstend, -4]
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* Copy 0..3 bytes using a branchless sequence. */
|
||||||
|
L(copy4):
|
||||||
|
cbz count, L(copy0)
|
||||||
|
lsr tmp1, count, 1
|
||||||
|
ldrb A_lw, [src]
|
||||||
|
ldrb C_lw, [srcend, -1]
|
||||||
|
ldrb B_lw, [src, tmp1]
|
||||||
|
strb A_lw, [dstin]
|
||||||
|
strb B_lw, [dstin, tmp1]
|
||||||
|
strb C_lw, [dstend, -1]
|
||||||
|
L(copy0):
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
/* Medium copies: 33..128 bytes. */
|
||||||
|
L(copy32_128):
|
||||||
|
ldp A_l, A_h, [src]
|
||||||
|
ldp B_l, B_h, [src, 16]
|
||||||
|
ldp C_l, C_h, [srcend, -32]
|
||||||
|
ldp D_l, D_h, [srcend, -16]
|
||||||
|
cmp count, 64
|
||||||
|
b.hi L(copy128)
|
||||||
|
stp A_l, A_h, [dstin]
|
||||||
|
stp B_l, B_h, [dstin, 16]
|
||||||
|
stp C_l, C_h, [dstend, -32]
|
||||||
|
stp D_l, D_h, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
/* Copy 65..128 bytes. */
|
||||||
|
L(copy128):
|
||||||
|
ldp E_l, E_h, [src, 32]
|
||||||
|
ldp F_l, F_h, [src, 48]
|
||||||
|
cmp count, 96
|
||||||
|
b.ls L(copy96)
|
||||||
|
ldp G_l, G_h, [srcend, -64]
|
||||||
|
ldp H_l, H_h, [srcend, -48]
|
||||||
|
stp G_l, G_h, [dstend, -64]
|
||||||
|
stp H_l, H_h, [dstend, -48]
|
||||||
|
L(copy96):
|
||||||
|
stp A_l, A_h, [dstin]
|
||||||
|
stp B_l, B_h, [dstin, 16]
|
||||||
|
stp E_l, E_h, [dstin, 32]
|
||||||
|
stp F_l, F_h, [dstin, 48]
|
||||||
|
stp C_l, C_h, [dstend, -32]
|
||||||
|
stp D_l, D_h, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
/* Copy more than 128 bytes. */
|
||||||
|
L(copy_long):
|
||||||
|
/* Use backwards copy if there is an overlap. */
|
||||||
|
sub tmp1, dstin, src
|
||||||
|
cbz tmp1, L(copy0)
|
||||||
|
cmp tmp1, count
|
||||||
|
b.lo L(copy_long_backwards)
|
||||||
|
|
||||||
|
/* Copy 16 bytes and then align dst to 16-byte alignment. */
|
||||||
|
|
||||||
|
ldp D_l, D_h, [src]
|
||||||
|
and tmp1, dstin, 15
|
||||||
|
bic dst, dstin, 15
|
||||||
|
sub src, src, tmp1
|
||||||
|
add count, count, tmp1 /* Count is now 16 too large. */
|
||||||
|
ldp A_l, A_h, [src, 16]
|
||||||
|
stp D_l, D_h, [dstin]
|
||||||
|
ldp B_l, B_h, [src, 32]
|
||||||
|
ldp C_l, C_h, [src, 48]
|
||||||
|
ldp D_l, D_h, [src, 64]!
|
||||||
|
subs count, count, 128 + 16 /* Test and readjust count. */
|
||||||
|
b.ls L(copy64_from_end)
|
||||||
|
|
||||||
|
L(loop64):
|
||||||
|
stp A_l, A_h, [dst, 16]
|
||||||
|
ldp A_l, A_h, [src, 16]
|
||||||
|
stp B_l, B_h, [dst, 32]
|
||||||
|
ldp B_l, B_h, [src, 32]
|
||||||
|
stp C_l, C_h, [dst, 48]
|
||||||
|
ldp C_l, C_h, [src, 48]
|
||||||
|
stp D_l, D_h, [dst, 64]!
|
||||||
|
ldp D_l, D_h, [src, 64]!
|
||||||
|
subs count, count, 64
|
||||||
|
b.hi L(loop64)
|
||||||
|
|
||||||
|
/* Write the last iteration and copy 64 bytes from the end. */
|
||||||
|
L(copy64_from_end):
|
||||||
|
ldp E_l, E_h, [srcend, -64]
|
||||||
|
stp A_l, A_h, [dst, 16]
|
||||||
|
ldp A_l, A_h, [srcend, -48]
|
||||||
|
stp B_l, B_h, [dst, 32]
|
||||||
|
ldp B_l, B_h, [srcend, -32]
|
||||||
|
stp C_l, C_h, [dst, 48]
|
||||||
|
ldp C_l, C_h, [srcend, -16]
|
||||||
|
stp D_l, D_h, [dst, 64]
|
||||||
|
stp E_l, E_h, [dstend, -64]
|
||||||
|
stp A_l, A_h, [dstend, -48]
|
||||||
|
stp B_l, B_h, [dstend, -32]
|
||||||
|
stp C_l, C_h, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
|
||||||
|
/* Large backwards copy for overlapping copies.
|
||||||
|
Copy 16 bytes and then align dst to 16-byte alignment. */
|
||||||
|
L(copy_long_backwards):
|
||||||
|
ldp D_l, D_h, [srcend, -16]
|
||||||
|
and tmp1, dstend, 15
|
||||||
|
sub srcend, srcend, tmp1
|
||||||
|
sub count, count, tmp1
|
||||||
|
ldp A_l, A_h, [srcend, -16]
|
||||||
|
stp D_l, D_h, [dstend, -16]
|
||||||
|
ldp B_l, B_h, [srcend, -32]
|
||||||
|
ldp C_l, C_h, [srcend, -48]
|
||||||
|
ldp D_l, D_h, [srcend, -64]!
|
||||||
|
sub dstend, dstend, tmp1
|
||||||
|
subs count, count, 128
|
||||||
|
b.ls L(copy64_from_start)
|
||||||
|
|
||||||
|
L(loop64_backwards):
|
||||||
|
stp A_l, A_h, [dstend, -16]
|
||||||
|
ldp A_l, A_h, [srcend, -16]
|
||||||
|
stp B_l, B_h, [dstend, -32]
|
||||||
|
ldp B_l, B_h, [srcend, -32]
|
||||||
|
stp C_l, C_h, [dstend, -48]
|
||||||
|
ldp C_l, C_h, [srcend, -48]
|
||||||
|
stp D_l, D_h, [dstend, -64]!
|
||||||
|
ldp D_l, D_h, [srcend, -64]!
|
||||||
|
subs count, count, 64
|
||||||
|
b.hi L(loop64_backwards)
|
||||||
|
|
||||||
|
/* Write the last iteration and copy 64 bytes from the start. */
|
||||||
|
L(copy64_from_start):
|
||||||
|
ldp G_l, G_h, [src, 48]
|
||||||
|
stp A_l, A_h, [dstend, -16]
|
||||||
|
ldp A_l, A_h, [src, 32]
|
||||||
|
stp B_l, B_h, [dstend, -32]
|
||||||
|
ldp B_l, B_h, [src, 16]
|
||||||
|
stp C_l, C_h, [dstend, -48]
|
||||||
|
ldp C_l, C_h, [src]
|
||||||
|
stp D_l, D_h, [dstend, -64]
|
||||||
|
stp G_l, G_h, [dstin, 48]
|
||||||
|
stp A_l, A_h, [dstin, 32]
|
||||||
|
stp B_l, B_h, [dstin, 16]
|
||||||
|
stp C_l, C_h, [dstin]
|
||||||
|
ret
|
||||||
|
|
||||||
|
END (memcpy)
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* memset - fill memory with a constant byte
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012-2020, Arm Limited.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Assumptions:
|
||||||
|
*
|
||||||
|
* ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asmdefs.h"
|
||||||
|
|
||||||
|
#define DC_ZVA_THRESHOLD 512
|
||||||
|
|
||||||
|
#define dstin x0
|
||||||
|
#define val x1
|
||||||
|
#define valw w1
|
||||||
|
#define count x2
|
||||||
|
#define dst x3
|
||||||
|
#define dstend x4
|
||||||
|
#define zva_val x5
|
||||||
|
|
||||||
|
ENTRY (memset)
|
||||||
|
|
||||||
|
bfi valw, valw, 8, 8
|
||||||
|
bfi valw, valw, 16, 16
|
||||||
|
bfi val, val, 32, 32
|
||||||
|
|
||||||
|
add dstend, dstin, count
|
||||||
|
|
||||||
|
cmp count, 96
|
||||||
|
b.hi L(set_long)
|
||||||
|
cmp count, 16
|
||||||
|
b.hs L(set_medium)
|
||||||
|
|
||||||
|
/* Set 0..15 bytes. */
|
||||||
|
tbz count, 3, 1f
|
||||||
|
str val, [dstin]
|
||||||
|
str val, [dstend, -8]
|
||||||
|
ret
|
||||||
|
1: tbz count, 2, 2f
|
||||||
|
str valw, [dstin]
|
||||||
|
str valw, [dstend, -4]
|
||||||
|
ret
|
||||||
|
2: cbz count, 3f
|
||||||
|
strb valw, [dstin]
|
||||||
|
tbz count, 1, 3f
|
||||||
|
strh valw, [dstend, -2]
|
||||||
|
3: ret
|
||||||
|
|
||||||
|
/* Set 16..96 bytes. */
|
||||||
|
.p2align 4
|
||||||
|
L(set_medium):
|
||||||
|
stp val, val, [dstin]
|
||||||
|
tbnz count, 6, L(set96)
|
||||||
|
stp val, val, [dstend, -16]
|
||||||
|
tbz count, 5, 1f
|
||||||
|
stp val, val, [dstin, 16]
|
||||||
|
stp val, val, [dstend, -32]
|
||||||
|
1: ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
/* Set 64..96 bytes. Write 64 bytes from the start and
|
||||||
|
32 bytes from the end. */
|
||||||
|
L(set96):
|
||||||
|
stp val, val, [dstin, 16]
|
||||||
|
stp val, val, [dstin, 32]
|
||||||
|
stp val, val, [dstin, 48]
|
||||||
|
stp val, val, [dstend, -32]
|
||||||
|
stp val, val, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
L(set_long):
|
||||||
|
stp val, val, [dstin]
|
||||||
|
bic dst, dstin, 15
|
||||||
|
#if DC_ZVA_THRESHOLD
|
||||||
|
cmp count, DC_ZVA_THRESHOLD
|
||||||
|
ccmp val, 0, 0, cs
|
||||||
|
b.eq L(zva_64)
|
||||||
|
#endif
|
||||||
|
/* Small-size or non-zero memset does not use DC ZVA. */
|
||||||
|
sub count, dstend, dst
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust count and bias for loop. By substracting extra 1 from count,
|
||||||
|
* it is easy to use tbz instruction to check whether loop tailing
|
||||||
|
* count is less than 33 bytes, so as to bypass 2 unneccesary stps.
|
||||||
|
*/
|
||||||
|
sub count, count, 64+16+1
|
||||||
|
|
||||||
|
#if DC_ZVA_THRESHOLD
|
||||||
|
/* Align loop on 16-byte boundary, this might be friendly to i-cache. */
|
||||||
|
nop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
1: stp val, val, [dst, 16]
|
||||||
|
stp val, val, [dst, 32]
|
||||||
|
stp val, val, [dst, 48]
|
||||||
|
stp val, val, [dst, 64]!
|
||||||
|
subs count, count, 64
|
||||||
|
b.hs 1b
|
||||||
|
|
||||||
|
tbz count, 5, 1f /* Remaining count is less than 33 bytes? */
|
||||||
|
stp val, val, [dst, 16]
|
||||||
|
stp val, val, [dst, 32]
|
||||||
|
1: stp val, val, [dstend, -32]
|
||||||
|
stp val, val, [dstend, -16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
#if DC_ZVA_THRESHOLD
|
||||||
|
.p2align 4
|
||||||
|
L(zva_64):
|
||||||
|
stp val, val, [dst, 16]
|
||||||
|
stp val, val, [dst, 32]
|
||||||
|
stp val, val, [dst, 48]
|
||||||
|
bic dst, dst, 63
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Previous memory writes might cross cache line boundary, and cause
|
||||||
|
* cache line partially dirty. Zeroing this kind of cache line using
|
||||||
|
* DC ZVA will incur extra cost, for it requires loading untouched
|
||||||
|
* part of the line from memory before zeoring.
|
||||||
|
*
|
||||||
|
* So, write the first 64 byte aligned block using stp to force
|
||||||
|
* fully dirty cache line.
|
||||||
|
*/
|
||||||
|
stp val, val, [dst, 64]
|
||||||
|
stp val, val, [dst, 80]
|
||||||
|
stp val, val, [dst, 96]
|
||||||
|
stp val, val, [dst, 112]
|
||||||
|
|
||||||
|
sub count, dstend, dst
|
||||||
|
/*
|
||||||
|
* Adjust count and bias for loop. By substracting extra 1 from count,
|
||||||
|
* it is easy to use tbz instruction to check whether loop tailing
|
||||||
|
* count is less than 33 bytes, so as to bypass 2 unneccesary stps.
|
||||||
|
*/
|
||||||
|
sub count, count, 128+64+64+1
|
||||||
|
add dst, dst, 128
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* DC ZVA sets 64 bytes each time. */
|
||||||
|
1: dc zva, dst
|
||||||
|
add dst, dst, 64
|
||||||
|
subs count, count, 64
|
||||||
|
b.hs 1b
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the last 64 byte aligned block using stp to force fully
|
||||||
|
* dirty cache line.
|
||||||
|
*/
|
||||||
|
stp val, val, [dst, 0]
|
||||||
|
stp val, val, [dst, 16]
|
||||||
|
stp val, val, [dst, 32]
|
||||||
|
stp val, val, [dst, 48]
|
||||||
|
|
||||||
|
tbz count, 5, 1f /* Remaining count is less than 33 bytes? */
|
||||||
|
stp val, val, [dst, 64]
|
||||||
|
stp val, val, [dst, 80]
|
||||||
|
1: stp val, val, [dstend, -32]
|
||||||
|
stp val, val, [dstend, -16]
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
END (memset)
|
||||||
@@ -61,6 +61,7 @@ QUICKREF
|
|||||||
/*SUPPRESS 20*/
|
/*SUPPRESS 20*/
|
||||||
void *
|
void *
|
||||||
//__inhibit_loop_to_libcall
|
//__inhibit_loop_to_libcall
|
||||||
|
__attribute__((weak))
|
||||||
memmove (void *dst_void,
|
memmove (void *dst_void,
|
||||||
const void *src_void,
|
const void *src_void,
|
||||||
size_t length)
|
size_t length)
|
||||||
@@ -169,6 +170,7 @@ QUICKREF
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
__attribute__((weak))
|
||||||
memcpy (void * dst0,
|
memcpy (void * dst0,
|
||||||
const void * __restrict src0,
|
const void * __restrict src0,
|
||||||
size_t len0)
|
size_t len0)
|
||||||
@@ -259,6 +261,7 @@ QUICKREF
|
|||||||
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
__attribute__((weak))
|
||||||
memset (void *m,
|
memset (void *m,
|
||||||
int c,
|
int c,
|
||||||
size_t n)
|
size_t n)
|
||||||
@@ -357,6 +360,7 @@ QUICKREF
|
|||||||
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
||||||
|
|
||||||
int
|
int
|
||||||
|
__attribute__((weak))
|
||||||
memcmp (const void *m1,
|
memcmp (const void *m1,
|
||||||
const void *m2,
|
const void *m2,
|
||||||
size_t n)
|
size_t n)
|
||||||
@@ -417,6 +421,228 @@ memcmp (const void *m1,
|
|||||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FUNCTION
|
||||||
|
<<strncpy>>---counted copy string
|
||||||
|
INDEX
|
||||||
|
strncpy
|
||||||
|
SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>,
|
||||||
|
size_t <[length]>);
|
||||||
|
DESCRIPTION
|
||||||
|
<<strncpy>> copies not more than <[length]> characters from the
|
||||||
|
the string pointed to by <[src]> (including the terminating
|
||||||
|
null character) to the array pointed to by <[dst]>. If the
|
||||||
|
string pointed to by <[src]> is shorter than <[length]>
|
||||||
|
characters, null characters are appended to the destination
|
||||||
|
array until a total of <[length]> characters have been
|
||||||
|
written.
|
||||||
|
RETURNS
|
||||||
|
This function returns the initial value of <[dst]>.
|
||||||
|
PORTABILITY
|
||||||
|
<<strncpy>> is ANSI C.
|
||||||
|
<<strncpy>> requires no supporting OS subroutines.
|
||||||
|
QUICKREF
|
||||||
|
strncpy ansi pure
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/*SUPPRESS 560*/
|
||||||
|
/*SUPPRESS 530*/
|
||||||
|
|
||||||
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||||
|
#define UNALIGNED(X, Y) \
|
||||||
|
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||||
|
|
||||||
|
#if LONG_MAX == 2147483647L
|
||||||
|
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
|
||||||
|
#else
|
||||||
|
#if LONG_MAX == 9223372036854775807L
|
||||||
|
/* Nonzero if X (a long int) contains a NULL byte. */
|
||||||
|
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
|
||||||
|
#else
|
||||||
|
#error long int is not a 32bit or 64bit type.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DETECTNULL
|
||||||
|
#error long int is not a 32bit or 64bit byte
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef TOO_SMALL
|
||||||
|
#define TOO_SMALL(LEN) ((LEN) < sizeof (long))
|
||||||
|
|
||||||
|
char *
|
||||||
|
strncpy (char *__restrict dst0,
|
||||||
|
const char *__restrict src0,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||||
|
char *dscan;
|
||||||
|
const char *sscan;
|
||||||
|
|
||||||
|
dscan = dst0;
|
||||||
|
sscan = src0;
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
--count;
|
||||||
|
if ((*dscan++ = *sscan++) == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (count-- > 0)
|
||||||
|
*dscan++ = '\0';
|
||||||
|
|
||||||
|
return dst0;
|
||||||
|
#else
|
||||||
|
char *dst = dst0;
|
||||||
|
const char *src = src0;
|
||||||
|
long *aligned_dst;
|
||||||
|
const long *aligned_src;
|
||||||
|
|
||||||
|
/* If SRC and DEST is aligned and count large enough, then copy words. */
|
||||||
|
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
|
||||||
|
{
|
||||||
|
aligned_dst = (long*)dst;
|
||||||
|
aligned_src = (long*)src;
|
||||||
|
|
||||||
|
/* SRC and DEST are both "long int" aligned, try to do "long int"
|
||||||
|
sized copies. */
|
||||||
|
while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
|
||||||
|
{
|
||||||
|
count -= sizeof (long int);
|
||||||
|
*aligned_dst++ = *aligned_src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = (char*)aligned_dst;
|
||||||
|
src = (char*)aligned_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
--count;
|
||||||
|
if ((*dst++ = *src++) == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count-- > 0)
|
||||||
|
*dst++ = '\0';
|
||||||
|
|
||||||
|
return dst0;
|
||||||
|
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FUNCTION
|
||||||
|
<<strncmp>>---character string compare
|
||||||
|
|
||||||
|
INDEX
|
||||||
|
strncmp
|
||||||
|
SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>);
|
||||||
|
DESCRIPTION
|
||||||
|
<<strncmp>> compares up to <[length]> characters
|
||||||
|
from the string at <[a]> to the string at <[b]>.
|
||||||
|
RETURNS
|
||||||
|
If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>,
|
||||||
|
<<strncmp>> returns a number greater than zero. If the two
|
||||||
|
strings are equivalent, <<strncmp>> returns zero. If <<*<[a]>>>
|
||||||
|
sorts lexicographically before <<*<[b]>>>, <<strncmp>> returns a
|
||||||
|
number less than zero.
|
||||||
|
PORTABILITY
|
||||||
|
<<strncmp>> is ANSI C.
|
||||||
|
<<strncmp>> requires no supporting OS subroutines.
|
||||||
|
QUICKREF
|
||||||
|
strncmp ansi pure
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||||
|
#define UNALIGNED(X, Y) \
|
||||||
|
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||||
|
|
||||||
|
/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
|
||||||
|
#if LONG_MAX == 2147483647L
|
||||||
|
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
|
||||||
|
#else
|
||||||
|
#if LONG_MAX == 9223372036854775807L
|
||||||
|
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
|
||||||
|
#else
|
||||||
|
#error long int is not a 32bit or 64bit type.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DETECTNULL
|
||||||
|
#error long int is not a 32bit or 64bit byte
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
strncmp (const char *s1,
|
||||||
|
const char *s2,
|
||||||
|
size_t n)
|
||||||
|
{
|
||||||
|
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (n-- != 0 && *s1 == *s2)
|
||||||
|
{
|
||||||
|
if (n == 0 || *s1 == '\0')
|
||||||
|
break;
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
||||||
|
#else
|
||||||
|
unsigned long *a1;
|
||||||
|
unsigned long *a2;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* If s1 or s2 are unaligned, then compare bytes. */
|
||||||
|
if (!UNALIGNED (s1, s2))
|
||||||
|
{
|
||||||
|
/* If s1 and s2 are word-aligned, compare them a word at a time. */
|
||||||
|
a1 = (unsigned long*)s1;
|
||||||
|
a2 = (unsigned long*)s2;
|
||||||
|
while (n >= sizeof (long) && *a1 == *a2)
|
||||||
|
{
|
||||||
|
n -= sizeof (long);
|
||||||
|
|
||||||
|
/* If we've run out of bytes or hit a null, return zero
|
||||||
|
since we already know *a1 == *a2. */
|
||||||
|
if (n == 0 || DETECTNULL (*a1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
a1++;
|
||||||
|
a2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A difference was detected in last few bytes of s1, so search bytewise */
|
||||||
|
s1 = (char*)a1;
|
||||||
|
s2 = (char*)a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n-- > 0 && *s1 == *s2)
|
||||||
|
{
|
||||||
|
/* If we've run out of bytes or hit a null, return zero
|
||||||
|
since we already know *s1 == *s2. */
|
||||||
|
if (n == 0 || *s1 == '\0')
|
||||||
|
return 0;
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
||||||
|
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
@@ -21,28 +21,112 @@ namespace ams::kern::svc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
Result GetInfo(u64 *out, ams::svc::InfoType info_type, ams::svc::Handle handle, u64 info_subtype) {
|
||||||
|
MESOSPHERE_LOG("GetInfo(%p, %u, %08x, %lu) was called\n", out, static_cast<u32>(info_type), static_cast<u32>(handle), info_subtype);
|
||||||
|
ON_SCOPE_EXIT{ MESOSPHERE_LOG("GetInfo returned %016lx\n", *out); };
|
||||||
|
|
||||||
|
switch (info_type) {
|
||||||
|
case ams::svc::InfoType_AliasRegionAddress:
|
||||||
|
case ams::svc::InfoType_AliasRegionSize:
|
||||||
|
case ams::svc::InfoType_HeapRegionAddress:
|
||||||
|
case ams::svc::InfoType_HeapRegionSize:
|
||||||
|
case ams::svc::InfoType_AslrRegionAddress:
|
||||||
|
case ams::svc::InfoType_AslrRegionSize:
|
||||||
|
case ams::svc::InfoType_StackRegionAddress:
|
||||||
|
case ams::svc::InfoType_StackRegionSize:
|
||||||
|
{
|
||||||
|
/* These info types don't support non-zero subtypes. */
|
||||||
|
R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination());
|
||||||
|
|
||||||
|
/* Get the process from its handle. */
|
||||||
|
KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject<KProcess>(handle);
|
||||||
|
R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle());
|
||||||
|
|
||||||
|
switch (info_type) {
|
||||||
|
case ams::svc::InfoType_AliasRegionAddress:
|
||||||
|
*out = GetInteger(process->GetPageTable().GetAliasRegionStart());
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_AliasRegionSize:
|
||||||
|
*out = process->GetPageTable().GetAliasRegionSize();
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_HeapRegionAddress:
|
||||||
|
*out = GetInteger(process->GetPageTable().GetHeapRegionStart());
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_HeapRegionSize:
|
||||||
|
*out = process->GetPageTable().GetHeapRegionSize();
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_AslrRegionAddress:
|
||||||
|
*out = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_AslrRegionSize:
|
||||||
|
*out = process->GetPageTable().GetAliasCodeRegionSize();
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_StackRegionAddress:
|
||||||
|
*out = GetInteger(process->GetPageTable().GetStackRegionStart());
|
||||||
|
break;
|
||||||
|
case ams::svc::InfoType_StackRegionSize:
|
||||||
|
*out = process->GetPageTable().GetStackRegionSize();
|
||||||
|
break;
|
||||||
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return svc::ResultInvalidEnumValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetSystemInfo(u64 *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, u64 info_subtype) {
|
||||||
|
MESOSPHERE_LOG("GetSystemInfo(%p, %u, %08x, %lu) was called\n", out, static_cast<u32>(info_type), static_cast<u32>(handle), info_subtype);
|
||||||
|
ON_SCOPE_EXIT{ MESOSPHERE_LOG("GetSystemInfo returned %016lx\n", *out); };
|
||||||
|
|
||||||
|
switch (info_type) {
|
||||||
|
case ams::svc::SystemInfoType_InitialProcessIdRange:
|
||||||
|
{
|
||||||
|
R_UNLESS(handle == ams::svc::InvalidHandle, svc::ResultInvalidHandle());
|
||||||
|
switch (static_cast<ams::svc::InitialProcessIdRangeInfo>(info_subtype)) {
|
||||||
|
case ams::svc::InitialProcessIdRangeInfo_Minimum:
|
||||||
|
MESOSPHERE_ABORT_UNLESS(GetInitialProcessIdMin() <= GetInitialProcessIdMax());
|
||||||
|
*out = GetInitialProcessIdMin();
|
||||||
|
break;
|
||||||
|
case ams::svc::InitialProcessIdRangeInfo_Maximum:
|
||||||
|
MESOSPHERE_ABORT_UNLESS(GetInitialProcessIdMin() <= GetInitialProcessIdMax());
|
||||||
|
*out = GetInitialProcessIdMax();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return svc::ResultInvalidCombination();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return svc::ResultInvalidEnumValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================= 64 ABI ============================= */
|
/* ============================= 64 ABI ============================= */
|
||||||
|
|
||||||
Result GetInfo64(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
Result GetInfo64(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetInfo64 was called.");
|
return GetInfo(out, info_type, handle, info_subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetSystemInfo64(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
Result GetSystemInfo64(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetSystemInfo64 was called.");
|
return GetSystemInfo(out, info_type, handle, info_subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================= 64From32 ABI ============================= */
|
/* ============================= 64From32 ABI ============================= */
|
||||||
|
|
||||||
Result GetInfo64From32(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
Result GetInfo64From32(uint64_t *out, ams::svc::InfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetInfo64From32 was called.");
|
return GetInfo(out, info_type, handle, info_subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetSystemInfo64From32(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
Result GetSystemInfo64From32(uint64_t *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, uint64_t info_subtype) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetSystemInfo64From32 was called.");
|
return GetSystemInfo(out, info_type, handle, info_subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,61 @@ namespace ams::kern::svc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
Result ManageNamedPort(ams::svc::Handle *out_server_handle, KUserPointer<const char *> user_name, s32 max_sessions) {
|
||||||
|
/* Copy the provided name from user memory to kernel memory. */
|
||||||
|
char name[KObjectName::NameLengthMax] = {};
|
||||||
|
R_TRY(user_name.CopyStringTo(name, sizeof(name)));
|
||||||
|
|
||||||
|
/* Validate that sessions and name are valid. */
|
||||||
|
R_UNLESS(max_sessions >= 0, svc::ResultOutOfRange());
|
||||||
|
R_UNLESS(name[sizeof(name) - 1] == '\x00', svc::ResultOutOfRange());
|
||||||
|
|
||||||
|
if (max_sessions > 0) {
|
||||||
|
MESOSPHERE_LOG("Creating Named Port %s (max sessions = %d)\n", name, max_sessions);
|
||||||
|
/* Get the current handle table. */
|
||||||
|
auto &handle_table = GetCurrentProcess().GetHandleTable();
|
||||||
|
|
||||||
|
/* Create a new port. */
|
||||||
|
KPort *port = KPort::Create();
|
||||||
|
R_UNLESS(port != nullptr, svc::ResultOutOfResource());
|
||||||
|
|
||||||
|
/* Reserve a handle for the server port. */
|
||||||
|
R_TRY(handle_table.Reserve(out_server_handle));
|
||||||
|
auto reserve_guard = SCOPE_GUARD { handle_table.Unreserve(*out_server_handle); };
|
||||||
|
|
||||||
|
/* Initialize the new port. */
|
||||||
|
port->Initialize(max_sessions, false, 0);
|
||||||
|
|
||||||
|
/* Register the port. */
|
||||||
|
KPort::Register(port);
|
||||||
|
|
||||||
|
/* Register the handle in the table. */
|
||||||
|
handle_table.Register(*out_server_handle, std::addressof(port->GetServerPort()));
|
||||||
|
reserve_guard.Cancel();
|
||||||
|
auto register_guard = SCOPE_GUARD { handle_table.Remove(*out_server_handle); };
|
||||||
|
|
||||||
|
/* Create a new object name. */
|
||||||
|
R_TRY(KObjectName::NewFromName(std::addressof(port->GetClientPort()), name));
|
||||||
|
|
||||||
|
/* Perform resource cleanup. */
|
||||||
|
port->GetServerPort().Close();
|
||||||
|
port->GetClientPort().Close();
|
||||||
|
register_guard.Cancel();
|
||||||
|
} else /* if (max_sessions == 0) */ {
|
||||||
|
MESOSPHERE_LOG("Deleting Named Port %s\n", name);
|
||||||
|
|
||||||
|
/* Ensure that this else case is correct. */
|
||||||
|
MESOSPHERE_AUDIT(max_sessions == 0);
|
||||||
|
|
||||||
|
/* If we're closing, there's no server handle. */
|
||||||
|
*out_server_handle = ams::svc::InvalidHandle;
|
||||||
|
|
||||||
|
/* Delete the object. */
|
||||||
|
R_TRY(KObjectName::Delete<KClientPort>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +90,7 @@ namespace ams::kern::svc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ManageNamedPort64(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
|
Result ManageNamedPort64(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcManageNamedPort64 was called.");
|
return ManageNamedPort(out_server_handle, name, max_sessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ConnectToPort64(ams::svc::Handle *out_handle, ams::svc::Handle port) {
|
Result ConnectToPort64(ams::svc::Handle *out_handle, ams::svc::Handle port) {
|
||||||
@@ -54,7 +108,7 @@ namespace ams::kern::svc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ManageNamedPort64From32(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
|
Result ManageNamedPort64From32(ams::svc::Handle *out_server_handle, KUserPointer<const char *> name, int32_t max_sessions) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcManageNamedPort64From32 was called.");
|
return ManageNamedPort(out_server_handle, name, max_sessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ConnectToPort64From32(ams::svc::Handle *out_handle, ams::svc::Handle port) {
|
Result ConnectToPort64From32(ams::svc::Handle *out_handle, ams::svc::Handle port) {
|
||||||
|
|||||||
@@ -21,6 +21,32 @@ namespace ams::kern::svc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
Result GetProcessId(u64 *out_process_id, ams::svc::Handle handle) {
|
||||||
|
/* Get the object from the handle table. */
|
||||||
|
KScopedAutoObject obj = GetCurrentProcess().GetHandleTable().GetObject<KAutoObject>(handle);
|
||||||
|
R_UNLESS(obj.IsNotNull(), svc::ResultInvalidHandle());
|
||||||
|
|
||||||
|
/* Get the process from the object. */
|
||||||
|
KProcess *process = nullptr;
|
||||||
|
if (obj->IsDerivedFrom(KProcess::GetStaticTypeObj())) {
|
||||||
|
/* The object is a process, so we can use it directly. */
|
||||||
|
process = reinterpret_cast<KProcess *>(obj.GetPointerUnsafe());
|
||||||
|
} else if (obj->IsDerivedFrom(KThread::GetStaticTypeObj())) {
|
||||||
|
/* The object is a thread, so we want to use its parent. */
|
||||||
|
process = reinterpret_cast<KThread *>(obj.GetPointerUnsafe())->GetOwnerProcess();
|
||||||
|
} else if (obj->IsDerivedFrom(KDebug::GetStaticTypeObj())) {
|
||||||
|
/* The object is a debug, so we want to use the process it's attached to. */
|
||||||
|
MESOSPHERE_UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the target process exists. */
|
||||||
|
R_UNLESS(process != nullptr, svc::ResultInvalidHandle());
|
||||||
|
|
||||||
|
/* Get the process id. */
|
||||||
|
*out_process_id = process->GetId();
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -32,7 +58,7 @@ namespace ams::kern::svc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) {
|
Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetProcessId64 was called.");
|
return GetProcessId(out_process_id, process_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessList64(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
Result GetProcessList64(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
||||||
@@ -62,7 +88,7 @@ namespace ams::kern::svc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) {
|
Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcGetProcessId64From32 was called.");
|
return GetProcessId(out_process_id, process_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessList64From32(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
Result GetProcessList64From32(int32_t *out_num_processes, KUserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace ams::kern::svc {
|
|||||||
/* ============================= 64 ABI ============================= */
|
/* ============================= 64 ABI ============================= */
|
||||||
|
|
||||||
void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) {
|
void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||||
MESOSPHERE_PANIC("Stubbed SvcCallSecureMonitor64 was called.");
|
KSystemControl::CallSecureMonitorFromUser(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================= 64From32 ABI ============================= */
|
/* ============================= 64From32 ABI ============================= */
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -flto
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -flto
|
||||||
|
|||||||
@@ -20,41 +20,49 @@
|
|||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
/* Libstratosphere-only utility. */
|
/* Libstratosphere-only utility. */
|
||||||
#include "stratosphere/util.hpp"
|
#include <stratosphere/util.hpp>
|
||||||
|
|
||||||
|
/* Sadly required shims. */
|
||||||
|
#include <stratosphere/svc/svc_stratosphere_shims.hpp>
|
||||||
|
|
||||||
/* Critical modules with no dependencies. */
|
/* Critical modules with no dependencies. */
|
||||||
#include "stratosphere/ams.hpp"
|
#include <stratosphere/ams.hpp>
|
||||||
#include "stratosphere/os.hpp"
|
#include <stratosphere/os.hpp>
|
||||||
#include "stratosphere/dd.hpp"
|
#include <stratosphere/dd.hpp>
|
||||||
#include "stratosphere/lmem.hpp"
|
#include <stratosphere/lmem.hpp>
|
||||||
|
#include <stratosphere/mem.hpp>
|
||||||
|
|
||||||
/* Pull in all ID definitions from NCM. */
|
/* Pull in all ID definitions from NCM. */
|
||||||
#include "stratosphere/ncm/ncm_ids.hpp"
|
#include <stratosphere/ncm/ncm_ids.hpp>
|
||||||
|
|
||||||
/* At this point, just include the rest alphabetically. */
|
/* At this point, just include the rest alphabetically. */
|
||||||
/* TODO: Figure out optimal order. */
|
/* TODO: Figure out optimal order. */
|
||||||
#include "stratosphere/boot2.hpp"
|
#include <stratosphere/boot2.hpp>
|
||||||
#include "stratosphere/cfg.hpp"
|
#include <stratosphere/cfg.hpp>
|
||||||
#include "stratosphere/dmnt.hpp"
|
#include <stratosphere/dmnt.hpp>
|
||||||
#include "stratosphere/fatal.hpp"
|
#include <stratosphere/erpt.hpp>
|
||||||
#include "stratosphere/hid.hpp"
|
#include <stratosphere/fatal.hpp>
|
||||||
#include "stratosphere/hos.hpp"
|
#include <stratosphere/hid.hpp>
|
||||||
#include "stratosphere/kvdb.hpp"
|
#include <stratosphere/hos.hpp>
|
||||||
#include "stratosphere/ldr.hpp"
|
#include <stratosphere/kvdb.hpp>
|
||||||
#include "stratosphere/lr.hpp"
|
#include <stratosphere/ldr.hpp>
|
||||||
#include "stratosphere/map.hpp"
|
#include <stratosphere/lr.hpp>
|
||||||
#include "stratosphere/ncm.hpp"
|
#include <stratosphere/map.hpp>
|
||||||
#include "stratosphere/patcher.hpp"
|
#include <stratosphere/ncm.hpp>
|
||||||
#include "stratosphere/pm.hpp"
|
#include <stratosphere/nim.hpp>
|
||||||
#include "stratosphere/reg.hpp"
|
#include <stratosphere/patcher.hpp>
|
||||||
#include "stratosphere/ro.hpp"
|
#include <stratosphere/psc.hpp>
|
||||||
#include "stratosphere/settings.hpp"
|
#include <stratosphere/pm.hpp>
|
||||||
#include "stratosphere/sf.hpp"
|
#include <stratosphere/reg.hpp>
|
||||||
#include "stratosphere/sm.hpp"
|
#include <stratosphere/ro.hpp>
|
||||||
#include "stratosphere/spl.hpp"
|
#include <stratosphere/settings.hpp>
|
||||||
#include "stratosphere/updater.hpp"
|
#include <stratosphere/sf.hpp>
|
||||||
|
#include <stratosphere/sm.hpp>
|
||||||
|
#include <stratosphere/spl.hpp>
|
||||||
|
#include <stratosphere/time.hpp>
|
||||||
|
#include <stratosphere/updater.hpp>
|
||||||
|
|
||||||
/* Include FS last. */
|
/* Include FS last. */
|
||||||
#include "stratosphere/fs.hpp"
|
#include <stratosphere/fs.hpp>
|
||||||
#include "stratosphere/fssrv.hpp"
|
#include <stratosphere/fssrv.hpp>
|
||||||
#include "stratosphere/fssystem.hpp"
|
#include <stratosphere/fssystem.hpp>
|
||||||
25
libraries/libstratosphere/include/stratosphere/erpt.hpp
Normal file
25
libraries/libstratosphere/include/stratosphere/erpt.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <stratosphere/erpt/erpt_ids.autogen.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_multiple_category_context.hpp>
|
||||||
|
#include <stratosphere/erpt/sf/erpt_sf_i_context.hpp>
|
||||||
|
#include <stratosphere/erpt/sf/erpt_sf_i_session.hpp>
|
||||||
|
#include <stratosphere/erpt/srv/erpt_srv_types.hpp>
|
||||||
|
#include <stratosphere/erpt/srv/erpt_srv_api.hpp>
|
||||||
@@ -0,0 +1,780 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
|
||||||
|
/* NOTE: This file is auto-generated. */
|
||||||
|
/* Do not make edits to this file by hand. */
|
||||||
|
|
||||||
|
#define AMS_ERPT_FOREACH_FIELD_TYPE(HANDLER) \
|
||||||
|
HANDLER(FieldType_NumericU64, 0 ) \
|
||||||
|
HANDLER(FieldType_NumericU32, 1 ) \
|
||||||
|
HANDLER(FieldType_NumericI64, 2 ) \
|
||||||
|
HANDLER(FieldType_NumericI32, 3 ) \
|
||||||
|
HANDLER(FieldType_String, 4 ) \
|
||||||
|
HANDLER(FieldType_U8Array, 5 ) \
|
||||||
|
HANDLER(FieldType_U32Array, 6 ) \
|
||||||
|
HANDLER(FieldType_U64Array, 7 ) \
|
||||||
|
HANDLER(FieldType_I32Array, 8 ) \
|
||||||
|
HANDLER(FieldType_I64Array, 9 ) \
|
||||||
|
HANDLER(FieldType_Bool, 10) \
|
||||||
|
HANDLER(FieldType_NumericU16, 11) \
|
||||||
|
HANDLER(FieldType_NumericU8, 12) \
|
||||||
|
HANDLER(FieldType_NumericI16, 13) \
|
||||||
|
HANDLER(FieldType_NumericI8, 14) \
|
||||||
|
HANDLER(FieldType_I8Array, 15) \
|
||||||
|
|
||||||
|
#define AMS_ERPT_FOREACH_CATEGORY(HANDLER) \
|
||||||
|
HANDLER(Test, 0 ) \
|
||||||
|
HANDLER(ErrorInfo, 1 ) \
|
||||||
|
HANDLER(ConnectionStatusInfo, 2 ) \
|
||||||
|
HANDLER(NetworkInfo, 3 ) \
|
||||||
|
HANDLER(NXMacAddressInfo, 4 ) \
|
||||||
|
HANDLER(StealthNetworkInfo, 5 ) \
|
||||||
|
HANDLER(LimitHighCapacityInfo, 6 ) \
|
||||||
|
HANDLER(NATTypeInfo, 7 ) \
|
||||||
|
HANDLER(WirelessAPMacAddressInfo, 8 ) \
|
||||||
|
HANDLER(GlobalIPAddressInfo, 9 ) \
|
||||||
|
HANDLER(EnableWirelessInterfaceInfo, 10 ) \
|
||||||
|
HANDLER(EnableWifiInfo, 11 ) \
|
||||||
|
HANDLER(EnableBluetoothInfo, 12 ) \
|
||||||
|
HANDLER(EnableNFCInfo, 13 ) \
|
||||||
|
HANDLER(NintendoZoneSSIDListVersionInfo, 14 ) \
|
||||||
|
HANDLER(LANAdapterMacAddressInfo, 15 ) \
|
||||||
|
HANDLER(ApplicationInfo, 16 ) \
|
||||||
|
HANDLER(OccurrenceInfo, 17 ) \
|
||||||
|
HANDLER(ProductModelInfo, 18 ) \
|
||||||
|
HANDLER(CurrentLanguageInfo, 19 ) \
|
||||||
|
HANDLER(UseNetworkTimeProtocolInfo, 20 ) \
|
||||||
|
HANDLER(TimeZoneInfo, 21 ) \
|
||||||
|
HANDLER(ControllerFirmwareInfo, 22 ) \
|
||||||
|
HANDLER(VideoOutputInfo, 23 ) \
|
||||||
|
HANDLER(NANDFreeSpaceInfo, 24 ) \
|
||||||
|
HANDLER(SDCardFreeSpaceInfo, 25 ) \
|
||||||
|
HANDLER(ScreenBrightnessInfo, 26 ) \
|
||||||
|
HANDLER(AudioFormatInfo, 27 ) \
|
||||||
|
HANDLER(MuteOnHeadsetUnpluggedInfo, 28 ) \
|
||||||
|
HANDLER(NumUserRegisteredInfo, 29 ) \
|
||||||
|
HANDLER(DataDeletionInfo, 30 ) \
|
||||||
|
HANDLER(ControllerVibrationInfo, 31 ) \
|
||||||
|
HANDLER(LockScreenInfo, 32 ) \
|
||||||
|
HANDLER(InternalBatteryLotNumberInfo, 33 ) \
|
||||||
|
HANDLER(LeftControllerSerialNumberInfo, 34 ) \
|
||||||
|
HANDLER(RightControllerSerialNumberInfo, 35 ) \
|
||||||
|
HANDLER(NotificationInfo, 36 ) \
|
||||||
|
HANDLER(TVInfo, 37 ) \
|
||||||
|
HANDLER(SleepInfo, 38 ) \
|
||||||
|
HANDLER(ConnectionInfo, 39 ) \
|
||||||
|
HANDLER(NetworkErrorInfo, 40 ) \
|
||||||
|
HANDLER(FileAccessPathInfo, 41 ) \
|
||||||
|
HANDLER(GameCardCIDInfo, 42 ) \
|
||||||
|
HANDLER(NANDCIDInfo, 43 ) \
|
||||||
|
HANDLER(MicroSDCIDInfo, 44 ) \
|
||||||
|
HANDLER(NANDSpeedModeInfo, 45 ) \
|
||||||
|
HANDLER(MicroSDSpeedModeInfo, 46 ) \
|
||||||
|
HANDLER(GameCardSpeedModeInfo, 47 ) \
|
||||||
|
HANDLER(UserAccountInternalIDInfo, 48 ) \
|
||||||
|
HANDLER(NetworkServiceAccountInternalIDInfo, 49 ) \
|
||||||
|
HANDLER(NintendoAccountInternalIDInfo, 50 ) \
|
||||||
|
HANDLER(USB3AvailableInfo, 51 ) \
|
||||||
|
HANDLER(CallStackInfo, 52 ) \
|
||||||
|
HANDLER(SystemStartupLogInfo, 53 ) \
|
||||||
|
HANDLER(RegionSettingInfo, 54 ) \
|
||||||
|
HANDLER(NintendoZoneConnectedInfo, 55 ) \
|
||||||
|
HANDLER(ForceSleepInfo, 56 ) \
|
||||||
|
HANDLER(ChargerInfo, 57 ) \
|
||||||
|
HANDLER(RadioStrengthInfo, 58 ) \
|
||||||
|
HANDLER(ErrorInfoAuto, 59 ) \
|
||||||
|
HANDLER(AccessPointInfo, 60 ) \
|
||||||
|
HANDLER(ErrorInfoDefaults, 61 ) \
|
||||||
|
HANDLER(SystemPowerStateInfo, 62 ) \
|
||||||
|
HANDLER(PerformanceInfo, 63 ) \
|
||||||
|
HANDLER(ThrottlingInfo, 64 ) \
|
||||||
|
HANDLER(GameCardErrorInfo, 65 ) \
|
||||||
|
HANDLER(EdidInfo, 66 ) \
|
||||||
|
HANDLER(ThermalInfo, 67 ) \
|
||||||
|
HANDLER(CradleFirmwareInfo, 68 ) \
|
||||||
|
HANDLER(RunningApplicationInfo, 69 ) \
|
||||||
|
HANDLER(RunningAppletInfo, 70 ) \
|
||||||
|
HANDLER(FocusedAppletHistoryInfo, 71 ) \
|
||||||
|
HANDLER(CompositorInfo, 72 ) \
|
||||||
|
HANDLER(BatteryChargeInfo, 73 ) \
|
||||||
|
HANDLER(NANDExtendedCsd, 74 ) \
|
||||||
|
HANDLER(NANDPatrolInfo, 75 ) \
|
||||||
|
HANDLER(NANDErrorInfo, 76 ) \
|
||||||
|
HANDLER(NANDDriverLog, 77 ) \
|
||||||
|
HANDLER(SdCardSizeSpec, 78 ) \
|
||||||
|
HANDLER(SdCardErrorInfo, 79 ) \
|
||||||
|
HANDLER(SdCardDriverLog , 80 ) \
|
||||||
|
HANDLER(FsProxyErrorInfo, 81 ) \
|
||||||
|
HANDLER(SystemAppletSceneInfo, 82 ) \
|
||||||
|
HANDLER(VideoInfo, 83 ) \
|
||||||
|
HANDLER(GpuErrorInfo, 84 ) \
|
||||||
|
HANDLER(PowerClockInfo, 85 ) \
|
||||||
|
HANDLER(AdspErrorInfo, 86 ) \
|
||||||
|
HANDLER(NvDispDeviceInfo, 87 ) \
|
||||||
|
HANDLER(NvDispDcWindowInfo, 88 ) \
|
||||||
|
HANDLER(NvDispDpModeInfo, 89 ) \
|
||||||
|
HANDLER(NvDispDpLinkSpec, 90 ) \
|
||||||
|
HANDLER(NvDispDpLinkStatus, 91 ) \
|
||||||
|
HANDLER(NvDispDpHdcpInfo, 92 ) \
|
||||||
|
HANDLER(NvDispDpAuxCecInfo, 93 ) \
|
||||||
|
HANDLER(NvDispDcInfo, 94 ) \
|
||||||
|
HANDLER(NvDispDsiInfo, 95 ) \
|
||||||
|
HANDLER(NvDispErrIDInfo, 96 ) \
|
||||||
|
HANDLER(SdCardMountInfo, 97 ) \
|
||||||
|
HANDLER(RetailInteractiveDisplayInfo, 98 ) \
|
||||||
|
HANDLER(CompositorStateInfo, 99 ) \
|
||||||
|
HANDLER(CompositorLayerInfo, 100) \
|
||||||
|
HANDLER(CompositorDisplayInfo, 101) \
|
||||||
|
HANDLER(CompositorHWCInfo, 102) \
|
||||||
|
HANDLER(MonitorCapability, 103) \
|
||||||
|
HANDLER(ErrorReportSharePermissionInfo, 104) \
|
||||||
|
HANDLER(MultimediaInfo, 105) \
|
||||||
|
HANDLER(ConnectedControllerInfo, 106) \
|
||||||
|
HANDLER(FsMemoryInfo, 107) \
|
||||||
|
HANDLER(UserClockContextInfo, 108) \
|
||||||
|
HANDLER(NetworkClockContextInfo, 109) \
|
||||||
|
HANDLER(AcpGeneralSettingsInfo, 110) \
|
||||||
|
HANDLER(AcpPlayLogSettingsInfo, 111) \
|
||||||
|
HANDLER(AcpAocSettingsInfo, 112) \
|
||||||
|
HANDLER(AcpBcatSettingsInfo, 113) \
|
||||||
|
HANDLER(AcpStorageSettingsInfo, 114) \
|
||||||
|
HANDLER(AcpRatingSettingsInfo, 115) \
|
||||||
|
HANDLER(MonitorSettings, 116) \
|
||||||
|
HANDLER(RebootlessSystemUpdateVersionInfo, 117) \
|
||||||
|
HANDLER(NifmConnectionTestInfo, 118) \
|
||||||
|
HANDLER(PcieLoggedStateInfo, 119) \
|
||||||
|
HANDLER(NetworkSecurityCertificateInfo, 120) \
|
||||||
|
HANDLER(AcpNeighborDetectionInfo, 121) \
|
||||||
|
HANDLER(GpuCrashInfo, 122) \
|
||||||
|
HANDLER(UsbStateInfo, 123) \
|
||||||
|
HANDLER(NvHostErrInfo, 124) \
|
||||||
|
HANDLER(RunningUlaInfo, 125) \
|
||||||
|
|
||||||
|
#define AMS_ERPT_FOREACH_FIELD(HANDLER) \
|
||||||
|
HANDLER(TestU64, 0, Test, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU32, 1, Test, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI64, 2, Test, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI32, 3, Test, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(TestString, 4, Test, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU8Array, 5, Test, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU32Array, 6, Test, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU64Array, 7, Test, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI32Array, 8, Test, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI64Array, 9, Test, FieldType_I64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ErrorCode, 10, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ErrorDescription, 11, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(OccurrenceTimestamp, 12, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ReportIdentifier, 13, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ConnectionStatus, 14, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AccessPointSSID, 15, AccessPointInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AccessPointSecurityType, 16, AccessPointInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RadioStrength, 17, RadioStrengthInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NXMacAddress, 18, NXMacAddressInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(IPAddressAcquisitionMethod, 19, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CurrentIPAddress, 20, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SubnetMask, 21, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GatewayIPAddress, 22, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(DNSType, 23, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PriorityDNSIPAddress, 24, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AlternateDNSIPAddress, 25, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(UseProxyFlag, 26, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ProxyIPAddress, 27, NetworkInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ProxyPort, 28, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ProxyAutoAuthenticateFlag, 29, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(MTU, 30, NetworkInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ConnectAutomaticallyFlag, 31, NetworkInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(UseStealthNetworkFlag, 32, StealthNetworkInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(LimitHighCapacityFlag, 33, LimitHighCapacityInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NATType, 34, NATTypeInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(WirelessAPMacAddress, 35, WirelessAPMacAddressInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GlobalIPAddress, 36, GlobalIPAddressInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(EnableWirelessInterfaceFlag, 37, EnableWirelessInterfaceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(EnableWifiFlag, 38, EnableWifiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(EnableBluetoothFlag, 39, EnableBluetoothInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(EnableNFCFlag, 40, EnableNFCInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NintendoZoneSSIDListVersion, 41, NintendoZoneSSIDListVersionInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(LANAdapterMacAddress, 42, LANAdapterMacAddressInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationID, 43, ApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationTitle, 44, ApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationVersion, 45, ApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationStorageLocation, 46, ApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(DownloadContentType, 47, OccurrenceInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(InstallContentType, 48, OccurrenceInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ConsoleStartingUpFlag, 49, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(SystemStartingUpFlag, 50, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ConsoleFirstInitFlag, 51, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(HomeMenuScreenDisplayedFlag, 52, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(DataManagementScreenDisplayedFlag, 53, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ConnectionTestingFlag, 54, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationRunningFlag, 55, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(DataCorruptionDetectedFlag, 56, OccurrenceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ProductModel, 57, ProductModelInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CurrentLanguage, 58, CurrentLanguageInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(UseNetworkTimeProtocolFlag, 59, UseNetworkTimeProtocolInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(TimeZone, 60, TimeZoneInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerFirmware, 61, ControllerFirmwareInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoOutputSetting, 62, VideoOutputInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDFreeSpace, 63, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SDCardFreeSpace, 64, SDCardFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SerialNumber, 65, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(OsVersion, 66, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ScreenBrightnessAutoAdjustFlag, 67, ScreenBrightnessInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(HdmiAudioOutputMode, 68, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SpeakerAudioOutputMode, 69, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(HeadphoneAudioOutputMode, 70, AudioFormatInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(MuteOnHeadsetUnpluggedFlag, 71, MuteOnHeadsetUnpluggedInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NumUserRegistered, 72, NumUserRegisteredInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(StorageAutoOrganizeFlag, 73, DataDeletionInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerVibrationVolume, 74, ControllerVibrationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(LockScreenFlag, 75, LockScreenInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(InternalBatteryLotNumber, 76, InternalBatteryLotNumberInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(LeftControllerSerialNumber, 77, LeftControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RightControllerSerialNumber, 78, RightControllerSerialNumberInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NotifyInGameDownloadCompletionFlag, 79, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NotificationSoundFlag, 80, NotificationInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(TVResolutionSetting, 81, TVInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RGBRangeSetting, 82, TVInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ReduceScreenBurnFlag, 83, TVInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(TVAllowsCecFlag, 84, TVInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(HandheldModeTimeToScreenSleep, 85, SleepInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ConsoleModeTimeToScreenSleep, 86, SleepInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(StopAutoSleepDuringContentPlayFlag, 87, SleepInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(LastConnectionTestDownloadSpeed, 88, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(LastConnectionTestUploadSpeed, 89, ConnectionInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(DEPRECATED_ServerFQDN, 90, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(HTTPRequestContents, 91, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(HTTPRequestResponseContents, 92, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(EdgeServerIPAddress, 93, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CDNContentPath, 94, NetworkErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(FileAccessPath, 95, FileAccessPathInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardCID, 96, GameCardCIDInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDCID, 97, NANDCIDInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(MicroSDCID, 98, MicroSDCIDInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDSpeedMode, 99, NANDSpeedModeInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(MicroSDSpeedMode, 100, MicroSDSpeedModeInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardSpeedMode, 101, GameCardSpeedModeInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(UserAccountInternalID, 102, UserAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NetworkServiceAccountInternalID, 103, NetworkServiceAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NintendoAccountInternalID, 104, NintendoAccountInternalIDInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(USB3AvailableFlag, 105, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(CallStack, 106, CallStackInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SystemStartupLog, 107, SystemStartupLogInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RegionSetting, 108, RegionSettingInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NintendoZoneConnectedFlag, 109, NintendoZoneConnectedInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ForcedSleepHighTemperatureReading, 110, ForceSleepInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ForcedSleepFanSpeedReading, 111, ForceSleepInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ForcedSleepHWInfo, 112, ForceSleepInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AbnormalPowerStateInfo, 113, ChargerInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ScreenBrightnessLevel, 114, ScreenBrightnessInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ProgramId, 115, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AbortFlag, 116, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ReportVisibilityFlag, 117, ErrorInfoAuto, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(FatalFlag, 118, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(OccurrenceTimestampNet, 119, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ResultBacktrace, 120, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GeneralRegisterAarch32, 121, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(StackBacktrace32, 122, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ExceptionInfoAarch32, 123, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GeneralRegisterAarch64, 124, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ExceptionInfoAarch64, 125, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(StackBacktrace64, 126, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(RegisterSetFlag32, 127, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(RegisterSetFlag64, 128, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(ProgramMappedAddr32, 129, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ProgramMappedAddr64, 130, ErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AbortType, 131, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PrivateOsVersion, 132, ErrorInfoAuto, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CurrentSystemPowerState, 133, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PreviousSystemPowerState, 134, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(DestinationSystemPowerState, 135, SystemPowerStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PscTransitionCurrentState, 136, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PscTransitionPreviousState, 137, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PscInitializedList, 138, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PscCurrentPmStateList, 139, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PscNextPmStateList, 140, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PerformanceMode, 141, PerformanceInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PerformanceConfiguration, 142, PerformanceInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(Throttled, 143, ThrottlingInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ThrottlingDuration, 144, ThrottlingInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ThrottlingTimestamp, 145, ThrottlingInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardCrcErrorCount, 146, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAsicCrcErrorCount, 147, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardRefreshCount, 148, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardReadRetryCount, 149, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(EdidBlock, 150, EdidInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EdidExtensionBlock, 151, EdidInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(CreateProcessFailureFlag, 152, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(TemperaturePcb, 153, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(TemperatureSoc, 154, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(CurrentFanDuty, 155, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(LastDvfsThresholdTripped, 156, ThermalInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(CradlePdcHFwVersion, 157, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CradlePdcAFwVersion, 158, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CradleMcuFwVersion, 159, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CradleDp2HdmiFwVersion, 160, CradleFirmwareInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationId, 161, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationTitle, 162, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationVersion, 163, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationStorageLocation, 164, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningAppletList, 165, RunningAppletInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(FocusedAppletHistory, 166, FocusedAppletHistoryInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(CompositorState, 167, CompositorStateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CompositorLayerState, 168, CompositorLayerInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CompositorDisplayState, 169, CompositorDisplayInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CompositorHWCState, 170, CompositorHWCInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(InputCurrentLimit, 171, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(BoostModeCurrentLimit, 172, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FastChargeCurrentLimit, 173, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(ChargeVoltageLimit, 174, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(ChargeConfiguration, 175, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(HizMode, 176, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ChargeEnabled, 177, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerSupplyPath, 178, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(BatteryTemperature, 179, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(BatteryChargePercent, 180, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(BatteryChargeVoltage, 181, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(BatteryAge, 182, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerRole, 183, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerSupplyType, 184, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerSupplyVoltage, 185, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerSupplyCurrent, 186, BatteryChargeInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FastBatteryChargingEnabled, 187, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerPowerSupplyAcquired, 188, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(OtgRequested, 189, BatteryChargeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDPreEolInfo, 190, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDDeviceLifeTimeEstTypA, 191, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDDeviceLifeTimeEstTypB, 192, NANDExtendedCsd, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDPatrolCount, 193, NANDPatrolInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDNumActivationFailures, 194, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDNumActivationErrorCorrections, 195, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDNumReadWriteFailures, 196, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDNumReadWriteErrorCorrections, 197, NANDErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDErrorLog, 198, NANDDriverLog, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardUserAreaSize, 199, SdCardSizeSpec, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardProtectedAreaSize, 200, SdCardSizeSpec, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardNumActivationFailures, 201, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardNumActivationErrorCorrections, 202, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardNumReadWriteFailures, 203, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardNumReadWriteErrorCorrections, 204, SdCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardErrorLog, 205, SdCardDriverLog , FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptionKey, 206, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptedExceptionInfo, 207, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardTimeoutRetryErrorCount, 208, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FsRemountForDataCorruptCount, 209, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FsRemountForDataCorruptRetryOutCount, 210, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardInsertionCount, 211, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardRemovalCount, 212, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAsicInitializeCount, 213, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU16, 214, Test, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(TestU8, 215, Test, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI16, 216, Test, FieldType_NumericI16, FieldFlag_None ) \
|
||||||
|
HANDLER(TestI8, 217, Test, FieldType_NumericI8, FieldFlag_None ) \
|
||||||
|
HANDLER(SystemAppletScene, 218, SystemAppletSceneInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(CodecType, 219, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(DecodeBuffers, 220, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FrameWidth, 221, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FrameHeight, 222, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(ColorPrimaries, 223, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(TransferCharacteristics, 224, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(MatrixCoefficients, 225, VideoInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(DisplayWidth, 226, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(DisplayHeight, 227, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(DARWidth, 228, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(DARHeight, 229, VideoInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(ColorFormat, 230, VideoInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(ColorSpace, 231, VideoInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SurfaceLayout, 232, VideoInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(BitStream, 233, VideoInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoDecState, 234, VideoInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorChannelId, 235, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorAruId, 236, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorType, 237, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorFaultInfo, 238, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorWriteAccess, 239, GpuErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorFaultAddress, 240, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorFaultUnit, 241, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorFaultType, 242, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorHwContextPointer, 243, GpuErrorInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorContextStatus, 244, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaIntr, 245, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaErrorType, 246, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaHeaderShadow, 247, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaHeader, 248, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaGpShadow0, 249, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuErrorPbdmaGpShadow1, 250, GpuErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AccessPointChannel, 251, AccessPointInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(ThreadName, 252, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionRegisters, 253, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionSpsr, 254, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionProgramCounter, 255, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionLinkRegister, 256, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionStackPointer, 257, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionArmModeRegisters, 258, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionStackAddress, 259, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionStackDump, 260, AdspErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AdspExceptionReason, 261, AdspErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(OscillatorClock, 262, PowerClockInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CpuDvfsTableClocks, 263, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(CpuDvfsTableVoltages, 264, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuDvfsTableClocks, 265, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuDvfsTableVoltages, 266, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EmcDvfsTableClocks, 267, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EmcDvfsTableVoltages, 268, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ModuleClockFrequencies, 269, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ModuleClockEnableFlags, 270, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ModulePowerEnableFlags, 271, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ModuleResetAssertFlags, 272, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ModuleMinimumVoltageClockRates, 273, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerDomainEnableFlags, 274, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PowerDomainVoltages, 275, PowerClockInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AccessPointRssi, 276, RadioStrengthInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FuseInfo, 277, PowerClockInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoLog, 278, VideoInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardDeviceId, 279, GameCardCIDInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAsicReinitializeCount, 280, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAsicReinitializeFailureCount, 281, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAsicReinitializeFailureDetail, 282, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardRefreshSuccessCount, 283, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAwakenCount, 284, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardAwakenFailureCount, 285, GameCardErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardReadCountFromInsert, 286, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardReadCountFromAwaken, 287, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardLastReadErrorPageAddress, 288, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GameCardLastReadErrorPageCount, 289, GameCardErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AppletManagerContextTrace, 290, ErrorInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispIsRegistered, 291, NvDispDeviceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispIsSuspend, 292, NvDispDeviceInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDC0SurfaceNum, 293, NvDispDeviceInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDC1SurfaceNum, 294, NvDispDeviceInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowSrcRectX, 295, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowSrcRectY, 296, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowSrcRectWidth, 297, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowSrcRectHeight, 298, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowDstRectX, 299, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowDstRectY, 300, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowDstRectWidth, 301, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowDstRectHeight, 302, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowIndex, 303, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowBlendOperation, 304, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowAlphaOperation, 305, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowDepth, 306, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowAlpha, 307, NvDispDcWindowInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowHFilter, 308, NvDispDcWindowInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowVFilter, 309, NvDispDcWindowInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowOptions, 310, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispWindowSyncPointId, 311, NvDispDcWindowInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPSorPower, 312, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPClkType, 313, NvDispDpModeInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPEnable, 314, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPState, 315, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPEdid, 316, NvDispDpModeInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPEdidSize, 317, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPEdidExtSize, 318, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPFakeMode, 319, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPModeNumber, 320, NvDispDpModeInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPPlugInOut, 321, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPAuxIntHandler, 322, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPForceMaxLinkBW, 323, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPIsConnected, 324, NvDispDpModeInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkValid, 325, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkMaxBW, 326, NvDispDpLinkSpec, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkMaxLaneCount, 327, NvDispDpLinkSpec, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkDownSpread, 328, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkSupportEnhancedFraming, 329, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkBpp, 330, NvDispDpLinkSpec, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkScaramberCap, 331, NvDispDpLinkSpec, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkBW, 332, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkLaneCount, 333, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkEnhancedFraming, 334, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkScrambleEnable, 335, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkActivePolarity, 336, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkActiveCount, 337, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkTUSize, 338, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkActiveFrac, 339, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkWatermark, 340, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkHBlank, 341, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkVBlank, 342, NvDispDpLinkStatus, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkOnlyEnhancedFraming, 343, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkOnlyEdpCap, 344, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkSupportFastLT, 345, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkLTDataValid, 346, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkTsp3Support, 347, NvDispDpLinkStatus, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDPLinkAuxInterval, 348, NvDispDpLinkStatus, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpCreated, 349, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpUserRequest, 350, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpPlugged, 351, NvDispDpHdcpInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpState, 352, NvDispDpHdcpInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpFailCount, 353, NvDispDpHdcpInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpHdcp22, 354, NvDispDpHdcpInfo, FieldType_NumericI8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpMaxRetry, 355, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpHpd, 356, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispHdcpRepeater, 357, NvDispDpHdcpInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecRxBuf, 358, NvDispDpAuxCecInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecRxLength, 359, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecTxBuf, 360, NvDispDpAuxCecInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecTxLength, 361, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecTxRet, 362, NvDispDpAuxCecInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecState, 363, NvDispDpAuxCecInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecTxInfo, 364, NvDispDpAuxCecInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispCecRxInfo, 365, NvDispDpAuxCecInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCIndex, 366, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCInitialize, 367, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCClock, 368, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCFrequency, 369, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCFailed, 370, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCModeWidth, 371, NvDispDcInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCModeHeight, 372, NvDispDcInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCModeBpp, 373, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCPanelFrequency, 374, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCWinDirty, 375, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCWinEnable, 376, NvDispDcInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCVrr, 377, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDCPanelInitialize, 378, NvDispDcInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiDataFormat, 379, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiVideoMode, 380, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiRefreshRate, 381, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiLpCmdModeFrequency, 382, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiHsCmdModeFrequency, 383, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiPanelResetTimeout, 384, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiPhyFrequency, 385, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiFrequency, 386, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDsiInstance, 387, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiHostCtrlEnable, 388, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiInit, 389, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiEnable, 390, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiHsMode, 391, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiVendorId, 392, NvDispDsiInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiLcdVendorNum, 393, NvDispDsiInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiHsClockControl, 394, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiEnableHsClockInLpMode, 395, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiTeFrameUpdate, 396, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiGangedType, 397, NvDispDsiInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispDcDsiHbpInPktSeq, 398, NvDispDsiInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispErrID, 399, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispErrData0, 400, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvDispErrData1, 401, NvDispErrIDInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardMountStatus, 402, SdCardMountInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardMountUnexpectedResult, 403, SdCardMountInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDTotalSize, 404, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SdCardTotalSize, 405, SDCardFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(ElapsedTimeSinceInitialLaunch, 406, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ElapsedTimeSincePowerOn, 407, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ElapsedTimeSinceLastAwake, 408, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(OccurrenceTick, 409, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(RetailInteractiveDisplayFlag, 410, RetailInteractiveDisplayInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(FatFsError, 411, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FatFsExtraError, 412, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FatFsErrorDrive, 413, FsProxyErrorInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(FatFsErrorName, 414, FsProxyErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorManufactureCode, 415, MonitorCapability, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorProductCode, 416, MonitorCapability, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorSerialNumber, 417, MonitorCapability, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorManufactureYear, 418, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(PhysicalAddress, 419, MonitorCapability, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(Is4k60Hz, 420, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(Is4k30Hz, 421, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(Is1080P60Hz, 422, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(Is720P60Hz, 423, MonitorCapability, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(PcmChannelMax, 424, MonitorCapability, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(CrashReportHash, 425, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ErrorReportSharePermission, 426, ErrorReportSharePermissionInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoCodecTypeEnum, 427, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoBitRate, 428, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoFrameRate, 429, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoWidth, 430, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(VideoHeight, 431, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(AudioCodecTypeEnum, 432, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(AudioSampleRate, 433, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(AudioChannelCount, 434, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(AudioBitRate, 435, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaContainerType, 436, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaProfileType, 437, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaLevelType, 438, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaCacheSizeEnum, 439, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaErrorStatusEnum, 440, MultimediaInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(MultimediaErrorLog, 441, MultimediaInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerFqdn, 442, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerIpAddress, 443, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(TestStringEncrypt, 444, Test, FieldType_String, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(TestU8ArrayEncrypt, 445, Test, FieldType_U8Array, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(TestU32ArrayEncrypt, 446, Test, FieldType_U32Array, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(TestU64ArrayEncrypt, 447, Test, FieldType_U64Array, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(TestI32ArrayEncrypt, 448, Test, FieldType_I32Array, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(TestI64ArrayEncrypt, 449, Test, FieldType_I64Array, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(CipherKey, 450, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(FileSystemPath, 451, ErrorInfo, FieldType_String, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(WebMediaPlayerOpenUrl, 452, ErrorInfo, FieldType_String, FieldFlag_Encrypt) \
|
||||||
|
HANDLER(WebMediaPlayerLastSocketErrors, 453, ErrorInfo, FieldType_I32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(UnknownControllerCount, 454, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AttachedControllerCount, 455, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(BluetoothControllerCount, 456, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(UsbControllerCount, 457, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerTypeList, 458, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerInterfaceList, 459, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ControllerStyleList, 460, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(FsPooledBufferPeakFreeSize, 461, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsPooledBufferRetriedCount, 462, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsPooledBufferReduceAllocationCount, 463, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsBufferManagerPeakFreeSize, 464, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsBufferManagerRetriedCount, 465, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsExpHeapPeakFreeSize, 466, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsBufferPoolPeakFreeSize, 467, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsPatrolReadAllocateBufferSuccessCount, 468, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(FsPatrolReadAllocateBufferFailureCount, 469, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SteadyClockInternalOffset, 470, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(SteadyClockCurrentTimePointValue, 471, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(UserClockContextOffset, 472, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(UserClockContextTimeStampValue, 473, UserClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(NetworkClockContextOffset, 474, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(NetworkClockContextTimeStampValue, 475, NetworkClockContextInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(SystemAbortFlag, 476, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationAbortFlag, 477, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(NifmErrorCode, 478, ConnectionStatusInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsApplicationId, 479, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsContentMetaKeyIdList, 480, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsContentMetaKeyVersionList, 481, ErrorInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsContentMetaKeyTypeList, 482, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsContentMetaKeyInstallTypeList, 483, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsSenderFlag, 484, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsApplicationRequestFlag, 485, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsHasExFatDriverFlag, 486, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(LcsIpAddress, 487, ErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpStartupUserAccount, 488, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpAocRegistrationType, 489, AcpAocSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpAttributeFlag, 490, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpSupportedLanguageFlag, 491, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpParentalControlFlag, 492, AcpGeneralSettingsInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpScreenShot, 493, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpVideoCapture, 494, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpDataLossConfirmation, 495, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpPlayLogPolicy, 496, AcpPlayLogSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpPresenceGroupId, 497, AcpGeneralSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpRatingAge, 498, AcpRatingSettingsInfo, FieldType_I8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpAocBaseId, 499, AcpAocSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpSaveDataOwnerId, 500, AcpStorageSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpUserAccountSaveDataSize, 501, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpUserAccountSaveDataJournalSize, 502, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpDeviceSaveDataSize, 503, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpDeviceSaveDataJournalSize, 504, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpBcatDeliveryCacheStorageSize, 505, AcpBcatSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpApplicationErrorCodeCategory, 506, AcpGeneralSettingsInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpLocalCommunicationId, 507, AcpGeneralSettingsInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpLogoType, 508, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpLogoHandling, 509, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpRuntimeAocInstall, 510, AcpAocSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpCrashReport, 511, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpHdcp, 512, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpSeedForPseudoDeviceId, 513, AcpGeneralSettingsInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpBcatPassphrase, 514, AcpBcatSettingsInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpUserAccountSaveDataSizeMax, 515, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpUserAccountSaveDataJournalSizeMax, 516, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpDeviceSaveDataSizeMax, 517, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpDeviceSaveDataJournalSizeMax, 518, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpTemporaryStorageSize, 519, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpCacheStorageSize, 520, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpCacheStorageJournalSize, 521, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpCacheStorageDataAndJournalSizeMax, 522, AcpStorageSettingsInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpCacheStorageIndexMax, 523, AcpStorageSettingsInfo, FieldType_NumericI16, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpPlayLogQueryableApplicationId, 524, AcpPlayLogSettingsInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpPlayLogQueryCapability, 525, AcpPlayLogSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpRepairFlag, 526, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationPatchStorageLocation, 527, RunningApplicationInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationVersionNumber, 528, RunningApplicationInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FsRecoveredByInvalidateCacheCount, 529, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FsSaveDataIndexCount, 530, FsProxyErrorInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(FsBufferManagerPeakTotalAllocatableSize, 531, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorCurrentWidth, 532, MonitorSettings, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorCurrentHeight, 533, MonitorSettings, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(MonitorCurrentRefreshRate, 534, MonitorSettings, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RebootlessSystemUpdateVersion, 535, RebootlessSystemUpdateVersionInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptedExceptionInfo1, 536, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptedExceptionInfo2, 537, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptedExceptionInfo3, 538, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(EncryptedDyingMessage, 539, ErrorInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(DramId, 540, PowerClockInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NifmConnectionTestRedirectUrl, 541, NifmConnectionTestInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpRequiredNetworkServiceLicenseOnLaunchFlag, 542, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort0Flags, 543, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort0Speed, 544, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort0ResetTimeInUs, 545, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort0IrqCount, 546, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort0Statistics, 547, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort1Flags, 548, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort1Speed, 549, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort1ResetTimeInUs, 550, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort1IrqCount, 551, PcieLoggedStateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePort1Statistics, 552, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction0VendorId, 553, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction0DeviceId, 554, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction0PmState, 555, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction0IsAcquired, 556, PcieLoggedStateInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction1VendorId, 557, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction1DeviceId, 558, PcieLoggedStateInfo, FieldType_NumericU16, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction1PmState, 559, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieFunction1IsAcquired, 560, PcieLoggedStateInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(PcieGlobalRootComplexStatistics, 561, PcieLoggedStateInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(PciePllResistorCalibrationValue, 562, PcieLoggedStateInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateRequestedHostName, 563, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateCommonName, 564, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateSANCount, 565, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateSANs, 566, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(FsBufferPoolMaxAllocateSize, 567, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateIssuerName, 568, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationAliveTime, 569, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationInFocusTime, 570, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationOutOfFocusTime, 571, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(ApplicationBackgroundFocusTime, 572, ErrorInfoAuto, FieldType_NumericI64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpUserAccountSwitchLock, 573, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(USB3HostAvailableFlag, 574, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(USB3DeviceAvailableFlag, 575, USB3AvailableInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpNeighborDetectionClientConfigurationSendDataId, 576, AcpNeighborDetectionInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpNeighborDetectionClientConfigurationReceivableDataIds, 577, AcpNeighborDetectionInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpStartupUserAccountOptionFlag, 578, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerErrorCode, 579, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(AppletManagerMetaLogTrace, 580, ErrorInfo, FieldType_U64Array, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerCertificateSerialNumber, 581, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerCertificatePublicKeyAlgorithm, 582, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerCertificateSignatureAlgorithm, 583, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerCertificateNotBefore, 584, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(ServerCertificateNotAfter, 585, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(CertificateAlgorithmInfoBits, 586, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(TlsConnectionPeerIpAddress, 587, NetworkSecurityCertificateInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(TlsConnectionLastHandshakeState, 588, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(TlsConnectionInfoBits, 589, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SslStateBits, 590, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SslProcessInfoBits, 591, NetworkSecurityCertificateInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(SslProcessHeapSize, 592, NetworkSecurityCertificateInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(SslBaseErrorCode, 593, NetworkSecurityCertificateInfo, FieldType_NumericI32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuCrashDumpSize, 594, GpuCrashInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(GpuCrashDump, 595, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningApplicationProgramIndex, 596, RunningApplicationInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(UsbTopology, 597, UsbStateInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||||
|
HANDLER(AkamaiReferenceId, 598, ErrorInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NvHostErrID, 599, NvHostErrInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(NvHostErrDataArrayU32, 600, NvHostErrInfo, FieldType_U32Array, FieldFlag_None ) \
|
||||||
|
HANDLER(HasSyslogFlag, 601, ErrorInfo, FieldType_Bool, FieldFlag_None ) \
|
||||||
|
HANDLER(AcpRuntimeParameterDelivery, 602, AcpGeneralSettingsInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(PlatformRegion, 603, RegionSettingInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningUlaApplicationId, 604, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningUlaAppletId, 605, RunningUlaInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningUlaVersion, 606, RunningUlaInfo, FieldType_NumericU32, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningUlaApplicationStorageLocation, 607, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(RunningUlaPatchStorageLocation, 608, RunningUlaInfo, FieldType_String, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDTotalSizeOfSystem, 609, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
HANDLER(NANDFreeSpaceOfSystem, 610, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
#include <stratosphere/sf/sf_buffer_tags.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt {
|
||||||
|
|
||||||
|
constexpr inline u32 CategoriesPerMultipleCategoryContext = 0x10;
|
||||||
|
constexpr inline u32 FieldsPerMultipleCategoryContext = CategoriesPerMultipleCategoryContext * 4;
|
||||||
|
|
||||||
|
struct MultipleCategoryContextEntry : public sf::LargeData, public sf::PrefersMapAliasTransferMode {
|
||||||
|
u32 version;
|
||||||
|
u32 category_count;
|
||||||
|
CategoryId categories[CategoriesPerMultipleCategoryContext];
|
||||||
|
u32 field_counts[CategoriesPerMultipleCategoryContext];
|
||||||
|
u32 array_buf_counts[CategoriesPerMultipleCategoryContext];
|
||||||
|
FieldEntry fields[FieldsPerMultipleCategoryContext];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
#include <stratosphere/time/time_posix_time.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_ids.autogen.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt {
|
||||||
|
|
||||||
|
#define GENERATE_ENUM(NAME, ID, ...) NAME = ID,
|
||||||
|
|
||||||
|
enum FieldType {
|
||||||
|
AMS_ERPT_FOREACH_FIELD_TYPE(GENERATE_ENUM)
|
||||||
|
FieldType_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef GENERATE_ENUM
|
||||||
|
|
||||||
|
#define GENERATE_ENUM(NAME, ID, ...) CategoryId_##NAME = ID,
|
||||||
|
|
||||||
|
enum CategoryId {
|
||||||
|
AMS_ERPT_FOREACH_CATEGORY(GENERATE_ENUM)
|
||||||
|
CategoryId_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef GENERATE_ENUM
|
||||||
|
|
||||||
|
#define GENERATE_ENUM(NAME, ID, ...) FieldId_##NAME = ID,
|
||||||
|
|
||||||
|
enum FieldId {
|
||||||
|
AMS_ERPT_FOREACH_FIELD(GENERATE_ENUM)
|
||||||
|
FieldId_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef GENERATE_ENUM
|
||||||
|
|
||||||
|
constexpr inline u32 ArrayBufferSizeDefault = 0x100;
|
||||||
|
constexpr inline u32 ArrayBufferSizeMax = 96_KB;
|
||||||
|
constexpr inline u32 ArrayFieldSizeMax = 16_KB - 1;
|
||||||
|
|
||||||
|
enum ReportType {
|
||||||
|
ReportType_Start = 0,
|
||||||
|
|
||||||
|
ReportType_Visible = ReportType_Start,
|
||||||
|
ReportType_Invisible = 1,
|
||||||
|
|
||||||
|
ReportType_End = 2,
|
||||||
|
|
||||||
|
ReportType_Count = ReportType_End,
|
||||||
|
|
||||||
|
ReportType_Any = ReportType_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline u32 ReportCountMax = 50;
|
||||||
|
constexpr inline u32 AttachmentsPerReportMax = 5;
|
||||||
|
constexpr inline u32 AttachmentCountMax = ReportCountMax * AttachmentsPerReportMax;
|
||||||
|
|
||||||
|
constexpr inline u32 ReportMetaDataSize = 0x20;
|
||||||
|
struct ReportMetaData {
|
||||||
|
u8 user_data[ReportMetaDataSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
constexpr inline u32 ReportIdSize = 20;
|
||||||
|
struct ReportId {
|
||||||
|
union {
|
||||||
|
u8 id[ReportIdSize];
|
||||||
|
util::Uuid uuid;
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct {
|
||||||
|
u32 time_low;
|
||||||
|
u16 time_mid;
|
||||||
|
u16 time_high_and_version;
|
||||||
|
u8 clock_high;
|
||||||
|
u8 clock_low;
|
||||||
|
u64 node;
|
||||||
|
} uuid_data;
|
||||||
|
#pragma pack(pop)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ReportId) == ReportIdSize);
|
||||||
|
|
||||||
|
inline bool operator==(const ReportId &lhs, const ReportId &rhs) {
|
||||||
|
return std::memcmp(lhs.id, rhs.id, sizeof(lhs.uuid)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const ReportId &lhs, const ReportId &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReportFlag {
|
||||||
|
using Transmitted = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>::Flag<0>;
|
||||||
|
using HasAttachment = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>::Flag<1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ReportFlagSet = util::BitFlagSet<BITSIZEOF(u32), ReportFlag>;
|
||||||
|
static_assert(std::is_pod<ReportFlagSet>::value);
|
||||||
|
static_assert(sizeof(ReportFlagSet) == sizeof(u32));
|
||||||
|
|
||||||
|
struct ReportInfo {
|
||||||
|
ReportType type;
|
||||||
|
ReportId id;
|
||||||
|
ReportMetaData meta_data;
|
||||||
|
ReportFlagSet flags;
|
||||||
|
time::PosixTime timestamp_user;
|
||||||
|
time::PosixTime timestamp_network;
|
||||||
|
s64 report_size;
|
||||||
|
u64 reserved[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReportList {
|
||||||
|
u32 report_count;
|
||||||
|
ReportInfo reports[ReportCountMax];
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline u32 AttachmentIdSize = 20;
|
||||||
|
struct AttachmentId {
|
||||||
|
union {
|
||||||
|
u8 id[AttachmentIdSize];
|
||||||
|
util::Uuid uuid;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AttachmentId) == AttachmentIdSize);
|
||||||
|
|
||||||
|
inline bool operator==(const AttachmentId &lhs, const AttachmentId &rhs) {
|
||||||
|
return std::memcmp(lhs.id, rhs.id, sizeof(lhs.uuid)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const AttachmentId &lhs, const AttachmentId &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AttachmentFlag {
|
||||||
|
using HasOwner = util::BitFlagSet<BITSIZEOF(u32), AttachmentFlag>::Flag<1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AttachmentFlagSet = util::BitFlagSet<BITSIZEOF(u32), AttachmentFlag>;
|
||||||
|
static_assert(std::is_pod<AttachmentFlagSet>::value);
|
||||||
|
static_assert(sizeof(AttachmentFlagSet) == sizeof(u32));
|
||||||
|
|
||||||
|
constexpr inline u32 AttachmentNameSizeMax = 0x20;
|
||||||
|
struct AttachmentInfo {
|
||||||
|
ReportId owner_report_id;
|
||||||
|
AttachmentId attachment_id;
|
||||||
|
AttachmentFlagSet flags;
|
||||||
|
s64 attachment_size;
|
||||||
|
char attachment_name[AttachmentNameSizeMax];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AttachmentList {
|
||||||
|
u32 attachment_count;
|
||||||
|
AttachmentInfo attachments[AttachmentsPerReportMax];
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline u32 AttachmentSizeMax = 512_KB;
|
||||||
|
|
||||||
|
struct FieldEntry {
|
||||||
|
FieldId id;
|
||||||
|
FieldType type;
|
||||||
|
union {
|
||||||
|
u64 value_u64;
|
||||||
|
u32 value_u32;
|
||||||
|
u16 value_u16;
|
||||||
|
u8 value_u8;
|
||||||
|
s64 value_i64;
|
||||||
|
s32 value_i32;
|
||||||
|
s16 value_i16;
|
||||||
|
s8 value_i8;
|
||||||
|
bool value_bool;
|
||||||
|
struct {
|
||||||
|
u32 start_idx;
|
||||||
|
u32 size;
|
||||||
|
} value_array;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline u32 FieldsPerContext = 20;
|
||||||
|
struct ContextEntry {
|
||||||
|
u32 version;
|
||||||
|
u32 field_count;
|
||||||
|
CategoryId category;
|
||||||
|
FieldEntry fields[FieldsPerContext];
|
||||||
|
u8 *array_buffer;
|
||||||
|
u32 array_free_count;
|
||||||
|
u32 array_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StorageUsageStatistics {
|
||||||
|
util::Uuid journal_uuid;
|
||||||
|
u32 used_storage_size;
|
||||||
|
s64 max_report_size;
|
||||||
|
u32 report_count[ReportType_Count];
|
||||||
|
u32 transmitted_count[ReportType_Count];
|
||||||
|
u32 untransmitted_count[ReportType_Count];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* https://github.com/msgpack/msgpack/blob/master/spec.md#overview */
|
||||||
|
enum class ValueTypeTag {
|
||||||
|
FixMap = 0x80,
|
||||||
|
FixArray = 0x90,
|
||||||
|
FixStr = 0xA0,
|
||||||
|
False = 0xC2,
|
||||||
|
True = 0xC3,
|
||||||
|
Bin8 = 0xC4,
|
||||||
|
Bin16 = 0xC5,
|
||||||
|
U8 = 0xCC,
|
||||||
|
U16 = 0xCD,
|
||||||
|
U32 = 0xCE,
|
||||||
|
U64 = 0xCF,
|
||||||
|
I8 = 0xD0,
|
||||||
|
I16 = 0xD1,
|
||||||
|
I32 = 0xD2,
|
||||||
|
I64 = 0xD3,
|
||||||
|
Str8 = 0xD9,
|
||||||
|
Str16 = 0xDA,
|
||||||
|
Array16 = 0xDC,
|
||||||
|
Map16 = 0xDE,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::sf {
|
||||||
|
|
||||||
|
class IAttachment : public ams::sf::IServiceObject {
|
||||||
|
protected:
|
||||||
|
enum class CommandId {
|
||||||
|
Open = 0,
|
||||||
|
Read = 1,
|
||||||
|
SetFlags = 2,
|
||||||
|
GetFlags = 3,
|
||||||
|
Close = 4,
|
||||||
|
GetSize = 5,
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
virtual Result Open(const AttachmentId &attachment_id) = 0;
|
||||||
|
virtual Result Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) = 0;
|
||||||
|
virtual Result SetFlags(AttachmentFlagSet flags) = 0;
|
||||||
|
virtual Result GetFlags(ams::sf::Out<AttachmentFlagSet> out) = 0;
|
||||||
|
virtual Result Close() = 0;
|
||||||
|
virtual Result GetSize(ams::sf::Out<s64> out) = 0;
|
||||||
|
public:
|
||||||
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MAKE_SERVICE_COMMAND_META(Open),
|
||||||
|
MAKE_SERVICE_COMMAND_META(Read),
|
||||||
|
MAKE_SERVICE_COMMAND_META(SetFlags),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetFlags),
|
||||||
|
MAKE_SERVICE_COMMAND_META(Close),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetSize),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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>
|
||||||
|
#include <stratosphere/sf.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_multiple_category_context.hpp>
|
||||||
|
#include <stratosphere/time/time_steady_clock_time_point.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::sf {
|
||||||
|
|
||||||
|
class IContext : public ams::sf::IServiceObject {
|
||||||
|
protected:
|
||||||
|
enum class CommandId {
|
||||||
|
SubmitContext = 0,
|
||||||
|
CreateReport = 1,
|
||||||
|
SetInitialLaunchSettingsCompletionTime = 2,
|
||||||
|
ClearInitialLaunchSettingsCompletionTime = 3,
|
||||||
|
UpdatePowerOnTime = 4,
|
||||||
|
UpdateAwakeTime = 5,
|
||||||
|
SubmitMultipleCategoryContext = 6,
|
||||||
|
UpdateApplicationLaunchTime = 7,
|
||||||
|
ClearApplicationLaunchTime = 8,
|
||||||
|
SubmitAttachment = 9,
|
||||||
|
CreateReportWithAttachments = 10,
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
virtual Result SubmitContext(const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer) = 0;
|
||||||
|
virtual Result CreateReport(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer) = 0;
|
||||||
|
virtual Result SetInitialLaunchSettingsCompletionTime(const time::SteadyClockTimePoint &time_point) = 0;
|
||||||
|
virtual Result ClearInitialLaunchSettingsCompletionTime() = 0;
|
||||||
|
virtual Result UpdatePowerOnTime() = 0;
|
||||||
|
virtual Result UpdateAwakeTime() = 0;
|
||||||
|
virtual Result SubmitMultipleCategoryContext(const MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer) = 0;
|
||||||
|
virtual Result UpdateApplicationLaunchTime() = 0;
|
||||||
|
virtual Result ClearApplicationLaunchTime() = 0;
|
||||||
|
virtual Result SubmitAttachment(ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data) = 0;
|
||||||
|
virtual Result CreateReportWithAttachments(ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer) = 0;
|
||||||
|
public:
|
||||||
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MAKE_SERVICE_COMMAND_META(SubmitContext),
|
||||||
|
MAKE_SERVICE_COMMAND_META(CreateReport),
|
||||||
|
MAKE_SERVICE_COMMAND_META(SetInitialLaunchSettingsCompletionTime, hos::Version_300),
|
||||||
|
MAKE_SERVICE_COMMAND_META(ClearInitialLaunchSettingsCompletionTime, hos::Version_300),
|
||||||
|
MAKE_SERVICE_COMMAND_META(UpdatePowerOnTime, hos::Version_300),
|
||||||
|
MAKE_SERVICE_COMMAND_META(UpdateAwakeTime, hos::Version_300),
|
||||||
|
MAKE_SERVICE_COMMAND_META(SubmitMultipleCategoryContext, hos::Version_500),
|
||||||
|
MAKE_SERVICE_COMMAND_META(UpdateApplicationLaunchTime, hos::Version_600),
|
||||||
|
MAKE_SERVICE_COMMAND_META(ClearApplicationLaunchTime, hos::Version_600),
|
||||||
|
MAKE_SERVICE_COMMAND_META(SubmitAttachment, hos::Version_800),
|
||||||
|
MAKE_SERVICE_COMMAND_META(CreateReportWithAttachments, hos::Version_800),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::sf {
|
||||||
|
|
||||||
|
class IManager : public ams::sf::IServiceObject {
|
||||||
|
protected:
|
||||||
|
enum class CommandId {
|
||||||
|
GetReportList = 0,
|
||||||
|
GetEvent = 1,
|
||||||
|
CleanupReports = 2,
|
||||||
|
DeleteReport = 3,
|
||||||
|
GetStorageUsageStatistics = 4,
|
||||||
|
GetAttachmentList = 5,
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
virtual Result GetReportList(const ams::sf::OutBuffer &out_list, ReportType type_filter) = 0;
|
||||||
|
virtual Result GetEvent(ams::sf::OutCopyHandle out) = 0;
|
||||||
|
virtual Result CleanupReports() = 0;
|
||||||
|
virtual Result DeleteReport(const ReportId &report_id) = 0;
|
||||||
|
virtual Result GetStorageUsageStatistics(ams::sf::Out<StorageUsageStatistics> out) = 0;
|
||||||
|
virtual Result GetAttachmentList(const ams::sf::OutBuffer &out_buf, const ReportId &report_id) = 0;
|
||||||
|
public:
|
||||||
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetReportList),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetEvent),
|
||||||
|
MAKE_SERVICE_COMMAND_META(CleanupReports, hos::Version_400),
|
||||||
|
MAKE_SERVICE_COMMAND_META(DeleteReport, hos::Version_500),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetStorageUsageStatistics, hos::Version_500),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetAttachmentList, hos::Version_800),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::sf {
|
||||||
|
|
||||||
|
class IReport : public ams::sf::IServiceObject {
|
||||||
|
protected:
|
||||||
|
enum class CommandId {
|
||||||
|
Open = 0,
|
||||||
|
Read = 1,
|
||||||
|
SetFlags = 2,
|
||||||
|
GetFlags = 3,
|
||||||
|
Close = 4,
|
||||||
|
GetSize = 5,
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
virtual Result Open(const ReportId &report_id) = 0;
|
||||||
|
virtual Result Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) = 0;
|
||||||
|
virtual Result SetFlags(ReportFlagSet flags) = 0;
|
||||||
|
virtual Result GetFlags(ams::sf::Out<ReportFlagSet> out) = 0;
|
||||||
|
virtual Result Close() = 0;
|
||||||
|
virtual Result GetSize(ams::sf::Out<s64> out) = 0;
|
||||||
|
public:
|
||||||
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MAKE_SERVICE_COMMAND_META(Open),
|
||||||
|
MAKE_SERVICE_COMMAND_META(Read),
|
||||||
|
MAKE_SERVICE_COMMAND_META(SetFlags),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetFlags),
|
||||||
|
MAKE_SERVICE_COMMAND_META(Close),
|
||||||
|
MAKE_SERVICE_COMMAND_META(GetSize),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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>
|
||||||
|
#include <stratosphere/erpt/erpt_types.hpp>
|
||||||
|
#include <stratosphere/erpt/sf/erpt_sf_i_report.hpp>
|
||||||
|
#include <stratosphere/erpt/sf/erpt_sf_i_manager.hpp>
|
||||||
|
#include <stratosphere/erpt/sf/erpt_sf_i_attachment.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::sf {
|
||||||
|
|
||||||
|
class ISession : public ams::sf::IServiceObject {
|
||||||
|
protected:
|
||||||
|
enum class CommandId {
|
||||||
|
OpenReport = 0,
|
||||||
|
OpenManager = 1,
|
||||||
|
OpenAttachment = 2,
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
virtual Result OpenReport(ams::sf::Out<std::shared_ptr<erpt::sf::IReport>> out) = 0;
|
||||||
|
virtual Result OpenManager(ams::sf::Out<std::shared_ptr<erpt::sf::IManager>> out) = 0;
|
||||||
|
virtual Result OpenAttachment(ams::sf::Out<std::shared_ptr<erpt::sf::IAttachment>> out) = 0;
|
||||||
|
public:
|
||||||
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MAKE_SERVICE_COMMAND_META(OpenReport),
|
||||||
|
MAKE_SERVICE_COMMAND_META(OpenManager),
|
||||||
|
MAKE_SERVICE_COMMAND_META(OpenAttachment, hos::Version_800),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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::erpt::srv {
|
||||||
|
|
||||||
|
Result Initialize(u8 *mem, size_t mem_size);
|
||||||
|
Result InitializeAndStartService();
|
||||||
|
|
||||||
|
Result SetSerialNumberAndOsVersion(const char *sn, u32 sn_len, const char *os, u32 os_len, const char *os_priv, u32 os_priv_len);
|
||||||
|
Result SetProductModel(const char *model, u32 model_len);
|
||||||
|
Result SetRegionSetting(const char *region, u32 region_len);
|
||||||
|
|
||||||
|
/* Atmosphere extension. */
|
||||||
|
Result SetRedirectNewReportsToSdCard(bool redirect);
|
||||||
|
|
||||||
|
void Wait();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
#include <stratosphere/erpt/erpt_ids.autogen.hpp>
|
||||||
|
|
||||||
|
namespace ams::erpt::srv {
|
||||||
|
|
||||||
|
constexpr inline const char ReportOnSdStoragePath[] = "ersd";
|
||||||
|
|
||||||
|
constexpr inline const char ReportStoragePath[] = "save";
|
||||||
|
constexpr inline const char JournalFileName[] = "save:/journal";
|
||||||
|
|
||||||
|
constexpr size_t ReportFileNameLength = 64;
|
||||||
|
constexpr size_t AttachmentFileNameLength = 64;
|
||||||
|
constexpr size_t MaxFieldStringSize = 64;
|
||||||
|
|
||||||
|
struct ReportFileName {
|
||||||
|
char name[ReportFileNameLength];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AttachmentFileName {
|
||||||
|
char name[AttachmentFileNameLength];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FieldFlag : u8 {
|
||||||
|
FieldFlag_None = 0,
|
||||||
|
FieldFlag_Encrypt = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STRINGIZE_HANDLER(NAME, ...) #NAME,
|
||||||
|
constexpr inline const char * const FieldString[] = {
|
||||||
|
AMS_ERPT_FOREACH_FIELD(STRINGIZE_HANDLER)
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline const char * const CategoryString[] = {
|
||||||
|
AMS_ERPT_FOREACH_CATEGORY(STRINGIZE_HANDLER)
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline const char * const TypeString[] = {
|
||||||
|
AMS_ERPT_FOREACH_FIELD_TYPE(STRINGIZE_HANDLER)
|
||||||
|
};
|
||||||
|
#undef STRINGIZE_HANDLER
|
||||||
|
|
||||||
|
#define GET_FIELD_CATEGORY(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = CategoryId_##CATEGORY,
|
||||||
|
constexpr inline const CategoryId FieldToCategoryMap[] = {
|
||||||
|
AMS_ERPT_FOREACH_FIELD(GET_FIELD_CATEGORY)
|
||||||
|
};
|
||||||
|
#undef GET_FIELD_CATEGORY
|
||||||
|
|
||||||
|
#define GET_FIELD_TYPE(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = TYPE,
|
||||||
|
constexpr inline const FieldType FieldToTypeMap[] = {
|
||||||
|
AMS_ERPT_FOREACH_FIELD(GET_FIELD_TYPE)
|
||||||
|
};
|
||||||
|
#undef GET_FIELD_TYPE
|
||||||
|
|
||||||
|
#define GET_FIELD_FLAG(FIELD, ID, CATEGORY, TYPE, FLAG) [FieldId_##FIELD] = FLAG,
|
||||||
|
constexpr inline const FieldFlag FieldToFlagMap[] = {
|
||||||
|
AMS_ERPT_FOREACH_FIELD(GET_FIELD_FLAG)
|
||||||
|
};
|
||||||
|
#undef GET_FIELD_FLAG
|
||||||
|
|
||||||
|
constexpr inline ReportFlagSet MakeNoReportFlags() {
|
||||||
|
return util::MakeBitFlagSet<32, ReportFlag>();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline AttachmentFlagSet MakeNoAttachmentFlags() {
|
||||||
|
return util::MakeBitFlagSet<32, AttachmentFlag>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -324,28 +324,20 @@ namespace ams::fatal {
|
|||||||
bool is_creport;
|
bool is_creport;
|
||||||
CpuContext cpu_ctx;
|
CpuContext cpu_ctx;
|
||||||
bool generate_error_report;
|
bool generate_error_report;
|
||||||
Event erpt_event;
|
os::Event *erpt_event;
|
||||||
Event battery_event;
|
os::Event *battery_event;
|
||||||
size_t stack_dump_size;
|
size_t stack_dump_size;
|
||||||
u64 stack_dump_base;
|
u64 stack_dump_base;
|
||||||
u8 stack_dump[0x100];
|
u8 stack_dump[0x100];
|
||||||
u64 tls_address;
|
u64 tls_address;
|
||||||
u8 tls_dump[0x100];
|
u8 tls_dump[0x100];
|
||||||
|
|
||||||
void ClearState() {
|
ThrowContext(os::Event *erpt, os::Event *bat)
|
||||||
this->result = ResultSuccess();
|
: result(ResultSuccess()), program_id(), proc_name(), is_creport(), cpu_ctx(), generate_error_report(),
|
||||||
this->program_id = ncm::ProgramId::Invalid;
|
erpt_event(erpt), battery_event(bat),
|
||||||
std::memset(this->proc_name, 0, sizeof(this->proc_name));
|
stack_dump_size(), stack_dump_base(), stack_dump(), tls_address(), tls_dump()
|
||||||
this->is_creport = false;
|
{
|
||||||
std::memset(&this->cpu_ctx, 0, sizeof(this->cpu_ctx));
|
/* ... */
|
||||||
this->generate_error_report = false;
|
|
||||||
std::memset(&this->erpt_event, 0, sizeof(this->erpt_event));
|
|
||||||
std::memset(&this->battery_event, 0, sizeof(this->battery_event));
|
|
||||||
this->stack_dump_size = 0;
|
|
||||||
this->stack_dump_base = 0;
|
|
||||||
std::memset(this->stack_dump, 0, sizeof(this->stack_dump));
|
|
||||||
this->tls_address = 0;
|
|
||||||
std::memset(this->tls_dump, 0, sizeof(this->tls_dump));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,11 +41,13 @@
|
|||||||
#include <stratosphere/fs/fs_code.hpp>
|
#include <stratosphere/fs/fs_code.hpp>
|
||||||
#include <stratosphere/fs/fs_content.hpp>
|
#include <stratosphere/fs/fs_content.hpp>
|
||||||
#include <stratosphere/fs/fs_content_storage.hpp>
|
#include <stratosphere/fs/fs_content_storage.hpp>
|
||||||
|
#include <stratosphere/fs/fs_image_directory.hpp>
|
||||||
#include <stratosphere/fs/fs_game_card.hpp>
|
#include <stratosphere/fs/fs_game_card.hpp>
|
||||||
#include <stratosphere/fs/fs_save_data_types.hpp>
|
#include <stratosphere/fs/fs_save_data_types.hpp>
|
||||||
#include <stratosphere/fs/fs_save_data_management.hpp>
|
#include <stratosphere/fs/fs_save_data_management.hpp>
|
||||||
#include <stratosphere/fs/fs_save_data_transaction.hpp>
|
#include <stratosphere/fs/fs_save_data_transaction.hpp>
|
||||||
|
#include <stratosphere/fs/fs_device_save_data.hpp>
|
||||||
|
#include <stratosphere/fs/fs_system_save_data.hpp>
|
||||||
#include <stratosphere/fs/fs_sd_card.hpp>
|
#include <stratosphere/fs/fs_sd_card.hpp>
|
||||||
#include <stratosphere/fs/fs_signed_system_partition.hpp>
|
#include <stratosphere/fs/fs_signed_system_partition.hpp>
|
||||||
#include <stratosphere/fs/fs_system_data.hpp>
|
#include <stratosphere/fs/fs_system_data.hpp>
|
||||||
#include <stratosphere/fs/fs_system_save_data.hpp>
|
|
||||||
|
|||||||
@@ -115,12 +115,11 @@ namespace ams::fs {
|
|||||||
return this->GetImpl(std::addressof(pos), out, key, hash_key, aux, aux_size);
|
return this->GetImpl(std::addressof(pos), out, key, hash_key, aux, aux_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FindOpen(FindIndex *out) const {
|
void FindOpen(FindIndex *out) const {
|
||||||
AMS_ASSERT(out != nullptr);
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
out->ind = static_cast<BucketIndex>(-1);
|
out->ind = static_cast<BucketIndex>(-1);
|
||||||
out->pos = InvalidPosition;
|
out->pos = InvalidPosition;
|
||||||
return ResultSuccess();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FindNext(Key *out_key, Value *out_val, FindIndex *find) {
|
Result FindNext(Key *out_key, Value *out_val, FindIndex *find) {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 "fs_common.hpp"
|
||||||
|
#include "fs_save_data_types.hpp"
|
||||||
|
|
||||||
|
namespace ams::fs {
|
||||||
|
|
||||||
|
Result MountDeviceSaveData(const char *name);
|
||||||
|
Result MountDeviceSaveData(const char *name, const ncm::ApplicationId application_id);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,13 +14,14 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "fs_common.hpp"
|
#include <stratosphere/fs/fs_common.hpp>
|
||||||
#include "fs_istorage.hpp"
|
#include <stratosphere/fs/fs_istorage.hpp>
|
||||||
#include "fsa/fs_ifile.hpp"
|
#include <stratosphere/fs/fsa/fs_ifile.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
class FileStorage : public IStorage {
|
class FileStorage : public IStorage, public impl::Newable {
|
||||||
private:
|
private:
|
||||||
static constexpr s64 InvalidSize = -1;
|
static constexpr s64 InvalidSize = -1;
|
||||||
private:
|
private:
|
||||||
@@ -53,4 +54,32 @@ namespace ams::fs {
|
|||||||
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FileHandleStorage : public IStorage, public impl::Newable {
|
||||||
|
private:
|
||||||
|
static constexpr s64 InvalidSize = -1;
|
||||||
|
private:
|
||||||
|
FileHandle handle;
|
||||||
|
bool close_file;
|
||||||
|
s64 size;
|
||||||
|
os::Mutex mutex;
|
||||||
|
public:
|
||||||
|
constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex(false) { /* ... */ }
|
||||||
|
constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ }
|
||||||
|
|
||||||
|
virtual ~FileHandleStorage() override {
|
||||||
|
if (this->close_file) {
|
||||||
|
CloseFile(this->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
Result UpdateSize();
|
||||||
|
public:
|
||||||
|
virtual Result Read(s64 offset, void *buffer, size_t size) override;
|
||||||
|
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
|
||||||
|
virtual Result Flush() override;
|
||||||
|
virtual Result GetSize(s64 *out_size) override;
|
||||||
|
virtual Result SetSize(s64 size) override;
|
||||||
|
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 "fs_common.hpp"
|
||||||
|
|
||||||
|
namespace ams::fs {
|
||||||
|
|
||||||
|
enum class ImageDirectoryId {
|
||||||
|
Nand = 0,
|
||||||
|
SdCard = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Result MountImageDirectory(const char *name, ImageDirectoryId id);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
struct QueryRangeInfo {
|
struct QueryRangeInfo {
|
||||||
u32 aes_ctr_key_type;
|
s32 aes_ctr_key_type;
|
||||||
u32 speed_emulation_type;
|
s32 speed_emulation_type;
|
||||||
u32 reserved[0x38 / sizeof(u32)];
|
u8 reserved[0x38];
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
this->aes_ctr_key_type = 0;
|
this->aes_ctr_key_type = 0;
|
||||||
@@ -45,4 +45,8 @@ namespace ams::fs {
|
|||||||
|
|
||||||
Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size);
|
Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size);
|
||||||
|
|
||||||
|
enum class AesCtrKeyTypeFlag : s32 {
|
||||||
|
InternalKeyForSoftwareAes = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace ams::fs {
|
|||||||
private:
|
private:
|
||||||
virtual Result OpenFileImpl(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
|
virtual Result OpenFileImpl(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
|
||||||
/* Only allow opening files with mode = read. */
|
/* Only allow opening files with mode = read. */
|
||||||
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidArgument());
|
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
|
||||||
|
|
||||||
std::unique_ptr<fsa::IFile> base_file;
|
std::unique_ptr<fsa::IFile> base_file;
|
||||||
R_TRY(this->base_fs->OpenFile(std::addressof(base_file), path, mode));
|
R_TRY(this->base_fs->OpenFile(std::addressof(base_file), path, mode));
|
||||||
|
|||||||
@@ -19,12 +19,26 @@
|
|||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
union RightsId {
|
union RightsId {
|
||||||
u8 data[0x10];
|
u8 data[0x10];
|
||||||
u64 data64[2];
|
u64 data64[2];
|
||||||
};
|
};
|
||||||
static_assert(sizeof(RightsId) == 0x10);
|
static_assert(sizeof(RightsId) == 0x10);
|
||||||
static_assert(std::is_pod<RightsId>::value);
|
static_assert(std::is_pod<RightsId>::value);
|
||||||
|
|
||||||
|
inline bool operator==(const RightsId &lhs, const RightsId &rhs) {
|
||||||
|
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const RightsId &lhs, const RightsId &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const RightsId &lhs, const RightsId &rhs) {
|
||||||
|
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline RightsId InvalidRightsId = {};
|
||||||
|
|
||||||
/* Rights ID API */
|
/* Rights ID API */
|
||||||
Result GetRightsId(RightsId *out, const char *path);
|
Result GetRightsId(RightsId *out, const char *path);
|
||||||
Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path);
|
Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path);
|
||||||
|
|||||||
@@ -26,4 +26,9 @@ namespace ams::fs {
|
|||||||
Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id);
|
Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id);
|
||||||
Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags);
|
Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags);
|
||||||
|
|
||||||
|
Result GetSaveDataAvailableSize(s64 *out, SaveDataId id);
|
||||||
|
Result GetSaveDataJournalSize(s64 *out, SaveDataId id);
|
||||||
|
|
||||||
|
Result ExtendSaveData(SaveDataSpaceId space_id, SaveDataId id, s64 available_size, s64 journal_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,6 @@ namespace ams::fs {
|
|||||||
|
|
||||||
Result MountSdCard(const char *name);
|
Result MountSdCard(const char *name);
|
||||||
|
|
||||||
|
Result MountSdCardErrorReportDirectoryForAtmosphere(const char *name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace ams::fs {
|
|||||||
public:
|
public:
|
||||||
SubStorage() : shared_base_storage(), base_storage(nullptr), offset(0), size(0), resizable(false) { /* ... */ }
|
SubStorage() : shared_base_storage(), base_storage(nullptr), offset(0), size(0), resizable(false) { /* ... */ }
|
||||||
|
|
||||||
SubStorage(const SubStorage &rhs) : shared_base_storage(), base_storage(rhs.base_storage), offset(rhs.offset), size(rhs.size), resizable(rhs.resizable) { /* ... */}
|
SubStorage(const SubStorage &rhs) : shared_base_storage(), base_storage(rhs.base_storage), offset(rhs.offset), size(rhs.size), resizable(rhs.resizable) { /* ... */}
|
||||||
SubStorage &operator=(const SubStorage &rhs) {
|
SubStorage &operator=(const SubStorage &rhs) {
|
||||||
if (this != std::addressof(rhs)) {
|
if (this != std::addressof(rhs)) {
|
||||||
this->base_storage = rhs.base_storage;
|
this->base_storage = rhs.base_storage;
|
||||||
@@ -44,19 +44,19 @@ namespace ams::fs {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubStorage(IStorage *storage, s64 o, s64 sz) : shared_base_storage(), base_storage(storage), offset(o), size(sz) {
|
SubStorage(IStorage *storage, s64 o, s64 sz) : shared_base_storage(), base_storage(storage), offset(o), size(sz), resizable(false) {
|
||||||
AMS_ABORT_UNLESS(this->IsValid());
|
AMS_ABORT_UNLESS(this->IsValid());
|
||||||
AMS_ABORT_UNLESS(this->offset >= 0);
|
AMS_ABORT_UNLESS(this->offset >= 0);
|
||||||
AMS_ABORT_UNLESS(this->size >= 0);
|
AMS_ABORT_UNLESS(this->size >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubStorage(std::shared_ptr<IStorage> storage, s64 o, s64 sz) : shared_base_storage(storage), base_storage(storage.get()), offset(o), size(sz) {
|
SubStorage(std::shared_ptr<IStorage> storage, s64 o, s64 sz) : shared_base_storage(storage), base_storage(storage.get()), offset(o), size(sz), resizable(false) {
|
||||||
AMS_ABORT_UNLESS(this->IsValid());
|
AMS_ABORT_UNLESS(this->IsValid());
|
||||||
AMS_ABORT_UNLESS(this->offset >= 0);
|
AMS_ABORT_UNLESS(this->offset >= 0);
|
||||||
AMS_ABORT_UNLESS(this->size >= 0);
|
AMS_ABORT_UNLESS(this->size >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubStorage(SubStorage *sub, s64 o, s64 sz) : shared_base_storage(), base_storage(sub->base_storage), offset(o + sub->offset), size(sz) {
|
SubStorage(SubStorage *sub, s64 o, s64 sz) : shared_base_storage(), base_storage(sub->base_storage), offset(o + sub->offset), size(sz), resizable(false) {
|
||||||
AMS_ABORT_UNLESS(this->IsValid());
|
AMS_ABORT_UNLESS(this->IsValid());
|
||||||
AMS_ABORT_UNLESS(this->offset >= 0);
|
AMS_ABORT_UNLESS(this->offset >= 0);
|
||||||
AMS_ABORT_UNLESS(this->size >= 0);
|
AMS_ABORT_UNLESS(this->size >= 0);
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace ams::fs::fsa {
|
|||||||
protected:
|
protected:
|
||||||
Result DryRead(size_t *out, s64 offset, size_t size, const fs::ReadOption &option, OpenMode open_mode) {
|
Result DryRead(size_t *out, s64 offset, size_t size, const fs::ReadOption &option, OpenMode open_mode) {
|
||||||
/* Check that we can read. */
|
/* Check that we can read. */
|
||||||
R_UNLESS((open_mode & OpenMode_Read) != 0, fs::ResultInvalidOperationForOpenMode());
|
R_UNLESS((open_mode & OpenMode_Read) != 0, fs::ResultReadNotPermitted());
|
||||||
|
|
||||||
/* Get the file size, and validate our offset. */
|
/* Get the file size, and validate our offset. */
|
||||||
s64 file_size = 0;
|
s64 file_size = 0;
|
||||||
@@ -98,12 +98,31 @@ namespace ams::fs::fsa {
|
|||||||
|
|
||||||
Result DrySetSize(s64 size, fs::OpenMode open_mode) {
|
Result DrySetSize(s64 size, fs::OpenMode open_mode) {
|
||||||
/* Check that we can write. */
|
/* Check that we can write. */
|
||||||
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultInvalidOperationForOpenMode());
|
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
|
||||||
|
|
||||||
AMS_ASSERT(size >= 0);
|
AMS_ASSERT(size >= 0);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result DryWrite(bool *out_append, s64 offset, size_t size, const fs::WriteOption &option, fs::OpenMode open_mode) {
|
||||||
|
/* Check that we can write. */
|
||||||
|
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
|
||||||
|
|
||||||
|
/* Get the file size. */
|
||||||
|
s64 file_size = 0;
|
||||||
|
R_TRY(this->GetSize(&file_size));
|
||||||
|
|
||||||
|
/* Determine if we need to append. */
|
||||||
|
if (file_size < offset + static_cast<s64>(size)) {
|
||||||
|
R_UNLESS((open_mode & OpenMode_AllowAppend) != 0, fs::ResultFileExtensionWithoutOpenModeAllowAppend());
|
||||||
|
*out_append = true;
|
||||||
|
} else {
|
||||||
|
*out_append = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
virtual Result ReadImpl(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) = 0;
|
virtual Result ReadImpl(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) = 0;
|
||||||
virtual Result GetSizeImpl(s64 *out) = 0;
|
virtual Result GetSizeImpl(s64 *out) = 0;
|
||||||
|
|||||||
@@ -83,16 +83,16 @@ namespace ams::fs::fsa {
|
|||||||
Result OpenFile(std::unique_ptr<IFile> *out_file, const char *path, OpenMode mode) {
|
Result OpenFile(std::unique_ptr<IFile> *out_file, const char *path, OpenMode mode) {
|
||||||
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
|
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
|
||||||
R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument());
|
R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument());
|
||||||
R_UNLESS((mode & OpenMode_ReadWrite) != 0, fs::ResultInvalidArgument());
|
R_UNLESS((mode & OpenMode_ReadWrite) != 0, fs::ResultInvalidOpenMode());
|
||||||
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidArgument());
|
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidOpenMode());
|
||||||
return this->OpenFileImpl(out_file, path, mode);
|
return this->OpenFileImpl(out_file, path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) {
|
Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) {
|
||||||
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
|
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
|
||||||
R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument());
|
R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument());
|
||||||
R_UNLESS((mode & OpenDirectoryMode_All) != 0, fs::ResultInvalidArgument());
|
R_UNLESS((mode & OpenDirectoryMode_All) != 0, fs::ResultInvalidOpenMode());
|
||||||
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidArgument());
|
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidOpenMode());
|
||||||
return this->OpenDirectoryImpl(out_dir, path, mode);
|
return this->OpenDirectoryImpl(out_dir, path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "fssystem/fssystem_utility.hpp"
|
#include <stratosphere/fssystem/fssystem_utility.hpp>
|
||||||
#include "fssystem/fssystem_external_code.hpp"
|
#include <stratosphere/fssystem/fssystem_external_code.hpp>
|
||||||
#include "fssystem/fssystem_path_tool.hpp"
|
#include <stratosphere/fssystem/fssystem_partition_file_system.hpp>
|
||||||
#include "fssystem/fssystem_subdirectory_filesystem.hpp"
|
#include <stratosphere/fssystem/fssystem_partition_file_system_meta.hpp>
|
||||||
#include "fssystem/fssystem_directory_redirection_filesystem.hpp"
|
#include <stratosphere/fssystem/fssystem_path_tool.hpp>
|
||||||
#include "fssystem/fssystem_directory_savedata_filesystem.hpp"
|
#include <stratosphere/fssystem/fssystem_thread_priority_changer.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_aes_ctr_storage.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_aes_xts_storage.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_subdirectory_filesystem.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_directory_redirection_filesystem.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_directory_savedata_filesystem.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_romfs_file_system.hpp>
|
||||||
|
#include <stratosphere/fssystem/buffers/fssystem_buffer_manager_utils.hpp>
|
||||||
|
#include <stratosphere/fssystem/buffers/fssystem_file_system_buddy_heap.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_pooled_buffer.hpp>
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem::buffers {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
constexpr inline auto RetryWait = TimeSpan::FromMilliSeconds(10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F, typename OnFailure>
|
||||||
|
Result DoContinuouslyUntilBufferIsAllocated(F f, OnFailure on_failure, const char *function_name) {
|
||||||
|
constexpr auto BufferAllocationRetryLogCountMax = 10;
|
||||||
|
constexpr auto BufferAllocationRetryLogInterval = 100;
|
||||||
|
for (auto count = 1; true; count++) {
|
||||||
|
R_TRY_CATCH(f()) {
|
||||||
|
R_CATCH(fs::ResultBufferAllocationFailed) {
|
||||||
|
if ((1 <= count && count <= BufferAllocationRetryLogCountMax) || ((count % BufferAllocationRetryLogInterval) == 0)) {
|
||||||
|
/* TODO: Log */
|
||||||
|
}
|
||||||
|
R_TRY(on_failure());
|
||||||
|
|
||||||
|
/* TODO: os::SleepThread */
|
||||||
|
svc::SleepThread(impl::RetryWait.GetNanoSeconds());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
Result DoContinuouslyUntilBufferIsAllocated(F f, const char *function_name) {
|
||||||
|
R_TRY(DoContinuouslyUntilBufferIsAllocated(f, []() ALWAYS_INLINE_LAMBDA { return ResultSuccess(); }, function_name));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BufferManagerContext {
|
||||||
|
private:
|
||||||
|
bool needs_blocking;
|
||||||
|
public:
|
||||||
|
constexpr BufferManagerContext() : needs_blocking(false) { /* ... */ }
|
||||||
|
public:
|
||||||
|
bool IsNeedBlocking() const { return this->needs_blocking; }
|
||||||
|
|
||||||
|
void SetNeedBlocking(bool need) { this->needs_blocking = need; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void RegisterBufferManagerContext(const BufferManagerContext *context);
|
||||||
|
BufferManagerContext *GetBufferManagerContext();
|
||||||
|
void EnableBlockingBufferManagerAllocation();
|
||||||
|
|
||||||
|
class ScopedBufferManagerContextRegistration {
|
||||||
|
private:
|
||||||
|
BufferManagerContext cur_context;
|
||||||
|
const BufferManagerContext *old_context;
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE explicit ScopedBufferManagerContextRegistration() {
|
||||||
|
this->old_context = GetBufferManagerContext();
|
||||||
|
if (this->old_context != nullptr) {
|
||||||
|
this->cur_context = *this->old_context;
|
||||||
|
}
|
||||||
|
RegisterBufferManagerContext(std::addressof(this->cur_context));
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE ~ScopedBufferManagerContextRegistration() {
|
||||||
|
RegisterBufferManagerContext(this->old_context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
class FileSystemBuddyHeap {
|
||||||
|
NON_COPYABLE(FileSystemBuddyHeap);
|
||||||
|
NON_MOVEABLE(FileSystemBuddyHeap);
|
||||||
|
public:
|
||||||
|
static constexpr size_t BufferAlignment = sizeof(void *);
|
||||||
|
static constexpr size_t BlockSizeMin = 2 * sizeof(void *);
|
||||||
|
static constexpr s32 OrderUpperLimit = BITSIZEOF(s32) - 1;
|
||||||
|
private:
|
||||||
|
class PageList;
|
||||||
|
|
||||||
|
struct PageEntry { PageEntry *next; };
|
||||||
|
static_assert(std::is_pod<PageEntry>::value);
|
||||||
|
static_assert(sizeof(PageEntry) <= BlockSizeMin);
|
||||||
|
|
||||||
|
class PageList : public ::ams::fs::impl::Newable {
|
||||||
|
NON_COPYABLE(PageList);
|
||||||
|
NON_MOVEABLE(PageList);
|
||||||
|
private:
|
||||||
|
PageEntry *first_page_entry;
|
||||||
|
PageEntry *last_page_entry;
|
||||||
|
s32 entry_count;
|
||||||
|
public:
|
||||||
|
constexpr PageList() : first_page_entry(), last_page_entry(), entry_count() { /* ... */ }
|
||||||
|
|
||||||
|
constexpr bool IsEmpty() const { return this->entry_count == 0; }
|
||||||
|
constexpr s32 GetSize() const { return this->entry_count; }
|
||||||
|
|
||||||
|
constexpr const PageEntry *GetFront() const { return this->first_page_entry; }
|
||||||
|
public:
|
||||||
|
PageEntry *PopFront();
|
||||||
|
void PushBack(PageEntry *page_entry);
|
||||||
|
bool Remove(PageEntry *page_entry);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
size_t block_size;
|
||||||
|
s32 order_max;
|
||||||
|
uintptr_t heap_start;
|
||||||
|
size_t heap_size;
|
||||||
|
|
||||||
|
PageList *free_lists;
|
||||||
|
size_t total_free_size;
|
||||||
|
PageList *external_free_lists;
|
||||||
|
std::unique_ptr<PageList[]> internal_free_lists;
|
||||||
|
public:
|
||||||
|
static constexpr s32 GetBlockCountFromOrder(s32 order) {
|
||||||
|
AMS_ASSERT(0 <= order);
|
||||||
|
AMS_ASSERT(order < OrderUpperLimit);
|
||||||
|
return (1 << order);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr size_t QueryWorkBufferSize(s32 order_max) {
|
||||||
|
AMS_ASSERT(0 < order_max && order_max < OrderUpperLimit);
|
||||||
|
return util::AlignUp(sizeof(PageList) * (order_max + 1) + alignof(PageList), alignof(u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr s32 QueryOrderMax(size_t size, size_t block_size) {
|
||||||
|
AMS_ASSERT(size >= block_size);
|
||||||
|
AMS_ASSERT(block_size >= BlockSizeMin);
|
||||||
|
AMS_ASSERT(util::IsPowerOfTwo(block_size));
|
||||||
|
const auto block_count = static_cast<s32>(util::AlignUp(size, block_size) / block_size);
|
||||||
|
for (auto order = 1; true; order++) {
|
||||||
|
if (block_count <= GetBlockCountFromOrder(order)) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr FileSystemBuddyHeap() : block_size(), order_max(), heap_start(), heap_size(), free_lists(), total_free_size(), external_free_lists(), internal_free_lists() { /* ... */ }
|
||||||
|
|
||||||
|
Result Initialize(uintptr_t address, size_t size, size_t block_size, s32 order_max);
|
||||||
|
|
||||||
|
Result Initialize(uintptr_t address, size_t size, size_t block_size) {
|
||||||
|
return this->Initialize(address, size, block_size, QueryOrderMax(size, block_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Initialize(uintptr_t address, size_t size, size_t block_size, s32 order_max, void *work, size_t work_size) {
|
||||||
|
AMS_ASSERT(work_size >= QueryWorkBufferSize(order_max));
|
||||||
|
const auto aligned_work = util::AlignUp(reinterpret_cast<uintptr_t>(work), alignof(PageList));
|
||||||
|
this->external_free_lists = reinterpret_cast<PageList *>(aligned_work);
|
||||||
|
return this->Initialize(address, size, block_size, order_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Initialize(uintptr_t address, size_t size, size_t block_size, void *work, size_t work_size) {
|
||||||
|
return this->Initialize(address, size, block_size, QueryOrderMax(size, block_size), work, work_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
void *AllocateByOrder(s32 order);
|
||||||
|
void Free(void *ptr, s32 order);
|
||||||
|
|
||||||
|
size_t GetTotalFreeSize() const;
|
||||||
|
size_t GetAllocatableSizeMax() const;
|
||||||
|
void Dump() const;
|
||||||
|
|
||||||
|
s32 GetOrderFromBytes(size_t size) const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
return this->GetOrderFromBlockCount(this->GetBlockCountFromSize(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetBytesFromOrder(s32 order) const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
AMS_ASSERT(0 <= order);
|
||||||
|
AMS_ASSERT(order < this->GetOrderMax());
|
||||||
|
return (this->GetBlockSize() << order);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetOrderMax() const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
return this->order_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetBlockSize() const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
return this->block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetPageBlockCountMax() const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
return 1 << this->GetOrderMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetPageSizeMax() const {
|
||||||
|
AMS_ASSERT(this->free_lists != nullptr);
|
||||||
|
return this->GetPageBlockCountMax() * this->GetBlockSize();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void DivideBuddies(PageEntry *page_entry, s32 required_order, s32 chosen_order);
|
||||||
|
void JoinBuddies(PageEntry *page_entry, s32 order);
|
||||||
|
PageEntry *GetBuddy(PageEntry *page_entry, s32 order);
|
||||||
|
PageEntry *GetFreePageEntry(s32 order);
|
||||||
|
|
||||||
|
s32 GetOrderFromBlockCount(s32 block_count) const;
|
||||||
|
|
||||||
|
s32 GetBlockCountFromSize(size_t size) const {
|
||||||
|
const size_t bsize = this->GetBlockSize();
|
||||||
|
return static_cast<s32>(util::AlignUp(size, bsize) / bsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t GetAddressFromPageEntry(const PageEntry &page_entry) const {
|
||||||
|
const uintptr_t address = reinterpret_cast<uintptr_t>(std::addressof(page_entry));
|
||||||
|
AMS_ASSERT(this->heap_start <= address);
|
||||||
|
AMS_ASSERT(address < this->heap_start + this->heap_size);
|
||||||
|
AMS_ASSERT(util::IsAligned(address - this->heap_start, this->GetBlockSize()));
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageEntry *GetPageEntryFromAddress(uintptr_t address) const {
|
||||||
|
AMS_ASSERT(this->heap_start <= address);
|
||||||
|
AMS_ASSERT(address < this->heap_start + this->heap_size);
|
||||||
|
return reinterpret_cast<PageEntry *>(this->heap_start + util::AlignDown(address - this->heap_start, this->GetBlockSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetIndexFromPageEntry(const PageEntry &page_entry) const {
|
||||||
|
const uintptr_t address = reinterpret_cast<uintptr_t>(std::addressof(page_entry));
|
||||||
|
AMS_ASSERT(this->heap_start <= address);
|
||||||
|
AMS_ASSERT(address < this->heap_start + this->heap_size);
|
||||||
|
AMS_ASSERT(util::IsAligned(address - this->heap_start, this->GetBlockSize()));
|
||||||
|
return static_cast<s32>((address - this->heap_start) / this->GetBlockSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAlignedToOrder(const PageEntry *page_entry, s32 order) const {
|
||||||
|
return util::IsAligned(GetIndexFromPageEntry(*page_entry), GetBlockCountFromOrder(order));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fs/fs_istorage.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
class AesCtrStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
|
||||||
|
NON_COPYABLE(AesCtrStorage);
|
||||||
|
NON_MOVEABLE(AesCtrStorage);
|
||||||
|
public:
|
||||||
|
static constexpr size_t BlockSize = crypto::Aes128CtrEncryptor::BlockSize;
|
||||||
|
static constexpr size_t KeySize = crypto::Aes128CtrEncryptor::KeySize;
|
||||||
|
static constexpr size_t IvSize = crypto::Aes128CtrEncryptor::IvSize;
|
||||||
|
private:
|
||||||
|
IStorage * const base_storage;
|
||||||
|
char key[KeySize];
|
||||||
|
char iv[IvSize];
|
||||||
|
public:
|
||||||
|
static void MakeIv(void *dst, size_t dst_size, u64 upper, s64 offset);
|
||||||
|
public:
|
||||||
|
AesCtrStorage(IStorage *base, const void *key, size_t key_size, const void *iv, size_t iv_size);
|
||||||
|
|
||||||
|
virtual Result Read(s64 offset, void *buffer, size_t size) override;
|
||||||
|
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
|
||||||
|
|
||||||
|
virtual Result Flush() override;
|
||||||
|
|
||||||
|
virtual Result SetSize(s64 size) override;
|
||||||
|
virtual Result GetSize(s64 *out) override;
|
||||||
|
|
||||||
|
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fs/fs_istorage.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
class AesXtsStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
|
||||||
|
NON_COPYABLE(AesXtsStorage);
|
||||||
|
NON_MOVEABLE(AesXtsStorage);
|
||||||
|
public:
|
||||||
|
static constexpr size_t AesBlockSize = crypto::Aes128XtsEncryptor::BlockSize;
|
||||||
|
static constexpr size_t KeySize = crypto::Aes128XtsEncryptor::KeySize;
|
||||||
|
static constexpr size_t IvSize = crypto::Aes128XtsEncryptor::IvSize;
|
||||||
|
private:
|
||||||
|
IStorage * const base_storage;
|
||||||
|
char key[2][KeySize];
|
||||||
|
char iv[IvSize];
|
||||||
|
const size_t block_size;
|
||||||
|
os::Mutex mutex;
|
||||||
|
public:
|
||||||
|
AesXtsStorage(IStorage *base, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, size_t block_size);
|
||||||
|
|
||||||
|
virtual Result Read(s64 offset, void *buffer, size_t size) override;
|
||||||
|
virtual Result Write(s64 offset, const void *buffer, size_t size) override;
|
||||||
|
|
||||||
|
virtual Result Flush() override;
|
||||||
|
|
||||||
|
virtual Result SetSize(s64 size) override;
|
||||||
|
virtual Result GetSize(s64 *out) override;
|
||||||
|
|
||||||
|
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,684 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fssystem/fssystem_dbm_rom_types.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_dbm_rom_path_tool.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_dbm_rom_key_value_storage.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
template<typename DBS, typename DES, typename FBS, typename FES>
|
||||||
|
class HierarchicalRomFileTable {
|
||||||
|
private:
|
||||||
|
using DirectoryBucketStorage = DBS;
|
||||||
|
using DirectoryEntryStorage = DES;
|
||||||
|
using FileBucketStorage = FBS;
|
||||||
|
using FileEntryStorage = FES;
|
||||||
|
public:
|
||||||
|
using Position = u32;
|
||||||
|
|
||||||
|
struct FindPosition {
|
||||||
|
Position next_dir;
|
||||||
|
Position next_file;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<FindPosition>::value);
|
||||||
|
|
||||||
|
using DirectoryInfo = RomDirectoryInfo;
|
||||||
|
using FileInfo = RomFileInfo;
|
||||||
|
|
||||||
|
static constexpr RomFileId ConvertToFileId(Position pos) {
|
||||||
|
return static_cast<RomFileId>(pos);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static constexpr inline Position InvalidPosition = ~Position();
|
||||||
|
static constexpr inline Position RootPosition = 0;
|
||||||
|
static constexpr inline size_t ReservedDirectoryCount = 1;
|
||||||
|
|
||||||
|
static constexpr RomDirectoryId ConvertToDirectoryId(Position pos) {
|
||||||
|
return static_cast<RomDirectoryId>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Position ConvertToPosition(RomDirectoryId id) {
|
||||||
|
return static_cast<Position>(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(std::is_same<RomDirectoryId, RomFileId>::value);
|
||||||
|
|
||||||
|
struct RomDirectoryEntry {
|
||||||
|
Position next;
|
||||||
|
Position dir;
|
||||||
|
Position file;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomDirectoryEntry>::value);
|
||||||
|
|
||||||
|
struct RomFileEntry {
|
||||||
|
Position next;
|
||||||
|
FileInfo info;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomFileEntry>::value);
|
||||||
|
|
||||||
|
static constexpr inline u32 MaxKeyLength = RomPathTool::MaxPathLength;
|
||||||
|
|
||||||
|
template<typename BucketStorageType, typename EntryStorageType, typename ImplKeyType, typename ClientKeyType, typename ValueType>
|
||||||
|
class EntryMapTable : public RomKeyValueStorage<BucketStorageType, EntryStorageType, ImplKeyType, ValueType, MaxKeyLength> {
|
||||||
|
private:
|
||||||
|
using BucketStorage = BucketStorageType;
|
||||||
|
using EntryStorage = EntryStorageType;
|
||||||
|
public:
|
||||||
|
using ImplKey = ImplKeyType;
|
||||||
|
using ClientKey = ClientKeyType;
|
||||||
|
using Value = ValueType;
|
||||||
|
using Position = HierarchicalRomFileTable::Position;
|
||||||
|
using Base = RomKeyValueStorage<BucketStorageType, EntryStorageType, ImplKeyType, ValueType, MaxKeyLength>;
|
||||||
|
public:
|
||||||
|
Result Add(Position *out, const ClientKeyType &key, const Value &value) {
|
||||||
|
return Base::AddImpl(out, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Get(Position *out_pos, Value *out_val, const ClientKeyType &key) const {
|
||||||
|
return Base::GetImpl(out_pos, out_val, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetByPosition(ImplKey *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) const {
|
||||||
|
return Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetByPosition(Position pos, const Value &value, fs::WriteOption option) const {
|
||||||
|
return Base::SetByPosition(pos, value, option);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RomEntryKey {
|
||||||
|
Position parent;
|
||||||
|
|
||||||
|
bool IsEqual(const RomEntryKey &rhs, const void *aux_lhs, size_t aux_lhs_size, const void *aux_rhs, size_t aux_rhs_size) const {
|
||||||
|
if (this->parent != rhs.parent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (aux_lhs_size != aux_rhs_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return RomPathTool::IsEqualPath(reinterpret_cast<const RomPathChar *>(aux_lhs), reinterpret_cast<const RomPathChar *>(aux_rhs), aux_lhs_size / sizeof(RomPathChar));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomEntryKey>::value);
|
||||||
|
|
||||||
|
struct EntryKey {
|
||||||
|
RomEntryKey key;
|
||||||
|
RomPathTool::RomEntryName name;
|
||||||
|
|
||||||
|
constexpr u32 Hash() const {
|
||||||
|
u32 hash = this->key.parent ^ 123456789;
|
||||||
|
const RomPathChar *name = this->name.path;
|
||||||
|
const RomPathChar *end = name + this->name.length;
|
||||||
|
while (name < end) {
|
||||||
|
const u32 cur = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(name++)));
|
||||||
|
hash = ((hash >> 5) | (hash << 27)) ^ cur;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<EntryKey>::value);
|
||||||
|
|
||||||
|
using DirectoryEntryMapTable = EntryMapTable<DirectoryBucketStorage, DirectoryEntryStorage, RomEntryKey, EntryKey, RomDirectoryEntry>;
|
||||||
|
using FileEntryMapTable = EntryMapTable<FileBucketStorage, FileEntryStorage, RomEntryKey, EntryKey, RomFileEntry>;
|
||||||
|
private:
|
||||||
|
DirectoryEntryMapTable dir_table;
|
||||||
|
FileEntryMapTable file_table;
|
||||||
|
public:
|
||||||
|
static u32 QueryDirectoryEntrySize(u32 name_len) {
|
||||||
|
AMS_ABORT_UNLESS(name_len <= RomPathTool::MaxPathLength);
|
||||||
|
return DirectoryEntryMapTable::QueryEntrySize(name_len * sizeof(RomPathChar));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 QueryFileEntrySize(u32 name_len) {
|
||||||
|
AMS_ABORT_UNLESS(name_len <= RomPathTool::MaxPathLength);
|
||||||
|
return FileEntryMapTable::QueryEntrySize(name_len * sizeof(RomPathChar));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 QueryDirectoryEntryBucketStorageSize(u32 count) { return DirectoryEntryMapTable::QueryBucketStorageSize(count); }
|
||||||
|
static u32 QueryFileEntryBucketStorageSize(u32 count) { return FileEntryMapTable::QueryBucketStorageSize(count); }
|
||||||
|
|
||||||
|
static Result Format(DirectoryBucketStorage *dir_bucket, s64 dir_bucket_ofs, u32 dir_bucket_size, DirectoryEntryStorage *dir_entry, s64 dir_entry_ofs, u32 dir_entry_size, FileBucketStorage *file_bucket, s64 file_bucket_ofs, u32 file_bucket_size, FileEntryStorage *file_entry, s64 file_entry_ofs, u32 file_entry_size) {
|
||||||
|
R_TRY(DirectoryEntryMapTable::Format(dir_bucket, dir_bucket_ofs, DirectoryEntryMapTable::QueryBucketCount(dir_bucket_size), dir_entry, dir_entry_ofs, dir_entry_size));
|
||||||
|
R_TRY(FileEntryMapTable::Format(file_bucket, file_bucket_ofs, FileEntryMapTable::QueryBucketCount(file_bucket_size), file_entry, file_entry_ofs, file_entry_size));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
HierarchicalRomFileTable() { /* ... */ }
|
||||||
|
|
||||||
|
constexpr u32 GetDirectoryEntryCount() const {
|
||||||
|
return this->dir_table.GetEntryCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetFileEntryCount() const {
|
||||||
|
return this->file_table.GetEntryCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Initialize(DirectoryBucketStorage *dir_bucket, s64 dir_bucket_ofs, u32 dir_bucket_size, DirectoryEntryStorage *dir_entry, s64 dir_entry_ofs, u32 dir_entry_size, FileBucketStorage *file_bucket, s64 file_bucket_ofs, u32 file_bucket_size, FileEntryStorage *file_entry, s64 file_entry_ofs, u32 file_entry_size) {
|
||||||
|
AMS_ASSERT(dir_bucket != nullptr);
|
||||||
|
AMS_ASSERT(dir_entry != nullptr);
|
||||||
|
AMS_ASSERT(file_bucket != nullptr);
|
||||||
|
AMS_ASSERT(file_entry != nullptr);
|
||||||
|
|
||||||
|
R_TRY(this->dir_table.Initialize(dir_bucket, dir_bucket_ofs, DirectoryEntryMapTable::QueryBucketCount(dir_bucket_size), dir_entry, dir_entry_ofs, dir_entry_size));
|
||||||
|
R_TRY(this->file_table.Initialize(file_bucket, file_bucket_ofs, FileEntryMapTable::QueryBucketCount(file_bucket_size), file_entry, file_entry_ofs, file_entry_size));
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize() {
|
||||||
|
this->dir_table.Finalize();
|
||||||
|
this->file_table.Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result CreateRootDirectory() {
|
||||||
|
Position root_pos = RootPosition;
|
||||||
|
EntryKey root_key = {};
|
||||||
|
root_key.key.parent = root_pos;
|
||||||
|
RomPathTool::InitializeRomEntryName(std::addressof(root_key.name));
|
||||||
|
RomDirectoryEntry root_entry = {
|
||||||
|
.next = InvalidPosition,
|
||||||
|
.dir = InvalidPosition,
|
||||||
|
.file = InvalidPosition,
|
||||||
|
};
|
||||||
|
return this->dir_table.Add(std::addressof(root_pos), root_key, root_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path, const DirectoryInfo &info) {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey new_key = {};
|
||||||
|
R_TRY(this->FindDirectoryRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(new_key), path));
|
||||||
|
|
||||||
|
R_TRY(this->CheckSameEntryExists(new_key, fs::ResultDbmAlreadyExists()));
|
||||||
|
|
||||||
|
RomDirectoryEntry new_entry = {
|
||||||
|
.next = InvalidPosition,
|
||||||
|
.dir = InvalidPosition,
|
||||||
|
.file = InvalidPosition,
|
||||||
|
};
|
||||||
|
|
||||||
|
Position new_pos = 0;
|
||||||
|
R_TRY_CATCH(this->dir_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||||
|
R_CONVERT(fs::ResultDbmKeyFull, fs::ResultDbmDirectoryEntryFull())
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
*out = ConvertToDirectoryId(new_pos);
|
||||||
|
|
||||||
|
if (parent_entry.dir == InvalidPosition) {
|
||||||
|
parent_entry.dir = new_pos;
|
||||||
|
|
||||||
|
R_TRY(this->dir_table.SetByPosition(new_key.key.parent, parent_entry, fs::WriteOption::None));
|
||||||
|
} else {
|
||||||
|
Position cur_pos = parent_entry.dir;
|
||||||
|
while (true) {
|
||||||
|
RomEntryKey cur_key = {};
|
||||||
|
RomDirectoryEntry cur_entry = {};
|
||||||
|
R_TRY(this->dir_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), nullptr, nullptr, cur_pos));
|
||||||
|
|
||||||
|
if (cur_entry.next == InvalidPosition) {
|
||||||
|
cur_entry.next = new_pos;
|
||||||
|
|
||||||
|
R_TRY(this->dir_table.SetByPosition(cur_pos, cur_entry, fs::WriteOption::None));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_pos = cur_entry.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result CreateFile(RomFileId *out, const RomPathChar *path, const FileInfo &info) {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey new_key = {};
|
||||||
|
R_TRY(this->FindFileRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(new_key), path));
|
||||||
|
|
||||||
|
R_TRY(this->CheckSameEntryExists(new_key, fs::ResultDbmAlreadyExists()));
|
||||||
|
|
||||||
|
RomFileEntry new_entry = {
|
||||||
|
.next = InvalidPosition,
|
||||||
|
.info = info,
|
||||||
|
};
|
||||||
|
|
||||||
|
Position new_pos = 0;
|
||||||
|
R_TRY_CATCH(this->file_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||||
|
R_CONVERT(fs::ResultDbmKeyFull, fs::ResultDbmFileEntryFull())
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
*out = ConvertToFileId(new_pos);
|
||||||
|
|
||||||
|
if (parent_entry.file == InvalidPosition) {
|
||||||
|
parent_entry.file = new_pos;
|
||||||
|
|
||||||
|
R_TRY(this->dir_table.SetByPosition(new_key.key.parent, parent_entry, fs::WriteOption::None));
|
||||||
|
} else {
|
||||||
|
Position cur_pos = parent_entry.file;
|
||||||
|
while (true) {
|
||||||
|
RomEntryKey cur_key = {};
|
||||||
|
RomFileEntry cur_entry = {};
|
||||||
|
R_TRY(this->file_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), nullptr, nullptr, cur_pos));
|
||||||
|
|
||||||
|
if (cur_entry.next == InvalidPosition) {
|
||||||
|
cur_entry.next = new_pos;
|
||||||
|
|
||||||
|
R_TRY(this->file_table.SetByPosition(cur_pos, cur_entry, fs::WriteOption::None));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_pos = cur_entry.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ConvertPathToDirectoryId(RomDirectoryId *out, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey key = {};
|
||||||
|
R_TRY(this->FindDirectoryRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(key), path));
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(pos), std::addressof(entry), key));
|
||||||
|
|
||||||
|
*out = ConvertToDirectoryId(pos);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ConvertPathToFileId(RomFileId *out, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey key = {};
|
||||||
|
R_TRY(this->FindDirectoryRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(key), path));
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
R_TRY(this->GetFileEntry(std::addressof(pos), std::addressof(entry), key));
|
||||||
|
|
||||||
|
*out = ConvertToFileId(pos);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirectoryInformation(DirectoryInfo *out, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey key = {};
|
||||||
|
R_TRY(this->FindDirectoryRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(key), path));
|
||||||
|
|
||||||
|
return this->GetDirectoryInformation(out, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirectoryInformation(DirectoryInfo *out, RomDirectoryId id) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(entry), id));
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenFile(FileInfo *out, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey key = {};
|
||||||
|
R_TRY(this->FindFileRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(key), path));
|
||||||
|
|
||||||
|
return this->OpenFile(out, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenFile(FileInfo *out, RomFileId id) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
R_TRY(this->GetFileEntry(std::addressof(entry), id));
|
||||||
|
|
||||||
|
*out = entry.info;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindOpen(FindPosition *out, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
EntryKey parent_key = {};
|
||||||
|
RomDirectoryEntry parent_entry = {};
|
||||||
|
EntryKey key = {};
|
||||||
|
R_TRY(this->FindDirectoryRecursive(std::addressof(parent_key), std::addressof(parent_entry), std::addressof(key), path));
|
||||||
|
|
||||||
|
return this->FindOpen(out, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindOpen(FindPosition *out, RomDirectoryId id) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
out->next_dir = InvalidPosition;
|
||||||
|
out->next_file = InvalidPosition;
|
||||||
|
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(entry), id));
|
||||||
|
|
||||||
|
out->next_dir = entry.dir;
|
||||||
|
out->next_file = entry.file;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindNextDirectory(RomPathChar *out, FindPosition *find) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(find != nullptr);
|
||||||
|
|
||||||
|
R_UNLESS(find->next_dir != InvalidPosition, fs::ResultDbmFindFinished());
|
||||||
|
|
||||||
|
RomEntryKey key = {};
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
size_t aux_size = 0;
|
||||||
|
R_TRY(this->dir_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_dir));
|
||||||
|
|
||||||
|
out[aux_size / sizeof(RomPathChar)] = RomStringTraits::NullTerminator;
|
||||||
|
|
||||||
|
find->next_dir = entry.next;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindNextFile(RomPathChar *out, FindPosition *find) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(find != nullptr);
|
||||||
|
|
||||||
|
R_UNLESS(find->next_file != InvalidPosition, fs::ResultDbmFindFinished());
|
||||||
|
|
||||||
|
RomEntryKey key = {};
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
size_t aux_size = 0;
|
||||||
|
R_TRY(this->file_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_file));
|
||||||
|
|
||||||
|
out[aux_size / sizeof(RomPathChar)] = RomStringTraits::NullTerminator;
|
||||||
|
|
||||||
|
find->next_file = entry.next;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result QueryRomFileSystemSize(u32 *out_dir_entry_size, u32 *out_file_entry_size) {
|
||||||
|
AMS_ASSERT(out_dir_entry_size != nullptr);
|
||||||
|
AMS_ASSERT(out_file_entry_size != nullptr);
|
||||||
|
|
||||||
|
*out_dir_entry_size = this->dir_table.GetTotalEntrySize();
|
||||||
|
*out_file_entry_size = this->file_table.GetTotalEntrySize();
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Result GetGrandParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_dir_key != nullptr);
|
||||||
|
AMS_ASSERT(out_dir_entry != nullptr);
|
||||||
|
|
||||||
|
RomEntryKey gp_key = {};
|
||||||
|
RomDirectoryEntry gp_entry = {};
|
||||||
|
R_TRY(this->dir_table.GetByPosition(std::addressof(gp_key), std::addressof(gp_entry), nullptr, nullptr, pos));
|
||||||
|
out_dir_key->key.parent = gp_key.parent;
|
||||||
|
|
||||||
|
R_TRY(RomPathTool::GetParentDirectoryName(std::addressof(out_dir_key->name), name, path));
|
||||||
|
|
||||||
|
R_TRY(this->GetDirectoryEntry(out_pos, out_dir_entry, *out_dir_key));
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindParentDirectoryRecursive(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, RomPathTool::PathParser &parser, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_dir_key != nullptr);
|
||||||
|
AMS_ASSERT(out_dir_entry != nullptr);
|
||||||
|
|
||||||
|
Position dir_pos = RootPosition;
|
||||||
|
EntryKey dir_key = {};
|
||||||
|
RomDirectoryEntry dir_entry = {};
|
||||||
|
dir_key.key.parent = RootPosition;
|
||||||
|
|
||||||
|
R_TRY(parser.GetNextDirectoryName(std::addressof(dir_key.name)));
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(dir_pos), std::addressof(dir_entry), dir_key));
|
||||||
|
|
||||||
|
Position parent_pos = dir_pos;
|
||||||
|
while (!parser.IsFinished()) {
|
||||||
|
EntryKey old_key = dir_key;
|
||||||
|
|
||||||
|
R_TRY(parser.GetNextDirectoryName(std::addressof(dir_key.name)));
|
||||||
|
|
||||||
|
if (RomPathTool::IsCurrentDirectory(dir_key.name)) {
|
||||||
|
dir_key = old_key;
|
||||||
|
continue;
|
||||||
|
} else if (RomPathTool::IsParentDirectory(dir_key.name)) {
|
||||||
|
R_UNLESS(parent_pos != RootPosition, fs::ResultDbmInvalidOperation());
|
||||||
|
|
||||||
|
R_TRY(this->GetGrandParent(std::addressof(parent_pos), std::addressof(dir_key), std::addressof(dir_entry), dir_key.key.parent, dir_key.name, path));
|
||||||
|
} else {
|
||||||
|
dir_key.key.parent = parent_pos;
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(dir_pos), std::addressof(dir_entry), dir_key));
|
||||||
|
|
||||||
|
parent_pos = dir_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_pos = parent_pos;
|
||||||
|
*out_dir_key = dir_key;
|
||||||
|
*out_dir_entry = dir_entry;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindPathRecursive(EntryKey *out_parent_key, RomDirectoryEntry *out_parent_dir_entry, EntryKey *out_key, bool is_dir, const RomPathChar *path) const {
|
||||||
|
AMS_ASSERT(out_parent_key != nullptr);
|
||||||
|
AMS_ASSERT(out_parent_dir_entry != nullptr);
|
||||||
|
AMS_ASSERT(out_key != nullptr);
|
||||||
|
AMS_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
RomPathTool::PathParser parser;
|
||||||
|
R_TRY(parser.Initialize(path));
|
||||||
|
|
||||||
|
Position parent_pos = 0;
|
||||||
|
R_TRY(this->FindParentDirectoryRecursive(std::addressof(parent_pos), out_parent_key, out_parent_dir_entry, parser, path));
|
||||||
|
|
||||||
|
if (is_dir) {
|
||||||
|
RomPathTool::RomEntryName name = {};
|
||||||
|
R_TRY(parser.GetAsDirectoryName(std::addressof(name)));
|
||||||
|
|
||||||
|
if (RomPathTool::IsCurrentDirectory(name)) {
|
||||||
|
*out_key = *out_parent_key;
|
||||||
|
if (out_key->key.parent != RootPosition) {
|
||||||
|
Position pos = 0;
|
||||||
|
R_TRY(this->GetGrandParent(std::addressof(pos), out_parent_key, out_parent_dir_entry, out_key->key.parent, out_key->name, path));
|
||||||
|
}
|
||||||
|
} else if (RomPathTool::IsParentDirectory(name)) {
|
||||||
|
R_UNLESS(parent_pos != RootPosition, fs::ResultDbmInvalidOperation());
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomDirectoryEntry cur_entry = {};
|
||||||
|
R_TRY(this->GetGrandParent(std::addressof(pos), out_key, std::addressof(cur_entry), out_parent_key->key.parent, out_parent_key->name, path));
|
||||||
|
|
||||||
|
if (out_key->key.parent != RootPosition) {
|
||||||
|
R_TRY(this->GetGrandParent(std::addressof(pos), out_parent_key, out_parent_dir_entry, out_key->key.parent, out_key->name, path));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out_key->name = name;
|
||||||
|
out_key->key.parent = (out_key->name.length > 0) ? parent_pos : RootPosition;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
R_UNLESS(!parser.IsDirectoryPath(), fs::ResultDbmInvalidOperation());
|
||||||
|
|
||||||
|
out_key->key.parent = parent_pos;
|
||||||
|
R_TRY(parser.GetAsFileName(std::addressof(out_key->name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindDirectoryRecursive(EntryKey *out_parent_key, RomDirectoryEntry *out_parent_dir_entry, EntryKey *out_key, const RomPathChar *path) const {
|
||||||
|
return this->FindPathRecursive(out_parent_key, out_parent_dir_entry, out_key, true, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindFileRecursive(EntryKey *out_parent_key, RomDirectoryEntry *out_parent_dir_entry, EntryKey *out_key, const RomPathChar *path) const {
|
||||||
|
return this->FindPathRecursive(out_parent_key, out_parent_dir_entry, out_key, false, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result CheckSameEntryExists(const EntryKey &key, Result if_exists) const {
|
||||||
|
/* Check dir */
|
||||||
|
{
|
||||||
|
Position pos = InvalidPosition;
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
const Result get_res = this->dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||||
|
if (!fs::ResultDbmKeyNotFound::Includes(get_res)) {
|
||||||
|
R_TRY(get_res);
|
||||||
|
return if_exists;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check file */
|
||||||
|
{
|
||||||
|
Position pos = InvalidPosition;
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
const Result get_res = this->file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||||
|
if (!fs::ResultDbmKeyNotFound::Includes(get_res)) {
|
||||||
|
R_TRY(get_res);
|
||||||
|
return if_exists;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirectoryEntry(Position *out_pos, RomDirectoryEntry *out_entry, const EntryKey &key) const {
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_entry != nullptr);
|
||||||
|
|
||||||
|
const Result dir_res = this->dir_table.Get(out_pos, out_entry, key);
|
||||||
|
R_UNLESS(R_FAILED(dir_res), dir_res);
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), dir_res);
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
const Result file_res = this->file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||||
|
R_UNLESS(R_FAILED(file_res), fs::ResultDbmInvalidOperation());
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), fs::ResultDbmDirectoryNotFound());
|
||||||
|
return file_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirectoryEntry(RomDirectoryEntry *out_entry, RomDirectoryId id) const {
|
||||||
|
AMS_ASSERT(out_entry != nullptr);
|
||||||
|
Position pos = ConvertToPosition(id);
|
||||||
|
|
||||||
|
RomEntryKey key = {};
|
||||||
|
const Result dir_res = this->dir_table.GetByPosition(std::addressof(key), out_entry, nullptr, nullptr, pos);
|
||||||
|
R_UNLESS(R_FAILED(dir_res), dir_res);
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), dir_res);
|
||||||
|
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
const Result file_res = this->file_table.GetByPosition(std::addressof(key), std::addressof(entry), nullptr, nullptr, pos);
|
||||||
|
R_UNLESS(R_FAILED(file_res), fs::ResultDbmInvalidOperation());
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), fs::ResultDbmDirectoryNotFound());
|
||||||
|
return file_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetFileEntry(Position *out_pos, RomFileEntry *out_entry, const EntryKey &key) const {
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_entry != nullptr);
|
||||||
|
|
||||||
|
const Result file_res = this->file_table.Get(out_pos, out_entry, key);
|
||||||
|
R_UNLESS(R_FAILED(file_res), file_res);
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), file_res);
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
const Result dir_res = this->dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||||
|
R_UNLESS(R_FAILED(dir_res), fs::ResultDbmInvalidOperation());
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), fs::ResultDbmFileNotFound());
|
||||||
|
return dir_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetFileEntry(RomFileEntry *out_entry, RomFileId id) const {
|
||||||
|
AMS_ASSERT(out_entry != nullptr);
|
||||||
|
Position pos = ConvertToPosition(id);
|
||||||
|
|
||||||
|
RomEntryKey key = {};
|
||||||
|
const Result file_res = this->file_table.GetByPosition(std::addressof(key), out_entry, nullptr, nullptr, pos);
|
||||||
|
R_UNLESS(R_FAILED(file_res), file_res);
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), file_res);
|
||||||
|
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
const Result dir_res = this->dir_table.GetByPosition(std::addressof(key), std::addressof(entry), nullptr, nullptr, pos);
|
||||||
|
R_UNLESS(R_FAILED(dir_res), fs::ResultDbmInvalidOperation());
|
||||||
|
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), fs::ResultDbmFileNotFound());
|
||||||
|
return dir_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetDirectoryInformation(DirectoryInfo *out, const EntryKey &key) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(pos), std::addressof(entry), key));
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result OpenFile(FileInfo *out, const EntryKey &key) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomFileEntry entry = {};
|
||||||
|
R_TRY(this->GetFileEntry(std::addressof(pos), std::addressof(entry), key));
|
||||||
|
|
||||||
|
*out = entry.info;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindOpen(FindPosition *out, const EntryKey &key) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
out->next_dir = InvalidPosition;
|
||||||
|
out->next_file = InvalidPosition;
|
||||||
|
|
||||||
|
Position pos = 0;
|
||||||
|
RomDirectoryEntry entry = {};
|
||||||
|
R_TRY(this->GetDirectoryEntry(std::addressof(pos), std::addressof(entry), key));
|
||||||
|
|
||||||
|
out->next_dir = entry.dir;
|
||||||
|
out->next_file = entry.file;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fssystem/fssystem_dbm_rom_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u32 AlignRomAddress(u32 addr) {
|
||||||
|
return util::AlignUp(addr, sizeof(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BucketStorageType, typename EntryStorageType, typename KeyType, typename ValueType, size_t MaxAuxiliarySize>
|
||||||
|
class RomKeyValueStorage {
|
||||||
|
public:
|
||||||
|
using BucketStorage = BucketStorageType;
|
||||||
|
using EntryStorage = EntryStorageType;
|
||||||
|
using Key = KeyType;
|
||||||
|
using Value = ValueType;
|
||||||
|
using Position = u32;
|
||||||
|
using BucketIndex = u32;
|
||||||
|
|
||||||
|
struct FindIndex {
|
||||||
|
BucketIndex ind;
|
||||||
|
Position pos;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<FindIndex>::value);
|
||||||
|
private:
|
||||||
|
static constexpr inline Position InvalidPosition = ~Position();
|
||||||
|
|
||||||
|
struct Element {
|
||||||
|
Key key;
|
||||||
|
Value value;
|
||||||
|
Position next;
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<Element>::value);
|
||||||
|
private:
|
||||||
|
s64 bucket_offset;
|
||||||
|
u32 bucket_count;
|
||||||
|
BucketStorage *bucket_storage;
|
||||||
|
s64 kv_offset;
|
||||||
|
u32 kv_size;
|
||||||
|
EntryStorage *kv_storage;
|
||||||
|
u32 total_entry_size;
|
||||||
|
u32 entry_count;
|
||||||
|
public:
|
||||||
|
static constexpr u32 QueryEntrySize(u32 aux_size) {
|
||||||
|
return AlignRomAddress(sizeof(Element) + aux_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr u32 QueryBucketStorageSize(u32 num) {
|
||||||
|
return num * sizeof(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr u32 QueryBucketCount(u32 size) {
|
||||||
|
return size / sizeof(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr u32 QueryKeyValueStorageSize(u32 num) {
|
||||||
|
return num * sizeof(Element);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result Format(BucketStorage *bucket, s64 bucket_ofs, u32 bucket_count, EntryStorage *kv, s64 kv_ofs, u32 kv_size) {
|
||||||
|
AMS_ASSERT(bucket != nullptr);
|
||||||
|
AMS_ASSERT(kv != nullptr);
|
||||||
|
AMS_ASSERT(kv_size >= 0);
|
||||||
|
|
||||||
|
const Position pos = InvalidPosition;
|
||||||
|
for (s64 i = 0; i < bucket_count; i++) {
|
||||||
|
R_TRY(bucket->Write(bucket_ofs + i * sizeof(pos), std::addressof(pos), sizeof(pos)));
|
||||||
|
}
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
RomKeyValueStorage() : bucket_offset(), bucket_count(), bucket_storage(), kv_offset(), kv_size(), kv_storage(), total_entry_size(), entry_count() { /* ... */ }
|
||||||
|
|
||||||
|
Result Initialize(BucketStorage *bucket, s64 bucket_ofs, u32 bucket_count, EntryStorage *kv, s64 kv_ofs, u32 kv_size) {
|
||||||
|
AMS_ASSERT(bucket != nullptr);
|
||||||
|
AMS_ASSERT(kv != nullptr);
|
||||||
|
AMS_ASSERT(bucket_count > 0);
|
||||||
|
|
||||||
|
this->bucket_storage = bucket;
|
||||||
|
this->bucket_offset = bucket_ofs;
|
||||||
|
this->bucket_count = bucket_count;
|
||||||
|
|
||||||
|
this->kv_storage = kv;
|
||||||
|
this->kv_offset = kv_ofs;
|
||||||
|
this->kv_size = kv_size;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize() {
|
||||||
|
this->bucket_storage = nullptr;
|
||||||
|
this->bucket_offset = 0;
|
||||||
|
this->bucket_count = 0;
|
||||||
|
|
||||||
|
this->kv_storage = nullptr;
|
||||||
|
this->kv_offset = 0;
|
||||||
|
this->kv_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetTotalEntrySize() const {
|
||||||
|
return this->total_entry_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetFreeSize() const {
|
||||||
|
return (this->kv_size - this->total_entry_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 GetEntryCount() const {
|
||||||
|
return this->entry_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Add(const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
|
||||||
|
AMS_ASSERT(aux != nullptr);
|
||||||
|
AMS_ASSERT(aux_size <= MaxAuxiliarySize);
|
||||||
|
Position pos;
|
||||||
|
return this->AddImpl(std::addressof(pos), key, hash_key, aux, aux_size, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Get(Value *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
|
||||||
|
AMS_ASSERT(aux != nullptr);
|
||||||
|
AMS_ASSERT(aux_size <= MaxAuxiliarySize);
|
||||||
|
Position pos;
|
||||||
|
return this->GetImpl(std::addressof(pos), out, key, hash_key, aux, aux_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindOpen(FindIndex *out) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
out->ind = static_cast<BucketIndex>(-1);
|
||||||
|
out->pos = InvalidPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindNext(Key *out_key, Value *out_val, FindIndex *find) {
|
||||||
|
AMS_ASSERT(out_key != nullptr);
|
||||||
|
AMS_ASSERT(out_val != nullptr);
|
||||||
|
AMS_ASSERT(find != nullptr);
|
||||||
|
|
||||||
|
Element elem;
|
||||||
|
|
||||||
|
BucketIndex ind = find->ind;
|
||||||
|
R_UNLESS((ind < this->bucket_count) || ind == static_cast<BucketIndex>(-1), fs::ResultDbmFindKeyFinished());
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (find->pos != InvalidPosition) {
|
||||||
|
R_TRY(this->ReadKeyValue(std::addressof(elem), nullptr, nullptr, find->pos));
|
||||||
|
|
||||||
|
AMS_ASSERT(elem.next == InvalidPosition || elem.next < this->kv_size);
|
||||||
|
find->pos = elem.next;
|
||||||
|
*out_key = elem.key;
|
||||||
|
*out_val = elem.val;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ind++;
|
||||||
|
if (ind == this->bucket_count) {
|
||||||
|
find->ind = ind;
|
||||||
|
find->pos = InvalidPosition;
|
||||||
|
return fs::ResultDbmFindKeyFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
Position pos;
|
||||||
|
R_TRY(this->ReadBucket(std::addressof(pos), ind));
|
||||||
|
AMS_ASSERT(pos == InvalidPosition || pos < this->kv_size);
|
||||||
|
|
||||||
|
if (pos != InvalidPosition) {
|
||||||
|
find->ind = ind;
|
||||||
|
find->pos = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
Result AddImpl(Position *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
|
||||||
|
Position pos, prev_pos;
|
||||||
|
Element elem;
|
||||||
|
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(this->bucket_count > 0);
|
||||||
|
AMS_ASSERT(this->kv_size >= 0);
|
||||||
|
|
||||||
|
const Result find_res = this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size);
|
||||||
|
R_UNLESS(R_FAILED(find_res), fs::ResultDbmAlreadyExists());
|
||||||
|
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(find_res), find_res);
|
||||||
|
|
||||||
|
R_TRY(this->AllocateEntry(std::addressof(pos), aux_size));
|
||||||
|
|
||||||
|
Position next_pos;
|
||||||
|
R_TRY(this->LinkEntry(std::addressof(next_pos), pos, hash_key));
|
||||||
|
|
||||||
|
elem = { key, value, next_pos, static_cast<u32>(aux_size) };
|
||||||
|
*out = pos;
|
||||||
|
R_TRY(this->WriteKeyValue(std::addressof(elem), pos, aux, aux_size, fs::WriteOption::None));
|
||||||
|
|
||||||
|
this->entry_count++;
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetImpl(Position *out_pos, Value *out_val, const Key &key, u32 hash_key, const void *aux, size_t aux_size) const {
|
||||||
|
Position pos, prev_pos;
|
||||||
|
Element elem;
|
||||||
|
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_val != nullptr);
|
||||||
|
|
||||||
|
R_TRY(this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size));
|
||||||
|
|
||||||
|
*out_pos = pos;
|
||||||
|
*out_val = elem.value;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetByPosition(Key *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) const {
|
||||||
|
AMS_ASSERT(out_key != nullptr);
|
||||||
|
AMS_ASSERT(out_val != nullptr);
|
||||||
|
|
||||||
|
Element elem;
|
||||||
|
R_TRY(this->ReadKeyValue(std::addressof(elem), out_aux, out_aux_size, pos));
|
||||||
|
|
||||||
|
*out_key = elem.key;
|
||||||
|
*out_val = elem.value;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetByPosition(Position pos, const Value &value, fs::WriteOption option) const {
|
||||||
|
Element elem;
|
||||||
|
R_TRY(this->ReadKeyValue(std::addressof(elem), nullptr, nullptr, pos));
|
||||||
|
elem.value = value;
|
||||||
|
return this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0, option);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
BucketIndex HashToBucket(u32 hash_key) const {
|
||||||
|
return hash_key % this->bucket_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FindImpl(Position *out_pos, Position *out_prev, Element *out_elem, const Key &key, u32 hash_key, const void *aux, size_t aux_size) const {
|
||||||
|
AMS_ASSERT(out_pos != nullptr);
|
||||||
|
AMS_ASSERT(out_prev != nullptr);
|
||||||
|
AMS_ASSERT(out_elem != nullptr);
|
||||||
|
AMS_ASSERT(this->bucket_count > 0);
|
||||||
|
AMS_ASSERT(this->kv_size >= 0);
|
||||||
|
|
||||||
|
*out_pos = 0;
|
||||||
|
*out_prev = 0;
|
||||||
|
|
||||||
|
const BucketIndex ind = HashToBucket(hash_key);
|
||||||
|
|
||||||
|
Position cur;
|
||||||
|
R_TRY(this->ReadBucket(std::addressof(cur), ind));
|
||||||
|
AMS_ASSERT(cur == InvalidPosition || cur < this->kv_size);
|
||||||
|
|
||||||
|
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
|
||||||
|
|
||||||
|
u8 buf[MaxAuxiliarySize];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
size_t cur_aux_size;
|
||||||
|
R_TRY(this->ReadKeyValue(out_elem, buf, std::addressof(cur_aux_size), cur));
|
||||||
|
|
||||||
|
if (key.IsEqual(out_elem->key, aux, aux_size, buf, cur_aux_size)) {
|
||||||
|
*out_pos = cur;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_prev = cur;
|
||||||
|
cur = out_elem->next;
|
||||||
|
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result AllocateEntry(Position *out, size_t aux_size) {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
R_UNLESS(this->total_entry_size + sizeof(Element) + aux_size <= this->kv_size, fs::ResultDbmKeyFull());
|
||||||
|
|
||||||
|
*out = static_cast<Position>(this->total_entry_size);
|
||||||
|
|
||||||
|
this->total_entry_size = AlignRomAddress(this->total_entry_size + sizeof(Element) + static_cast<u32>(aux_size));
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LinkEntry(Position *out, Position pos, u32 hash_key) {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
|
||||||
|
const BucketIndex ind = HashToBucket(hash_key);
|
||||||
|
|
||||||
|
Position next;
|
||||||
|
R_TRY(this->ReadBucket(std::addressof(next), ind));
|
||||||
|
AMS_ASSERT(next == InvalidPosition || next < this->kv_size);
|
||||||
|
|
||||||
|
R_TRY(this->WriteBucket(pos, ind, fs::WriteOption::None));
|
||||||
|
|
||||||
|
*out = next;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ReadBucket(Position *out, BucketIndex ind) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(this->bucket_storage != nullptr);
|
||||||
|
AMS_ASSERT(ind < this->bucket_count);
|
||||||
|
|
||||||
|
const s64 offset = this->bucket_offset + ind * sizeof(Position);
|
||||||
|
return this->bucket_storage->Read(offset, out, sizeof(*out));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result WriteBucket(Position pos, BucketIndex ind, fs::WriteOption option) const {
|
||||||
|
AMS_ASSERT(this->bucket_storage != nullptr);
|
||||||
|
AMS_ASSERT(ind < this->bucket_count);
|
||||||
|
|
||||||
|
const s64 offset = this->bucket_offset + ind * sizeof(Position);
|
||||||
|
return this->bucket_storage.Write(offset, std::addressof(pos), sizeof(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ReadKeyValue(Element *out, void *out_aux, size_t *out_aux_size, Position pos) const {
|
||||||
|
AMS_ASSERT(out != nullptr);
|
||||||
|
AMS_ASSERT(this->kv_storage != nullptr);
|
||||||
|
AMS_ASSERT(pos < this->kv_size);
|
||||||
|
|
||||||
|
const s64 offset = this->kv_offset + pos;
|
||||||
|
R_TRY(this->kv_storage->Read(offset, out, sizeof(*out)));
|
||||||
|
|
||||||
|
if (out_aux != nullptr && out_aux_size != nullptr) {
|
||||||
|
*out_aux_size = out->size;
|
||||||
|
if (out->size > 0) {
|
||||||
|
R_TRY(this->kv_storage->Read(offset + sizeof(*out), out_aux, out->size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result WriteKeyValue(const Element *elem, Position pos, const void *aux, size_t aux_size, fs::WriteOption option) const {
|
||||||
|
AMS_ASSERT(elem != nullptr);
|
||||||
|
AMS_ASSERT(this->kv_storage != nullptr);
|
||||||
|
AMS_ASSERT(pos < this->kv_size);
|
||||||
|
|
||||||
|
const s64 offset = this->kv_offset + pos;
|
||||||
|
R_TRY(this->kv_storage->Write(offset, elem, sizeof(*elem)));
|
||||||
|
|
||||||
|
if (aux != nullptr && aux_size > 0) {
|
||||||
|
R_TRY(this->kv_storage->Write(offset + sizeof(*elem), aux, aux_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <stratosphere/fssystem/fssystem_dbm_rom_types.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
namespace RomPathTool {
|
||||||
|
|
||||||
|
constexpr inline u32 MaxPathLength = 0x300;
|
||||||
|
|
||||||
|
struct RomEntryName {
|
||||||
|
size_t length;
|
||||||
|
const RomPathChar *path;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomEntryName>::value);
|
||||||
|
|
||||||
|
constexpr void InitializeRomEntryName(RomEntryName *entry) {
|
||||||
|
entry->length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsSeparator(RomPathChar c) {
|
||||||
|
return c == RomStringTraits::DirectorySeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsNullTerminator(RomPathChar c) {
|
||||||
|
return c == RomStringTraits::NullTerminator;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsDot(RomPathChar c) {
|
||||||
|
return c == RomStringTraits::Dot;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsCurrentDirectory(const RomEntryName &name) {
|
||||||
|
return name.length == 1 && IsDot(name.path[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsCurrentDirectory(const RomPathChar *p, size_t length) {
|
||||||
|
return length == 1 && IsDot(p[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsCurrentDirectory(const RomPathChar *p) {
|
||||||
|
return IsDot(p[0]) && IsNullTerminator(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsParentDirectory(const RomEntryName &name) {
|
||||||
|
return name.length == 2 && IsDot(name.path[0]) && IsDot(name.path[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsParentDirectory(const RomPathChar *p) {
|
||||||
|
return IsDot(p[0]) && IsDot(p[1]) && IsNullTerminator(p[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsParentDirectory(const RomPathChar *p, size_t length) {
|
||||||
|
return length == 2 && IsDot(p[0]) && IsDot(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsEqualPath(const RomPathChar *lhs, const RomPathChar *rhs, size_t length) {
|
||||||
|
return std::strncmp(lhs, rhs, length) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomPathChar *rhs) {
|
||||||
|
if (strnlen(rhs, MaxPathLength) != lhs.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return IsEqualPath(lhs.path, rhs, lhs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomEntryName &rhs) {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return IsEqualPath(lhs.path, rhs.path, lhs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetParentDirectoryName(RomEntryName *out, const RomEntryName &cur, const RomPathChar *p);
|
||||||
|
|
||||||
|
class PathParser {
|
||||||
|
private:
|
||||||
|
const RomPathChar *prev_path_start;
|
||||||
|
const RomPathChar *prev_path_end;
|
||||||
|
const RomPathChar *next_path;
|
||||||
|
bool finished;
|
||||||
|
public:
|
||||||
|
constexpr PathParser() : prev_path_start(), prev_path_end(), next_path(), finished() { /* ... */ }
|
||||||
|
|
||||||
|
Result Initialize(const RomPathChar *path);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
bool IsFinished() const;
|
||||||
|
bool IsDirectoryPath() const;
|
||||||
|
|
||||||
|
Result GetAsDirectoryName(RomEntryName *out) const;
|
||||||
|
Result GetAsFileName(RomEntryName *out) const;
|
||||||
|
|
||||||
|
Result GetNextDirectoryName(RomEntryName *out);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <stratosphere/fs/fs_common.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
using RomPathChar = char;
|
||||||
|
using RomFileId = s32;
|
||||||
|
using RomDirectoryId = s32;
|
||||||
|
|
||||||
|
struct RomFileSystemInformation {
|
||||||
|
s64 size;
|
||||||
|
s64 directory_bucket_offset;
|
||||||
|
s64 directory_bucket_size;
|
||||||
|
s64 directory_entry_offset;
|
||||||
|
s64 directory_entry_size;
|
||||||
|
s64 file_bucket_offset;
|
||||||
|
s64 file_bucket_size;
|
||||||
|
s64 file_entry_offset;
|
||||||
|
s64 file_entry_size;
|
||||||
|
s64 body_offset;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomFileSystemInformation>::value);
|
||||||
|
static_assert(sizeof(RomFileSystemInformation) == 0x50);
|
||||||
|
|
||||||
|
struct RomDirectoryInfo {
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomDirectoryInfo>::value);
|
||||||
|
|
||||||
|
struct RomFileInfo {
|
||||||
|
fs::Int64 offset;
|
||||||
|
fs::Int64 size;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<RomFileInfo>::value);
|
||||||
|
|
||||||
|
namespace RomStringTraits {
|
||||||
|
|
||||||
|
constexpr inline char DirectorySeparator = '/';
|
||||||
|
constexpr inline char NullTerminator = '\x00';
|
||||||
|
constexpr inline char Dot = '.';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Adubbz, 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 "fssystem_partition_file_system_meta.hpp"
|
||||||
|
#include "../fs/fsa/fs_ifile.hpp"
|
||||||
|
#include "../fs/fsa/fs_idirectory.hpp"
|
||||||
|
#include "../fs/fsa/fs_ifilesystem.hpp"
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
template<typename MetaType>
|
||||||
|
class PartitionFileSystemCore : public fs::impl::Newable, public fs::fsa::IFileSystem {
|
||||||
|
NON_COPYABLE(PartitionFileSystemCore);
|
||||||
|
NON_MOVEABLE(PartitionFileSystemCore);
|
||||||
|
private:
|
||||||
|
class PartitionFile;
|
||||||
|
class PartitionDirectory;
|
||||||
|
private:
|
||||||
|
fs::IStorage *base_storage;
|
||||||
|
MetaType *meta_data;
|
||||||
|
bool initialized;
|
||||||
|
size_t meta_data_size;
|
||||||
|
std::unique_ptr<MetaType> unique_meta_data;
|
||||||
|
std::shared_ptr<fs::IStorage> shared_storage;
|
||||||
|
private:
|
||||||
|
Result Initialize(fs::IStorage *base_storage, MemoryResource *allocator);
|
||||||
|
public:
|
||||||
|
PartitionFileSystemCore();
|
||||||
|
virtual ~PartitionFileSystemCore() override;
|
||||||
|
|
||||||
|
Result Initialize(std::unique_ptr<MetaType> &&meta_data, std::shared_ptr<fs::IStorage> base_storage);
|
||||||
|
Result Initialize(MetaType *meta_data, std::shared_ptr<fs::IStorage> base_storage);
|
||||||
|
Result Initialize(fs::IStorage *base_storage);
|
||||||
|
Result Initialize(std::shared_ptr<fs::IStorage> base_storage);
|
||||||
|
Result Initialize(std::shared_ptr<fs::IStorage> base_storage, MemoryResource *allocator);
|
||||||
|
|
||||||
|
Result GetFileBaseOffset(s64 *out_offset, const char *path);
|
||||||
|
|
||||||
|
virtual Result CreateFileImpl(const char *path, s64 size, int option) override;
|
||||||
|
virtual Result DeleteFileImpl(const char *path) override;
|
||||||
|
virtual Result CreateDirectoryImpl(const char *path) override;
|
||||||
|
virtual Result DeleteDirectoryImpl(const char *path) override;
|
||||||
|
virtual Result DeleteDirectoryRecursivelyImpl(const char *path) override;
|
||||||
|
virtual Result RenameFileImpl(const char *old_path, const char *new_path) override;
|
||||||
|
virtual Result RenameDirectoryImpl(const char *old_path, const char *new_path) override;
|
||||||
|
virtual Result GetEntryTypeImpl(fs::DirectoryEntryType *out, const char *path) override;
|
||||||
|
virtual Result OpenFileImpl(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
|
||||||
|
virtual Result OpenDirectoryImpl(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
|
||||||
|
virtual Result CommitImpl() override;
|
||||||
|
virtual Result CleanDirectoryRecursivelyImpl(const char *path) override;
|
||||||
|
|
||||||
|
/* These aren't accessible as commands. */
|
||||||
|
virtual Result CommitProvisionallyImpl(s64 counter) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PartitionFileSystem = PartitionFileSystemCore<PartitionFileSystemMeta>;
|
||||||
|
using Sha256PartitionFileSystem = PartitionFileSystemCore<Sha256PartitionFileSystemMeta>;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Adubbz, 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 <stratosphere/fs/fs_common.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
struct PartitionFileSystemFormat {
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct PartitionEntry {
|
||||||
|
u64 offset;
|
||||||
|
u64 size;
|
||||||
|
u32 name_offset;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<PartitionEntry>::value);
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static constexpr const char VersionSignature[] = { 'P', 'F', 'S', '0' };
|
||||||
|
|
||||||
|
static constexpr size_t EntryNameLengthMax = ::ams::fs::EntryNameLengthMax;
|
||||||
|
static constexpr size_t FileDataAlignmentSize = 0x20;
|
||||||
|
|
||||||
|
using ResultSignatureVerificationFailed = fs::ResultPartitionSignatureVerificationFailed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sha256PartitionFileSystemFormat {
|
||||||
|
static constexpr size_t HashSize = ::ams::crypto::Sha256Generator::HashSize;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct PartitionEntry {
|
||||||
|
u64 offset;
|
||||||
|
u64 size;
|
||||||
|
u32 name_offset;
|
||||||
|
u32 hash_target_size;
|
||||||
|
u64 hash_target_offset;
|
||||||
|
char hash[HashSize];
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<PartitionEntry>::value);
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static constexpr const char VersionSignature[] = { 'H', 'F', 'S', '0' };
|
||||||
|
|
||||||
|
static constexpr size_t EntryNameLengthMax = ::ams::fs::EntryNameLengthMax;
|
||||||
|
static constexpr size_t FileDataAlignmentSize = 0x200;
|
||||||
|
|
||||||
|
using ResultSignatureVerificationFailed = fs::ResultSha256PartitionSignatureVerificationFailed;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Format>
|
||||||
|
class PartitionFileSystemMetaCore : public fs::impl::Newable {
|
||||||
|
public:
|
||||||
|
static constexpr size_t EntryNameLengthMax = Format::EntryNameLengthMax;
|
||||||
|
static constexpr size_t FileDataAlignmentSize = Format::FileDataAlignmentSize;
|
||||||
|
|
||||||
|
/* Forward declare header. */
|
||||||
|
struct PartitionFileSystemHeader;
|
||||||
|
|
||||||
|
using PartitionEntry = typename Format::PartitionEntry;
|
||||||
|
protected:
|
||||||
|
bool initialized;
|
||||||
|
PartitionFileSystemHeader *header;
|
||||||
|
PartitionEntry *entries;
|
||||||
|
char *name_table;
|
||||||
|
size_t meta_data_size;
|
||||||
|
MemoryResource *allocator;
|
||||||
|
char *buffer;
|
||||||
|
public:
|
||||||
|
PartitionFileSystemMetaCore() : initialized(false), allocator(nullptr), buffer(nullptr) { /* ... */ }
|
||||||
|
~PartitionFileSystemMetaCore();
|
||||||
|
|
||||||
|
Result Initialize(fs::IStorage *storage, MemoryResource *allocator);
|
||||||
|
Result Initialize(fs::IStorage *storage, void *header, size_t header_size);
|
||||||
|
|
||||||
|
const PartitionEntry *GetEntry(s32 index) const;
|
||||||
|
s32 GetEntryCount() const;
|
||||||
|
s32 GetEntryIndex(const char *name) const;
|
||||||
|
const char *GetEntryName(s32 index) const;
|
||||||
|
size_t GetHeaderSize() const;
|
||||||
|
size_t GetMetaDataSize() const;
|
||||||
|
public:
|
||||||
|
static Result QueryMetaDataSize(size_t *out_size, fs::IStorage *storage);
|
||||||
|
protected:
|
||||||
|
void DeallocateBuffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
using PartitionFileSystemMeta = PartitionFileSystemMetaCore<impl::PartitionFileSystemFormat>;
|
||||||
|
|
||||||
|
class Sha256PartitionFileSystemMeta : public PartitionFileSystemMetaCore<impl::Sha256PartitionFileSystemFormat> {
|
||||||
|
public:
|
||||||
|
using PartitionFileSystemMetaCore<impl::Sha256PartitionFileSystemFormat>::Initialize;
|
||||||
|
Result Initialize(fs::IStorage *base_storage, MemoryResource *allocator, const void *hash, size_t hash_size, std::optional<u8> suffix = std::nullopt);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
constexpr inline size_t BufferPoolAlignment = 4_KB;
|
||||||
|
constexpr inline size_t BufferPoolWorkSize = 320;
|
||||||
|
|
||||||
|
class PooledBuffer {
|
||||||
|
NON_COPYABLE(PooledBuffer);
|
||||||
|
private:
|
||||||
|
char *buffer;
|
||||||
|
size_t size;
|
||||||
|
private:
|
||||||
|
static size_t GetAllocatableSizeMaxCore(bool large);
|
||||||
|
public:
|
||||||
|
static size_t GetAllocatableSizeMax() { return GetAllocatableSizeMaxCore(false); }
|
||||||
|
static size_t GetAllocatableParticularlyLargeSizeMax() { return GetAllocatableSizeMaxCore(true); }
|
||||||
|
private:
|
||||||
|
void Swap(PooledBuffer &rhs) {
|
||||||
|
std::swap(this->buffer, rhs.buffer);
|
||||||
|
std::swap(this->size, rhs.size);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
/* Constructor/Destructor. */
|
||||||
|
constexpr PooledBuffer() : buffer(), size() { /* ... */ }
|
||||||
|
|
||||||
|
PooledBuffer(size_t ideal_size, size_t required_size) : buffer(), size() {
|
||||||
|
this->Allocate(ideal_size, required_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
~PooledBuffer() {
|
||||||
|
this->Deallocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move and assignment. */
|
||||||
|
explicit PooledBuffer(PooledBuffer &&rhs) : buffer(rhs.buffer), size(rhs.size) {
|
||||||
|
rhs.buffer = nullptr;
|
||||||
|
rhs.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PooledBuffer &operator=(PooledBuffer &&rhs) {
|
||||||
|
PooledBuffer(std::move(rhs)).Swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocation API. */
|
||||||
|
void Allocate(size_t ideal_size, size_t required_size) {
|
||||||
|
return this->AllocateCore(ideal_size, required_size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateParticularlyLarge(size_t ideal_size, size_t required_size) {
|
||||||
|
return this->AllocateCore(ideal_size, required_size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shrink(size_t ideal_size);
|
||||||
|
|
||||||
|
void Deallocate() {
|
||||||
|
/* Shrink the buffer to empty. */
|
||||||
|
this->Shrink(0);
|
||||||
|
AMS_ASSERT(this->buffer == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *GetBuffer() const {
|
||||||
|
AMS_ASSERT(this->buffer != nullptr);
|
||||||
|
return this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetSize() const {
|
||||||
|
AMS_ASSERT(this->buffer != nullptr);
|
||||||
|
return this->size;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void AllocateCore(size_t ideal_size, size_t required_size, bool large);
|
||||||
|
};
|
||||||
|
|
||||||
|
Result InitializeBufferPool(char *buffer, size_t size);
|
||||||
|
Result InitializeBufferPool(char *buffer, size_t size, char *work, size_t work_size);
|
||||||
|
|
||||||
|
bool IsPooledBuffer(const void *buffer);
|
||||||
|
|
||||||
|
size_t GetPooledBufferRetriedCount();
|
||||||
|
size_t GetPooledBufferReduceAllocationCount();
|
||||||
|
size_t GetPooledBufferFreeSizePeak();
|
||||||
|
|
||||||
|
void ClearPooledBufferPeak();
|
||||||
|
|
||||||
|
void RegisterAdditionalDeviceAddress(uintptr_t address, size_t size);
|
||||||
|
void UnregisterAdditionalDeviceAddress(uintptr_t address);
|
||||||
|
bool IsAdditionalDeviceAddress(const void *ptr);
|
||||||
|
|
||||||
|
inline bool IsDeviceAddress(const void *buffer) {
|
||||||
|
return IsPooledBuffer(buffer) || IsAdditionalDeviceAddress(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
#include <stratosphere/fssystem/fssystem_dbm_hierarchical_rom_file_table.hpp>
|
||||||
|
#include <stratosphere/fs/fs_istorage.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
class RomFsFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
|
||||||
|
NON_COPYABLE(RomFsFileSystem);
|
||||||
|
public:
|
||||||
|
using RomFileTable = HierarchicalRomFileTable<fs::IStorage, fs::IStorage, fs::IStorage, fs::IStorage>;
|
||||||
|
private:
|
||||||
|
RomFileTable rom_file_table;
|
||||||
|
fs::IStorage *base_storage;
|
||||||
|
std::shared_ptr<fs::IStorage> shared_storage;
|
||||||
|
std::unique_ptr<fs::IStorage> dir_bucket_storage;
|
||||||
|
std::unique_ptr<fs::IStorage> dir_entry_storage;
|
||||||
|
std::unique_ptr<fs::IStorage> file_bucket_storage;
|
||||||
|
std::unique_ptr<fs::IStorage> file_entry_storage;
|
||||||
|
s64 entry_size;
|
||||||
|
private:
|
||||||
|
Result GetFileInfo(RomFileTable::FileInfo *out, const char *path);
|
||||||
|
public:
|
||||||
|
static Result GetRequiredWorkingMemorySize(size_t *out, fs::IStorage *storage);
|
||||||
|
public:
|
||||||
|
RomFsFileSystem();
|
||||||
|
virtual ~RomFsFileSystem() override;
|
||||||
|
|
||||||
|
Result Initialize(fs::IStorage *base, void *work, size_t work_size, bool use_cache);
|
||||||
|
Result Initialize(std::shared_ptr<fs::IStorage> base, void *work, size_t work_size, bool use_cache);
|
||||||
|
|
||||||
|
fs::IStorage *GetBaseStorage();
|
||||||
|
RomFileTable *GetRomFileTable();
|
||||||
|
Result GetFileBaseOffset(s64 *out, const char *path);
|
||||||
|
public:
|
||||||
|
virtual Result CreateFileImpl(const char *path, s64 size, int flags) override;
|
||||||
|
virtual Result DeleteFileImpl(const char *path) override;
|
||||||
|
virtual Result CreateDirectoryImpl(const char *path) override;
|
||||||
|
virtual Result DeleteDirectoryImpl(const char *path) override;
|
||||||
|
virtual Result DeleteDirectoryRecursivelyImpl(const char *path) override;
|
||||||
|
virtual Result RenameFileImpl(const char *old_path, const char *new_path) override;
|
||||||
|
virtual Result RenameDirectoryImpl(const char *old_path, const char *new_path) override;
|
||||||
|
virtual Result GetEntryTypeImpl(fs::DirectoryEntryType *out, const char *path) override;
|
||||||
|
virtual Result OpenFileImpl(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
|
||||||
|
virtual Result OpenDirectoryImpl(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
|
||||||
|
virtual Result CommitImpl() override;
|
||||||
|
virtual Result GetFreeSpaceSizeImpl(s64 *out, const char *path) override;
|
||||||
|
virtual Result CleanDirectoryRecursivelyImpl(const char *path) override;
|
||||||
|
|
||||||
|
/* These aren't accessible as commands. */
|
||||||
|
virtual Result CommitProvisionallyImpl(s64 counter) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/os.hpp>
|
||||||
|
|
||||||
|
namespace ams::fssystem {
|
||||||
|
|
||||||
|
class ScopedThreadPriorityChanger {
|
||||||
|
public:
|
||||||
|
enum class Mode {
|
||||||
|
Absolute,
|
||||||
|
Relative,
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/* TODO */
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE explicit ScopedThreadPriorityChanger(s32 priority, Mode mode) {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE ~ScopedThreadPriorityChanger() {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -170,4 +170,6 @@ namespace ams::fssystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddCounter(void *counter, size_t counter_size, u64 value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,16 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../../fs/fs_common.hpp"
|
#include <stratosphere/fs/fs_common.hpp>
|
||||||
#include "../../fs/fsa/fs_ifile.hpp"
|
#include <stratosphere/fs/fsa/fs_ifile.hpp>
|
||||||
#include "../../fs/fsa/fs_idirectory.hpp"
|
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
|
||||||
#include "../../fs/fsa/fs_ifilesystem.hpp"
|
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
|
||||||
|
#include <stratosphere/fs/impl/fs_newable.hpp>
|
||||||
|
|
||||||
namespace ams::fssystem::impl {
|
namespace ams::fssystem::impl {
|
||||||
|
|
||||||
template<typename Impl>
|
template<typename Impl>
|
||||||
class IPathResolutionFileSystem : public fs::fsa::IFileSystem {
|
class IPathResolutionFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
|
||||||
NON_COPYABLE(IPathResolutionFileSystem);
|
NON_COPYABLE(IPathResolutionFileSystem);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<fs::fsa::IFileSystem> shared_fs;
|
std::shared_ptr<fs::fsa::IFileSystem> shared_fs;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace ams::kvdb {
|
|||||||
rhs.size = 0;
|
rhs.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoBuffer& operator=(AutoBuffer &&rhs) {
|
AutoBuffer &operator=(AutoBuffer &&rhs) {
|
||||||
AutoBuffer(std::move(rhs)).Swap(*this);
|
AutoBuffer(std::move(rhs)).Swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ namespace ams::kvdb {
|
|||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
if (this->buffer != nullptr) {
|
if (this->buffer != nullptr) {
|
||||||
std::free(this->buffer);
|
delete[] this->buffer;
|
||||||
this->buffer = nullptr;
|
this->buffer = nullptr;
|
||||||
this->size = 0;
|
this->size = 0;
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ namespace ams::kvdb {
|
|||||||
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
||||||
|
|
||||||
/* Allocate a buffer. */
|
/* Allocate a buffer. */
|
||||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
this->buffer = new (std::nothrow) u8[size];
|
||||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||||
|
|
||||||
this->size = size;
|
this->size = size;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace ams::kvdb {
|
|||||||
Path GetPath(const void *key, size_t key_size);
|
Path GetPath(const void *key, size_t key_size);
|
||||||
Result GetKey(size_t *out_size, void *out_key, size_t max_out_size, const FileName &file_name);
|
Result GetKey(size_t *out_size, void *out_key, size_t max_out_size, const FileName &file_name);
|
||||||
public:
|
public:
|
||||||
FileKeyValueStore() { /* ... */ }
|
FileKeyValueStore() : lock(false) { /* ... */ }
|
||||||
|
|
||||||
/* Basic accessors. */
|
/* Basic accessors. */
|
||||||
Result Initialize(const char *dir);
|
Result Initialize(const char *dir);
|
||||||
|
|||||||
@@ -93,13 +93,14 @@ namespace ams::kvdb {
|
|||||||
size_t count;
|
size_t count;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
Entry *entries;
|
Entry *entries;
|
||||||
|
MemoryResource *memory_resource;
|
||||||
public:
|
public:
|
||||||
Index() : count(0), capacity(0), entries(nullptr) { /* ... */ }
|
Index() : count(0), capacity(0), entries(nullptr), memory_resource(nullptr) { /* ... */ }
|
||||||
|
|
||||||
~Index() {
|
~Index() {
|
||||||
if (this->entries != nullptr) {
|
if (this->entries != nullptr) {
|
||||||
this->ResetEntries();
|
this->ResetEntries();
|
||||||
std::free(this->entries);
|
this->memory_resource->Deallocate(this->entries, sizeof(Entry) * this->capacity);
|
||||||
this->entries = nullptr;
|
this->entries = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,30 +115,25 @@ namespace ams::kvdb {
|
|||||||
|
|
||||||
void ResetEntries() {
|
void ResetEntries() {
|
||||||
for (size_t i = 0; i < this->count; i++) {
|
for (size_t i = 0; i < this->count; i++) {
|
||||||
std::free(this->entries[i].GetValuePointer());
|
this->memory_resource->Deallocate(this->entries[i].GetValuePointer(), this->entries[i].GetValueSize());
|
||||||
}
|
}
|
||||||
this->count = 0;
|
this->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(size_t capacity) {
|
Result Initialize(size_t capacity, MemoryResource *mr) {
|
||||||
this->entries = reinterpret_cast<Entry *>(std::malloc(sizeof(Entry) * capacity));
|
this->entries = reinterpret_cast<Entry *>(mr->Allocate(sizeof(Entry) * capacity));
|
||||||
R_UNLESS(this->entries != nullptr, ResultAllocationFailed());
|
R_UNLESS(this->entries != nullptr, ResultAllocationFailed());
|
||||||
this->capacity = capacity;
|
this->capacity = capacity;
|
||||||
|
this->memory_resource = mr;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Set(const Key &key, const void *value, size_t value_size) {
|
Result Set(const Key &key, const void *value, size_t value_size) {
|
||||||
/* Allocate new value. */
|
|
||||||
void *new_value = std::malloc(value_size);
|
|
||||||
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
|
||||||
auto value_guard = SCOPE_GUARD { std::free(new_value); };
|
|
||||||
std::memcpy(new_value, value, value_size);
|
|
||||||
|
|
||||||
/* Find entry for key. */
|
/* Find entry for key. */
|
||||||
Entry *it = this->lower_bound(key);
|
Entry *it = this->lower_bound(key);
|
||||||
if (it != this->end() && it->GetKey() == key) {
|
if (it != this->end() && it->GetKey() == key) {
|
||||||
/* Entry already exists. Free old value. */
|
/* Entry already exists. Free old value. */
|
||||||
std::free(it->GetValuePointer());
|
this->memory_resource->Deallocate(it->GetValuePointer(), it->GetValueSize());
|
||||||
} else {
|
} else {
|
||||||
/* We need to add a new entry. Check we have room, move future keys forward. */
|
/* We need to add a new entry. Check we have room, move future keys forward. */
|
||||||
R_UNLESS(this->count < this->capacity, ResultOutOfKeyResource());
|
R_UNLESS(this->count < this->capacity, ResultOutOfKeyResource());
|
||||||
@@ -145,8 +141,12 @@ namespace ams::kvdb {
|
|||||||
this->count++;
|
this->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate new value. */
|
||||||
|
void *new_value = this->memory_resource->Allocate(value_size);
|
||||||
|
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
||||||
|
std::memcpy(new_value, value, value_size);
|
||||||
|
|
||||||
/* Save the new Entry in the map. */
|
/* Save the new Entry in the map. */
|
||||||
value_guard.Cancel();
|
|
||||||
*it = Entry(key, new_value, value_size);
|
*it = Entry(key, new_value, value_size);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ namespace ams::kvdb {
|
|||||||
R_UNLESS(it != this->end(), ResultKeyNotFound());
|
R_UNLESS(it != this->end(), ResultKeyNotFound());
|
||||||
|
|
||||||
/* Free the value, move entries back. */
|
/* Free the value, move entries back. */
|
||||||
std::free(it->GetValuePointer());
|
this->memory_resource->Deallocate(it->GetValuePointer(), it->GetValueSize());
|
||||||
std::memmove(it, it + 1, sizeof(*it) * (this->end() - (it + 1)));
|
std::memmove(it, it + 1, sizeof(*it) * (this->end() - (it + 1)));
|
||||||
this->count--;
|
this->count--;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
@@ -258,10 +258,11 @@ namespace ams::kvdb {
|
|||||||
Index index;
|
Index index;
|
||||||
Path path;
|
Path path;
|
||||||
Path temp_path;
|
Path temp_path;
|
||||||
|
MemoryResource *memory_resource;
|
||||||
public:
|
public:
|
||||||
MemoryKeyValueStore() { /* ... */ }
|
MemoryKeyValueStore() { /* ... */ }
|
||||||
|
|
||||||
Result Initialize(const char *dir, size_t capacity) {
|
Result Initialize(const char *dir, size_t capacity, MemoryResource *mr) {
|
||||||
/* Ensure that the passed path is a directory. */
|
/* Ensure that the passed path is a directory. */
|
||||||
fs::DirectoryEntryType entry_type;
|
fs::DirectoryEntryType entry_type;
|
||||||
R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
|
R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
|
||||||
@@ -272,18 +273,21 @@ namespace ams::kvdb {
|
|||||||
this->temp_path.SetFormat("%s%s", dir, "/imkvdb.tmp");
|
this->temp_path.SetFormat("%s%s", dir, "/imkvdb.tmp");
|
||||||
|
|
||||||
/* Initialize our index. */
|
/* Initialize our index. */
|
||||||
R_TRY(this->index.Initialize(capacity));
|
R_TRY(this->index.Initialize(capacity, mr));
|
||||||
|
this->memory_resource = mr;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(size_t capacity) {
|
Result Initialize(size_t capacity, MemoryResource *mr) {
|
||||||
/* This initializes without an archive file. */
|
/* This initializes without an archive file. */
|
||||||
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
||||||
this->path.Set("");
|
this->path.Set("");
|
||||||
this->temp_path.Set("");
|
this->temp_path.Set("");
|
||||||
|
|
||||||
/* Initialize our index. */
|
/* Initialize our index. */
|
||||||
R_TRY(this->index.Initialize(capacity));
|
R_TRY(this->index.Initialize(capacity, mr));
|
||||||
|
this->memory_resource = mr;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,9 +323,9 @@ namespace ams::kvdb {
|
|||||||
R_TRY(reader.GetEntrySize(&key_size, &value_size));
|
R_TRY(reader.GetEntrySize(&key_size, &value_size));
|
||||||
|
|
||||||
/* Allocate memory for value. */
|
/* Allocate memory for value. */
|
||||||
void *new_value = std::malloc(value_size);
|
void *new_value = this->memory_resource->Allocate(value_size);
|
||||||
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
||||||
auto value_guard = SCOPE_GUARD { std::free(new_value); };
|
auto value_guard = SCOPE_GUARD { this->memory_resource->Deallocate(new_value, value_size); };
|
||||||
|
|
||||||
/* Read key and value. */
|
/* Read key and value. */
|
||||||
Key key;
|
Key key;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace ams::lmem::impl {
|
|||||||
|
|
||||||
void *heap_start;
|
void *heap_start;
|
||||||
void *heap_end;
|
void *heap_end;
|
||||||
os::Mutex mutex;
|
os::MutexType mutex;
|
||||||
u8 option;
|
u8 option;
|
||||||
ImplementationHeapHead impl_head;
|
ImplementationHeapHead impl_head;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace ams::lr {
|
|||||||
std::shared_ptr<IRegisteredLocationResolver> registered_location_resolver = nullptr;
|
std::shared_ptr<IRegisteredLocationResolver> registered_location_resolver = nullptr;
|
||||||
std::shared_ptr<IAddOnContentLocationResolver> add_on_content_location_resolver = nullptr;
|
std::shared_ptr<IAddOnContentLocationResolver> add_on_content_location_resolver = nullptr;
|
||||||
|
|
||||||
os::Mutex mutex;
|
os::Mutex mutex{false};
|
||||||
public:
|
public:
|
||||||
/* Actual commands. */
|
/* Actual commands. */
|
||||||
virtual Result OpenLocationResolver(sf::Out<std::shared_ptr<ILocationResolver>> out, ncm::StorageId storage_id) override;
|
virtual Result OpenLocationResolver(sf::Out<std::shared_ptr<ILocationResolver>> out, ncm::StorageId storage_id) override;
|
||||||
|
|||||||
20
libraries/libstratosphere/include/stratosphere/mem.hpp
Normal file
20
libraries/libstratosphere/include/stratosphere/mem.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <stratosphere/mem/mem_standard_allocator.hpp>
|
||||||
|
#include <stratosphere/mem/impl/mem_impl_heap.hpp>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/mem/impl/mem_impl_common.hpp>
|
||||||
|
|
||||||
|
namespace ams::mem::impl::heap {
|
||||||
|
|
||||||
|
class TlsHeapCache;
|
||||||
|
|
||||||
|
class CachedHeap final {
|
||||||
|
NON_COPYABLE(CachedHeap);
|
||||||
|
private:
|
||||||
|
TlsHeapCache *tls_heap_cache;
|
||||||
|
public:
|
||||||
|
constexpr CachedHeap() : tls_heap_cache() { /* ... */ }
|
||||||
|
~CachedHeap() { this->Finalize(); }
|
||||||
|
|
||||||
|
ALWAYS_INLINE CachedHeap(CachedHeap &&rhs) : tls_heap_cache(rhs.tls_heap_cache) {
|
||||||
|
rhs.tls_heap_cache = nullptr;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE CachedHeap &operator=(CachedHeap &&rhs) {
|
||||||
|
this->Reset();
|
||||||
|
this->tls_heap_cache = rhs.tls_heap_cache;
|
||||||
|
rhs.tls_heap_cache = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Allocate(size_t n);
|
||||||
|
void *Allocate(size_t n, size_t align);
|
||||||
|
size_t GetAllocationSize(const void *ptr);
|
||||||
|
errno_t Free(void *p);
|
||||||
|
errno_t FreeWithSize(void *p, size_t size);
|
||||||
|
errno_t Reallocate(void *ptr, size_t size, void **p);
|
||||||
|
errno_t Shrink(void *ptr, size_t size);
|
||||||
|
|
||||||
|
void ReleaseAllCache();
|
||||||
|
void Finalize();
|
||||||
|
bool CheckCache();
|
||||||
|
errno_t QueryV(int query, std::va_list vl);
|
||||||
|
errno_t Query(int query, ...);
|
||||||
|
|
||||||
|
void Reset() { this->Finalize(); }
|
||||||
|
void Reset(TlsHeapCache *thc);
|
||||||
|
TlsHeapCache *Release();
|
||||||
|
|
||||||
|
constexpr explicit ALWAYS_INLINE operator bool() const { return this->tls_heap_cache != nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <stratosphere/mem/impl/mem_impl_common.hpp>
|
||||||
|
#include <stratosphere/mem/impl/mem_impl_declarations.hpp>
|
||||||
|
|
||||||
|
namespace ams::mem::impl::heap {
|
||||||
|
|
||||||
|
class CachedHeap;
|
||||||
|
class TlsHeapCentral;
|
||||||
|
|
||||||
|
using HeapWalkCallback = int (*)(void *ptr, size_t size, void *user_data);
|
||||||
|
|
||||||
|
class CentralHeap final {
|
||||||
|
NON_COPYABLE(CentralHeap);
|
||||||
|
NON_MOVEABLE(CentralHeap);
|
||||||
|
public:
|
||||||
|
static constexpr size_t PageSize = 4_KB;
|
||||||
|
static constexpr size_t MinimumAlignment = alignof(u64);
|
||||||
|
using DestructorHandler = void (*)(void *start, void *end);
|
||||||
|
private:
|
||||||
|
TlsHeapCentral *tls_heap_central;
|
||||||
|
bool use_virtual_memory;
|
||||||
|
u32 option;
|
||||||
|
u8 *start;
|
||||||
|
u8 *end;
|
||||||
|
public:
|
||||||
|
constexpr CentralHeap() : tls_heap_central(), use_virtual_memory(), option(), start(), end() { /* ... */ }
|
||||||
|
~CentralHeap() { this->Finalize(); }
|
||||||
|
|
||||||
|
errno_t Initialize(void *start, size_t size, u32 option);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
ALWAYS_INLINE void *Allocate(size_t n) { return this->Allocate(n, MinimumAlignment); }
|
||||||
|
void *Allocate(size_t n, size_t align);
|
||||||
|
size_t GetAllocationSize(const void *ptr);
|
||||||
|
errno_t Free(void *p);
|
||||||
|
errno_t FreeWithSize(void *p, size_t size);
|
||||||
|
errno_t Reallocate(void *ptr, size_t size, void **p);
|
||||||
|
errno_t Shrink(void *ptr, size_t size);
|
||||||
|
|
||||||
|
bool MakeCache(CachedHeap *cached_heap);
|
||||||
|
errno_t WalkAllocatedPointers(HeapWalkCallback callback, void *user_data);
|
||||||
|
errno_t QueryV(int query, std::va_list vl);
|
||||||
|
errno_t Query(int query, ...);
|
||||||
|
private:
|
||||||
|
errno_t QueryVImpl(int query, std::va_list *vl_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(CentralHeap) <= sizeof(::ams::mem::impl::InternalCentralHeapStorage));
|
||||||
|
static_assert(alignof(CentralHeap) <= alignof(void *));
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
namespace ams::mem::impl {
|
||||||
|
|
||||||
|
constexpr inline size_t MaxSize = static_cast<size_t>(std::numeric_limits<s64>::max());
|
||||||
|
|
||||||
|
using errno_t = int;
|
||||||
|
|
||||||
|
enum DumpMode {
|
||||||
|
DumpMode_Basic = (0 << 0),
|
||||||
|
DumpMode_Spans = (1 << 0),
|
||||||
|
DumpMode_Pointers = (1 << 1),
|
||||||
|
DumpMode_Pages = (1 << 2),
|
||||||
|
DumpMode_All = (DumpMode_Pages | DumpMode_Pointers | DumpMode_Spans | DumpMode_Basic),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AllocQuery {
|
||||||
|
AllocQuery_Dump = 0,
|
||||||
|
AllocQuery_PageSize = 1,
|
||||||
|
AllocQuery_AllocatedSize = 2,
|
||||||
|
AllocQuery_FreeSize = 3,
|
||||||
|
AllocQuery_SystemSize = 4,
|
||||||
|
AllocQuery_MaxAllocatableSize = 5,
|
||||||
|
AllocQuery_IsClean = 6,
|
||||||
|
AllocQuery_HeapHash = 7,
|
||||||
|
AllocQuery_UnifyFreeList = 8,
|
||||||
|
AllocQuery_SetColor = 9,
|
||||||
|
AllocQuery_GetColor = 10,
|
||||||
|
AllocQuery_SetName = 11,
|
||||||
|
AllocQuery_GetName = 12,
|
||||||
|
/* AllocQuery_Thirteen = 13, */
|
||||||
|
AllocQuery_CheckCache = 14,
|
||||||
|
AllocQuery_ClearCache = 15,
|
||||||
|
AllocQuery_FinalizeCache = 16,
|
||||||
|
AllocQuery_FreeSizeMapped = 17,
|
||||||
|
AllocQuery_MaxAllocatableSizeMapped = 18,
|
||||||
|
AllocQuery_DumpJson = 19,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HeapOption {
|
||||||
|
HeapOption_UseEnvironment = (1 << 0),
|
||||||
|
HeapOption_DisableCache = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HeapHash {
|
||||||
|
size_t alloc_count;
|
||||||
|
size_t alloc_size;
|
||||||
|
size_t hash;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<HeapHash>::value);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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
|
||||||
|
|
||||||
|
namespace ams::mem::impl {
|
||||||
|
|
||||||
|
namespace heap {
|
||||||
|
|
||||||
|
class CentralHeap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using InternalCentralHeapStorage = ::ams::util::TypedStorage<::ams::mem::impl::heap::CentralHeap, sizeof(void *) * 6, alignof(void *)>;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <stratosphere/mem/impl/mem_impl_common.hpp>
|
||||||
|
#include <stratosphere/mem/impl/heap/mem_impl_heap_cached_heap.hpp>
|
||||||
|
#include <stratosphere/mem/impl/heap/mem_impl_heap_central_heap.hpp>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 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 <stratosphere/os.hpp>
|
||||||
|
#include <stratosphere/mem/impl/mem_impl_declarations.hpp>
|
||||||
|
|
||||||
|
namespace ams::mem {
|
||||||
|
|
||||||
|
class StandardAllocator {
|
||||||
|
NON_COPYABLE(StandardAllocator);
|
||||||
|
NON_MOVEABLE(StandardAllocator);
|
||||||
|
public:
|
||||||
|
using WalkCallback = int (*)(void *ptr, size_t size, void *user_data);
|
||||||
|
|
||||||
|
struct AllocatorHash {
|
||||||
|
size_t allocated_count;
|
||||||
|
size_t allocated_size;
|
||||||
|
size_t hash;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
bool initialized;
|
||||||
|
bool enable_thread_cache;
|
||||||
|
uintptr_t unused;
|
||||||
|
os::TlsSlot tls_slot;
|
||||||
|
impl::InternalCentralHeapStorage central_heap_storage;
|
||||||
|
public:
|
||||||
|
StandardAllocator();
|
||||||
|
StandardAllocator(void *mem, size_t size);
|
||||||
|
StandardAllocator(void *mem, size_t size, bool enable_cache);
|
||||||
|
|
||||||
|
~StandardAllocator() {
|
||||||
|
if (this->initialized) {
|
||||||
|
this->Finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize(void *mem, size_t size);
|
||||||
|
void Initialize(void *mem, size_t size, bool enable_cache);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
void *Allocate(size_t size);
|
||||||
|
void *Allocate(size_t size, size_t alignment);
|
||||||
|
void Free(void *ptr);
|
||||||
|
void *Reallocate(void *ptr, size_t new_size);
|
||||||
|
size_t Shrink(void *ptr, size_t new_size);
|
||||||
|
|
||||||
|
void ClearThreadCache() const;
|
||||||
|
void CleanUpManagementArea() const;
|
||||||
|
|
||||||
|
size_t GetSizeOf(const void *ptr) const;
|
||||||
|
size_t GetTotalFreeSize() const;
|
||||||
|
size_t GetAllocatableSize() const;
|
||||||
|
|
||||||
|
void WalkAllocatedBlocks(WalkCallback callback, void *user_data) const;
|
||||||
|
|
||||||
|
void Dump() const;
|
||||||
|
AllocatorHash Hash() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,13 +17,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stratosphere/ncm/ncm_ids.hpp>
|
#include <stratosphere/ncm/ncm_ids.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_max_count.hpp>
|
||||||
#include <stratosphere/ncm/ncm_program_location.hpp>
|
#include <stratosphere/ncm/ncm_program_location.hpp>
|
||||||
#include <stratosphere/ncm/ncm_auto_buffer.hpp>
|
#include <stratosphere/ncm/ncm_auto_buffer.hpp>
|
||||||
#include <stratosphere/ncm/ncm_make_path.hpp>
|
#include <stratosphere/ncm/ncm_make_path.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_id_utils.hpp>
|
#include <stratosphere/ncm/ncm_content_id_utils.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_content_info_utils.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_meta.hpp>
|
#include <stratosphere/ncm/ncm_content_meta.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_content_meta_extended_data.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
|
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_storage.hpp>
|
#include <stratosphere/ncm/ncm_content_storage.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_manager_impl.hpp>
|
#include <stratosphere/ncm/ncm_content_manager_impl.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
|
#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_firmware_variation.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_install_task_base.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_install_task_data.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_install_task_occupied_size.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_package_install_task_base.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_package_install_task.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_package_system_update_task.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_submission_package_install_task.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_storage_utils.hpp>
|
||||||
#include <stratosphere/ncm/ncm_api.hpp>
|
#include <stratosphere/ncm/ncm_api.hpp>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace ams::ncm {
|
|||||||
rhs.size = 0;
|
rhs.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoBuffer& operator=(AutoBuffer &&rhs) {
|
AutoBuffer &operator=(AutoBuffer &&rhs) {
|
||||||
AutoBuffer(std::move(rhs)).Swap(*this);
|
AutoBuffer(std::move(rhs)).Swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ namespace ams::ncm {
|
|||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
if (this->buffer != nullptr) {
|
if (this->buffer != nullptr) {
|
||||||
std::free(this->buffer);
|
delete[] this->buffer;
|
||||||
this->buffer = nullptr;
|
this->buffer = nullptr;
|
||||||
this->size = 0;
|
this->size = 0;
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ namespace ams::ncm {
|
|||||||
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
||||||
|
|
||||||
/* Allocate a buffer. */
|
/* Allocate a buffer. */
|
||||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
this->buffer = new (std::nothrow) u8[size];
|
||||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||||
|
|
||||||
this->size = size;
|
this->size = size;
|
||||||
@@ -85,4 +85,5 @@ namespace ams::ncm {
|
|||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,19 +21,19 @@ namespace ams::ncm {
|
|||||||
struct alignas(4) ContentId {
|
struct alignas(4) ContentId {
|
||||||
util::Uuid uuid;
|
util::Uuid uuid;
|
||||||
|
|
||||||
bool operator==(const ContentId& other) const {
|
bool operator==(const ContentId &other) const {
|
||||||
return this->uuid == other.uuid;
|
return this->uuid == other.uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const ContentId& other) const {
|
bool operator!=(const ContentId &other) const {
|
||||||
return this->uuid != other.uuid;
|
return this->uuid != other.uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const util::Uuid& other) const {
|
bool operator==(const util::Uuid &other) const {
|
||||||
return this->uuid == other;
|
return this->uuid == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const util::Uuid& other) const {
|
bool operator!=(const util::Uuid &other) const {
|
||||||
return this->uuid != other;
|
return this->uuid != other;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ namespace ams::ncm {
|
|||||||
ContentIdString GetContentIdString(ContentId id);
|
ContentIdString GetContentIdString(ContentId id);
|
||||||
|
|
||||||
void GetStringFromContentId(char *dst, size_t dst_size, ContentId id);
|
void GetStringFromContentId(char *dst, size_t dst_size, ContentId id);
|
||||||
|
void GetStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
|
||||||
|
|
||||||
|
void GetTicketFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
|
||||||
|
void GetCertificateFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
|
||||||
|
|
||||||
std::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
|
std::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ namespace ams::ncm {
|
|||||||
u8 data[crypto::Sha256Generator::HashSize];
|
u8 data[crypto::Sha256Generator::HashSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class InstallState : u8 {
|
||||||
|
NotPrepared,
|
||||||
|
Prepared,
|
||||||
|
Installed,
|
||||||
|
AlreadyExists,
|
||||||
|
};
|
||||||
|
|
||||||
struct PackagedContentInfo {
|
struct PackagedContentInfo {
|
||||||
Digest digest;
|
Digest digest;
|
||||||
ContentInfo info;
|
ContentInfo info;
|
||||||
@@ -42,4 +49,74 @@ namespace ams::ncm {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InstallContentInfo {
|
||||||
|
Digest digest;
|
||||||
|
crypto::Sha256Context context;
|
||||||
|
u8 buffered_data[crypto::Sha256Generator::BlockSize];
|
||||||
|
u64 buffered_data_size;
|
||||||
|
ContentInfo info;
|
||||||
|
PlaceHolderId placeholder_id;
|
||||||
|
ContentMetaType meta_type;
|
||||||
|
InstallState install_state;
|
||||||
|
bool verify_digest;
|
||||||
|
StorageId storage_id;
|
||||||
|
bool is_temporary;
|
||||||
|
bool is_sha256_calculated;
|
||||||
|
s64 written;
|
||||||
|
|
||||||
|
constexpr const ContentId &GetId() const {
|
||||||
|
return this->info.GetId();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const u64 GetSize() const {
|
||||||
|
return this->info.GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const ContentType GetType() const {
|
||||||
|
return this->info.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const u8 GetIdOffset() const {
|
||||||
|
return this->info.GetIdOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const PlaceHolderId &GetPlaceHolderId() const {
|
||||||
|
return this->placeholder_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const ContentMetaType GetContentMetaType() const {
|
||||||
|
return this->meta_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const InstallState GetInstallState() const {
|
||||||
|
return this->install_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const StorageId GetStorageId() const {
|
||||||
|
return this->storage_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr s64 GetSizeWritten() const {
|
||||||
|
return this->written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr InstallContentInfo Make(const ContentInfo &info, ContentMetaType meta_type) {
|
||||||
|
return {
|
||||||
|
.info = info,
|
||||||
|
.meta_type = meta_type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr InstallContentInfo Make(const PackagedContentInfo &info, ContentMetaType meta_type) {
|
||||||
|
return {
|
||||||
|
.digest = info.digest,
|
||||||
|
.info = info.info,
|
||||||
|
.meta_type = meta_type,
|
||||||
|
.verify_digest = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(InstallContentInfo) == 0xC8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user