Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8696bd5d4 | ||
|
|
af7baa6b34 | ||
|
|
6de1361c8b |
3
Makefile
3
Makefile
@@ -58,7 +58,6 @@ dist-no-debug: all
|
|||||||
mkdir atmosphere-$(AMSVER)/switch
|
mkdir atmosphere-$(AMSVER)/switch
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/010000000000002B
|
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036
|
||||||
@@ -83,7 +82,6 @@ dist-no-debug: all
|
|||||||
cp -r config_templates/hbl_html atmosphere-$(AMSVER)/atmosphere/hbl_html
|
cp -r config_templates/hbl_html atmosphere-$(AMSVER)/atmosphere/hbl_html
|
||||||
cp stratosphere/boot2/boot2.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008/exefs.nsp
|
cp stratosphere/boot2/boot2.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000008/exefs.nsp
|
||||||
cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D/exefs.nsp
|
cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000000D/exefs.nsp
|
||||||
cp stratosphere/erpt/erpt.nsp atmosphere-$(AMSVER)/atmosphere/contents/010000000000002B/exefs.nsp
|
|
||||||
cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/exefs.nsp
|
cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000032/exefs.nsp
|
||||||
cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034/exefs.nsp
|
cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000034/exefs.nsp
|
||||||
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036/exefs.nsp
|
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/contents/0100000000000036/exefs.nsp
|
||||||
@@ -135,7 +133,6 @@ dist: dist-no-debug
|
|||||||
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
||||||
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
||||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
||||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
|
||||||
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||||
rm -r atmosphere-$(AMSVER)-debug
|
rm -r atmosphere-$(AMSVER)-debug
|
||||||
mv atmosphere-$(AMSVER)-debug.zip out/atmosphere-$(AMSVER)-debug.zip
|
mv atmosphere-$(AMSVER)-debug.zip out/atmosphere-$(AMSVER)-debug.zip
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1,34 +1,4 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
## 0.11.1
|
|
||||||
+ A bug was fixed that could cause owls to flicker under certain circumstances.
|
|
||||||
+ For those interested in technical details, in 10.0.0 kernelldr/kernel no longer set cpuactlr_el1, assuming that it was set correctly by the secure monitor.
|
|
||||||
+ However, exosphere did not set cpuactlr_el1. This meant that the register held the reset value going into boot.
|
|
||||||
+ This caused a variety of highly erratic symptoms, including causing basically any game to crash seemingly randomly.
|
|
||||||
+ A number of other major inaccuracies in exosphere were corrected.
|
|
||||||
+ General system stability improvements to enhance the user's experience.
|
|
||||||
## 0.11.0
|
|
||||||
+ Support was added for 10.0.0.
|
|
||||||
+ Exosphere has been updated to reflect the new key import semantics in 10.0.0.
|
|
||||||
+ kernel_ldr now implements physical ASLR for the kernel's backing pages.
|
|
||||||
+ Loader, NCM, and PM have been updated to reflect the changes Nintendo made in 10.0.0.
|
|
||||||
+ Creport was updated to use the new `pgl` service to terminate processes instead of `ns:dev`.
|
|
||||||
+ A reimplementation of the `erpt` (error reports) system module was added.
|
|
||||||
+ In previous versions of Atmosphere, a majority of error reports were prevented via a combination of custom creport, fatal, and stubbed eclct.
|
|
||||||
+ However, error reports were still generated via some system actions.
|
|
||||||
+ Most notably, any time the error applet appeared, an error report was generated.
|
|
||||||
+ By default, atmosphere disabled the *uploading* of error reports, but going online in OFW after an error report occurred in Atmosphere could lead to undesirable telemetry.
|
|
||||||
+ Atmosphere's `erpt` reimplementation allows the system to interact with existing error reports as expected.
|
|
||||||
+ However, all new error reports are instead saved to the sd card (`/atmosphere/erpt_reports`), and are not committed to the system savegame.
|
|
||||||
+ Users curious about what kind of telemetry is being prevented can view the reports as they're generated in there.
|
|
||||||
+ Reports are saved as msgpack (as this is what Nintendo uses).
|
|
||||||
+ Please note, not all telemetry is disabled. Play reports and System reports will continue to function unmodified.
|
|
||||||
+ With atmosphere's `erpt` implementation, homebrew can now use the native error applet to display errors without worrying about generating undesirable telemetry.
|
|
||||||
+ libstratosphere and libvapours received a number of improvements.
|
|
||||||
+ With thanks to @Adubbz for his work, the NCM namespace now has client code.
|
|
||||||
+ This lays the groundwork for first-class system update/downgrade homebrew support in the near future.
|
|
||||||
+ In particular, code implementing the os namespace is significantly more accurate.
|
|
||||||
+ In addition, Nintendo's allocators were implemented, allowing for identical memory efficiency versus Nintendo's implementations.
|
|
||||||
+ General system stability improvements to enhance the user's experience.
|
|
||||||
## 0.10.5
|
## 0.10.5
|
||||||
+ Changes were made to the way fs.mitm builds images when providing a layeredfs romfs.
|
+ 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.
|
+ Building romfs metadata previously had a memory cost of about ~4-5x the file table size.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/m4xw/emuMMC
|
remote = https://github.com/m4xw/emuMMC
|
||||||
branch = develop
|
branch = develop
|
||||||
commit = b168ddf5fbb31013ff529a4859110c82b11eb361
|
commit = d12dd5464422029a1e5601916517ec3f1c81d8d0
|
||||||
parent = c07f54f3709a4710e0aead6c91139fa0893b5e5c
|
parent = 259a1a7513236a1de4d373bc6cb99032ede2c626
|
||||||
method = rebase
|
method = rebase
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
||||||
|
|
||||||
### Supported Horizon Versions
|
### Supported Horizon Versions
|
||||||
**1.0.0 - 10.0.0**
|
**1.0.0 - 9.1.0**
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Arbitrary SDMMC backend selection
|
* Arbitrary SDMMC backend selection
|
||||||
|
|||||||
@@ -45,8 +45,6 @@
|
|||||||
#include "offsets/900_exfat.h"
|
#include "offsets/900_exfat.h"
|
||||||
#include "offsets/910.h"
|
#include "offsets/910.h"
|
||||||
#include "offsets/910_exfat.h"
|
#include "offsets/910_exfat.h"
|
||||||
#include "offsets/1000.h"
|
|
||||||
#include "offsets/1000_exfat.h"
|
|
||||||
#include "../utils/fatal.h"
|
#include "../utils/fatal.h"
|
||||||
|
|
||||||
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
||||||
@@ -102,8 +100,6 @@ DEFINE_OFFSET_STRUCT(_900);
|
|||||||
DEFINE_OFFSET_STRUCT(_900_EXFAT);
|
DEFINE_OFFSET_STRUCT(_900_EXFAT);
|
||||||
DEFINE_OFFSET_STRUCT(_910);
|
DEFINE_OFFSET_STRUCT(_910);
|
||||||
DEFINE_OFFSET_STRUCT(_910_EXFAT);
|
DEFINE_OFFSET_STRUCT(_910_EXFAT);
|
||||||
DEFINE_OFFSET_STRUCT(_1000);
|
|
||||||
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
|
|
||||||
|
|
||||||
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
@@ -165,10 +161,6 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
|||||||
return &(GET_OFFSET_STRUCT_NAME(_910));
|
return &(GET_OFFSET_STRUCT_NAME(_910));
|
||||||
case FS_VER_9_1_0_EXFAT:
|
case FS_VER_9_1_0_EXFAT:
|
||||||
return &(GET_OFFSET_STRUCT_NAME(_910_EXFAT));
|
return &(GET_OFFSET_STRUCT_NAME(_910_EXFAT));
|
||||||
case FS_VER_10_0_0:
|
|
||||||
return &(GET_OFFSET_STRUCT_NAME(_1000));
|
|
||||||
case FS_VER_10_0_0_EXFAT:
|
|
||||||
return &(GET_OFFSET_STRUCT_NAME(_1000_EXFAT));
|
|
||||||
default:
|
default:
|
||||||
fatal_abort(Fatal_UnknownVersion);
|
fatal_abort(Fatal_UnknownVersion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,9 +65,6 @@ enum FS_VER
|
|||||||
FS_VER_9_1_0,
|
FS_VER_9_1_0,
|
||||||
FS_VER_9_1_0_EXFAT,
|
FS_VER_9_1_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_10_0_0,
|
|
||||||
FS_VER_10_0_0_EXFAT,
|
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
|
||||||
* Copyright (c) 2019 Atmosphere-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef __FS_1000_H__
|
|
||||||
#define __FS_1000_H__
|
|
||||||
|
|
||||||
// Accessor vtable getters
|
|
||||||
#define FS_OFFSET_1000_SDMMC_ACCESSOR_GC 0x14DC90
|
|
||||||
#define FS_OFFSET_1000_SDMMC_ACCESSOR_SD 0x14BDA0
|
|
||||||
#define FS_OFFSET_1000_SDMMC_ACCESSOR_NAND 0x146C20
|
|
||||||
|
|
||||||
// Hooks
|
|
||||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_READ 0x142380
|
|
||||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_WRITE 0x142460
|
|
||||||
#define FS_OFFSET_1000_RTLD 0x634
|
|
||||||
#define FS_OFFSET_1000_RTLD_DESTINATION 0x9C
|
|
||||||
|
|
||||||
#define FS_OFFSET_1000_CLKRST_SET_MIN_V_CLK_RATE 0x1415A0
|
|
||||||
|
|
||||||
// Misc funcs
|
|
||||||
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910
|
|
||||||
#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960
|
|
||||||
|
|
||||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
|
||||||
|
|
||||||
// Misc Data
|
|
||||||
#define FS_OFFSET_1000_SD_MUTEX 0xE273E8
|
|
||||||
#define FS_OFFSET_1000_NAND_MUTEX 0xE22DA0
|
|
||||||
#define FS_OFFSET_1000_ACTIVE_PARTITION 0xE22DE0
|
|
||||||
#define FS_OFFSET_1000_SDMMC_DAS_HANDLE 0xE0AB90
|
|
||||||
|
|
||||||
// NOPs
|
|
||||||
#define FS_OFFSET_1000_SD_DAS_INIT 0x151CEC
|
|
||||||
|
|
||||||
// Nintendo Paths
|
|
||||||
#define FS_OFFSET_1000_NINTENDO_PATHS \
|
|
||||||
{ \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __FS_1000_H__
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
|
||||||
* Copyright (c) 2019 Atmosphere-NX
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef __FS_1000_EXFAT_H__
|
|
||||||
#define __FS_1000_EXFAT_H__
|
|
||||||
|
|
||||||
// Accessor vtable getters
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_GC 0x14DC90
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_SD 0x14BDA0
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_NAND 0x146C20
|
|
||||||
|
|
||||||
// Hooks
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_READ 0x142380
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_WRITE 0x142460
|
|
||||||
#define FS_OFFSET_1000_EXFAT_RTLD 0x634
|
|
||||||
#define FS_OFFSET_1000_EXFAT_RTLD_DESTINATION 0x9C
|
|
||||||
|
|
||||||
#define FS_OFFSET_1000_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1415A0
|
|
||||||
|
|
||||||
// Misc funcs
|
|
||||||
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
|
|
||||||
#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960
|
|
||||||
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
|
||||||
|
|
||||||
// Misc Data
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SD_MUTEX 0xE353E8
|
|
||||||
#define FS_OFFSET_1000_EXFAT_NAND_MUTEX 0xE30DA0
|
|
||||||
#define FS_OFFSET_1000_EXFAT_ACTIVE_PARTITION 0xE30DE0
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SDMMC_DAS_HANDLE 0xE18B90
|
|
||||||
|
|
||||||
// NOPs
|
|
||||||
#define FS_OFFSET_1000_EXFAT_SD_DAS_INIT 0x151CEC
|
|
||||||
|
|
||||||
// Nintendo Paths
|
|
||||||
#define FS_OFFSET_1000_EXFAT_NINTENDO_PATHS \
|
|
||||||
{ \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
|
|
||||||
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __FS_1000_EXFAT_H__
|
|
||||||
@@ -36,6 +36,7 @@ sdmmc_storage_t sd_storage;
|
|||||||
|
|
||||||
// init vars
|
// init vars
|
||||||
bool custom_driver = true;
|
bool custom_driver = true;
|
||||||
|
extern const volatile emuMMC_ctx_t emuMMC_ctx;
|
||||||
|
|
||||||
// FS funcs
|
// FS funcs
|
||||||
_sdmmc_accessor_gc sdmmc_accessor_gc;
|
_sdmmc_accessor_gc sdmmc_accessor_gc;
|
||||||
@@ -343,7 +344,7 @@ uint64_t sdmmc_wrapper_controller_close(int mmc_id)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mmc_id == FS_SDMMC_EMMC)
|
if (mmc_id == FS_SDMMC_EMMC)
|
||||||
{
|
{
|
||||||
// Close file handles and unmount
|
// Close file handles and unmount
|
||||||
|
|||||||
@@ -50,18 +50,8 @@ extern "C" {
|
|||||||
* @return Result code.
|
* @return Result code.
|
||||||
* @note Syscall number 0x55.
|
* @note Syscall number 0x55.
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
||||||
* @warning Only exists on [10.0.0+]. For older versions use \ref svcLegacyQueryIoMapping.
|
|
||||||
*/
|
*/
|
||||||
Result svcQueryIoMapping(u64* virtaddr, u64* out_size, u64 physaddr, u64 size);
|
Result svcQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a virtual address mapped to a given IO range.
|
|
||||||
* @return Result code.
|
|
||||||
* @note Syscall number 0x55.
|
|
||||||
* @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available.
|
|
||||||
* @warning Only exists on [1.0.0-9.2.0]. For newer versions use \ref svcQueryIoMapping.
|
|
||||||
*/
|
|
||||||
Result svcLegacyQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attaches a device address space to a device.
|
* @brief Attaches a device address space to a device.
|
||||||
|
|||||||
@@ -17,15 +17,6 @@
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
SVC_BEGIN svcQueryIoMapping
|
SVC_BEGIN svcQueryIoMapping
|
||||||
STP X0, X1, [SP, #-16]!
|
|
||||||
SVC 0x55
|
|
||||||
LDP X3, X4, [SP], #16
|
|
||||||
STR X1, [X3]
|
|
||||||
STR X2, [X4]
|
|
||||||
RET
|
|
||||||
SVC_END
|
|
||||||
|
|
||||||
SVC_BEGIN svcLegacyQueryIoMapping
|
|
||||||
STR X0, [SP, #-16]!
|
STR X0, [SP, #-16]!
|
||||||
SVC 0x55
|
SVC 0x55
|
||||||
LDR X2, [SP], #16
|
LDR X2, [SP], #16
|
||||||
|
|||||||
@@ -25,12 +25,11 @@ enum FatalReason
|
|||||||
Fatal_InvalidAccessor,
|
Fatal_InvalidAccessor,
|
||||||
Fatal_ReadNoAccessor,
|
Fatal_ReadNoAccessor,
|
||||||
Fatal_WriteNoAccessor,
|
Fatal_WriteNoAccessor,
|
||||||
Fatal_IoMappingLegacy,
|
Fatal_IoMapping,
|
||||||
Fatal_UnknownVersion,
|
Fatal_UnknownVersion,
|
||||||
Fatal_BadResult,
|
Fatal_BadResult,
|
||||||
Fatal_GetConfig,
|
Fatal_GetConfig,
|
||||||
Fatal_CloseAccessor,
|
Fatal_CloseAccessor,
|
||||||
Fatal_IoMapping,
|
|
||||||
Fatal_Max
|
Fatal_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,15 +38,8 @@ static inline uintptr_t _GetIoMapping(u64 io_addr, u64 io_size)
|
|||||||
u64 vaddr;
|
u64 vaddr;
|
||||||
u64 aligned_addr = (io_addr & ~0xFFFul);
|
u64 aligned_addr = (io_addr & ~0xFFFul);
|
||||||
u64 aligned_size = io_size + (io_addr - aligned_addr);
|
u64 aligned_size = io_size + (io_addr - aligned_addr);
|
||||||
if (emuMMC_ctx.fs_ver >= FS_VER_10_0_0) {
|
if (svcQueryIoMapping(&vaddr, aligned_addr, aligned_size) != 0) {
|
||||||
u64 out_size;
|
fatal_abort(Fatal_IoMapping);
|
||||||
if (svcQueryIoMapping(&vaddr, &out_size, aligned_addr, aligned_size) != 0) {
|
|
||||||
fatal_abort(Fatal_IoMapping);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (svcLegacyQueryIoMapping(&vaddr, aligned_addr, aligned_size) != 0) {
|
|
||||||
fatal_abort(Fatal_IoMappingLegacy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (uintptr_t)(vaddr + (io_addr - aligned_addr));
|
return (uintptr_t)(vaddr + (io_addr - aligned_addr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#define _UTIL_H_
|
#define _UTIL_H_
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "../emuMMC/emummc_ctx.h"
|
|
||||||
|
|
||||||
intptr_t QueryIoMapping(u64 addr, u64 size);
|
intptr_t QueryIoMapping(u64 addr, u64 size);
|
||||||
#define byte_swap_32(num) ((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
|
#define byte_swap_32(num) ((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
|
||||||
@@ -38,6 +37,4 @@ void usleep(u64 ticks);
|
|||||||
void msleep(u64 milliseconds);
|
void msleep(u64 milliseconds);
|
||||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||||
|
|
||||||
extern volatile emuMMC_ctx_t emuMMC_ctx;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -263,20 +263,19 @@ uint32_t fuse_get_5x_key_generation(void) {
|
|||||||
/* Returns the fuse version expected for the firmware. */
|
/* Returns the fuse version expected for the firmware. */
|
||||||
uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) {
|
uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) {
|
||||||
static const uint8_t expected_versions[ATMOSPHERE_TARGET_FIRMWARE_COUNT+1] = {
|
static const uint8_t expected_versions[ATMOSPHERE_TARGET_FIRMWARE_COUNT+1] = {
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_100] = 1,
|
[ATMOSPHERE_TARGET_FIRMWARE_100] = 1,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_200] = 2,
|
[ATMOSPHERE_TARGET_FIRMWARE_200] = 2,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_300] = 3,
|
[ATMOSPHERE_TARGET_FIRMWARE_300] = 3,
|
||||||
/* [ATMOSPHERE_TARGET_FIRMWARE_302] = 4, */
|
/* [ATMOSPHERE_TARGET_FIRMWARE_302] = 4, */
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_400] = 5,
|
[ATMOSPHERE_TARGET_FIRMWARE_400] = 5,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_500] = 6,
|
[ATMOSPHERE_TARGET_FIRMWARE_500] = 6,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_600] = 7,
|
[ATMOSPHERE_TARGET_FIRMWARE_600] = 7,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_620] = 8,
|
[ATMOSPHERE_TARGET_FIRMWARE_620] = 8,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_700] = 9,
|
[ATMOSPHERE_TARGET_FIRMWARE_700] = 9,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_800] = 9,
|
[ATMOSPHERE_TARGET_FIRMWARE_800] = 9,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_810] = 10,
|
[ATMOSPHERE_TARGET_FIRMWARE_810] = 10,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_900] = 11,
|
[ATMOSPHERE_TARGET_FIRMWARE_900] = 11,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_910] = 12,
|
[ATMOSPHERE_TARGET_FIRMWARE_910] = 12,
|
||||||
[ATMOSPHERE_TARGET_FIRMWARE_1000] = 13,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (target_firmware > ATMOSPHERE_TARGET_FIRMWARE_COUNT) {
|
if (target_firmware > ATMOSPHERE_TARGET_FIRMWARE_COUNT) {
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EXOSPHERE_MC0_H
|
|
||||||
#define EXOSPHERE_MC0_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "memory_map.h"
|
|
||||||
|
|
||||||
/* Exosphere driver for the Tegra X1 MC0. */
|
|
||||||
|
|
||||||
static inline uintptr_t get_mc0_base(void) {
|
|
||||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MC0_BASE (get_mc0_base())
|
|
||||||
#define MAKE_MC0_REG(n) MAKE_REG32(MC0_BASE + n)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EXOSPHERE_MC0_H
|
|
||||||
#define EXOSPHERE_MC0_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "memory_map.h"
|
|
||||||
|
|
||||||
/* Exosphere driver for the Tegra X1 MC1. */
|
|
||||||
|
|
||||||
static inline uintptr_t get_mc1_base(void) {
|
|
||||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MC1_BASE (get_mc1_base())
|
|
||||||
#define MAKE_MC1_REG(n) MAKE_REG32(MC1_BASE + n)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXOSPHERE_MEMORY_MAP_H
|
#ifndef EXOSPHERE_MEMORY_MAP_H
|
||||||
#define EXOSPHERE_MEMORY_MAP_H
|
#define EXOSPHERE_MEMORY_MAP_H
|
||||||
|
|
||||||
@@ -48,11 +48,9 @@
|
|||||||
#define _MMAPDEV15 ( 0x6000D000ull, 0x1000ull, true ) /* GPIO-1 - GPIO-8 */
|
#define _MMAPDEV15 ( 0x6000D000ull, 0x1000ull, true ) /* GPIO-1 - GPIO-8 */
|
||||||
#define _MMAPDEV16 ( 0x7000C000ull, 0x1000ull, true ) /* I2C-I2C4 */
|
#define _MMAPDEV16 ( 0x7000C000ull, 0x1000ull, true ) /* I2C-I2C4 */
|
||||||
#define _MMAPDEV17 ( 0x6000F000ull, 0x1000ull, true ) /* Exception vectors */
|
#define _MMAPDEV17 ( 0x6000F000ull, 0x1000ull, true ) /* Exception vectors */
|
||||||
#define _MMAPDEV18 ( 0x7001C000ull, 0x1000ull, true ) /* MC0 */
|
#define _MMAPDEV18 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */
|
||||||
#define _MMAPDEV19 ( 0x7001D000ull, 0x1000ull, true ) /* MC1 */
|
#define _MMAPDEV19 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */
|
||||||
#define _MMAPDEV20 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */
|
#define _MMAPDEV20 ( 0x40038000ull, 0x5000ull, true ) /* DEBUG: IRAM */
|
||||||
#define _MMAPDEV21 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */
|
|
||||||
#define _MMAPDEV22 ( 0x40038000ull, 0x1000ull, true ) /* DEBUG: IRAM */
|
|
||||||
|
|
||||||
/* MMIO 7.0.0+. (addr). */
|
/* MMIO 7.0.0+. (addr). */
|
||||||
#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */
|
#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */
|
||||||
@@ -73,11 +71,9 @@
|
|||||||
#define _MMAPDEV7X15 ( 0x6000D000ull ) /* GPIO-1 - GPIO-8 */
|
#define _MMAPDEV7X15 ( 0x6000D000ull ) /* GPIO-1 - GPIO-8 */
|
||||||
#define _MMAPDEV7X16 ( 0x7000C000ull ) /* I2C-I2C4 */
|
#define _MMAPDEV7X16 ( 0x7000C000ull ) /* I2C-I2C4 */
|
||||||
#define _MMAPDEV7X17 ( 0x6000F000ull ) /* Exception vectors */
|
#define _MMAPDEV7X17 ( 0x6000F000ull ) /* Exception vectors */
|
||||||
#define _MMAPDEV7X18 ( 0x7001C000ull ) /* MC0 */
|
#define _MMAPDEV7X18 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */
|
||||||
#define _MMAPDEV7X19 ( 0x7001D000ull ) /* MC1 */
|
#define _MMAPDEV7X19 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */
|
||||||
#define _MMAPDEV7X20 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */
|
#define _MMAPDEV7X20 ( 0x40038000ull ) /* DEBUG: IRAM */
|
||||||
#define _MMAPDEV7X21 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */
|
|
||||||
#define _MMAPDEV7X22 ( 0x40038000ull ) /* DEBUG: IRAM */
|
|
||||||
|
|
||||||
/* LP0 entry ram segments (addr, size, additional attributes) */
|
/* LP0 entry ram segments (addr, size, additional attributes) */
|
||||||
#define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */
|
#define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */
|
||||||
@@ -137,12 +133,10 @@
|
|||||||
#define MMIO_DEVID_GPIO 15
|
#define MMIO_DEVID_GPIO 15
|
||||||
#define MMIO_DEVID_DTV_I2C234 16
|
#define MMIO_DEVID_DTV_I2C234 16
|
||||||
#define MMIO_DEVID_EXCEPTION_VECTORS 17
|
#define MMIO_DEVID_EXCEPTION_VECTORS 17
|
||||||
#define MMIO_DEVID_MC0 18
|
#define MMIO_DEVID_AMS_IRAM_PAGE 18
|
||||||
#define MMIO_DEVID_MC1 19
|
#define MMIO_DEVID_AMS_USER_PAGE 19
|
||||||
#define MMIO_DEVID_AMS_IRAM_PAGE 20
|
#define MMIO_DEVID_DEBUG_IRAM 20
|
||||||
#define MMIO_DEVID_AMS_USER_PAGE 21
|
#define MMIO_DEVID_MAX 21
|
||||||
#define MMIO_DEVID_DEBUG_IRAM 22
|
|
||||||
#define MMIO_DEVID_MAX 23
|
|
||||||
|
|
||||||
#define LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM 0
|
#define LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM 0
|
||||||
#define LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE 1
|
#define LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE 1
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ static void setup_se(void) {
|
|||||||
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
|
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -339,7 +338,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
|||||||
|
|
||||||
/* Perform version checks. */
|
/* Perform version checks. */
|
||||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1000_CURRENT) {
|
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_910_CURRENT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +466,6 @@ static void copy_warmboot_bin_to_dram() {
|
|||||||
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
warmboot_src = (uint8_t *)0x4003E000;
|
warmboot_src = (uint8_t *)0x4003E000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -553,9 +551,6 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
|||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
MAKE_REG32(PMC_BASE + 0x360) = 0x18C;
|
MAKE_REG32(PMC_BASE + 0x360) = 0x18C;
|
||||||
break;
|
break;
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
MAKE_REG32(PMC_BASE + 0x360) = 0x1AD;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,8 +73,7 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
|
|||||||
#define PACKAGE2_MAXVER_700_800 0xA
|
#define PACKAGE2_MAXVER_700_800 0xA
|
||||||
#define PACKAGE2_MAXVER_810 0xB
|
#define PACKAGE2_MAXVER_810 0xB
|
||||||
#define PACKAGE2_MAXVER_900 0xC
|
#define PACKAGE2_MAXVER_900 0xC
|
||||||
#define PACKAGE2_MAXVER_910_920 0xD
|
#define PACKAGE2_MAXVER_910_CURRENT 0xD
|
||||||
#define PACKAGE2_MAXVER_1000_CURRENT 0xE
|
|
||||||
|
|
||||||
#define PACKAGE2_MINVER_100 0x3
|
#define PACKAGE2_MINVER_100 0x3
|
||||||
#define PACKAGE2_MINVER_200 0x4
|
#define PACKAGE2_MINVER_200 0x4
|
||||||
@@ -87,8 +86,7 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
|
|||||||
#define PACKAGE2_MINVER_700_800 0xB
|
#define PACKAGE2_MINVER_700_800 0xB
|
||||||
#define PACKAGE2_MINVER_810 0xC
|
#define PACKAGE2_MINVER_810 0xC
|
||||||
#define PACKAGE2_MINVER_900 0xD
|
#define PACKAGE2_MINVER_900 0xD
|
||||||
#define PACKAGE2_MINVER_910_920 0xE
|
#define PACKAGE2_MINVER_910_CURRENT 0xE
|
||||||
#define PACKAGE2_MINVER_1000_CURRENT 0xF
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "rsa_common.h"
|
|
||||||
|
|
||||||
/* Instantiate the shared RSA data inside a single translation unit. */
|
|
||||||
rsa_shared_data_t g_rsa_shared_data = {};
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EXOSPHERE_RSA_COMMON_H
|
|
||||||
#define EXOSPHERE_RSA_COMMON_H
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint8_t user_data[0x100];
|
|
||||||
} storage_exp_mod;
|
|
||||||
struct {
|
|
||||||
uint32_t master_key_rev;
|
|
||||||
uint32_t type;
|
|
||||||
uint64_t expected_label_hash[4];
|
|
||||||
} unwrap_titlekey;
|
|
||||||
} rsa_shared_data_t __attribute__((aligned(4)));
|
|
||||||
|
|
||||||
_Static_assert(sizeof(rsa_shared_data_t) == 0x100);
|
|
||||||
|
|
||||||
extern rsa_shared_data_t g_rsa_shared_data;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@@ -47,25 +47,24 @@ void ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
|||||||
ll->addr_info.address = 0;
|
ll->addr_info.address = 0;
|
||||||
ll->addr_info.size = 0;
|
ll->addr_info.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll));
|
flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_security_engine_callback(unsigned int (*callback)(void)) {
|
void set_security_engine_callback(unsigned int (*callback)(void)) {
|
||||||
/* Set the callback. */
|
if (callback == NULL || g_se_callback != NULL) {
|
||||||
g_se_callback = callback;
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable SE Interrupt firing for async op. */
|
g_se_callback = callback;
|
||||||
se_get_regs()->SE_INT_ENABLE = 0x10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fires on Security Engine operation completion. */
|
/* Fires on Security Engine operation completion. */
|
||||||
void se_operation_completed(void) {
|
void se_operation_completed(void) {
|
||||||
se_get_regs()->SE_INT_ENABLE = 0;
|
se_get_regs()->SE_INT_ENABLE = 0;
|
||||||
unsigned int (*callback)(void) = g_se_callback;
|
if (g_se_callback != NULL) {
|
||||||
if (callback != NULL) {
|
g_se_callback();
|
||||||
g_se_callback = NULL;
|
g_se_callback = NULL;
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +103,7 @@ void se_validate_stored_vector(void) {
|
|||||||
|
|
||||||
uint8_t calc_vector[0x10];
|
uint8_t calc_vector[0x10];
|
||||||
se_generate_test_vector(calc_vector);
|
se_generate_test_vector(calc_vector);
|
||||||
|
|
||||||
/* Ensure nobody's messed with the security engine while we slept. */
|
/* Ensure nobody's messed with the security engine while we slept. */
|
||||||
if (memcmp(calc_vector, g_se_stored_test_vector, 0x10) != 0) {
|
if (memcmp(calc_vector, g_se_stored_test_vector, 0x10) != 0) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
@@ -123,7 +122,7 @@ void se_generate_stored_vector(void) {
|
|||||||
/* Set the flags for an AES keyslot. */
|
/* Set the flags for an AES keyslot. */
|
||||||
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -142,7 +141,7 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
|||||||
/* Set the flags for an RSA keyslot. */
|
/* Set the flags for an RSA keyslot. */
|
||||||
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_RSA_MAX) {
|
if (keyslot >= KEYSLOT_RSA_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -161,7 +160,7 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
|||||||
|
|
||||||
void clear_aes_keyslot(unsigned int keyslot) {
|
void clear_aes_keyslot(unsigned int keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -175,7 +174,7 @@ void clear_aes_keyslot(unsigned int keyslot) {
|
|||||||
|
|
||||||
void clear_rsa_keyslot(unsigned int keyslot) {
|
void clear_rsa_keyslot(unsigned int keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_RSA_MAX) {
|
if (keyslot >= KEYSLOT_RSA_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -195,7 +194,7 @@ void clear_rsa_keyslot(unsigned int keyslot) {
|
|||||||
|
|
||||||
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -208,7 +207,7 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
|||||||
|
|
||||||
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
|
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
|
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -229,7 +228,7 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
|
|||||||
|
|
||||||
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
|
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -242,7 +241,7 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
|||||||
|
|
||||||
void clear_aes_keyslot_iv(unsigned int keyslot) {
|
void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -261,7 +260,7 @@ void set_se_ctr(const void *ctr) {
|
|||||||
|
|
||||||
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
|
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
|
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -277,7 +276,7 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
|
|||||||
|
|
||||||
void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) {
|
void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -305,6 +304,9 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
|
|||||||
/* Set the callback, for after the async operation. */
|
/* Set the callback, for after the async operation. */
|
||||||
set_security_engine_callback(callback);
|
set_security_engine_callback(callback);
|
||||||
|
|
||||||
|
/* Enable SE Interrupt firing for async op. */
|
||||||
|
se->SE_INT_ENABLE = 0x10;
|
||||||
|
|
||||||
/* Setup Input/Output lists */
|
/* Setup Input/Output lists */
|
||||||
se->SE_IN_LL_ADDR = in_ll_paddr;
|
se->SE_IN_LL_ADDR = in_ll_paddr;
|
||||||
se->SE_OUT_LL_ADDR = out_ll_paddr;
|
se->SE_OUT_LL_ADDR = out_ll_paddr;
|
||||||
@@ -336,7 +338,7 @@ void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, ui
|
|||||||
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback);
|
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int (*callback)(void)) {
|
void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
uint8_t stack_buf[KEYSIZE_RSA_MAX];
|
uint8_t stack_buf[KEYSIZE_RSA_MAX];
|
||||||
|
|
||||||
@@ -346,7 +348,7 @@ void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int
|
|||||||
|
|
||||||
/* Endian swap the input. */
|
/* Endian swap the input. */
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
stack_buf[i] = *((const uint8_t *)buf + size - i - 1);
|
stack_buf[i] = *((uint8_t *)buf + size - i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
||||||
@@ -356,6 +358,9 @@ void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int
|
|||||||
|
|
||||||
set_security_engine_callback(callback);
|
set_security_engine_callback(callback);
|
||||||
|
|
||||||
|
/* Enable SE interrupt firing for async op. */
|
||||||
|
se->SE_INT_ENABLE = 0x10;
|
||||||
|
|
||||||
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
|
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
|
||||||
trigger_se_rsa_op(stack_buf, size);
|
trigger_se_rsa_op(stack_buf, size);
|
||||||
|
|
||||||
@@ -463,7 +468,7 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v
|
|||||||
void trigger_se_rsa_op(void *buf, size_t size) {
|
void trigger_se_rsa_op(void *buf, size_t size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
se_ll_t in_ll;
|
se_ll_t in_ll;
|
||||||
|
|
||||||
ll_init(&in_ll, (void *)buf, size);
|
ll_init(&in_ll, (void *)buf, size);
|
||||||
|
|
||||||
/* Set the input LL. */
|
/* Set the input LL. */
|
||||||
@@ -486,19 +491,19 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
|||||||
|
|
||||||
ll_init(&in_ll, (void *)src, src_size);
|
ll_init(&in_ll, (void *)src, src_size);
|
||||||
ll_init(&out_ll, dst, dst_size);
|
ll_init(&out_ll, dst, dst_size);
|
||||||
|
|
||||||
__dsb_sy();
|
__dsb_sy();
|
||||||
|
|
||||||
/* Set the LLs. */
|
/* Set the LLs. */
|
||||||
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
||||||
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
|
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
|
||||||
|
|
||||||
/* Set registers for operation. */
|
/* Set registers for operation. */
|
||||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||||
se->SE_OPERATION = op;
|
se->SE_OPERATION = op;
|
||||||
(void)(se->SE_OPERATION);
|
(void)(se->SE_OPERATION);
|
||||||
|
|
||||||
__dsb_ish();
|
__dsb_ish();
|
||||||
|
|
||||||
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
||||||
@@ -533,7 +538,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
|||||||
|
|
||||||
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
|
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
|
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -543,7 +548,7 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
|||||||
}
|
}
|
||||||
if (dst_size) {
|
if (dst_size) {
|
||||||
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size);
|
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int num_blocks = src_size >> 4;
|
unsigned int num_blocks = src_size >> 4;
|
||||||
|
|
||||||
@@ -571,12 +576,12 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
|||||||
|
|
||||||
if (dst_size) {
|
if (dst_size) {
|
||||||
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size);
|
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
|
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -601,7 +606,7 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
|
|||||||
|
|
||||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -627,15 +632,15 @@ void shift_left_xor_rb(uint8_t *key) {
|
|||||||
|
|
||||||
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
|
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_size) {
|
if (data_size) {
|
||||||
flush_dcache_range((uint8_t *)data, (uint8_t *)data + data_size);
|
flush_dcache_range((uint8_t *)data, (uint8_t *)data + data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the derived key, to be XOR'd with final output block. */
|
/* Generate the derived key, to be XOR'd with final output block. */
|
||||||
uint8_t derived_key[0x10] = {0};
|
uint8_t derived_key[0x10] = {0};
|
||||||
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
|
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
|
||||||
@@ -647,7 +652,7 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
|||||||
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
||||||
clear_aes_keyslot_iv(keyslot);
|
clear_aes_keyslot_iv(keyslot);
|
||||||
|
|
||||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||||
/* Handle aligned blocks. */
|
/* Handle aligned blocks. */
|
||||||
if (num_blocks > 1) {
|
if (num_blocks > 1) {
|
||||||
@@ -655,7 +660,7 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
|||||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||||
se->SE_CRYPTO_CONFIG |= 0x80;
|
se->SE_CRYPTO_CONFIG |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create final block. */
|
/* Create final block. */
|
||||||
uint8_t last_block[0x10] = {0};
|
uint8_t last_block[0x10] = {0};
|
||||||
if (data_size & 0xF) {
|
if (data_size & 0xF) {
|
||||||
@@ -664,11 +669,11 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
|||||||
} else if (data_size >= 0x10) {
|
} else if (data_size >= 0x10) {
|
||||||
memcpy(last_block, data + data_size - 0x10, 0x10);
|
memcpy(last_block, data + data_size - 0x10, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 0x10; i++) {
|
for (unsigned int i = 0; i < 0x10; i++) {
|
||||||
last_block[i] ^= derived_key[i];
|
last_block[i] ^= derived_key[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform last operation. */
|
/* Perform last operation. */
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
flush_dcache_range(last_block, last_block + sizeof(last_block));
|
flush_dcache_range(last_block, last_block + sizeof(last_block));
|
||||||
@@ -689,11 +694,11 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size,
|
|||||||
|
|
||||||
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
|
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
|
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
|
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
|
||||||
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||||
@@ -704,7 +709,7 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
|||||||
/* SHA256 Implementation. */
|
/* SHA256 Implementation. */
|
||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
/* Setup config for SHA256, size = BITS(src_size) */
|
/* Setup config for SHA256, size = BITS(src_size) */
|
||||||
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||||
se->SE_SHA_CONFIG = 1;
|
se->SE_SHA_CONFIG = 1;
|
||||||
@@ -716,7 +721,7 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
|||||||
se->SE_SHA_MSG_LEFT[1] = 0;
|
se->SE_SHA_MSG_LEFT[1] = 0;
|
||||||
se->SE_SHA_MSG_LEFT[2] = 0;
|
se->SE_SHA_MSG_LEFT[2] = 0;
|
||||||
se->SE_SHA_MSG_LEFT[3] = 0;
|
se->SE_SHA_MSG_LEFT[3] = 0;
|
||||||
|
|
||||||
/* Trigger the operation. */
|
/* Trigger the operation. */
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||||
|
|
||||||
@@ -729,7 +734,7 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
|||||||
/* RNG API */
|
/* RNG API */
|
||||||
void se_initialize_rng(unsigned int keyslot) {
|
void se_initialize_rng(unsigned int keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -749,7 +754,7 @@ void se_initialize_rng(unsigned int keyslot) {
|
|||||||
|
|
||||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -772,7 +777,7 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
|||||||
/* SE context save API. */
|
/* SE context save API. */
|
||||||
void se_set_in_context_save_mode(bool is_context_save_mode) {
|
void se_set_in_context_save_mode(bool is_context_save_mode) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
uint32_t val = se->SE_SE_SECURITY;
|
uint32_t val = se->SE_SE_SECURITY;
|
||||||
if (is_context_save_mode) {
|
if (is_context_save_mode) {
|
||||||
val |= 0x10000;
|
val |= 0x10000;
|
||||||
@@ -786,7 +791,7 @@ void se_set_in_context_save_mode(bool is_context_save_mode) {
|
|||||||
|
|
||||||
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
|
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) {
|
if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -796,7 +801,7 @@ void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot)
|
|||||||
se->SE_CRYPTO_CONFIG = (rng_keyslot << 24) | 0x108;
|
se->SE_CRYPTO_CONFIG = (rng_keyslot << 24) | 0x108;
|
||||||
se->SE_RNG_CONFIG = 4;
|
se->SE_RNG_CONFIG = 4;
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
|
|
||||||
/* Generate low part of key. */
|
/* Generate low part of key. */
|
||||||
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8);
|
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8);
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||||
@@ -807,7 +812,7 @@ void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot)
|
|||||||
|
|
||||||
void se_generate_srk(unsigned int srkgen_keyslot) {
|
void se_generate_srk(unsigned int srkgen_keyslot) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
se->SE_CONFIG = (ALG_RNG | DST_SRK);
|
se->SE_CONFIG = (ALG_RNG | DST_SRK);
|
||||||
se->SE_CRYPTO_CONFIG = (srkgen_keyslot << 24) | 0x108;
|
se->SE_CRYPTO_CONFIG = (srkgen_keyslot << 24) | 0x108;
|
||||||
se->SE_RNG_CONFIG = 6;
|
se->SE_RNG_CONFIG = 6;
|
||||||
@@ -842,24 +847,24 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
|||||||
/* Generate the SRK (context save encryption key). */
|
/* Generate the SRK (context save encryption key). */
|
||||||
se_generate_random_key(srkgen_keyslot, rng_keyslot);
|
se_generate_random_key(srkgen_keyslot, rng_keyslot);
|
||||||
se_generate_srk(srkgen_keyslot);
|
se_generate_srk(srkgen_keyslot);
|
||||||
|
|
||||||
flush_dcache_range(work_buf, work_buf + 0x10);
|
flush_dcache_range(work_buf, work_buf + 0x10);
|
||||||
se_generate_random(rng_keyslot, work_buf, 0x10);
|
se_generate_random(rng_keyslot, work_buf, 0x10);
|
||||||
flush_dcache_range(work_buf, work_buf + 0x10);
|
flush_dcache_range(work_buf, work_buf + 0x10);
|
||||||
|
|
||||||
/* Save random initial block. */
|
/* Save random initial block. */
|
||||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst, 0x10, work_buf, 0x10);
|
se_encrypt_with_srk(dst, 0x10, work_buf, 0x10);
|
||||||
|
|
||||||
/* Save Sticky Bits. */
|
/* Save Sticky Bits. */
|
||||||
for (unsigned int i = 0; i < 0x2; i++) {
|
for (unsigned int i = 0; i < 0x2; i++) {
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0);
|
se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save AES Key Table. */
|
/* Save AES Key Table. */
|
||||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
|
||||||
@@ -869,21 +874,21 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
|||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0);
|
se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save AES Original IVs. */
|
/* Save AES Original IVs. */
|
||||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0);
|
se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save AES Updated IVs */
|
/* Save AES Updated IVs */
|
||||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0);
|
se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save RSA Keytable. */
|
/* Save RSA Keytable. */
|
||||||
uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430;
|
uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430;
|
||||||
for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) {
|
for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) {
|
||||||
@@ -896,13 +901,13 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save "Known Pattern. " */
|
/* Save "Known Pattern. " */
|
||||||
static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10);
|
se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10);
|
||||||
|
|
||||||
/* Save SRK into PMC registers. */
|
/* Save SRK into PMC registers. */
|
||||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_SRK);
|
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_SRK);
|
||||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXOSPHERE_SE_H
|
#ifndef EXOSPHERE_SE_H
|
||||||
#define EXOSPHERE_SE_H
|
#define EXOSPHERE_SE_H
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
|||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
||||||
|
|
||||||
/* RSA API */
|
/* RSA API */
|
||||||
void se_exp_mod(unsigned int keyslot, const void *buf, size_t size, unsigned int (*callback)(void));
|
void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void));
|
||||||
void se_get_exp_mod_output(void *buf, size_t size);
|
void se_get_exp_mod_output(void *buf, size_t size);
|
||||||
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size);
|
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size);
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
#include "synchronization.h"
|
#include "synchronization.h"
|
||||||
#include "masterkey.h"
|
#include "masterkey.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "mc0.h"
|
|
||||||
#include "mc1.h"
|
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
#include "randomcache.h"
|
#include "randomcache.h"
|
||||||
@@ -190,7 +188,6 @@ void set_version_specific_smcs(void) {
|
|||||||
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
/* No more LoadSecureExpModKey. */
|
/* No more LoadSecureExpModKey. */
|
||||||
g_smc_user_table[0xE].handler = NULL;
|
g_smc_user_table[0xE].handler = NULL;
|
||||||
g_smc_user_table[0xC].id = 0xC300D60C;
|
g_smc_user_table[0xC].id = 0xC300D60C;
|
||||||
@@ -436,18 +433,19 @@ uint32_t smc_get_result(smc_args_t *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) {
|
uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) {
|
||||||
uint32_t res = get_exp_mod_result();
|
if (get_exp_mod_done() != 1) {
|
||||||
if (res == 0) {
|
return 3;
|
||||||
if (size == 0x100) {
|
|
||||||
se_get_exp_mod_output(buf, 0x100);
|
|
||||||
/* smc_exp_mod is done now. */
|
|
||||||
clear_user_smc_in_progress();
|
|
||||||
res = 0;
|
|
||||||
} else {
|
|
||||||
res = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
if (size != 0x100) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
se_get_exp_mod_output(buf, 0x100);
|
||||||
|
|
||||||
|
/* smc_exp_mod is done now. */
|
||||||
|
clear_user_smc_in_progress();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_exp_mod(smc_args_t *args) {
|
uint32_t smc_exp_mod(smc_args_t *args) {
|
||||||
@@ -510,31 +508,30 @@ uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey_get_result(void *buf, uint64_t siz
|
|||||||
uint8_t aes_wrapped_titlekey[0x10];
|
uint8_t aes_wrapped_titlekey[0x10];
|
||||||
uint8_t titlekey[0x10];
|
uint8_t titlekey[0x10];
|
||||||
uint64_t sealed_titlekey[2];
|
uint64_t sealed_titlekey[2];
|
||||||
uint32_t res = get_exp_mod_result();
|
if (get_exp_mod_done() != 1) {
|
||||||
if (res == 0) {
|
return 3;
|
||||||
if (size == 0x10) {
|
|
||||||
se_get_exp_mod_output(rsa_wrapped_titlekey, 0x100);
|
|
||||||
if (tkey_rsa_oaep_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) == 0x10) {
|
|
||||||
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
|
||||||
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10);
|
|
||||||
|
|
||||||
p_sealed_key[0] = sealed_titlekey[0];
|
|
||||||
p_sealed_key[1] = sealed_titlekey[1];
|
|
||||||
|
|
||||||
res = 0;
|
|
||||||
} else {
|
|
||||||
/* Failed to extract RSA OAEP wrapped key. */
|
|
||||||
res = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* smc_unwrap_rsa_oaep_wrapped_titlekey is done now. */
|
|
||||||
clear_user_smc_in_progress();
|
|
||||||
} else {
|
|
||||||
res = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
if (size != 0x10) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
se_get_exp_mod_output(rsa_wrapped_titlekey, 0x100);
|
||||||
|
if (tkey_rsa_oaep_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) != 0x10) {
|
||||||
|
/* Failed to extract RSA OAEP wrapped key. */
|
||||||
|
clear_user_smc_in_progress();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
||||||
|
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10);
|
||||||
|
|
||||||
|
p_sealed_key[0] = sealed_titlekey[0];
|
||||||
|
p_sealed_key[1] = sealed_titlekey[1];
|
||||||
|
|
||||||
|
/* smc_unwrap_rsa_oaep_wrapped_titlekey is done now. */
|
||||||
|
clear_user_smc_in_progress();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
|
uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
|
||||||
@@ -619,7 +616,7 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||||||
}
|
}
|
||||||
/* Check for PMC registers. */
|
/* Check for PMC registers. */
|
||||||
if (0x7000E400 <= address && address <= 0x7000EFFF) {
|
if (0x7000E400 <= address && address <= 0x7000EFFF) {
|
||||||
static const uint8_t pmc_whitelist[0x28] = {
|
const uint8_t pmc_whitelist[0x28] = {
|
||||||
0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03,
|
0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03,
|
||||||
0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00,
|
0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00,
|
||||||
@@ -635,83 +632,39 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address &&
|
||||||
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) {
|
address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + MMIO_GET_DEVICE_SIZE(MMIO_DEVID_MC)) {
|
||||||
static const uint8_t mc_whitelist_5x[0xD00/(sizeof(uint32_t) * 8)] = {
|
/* Memory Controller RW supported only on 4.0.0+ */
|
||||||
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
const uint8_t mc_whitelist[0x68] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
||||||
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
||||||
0x80, 0xFF, 0x08, 0x80, 0x03, 0x38, 0x8E, 0x1F,
|
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
||||||
0xC8, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00,
|
||||||
0xF0, 0x1F, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F,
|
0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
||||||
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F,
|
||||||
};
|
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
||||||
static const uint8_t mc01_whitelist_5x[0xC00/(sizeof(uint32_t) * 8)] = {
|
};
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
uint32_t offset = (uint32_t)(address - 0x70019000);
|
||||||
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
uint32_t wl_ind = (offset >> 5);
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* If address is whitelisted, allow write. */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
if (wl_ind < sizeof(mc_whitelist) && (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
p_mmio = (volatile uint32_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC) + offset);
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
} else {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* These addresses are not allowed by the whitelist. */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* This is "probably" to fuck with hackers who got access to smcReadWriteRegister and are trying to get */
|
||||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
/* control of the BPMP for jamais vu etc., since there's no other reason to return 0 despite failure. */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00,
|
if (address == 0x7001923C || address == 0x70019298) {
|
||||||
};
|
return 0;
|
||||||
static const struct {
|
|
||||||
uint32_t phys_addr;
|
|
||||||
uint32_t size;
|
|
||||||
uint64_t virt_addr;
|
|
||||||
const uint8_t *whitelist;
|
|
||||||
} register_whitelists[3] = {
|
|
||||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC), sizeof(mc_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC), mc_whitelist_5x },
|
|
||||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC0), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0), mc01_whitelist_5x },
|
|
||||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC1), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1), mc01_whitelist_5x },
|
|
||||||
};
|
|
||||||
for (unsigned int which = 0; which < 3; which++) {
|
|
||||||
if (register_whitelists[which].phys_addr <= address && address < register_whitelists[which].phys_addr + register_whitelists[which].size) {
|
|
||||||
uint32_t offset = (uint32_t)(address - register_whitelists[which].phys_addr);
|
|
||||||
uint32_t wl_ind = (offset >> 5);
|
|
||||||
/* If address is whitelisted, allow write. */
|
|
||||||
if (register_whitelists[which].whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) {
|
|
||||||
p_mmio = (volatile uint32_t *)(register_whitelists[which].virt_addr + offset);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) {
|
|
||||||
if (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + 0xD00) {
|
|
||||||
/* Memory Controller RW supported only on 4.0.0+ */
|
|
||||||
static const uint8_t mc_whitelist[0x68] = {
|
|
||||||
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
|
||||||
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
|
||||||
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
|
||||||
0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00,
|
|
||||||
0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
|
||||||
0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F,
|
|
||||||
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
|
||||||
};
|
|
||||||
uint32_t offset = (uint32_t)(address - MMIO_GET_DEVICE_PA(MMIO_DEVID_MC));
|
|
||||||
uint32_t wl_ind = (offset >> 5);
|
|
||||||
/* If address is whitelisted, allow write. */
|
|
||||||
if (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) {
|
|
||||||
p_mmio = (volatile uint32_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC) + offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,16 +683,9 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||||||
/* Return old value. */
|
/* Return old value. */
|
||||||
args->X[1] = old_value;
|
args->X[1] = old_value;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && (address == 0x7001923C || address == 0x70019298)) {
|
|
||||||
/* These addresses are not allowed by the whitelist. */
|
|
||||||
/* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */
|
|
||||||
/* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */
|
|
||||||
/* This is "probably" to fuck with hackers who got access to smcReadWriteRegister and are trying to get */
|
|
||||||
/* control of the BPMP for jamais vu etc., since there's no other reason to return 0 despite failure. */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,93 +34,12 @@
|
|||||||
|
|
||||||
/* Globals. */
|
/* Globals. */
|
||||||
static bool g_crypt_aes_done = false;
|
static bool g_crypt_aes_done = false;
|
||||||
static uint32_t g_exp_mod_result = 0;
|
static bool g_exp_mod_done = false;
|
||||||
|
|
||||||
static __attribute__((aligned(4))) uint8_t g_imported_exponents[4][0x100];
|
static uint8_t g_imported_exponents[4][0x100];
|
||||||
static __attribute__((aligned(4))) uint8_t g_imported_moduli[4][0x100];
|
|
||||||
static bool g_is_modulus_verified[4];
|
|
||||||
|
|
||||||
static __attribute__((aligned(4))) const uint8_t g_rsa_public_key[4] = { 0x00, 0x01, 0x00, 0x01 };
|
|
||||||
|
|
||||||
static __attribute__((aligned(4))) const uint8_t g_rsa_test_vector[0x100] = {
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
|
|
||||||
'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint32_t g_test_exp_mod_keyslot = 0;
|
|
||||||
static uint32_t g_test_exp_mod_usecase = 0;
|
|
||||||
static bool g_test_exp_mod_in_progress = false;
|
|
||||||
|
|
||||||
static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6};
|
static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6};
|
||||||
|
|
||||||
static void import_rsa_exponent(unsigned int which, const uint8_t *exponent, uint64_t size) {
|
|
||||||
g_is_modulus_verified[which] = false;
|
|
||||||
for (unsigned int i = 0; i < 0x100; i++) {
|
|
||||||
g_imported_exponents[which][i] = exponent[i];
|
|
||||||
g_imported_moduli[which][i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void import_rsa_modulus(unsigned int which, const uint8_t *modulus, uint64_t size) {
|
|
||||||
uint64_t clamped_size = 0x100;
|
|
||||||
if (size <= 0x100) {
|
|
||||||
clamped_size = size;
|
|
||||||
}
|
|
||||||
if (clamped_size != 0) {
|
|
||||||
/* The official secure monitor implements this via bit-fiddling, */
|
|
||||||
/* and to prevent accidental inaccuracy we will too. */
|
|
||||||
/* It's probably done to prevent errors on negative sizes. */
|
|
||||||
uint64_t remaining = 0x100;
|
|
||||||
if (size != 0x100 && (~size >= ~0xFFFFFFFFFFFFFEFFULL)) {
|
|
||||||
remaining = size;
|
|
||||||
}
|
|
||||||
memcpy(&g_imported_moduli[which][0], modulus, remaining);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool load_imported_rsa_keypair(unsigned int keyslot, unsigned int which) {
|
|
||||||
if (!g_is_modulus_verified[which]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
set_rsa_keyslot(keyslot, g_imported_moduli[which], 0x100, g_imported_exponents[which], 0x100);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rsa_modulus_public(unsigned int which, unsigned int keyslot, const uint8_t *modulus, uint64_t modulus_size, unsigned int (*callback)(void)) {
|
|
||||||
import_rsa_modulus(which, modulus, modulus_size);
|
|
||||||
set_rsa_keyslot(keyslot, modulus, modulus_size, g_rsa_public_key, 0x4);
|
|
||||||
se_exp_mod(keyslot, g_rsa_test_vector, 0x100, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rsa_modulus_private(unsigned int which, unsigned int keyslot, unsigned int (*callback)(void)) {
|
|
||||||
uint8_t exponentiated_data[0x100];
|
|
||||||
se_get_exp_mod_output(exponentiated_data, sizeof(exponentiated_data));
|
|
||||||
set_rsa_keyslot(keyslot, g_imported_moduli[which], 0x100, g_imported_exponents[which], 0x100);
|
|
||||||
se_exp_mod(keyslot, exponentiated_data, 0x100, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void validate_rsa_result(unsigned int which) {
|
|
||||||
char result[0x100];
|
|
||||||
se_get_exp_mod_output(result, sizeof(result));
|
|
||||||
if (memcmp(result, g_rsa_test_vector, sizeof(result)) == 0) {
|
|
||||||
g_is_modulus_verified[which] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_user_keyslot_valid(unsigned int keyslot) {
|
static bool is_user_keyslot_valid(unsigned int keyslot) {
|
||||||
switch (exosphere_get_target_firmware()) {
|
switch (exosphere_get_target_firmware()) {
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_100:
|
case ATMOSPHERE_TARGET_FIRMWARE_100:
|
||||||
@@ -136,45 +55,27 @@ static bool is_user_keyslot_valid(unsigned int keyslot) {
|
|||||||
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
case ATMOSPHERE_TARGET_FIRMWARE_810:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
case ATMOSPHERE_TARGET_FIRMWARE_900:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
default:
|
default:
|
||||||
return keyslot <= 5;
|
return keyslot <= 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_exp_mod_result(uint32_t result) {
|
void set_exp_mod_done(bool done) {
|
||||||
g_exp_mod_result = result;
|
g_exp_mod_done = done;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_exp_mod_result(void) {
|
bool get_exp_mod_done(void) {
|
||||||
return g_exp_mod_result;
|
return g_exp_mod_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t exp_mod_done_handler(void) {
|
uint32_t exp_mod_done_handler(void) {
|
||||||
set_exp_mod_result(0);
|
set_exp_mod_done(true);
|
||||||
|
|
||||||
se_trigger_interrupt();
|
se_trigger_interrupt();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t test_exp_mod_done_handler(void) {
|
|
||||||
if (g_test_exp_mod_in_progress) {
|
|
||||||
g_test_exp_mod_in_progress = false;
|
|
||||||
test_rsa_modulus_private(g_test_exp_mod_usecase, g_test_exp_mod_keyslot, test_exp_mod_done_handler);
|
|
||||||
} else {
|
|
||||||
validate_rsa_result(g_test_exp_mod_usecase);
|
|
||||||
if (load_imported_rsa_keypair(g_test_exp_mod_keyslot, g_test_exp_mod_usecase)) {
|
|
||||||
se_exp_mod(g_test_exp_mod_keyslot, g_rsa_shared_data.storage_exp_mod.user_data, 0x100, exp_mod_done_handler);
|
|
||||||
} else {
|
|
||||||
set_exp_mod_result(2);
|
|
||||||
se_trigger_interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t user_exp_mod(smc_args_t *args) {
|
uint32_t user_exp_mod(smc_args_t *args) {
|
||||||
uint8_t modulus[0x100];
|
uint8_t modulus[0x100];
|
||||||
uint8_t exponent[0x100];
|
uint8_t exponent[0x100];
|
||||||
@@ -207,8 +108,7 @@ uint32_t user_exp_mod(smc_args_t *args) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_exp_mod_result(3);
|
set_exp_mod_done(false);
|
||||||
|
|
||||||
/* Hardcode RSA keyslot 0. */
|
/* Hardcode RSA keyslot 0. */
|
||||||
set_rsa_keyslot(0, modulus, 0x100, exponent, exponent_size);
|
set_rsa_keyslot(0, modulus, 0x100, exponent, exponent_size);
|
||||||
se_exp_mod(0, input, 0x100, exp_mod_done_handler);
|
se_exp_mod(0, input, 0x100, exp_mod_done_handler);
|
||||||
@@ -750,21 +650,10 @@ uint32_t user_secure_exp_mod(smc_args_t *args) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_exp_mod_result(3);
|
set_exp_mod_done(false);
|
||||||
|
|
||||||
/* Hardcode RSA keyslot 0. */
|
/* Hardcode RSA keyslot 0. */
|
||||||
if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_1000) {
|
set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[exponent_id], 0x100);
|
||||||
set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[exponent_id], 0x100);
|
se_exp_mod(0, input, 0x100, exp_mod_done_handler);
|
||||||
se_exp_mod(0, input, 0x100, exp_mod_done_handler);
|
|
||||||
} else if (load_imported_rsa_keypair(0, exponent_id)) {
|
|
||||||
se_exp_mod(0, input, 0x100, exp_mod_done_handler);
|
|
||||||
} else {
|
|
||||||
memcpy(g_rsa_shared_data.storage_exp_mod.user_data, input, 0x100);
|
|
||||||
g_test_exp_mod_keyslot = 0;
|
|
||||||
g_test_exp_mod_usecase = exponent_id;
|
|
||||||
g_test_exp_mod_in_progress = true;
|
|
||||||
test_rsa_modulus_public(exponent_id, 0, modulus, 0x100, test_exp_mod_done_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -811,7 +700,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_exp_mod_result(3);
|
set_exp_mod_done(false);
|
||||||
|
|
||||||
/* Expected label_hash occupies args->X[3] to args->X[6]. */
|
/* Expected label_hash occupies args->X[3] to args->X[6]. */
|
||||||
tkey_set_expected_label_hash(&args->X[3]);
|
tkey_set_expected_label_hash(&args->X[3]);
|
||||||
@@ -990,7 +879,6 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int exponent_id;
|
unsigned int exponent_id;
|
||||||
bool import_modulus;
|
|
||||||
|
|
||||||
switch (usecase) {
|
switch (usecase) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -1000,33 +888,22 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) {
|
|||||||
return 0;
|
return 0;
|
||||||
case 1:
|
case 1:
|
||||||
exponent_id = 1;
|
exponent_id = 1;
|
||||||
import_modulus = false;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
exponent_id = 0;
|
exponent_id = 0;
|
||||||
import_modulus = true;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
exponent_id = 2;
|
exponent_id = 2;
|
||||||
import_modulus = false;
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
exponent_id = 3;
|
exponent_id = 3;
|
||||||
import_modulus = true;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modulus import isn't implemented on < 10.0.0. */
|
/* Copy key to global. */
|
||||||
import_modulus &= (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_1000);
|
memcpy(g_imported_exponents[exponent_id], user_data, 0x100);
|
||||||
|
|
||||||
/* Import the key. */
|
|
||||||
import_rsa_exponent(exponent_id, user_data, 0x100);
|
|
||||||
if (import_modulus) {
|
|
||||||
import_rsa_modulus(exponent_id, user_data + 0x100, 0x100);
|
|
||||||
g_is_modulus_verified[exponent_id] = true;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXOSPHERE_SMC_USER_H
|
#ifndef EXOSPHERE_SMC_USER_H
|
||||||
#define EXOSPHERE_SMC_USER_H
|
#define EXOSPHERE_SMC_USER_H
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args);
|
|||||||
void set_crypt_aes_done(bool done);
|
void set_crypt_aes_done(bool done);
|
||||||
bool get_crypt_aes_done(void);
|
bool get_crypt_aes_done(void);
|
||||||
|
|
||||||
void set_exp_mod_result(uint32_t result);
|
void set_exp_mod_done(bool done);
|
||||||
uint32_t get_exp_mod_result(void);
|
bool get_exp_mod_done(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -25,10 +25,14 @@
|
|||||||
#include "masterkey.h"
|
#include "masterkey.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
|
||||||
|
static uint64_t g_tkey_expected_label_hash[4];
|
||||||
|
static unsigned int g_tkey_master_key_rev = MASTERKEY_REVISION_MAX;
|
||||||
|
static unsigned int g_tkey_type = 0;
|
||||||
|
|
||||||
/* Set the expected db prefix. */
|
/* Set the expected db prefix. */
|
||||||
void tkey_set_expected_label_hash(uint64_t *label_hash) {
|
void tkey_set_expected_label_hash(uint64_t *label_hash) {
|
||||||
for (unsigned int i = 0; i < 4; i++) {
|
for (unsigned int i = 0; i < 4; i++) {
|
||||||
g_rsa_shared_data.unwrap_titlekey.expected_label_hash[i] = label_hash[i];
|
g_tkey_expected_label_hash[i] = label_hash[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +40,7 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) {
|
|||||||
if (master_key_rev >= MASTERKEY_REVISION_MAX) {
|
if (master_key_rev >= MASTERKEY_REVISION_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
g_rsa_shared_data.unwrap_titlekey.master_key_rev = master_key_rev;
|
g_tkey_master_key_rev = master_key_rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tkey_validate_type(unsigned int type) {
|
static void tkey_validate_type(unsigned int type) {
|
||||||
@@ -47,7 +51,7 @@ static void tkey_validate_type(unsigned int type) {
|
|||||||
|
|
||||||
void tkey_set_type(unsigned int type) {
|
void tkey_set_type(unsigned int type) {
|
||||||
tkey_validate_type(type);
|
tkey_validate_type(type);
|
||||||
g_rsa_shared_data.unwrap_titlekey.type = type;
|
g_tkey_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */
|
/* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */
|
||||||
@@ -112,7 +116,7 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si
|
|||||||
uint8_t *db = message + 0x21;
|
uint8_t *db = message + 0x21;
|
||||||
|
|
||||||
/* This will be passed to smc_unwrap_rsa_oaep_wrapped_titlekey. */
|
/* This will be passed to smc_unwrap_rsa_oaep_wrapped_titlekey. */
|
||||||
uint8_t *expected_label_hash = (uint8_t *)(&g_rsa_shared_data.unwrap_titlekey.expected_label_hash[0]);
|
uint8_t *expected_label_hash = (uint8_t *)(&g_tkey_expected_label_hash[0]);
|
||||||
|
|
||||||
/* Unmask the salt. */
|
/* Unmask the salt. */
|
||||||
calculate_mgf1_and_xor(salt, 0x20, db, 0xDF);
|
calculate_mgf1_and_xor(salt, 0x20, db, 0xDF);
|
||||||
@@ -167,13 +171,13 @@ static const uint8_t titlekek_sources[TITLEKEY_TYPE_MAX+1][0x10] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
if (g_rsa_shared_data.unwrap_titlekey.master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) {
|
if (g_tkey_master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the appropriate titlekek into keyslot 9. */
|
/* Generate the appropriate titlekek into keyslot 9. */
|
||||||
unsigned int master_keyslot = mkey_get_keyslot(g_rsa_shared_data.unwrap_titlekey.master_key_rev);
|
unsigned int master_keyslot = mkey_get_keyslot(g_tkey_master_key_rev);
|
||||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_rsa_shared_data.unwrap_titlekey.type], 0x10);
|
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_tkey_type], 0x10);
|
||||||
|
|
||||||
/* Unwrap the titlekey using the titlekek. */
|
/* Unwrap the titlekey using the titlekek. */
|
||||||
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10);
|
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10);
|
||||||
|
|||||||
@@ -13,12 +13,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXOSPHERE_TITLEKEY_H
|
#ifndef EXOSPHERE_TITLEKEY_H
|
||||||
#define EXOSPHERE_TITLEKEY_H
|
#define EXOSPHERE_TITLEKEY_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "rsa_common.h"
|
|
||||||
|
|
||||||
#define TITLEKEY_TYPE_MAX 0x1
|
#define TITLEKEY_TYPE_MAX 0x1
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
@@ -65,7 +65,7 @@ void init_dma_controllers(unsigned int target_firmware) {
|
|||||||
MAKE_REG32(0x6000C038) = 0x0;
|
MAKE_REG32(0x6000C038) = 0x0;
|
||||||
|
|
||||||
/* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */
|
/* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */
|
||||||
MAKE_REG32(0x50060000) = (MAKE_REG32(0x50060000) & 0xC4FFFFFF) | 0x38000000;
|
MAKE_REG32(0x50060000) |= 0x38000000;
|
||||||
|
|
||||||
/* AHB_ARBITRATION_DISABLE_0 - Disables USB, USB2, and AHB-DMA from arbitration */
|
/* AHB_ARBITRATION_DISABLE_0 - Disables USB, USB2, and AHB-DMA from arbitration */
|
||||||
MAKE_REG32(0x6000C004) = 0x40060;
|
MAKE_REG32(0x6000C004) = 0x40060;
|
||||||
@@ -99,7 +99,7 @@ void init_dma_controllers(unsigned int target_firmware) {
|
|||||||
MAKE_REG32(0x60020038) = 0;
|
MAKE_REG32(0x60020038) = 0;
|
||||||
|
|
||||||
/* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */
|
/* MSELECT_CONFIG_0 |= WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */
|
||||||
MAKE_REG32(0x50060000) |= (MAKE_REG32(0x50060000) & 0xC4FFFFFF) | 0x38000000;
|
MAKE_REG32(0x50060000) |= 0x38000000;
|
||||||
|
|
||||||
/* AHB_ARBITRATION_PRIORITY_CTRL_0 - Select high prio group with prio 7 */
|
/* AHB_ARBITRATION_PRIORITY_CTRL_0 - Select high prio group with prio 7 */
|
||||||
MAKE_REG32(0x6000C008) = 0xE0000001;
|
MAKE_REG32(0x6000C008) = 0xE0000001;
|
||||||
@@ -111,14 +111,6 @@ void init_dma_controllers(unsigned int target_firmware) {
|
|||||||
|
|
||||||
void _set_memory_registers_enable_mmu(const uintptr_t ttbr0) {
|
void _set_memory_registers_enable_mmu(const uintptr_t ttbr0) {
|
||||||
static const uintptr_t vbar = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800;
|
static const uintptr_t vbar = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800;
|
||||||
/*
|
|
||||||
- Non-cacheable load forwarding enabled
|
|
||||||
- Disable load-pass DMB.
|
|
||||||
- NOTE: This and this alone is done via inline asm, due to register argument limits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const uint64_t cpuactlr = 0x800000001000000ull;
|
|
||||||
__asm__ __volatile__("msr s3_1_c15_c2_0, %0" :: "r"(cpuactlr) : "memory", "cc");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- Disable table walk descriptor access prefetch.
|
- Disable table walk descriptor access prefetch.
|
||||||
@@ -205,12 +197,12 @@ void warmboot_init(void) {
|
|||||||
*/
|
*/
|
||||||
flush_dcache_all();
|
flush_dcache_all();
|
||||||
invalidate_icache_all();
|
invalidate_icache_all();
|
||||||
|
|
||||||
/* On warmboot (not cpu_on) only */
|
/* On warmboot (not cpu_on) only */
|
||||||
if (VIRT_MC_SECURITY_CFG3 == 0) {
|
if (VIRT_MC_SECURITY_CFG3 == 0) {
|
||||||
init_dma_controllers(g_exosphere_target_firmware_for_init);
|
init_dma_controllers(g_exosphere_target_firmware_for_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*identity_remap_tzram();*/
|
/*identity_remap_tzram();*/
|
||||||
/* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */
|
/* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */
|
||||||
if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) {
|
if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) {
|
||||||
|
|||||||
@@ -82,9 +82,6 @@ typedef enum {
|
|||||||
FS_VER_9_1_0,
|
FS_VER_9_1_0,
|
||||||
FS_VER_9_1_0_EXFAT,
|
FS_VER_9_1_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_10_0_0,
|
|
||||||
FS_VER_10_0_0_EXFAT,
|
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
} emummc_fs_ver_t;
|
} emummc_fs_ver_t;
|
||||||
|
|
||||||
|
|||||||
@@ -417,9 +417,6 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
|
|||||||
|
|
||||||
"\xB5\xE7\xA6\x4C\x6F\x5C\x4F\xE3", /* FS_VER_9_1_0 */
|
"\xB5\xE7\xA6\x4C\x6F\x5C\x4F\xE3", /* FS_VER_9_1_0 */
|
||||||
"\xF1\x96\xD1\x44\xD0\x44\x45\xB6", /* FS_VER_9_1_0_EXFAT */
|
"\xF1\x96\xD1\x44\xD0\x44\x45\xB6", /* FS_VER_9_1_0_EXFAT */
|
||||||
|
|
||||||
"\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", /* FS_VER_10_0_0 */
|
|
||||||
"\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", /* FS_VER_10_0_0_EXFAT */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
||||||
|
|||||||
@@ -486,77 +486,20 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(900, proc_id_send)[] = {0xA9BF
|
|||||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(900, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x17, 0x2A, 0xF7, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
|
static const uint8_t MAKE_KERNEL_PATTERN_NAME(900, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x17, 0x2A, 0xF7, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||||
|
|
||||||
/*
|
|
||||||
stp x10, x11, [sp, #-0x10]!
|
|
||||||
ldr x11, [sp, #0xC0]
|
|
||||||
mov w10, w22
|
|
||||||
lsl x10, x10, #2
|
|
||||||
ldr x10, [x11, x10]
|
|
||||||
mov x9, #0x0000ffffffffffff
|
|
||||||
and x8, x10, x9
|
|
||||||
mov x9, #0xffff000000000000
|
|
||||||
and x10, x10, x9
|
|
||||||
mov x9, #0xfffe000000000000
|
|
||||||
cmp x10, x9
|
|
||||||
beq #0x20
|
|
||||||
|
|
||||||
stp x8, x9, [sp, #-0x10]!
|
|
||||||
ldr x8, [x23]
|
|
||||||
ldr x8, [x8, #0x38]
|
|
||||||
mov x0, x23
|
|
||||||
blr x8
|
|
||||||
ldp x8, x9, [sp],#0x10
|
|
||||||
mov x8, x0
|
|
||||||
|
|
||||||
ldp x10, x11, [sp],#0x10
|
|
||||||
mov x0, x8
|
|
||||||
*/
|
|
||||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1000, proc_id_send)[] = {0xE8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x17, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0x08, 0x4B, 0x36, 0x8B, 0x09, 0xFC, 0x60, 0xD3, 0x00, 0x25, 0x00, 0x29};
|
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_send)[] = {0xA9BF2FEA, 0xF94063EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
|
||||||
/*
|
|
||||||
stp x10, x11, [sp, #-0x10]!
|
|
||||||
ldr x11, [sp, #0xC8]
|
|
||||||
mov w10, w26
|
|
||||||
lsl x10, x10, #2
|
|
||||||
ldr x10, [x11, x10]
|
|
||||||
mov x9, #0x0000ffffffffffff
|
|
||||||
and x8, x10, x9
|
|
||||||
mov x9, #0xffff000000000000
|
|
||||||
and x10, x10, x9
|
|
||||||
mov x9, #0xfffe000000000000
|
|
||||||
cmp x10, x9
|
|
||||||
beq #0x20
|
|
||||||
|
|
||||||
stp x8, x9, [sp, #-0x10]!
|
|
||||||
ldr x8, [x28]
|
|
||||||
ldr x8, [x8, #0x38]
|
|
||||||
mov x0, x28
|
|
||||||
blr x8
|
|
||||||
ldp x8, x9, [sp],#0x10
|
|
||||||
mov x8, x0
|
|
||||||
|
|
||||||
ldp x10, x11, [sp],#0x10
|
|
||||||
mov x0, x8
|
|
||||||
*/
|
|
||||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1000, proc_id_recv)[] = {0x88, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1C, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x87, 0x40, 0xF9, 0x08, 0x49, 0x3A, 0x8B, 0x09, 0xFC, 0x60, 0xD3};
|
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
|
||||||
|
|
||||||
|
|
||||||
/* svcControlCodeMemory Patches */
|
/* svcControlCodeMemory Patches */
|
||||||
/* b.eq -> nop */
|
/* b.eq -> nop */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory)[] = {MAKE_NOP};
|
|
||||||
|
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, system_memory_increase)[] = {0x52A3C008}; /* MOV W8, #0x1E000000 */
|
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, system_memory_increase)[] = {0x52A3C008}; /* MOV W8, #0x1E000000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||||
|
|
||||||
/* Hook Definitions. */
|
/* Hook Definitions. */
|
||||||
static const kernel_patch_t g_kernel_patches_100[] = {
|
static const kernel_patch_t g_kernel_patches_100[] = {
|
||||||
@@ -792,35 +735,6 @@ static const kernel_patch_t g_kernel_patches_900[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const kernel_patch_t g_kernel_patches_1000[] = {
|
|
||||||
{ /* Send Message Process ID Patch. */
|
|
||||||
.pattern_size = 0x1C,
|
|
||||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1000, proc_id_send),
|
|
||||||
.pattern_hook_offset = 0x0,
|
|
||||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1000, proc_id_send))/sizeof(instruction_t),
|
|
||||||
.branch_back_offset = 0x10,
|
|
||||||
.payload = MAKE_KERNEL_PATCH_NAME(1000, proc_id_send)
|
|
||||||
},
|
|
||||||
{ /* Receive Message Process ID Patch. */
|
|
||||||
.pattern_size = 0x1C,
|
|
||||||
.pattern = MAKE_KERNEL_PATTERN_NAME(1000, proc_id_recv),
|
|
||||||
.pattern_hook_offset = 0x0,
|
|
||||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv))/sizeof(instruction_t),
|
|
||||||
.branch_back_offset = 0x10,
|
|
||||||
.payload = MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)
|
|
||||||
},
|
|
||||||
{ /* svcControlCodeMemory Patch. */
|
|
||||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory))/sizeof(instruction_t),
|
|
||||||
.payload = MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory),
|
|
||||||
.patch_offset = 0x45DAC,
|
|
||||||
},
|
|
||||||
{ /* System Memory Increase Patch. */
|
|
||||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase))/sizeof(instruction_t),
|
|
||||||
.payload = MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase),
|
|
||||||
.patch_offset = 0x66950,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
||||||
|
|
||||||
/* Kernel Infos. */
|
/* Kernel Infos. */
|
||||||
@@ -897,15 +811,6 @@ static const kernel_info_t g_kernel_infos[] = {
|
|||||||
.embedded_ini_ptr = 0x180,
|
.embedded_ini_ptr = 0x180,
|
||||||
.free_code_space_offset = 0x65780,
|
.free_code_space_offset = 0x65780,
|
||||||
KERNEL_PATCHES(900)
|
KERNEL_PATCHES(900)
|
||||||
},
|
|
||||||
{ /* 10.0.0. */
|
|
||||||
.hash = {0x59, 0x31, 0xE6, 0x46, 0xF7, 0xAA, 0x15, 0x59, 0x78, 0xC7, 0xB3, 0xA5, 0xFA, 0x80, 0xE2, 0xC0, 0xCA, 0x6F, 0x31, 0x97, 0x3D, 0x86, 0x8A, 0x69, 0xF3, 0xBF, 0xE6, 0xE5, 0x61, 0xA7, 0x1B, 0x5B, },
|
|
||||||
.hash_offset = 0x1B8,
|
|
||||||
.hash_size = 0x93000 - 0x1B8,
|
|
||||||
.embedded_ini_offset = 0x93000,
|
|
||||||
.embedded_ini_ptr = 0x178,
|
|
||||||
.free_code_space_offset = 0x67790,
|
|
||||||
KERNEL_PATCHES(1000)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -950,7 +855,7 @@ const kernel_info_t *get_kernel_info(void *kernel, size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1, uint32_t target_firmware) {
|
void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1) {
|
||||||
const kernel_info_t *kernel_info = get_kernel_info(_kernel, *kernel_size);
|
const kernel_info_t *kernel_info = get_kernel_info(_kernel, *kernel_size);
|
||||||
*out_ini1 = NULL;
|
*out_ini1 = NULL;
|
||||||
|
|
||||||
@@ -971,12 +876,6 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
|||||||
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
|
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
|
||||||
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
|
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
|
||||||
|
|
||||||
/* Set target firmware for our kernel loader. */
|
|
||||||
uint32_t *kldr_u32 = (uint32_t *)((uintptr_t)_kernel + kernel_ldr_offset);
|
|
||||||
if (kldr_u32[1] == 0x30444C4D) {
|
|
||||||
kldr_u32[2] = target_firmware;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update size. */
|
/* Update size. */
|
||||||
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
void package2_patch_kernel(void *kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1, uint32_t target_firmware);
|
void package2_patch_kernel(void *kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -160,7 +160,6 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
|||||||
desired_keyblob = MASTERKEY_REVISION_900;
|
desired_keyblob = MASTERKEY_REVISION_900;
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
case ATMOSPHERE_TARGET_FIRMWARE_910:
|
||||||
case ATMOSPHERE_TARGET_FIRMWARE_1000:
|
|
||||||
desired_keyblob = MASTERKEY_REVISION_910_CURRENT;
|
desired_keyblob = MASTERKEY_REVISION_910_CURRENT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -232,8 +232,6 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
|||||||
return ATMOSPHERE_TARGET_FIRMWARE_900;
|
return ATMOSPHERE_TARGET_FIRMWARE_900;
|
||||||
} else if (memcmp(package1loader_header->build_timestamp, "20191021", 8) == 0) {
|
} else if (memcmp(package1loader_header->build_timestamp, "20191021", 8) == 0) {
|
||||||
return ATMOSPHERE_TARGET_FIRMWARE_910;
|
return ATMOSPHERE_TARGET_FIRMWARE_910;
|
||||||
} else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) {
|
|
||||||
return ATMOSPHERE_TARGET_FIRMWARE_1000;
|
|
||||||
} else {
|
} else {
|
||||||
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Perform any patches we want to the NX kernel. */
|
/* Perform any patches we want to the NX kernel. */
|
||||||
package2_patch_kernel(kernel, &kernel_size, is_sd_kernel, (void *)&orig_ini1, target_firmware);
|
package2_patch_kernel(kernel, &kernel_size, is_sd_kernel, (void *)&orig_ini1);
|
||||||
|
|
||||||
/* Ensure we know where embedded INI is if present, and we don't if not. */
|
/* Ensure we know where embedded INI is if present, and we don't if not. */
|
||||||
if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) ||
|
if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) ||
|
||||||
@@ -232,7 +232,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
|
|||||||
|
|
||||||
/* Perform version checks. */
|
/* Perform version checks. */
|
||||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1000_CURRENT) {
|
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_910_CURRENT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,7 @@
|
|||||||
#define PACKAGE2_MAXVER_700_800 0xA
|
#define PACKAGE2_MAXVER_700_800 0xA
|
||||||
#define PACKAGE2_MAXVER_810 0xB
|
#define PACKAGE2_MAXVER_810 0xB
|
||||||
#define PACKAGE2_MAXVER_900 0xC
|
#define PACKAGE2_MAXVER_900 0xC
|
||||||
#define PACKAGE2_MAXVER_910_920 0xD
|
#define PACKAGE2_MAXVER_910_CURRENT 0xD
|
||||||
#define PACKAGE2_MAXVER_1000_CURRENT 0xE
|
|
||||||
|
|
||||||
#define PACKAGE2_MINVER_100 0x3
|
#define PACKAGE2_MINVER_100 0x3
|
||||||
#define PACKAGE2_MINVER_200 0x4
|
#define PACKAGE2_MINVER_200 0x4
|
||||||
@@ -53,8 +52,7 @@
|
|||||||
#define PACKAGE2_MINVER_700_800 0xB
|
#define PACKAGE2_MINVER_700_800 0xB
|
||||||
#define PACKAGE2_MINVER_810 0xC
|
#define PACKAGE2_MINVER_810 0xC
|
||||||
#define PACKAGE2_MINVER_900 0xD
|
#define PACKAGE2_MINVER_900 0xD
|
||||||
#define PACKAGE2_MINVER_910_920 0xE
|
#define PACKAGE2_MINVER_910_CURRENT 0xE
|
||||||
#define PACKAGE2_MINVER_1000_CURRENT 0xF
|
|
||||||
|
|
||||||
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
||||||
|
|
||||||
|
|||||||
@@ -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 = 96825c7524c333536dcffadb76341bf599785538
|
commit = a40d4593d7e46ea296802e5c50fd0da2d9f92a76
|
||||||
parent = d81a3bdc36ddf3d7b4f3d7fae5cb85afc047b546
|
parent = 6de1361c8be886eda16faf87c73b9e4d01187bca
|
||||||
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+crc+crypto -mtp=soft
|
export ATMOSPHERE_SETTINGS += -march=armv8-a -mtp=soft
|
||||||
export ATMOSPHERE_CFLAGS +=
|
export ATMOSPHERE_CFLAGS +=
|
||||||
export ATMOSPHERE_CXXFLAGS +=
|
export ATMOSPHERE_CXXFLAGS +=
|
||||||
export ATMOSPHERE_ASFLAGS +=
|
export ATMOSPHERE_ASFLAGS +=
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ 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
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <mesosphere/kern_k_typed_address.hpp>
|
#include <mesosphere/kern_k_typed_address.hpp>
|
||||||
#include <mesosphere/kern_select_cpu.hpp>
|
#include <mesosphere/kern_select_cpu.hpp>
|
||||||
#include <mesosphere/arch/arm64/kern_k_page_table_entry.hpp>
|
#include <mesosphere/arch/arm64/kern_k_page_table_entry.hpp>
|
||||||
#include <mesosphere/kern_select_system_control.hpp>
|
|
||||||
|
|
||||||
namespace ams::kern::arch::arm64::init {
|
namespace ams::kern::arch::arm64::init {
|
||||||
|
|
||||||
@@ -65,220 +64,6 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
/* The MMU is necessarily not yet turned on, if we are creating an initial page table. */
|
/* The MMU is necessarily not yet turned on, if we are creating an initial page table. */
|
||||||
std::memset(reinterpret_cast<void *>(GetInteger(address)), 0, PageSize);
|
std::memset(reinterpret_cast<void *>(GetInteger(address)), 0, PageSize);
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
size_t NOINLINE GetBlockCount(KVirtualAddress virt_addr, size_t size, size_t block_size) {
|
|
||||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
|
||||||
size_t count = 0;
|
|
||||||
while (virt_addr < end_virt_addr) {
|
|
||||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
|
||||||
|
|
||||||
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
|
|
||||||
if (l1_entry->IsBlock() || l1_entry->IsEmpty()) {
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= L1BlockSize);
|
|
||||||
virt_addr += L1BlockSize;
|
|
||||||
if (l1_entry->IsBlock() && block_size == L1BlockSize) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non empty and non-block must be table. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L2. */
|
|
||||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
|
||||||
|
|
||||||
if (l2_entry->IsBlock() || l2_entry->IsEmpty()) {
|
|
||||||
const size_t advance_size = (l2_entry->IsBlock() && l2_entry->IsContiguous()) ? L2ContiguousBlockSize : L2BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
|
|
||||||
virt_addr += advance_size;
|
|
||||||
if (l2_entry->IsBlock() && block_size == advance_size) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non empty and non-block must be table. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L3. */
|
|
||||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
|
||||||
|
|
||||||
/* L3 must be block or empty. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsBlock() || l3_entry->IsEmpty());
|
|
||||||
|
|
||||||
const size_t advance_size = (l3_entry->IsBlock() && l3_entry->IsContiguous()) ? L3ContiguousBlockSize : L3BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
|
|
||||||
virt_addr += advance_size;
|
|
||||||
if (l3_entry->IsBlock() && block_size == advance_size) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
KVirtualAddress NOINLINE GetBlockByIndex(KVirtualAddress virt_addr, size_t size, size_t block_size, size_t index) {
|
|
||||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
|
||||||
size_t count = 0;
|
|
||||||
while (virt_addr < end_virt_addr) {
|
|
||||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
|
||||||
|
|
||||||
/* If an L1 block is mapped or we're empty, advance by L1BlockSize. */
|
|
||||||
if (l1_entry->IsBlock() || l1_entry->IsEmpty()) {
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= L1BlockSize);
|
|
||||||
if (l1_entry->IsBlock() && block_size == L1BlockSize) {
|
|
||||||
if ((count++) == index) {
|
|
||||||
return virt_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virt_addr += L1BlockSize;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non empty and non-block must be table. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L2. */
|
|
||||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
|
||||||
|
|
||||||
if (l2_entry->IsBlock() || l2_entry->IsEmpty()) {
|
|
||||||
const size_t advance_size = (l2_entry->IsBlock() && l2_entry->IsContiguous()) ? L2ContiguousBlockSize : L2BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
|
|
||||||
if (l2_entry->IsBlock() && block_size == advance_size) {
|
|
||||||
if ((count++) == index) {
|
|
||||||
return virt_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virt_addr += advance_size;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non empty and non-block must be table. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L3. */
|
|
||||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
|
||||||
|
|
||||||
/* L3 must be block or empty. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsBlock() || l3_entry->IsEmpty());
|
|
||||||
|
|
||||||
const size_t advance_size = (l3_entry->IsBlock() && l3_entry->IsContiguous()) ? L3ContiguousBlockSize : L3BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), advance_size));
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(static_cast<size_t>(end_virt_addr - virt_addr) >= advance_size);
|
|
||||||
if (l3_entry->IsBlock() && block_size == advance_size) {
|
|
||||||
if ((count++) == index) {
|
|
||||||
return virt_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virt_addr += advance_size;
|
|
||||||
}
|
|
||||||
return Null<KVirtualAddress>;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTableEntry *GetMappingEntry(KVirtualAddress virt_addr, size_t block_size) {
|
|
||||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
|
||||||
|
|
||||||
if (l1_entry->IsBlock()) {
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(block_size == L1BlockSize);
|
|
||||||
return l1_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L2. */
|
|
||||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
|
||||||
|
|
||||||
if (l2_entry->IsBlock()) {
|
|
||||||
const size_t real_size = (l2_entry->IsContiguous()) ? L2ContiguousBlockSize : L2BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(real_size == block_size);
|
|
||||||
return l2_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsTable());
|
|
||||||
|
|
||||||
/* Table, so check if we're mapped in L3. */
|
|
||||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
|
||||||
|
|
||||||
/* L3 must be block. */
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsBlock());
|
|
||||||
|
|
||||||
const size_t real_size = (l3_entry->IsContiguous()) ? L3ContiguousBlockSize : L3BlockSize;
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(real_size == block_size);
|
|
||||||
return l3_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NOINLINE SwapBlocks(KVirtualAddress src_virt_addr, KVirtualAddress dst_virt_addr, size_t block_size, bool do_copy) {
|
|
||||||
static_assert(L2ContiguousBlockSize / L2BlockSize == L3ContiguousBlockSize / L3BlockSize);
|
|
||||||
const bool contig = (block_size == L2ContiguousBlockSize || block_size == L3ContiguousBlockSize);
|
|
||||||
const size_t num_mappings = contig ? L2ContiguousBlockSize / L2BlockSize : 1;
|
|
||||||
|
|
||||||
/* Unmap the source. */
|
|
||||||
PageTableEntry *src_entry = this->GetMappingEntry(src_virt_addr, block_size);
|
|
||||||
const auto src_saved = *src_entry;
|
|
||||||
for (size_t i = 0; i < num_mappings; i++) {
|
|
||||||
*src_entry = InvalidPageTableEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmap the target. */
|
|
||||||
PageTableEntry *dst_entry = this->GetMappingEntry(dst_virt_addr, block_size);
|
|
||||||
const auto dst_saved = *dst_entry;
|
|
||||||
for (size_t i = 0; i < num_mappings; i++) {
|
|
||||||
*dst_entry = InvalidPageTableEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invalidate the entire tlb. */
|
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
|
||||||
cpu::InvalidateEntireTlb();
|
|
||||||
|
|
||||||
/* Copy data, if we should. */
|
|
||||||
const u64 negative_block_size_for_mask = static_cast<u64>(-static_cast<s64>(block_size));
|
|
||||||
const u64 offset_mask = negative_block_size_for_mask & ((1ul << 36) - 1);
|
|
||||||
const KVirtualAddress copy_src_addr = KVirtualAddress(src_saved.GetRawAttributesUnsafeForSwap() & offset_mask);
|
|
||||||
const KVirtualAddress copy_dst_addr = KVirtualAddress(dst_saved.GetRawAttributesUnsafeForSwap() & offset_mask);
|
|
||||||
if (block_size && do_copy) {
|
|
||||||
u8 tmp[0x100];
|
|
||||||
for (size_t ofs = 0; ofs < block_size; ofs += sizeof(tmp)) {
|
|
||||||
std::memcpy(tmp, GetVoidPointer(copy_src_addr + ofs), sizeof(tmp));
|
|
||||||
std::memcpy(GetVoidPointer(copy_src_addr + ofs), GetVoidPointer(copy_dst_addr + ofs), sizeof(tmp));
|
|
||||||
std::memcpy(GetVoidPointer(copy_dst_addr + ofs), tmp, sizeof(tmp));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Swap the mappings. */
|
|
||||||
const u64 attr_preserve_mask = (negative_block_size_for_mask | 0xFFFF000000000000ul) ^ ((1ul << 36) - 1);
|
|
||||||
const size_t shift_for_contig = contig ? 4 : 0;
|
|
||||||
size_t advanced_size = 0;
|
|
||||||
const u64 src_attr_val = src_saved.GetRawAttributesUnsafeForSwap() & attr_preserve_mask;
|
|
||||||
const u64 dst_attr_val = dst_saved.GetRawAttributesUnsafeForSwap() & attr_preserve_mask;
|
|
||||||
for (size_t i = 0; i < num_mappings; i++) {
|
|
||||||
reinterpret_cast<u64 *>(src_entry)[i] = GetInteger(copy_dst_addr + (advanced_size >> shift_for_contig)) | src_attr_val;
|
|
||||||
reinterpret_cast<u64 *>(dst_entry)[i] = GetInteger(copy_src_addr + (advanced_size >> shift_for_contig)) | dst_attr_val;
|
|
||||||
advanced_size += block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NOINLINE PhysicallyRandomize(KVirtualAddress virt_addr, size_t size, size_t block_size, bool do_copy) {
|
|
||||||
const size_t block_count = this->GetBlockCount(virt_addr, size, block_size);
|
|
||||||
if (block_count > 1) {
|
|
||||||
for (size_t cur_block = 0; cur_block < block_count; cur_block++) {
|
|
||||||
const size_t target_block = KSystemControl::Init::GenerateRandomRange(cur_block, block_count - 1);
|
|
||||||
if (cur_block != target_block) {
|
|
||||||
const KVirtualAddress cur_virt_addr = this->GetBlockByIndex(virt_addr, size, block_size, cur_block);
|
|
||||||
const KVirtualAddress target_virt_addr = this->GetBlockByIndex(virt_addr, size, block_size, target_block);
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(cur_virt_addr != Null<KVirtualAddress>);
|
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(target_virt_addr != Null<KVirtualAddress>);
|
|
||||||
this->SwapBlocks(cur_virt_addr, target_virt_addr, block_size, do_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
void NOINLINE Map(KVirtualAddress virt_addr, size_t size, KPhysicalAddress phys_addr, const PageTableEntry &attr, IPageAllocator &allocator) {
|
void NOINLINE Map(KVirtualAddress virt_addr, size_t size, KPhysicalAddress phys_addr, const PageTableEntry &attr, IPageAllocator &allocator) {
|
||||||
/* Ensure that addresses and sizes are page aligned. */
|
/* Ensure that addresses and sizes are page aligned. */
|
||||||
@@ -578,62 +363,32 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicallyRandomize(KVirtualAddress virt_addr, size_t size, bool do_copy) {
|
|
||||||
this->PhysicallyRandomize(virt_addr, size, L1BlockSize, do_copy);
|
|
||||||
this->PhysicallyRandomize(virt_addr, size, L2ContiguousBlockSize, do_copy);
|
|
||||||
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
|
||||||
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
|
||||||
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class KInitialPageAllocator : public KInitialPageTable::IPageAllocator {
|
class KInitialPageAllocator : public KInitialPageTable::IPageAllocator {
|
||||||
public:
|
|
||||||
struct State {
|
|
||||||
uintptr_t next_address;
|
|
||||||
uintptr_t free_bitmap;
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
State state;
|
uintptr_t next_address;
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE KInitialPageAllocator() : state{} { /* ... */ }
|
constexpr ALWAYS_INLINE KInitialPageAllocator() : next_address(Null<uintptr_t>) { /* ... */ }
|
||||||
|
|
||||||
ALWAYS_INLINE void Initialize(uintptr_t address) {
|
ALWAYS_INLINE void Initialize(uintptr_t address) {
|
||||||
this->state.next_address = address + BITSIZEOF(this->state.free_bitmap) * PageSize;
|
this->next_address = address;
|
||||||
this->state.free_bitmap = ~uintptr_t();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) {
|
ALWAYS_INLINE uintptr_t GetFinalNextAddress() {
|
||||||
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) {
|
const uintptr_t final_address = this->next_address;
|
||||||
this->state = *reinterpret_cast<State *>(state_val);
|
this->next_address = Null<uintptr_t>;
|
||||||
} else {
|
return final_address;
|
||||||
this->state.next_address = state_val;
|
|
||||||
this->state.free_bitmap = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void GetFinalState(State *out) {
|
ALWAYS_INLINE uintptr_t GetFinalState() {
|
||||||
*out = this->state;
|
return this->GetFinalNextAddress();
|
||||||
this->state = {};
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
virtual KPhysicalAddress Allocate() override {
|
virtual KPhysicalAddress Allocate() override {
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(this->state.next_address != Null<uintptr_t>);
|
MESOSPHERE_INIT_ABORT_UNLESS(this->next_address != Null<uintptr_t>);
|
||||||
uintptr_t allocated = this->state.next_address;
|
const uintptr_t allocated = this->next_address;
|
||||||
if (this->state.free_bitmap != 0) {
|
this->next_address += PageSize;
|
||||||
u64 index;
|
|
||||||
uintptr_t mask;
|
|
||||||
do {
|
|
||||||
index = KSystemControl::Init::GenerateRandomRange(0, BITSIZEOF(this->state.free_bitmap) - 1);
|
|
||||||
mask = (static_cast<uintptr_t>(1) << index);
|
|
||||||
} while ((this->state.free_bitmap & mask) == 0);
|
|
||||||
this->state.free_bitmap &= ~mask;
|
|
||||||
allocated = this->state.next_address - ((BITSIZEOF(this->state.free_bitmap) - index) * PageSize);
|
|
||||||
} else {
|
|
||||||
this->state.next_address += PageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memset(reinterpret_cast<void *>(allocated), 0, PageSize);
|
std::memset(reinterpret_cast<void *>(allocated), 0, PageSize);
|
||||||
return allocated;
|
return allocated;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,12 +31,6 @@ namespace ams::kern::arch::arm64 {
|
|||||||
public:
|
public:
|
||||||
struct InvalidTag{};
|
struct InvalidTag{};
|
||||||
|
|
||||||
enum ExtensionTag : u64 {
|
|
||||||
ExtensionTag_IsValidBit = (1ul << 56),
|
|
||||||
ExtensionTag_IsValid = (ExtensionTag_IsValidBit | (1ul << 0)),
|
|
||||||
ExtensionTag_IsBlockMask = (ExtensionTag_IsValidBit | (1ul << 1)),
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Permission : u64 {
|
enum Permission : u64 {
|
||||||
Permission_KernelRWX = ((0ul << 53) | (1ul << 54) | (0ul << 6)),
|
Permission_KernelRWX = ((0ul << 53) | (1ul << 54) | (0ul << 6)),
|
||||||
Permission_KernelRX = ((0ul << 53) | (1ul << 54) | (2ul << 6)),
|
Permission_KernelRX = ((0ul << 53) | (1ul << 54) | (2ul << 6)),
|
||||||
@@ -95,7 +89,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
|
|
||||||
/* Construct a new attribute. */
|
/* Construct a new attribute. */
|
||||||
constexpr ALWAYS_INLINE PageTableEntry(Permission perm, PageAttribute p_a, Shareable share)
|
constexpr ALWAYS_INLINE PageTableEntry(Permission perm, PageAttribute p_a, Shareable share)
|
||||||
: attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share) | static_cast<u64>(ExtensionTag_IsValid))
|
: attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share))
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -140,9 +134,8 @@ namespace ams::kern::arch::arm64 {
|
|||||||
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (this->attributes & ExtensionTag_IsBlockMask) == ExtensionTag_IsValidBit; }
|
constexpr ALWAYS_INLINE bool IsBlock() const { return this->GetBits(0, 2) == 0x1; }
|
||||||
constexpr ALWAYS_INLINE bool IsTable() const { return this->GetBits(0, 2) == 0x3; }
|
constexpr ALWAYS_INLINE bool IsTable() const { return this->GetBits(0, 2) == 0x3; }
|
||||||
constexpr ALWAYS_INLINE bool IsEmpty() const { return this->GetBits(0, 2) == 0x0; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetContiguousAllowed(bool en) { this->SetBit(55, !en); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetContiguousAllowed(bool en) { this->SetBit(55, !en); return *this; }
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
||||||
@@ -164,10 +157,6 @@ namespace ams::kern::arch::arm64 {
|
|||||||
return this->attributes == attr;
|
return this->attributes == attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
|
||||||
return this->attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
||||||
return this->attributes;
|
return this->attributes;
|
||||||
@@ -197,7 +186,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE L1PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr ALWAYS_INLINE L1PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionTag_IsValid)
|
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x1)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -242,7 +231,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE L2PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr ALWAYS_INLINE L2PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionTag_IsValid)
|
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x1)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -275,12 +264,12 @@ namespace ams::kern::arch::arm64 {
|
|||||||
constexpr ALWAYS_INLINE L3PageTableEntry(InvalidTag) : PageTableEntry(InvalidTag{}) { /* ... */ }
|
constexpr ALWAYS_INLINE L3PageTableEntry(InvalidTag) : PageTableEntry(InvalidTag{}) { /* ... */ }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE L3PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr ALWAYS_INLINE L3PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x2 | PageTableEntry::ExtensionTag_IsValid)
|
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x3)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (GetRawAttributes() & ExtensionTag_IsBlockMask) == ExtensionTag_IsBlockMask; }
|
constexpr ALWAYS_INLINE bool IsBlock() const { return this->GetBits(0, 2) == 0x3; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE KPhysicalAddress GetBlock() const {
|
constexpr ALWAYS_INLINE KPhysicalAddress GetBlock() const {
|
||||||
return this->SelectBits(12, 36);
|
return this->SelectBits(12, 36);
|
||||||
|
|||||||
@@ -20,24 +20,6 @@ namespace ams::kern {
|
|||||||
|
|
||||||
constexpr size_t PageSize = 4_KB;
|
constexpr size_t PageSize = 4_KB;
|
||||||
|
|
||||||
enum TargetFirmware : u32 {
|
|
||||||
TargetFirmware_1_0_0 = ATMOSPHERE_TARGET_FIRMWARE_100,
|
|
||||||
TargetFirmware_2_0_0 = ATMOSPHERE_TARGET_FIRMWARE_200,
|
|
||||||
TargetFirmware_3_0_0 = ATMOSPHERE_TARGET_FIRMWARE_300,
|
|
||||||
TargetFirmware_4_0_0 = ATMOSPHERE_TARGET_FIRMWARE_400,
|
|
||||||
TargetFirmware_5_0_0 = ATMOSPHERE_TARGET_FIRMWARE_500,
|
|
||||||
TargetFirmware_6_0_0 = ATMOSPHERE_TARGET_FIRMWARE_600,
|
|
||||||
TargetFirmware_6_2_0 = ATMOSPHERE_TARGET_FIRMWARE_620,
|
|
||||||
TargetFirmware_7_0_0 = ATMOSPHERE_TARGET_FIRMWARE_700,
|
|
||||||
TargetFirmware_8_0_0 = ATMOSPHERE_TARGET_FIRMWARE_800,
|
|
||||||
TargetFirmware_8_1_0 = ATMOSPHERE_TARGET_FIRMWARE_810,
|
|
||||||
TargetFirmware_9_0_0 = ATMOSPHERE_TARGET_FIRMWARE_900,
|
|
||||||
TargetFirmware_9_1_0 = ATMOSPHERE_TARGET_FIRMWARE_910,
|
|
||||||
TargetFirmware_10_0_0 = ATMOSPHERE_TARGET_FIRMWARE_1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
TargetFirmware GetTargetFirmware();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1 || defined(AMS_BUILD_FOR_AUDITING)
|
#if 1 || defined(AMS_BUILD_FOR_AUDITING)
|
||||||
|
|||||||
@@ -20,50 +20,46 @@
|
|||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
/* Libstratosphere-only utility. */
|
/* Libstratosphere-only utility. */
|
||||||
#include <stratosphere/util.hpp>
|
#include "stratosphere/util.hpp"
|
||||||
|
|
||||||
/* Sadly required shims. */
|
/* Sadly required shims. */
|
||||||
#include <stratosphere/svc/svc_stratosphere_shims.hpp>
|
#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>
|
#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/erpt.hpp>
|
#include "stratosphere/fatal.hpp"
|
||||||
#include <stratosphere/fatal.hpp>
|
#include "stratosphere/hid.hpp"
|
||||||
#include <stratosphere/hid.hpp>
|
#include "stratosphere/hos.hpp"
|
||||||
#include <stratosphere/hos.hpp>
|
#include "stratosphere/kvdb.hpp"
|
||||||
#include <stratosphere/kvdb.hpp>
|
#include "stratosphere/ldr.hpp"
|
||||||
#include <stratosphere/ldr.hpp>
|
#include "stratosphere/lr.hpp"
|
||||||
#include <stratosphere/lr.hpp>
|
#include "stratosphere/map.hpp"
|
||||||
#include <stratosphere/map.hpp>
|
#include "stratosphere/ncm.hpp"
|
||||||
#include <stratosphere/ncm.hpp>
|
#include "stratosphere/nim.hpp"
|
||||||
#include <stratosphere/nim.hpp>
|
#include "stratosphere/patcher.hpp"
|
||||||
#include <stratosphere/patcher.hpp>
|
#include "stratosphere/pm.hpp"
|
||||||
#include <stratosphere/pgl.hpp>
|
#include "stratosphere/reg.hpp"
|
||||||
#include <stratosphere/psc.hpp>
|
#include "stratosphere/ro.hpp"
|
||||||
#include <stratosphere/pm.hpp>
|
#include "stratosphere/settings.hpp"
|
||||||
#include <stratosphere/reg.hpp>
|
#include "stratosphere/sf.hpp"
|
||||||
#include <stratosphere/ro.hpp>
|
#include "stratosphere/sm.hpp"
|
||||||
#include <stratosphere/settings.hpp>
|
#include "stratosphere/spl.hpp"
|
||||||
#include <stratosphere/sf.hpp>
|
#include "stratosphere/updater.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"
|
||||||
@@ -35,7 +35,6 @@ namespace ams::exosphere {
|
|||||||
AMS_DEFINE_TARGET_FIRMWARE_ENUM(810),
|
AMS_DEFINE_TARGET_FIRMWARE_ENUM(810),
|
||||||
AMS_DEFINE_TARGET_FIRMWARE_ENUM(900),
|
AMS_DEFINE_TARGET_FIRMWARE_ENUM(900),
|
||||||
AMS_DEFINE_TARGET_FIRMWARE_ENUM(910),
|
AMS_DEFINE_TARGET_FIRMWARE_ENUM(910),
|
||||||
AMS_DEFINE_TARGET_FIRMWARE_ENUM(1000),
|
|
||||||
};
|
};
|
||||||
#undef AMS_DEFINE_TARGET_FIRMWARE_ENUM
|
#undef AMS_DEFINE_TARGET_FIRMWARE_ENUM
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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>
|
|
||||||
@@ -1,780 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ) \
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_3_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(ClearInitialLaunchSettingsCompletionTime, hos::Version_3_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(UpdatePowerOnTime, hos::Version_3_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(UpdateAwakeTime, hos::Version_3_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(SubmitMultipleCategoryContext, hos::Version_5_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(UpdateApplicationLaunchTime, hos::Version_6_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(ClearApplicationLaunchTime, hos::Version_6_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(SubmitAttachment, hos::Version_8_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(CreateReportWithAttachments, hos::Version_8_0_0),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_4_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(DeleteReport, hos::Version_5_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(GetStorageUsageStatistics, hos::Version_5_0_0),
|
|
||||||
MAKE_SERVICE_COMMAND_META(GetAttachmentList, hos::Version_8_0_0),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_8_0_0),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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,20 +324,28 @@ namespace ams::fatal {
|
|||||||
bool is_creport;
|
bool is_creport;
|
||||||
CpuContext cpu_ctx;
|
CpuContext cpu_ctx;
|
||||||
bool generate_error_report;
|
bool generate_error_report;
|
||||||
os::Event *erpt_event;
|
Event erpt_event;
|
||||||
os::Event *battery_event;
|
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];
|
||||||
|
|
||||||
ThrowContext(os::Event *erpt, os::Event *bat)
|
void ClearState() {
|
||||||
: result(ResultSuccess()), program_id(), proc_name(), is_creport(), cpu_ctx(), generate_error_report(),
|
this->result = ResultSuccess();
|
||||||
erpt_event(erpt), battery_event(bat),
|
this->program_id = ncm::ProgramId::Invalid;
|
||||||
stack_dump_size(), stack_dump_base(), stack_dump(), tls_address(), tls_dump()
|
std::memset(this->proc_name, 0, sizeof(this->proc_name));
|
||||||
{
|
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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,17 +19,9 @@
|
|||||||
|
|
||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
struct CodeInfo {
|
Result MountCode(const char *name, const char *path, ncm::ProgramId program_id);
|
||||||
u8 signature[crypto::Rsa2048PssSha256Verifier::SignatureSize];
|
|
||||||
u8 hash[crypto::Rsa2048PssSha256Verifier::HashSize];
|
|
||||||
bool is_signed;
|
|
||||||
u8 reserved[3];
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CodeInfo) == crypto::Rsa2048PssSha256Verifier::SignatureSize + crypto::Rsa2048PssSha256Verifier::HashSize + 4);
|
|
||||||
|
|
||||||
Result MountCode(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id);
|
Result MountCodeForAtmosphereWithRedirection(const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific);
|
||||||
|
Result MountCodeForAtmosphere(const char *name, const char *path, ncm::ProgramId program_id);
|
||||||
Result MountCodeForAtmosphereWithRedirection(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific);
|
|
||||||
Result MountCodeForAtmosphere(CodeInfo *out, const char *name, const char *path, ncm::ProgramId program_id);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,11 +115,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindOpen(FindIndex *out) const {
|
Result 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) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace ams::fs {
|
|||||||
s64 size;
|
s64 size;
|
||||||
os::Mutex mutex;
|
os::Mutex mutex;
|
||||||
public:
|
public:
|
||||||
constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex(false) { /* ... */ }
|
constexpr explicit FileHandleStorage(FileHandle handle, bool close_file) : handle(handle), close_file(close_file), size(InvalidSize), mutex() { /* ... */ }
|
||||||
constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ }
|
constexpr explicit FileHandleStorage(FileHandle handle) : FileHandleStorage(handle, false) { /* ... */ }
|
||||||
|
|
||||||
virtual ~FileHandleStorage() override {
|
virtual ~FileHandleStorage() override {
|
||||||
|
|||||||
@@ -20,9 +20,9 @@
|
|||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
struct QueryRangeInfo {
|
struct QueryRangeInfo {
|
||||||
s32 aes_ctr_key_type;
|
u32 aes_ctr_key_type;
|
||||||
s32 speed_emulation_type;
|
u32 speed_emulation_type;
|
||||||
u8 reserved[0x38];
|
u32 reserved[0x38 / sizeof(u32)];
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
this->aes_ctr_key_type = 0;
|
this->aes_ctr_key_type = 0;
|
||||||
@@ -45,8 +45,4 @@ 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::ResultInvalidOpenMode());
|
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidArgument());
|
||||||
|
|
||||||
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,26 +19,12 @@
|
|||||||
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,9 +26,4 @@ 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,6 +20,4 @@ namespace ams::fs {
|
|||||||
|
|
||||||
Result MountSdCard(const char *name);
|
Result MountSdCard(const char *name);
|
||||||
|
|
||||||
Result MountSdCardErrorReportDirectoryForAtmosphere(const char *name);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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::ResultInvalidOpenMode());
|
R_UNLESS((mode & OpenMode_ReadWrite) != 0, fs::ResultInvalidArgument());
|
||||||
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidOpenMode());
|
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidArgument());
|
||||||
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::ResultInvalidOpenMode());
|
R_UNLESS((mode & OpenDirectoryMode_All) != 0, fs::ResultInvalidArgument());
|
||||||
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidOpenMode());
|
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidArgument());
|
||||||
return this->OpenDirectoryImpl(out_dir, path, mode);
|
return this->OpenDirectoryImpl(out_dir, path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace ams::fssrv::impl {
|
|||||||
MAKE_SERVICE_COMMAND_META(GetSize),
|
MAKE_SERVICE_COMMAND_META(GetSize),
|
||||||
|
|
||||||
/* 4.0.0- */
|
/* 4.0.0- */
|
||||||
MAKE_SERVICE_COMMAND_META(OperateRange, hos::Version_4_0_0),
|
MAKE_SERVICE_COMMAND_META(OperateRange, hos::Version_400),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,11 +181,11 @@ namespace ams::fssrv::impl {
|
|||||||
MAKE_SERVICE_COMMAND_META(GetTotalSpaceSize),
|
MAKE_SERVICE_COMMAND_META(GetTotalSpaceSize),
|
||||||
|
|
||||||
/* 3.0.0- */
|
/* 3.0.0- */
|
||||||
MAKE_SERVICE_COMMAND_META(CleanDirectoryRecursively, hos::Version_3_0_0),
|
MAKE_SERVICE_COMMAND_META(CleanDirectoryRecursively, hos::Version_300),
|
||||||
MAKE_SERVICE_COMMAND_META(GetFileTimeStampRaw, hos::Version_3_0_0),
|
MAKE_SERVICE_COMMAND_META(GetFileTimeStampRaw, hos::Version_300),
|
||||||
|
|
||||||
/* 4.0.0- */
|
/* 4.0.0- */
|
||||||
MAKE_SERVICE_COMMAND_META(QueryEntry, hos::Version_4_0_0),
|
MAKE_SERVICE_COMMAND_META(QueryEntry, hos::Version_400),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace ams::fssrv::impl {
|
|||||||
MAKE_SERVICE_COMMAND_META(GetSize),
|
MAKE_SERVICE_COMMAND_META(GetSize),
|
||||||
|
|
||||||
/* 4.0.0- */
|
/* 4.0.0- */
|
||||||
MAKE_SERVICE_COMMAND_META(OperateRange, hos::Version_4_0_0),
|
MAKE_SERVICE_COMMAND_META(OperateRange, hos::Version_400),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,19 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere/fssystem/fssystem_utility.hpp>
|
#include "fssystem/fssystem_utility.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_external_code.hpp>
|
#include "fssystem/fssystem_external_code.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_acid_sign_key.hpp>
|
#include "fssystem/fssystem_partition_file_system.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_partition_file_system.hpp>
|
#include "fssystem/fssystem_partition_file_system_meta.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_partition_file_system_meta.hpp>
|
#include "fssystem/fssystem_path_tool.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_path_tool.hpp>
|
#include "fssystem/fssystem_subdirectory_filesystem.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_thread_priority_changer.hpp>
|
#include "fssystem/fssystem_directory_redirection_filesystem.hpp"
|
||||||
#include <stratosphere/fssystem/fssystem_aes_ctr_storage.hpp>
|
#include "fssystem/fssystem_directory_savedata_filesystem.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>
|
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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::fssystem {
|
|
||||||
|
|
||||||
constexpr inline size_t AcidSignatureKeyGenerationMax = 1;
|
|
||||||
|
|
||||||
constexpr inline size_t AcidSignatureKeyModulusSize = 0x100;
|
|
||||||
|
|
||||||
constexpr inline const u8 AcidSignatureKeyModulusDev[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
|
|
||||||
{
|
|
||||||
0xD6, 0x34, 0xA5, 0x78, 0x6C, 0x68, 0xCE, 0x5A, 0xC2, 0x37, 0x17, 0xF3, 0x82, 0x45, 0xC6, 0x89,
|
|
||||||
0xE1, 0x2D, 0x06, 0x67, 0xBF, 0xB4, 0x06, 0x19, 0x55, 0x6B, 0x27, 0x66, 0x0C, 0xA4, 0xB5, 0x87,
|
|
||||||
0x81, 0x25, 0xF4, 0x30, 0xBC, 0x53, 0x08, 0x68, 0xA2, 0x48, 0x49, 0x8C, 0x3F, 0x38, 0x40, 0x9C,
|
|
||||||
0xC4, 0x26, 0xF4, 0x79, 0xE2, 0xA1, 0x85, 0xF5, 0x5C, 0x7F, 0x58, 0xBA, 0xA6, 0x1C, 0xA0, 0x8B,
|
|
||||||
0x84, 0x16, 0x14, 0x6F, 0x85, 0xD9, 0x7C, 0xE1, 0x3C, 0x67, 0x22, 0x1E, 0xFB, 0xD8, 0xA7, 0xA5,
|
|
||||||
0x9A, 0xBF, 0xEC, 0x0E, 0xCF, 0x96, 0x7E, 0x85, 0xC2, 0x1D, 0x49, 0x5D, 0x54, 0x26, 0xCB, 0x32,
|
|
||||||
0x7C, 0xF6, 0xBB, 0x58, 0x03, 0x80, 0x2B, 0x5D, 0xF7, 0xFB, 0xD1, 0x9D, 0xC7, 0xC6, 0x2E, 0x53,
|
|
||||||
0xC0, 0x6F, 0x39, 0x2C, 0x1F, 0xA9, 0x92, 0xF2, 0x4D, 0x7D, 0x4E, 0x74, 0xFF, 0xE4, 0xEF, 0xE4,
|
|
||||||
0x7C, 0x3D, 0x34, 0x2A, 0x71, 0xA4, 0x97, 0x59, 0xFF, 0x4F, 0xA2, 0xF4, 0x66, 0x78, 0xD8, 0xBA,
|
|
||||||
0x99, 0xE3, 0xE6, 0xDB, 0x54, 0xB9, 0xE9, 0x54, 0xA1, 0x70, 0xFC, 0x05, 0x1F, 0x11, 0x67, 0x4B,
|
|
||||||
0x26, 0x8C, 0x0C, 0x3E, 0x03, 0xD2, 0xA3, 0x55, 0x5C, 0x7D, 0xC0, 0x5D, 0x9D, 0xFF, 0x13, 0x2F,
|
|
||||||
0xFD, 0x19, 0xBF, 0xED, 0x44, 0xC3, 0x8C, 0xA7, 0x28, 0xCB, 0xE5, 0xE0, 0xB1, 0xA7, 0x9C, 0x33,
|
|
||||||
0x8D, 0xB8, 0x6E, 0xDE, 0x87, 0x18, 0x22, 0x60, 0xC4, 0xAE, 0xF2, 0x87, 0x9F, 0xCE, 0x09, 0x5C,
|
|
||||||
0xB5, 0x99, 0xA5, 0x9F, 0x49, 0xF2, 0xD7, 0x58, 0xFA, 0xF9, 0xC0, 0x25, 0x7D, 0xD6, 0xCB, 0xF3,
|
|
||||||
0xD8, 0x6C, 0xA2, 0x69, 0x91, 0x68, 0x73, 0xB1, 0x94, 0x6F, 0xA3, 0xF3, 0xB9, 0x7D, 0xF8, 0xE0,
|
|
||||||
0x72, 0x9E, 0x93, 0x7B, 0x7A, 0xA2, 0x57, 0x60, 0xB7, 0x5B, 0xA9, 0x84, 0xAE, 0x64, 0x88, 0x69
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xBC, 0xA5, 0x6A, 0x7E, 0xEA, 0x38, 0x34, 0x62, 0xA6, 0x10, 0x18, 0x3C, 0xE1, 0x63, 0x7B, 0xF0,
|
|
||||||
0xD3, 0x08, 0x8C, 0xF5, 0xC5, 0xC4, 0xC7, 0x93, 0xE9, 0xD9, 0xE6, 0x32, 0xF3, 0xA0, 0xF6, 0x6E,
|
|
||||||
0x8A, 0x98, 0x76, 0x47, 0x33, 0x47, 0x65, 0x02, 0x70, 0xDC, 0x86, 0x5F, 0x3D, 0x61, 0x5A, 0x70,
|
|
||||||
0xBC, 0x5A, 0xCA, 0xCA, 0x50, 0xAD, 0x61, 0x7E, 0xC9, 0xEC, 0x27, 0xFF, 0xE8, 0x64, 0x42, 0x9A,
|
|
||||||
0xEE, 0xBE, 0xC3, 0xD1, 0x0B, 0xC0, 0xE9, 0xBF, 0x83, 0x8D, 0xC0, 0x0C, 0xD8, 0x00, 0x5B, 0x76,
|
|
||||||
0x90, 0xD2, 0x4B, 0x30, 0x84, 0x35, 0x8B, 0x1E, 0x20, 0xB7, 0xE4, 0xDC, 0x63, 0xE5, 0xDF, 0xCD,
|
|
||||||
0x00, 0x5F, 0x81, 0x5F, 0x67, 0xC5, 0x8B, 0xDF, 0xFC, 0xE1, 0x37, 0x5F, 0x07, 0xD9, 0xDE, 0x4F,
|
|
||||||
0xE6, 0x7B, 0xF1, 0xFB, 0xA1, 0x5A, 0x71, 0x40, 0xFE, 0xBA, 0x1E, 0xAE, 0x13, 0x22, 0xD2, 0xFE,
|
|
||||||
0x37, 0xA2, 0xB6, 0x8B, 0xAB, 0xEB, 0x84, 0x81, 0x4E, 0x7C, 0x1E, 0x02, 0xD1, 0xFB, 0xD7, 0x5D,
|
|
||||||
0x11, 0x84, 0x64, 0xD2, 0x4D, 0xBB, 0x50, 0x00, 0x67, 0x54, 0xE2, 0x77, 0x89, 0xBA, 0x0B, 0xE7,
|
|
||||||
0x05, 0x57, 0x9A, 0x22, 0x5A, 0xEC, 0x76, 0x1C, 0xFD, 0xE8, 0xA8, 0x18, 0x16, 0x41, 0x65, 0x03,
|
|
||||||
0xFA, 0xC4, 0xA6, 0x31, 0x5C, 0x1A, 0x7F, 0xAB, 0x11, 0xC8, 0x4A, 0x99, 0xB9, 0xE6, 0xCF, 0x62,
|
|
||||||
0x21, 0xA6, 0x72, 0x47, 0xDB, 0xBA, 0x96, 0x26, 0x4E, 0x2E, 0xD4, 0x8C, 0x46, 0xD6, 0xA7, 0x1A,
|
|
||||||
0x6C, 0x32, 0xA7, 0xDF, 0x85, 0x1C, 0x03, 0xC3, 0x6D, 0xA9, 0xE9, 0x68, 0xF4, 0x17, 0x1E, 0xB2,
|
|
||||||
0x70, 0x2A, 0xA1, 0xE5, 0xE1, 0xF3, 0x8F, 0x6F, 0x63, 0xAC, 0xEB, 0x72, 0x0B, 0x4C, 0x4A, 0x36,
|
|
||||||
0x3C, 0x60, 0x91, 0x9F, 0x6E, 0x1C, 0x71, 0xEA, 0xD0, 0x78, 0x78, 0xA0, 0x2E, 0xC6, 0x32, 0x6B
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr inline const u8 AcidSignatureKeyModulusProd[AcidSignatureKeyGenerationMax + 1][AcidSignatureKeyModulusSize] = {
|
|
||||||
{
|
|
||||||
0xDD, 0xC8, 0xDD, 0xF2, 0x4E, 0x6D, 0xF0, 0xCA, 0x9E, 0xC7, 0x5D, 0xC7, 0x7B, 0xAD, 0xFE, 0x7D,
|
|
||||||
0x23, 0x89, 0x69, 0xB6, 0xF2, 0x06, 0xA2, 0x02, 0x88, 0xE1, 0x55, 0x91, 0xAB, 0xCB, 0x4D, 0x50,
|
|
||||||
0x2E, 0xFC, 0x9D, 0x94, 0x76, 0xD6, 0x4C, 0xD8, 0xFF, 0x10, 0xFA, 0x5E, 0x93, 0x0A, 0xB4, 0x57,
|
|
||||||
0xAC, 0x51, 0xC7, 0x16, 0x66, 0xF4, 0x1A, 0x54, 0xC2, 0xC5, 0x04, 0x3D, 0x1B, 0xFE, 0x30, 0x20,
|
|
||||||
0x8A, 0xAC, 0x6F, 0x6F, 0xF5, 0xC7, 0xB6, 0x68, 0xB8, 0xC9, 0x40, 0x6B, 0x42, 0xAD, 0x11, 0x21,
|
|
||||||
0xE7, 0x8B, 0xE9, 0x75, 0x01, 0x86, 0xE4, 0x48, 0x9B, 0x0A, 0x0A, 0xF8, 0x7F, 0xE8, 0x87, 0xF2,
|
|
||||||
0x82, 0x01, 0xE6, 0xA3, 0x0F, 0xE4, 0x66, 0xAE, 0x83, 0x3F, 0x4E, 0x9F, 0x5E, 0x01, 0x30, 0xA4,
|
|
||||||
0x00, 0xB9, 0x9A, 0xAE, 0x5F, 0x03, 0xCC, 0x18, 0x60, 0xE5, 0xEF, 0x3B, 0x5E, 0x15, 0x16, 0xFE,
|
|
||||||
0x1C, 0x82, 0x78, 0xB5, 0x2F, 0x47, 0x7C, 0x06, 0x66, 0x88, 0x5D, 0x35, 0xA2, 0x67, 0x20, 0x10,
|
|
||||||
0xE7, 0x6C, 0x43, 0x68, 0xD3, 0xE4, 0x5A, 0x68, 0x2A, 0x5A, 0xE2, 0x6D, 0x73, 0xB0, 0x31, 0x53,
|
|
||||||
0x1C, 0x20, 0x09, 0x44, 0xF5, 0x1A, 0x9D, 0x22, 0xBE, 0x12, 0xA1, 0x77, 0x11, 0xE2, 0xA1, 0xCD,
|
|
||||||
0x40, 0x9A, 0xA2, 0x8B, 0x60, 0x9B, 0xEF, 0xA0, 0xD3, 0x48, 0x63, 0xA2, 0xF8, 0xA3, 0x2C, 0x08,
|
|
||||||
0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, 0x69, 0x2B, 0x31, 0x6A,
|
|
||||||
0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA,
|
|
||||||
0x37, 0xEA, 0xE8, 0x1E, 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B,
|
|
||||||
0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, 0x7D, 0x35, 0x22, 0xFD
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, 0x96, 0x5A, 0xBF, 0x90,
|
|
||||||
0xAC, 0xA7, 0xFD, 0x9B, 0x5B, 0xBD, 0x8A, 0x26, 0xB0, 0xCB, 0x20, 0x28, 0x9A, 0x72, 0x12, 0xF5,
|
|
||||||
0x20, 0x65, 0xB3, 0xB9, 0x84, 0x58, 0x1F, 0x27, 0xBC, 0x7C, 0xA2, 0xC9, 0x9E, 0x18, 0x95, 0xCF,
|
|
||||||
0xC2, 0x73, 0x2E, 0x74, 0x8C, 0x66, 0xE5, 0x9E, 0x79, 0x2B, 0xB8, 0x07, 0x0C, 0xB0, 0x4E, 0x8E,
|
|
||||||
0xAB, 0x85, 0x21, 0x42, 0xC4, 0xC5, 0x6D, 0x88, 0x9C, 0xDB, 0x15, 0x95, 0x3F, 0x80, 0xDB, 0x7A,
|
|
||||||
0x9A, 0x7D, 0x41, 0x56, 0x25, 0x17, 0x18, 0x42, 0x4D, 0x8C, 0xAC, 0xA5, 0x7B, 0xDB, 0x42, 0x5D,
|
|
||||||
0x59, 0x35, 0x45, 0x5D, 0x8A, 0x02, 0xB5, 0x70, 0xC0, 0x72, 0x35, 0x46, 0xD0, 0x1D, 0x60, 0x01,
|
|
||||||
0x4A, 0xCC, 0x1C, 0x46, 0xD3, 0xD6, 0x35, 0x52, 0xD6, 0xE1, 0xF8, 0x3B, 0x5D, 0xEA, 0xDD, 0xB8,
|
|
||||||
0xFE, 0x7D, 0x50, 0xCB, 0x35, 0x23, 0x67, 0x8B, 0xB6, 0xE4, 0x74, 0xD2, 0x60, 0xFC, 0xFD, 0x43,
|
|
||||||
0xBF, 0x91, 0x08, 0x81, 0xC5, 0x4F, 0x5D, 0x16, 0x9A, 0xC4, 0x9A, 0xC6, 0xF6, 0xF3, 0xE1, 0xF6,
|
|
||||||
0x5C, 0x07, 0xAA, 0x71, 0x6C, 0x13, 0xA4, 0xB1, 0xB3, 0x66, 0xBF, 0x90, 0x4C, 0x3D, 0xA2, 0xC4,
|
|
||||||
0x0B, 0xB8, 0x3D, 0x7A, 0x8C, 0x19, 0xFA, 0xFF, 0x6B, 0xB9, 0x1F, 0x02, 0xCC, 0xB6, 0xD3, 0x0C,
|
|
||||||
0x7D, 0x19, 0x1F, 0x47, 0xF9, 0xC7, 0x40, 0x01, 0xFA, 0x46, 0xEA, 0x0B, 0xD4, 0x02, 0xE0, 0x3D,
|
|
||||||
0x30, 0x9A, 0x1A, 0x0F, 0xEA, 0xA7, 0x66, 0x55, 0xF7, 0xCB, 0x28, 0xE2, 0xBB, 0x99, 0xE4, 0x83,
|
|
||||||
0xC3, 0x43, 0x03, 0xEE, 0xDC, 0x1F, 0x02, 0x23, 0xDD, 0xD1, 0x2D, 0x39, 0xA4, 0x65, 0x75, 0x03,
|
|
||||||
0xEF, 0x37, 0x9C, 0x06, 0xD6, 0xFA, 0xA1, 0x15, 0xF0, 0xDB, 0x17, 0x47, 0x26, 0x4F, 0x49, 0x03
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(AcidSignatureKeyModulusProd) == sizeof(AcidSignatureKeyModulusDev));
|
|
||||||
|
|
||||||
constexpr inline const u8 AcidSignatureKeyExponent[] = {
|
|
||||||
0x01, 0x00, 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr inline size_t AcidSignatureKeyExponentSize = util::size(AcidSignatureKeyExponent);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,684 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,367 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 = '.';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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,6 +170,4 @@ namespace ams::fssystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCounter(void *counter, size_t counter_size, u64 value);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,15 @@
|
|||||||
* 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 <stratosphere/fs/fs_common.hpp>
|
#include "../../fs/fs_common.hpp"
|
||||||
#include <stratosphere/fs/fsa/fs_ifile.hpp>
|
#include "../../fs/fsa/fs_ifile.hpp"
|
||||||
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
|
#include "../../fs/fsa/fs_idirectory.hpp"
|
||||||
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
|
#include "../../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, public fs::impl::Newable {
|
class IPathResolutionFileSystem : public fs::fsa::IFileSystem {
|
||||||
NON_COPYABLE(IPathResolutionFileSystem);
|
NON_COPYABLE(IPathResolutionFileSystem);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<fs::fsa::IFileSystem> shared_fs;
|
std::shared_ptr<fs::fsa::IFileSystem> shared_fs;
|
||||||
|
|||||||
@@ -20,20 +20,19 @@
|
|||||||
namespace ams::hos {
|
namespace ams::hos {
|
||||||
|
|
||||||
enum Version : u16 {
|
enum Version : u16 {
|
||||||
Version_Min = 0,
|
Version_Min = 0,
|
||||||
Version_1_0_0 = Version_Min,
|
Version_100 = Version_Min,
|
||||||
Version_2_0_0 = 1,
|
Version_200 = 1,
|
||||||
Version_3_0_0 = 2,
|
Version_300 = 2,
|
||||||
Version_4_0_0 = 3,
|
Version_400 = 3,
|
||||||
Version_5_0_0 = 4,
|
Version_500 = 4,
|
||||||
Version_6_0_0 = 5,
|
Version_600 = 5,
|
||||||
Version_7_0_0 = 6,
|
Version_700 = 6,
|
||||||
Version_8_0_0 = 7,
|
Version_800 = 7,
|
||||||
Version_8_1_0 = 8,
|
Version_810 = 8,
|
||||||
Version_9_0_0 = 9,
|
Version_900 = 9,
|
||||||
Version_9_1_0 = 10,
|
Version_910 = 10,
|
||||||
Version_10_0_0 = 11,
|
Version_Current = Version_910,
|
||||||
Version_Current = Version_10_0_0,
|
|
||||||
Version_Max = 32,
|
Version_Max = 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() : lock(false) { /* ... */ }
|
FileKeyValueStore() { /* ... */ }
|
||||||
|
|
||||||
/* Basic accessors. */
|
/* Basic accessors. */
|
||||||
Result Initialize(const char *dir);
|
Result Initialize(const char *dir);
|
||||||
|
|||||||
@@ -16,6 +16,5 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stratosphere/ldr/ldr_types.hpp>
|
#include "ldr/ldr_types.hpp"
|
||||||
#include <stratosphere/ldr/ldr_shell_api.hpp>
|
#include "ldr/ldr_pm_api.hpp"
|
||||||
#include <stratosphere/ldr/ldr_pm_api.hpp>
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace ams::ldr::pm {
|
|||||||
Result GetProgramInfo(ProgramInfo *out, const ncm::ProgramLocation &loc);
|
Result GetProgramInfo(ProgramInfo *out, const ncm::ProgramLocation &loc);
|
||||||
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc);
|
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc);
|
||||||
Result UnpinProgram(PinId pin_id);
|
Result UnpinProgram(PinId pin_id);
|
||||||
Result SetEnabledProgramVerification(bool enabled);
|
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id);
|
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id);
|
||||||
|
|
||||||
/* Atmosphere extension API. */
|
/* Atmosphere extension API. */
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/ncm/ncm_ids.hpp>
|
|
||||||
#include <stratosphere/ldr/ldr_types.hpp>
|
|
||||||
|
|
||||||
namespace ams::ldr {
|
|
||||||
|
|
||||||
/* Shell API. */
|
|
||||||
Result InitializeForShell();
|
|
||||||
Result FinalizeForShell();
|
|
||||||
|
|
||||||
Result SetProgramArgument(ncm::ProgramId program_id, const void *arg, size_t size);
|
|
||||||
Result FlushArguments();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -221,8 +221,7 @@ namespace ams::ldr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
u32 magic;
|
u32 magic;
|
||||||
u32 signature_key_generation;
|
u8 reserved_04[8];
|
||||||
u8 reserved_08[4];
|
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 reserved_0D;
|
u8 reserved_0D;
|
||||||
u8 main_thread_priority;
|
u8 main_thread_priority;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace ams::lmem::impl {
|
|||||||
|
|
||||||
void *heap_start;
|
void *heap_start;
|
||||||
void *heap_end;
|
void *heap_end;
|
||||||
os::MutexType mutex;
|
os::Mutex mutex;
|
||||||
u8 option;
|
u8 option;
|
||||||
ImplementationHeapHead impl_head;
|
ImplementationHeapHead impl_head;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
Result RegisterAddOnContentStorage(ncm::DataId id, ncm::ApplicationId application_id, ncm::StorageId storage_id) {
|
Result RegisterAddOnContentStorage(ncm::DataId id, ncm::ApplicationId application_id, ncm::StorageId storage_id) {
|
||||||
AMS_ASSERT(this->interface);
|
AMS_ASSERT(this->interface);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
return this->interface->RegisterAddOnContentStorage(id, application_id, storage_id);
|
return this->interface->RegisterAddOnContentStorage(id, application_id, storage_id);
|
||||||
} else {
|
} else {
|
||||||
return this->interface->RegisterAddOnContentStorageDeprecated(id, storage_id);
|
return this->interface->RegisterAddOnContentStorageDeprecated(id, storage_id);
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ namespace ams::lr {
|
|||||||
virtual Result UnregisterApplicationAddOnContent(ncm::ApplicationId id) = 0;
|
virtual Result UnregisterApplicationAddOnContent(ncm::ApplicationId id) = 0;
|
||||||
public:
|
public:
|
||||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveAddOnContentPath, hos::Version_2_0_0),
|
MAKE_SERVICE_COMMAND_META(ResolveAddOnContentPath, hos::Version_200),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorageDeprecated, hos::Version_2_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorageDeprecated, hos::Version_200, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorage, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorage, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(UnregisterAllAddOnContentPath, hos::Version_2_0_0),
|
MAKE_SERVICE_COMMAND_META(UnregisterAllAddOnContentPath, hos::Version_200),
|
||||||
MAKE_SERVICE_COMMAND_META(RefreshApplicationAddOnContent, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RefreshApplicationAddOnContent, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(UnregisterApplicationAddOnContent, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(UnregisterApplicationAddOnContent, hos::Version_900),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -88,27 +88,27 @@ namespace ams::lr {
|
|||||||
MAKE_SERVICE_COMMAND_META(ResolveApplicationControlPath),
|
MAKE_SERVICE_COMMAND_META(ResolveApplicationControlPath),
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveApplicationHtmlDocumentPath),
|
MAKE_SERVICE_COMMAND_META(ResolveApplicationHtmlDocumentPath),
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveDataPath),
|
MAKE_SERVICE_COMMAND_META(ResolveDataPath),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPathDeprecated, hos::Version_1_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPathDeprecated, hos::Version_100, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPathDeprecated, hos::Version_1_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPathDeprecated, hos::Version_100, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveApplicationLegalInformationPath),
|
MAKE_SERVICE_COMMAND_META(ResolveApplicationLegalInformationPath),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPathDeprecated, hos::Version_1_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPathDeprecated, hos::Version_100, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(Refresh),
|
MAKE_SERVICE_COMMAND_META(Refresh),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathDeprecated, hos::Version_5_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathDeprecated, hos::Version_500, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(ClearApplicationRedirectionDeprecated, hos::Version_5_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(ClearApplicationRedirectionDeprecated, hos::Version_500, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(ClearApplicationRedirection, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(ClearApplicationRedirection, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(EraseProgramRedirection, hos::Version_5_0_0),
|
MAKE_SERVICE_COMMAND_META(EraseProgramRedirection, hos::Version_500),
|
||||||
MAKE_SERVICE_COMMAND_META(EraseApplicationControlRedirection, hos::Version_5_0_0),
|
MAKE_SERVICE_COMMAND_META(EraseApplicationControlRedirection, hos::Version_500),
|
||||||
MAKE_SERVICE_COMMAND_META(EraseApplicationHtmlDocumentRedirection, hos::Version_5_0_0),
|
MAKE_SERVICE_COMMAND_META(EraseApplicationHtmlDocumentRedirection, hos::Version_500),
|
||||||
MAKE_SERVICE_COMMAND_META(EraseApplicationLegalInformationRedirection, hos::Version_5_0_0),
|
MAKE_SERVICE_COMMAND_META(EraseApplicationLegalInformationRedirection, hos::Version_500),
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveProgramPathForDebug, hos::Version_7_0_0),
|
MAKE_SERVICE_COMMAND_META(ResolveProgramPathForDebug, hos::Version_700),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectProgramPathForDebug, hos::Version_7_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectProgramPathForDebug, hos::Version_700),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebugDeprecated, hos::Version_7_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebugDeprecated, hos::Version_700, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebug, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebug, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(EraseProgramRedirectionForDebug, hos::Version_7_0_0),
|
MAKE_SERVICE_COMMAND_META(EraseProgramRedirectionForDebug, hos::Version_700),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,19 +56,19 @@ namespace ams::lr {
|
|||||||
public:
|
public:
|
||||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveProgramPath),
|
MAKE_SERVICE_COMMAND_META(ResolveProgramPath),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterProgramPathDeprecated, hos::Version_1_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RegisterProgramPathDeprecated, hos::Version_100, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterProgramPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RegisterProgramPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(UnregisterProgramPath),
|
MAKE_SERVICE_COMMAND_META(UnregisterProgramPath),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectProgramPathDeprecated, hos::Version_1_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectProgramPathDeprecated, hos::Version_100, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectProgramPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectProgramPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(ResolveHtmlDocumentPath, hos::Version_2_0_0),
|
MAKE_SERVICE_COMMAND_META(ResolveHtmlDocumentPath, hos::Version_200),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPathDeprecated, hos::Version_2_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPathDeprecated, hos::Version_200, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(UnregisterHtmlDocumentPath, hos::Version_2_0_0),
|
MAKE_SERVICE_COMMAND_META(UnregisterHtmlDocumentPath, hos::Version_200),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPathDeprecated, hos::Version_2_0_0, hos::Version_8_1_0),
|
MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPathDeprecated, hos::Version_200, hos::Version_810),
|
||||||
MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPath, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPath, hos::Version_900),
|
||||||
MAKE_SERVICE_COMMAND_META(Refresh, hos::Version_7_0_0),
|
MAKE_SERVICE_COMMAND_META(Refresh, hos::Version_700),
|
||||||
MAKE_SERVICE_COMMAND_META(RefreshExcluding, hos::Version_9_0_0),
|
MAKE_SERVICE_COMMAND_META(RefreshExcluding, hos::Version_900),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
void RedirectApplicationControlPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
void RedirectApplicationControlPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationControlPath(path, id, owner_id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationControlPath(path, id, owner_id));
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationControlPathDeprecated(path, id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationControlPathDeprecated(path, id));
|
||||||
@@ -77,7 +77,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
void RedirectApplicationHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
void RedirectApplicationHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPath(path, id, owner_id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPath(path, id, owner_id));
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPathDeprecated(path, id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPathDeprecated(path, id));
|
||||||
@@ -91,7 +91,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
void RedirectApplicationLegalInformationPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
void RedirectApplicationLegalInformationPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPath(path, id, owner_id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPath(path, id, owner_id));
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPathDeprecated(path, id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPathDeprecated(path, id));
|
||||||
@@ -105,7 +105,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
void RedirectApplicationProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
void RedirectApplicationProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPath(path, id, owner_id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPath(path, id, owner_id));
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathDeprecated(path, id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathDeprecated(path, id));
|
||||||
@@ -114,13 +114,13 @@ namespace ams::lr {
|
|||||||
|
|
||||||
Result ClearApplicationRedirection() {
|
Result ClearApplicationRedirection() {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
AMS_ASSERT(hos::GetVersion() < hos::Version_9_0_0);
|
AMS_ASSERT(hos::GetVersion() < hos::Version_900);
|
||||||
return this->ClearApplicationRedirection(nullptr, 0);
|
return this->ClearApplicationRedirection(nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ClearApplicationRedirection(const ncm::ProgramId *excluding_ids, size_t num_ids) {
|
Result ClearApplicationRedirection(const ncm::ProgramId *excluding_ids, size_t num_ids) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
return this->interface->ClearApplicationRedirection(sf::InArray<ncm::ProgramId>(excluding_ids, num_ids));
|
return this->interface->ClearApplicationRedirection(sf::InArray<ncm::ProgramId>(excluding_ids, num_ids));
|
||||||
} else {
|
} else {
|
||||||
return this->interface->ClearApplicationRedirectionDeprecated();
|
return this->interface->ClearApplicationRedirectionDeprecated();
|
||||||
@@ -159,7 +159,7 @@ namespace ams::lr {
|
|||||||
|
|
||||||
void RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
void RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
|
||||||
AMS_ASSERT(this->interface != nullptr);
|
AMS_ASSERT(this->interface != nullptr);
|
||||||
if (hos::GetVersion() >= hos::Version_9_0_0) {
|
if (hos::GetVersion() >= hos::Version_900) {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebug(path, id, owner_id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebug(path, id, owner_id));
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebugDeprecated(path, id));
|
R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebugDeprecated(path, id));
|
||||||
|
|||||||
@@ -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{false};
|
os::Mutex mutex;
|
||||||
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;
|
||||||
@@ -40,7 +40,7 @@ namespace ams::lr {
|
|||||||
MAKE_SERVICE_COMMAND_META(OpenLocationResolver),
|
MAKE_SERVICE_COMMAND_META(OpenLocationResolver),
|
||||||
MAKE_SERVICE_COMMAND_META(OpenRegisteredLocationResolver),
|
MAKE_SERVICE_COMMAND_META(OpenRegisteredLocationResolver),
|
||||||
MAKE_SERVICE_COMMAND_META(RefreshLocationResolver),
|
MAKE_SERVICE_COMMAND_META(RefreshLocationResolver),
|
||||||
MAKE_SERVICE_COMMAND_META(OpenAddOnContentLocationResolver, hos::Version_2_0_0),
|
MAKE_SERVICE_COMMAND_META(OpenAddOnContentLocationResolver, hos::Version_200),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user