mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 04:02:11 +00:00
Some changes.
* Placed C++ extern "C" blocks inside include guards. * Added a "clean_all" rule to the Makefile to avoid recompiling libusbhsfs after each time "clean" is used. * Added static asserts for all structs that may need it throughout the code. * Preprocessor macros are now used to generate certificate and ticket structs.
This commit is contained in:
parent
e0949bba6b
commit
3cb6ef93aa
36 changed files with 577 additions and 330 deletions
5
Makefile
5
Makefile
|
@ -158,7 +158,7 @@ ifneq ($(ROMFS),)
|
||||||
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
|
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
.PHONY: $(BUILD) clean clean_all all
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: $(BUILD)
|
all: $(BUILD)
|
||||||
|
@ -173,9 +173,10 @@ $(BUILD): usbhsfs
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@$(MAKE) --no-print-directory -C libusbhsfs clean
|
|
||||||
@rm -fr $(BUILD) *.pfs0 *.nso *.nro *.nacp *.elf
|
@rm -fr $(BUILD) *.pfs0 *.nso *.nro *.nacp *.elf
|
||||||
|
|
||||||
|
clean_all: clean
|
||||||
|
@$(MAKE) --no-print-directory -C libusbhsfs clean
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
|
12
source/aes.h
12
source/aes.h
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __AES_H__
|
||||||
|
#define __AES_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __AES_H__
|
|
||||||
#define __AES_H__
|
|
||||||
|
|
||||||
/// Performs an AES-128-XTS crypto operation using the non-standard Nintendo XTS tweak.
|
/// Performs an AES-128-XTS crypto operation using the non-standard Nintendo XTS tweak.
|
||||||
/// The Aes128XtsContext element should have been previously initialized with aes128XtsContextCreate(). 'encrypt' should match the value of 'is_encryptor' used with that call.
|
/// The Aes128XtsContext element should have been previously initialized with aes128XtsContextCreate(). 'encrypt' should match the value of 'is_encryptor' used with that call.
|
||||||
/// 'dst' and 'src' can both point to the same address.
|
/// 'dst' and 'src' can both point to the same address.
|
||||||
|
@ -84,8 +84,8 @@ NX_INLINE void aes128CtrUpdatePartialCtrEx(u8 *ctr, u32 ctr_val, u64 offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __AES_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __AES_H__ */
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __BFTTF_H__
|
||||||
|
#define __BFTTF_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __BFTTF_H__
|
|
||||||
#define __BFTTF_H__
|
|
||||||
|
|
||||||
/// Loosely based on PlSharedFontType.
|
/// Loosely based on PlSharedFontType.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BfttfFontType_Standard = 0, ///< Japan, US and Europe
|
BfttfFontType_Standard = 0, ///< Japan, US and Europe
|
||||||
|
@ -56,8 +56,8 @@ void bfttfExit(void);
|
||||||
/// Returns a specific BFTTF font using the provided BfttfFontType.
|
/// Returns a specific BFTTF font using the provided BfttfFontType.
|
||||||
bool bfttfGetFontByType(BfttfFontData *font, u8 font_type);
|
bool bfttfGetFontByType(BfttfFontData *font, u8 font_type);
|
||||||
|
|
||||||
#endif /* __BFTTF_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __BFTTF_H__ */
|
||||||
|
|
|
@ -21,15 +21,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __BKTR_H__
|
#ifndef __BKTR_H__
|
||||||
#define __BKTR_H__
|
#define __BKTR_H__
|
||||||
|
|
||||||
#include "romfs.h"
|
#include "romfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BktrIndirectStorageIndex_Original = 0,
|
BktrIndirectStorageIndex_Original = 0,
|
||||||
BktrIndirectStorageIndex_Patch = 1
|
BktrIndirectStorageIndex_Patch = 1
|
||||||
|
@ -43,6 +43,8 @@ typedef struct {
|
||||||
} BktrIndirectStorageEntry;
|
} BktrIndirectStorageEntry;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrIndirectStorageEntry, 0x14);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 entry_count;
|
u32 entry_count;
|
||||||
|
@ -51,6 +53,8 @@ typedef struct {
|
||||||
u8 reserved[0x3FF0 % sizeof(BktrIndirectStorageEntry)];
|
u8 reserved[0x3FF0 % sizeof(BktrIndirectStorageEntry)];
|
||||||
} BktrIndirectStorageBucket;
|
} BktrIndirectStorageBucket;
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrIndirectStorageBucket, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 bucket_count;
|
u32 bucket_count;
|
||||||
|
@ -59,12 +63,16 @@ typedef struct {
|
||||||
BktrIndirectStorageBucket indirect_storage_buckets[];
|
BktrIndirectStorageBucket indirect_storage_buckets[];
|
||||||
} BktrIndirectStorageBlock;
|
} BktrIndirectStorageBlock;
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrIndirectStorageBlock, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 generation;
|
u32 generation;
|
||||||
} BktrAesCtrExStorageEntry;
|
} BktrAesCtrExStorageEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrAesCtrExStorageEntry, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 entry_count;
|
u32 entry_count;
|
||||||
|
@ -72,6 +80,8 @@ typedef struct {
|
||||||
BktrAesCtrExStorageEntry aes_ctr_ex_storage_entries[0x3FF];
|
BktrAesCtrExStorageEntry aes_ctr_ex_storage_entries[0x3FF];
|
||||||
} BktrAesCtrExStorageBucket;
|
} BktrAesCtrExStorageBucket;
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrAesCtrExStorageBucket, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 bucket_count;
|
u32 bucket_count;
|
||||||
|
@ -80,6 +90,8 @@ typedef struct {
|
||||||
BktrAesCtrExStorageBucket aes_ctr_ex_storage_buckets[];
|
BktrAesCtrExStorageBucket aes_ctr_ex_storage_buckets[];
|
||||||
} BktrAesCtrExStorageBlock;
|
} BktrAesCtrExStorageBlock;
|
||||||
|
|
||||||
|
NXDT_ASSERT(BktrAesCtrExStorageBlock, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RomFileSystemContext base_romfs_ctx; ///< Base NCA RomFS context.
|
RomFileSystemContext base_romfs_ctx; ///< Base NCA RomFS context.
|
||||||
RomFileSystemContext patch_romfs_ctx; ///< Update NCA RomFS context. Must be used with RomFS directory/file entry functions, because it holds the updated directory/file tables.
|
RomFileSystemContext patch_romfs_ctx; ///< Update NCA RomFS context. Must be used with RomFS directory/file entry functions, because it holds the updated directory/file tables.
|
||||||
|
@ -157,8 +169,8 @@ NX_INLINE bool bktrGeneratePathFromFileEntry(BktrContext *ctx, RomFileSystemFile
|
||||||
return (ctx ? romfsGeneratePathFromFileEntry(&(ctx->patch_romfs_ctx), file_entry, out_path, out_path_size, illegal_char_replace_type) : false);
|
return (ctx ? romfsGeneratePathFromFileEntry(&(ctx->patch_romfs_ctx), file_entry, out_path, out_path_size, illegal_char_replace_type) : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __BKTR_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __BKTR_H__ */
|
||||||
|
|
193
source/cert.h
193
source/cert.h
|
@ -20,18 +20,93 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __CERT_H__
|
#ifndef __CERT_H__
|
||||||
#define __CERT_H__
|
#define __CERT_H__
|
||||||
|
|
||||||
#include "signature.h"
|
#include "signature.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SIGNED_CERT_MAX_SIZE sizeof(CertSigRsa4096PubKeyRsa4096)
|
#define SIGNED_CERT_MAX_SIZE sizeof(CertSigRsa4096PubKeyRsa4096)
|
||||||
#define SIGNED_CERT_MIN_SIZE sizeof(CertSigHmac160PubKeyEcc480)
|
#define SIGNED_CERT_MIN_SIZE sizeof(CertSigHmac160PubKeyEcc480)
|
||||||
|
|
||||||
|
#define GENERATE_CERT_STRUCT(sigtype, pubkeytype, certsize) \
|
||||||
|
\
|
||||||
|
typedef struct { \
|
||||||
|
SignatureBlock##sigtype sig_block; \
|
||||||
|
CertCommonBlock cert_common_block; \
|
||||||
|
CertPublicKeyBlock##pubkeytype pub_key_block; \
|
||||||
|
} CertSig##sigtype##PubKey##pubkeytype; \
|
||||||
|
\
|
||||||
|
NXDT_ASSERT(CertSig##sigtype##PubKey##pubkeytype, certsize);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CertPubKeyType_Rsa4096 = 0,
|
||||||
|
CertPubKeyType_Rsa2048 = 1,
|
||||||
|
CertPubKeyType_Ecc480 = 2
|
||||||
|
} CertPubKeyType;
|
||||||
|
|
||||||
|
/// Placed after the certificate signature block.
|
||||||
|
typedef struct {
|
||||||
|
char issuer[0x40];
|
||||||
|
u32 pub_key_type; ///< CertPubKeyType. Always stored using big endian byte order.
|
||||||
|
char name[0x40];
|
||||||
|
u32 date; ///< Stored using big endian byte order.
|
||||||
|
} CertCommonBlock;
|
||||||
|
|
||||||
|
NXDT_ASSERT(CertCommonBlock, 0x88);
|
||||||
|
|
||||||
|
/// RSA-4096 public key block. Placed after the certificate common block.
|
||||||
|
typedef struct {
|
||||||
|
u8 public_key[0x200];
|
||||||
|
u32 public_exponent;
|
||||||
|
u8 padding[0x34];
|
||||||
|
} CertPublicKeyBlockRsa4096;
|
||||||
|
|
||||||
|
NXDT_ASSERT(CertPublicKeyBlockRsa4096, 0x238);
|
||||||
|
|
||||||
|
/// RSA-2048 public key block. Placed after the certificate common block.
|
||||||
|
typedef struct {
|
||||||
|
u8 public_key[0x100];
|
||||||
|
u32 public_exponent;
|
||||||
|
u8 padding[0x34];
|
||||||
|
} CertPublicKeyBlockRsa2048;
|
||||||
|
|
||||||
|
NXDT_ASSERT(CertPublicKeyBlockRsa2048, 0x138);
|
||||||
|
|
||||||
|
/// ECC public key block. Placed after the certificate common block.
|
||||||
|
typedef struct {
|
||||||
|
u8 public_key[0x3C];
|
||||||
|
u8 padding[0x3C];
|
||||||
|
} CertPublicKeyBlockEcc480;
|
||||||
|
|
||||||
|
NXDT_ASSERT(CertPublicKeyBlockEcc480, 0x78);
|
||||||
|
|
||||||
|
/// All certificates generated below use a big endian sig_type field.
|
||||||
|
|
||||||
|
/// Certificates with RSA-4096 signatures.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa4096, Rsa4096, 0x500); /// pub_key_type field must be CertPubKeyType_Rsa4096.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa4096, Rsa2048, 0x400); /// pub_key_type field must be CertPubKeyType_Rsa2048.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa4096, Ecc480, 0x340); /// pub_key_type field must be CertPubKeyType_Ecc480.
|
||||||
|
|
||||||
|
/// Certificates with RSA-2048 signatures.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa2048, Rsa4096, 0x400); /// pub_key_type field must be CertPubKeyType_Rsa4096.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa2048, Rsa2048, 0x300); /// pub_key_type field must be CertPubKeyType_Rsa2048.
|
||||||
|
GENERATE_CERT_STRUCT(Rsa2048, Ecc480, 0x240); /// pub_key_type field must be CertPubKeyType_Ecc480.
|
||||||
|
|
||||||
|
/// Certificates with ECC signatures.
|
||||||
|
GENERATE_CERT_STRUCT(Ecc480, Rsa4096, 0x340); /// pub_key_type field must be CertPubKeyType_Rsa4096.
|
||||||
|
GENERATE_CERT_STRUCT(Ecc480, Rsa2048, 0x240); /// pub_key_type field must be CertPubKeyType_Rsa2048.
|
||||||
|
GENERATE_CERT_STRUCT(Ecc480, Ecc480, 0x180); /// pub_key_type field must be CertPubKeyType_Ecc480.
|
||||||
|
|
||||||
|
/// Certificates with HMAC signatures.
|
||||||
|
GENERATE_CERT_STRUCT(Hmac160, Rsa4096, 0x300); /// pub_key_type field must be CertPubKeyType_Rsa4096.
|
||||||
|
GENERATE_CERT_STRUCT(Hmac160, Rsa2048, 0x200); /// pub_key_type field must be CertPubKeyType_Rsa2048.
|
||||||
|
GENERATE_CERT_STRUCT(Hmac160, Ecc480, 0x140); /// pub_key_type field must be CertPubKeyType_Ecc480.
|
||||||
|
|
||||||
|
/// Certificate type.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CertType_None = 0,
|
CertType_None = 0,
|
||||||
CertType_SigRsa4096_PubKeyRsa4096 = 1,
|
CertType_SigRsa4096_PubKeyRsa4096 = 1,
|
||||||
|
@ -48,110 +123,6 @@ typedef enum {
|
||||||
CertType_SigHmac160_PubKeyEcc480 = 12
|
CertType_SigHmac160_PubKeyEcc480 = 12
|
||||||
} CertType;
|
} CertType;
|
||||||
|
|
||||||
/// Always stored using big endian byte order.
|
|
||||||
typedef enum {
|
|
||||||
CertPubKeyType_Rsa4096 = 0,
|
|
||||||
CertPubKeyType_Rsa2048 = 1,
|
|
||||||
CertPubKeyType_Ecc480 = 2
|
|
||||||
} CertPubKeyType;
|
|
||||||
|
|
||||||
/// Placed after the certificate signature block.
|
|
||||||
typedef struct {
|
|
||||||
char issuer[0x40];
|
|
||||||
u32 pub_key_type; ///< CertPubKeyType. Stored using big endian byte order.
|
|
||||||
char name[0x40];
|
|
||||||
u32 date; ///< Stored using big endian byte order.
|
|
||||||
} CertCommonBlock;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u8 public_key[0x200];
|
|
||||||
u32 public_exponent;
|
|
||||||
u8 padding[0x34];
|
|
||||||
} CertPublicKeyBlockRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u8 public_key[0x100];
|
|
||||||
u32 public_exponent;
|
|
||||||
u8 padding[0x34];
|
|
||||||
} CertPublicKeyBlockRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u8 public_key[0x3C];
|
|
||||||
u8 padding[0x3C];
|
|
||||||
} CertPublicKeyBlockEcc480;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa4096 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa4096.
|
|
||||||
CertPublicKeyBlockRsa4096 pub_key_block;
|
|
||||||
} CertSigRsa4096PubKeyRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa4096 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa2048.
|
|
||||||
CertPublicKeyBlockRsa2048 pub_key_block;
|
|
||||||
} CertSigRsa4096PubKeyRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa4096 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Ecc480.
|
|
||||||
CertPublicKeyBlockEcc480 pub_key_block;
|
|
||||||
} CertSigRsa4096PubKeyEcc480;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa2048 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa4096.
|
|
||||||
CertPublicKeyBlockRsa4096 pub_key_block;
|
|
||||||
} CertSigRsa2048PubKeyRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa2048 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa2048.
|
|
||||||
CertPublicKeyBlockRsa2048 pub_key_block;
|
|
||||||
} CertSigRsa2048PubKeyRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa2048 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Ecc480.
|
|
||||||
CertPublicKeyBlockEcc480 pub_key_block;
|
|
||||||
} CertSigRsa2048PubKeyEcc480;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockEcc480 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa4096.
|
|
||||||
CertPublicKeyBlockRsa4096 pub_key_block;
|
|
||||||
} CertSigEcc480PubKeyRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockEcc480 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa2048.
|
|
||||||
CertPublicKeyBlockRsa2048 pub_key_block;
|
|
||||||
} CertSigEcc480PubKeyRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockEcc480 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Ecc480.
|
|
||||||
CertPublicKeyBlockEcc480 pub_key_block;
|
|
||||||
} CertSigEcc480PubKeyEcc480;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockHmac160 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa4096.
|
|
||||||
CertPublicKeyBlockRsa4096 pub_key_block;
|
|
||||||
} CertSigHmac160PubKeyRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockHmac160 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Rsa2048.
|
|
||||||
CertPublicKeyBlockRsa2048 pub_key_block;
|
|
||||||
} CertSigHmac160PubKeyRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockHmac160 sig_block; ///< sig_type field is stored using big endian byte order.
|
|
||||||
CertCommonBlock cert_common_block; ///< pub_key_type field must be CertPubKeyType_Ecc480.
|
|
||||||
CertPublicKeyBlockEcc480 pub_key_block;
|
|
||||||
} CertSigHmac160PubKeyEcc480;
|
|
||||||
|
|
||||||
/// Used to store certificate type, size and raw data.
|
/// Used to store certificate type, size and raw data.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 type; ///< CertType.
|
u8 type; ///< CertType.
|
||||||
|
@ -244,8 +215,8 @@ NX_INLINE u64 certGetSignedCertificateHashAreaSize(void *buf)
|
||||||
return ((u64)sizeof(CertCommonBlock) + certGetPublicKeyBlockSize(__builtin_bswap32(cert_common_block->pub_key_type)));
|
return ((u64)sizeof(CertCommonBlock) + certGetPublicKeyBlockSize(__builtin_bswap32(cert_common_block->pub_key_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __CERT_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CERT_H__ */
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __CNMT_H__
|
#ifndef __CNMT_H__
|
||||||
#define __CNMT_H__
|
#define __CNMT_H__
|
||||||
|
|
||||||
#include "pfs.h"
|
#include "pfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CNMT_DIGEST_SIZE SHA256_HASH_SIZE
|
#define CNMT_DIGEST_SIZE SHA256_HASH_SIZE
|
||||||
|
|
||||||
/// Equivalent to NcmContentMetaAttribute.
|
/// Equivalent to NcmContentMetaAttribute.
|
||||||
|
@ -64,12 +64,16 @@ typedef struct {
|
||||||
u8 reserved_2[0x4];
|
u8 reserved_2[0x4];
|
||||||
} ContentMetaPackagedContentMetaHeader;
|
} ContentMetaPackagedContentMetaHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPackagedContentMetaHeader, 0x20);
|
||||||
|
|
||||||
/// Extended header for the SystemUpdate title.
|
/// Extended header for the SystemUpdate title.
|
||||||
/// Equivalent to NcmSystemUpdateMetaExtendedHeader.
|
/// Equivalent to NcmSystemUpdateMetaExtendedHeader.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 extended_data_size;
|
u32 extended_data_size;
|
||||||
} ContentMetaSystemUpdateMetaExtendedHeader;
|
} ContentMetaSystemUpdateMetaExtendedHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaSystemUpdateMetaExtendedHeader, 0x4);
|
||||||
|
|
||||||
/// Extended header for Application titles.
|
/// Extended header for Application titles.
|
||||||
/// Equivalent to NcmApplicationMetaExtendedHeader, but using VersionType1 structs.
|
/// Equivalent to NcmApplicationMetaExtendedHeader, but using VersionType1 structs.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -78,6 +82,8 @@ typedef struct {
|
||||||
VersionType1 required_application_version;
|
VersionType1 required_application_version;
|
||||||
} ContentMetaApplicationMetaExtendedHeader;
|
} ContentMetaApplicationMetaExtendedHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaApplicationMetaExtendedHeader, 0x10);
|
||||||
|
|
||||||
/// Extended header for Patch titles.
|
/// Extended header for Patch titles.
|
||||||
/// Equivalent to NcmPatchMetaExtendedHeader, but using a VersionType1 struct.
|
/// Equivalent to NcmPatchMetaExtendedHeader, but using a VersionType1 struct.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -87,6 +93,8 @@ typedef struct {
|
||||||
u8 reserved[0x8];
|
u8 reserved[0x8];
|
||||||
} ContentMetaPatchMetaExtendedHeader;
|
} ContentMetaPatchMetaExtendedHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPatchMetaExtendedHeader, 0x18);
|
||||||
|
|
||||||
/// Extended header for AddOnContent titles.
|
/// Extended header for AddOnContent titles.
|
||||||
/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a VersionType1 struct.
|
/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a VersionType1 struct.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -95,6 +103,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} ContentMetaAddOnContentMetaExtendedHeader;
|
} ContentMetaAddOnContentMetaExtendedHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaAddOnContentMetaExtendedHeader, 0x10);
|
||||||
|
|
||||||
/// Extended header for Delta titles.
|
/// Extended header for Delta titles.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 application_id;
|
u64 application_id;
|
||||||
|
@ -102,6 +112,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} ContentMetaDeltaMetaExtendedHeader;
|
} ContentMetaDeltaMetaExtendedHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaDeltaMetaExtendedHeader, 0x10);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ContentMetaFirmwareVariationVersion_Invalid = 0,
|
ContentMetaFirmwareVariationVersion_Invalid = 0,
|
||||||
ContentMetaFirmwareVariationVersion_V1 = 1,
|
ContentMetaFirmwareVariationVersion_V1 = 1,
|
||||||
|
@ -120,12 +132,16 @@ typedef struct {
|
||||||
u32 variation_count; ///< Determines how many firmware variation entries are available after this header.
|
u32 variation_count; ///< Determines how many firmware variation entries are available after this header.
|
||||||
} ContentMetaSystemUpdateMetaExtendedDataHeader;
|
} ContentMetaSystemUpdateMetaExtendedDataHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaSystemUpdateMetaExtendedDataHeader, 0x8);
|
||||||
|
|
||||||
/// Used if the firmware variation version matches ContentMetaFirmwareVariationVersion_V1.
|
/// Used if the firmware variation version matches ContentMetaFirmwareVariationVersion_V1.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 firmware_variation_id;
|
u32 firmware_variation_id;
|
||||||
u8 reserved[0x1C];
|
u8 reserved[0x1C];
|
||||||
} ContentMetaFirmwareVariationInfoV1;
|
} ContentMetaFirmwareVariationInfoV1;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaFirmwareVariationInfoV1, 0x20);
|
||||||
|
|
||||||
/// Used if the firmware variation version matches ContentMetaFirmwareVariationVersion_V2.
|
/// Used if the firmware variation version matches ContentMetaFirmwareVariationVersion_V2.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool refer_to_base;
|
bool refer_to_base;
|
||||||
|
@ -134,6 +150,8 @@ typedef struct {
|
||||||
u8 reserved_2[0x18];
|
u8 reserved_2[0x18];
|
||||||
} ContentMetaFirmwareVariationInfoV2;
|
} ContentMetaFirmwareVariationInfoV2;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaFirmwareVariationInfoV2, 0x20);
|
||||||
|
|
||||||
/// Header for the extended data region in Patch titles, pointed to by the extended header.
|
/// Header for the extended data region in Patch titles, pointed to by the extended header.
|
||||||
/// This is followed by:
|
/// This is followed by:
|
||||||
/// * 'history_count' ContentMetaPatchHistoryHeader entries.
|
/// * 'history_count' ContentMetaPatchHistoryHeader entries.
|
||||||
|
@ -153,6 +171,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} ContentMetaPatchMetaExtendedDataHeader;
|
} ContentMetaPatchMetaExtendedDataHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPatchMetaExtendedDataHeader, 0x1C);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcmContentMetaKey content_meta_key;
|
NcmContentMetaKey content_meta_key;
|
||||||
u8 digest[CNMT_DIGEST_SIZE];
|
u8 digest[CNMT_DIGEST_SIZE];
|
||||||
|
@ -160,6 +180,8 @@ typedef struct {
|
||||||
u8 reserved[0x6];
|
u8 reserved[0x6];
|
||||||
} ContentMetaPatchHistoryHeader;
|
} ContentMetaPatchHistoryHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPatchHistoryHeader, 0x38);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 source_patch_id;
|
u64 source_patch_id;
|
||||||
u64 destination_patch_id;
|
u64 destination_patch_id;
|
||||||
|
@ -169,6 +191,8 @@ typedef struct {
|
||||||
u8 reserved[0x8];
|
u8 reserved[0x8];
|
||||||
} ContentMetaPatchDeltaHistory;
|
} ContentMetaPatchDeltaHistory;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPatchDeltaHistory, 0x28);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 source_patch_id;
|
u64 source_patch_id;
|
||||||
u64 destination_patch_id;
|
u64 destination_patch_id;
|
||||||
|
@ -180,6 +204,8 @@ typedef struct {
|
||||||
u8 reserved_2[0x6];
|
u8 reserved_2[0x6];
|
||||||
} ContentMetaPatchDeltaHeader;
|
} ContentMetaPatchDeltaHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaPatchDeltaHeader, 0x28);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ContentMetaUpdateType_ApplyAsDelta = 0,
|
ContentMetaUpdateType_ApplyAsDelta = 0,
|
||||||
ContentMetaUpdateType_Overwrite = 1,
|
ContentMetaUpdateType_Overwrite = 1,
|
||||||
|
@ -201,11 +227,15 @@ typedef struct {
|
||||||
} ContentMetaFragmentSet;
|
} ContentMetaFragmentSet;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaFragmentSet, 0x34);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 content_info_index;
|
u16 content_info_index;
|
||||||
u16 fragment_index;
|
u16 fragment_index;
|
||||||
} ContentMetaFragmentIndicator;
|
} ContentMetaFragmentIndicator;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaFragmentIndicator, 0x4);
|
||||||
|
|
||||||
/// Header for the extended data region in Delta titles, pointed to by the extended header.
|
/// Header for the extended data region in Delta titles, pointed to by the extended header.
|
||||||
/// This is followed by:
|
/// This is followed by:
|
||||||
/// * 'fragment_set_count' ContentMetaFragmentSet entries.
|
/// * 'fragment_set_count' ContentMetaFragmentSet entries.
|
||||||
|
@ -219,6 +249,8 @@ typedef struct {
|
||||||
u8 reserved[0x6];
|
u8 reserved[0x6];
|
||||||
} ContentMetaDeltaMetaExtendedDataHeader;
|
} ContentMetaDeltaMetaExtendedDataHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ContentMetaDeltaMetaExtendedDataHeader, 0x20);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Meta NCA from which CNMT data is retrieved.
|
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Meta NCA from which CNMT data is retrieved.
|
||||||
PartitionFileSystemContext pfs_ctx; ///< PartitionFileSystemContext for the Meta NCA FS section #0, which is where the CNMT is stored.
|
PartitionFileSystemContext pfs_ctx; ///< PartitionFileSystemContext for the Meta NCA FS section #0, which is where the CNMT is stored.
|
||||||
|
@ -293,8 +325,8 @@ NX_INLINE u32 cnmtGetRequiredTitleVersion(ContentMetaContext *cnmt_ctx)
|
||||||
((VersionType1*)(cnmt_ctx->extended_header + sizeof(u64)))->value : 0);
|
((VersionType1*)(cnmt_ctx->extended_header + sizeof(u64)))->value : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __CNMT_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CNMT_H__ */
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
#ifndef __COMMON_H__
|
#ifndef __COMMON_H__
|
||||||
#define __COMMON_H__
|
#define __COMMON_H__
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
# include <stdatomic.h>
|
|
||||||
#else
|
|
||||||
# include <atomic>
|
|
||||||
# define _Atomic(X) std::atomic< X >
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -45,6 +38,13 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#else
|
||||||
|
#include <atomic>
|
||||||
|
#define _Atomic(X) std::atomic< X >
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "ums.h"
|
#include "ums.h"
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@
|
||||||
|
|
||||||
#define FAT32_FILESIZE_LIMIT (u64)0xFFFFFFFF /* 4 GiB - 1 (4294967295 bytes). */
|
#define FAT32_FILESIZE_LIMIT (u64)0xFFFFFFFF /* 4 GiB - 1 (4294967295 bytes). */
|
||||||
|
|
||||||
|
#define NXDT_ASSERT(name, size) static_assert(sizeof(name) == (size), "Bad size for " #name "! Expected " #size ".")
|
||||||
|
|
||||||
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{major_relstep}.{minor_relstep}".
|
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{major_relstep}.{minor_relstep}".
|
||||||
/// Referenced by multiple header files.
|
/// Referenced by multiple header files.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -71,6 +73,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} VersionType1;
|
} VersionType1;
|
||||||
|
|
||||||
|
NXDT_ASSERT(VersionType1, 0x4);
|
||||||
|
|
||||||
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{relstep}".
|
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{relstep}".
|
||||||
/// Only used by GameCardFwMode and NcaSdkAddOnVersion.
|
/// Only used by GameCardFwMode and NcaSdkAddOnVersion.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -85,6 +89,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} VersionType2;
|
} VersionType2;
|
||||||
|
|
||||||
|
NXDT_ASSERT(VersionType2, 0x4);
|
||||||
|
|
||||||
/// These are set in main().
|
/// These are set in main().
|
||||||
extern int g_argc;
|
extern int g_argc;
|
||||||
extern char **g_argv;
|
extern char **g_argv;
|
||||||
|
|
|
@ -23,19 +23,19 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __CRC32_FAST_H__
|
||||||
|
#define __CRC32_FAST_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __CRC32_FAST_H__
|
|
||||||
#define __CRC32_FAST_H__
|
|
||||||
|
|
||||||
/// Calculates a CRC32 checksum over the provided input buffer. Checksum calculation in chunks is supported.
|
/// Calculates a CRC32 checksum over the provided input buffer. Checksum calculation in chunks is supported.
|
||||||
/// CRC32 calculation state is both read from and saved to 'crc', which should be zero during the first call to this function.
|
/// CRC32 calculation state is both read from and saved to 'crc', which should be zero during the first call to this function.
|
||||||
void crc32FastCalculate(const void *data, u64 n_bytes, u32 *crc);
|
void crc32FastCalculate(const void *data, u64 n_bytes, u32 *crc);
|
||||||
|
|
||||||
#endif /* __CRC32_FAST_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CRC32_FAST_H__ */
|
||||||
|
|
|
@ -79,6 +79,8 @@ typedef struct {
|
||||||
u16 st_shndx; ///< Holds the relevant section header table index.
|
u16 st_shndx; ///< Holds the relevant section header table index.
|
||||||
} Elf32Symbol;
|
} Elf32Symbol;
|
||||||
|
|
||||||
|
NXDT_ASSERT(Elf32Symbol, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 st_name; ///< Symbol name offset within dynamic string table.
|
u32 st_name; ///< Symbol name offset within dynamic string table.
|
||||||
u8 st_info; ///< Symbol type (lower nibble) and binding attributes (upper nibble).
|
u8 st_info; ///< Symbol type (lower nibble) and binding attributes (upper nibble).
|
||||||
|
@ -88,4 +90,6 @@ typedef struct {
|
||||||
u64 st_size; ///< Symbol size.
|
u64 st_size; ///< Symbol size.
|
||||||
} Elf64Symbol;
|
} Elf64Symbol;
|
||||||
|
|
||||||
|
NXDT_ASSERT(Elf64Symbol, 0x18);
|
||||||
|
|
||||||
#endif /* __ELF_SYMBOL_H__ */
|
#endif /* __ELF_SYMBOL_H__ */
|
||||||
|
|
12
source/es.h
12
source/es.h
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __ES_H__
|
||||||
|
#define __ES_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __ES_H__
|
|
||||||
#define __ES_H__
|
|
||||||
|
|
||||||
Result esInitialize(void);
|
Result esInitialize(void);
|
||||||
void esExit(void);
|
void esExit(void);
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ Result esCountPersonalizedTicket(s32 *out_count);
|
||||||
Result esListCommonTicket(s32 *out_entries_written, FsRightsId *out_ids, s32 count);
|
Result esListCommonTicket(s32 *out_entries_written, FsRightsId *out_ids, s32 count);
|
||||||
Result esListPersonalizedTicket(s32 *out_entries_written, FsRightsId *out_ids, s32 count);
|
Result esListPersonalizedTicket(s32 *out_entries_written, FsRightsId *out_ids, s32 count);
|
||||||
|
|
||||||
#endif /* __ES_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __ES_H__ */
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __FS_EXT_H__
|
||||||
|
#define __FS_EXT_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __FS_EXT_H__
|
|
||||||
#define __FS_EXT_H__
|
|
||||||
|
|
||||||
#define GAMECARD_CERT_MAGIC 0x43455254 /* "CERT". */
|
#define GAMECARD_CERT_MAGIC 0x43455254 /* "CERT". */
|
||||||
|
|
||||||
/// Located at offset 0x7000 in the gamecard image.
|
/// Located at offset 0x7000 in the gamecard image.
|
||||||
|
@ -41,6 +41,8 @@ typedef struct {
|
||||||
u8 encrypted_data[0xD0];
|
u8 encrypted_data[0xD0];
|
||||||
} FsGameCardCertificate;
|
} FsGameCardCertificate;
|
||||||
|
|
||||||
|
NXDT_ASSERT(FsGameCardCertificate, 0x200);
|
||||||
|
|
||||||
/// IFileSystemProxy.
|
/// IFileSystemProxy.
|
||||||
Result fsOpenGameCardStorage(FsStorage *out, const FsGameCardHandle *handle, u32 partition);
|
Result fsOpenGameCardStorage(FsStorage *out, const FsGameCardHandle *handle, u32 partition);
|
||||||
Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier *out);
|
Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier *out);
|
||||||
|
@ -49,8 +51,8 @@ Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier *out);
|
||||||
Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator *d, const FsGameCardHandle *handle, u32 *out_title_version, u64 *out_title_id);
|
Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator *d, const FsGameCardHandle *handle, u32 *out_title_version, u64 *out_title_id);
|
||||||
Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator *d, const FsGameCardHandle *handle, FsGameCardCertificate *out);
|
Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator *d, const FsGameCardHandle *handle, FsGameCardCertificate *out);
|
||||||
|
|
||||||
#endif /* __FS_EXT_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __FS_EXT_H__ */
|
||||||
|
|
|
@ -61,6 +61,8 @@ typedef struct {
|
||||||
GameCardInitialData initial_data;
|
GameCardInitialData initial_data;
|
||||||
} GameCardSecurityInformation;
|
} GameCardSecurityInformation;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardSecurityInformation, 0x600);
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
static Mutex g_gameCardMutex = 0;
|
static Mutex g_gameCardMutex = 0;
|
||||||
|
|
|
@ -20,16 +20,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __GAMECARD_H__
|
#ifndef __GAMECARD_H__
|
||||||
#define __GAMECARD_H__
|
#define __GAMECARD_H__
|
||||||
|
|
||||||
#include "fs_ext.h"
|
#include "fs_ext.h"
|
||||||
#include "hfs.h"
|
#include "hfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GAMECARD_HEAD_MAGIC 0x48454144 /* "HEAD". */
|
#define GAMECARD_HEAD_MAGIC 0x48454144 /* "HEAD". */
|
||||||
|
|
||||||
#define GAMECARD_MEDIA_UNIT_SIZE 0x200
|
#define GAMECARD_MEDIA_UNIT_SIZE 0x200
|
||||||
|
@ -45,6 +45,8 @@ typedef struct {
|
||||||
u8 reserved[0x8]; ///< Just zeroes.
|
u8 reserved[0x8]; ///< Just zeroes.
|
||||||
} GameCardKeySource;
|
} GameCardKeySource;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardKeySource, 0x10);
|
||||||
|
|
||||||
/// Plaintext area. Dumped from FS program memory.
|
/// Plaintext area. Dumped from FS program memory.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GameCardKeySource key_source;
|
GameCardKeySource key_source;
|
||||||
|
@ -54,12 +56,16 @@ typedef struct {
|
||||||
u8 reserved[0x1C4];
|
u8 reserved[0x1C4];
|
||||||
} GameCardInitialData;
|
} GameCardInitialData;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardInitialData, 0x200);
|
||||||
|
|
||||||
/// Encrypted using AES-128-CTR with the key and IV/counter from the `GameCardTitleKeyEncryption` section. Assumed to be all zeroes in retail gamecards.
|
/// Encrypted using AES-128-CTR with the key and IV/counter from the `GameCardTitleKeyEncryption` section. Assumed to be all zeroes in retail gamecards.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 titlekey[0x10]; ///< Decrypted titlekey from the `GameCardInitialData` section.
|
u8 titlekey[0x10]; ///< Decrypted titlekey from the `GameCardInitialData` section.
|
||||||
u8 reserved[0xCF0];
|
u8 reserved[0xCF0];
|
||||||
} GameCardTitleKey;
|
} GameCardTitleKey;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardTitleKey, 0xD00);
|
||||||
|
|
||||||
/// Encrypted using RSA-2048-OAEP and a private OAEP key from AuthoringTool. Assumed to be all zeroes in retail gamecards.
|
/// Encrypted using RSA-2048-OAEP and a private OAEP key from AuthoringTool. Assumed to be all zeroes in retail gamecards.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 titlekey_encryption_key[0x10]; ///< Used as the AES-128-CTR key for the `GameCardTitleKey` section. Randomly generated during XCI creation by AuthoringTool.
|
u8 titlekey_encryption_key[0x10]; ///< Used as the AES-128-CTR key for the `GameCardTitleKey` section. Randomly generated during XCI creation by AuthoringTool.
|
||||||
|
@ -67,6 +73,8 @@ typedef struct {
|
||||||
u8 reserved[0xE0];
|
u8 reserved[0xE0];
|
||||||
} GameCardTitleKeyEncryption;
|
} GameCardTitleKeyEncryption;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardTitleKeyEncryption, 0x100);
|
||||||
|
|
||||||
/// Used to secure communications between the Lotus and the inserted gamecard.
|
/// Used to secure communications between the Lotus and the inserted gamecard.
|
||||||
/// Precedes the gamecard header.
|
/// Precedes the gamecard header.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -75,6 +83,8 @@ typedef struct {
|
||||||
GameCardTitleKeyEncryption titlekey_encryption;
|
GameCardTitleKeyEncryption titlekey_encryption;
|
||||||
} GameCardKeyArea;
|
} GameCardKeyArea;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardKeyArea, 0x1000);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GameCardKekIndex_Version0 = 0,
|
GameCardKekIndex_Version0 = 0,
|
||||||
GameCardKekIndex_VersionForDev = 1
|
GameCardKekIndex_VersionForDev = 1
|
||||||
|
@ -85,6 +95,8 @@ typedef struct {
|
||||||
u8 titlekey_dec_index : 4;
|
u8 titlekey_dec_index : 4;
|
||||||
} GameCardKeyIndex;
|
} GameCardKeyIndex;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardKeyIndex, 0x1);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GameCardRomSize_1GiB = 0xFA,
|
GameCardRomSize_1GiB = 0xFA,
|
||||||
GameCardRomSize_2GiB = 0xF8,
|
GameCardRomSize_2GiB = 0xF8,
|
||||||
|
@ -144,6 +156,8 @@ typedef struct {
|
||||||
u8 reserved_2[0x38];
|
u8 reserved_2[0x38];
|
||||||
} GameCardHeaderEncryptedArea;
|
} GameCardHeaderEncryptedArea;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardHeaderEncryptedArea, 0x70);
|
||||||
|
|
||||||
/// Placed after the `GameCardKeyArea` section.
|
/// Placed after the `GameCardKeyArea` section.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the header.
|
u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the header.
|
||||||
|
@ -169,6 +183,8 @@ typedef struct {
|
||||||
GameCardHeaderEncryptedArea encrypted_area;
|
GameCardHeaderEncryptedArea encrypted_area;
|
||||||
} GameCardHeader;
|
} GameCardHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(GameCardHeader, 0x200);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GameCardStatus_NotInserted = 0,
|
GameCardStatus_NotInserted = 0,
|
||||||
GameCardStatus_InsertedAndInfoNotLoaded = 1, ///< Most likely related to the "nogc" patch being enabled. Means nothing at all can be done with the inserted gamecard.
|
GameCardStatus_InsertedAndInfoNotLoaded = 1, ///< Most likely related to the "nogc" patch being enabled. Means nothing at all can be done with the inserted gamecard.
|
||||||
|
@ -238,8 +254,8 @@ bool gamecardGetHashFileSystemContext(u8 hfs_partition_type, HashFileSystemConte
|
||||||
/// If you need to get entry information by index, just retrieve the Hash FS context for the target partition and use Hash FS functions on it.
|
/// If you need to get entry information by index, just retrieve the Hash FS context for the target partition and use Hash FS functions on it.
|
||||||
bool gamecardGetHashFileSystemEntryInfoByName(u8 hfs_partition_type, const char *entry_name, u64 *out_offset, u64 *out_size);
|
bool gamecardGetHashFileSystemEntryInfoByName(u8 hfs_partition_type, const char *entry_name, u64 *out_offset, u64 *out_size);
|
||||||
|
|
||||||
#endif /* __GAMECARD_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __GAMECARD_H__ */
|
||||||
|
|
16
source/hfs.h
16
source/hfs.h
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __HFS_H__
|
||||||
|
#define __HFS_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __HFS_H__
|
|
||||||
#define __HFS_H__
|
|
||||||
|
|
||||||
#define HFS0_MAGIC 0x48465330 /* "HFS0". */
|
#define HFS0_MAGIC 0x48465330 /* "HFS0". */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -36,6 +36,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} HashFileSystemHeader;
|
} HashFileSystemHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(HashFileSystemHeader, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
@ -45,6 +47,8 @@ typedef struct {
|
||||||
u8 hash[SHA256_HASH_SIZE];
|
u8 hash[SHA256_HASH_SIZE];
|
||||||
} HashFileSystemEntry;
|
} HashFileSystemEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(HashFileSystemEntry, 0x40);
|
||||||
|
|
||||||
/// Internally used by gamecard functions.
|
/// Internally used by gamecard functions.
|
||||||
/// Use gamecardGetHashFileSystemContext() to retrieve a Hash FS context.
|
/// Use gamecardGetHashFileSystemContext() to retrieve a Hash FS context.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -121,8 +125,8 @@ NX_INLINE HashFileSystemEntry *hfsGetEntryByName(HashFileSystemContext *ctx, con
|
||||||
return hfsGetEntryByIndex(ctx, idx);
|
return hfsGetEntryByIndex(ctx, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __HFS_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __HFS_H__ */
|
||||||
|
|
|
@ -22,13 +22,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __KEYS_H__
|
||||||
|
#define __KEYS_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __KEYS_H__
|
|
||||||
#define __KEYS_H__
|
|
||||||
|
|
||||||
bool keysLoadNcaKeyset(void);
|
bool keysLoadNcaKeyset(void);
|
||||||
|
|
||||||
const u8 *keysGetNcaHeaderKey(void);
|
const u8 *keysGetNcaHeaderKey(void);
|
||||||
|
@ -37,8 +37,8 @@ const u8 *keysGetEticketRsaKek(bool personalized);
|
||||||
const u8 *keysGetTitlekek(u8 key_generation);
|
const u8 *keysGetTitlekek(u8 key_generation);
|
||||||
const u8 *keysGetKeyAreaEncryptionKey(u8 key_generation, u8 kaek_index);
|
const u8 *keysGetKeyAreaEncryptionKey(u8 key_generation, u8 kaek_index);
|
||||||
|
|
||||||
#endif /* __KEYS_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __KEYS_H__ */
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __LEGAL_INFO_H__
|
#ifndef __LEGAL_INFO_H__
|
||||||
#define __LEGAL_INFO_H__
|
#define __LEGAL_INFO_H__
|
||||||
|
|
||||||
#include "nca.h"
|
#include "nca.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaContext *nca_ctx; ///< Pointer to the NCA context for the LegalInformation NCA from which XML data is retrieved.
|
NcaContext *nca_ctx; ///< Pointer to the NCA context for the LegalInformation NCA from which XML data is retrieved.
|
||||||
char *authoring_tool_xml; ///< Pointer to a dynamically allocated, NULL-terminated buffer that holds AuthoringTool-like XML data.
|
char *authoring_tool_xml; ///< Pointer to a dynamically allocated, NULL-terminated buffer that holds AuthoringTool-like XML data.
|
||||||
|
@ -47,8 +47,8 @@ NX_INLINE void legalInfoFreeContext(LegalInfoContext *legal_info_ctx)
|
||||||
memset(legal_info_ctx, 0, sizeof(LegalInfoContext));
|
memset(legal_info_ctx, 0, sizeof(LegalInfoContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __LEGAL_INFO_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LEGAL_INFO_H__ */
|
||||||
|
|
12
source/log.h
12
source/log.h
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __LOG_H__
|
||||||
|
#define __LOG_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __LOG_H__
|
|
||||||
#define __LOG_H__
|
|
||||||
|
|
||||||
/// Helper macros.
|
/// Helper macros.
|
||||||
#define LOG_MSG(fmt, ...) logWriteFormattedStringToLogFile(__func__, fmt, ##__VA_ARGS__)
|
#define LOG_MSG(fmt, ...) logWriteFormattedStringToLogFile(__func__, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_MSG_BUF(dst, dst_size, fmt, ...) logWriteFormattedStringToBuffer(dst, dst_size, __func__, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF(dst, dst_size, fmt, ...) logWriteFormattedStringToBuffer(dst, dst_size, __func__, fmt, ##__VA_ARGS__)
|
||||||
|
@ -58,8 +58,8 @@ void logGetLastMessage(char *dst, size_t dst_size);
|
||||||
/// Use with caution.
|
/// Use with caution.
|
||||||
void logControlMutex(bool lock);
|
void logControlMutex(bool lock);
|
||||||
|
|
||||||
#endif /* __LOG_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LOG_H__ */
|
||||||
|
|
12
source/mem.h
12
source/mem.h
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __MEM_H__
|
||||||
|
#define __MEM_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __MEM_H__
|
|
||||||
#define __MEM_H__
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MemoryProgramSegmentType_Text = BIT(0),
|
MemoryProgramSegmentType_Text = BIT(0),
|
||||||
MemoryProgramSegmentType_Rodata = BIT(1),
|
MemoryProgramSegmentType_Rodata = BIT(1),
|
||||||
|
@ -59,8 +59,8 @@ NX_INLINE void memFreeMemoryLocation(MemoryLocation *location)
|
||||||
location->data_size = 0;
|
location->data_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __MEM_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __MEM_H__ */
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __NACP_H__
|
#ifndef __NACP_H__
|
||||||
#define __NACP_H__
|
#define __NACP_H__
|
||||||
|
|
||||||
#include "romfs.h"
|
#include "romfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NACP_MAX_ICON_SIZE 0x20000 /* 128 KiB. */
|
#define NACP_MAX_ICON_SIZE 0x20000 /* 128 KiB. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -36,6 +36,8 @@ typedef struct {
|
||||||
char publisher[0x100];
|
char publisher[0x100];
|
||||||
} NacpTitle;
|
} NacpTitle;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpTitle, 0x300);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NacpStartupUserAccount_None = 0,
|
NacpStartupUserAccount_None = 0,
|
||||||
NacpStartupUserAccount_Required = 1,
|
NacpStartupUserAccount_Required = 1,
|
||||||
|
@ -180,6 +182,8 @@ typedef struct {
|
||||||
s8 reserved[0x13];
|
s8 reserved[0x13];
|
||||||
} NacpRatingAge;
|
} NacpRatingAge;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpRatingAge, 0x20);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NacpLogoType_LicensedByNintendo = 0,
|
NacpLogoType_LicensedByNintendo = 0,
|
||||||
NacpLogoType_DistributedByNintendo = 1, ///< Removed.
|
NacpLogoType_DistributedByNintendo = 1, ///< Removed.
|
||||||
|
@ -252,15 +256,21 @@ typedef struct {
|
||||||
u64 memory_size;
|
u64 memory_size;
|
||||||
} NacpJitConfiguration;
|
} NacpJitConfiguration;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpJitConfiguration, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 index : 15;
|
u16 index : 15;
|
||||||
u16 continue_set : 1; ///< Called "flag" by Nintendo, which isn't really great.
|
u16 continue_set : 1; ///< Called "flag" by Nintendo, which isn't really great.
|
||||||
} NacpDescriptors;
|
} NacpDescriptors;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpDescriptors, 0x2);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NacpDescriptors descriptors[0x20];
|
NacpDescriptors descriptors[0x20];
|
||||||
} NacpRequiredAddOnContentsSetBinaryDescriptor;
|
} NacpRequiredAddOnContentsSetBinaryDescriptor;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpRequiredAddOnContentsSetBinaryDescriptor, 0x40);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NacpPlayReportPermission_None = 0,
|
NacpPlayReportPermission_None = 0,
|
||||||
NacpPlayReportPermission_TargetMarketing = 1,
|
NacpPlayReportPermission_TargetMarketing = 1,
|
||||||
|
@ -283,6 +293,8 @@ typedef struct {
|
||||||
u64 application_id[8];
|
u64 application_id[8];
|
||||||
} NacpAccessibleLaunchRequiredVersion;
|
} NacpAccessibleLaunchRequiredVersion;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NacpAccessibleLaunchRequiredVersion, 0x40);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NacpTitle title[0x10];
|
NacpTitle title[0x10];
|
||||||
char isbn[0x25];
|
char isbn[0x25];
|
||||||
|
@ -346,6 +358,8 @@ typedef struct {
|
||||||
u8 reserved_6[0xBB8];
|
u8 reserved_6[0xBB8];
|
||||||
} _NacpStruct;
|
} _NacpStruct;
|
||||||
|
|
||||||
|
NXDT_ASSERT(_NacpStruct, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 language; ///< NacpLanguage.
|
u8 language; ///< NacpLanguage.
|
||||||
u64 icon_size; ///< JPG icon size. Must not exceed NACP_MAX_ICON_SIZE.
|
u64 icon_size; ///< JPG icon size. Must not exceed NACP_MAX_ICON_SIZE.
|
||||||
|
@ -455,8 +469,8 @@ NX_INLINE bool nacpIsValidContext(NacpContext *nacp_ctx)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __NACP_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NACP_H__ */
|
||||||
|
|
50
source/nca.h
50
source/nca.h
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __NCA_H__
|
#ifndef __NCA_H__
|
||||||
#define __NCA_H__
|
#define __NCA_H__
|
||||||
|
|
||||||
#include "tik.h"
|
#include "tik.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NCA_FS_HEADER_COUNT 4
|
#define NCA_FS_HEADER_COUNT 4
|
||||||
#define NCA_FULL_HEADER_LENGTH (sizeof(NcaHeader) + (sizeof(NcaFsHeader) * NCA_FS_HEADER_COUNT))
|
#define NCA_FULL_HEADER_LENGTH (sizeof(NcaHeader) + (sizeof(NcaFsHeader) * NCA_FS_HEADER_COUNT))
|
||||||
|
|
||||||
|
@ -100,10 +100,14 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} NcaFsInfo;
|
} NcaFsInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaFsInfo, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 hash[SHA256_HASH_SIZE];
|
u8 hash[SHA256_HASH_SIZE];
|
||||||
} NcaFsHeaderHash;
|
} NcaFsHeaderHash;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaFsHeaderHash, 0x20);
|
||||||
|
|
||||||
/// Encrypted NCA key area used to hold NCA FS section encryption keys. Zeroed out if the NCA uses titlekey crypto.
|
/// Encrypted NCA key area used to hold NCA FS section encryption keys. Zeroed out if the NCA uses titlekey crypto.
|
||||||
/// Only the first 4 key entries are encrypted.
|
/// Only the first 4 key entries are encrypted.
|
||||||
/// If a particular key entry is unused, it is zeroed out before this area is encrypted.
|
/// If a particular key entry is unused, it is zeroed out before this area is encrypted.
|
||||||
|
@ -116,6 +120,8 @@ typedef struct {
|
||||||
u8 reserved[0xB0];
|
u8 reserved[0xB0];
|
||||||
} NcaEncryptedKeyArea;
|
} NcaEncryptedKeyArea;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaEncryptedKeyArea, 0x100);
|
||||||
|
|
||||||
/// First 0x400 bytes from every NCA.
|
/// First 0x400 bytes from every NCA.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 main_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using a fixed key.
|
u8 main_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using a fixed key.
|
||||||
|
@ -138,6 +144,8 @@ typedef struct {
|
||||||
NcaEncryptedKeyArea encrypted_key_area;
|
NcaEncryptedKeyArea encrypted_key_area;
|
||||||
} NcaHeader;
|
} NcaHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaHeader, 0x400);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NcaFsType_RomFs = 0,
|
NcaFsType_RomFs = 0,
|
||||||
NcaFsType_PartitionFs = 1
|
NcaFsType_PartitionFs = 1
|
||||||
|
@ -163,6 +171,8 @@ typedef struct {
|
||||||
u64 size;
|
u64 size;
|
||||||
} NcaRegion;
|
} NcaRegion;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaRegion, 0x10);
|
||||||
|
|
||||||
/// Used by NcaFsType_PartitionFs and NCA0 NcaFsType_RomFs.
|
/// Used by NcaFsType_PartitionFs and NCA0 NcaFsType_RomFs.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 master_hash[SHA256_HASH_SIZE];
|
u8 master_hash[SHA256_HASH_SIZE];
|
||||||
|
@ -171,6 +181,8 @@ typedef struct {
|
||||||
NcaRegion hash_region[NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT];
|
NcaRegion hash_region[NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT];
|
||||||
} NcaHierarchicalSha256Data;
|
} NcaHierarchicalSha256Data;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaHierarchicalSha256Data, 0x78);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
@ -178,10 +190,14 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} NcaHierarchicalIntegrityVerificationLevelInformation;
|
} NcaHierarchicalIntegrityVerificationLevelInformation;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaHierarchicalIntegrityVerificationLevelInformation, 0x18);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 value[0x20];
|
u8 value[0x20];
|
||||||
} NcaSignatureSalt;
|
} NcaSignatureSalt;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaSignatureSalt, 0x20);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 max_level_count; ///< Always NCA_IVFC_MAX_LEVEL_COUNT.
|
u32 max_level_count; ///< Always NCA_IVFC_MAX_LEVEL_COUNT.
|
||||||
|
@ -190,6 +206,8 @@ typedef struct {
|
||||||
} NcaInfoLevelHash;
|
} NcaInfoLevelHash;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaInfoLevelHash, 0xB4);
|
||||||
|
|
||||||
/// Used by NcaFsType_RomFs.
|
/// Used by NcaFsType_RomFs.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; ///< "IVFC".
|
u32 magic; ///< "IVFC".
|
||||||
|
@ -199,6 +217,8 @@ typedef struct {
|
||||||
u8 master_hash[SHA256_HASH_SIZE];
|
u8 master_hash[SHA256_HASH_SIZE];
|
||||||
} NcaIntegrityMetaInfo;
|
} NcaIntegrityMetaInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaIntegrityMetaInfo, 0xE0);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -214,6 +234,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} NcaHashData;
|
} NcaHashData;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaHashData, 0xF8);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; ///< "BKTR".
|
u32 magic; ///< "BKTR".
|
||||||
u32 version; ///< offset_count / node_count ?
|
u32 version; ///< offset_count / node_count ?
|
||||||
|
@ -221,18 +243,24 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} NcaBucketTreeHeader;
|
} NcaBucketTreeHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaBucketTreeHeader, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
NcaBucketTreeHeader header;
|
NcaBucketTreeHeader header;
|
||||||
} NcaBucketInfo;
|
} NcaBucketInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaBucketInfo, 0x20);
|
||||||
|
|
||||||
/// Only used for NcaEncryptionType_AesCtrEx (PatchRomFs).
|
/// Only used for NcaEncryptionType_AesCtrEx (PatchRomFs).
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaBucketInfo indirect_bucket;
|
NcaBucketInfo indirect_bucket;
|
||||||
NcaBucketInfo aes_ctr_ex_bucket;
|
NcaBucketInfo aes_ctr_ex_bucket;
|
||||||
} NcaPatchInfo;
|
} NcaPatchInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaPatchInfo, 0x40);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
u8 value[0x8];
|
u8 value[0x8];
|
||||||
|
@ -243,6 +271,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} NcaAesCtrUpperIv;
|
} NcaAesCtrUpperIv;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaAesCtrUpperIv, 0x8);
|
||||||
|
|
||||||
/// Used in NCAs with sparse storage.
|
/// Used in NCAs with sparse storage.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaBucketInfo sparse_bucket;
|
NcaBucketInfo sparse_bucket;
|
||||||
|
@ -251,6 +281,8 @@ typedef struct {
|
||||||
u8 reserved[0x6];
|
u8 reserved[0x6];
|
||||||
} NcaSparseInfo;
|
} NcaSparseInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaSparseInfo, 0x30);
|
||||||
|
|
||||||
/// Four NCA FS headers are placed right after the 0x400 byte long NCA header in NCA2 and NCA3.
|
/// Four NCA FS headers are placed right after the 0x400 byte long NCA header in NCA2 and NCA3.
|
||||||
/// NCA0 place the FS headers at the start sector from the NcaFsInfo entries.
|
/// NCA0 place the FS headers at the start sector from the NcaFsInfo entries.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -266,6 +298,8 @@ typedef struct {
|
||||||
u8 reserved_2[0x88];
|
u8 reserved_2[0x88];
|
||||||
} NcaFsHeader;
|
} NcaFsHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaFsHeader, 0x200);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NcaFsSectionType_PartitionFs = 0, ///< NcaFsType_PartitionFs + NcaHashType_HierarchicalSha256.
|
NcaFsSectionType_PartitionFs = 0, ///< NcaFsType_PartitionFs + NcaHashType_HierarchicalSha256.
|
||||||
NcaFsSectionType_RomFs = 1, ///< NcaFsType_RomFs + NcaHashType_HierarchicalIntegrity.
|
NcaFsSectionType_RomFs = 1, ///< NcaFsType_RomFs + NcaHashType_HierarchicalIntegrity.
|
||||||
|
@ -307,6 +341,8 @@ typedef struct {
|
||||||
u8 aes_ctr_ex[AES_128_KEY_SIZE]; ///< AES-128-CTR key used for NCA FS sections with NcaEncryptionType_AesCtrEx crypto.
|
u8 aes_ctr_ex[AES_128_KEY_SIZE]; ///< AES-128-CTR key used for NCA FS sections with NcaEncryptionType_AesCtrEx crypto.
|
||||||
} NcaDecryptedKeyArea;
|
} NcaDecryptedKeyArea;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NcaDecryptedKeyArea, 0x40);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 storage_id; ///< NcmStorageId.
|
u8 storage_id; ///< NcmStorageId.
|
||||||
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data from eMMC/SD.
|
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data from eMMC/SD.
|
||||||
|
@ -497,8 +533,8 @@ NX_INLINE void ncaFreeHierarchicalIntegrityPatch(NcaHierarchicalIntegrityPatch *
|
||||||
memset(patch, 0, sizeof(NcaHierarchicalIntegrityPatch));
|
memset(patch, 0, sizeof(NcaHierarchicalIntegrityPatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __NCA_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NCA_H__ */
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __NPDM_H__
|
#ifndef __NPDM_H__
|
||||||
#define __NPDM_H__
|
#define __NPDM_H__
|
||||||
|
|
||||||
#include "pfs.h"
|
#include "pfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NPDM_META_MAGIC 0x4D455441 /* "META". */
|
#define NPDM_META_MAGIC 0x4D455441 /* "META". */
|
||||||
#define NPDM_ACID_MAGIC 0x41434944 /* "ACID". */
|
#define NPDM_ACID_MAGIC 0x41434944 /* "ACID". */
|
||||||
#define NPDM_ACI0_MAGIC 0x41434930 /* "ACI0". */
|
#define NPDM_ACI0_MAGIC 0x41434930 /* "ACI0". */
|
||||||
|
@ -53,6 +53,8 @@ typedef struct {
|
||||||
u8 reserved : 2;
|
u8 reserved : 2;
|
||||||
} NpdmMetaFlags;
|
} NpdmMetaFlags;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMetaFlags, 0x1);
|
||||||
|
|
||||||
/// This is the start of every NPDM file.
|
/// This is the start of every NPDM file.
|
||||||
/// This is followed by ACID and ACI0 sections, both with variable offsets and sizes.
|
/// This is followed by ACID and ACI0 sections, both with variable offsets and sizes.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -76,6 +78,8 @@ typedef struct {
|
||||||
u32 acid_size;
|
u32 acid_size;
|
||||||
} NpdmMetaHeader;
|
} NpdmMetaHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMetaHeader, 0x80);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmMemoryRegion_Application = 0,
|
NpdmMemoryRegion_Application = 0,
|
||||||
NpdmMemoryRegion_Applet = 1,
|
NpdmMemoryRegion_Applet = 1,
|
||||||
|
@ -94,6 +98,8 @@ typedef struct {
|
||||||
u32 reserved : 28;
|
u32 reserved : 28;
|
||||||
} NpdmAcidFlags;
|
} NpdmAcidFlags;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmAcidFlags, 0x4);
|
||||||
|
|
||||||
/// This is the start of an ACID section.
|
/// This is the start of an ACID section.
|
||||||
/// This is followed by FsAccessControl, SrvAccessControl and KernelCapability descriptors, each one aligned to a 0x10 byte boundary using zero padding (if needed).
|
/// This is followed by FsAccessControl, SrvAccessControl and KernelCapability descriptors, each one aligned to a 0x10 byte boundary using zero padding (if needed).
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -114,6 +120,8 @@ typedef struct {
|
||||||
u8 reserved_2[0x8];
|
u8 reserved_2[0x8];
|
||||||
} NpdmAcidHeader;
|
} NpdmAcidHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmAcidHeader, 0x240);
|
||||||
|
|
||||||
/// This is the start of an ACI0 section.
|
/// This is the start of an ACI0 section.
|
||||||
/// This is followed by a FsAccessControl data block, as well as SrvAccessControl and KernelCapability descriptors, each one aligned to a 0x10 byte boundary using zero padding (if needed).
|
/// This is followed by a FsAccessControl data block, as well as SrvAccessControl and KernelCapability descriptors, each one aligned to a 0x10 byte boundary using zero padding (if needed).
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -130,6 +138,8 @@ typedef struct {
|
||||||
u8 reserved_3[0x8];
|
u8 reserved_3[0x8];
|
||||||
} NpdmAciHeader;
|
} NpdmAciHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmAciHeader, 0x40);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmFsAccessControlFlags_ApplicationInfo = BIT_LONG(0),
|
NpdmFsAccessControlFlags_ApplicationInfo = BIT_LONG(0),
|
||||||
NpdmFsAccessControlFlags_BootModeControl = BIT_LONG(1),
|
NpdmFsAccessControlFlags_BootModeControl = BIT_LONG(1),
|
||||||
|
@ -190,6 +200,8 @@ typedef struct {
|
||||||
} NpdmFsAccessControlDescriptor;
|
} NpdmFsAccessControlDescriptor;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmFsAccessControlDescriptor, 0x2C);
|
||||||
|
|
||||||
/// FsAccessControl data. Part of the ACI0 section body.
|
/// FsAccessControl data. Part of the ACI0 section body.
|
||||||
/// This is followed by:
|
/// This is followed by:
|
||||||
/// * A NpdmFsAccessControlDataContentOwnerBlock if 'content_owner_info_size' is greater than zero.
|
/// * A NpdmFsAccessControlDataContentOwnerBlock if 'content_owner_info_size' is greater than zero.
|
||||||
|
@ -207,11 +219,17 @@ typedef struct {
|
||||||
} NpdmFsAccessControlData;
|
} NpdmFsAccessControlData;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmFsAccessControlData, 0x1C);
|
||||||
|
|
||||||
/// Placed after NpdmFsAccessControlData if its 'content_owner_info_size' member is greater than zero.
|
/// Placed after NpdmFsAccessControlData if its 'content_owner_info_size' member is greater than zero.
|
||||||
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 content_owner_id_count;
|
u32 content_owner_id_count;
|
||||||
u64 content_owner_id[]; ///< 'content_owner_id_count' content owned IDs.
|
u64 content_owner_id[]; ///< 'content_owner_id_count' content owned IDs.
|
||||||
} NpdmFsAccessControlDataContentOwnerBlock;
|
} NpdmFsAccessControlDataContentOwnerBlock;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmFsAccessControlDataContentOwnerBlock, 0x4);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmAccessibility_Read = BIT(0),
|
NpdmAccessibility_Read = BIT(0),
|
||||||
|
@ -225,6 +243,8 @@ typedef struct {
|
||||||
u8 accessibility[]; ///< 'save_data_owner_id_count' NpdmAccessibility fields.
|
u8 accessibility[]; ///< 'save_data_owner_id_count' NpdmAccessibility fields.
|
||||||
} NpdmFsAccessControlDataSaveDataOwnerBlock;
|
} NpdmFsAccessControlDataSaveDataOwnerBlock;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmFsAccessControlDataSaveDataOwnerBlock, 0x4);
|
||||||
|
|
||||||
/// SrvAccessControl descriptor. Part of the ACID and ACI0 section bodies.
|
/// SrvAccessControl descriptor. Part of the ACID and ACI0 section bodies.
|
||||||
/// This descriptor is composed of a variable number of NpdmSrvAccessControlDescriptorEntry elements, each one with a variable size.
|
/// This descriptor is composed of a variable number of NpdmSrvAccessControlDescriptorEntry elements, each one with a variable size.
|
||||||
/// Since the total number of services isn't stored anywhere, this descriptor must be parsed until its total size is reached.
|
/// Since the total number of services isn't stored anywhere, this descriptor must be parsed until its total size is reached.
|
||||||
|
@ -235,6 +255,8 @@ typedef struct {
|
||||||
char name[]; ///< Service name, stored without a NULL terminator. Supports the "*" wildcard character.
|
char name[]; ///< Service name, stored without a NULL terminator. Supports the "*" wildcard character.
|
||||||
} NpdmSrvAccessControlDescriptorEntry;
|
} NpdmSrvAccessControlDescriptorEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmSrvAccessControlDescriptorEntry, 0x1);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmKernelCapabilityEntryNumber_ThreadInfo = 3,
|
NpdmKernelCapabilityEntryNumber_ThreadInfo = 3,
|
||||||
NpdmKernelCapabilityEntryNumber_EnableSystemCalls = 4,
|
NpdmKernelCapabilityEntryNumber_EnableSystemCalls = 4,
|
||||||
|
@ -271,6 +293,8 @@ typedef struct {
|
||||||
u32 max_core_number : 8;
|
u32 max_core_number : 8;
|
||||||
} NpdmThreadInfo;
|
} NpdmThreadInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmThreadInfo, 0x4);
|
||||||
|
|
||||||
/// System call table.
|
/// System call table.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
///< System calls for index 0.
|
///< System calls for index 0.
|
||||||
|
@ -423,6 +447,8 @@ typedef struct {
|
||||||
u32 index : 3; ///< System calls index.
|
u32 index : 3; ///< System calls index.
|
||||||
} NpdmEnableSystemCalls;
|
} NpdmEnableSystemCalls;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmEnableSystemCalls, 0x4);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmPermissionType_RW = 0,
|
NpdmPermissionType_RW = 0,
|
||||||
NpdmPermissionType_RO = 1
|
NpdmPermissionType_RO = 1
|
||||||
|
@ -440,6 +466,8 @@ typedef struct {
|
||||||
u32 permission_type : 1; ///< NpdmPermissionType.
|
u32 permission_type : 1; ///< NpdmPermissionType.
|
||||||
} NpdmMemoryMapType1;
|
} NpdmMemoryMapType1;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMemoryMapType1, 0x4);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryMap.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryMap.
|
||||||
u32 padding : 1; ///< Always set to zero.
|
u32 padding : 1; ///< Always set to zero.
|
||||||
|
@ -448,6 +476,8 @@ typedef struct {
|
||||||
u32 mapping_type : 1; ///< NpdmMappingType.
|
u32 mapping_type : 1; ///< NpdmMappingType.
|
||||||
} NpdmMemoryMapType2;
|
} NpdmMemoryMapType2;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMemoryMapType2, 0x4);
|
||||||
|
|
||||||
/// MemoryMap entry for the KernelCapability descriptor.
|
/// MemoryMap entry for the KernelCapability descriptor.
|
||||||
/// These are always stored in pairs of MemoryMapType1 + MemoryMapType2 entries.
|
/// These are always stored in pairs of MemoryMapType1 + MemoryMapType2 entries.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -457,6 +487,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} NpdmMemoryMap;
|
} NpdmMemoryMap;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMemoryMap, 0x4);
|
||||||
|
|
||||||
/// IoMemoryMap entry for the KernelCapability descriptor.
|
/// IoMemoryMap entry for the KernelCapability descriptor.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_IoMemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_IoMemoryMap.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_IoMemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_IoMemoryMap.
|
||||||
|
@ -464,6 +496,8 @@ typedef struct {
|
||||||
u32 begin_address : 24; ///< begin_address << 12.
|
u32 begin_address : 24; ///< begin_address << 12.
|
||||||
} NpdmIoMemoryMap;
|
} NpdmIoMemoryMap;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmIoMemoryMap, 0x4);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmRegionType_NoMapping = 0,
|
NpdmRegionType_NoMapping = 0,
|
||||||
NpdmRegionType_KernelTraceBuffer = 1,
|
NpdmRegionType_KernelTraceBuffer = 1,
|
||||||
|
@ -483,6 +517,8 @@ typedef struct {
|
||||||
u32 permission_type_3 : 1; ///< NpdmPermissionType.
|
u32 permission_type_3 : 1; ///< NpdmPermissionType.
|
||||||
} NpdmMemoryRegionMap;
|
} NpdmMemoryRegionMap;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMemoryRegionMap, 0x4);
|
||||||
|
|
||||||
/// EnableInterrupts entry for the KernelCapability descriptor.
|
/// EnableInterrupts entry for the KernelCapability descriptor.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_EnableInterrupts; ///< Always set to NpdmKernelCapabilityEntryValue_EnableInterrupts.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_EnableInterrupts; ///< Always set to NpdmKernelCapabilityEntryValue_EnableInterrupts.
|
||||||
|
@ -491,6 +527,8 @@ typedef struct {
|
||||||
u32 interrupt_number_2 : 10; ///< 0x3FF means empty.
|
u32 interrupt_number_2 : 10; ///< 0x3FF means empty.
|
||||||
} NpdmEnableInterrupts;
|
} NpdmEnableInterrupts;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmEnableInterrupts, 0x4);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NpdmProgramType_System = 0,
|
NpdmProgramType_System = 0,
|
||||||
NpdmProgramType_Application = 1,
|
NpdmProgramType_Application = 1,
|
||||||
|
@ -506,6 +544,8 @@ typedef struct {
|
||||||
u32 reserved : 15;
|
u32 reserved : 15;
|
||||||
} NpdmMiscParams;
|
} NpdmMiscParams;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMiscParams, 0x4);
|
||||||
|
|
||||||
/// KernelVersion entry for the KernelCapability descriptor.
|
/// KernelVersion entry for the KernelCapability descriptor.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_KernelVersion; ///< Always set to NpdmKernelCapabilityEntryValue_KernelVersion.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_KernelVersion; ///< Always set to NpdmKernelCapabilityEntryValue_KernelVersion.
|
||||||
|
@ -514,6 +554,8 @@ typedef struct {
|
||||||
u32 major_version : 13;
|
u32 major_version : 13;
|
||||||
} NpdmKernelVersion;
|
} NpdmKernelVersion;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmKernelVersion, 0x4);
|
||||||
|
|
||||||
/// HandleTableSize entry for the KernelCapability descriptor.
|
/// HandleTableSize entry for the KernelCapability descriptor.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_HandleTableSize; ///< Always set to NpdmKernelCapabilityEntryValue_HandleTableSize.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_HandleTableSize; ///< Always set to NpdmKernelCapabilityEntryValue_HandleTableSize.
|
||||||
|
@ -522,6 +564,8 @@ typedef struct {
|
||||||
u32 reserved : 6;
|
u32 reserved : 6;
|
||||||
} NpdmHandleTableSize;
|
} NpdmHandleTableSize;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmHandleTableSize, 0x4);
|
||||||
|
|
||||||
/// MiscFlags entry for the KernelCapability descriptor.
|
/// MiscFlags entry for the KernelCapability descriptor.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscFlags; ///< Always set to NpdmKernelCapabilityEntryValue_MiscFlags.
|
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscFlags; ///< Always set to NpdmKernelCapabilityEntryValue_MiscFlags.
|
||||||
|
@ -531,6 +575,8 @@ typedef struct {
|
||||||
u32 reserved : 13;
|
u32 reserved : 13;
|
||||||
} NpdmMiscFlags;
|
} NpdmMiscFlags;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmMiscFlags, 0x4);
|
||||||
|
|
||||||
/// KernelCapability descriptor. Part of the ACID and ACI0 section bodies.
|
/// KernelCapability descriptor. Part of the ACID and ACI0 section bodies.
|
||||||
/// This descriptor is composed of a variable number of u32 entries. Thus, the entry count can be calculated by dividing the KernelCapability descriptor size by 4.
|
/// This descriptor is composed of a variable number of u32 entries. Thus, the entry count can be calculated by dividing the KernelCapability descriptor size by 4.
|
||||||
/// The entry type is identified by a pattern of "01...11" (zero followed by ones) in the low u16, counting from the LSB. The variable number of ones must never exceed 16 (entirety of the low u16).
|
/// The entry type is identified by a pattern of "01...11" (zero followed by ones) in the low u16, counting from the LSB. The variable number of ones must never exceed 16 (entirety of the low u16).
|
||||||
|
@ -538,6 +584,8 @@ typedef struct {
|
||||||
u32 value;
|
u32 value;
|
||||||
} NpdmKernelCapabilityDescriptorEntry;
|
} NpdmKernelCapabilityDescriptorEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NpdmKernelCapabilityDescriptorEntry, 0x4);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which NPDM data is retrieved.
|
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which NPDM data is retrieved.
|
||||||
PartitionFileSystemContext *pfs_ctx; ///< PartitionFileSystemContext for the Program NCA FS section #0, which is where the NPDM is stored.
|
PartitionFileSystemContext *pfs_ctx; ///< PartitionFileSystemContext for the Program NCA FS section #0, which is where the NPDM is stored.
|
||||||
|
@ -592,8 +640,8 @@ NX_INLINE u32 npdmGetKernelCapabilityDescriptorEntryValue(NpdmKernelCapabilityDe
|
||||||
return (entry ? (((entry->value + 1) & ~entry->value) - 1) : 0);
|
return (entry ? (((entry->value + 1) & ~entry->value) - 1) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __NPDM_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NPDM_H__ */
|
||||||
|
|
34
source/nso.h
34
source/nso.h
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __NSO_H__
|
#ifndef __NSO_H__
|
||||||
#define __NSO_H__
|
#define __NSO_H__
|
||||||
|
|
||||||
#include "pfs.h"
|
#include "pfs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NSO_HEADER_MAGIC 0x4E534F30 /* "NSO0". */
|
#define NSO_HEADER_MAGIC 0x4E534F30 /* "NSO0". */
|
||||||
#define NSO_MOD_MAGIC 0x4D4F4430 /* "MOD0". */
|
#define NSO_MOD_MAGIC 0x4D4F4430 /* "MOD0". */
|
||||||
|
|
||||||
|
@ -47,11 +47,15 @@ typedef struct {
|
||||||
u32 size; ///< Decompressed segment size.
|
u32 size; ///< Decompressed segment size.
|
||||||
} NsoSegmentInfo;
|
} NsoSegmentInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoSegmentInfo, 0xC);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 offset; ///< Relative to the .rodata segment start.
|
u32 offset; ///< Relative to the .rodata segment start.
|
||||||
u32 size;
|
u32 size;
|
||||||
} NsoSectionInfo;
|
} NsoSectionInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoSectionInfo, 0x8);
|
||||||
|
|
||||||
/// This is the start of every NSO.
|
/// This is the start of every NSO.
|
||||||
/// This is always followed by a NsoModuleName block.
|
/// This is always followed by a NsoModuleName block.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -73,11 +77,13 @@ typedef struct {
|
||||||
NsoSectionInfo api_info_section_info;
|
NsoSectionInfo api_info_section_info;
|
||||||
NsoSectionInfo dynstr_section_info;
|
NsoSectionInfo dynstr_section_info;
|
||||||
NsoSectionInfo dynsym_section_info;
|
NsoSectionInfo dynsym_section_info;
|
||||||
u8 text_segment_hash[0x20]; ///< Decompressed .text segment SHA-256 checksum.
|
u8 text_segment_hash[SHA256_HASH_SIZE]; ///< Decompressed .text segment SHA-256 checksum.
|
||||||
u8 rodata_segment_hash[0x20]; ///< Decompressed .rodata segment SHA-256 checksum.
|
u8 rodata_segment_hash[SHA256_HASH_SIZE]; ///< Decompressed .rodata segment SHA-256 checksum.
|
||||||
u8 data_segment_hash[0x20]; ///< Decompressed .data segment SHA-256 checksum.
|
u8 data_segment_hash[SHA256_HASH_SIZE]; ///< Decompressed .data segment SHA-256 checksum.
|
||||||
} NsoHeader;
|
} NsoHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoHeader, 0x100);
|
||||||
|
|
||||||
/// Usually placed right after NsoHeader, but it's actual offset may vary.
|
/// Usually placed right after NsoHeader, but it's actual offset may vary.
|
||||||
/// If the 'module_name_size' member from NsoHeader is greater than 1 and the 'name_length' element from NsoModuleName is greater than 0, 'name' will hold the module name.
|
/// If the 'module_name_size' member from NsoHeader is greater than 1 and the 'name_length' element from NsoModuleName is greater than 0, 'name' will hold the module name.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -85,12 +91,16 @@ typedef struct {
|
||||||
char name[];
|
char name[];
|
||||||
} NsoModuleName;
|
} NsoModuleName;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoModuleName, 0x1);
|
||||||
|
|
||||||
/// Placed at the very start of the decompressed .text segment.
|
/// Placed at the very start of the decompressed .text segment.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 entry_point;
|
u32 entry_point;
|
||||||
u32 mod_offset; ///< NsoModHeader block offset (relative to the start of this header). Almost always set to 0x8 (the size of this struct).
|
u32 mod_offset; ///< NsoModHeader block offset (relative to the start of this header). Almost always set to 0x8 (the size of this struct).
|
||||||
} NsoModStart;
|
} NsoModStart;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoModStart, 0x8);
|
||||||
|
|
||||||
/// This is essentially a replacement for the PT_DYNAMIC program header available in ELF binaries.
|
/// This is essentially a replacement for the PT_DYNAMIC program header available in ELF binaries.
|
||||||
/// All offsets are signed 32-bit values relative to the start of this header.
|
/// All offsets are signed 32-bit values relative to the start of this header.
|
||||||
/// This is usually placed at the start of the decompressed .text segment, right after a NsoModStart block.
|
/// This is usually placed at the start of the decompressed .text segment, right after a NsoModStart block.
|
||||||
|
@ -106,6 +116,8 @@ typedef struct {
|
||||||
s32 module_object_offset; ///< Typically equal to bss_start_offset.
|
s32 module_object_offset; ///< Typically equal to bss_start_offset.
|
||||||
} NsoModHeader;
|
} NsoModHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoModHeader, 0x1C);
|
||||||
|
|
||||||
/// Placed at the start of the decompressed .rodata segment + 0x4.
|
/// Placed at the start of the decompressed .rodata segment + 0x4.
|
||||||
/// If the 'name_length' element is greater than 0, 'name' will hold the module name.
|
/// If the 'name_length' element is greater than 0, 'name' will hold the module name.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -113,6 +125,8 @@ typedef struct {
|
||||||
char name[];
|
char name[];
|
||||||
} NsoModuleInfo;
|
} NsoModuleInfo;
|
||||||
|
|
||||||
|
NXDT_ASSERT(NsoModuleInfo, 0x4);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PartitionFileSystemContext *pfs_ctx; ///< PartitionFileSystemContext for the Program NCA FS section #0, which is where this NSO is stored.
|
PartitionFileSystemContext *pfs_ctx; ///< PartitionFileSystemContext for the Program NCA FS section #0, which is where this NSO is stored.
|
||||||
PartitionFileSystemEntry *pfs_entry; ///< PartitionFileSystemEntry for this NSO in the Program NCA FS section #0. Used to read NSO data.
|
PartitionFileSystemEntry *pfs_entry; ///< PartitionFileSystemEntry for this NSO in the Program NCA FS section #0. Used to read NSO data.
|
||||||
|
@ -145,8 +159,8 @@ NX_INLINE void nsoFreeContext(NsoContext *nso_ctx)
|
||||||
memset(nso_ctx, 0, sizeof(NsoContext));
|
memset(nso_ctx, 0, sizeof(NsoContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __NSO_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NSO_H__ */
|
||||||
|
|
18
source/pfs.h
18
source/pfs.h
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __PFS_H__
|
#ifndef __PFS_H__
|
||||||
#define __PFS_H__
|
#define __PFS_H__
|
||||||
|
|
||||||
#include "nca.h"
|
#include "nca.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PFS0_MAGIC 0x50465330 /* "PFS0". */
|
#define PFS0_MAGIC 0x50465330 /* "PFS0". */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -38,6 +38,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} PartitionFileSystemHeader;
|
} PartitionFileSystemHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(PartitionFileSystemHeader, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
@ -45,6 +47,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} PartitionFileSystemEntry;
|
} PartitionFileSystemEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(PartitionFileSystemEntry, 0x18);
|
||||||
|
|
||||||
/// Used with Partition FS sections from NCAs.
|
/// Used with Partition FS sections from NCAs.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaFsSectionContext *nca_fs_ctx; ///< Used to read NCA FS section data.
|
NcaFsSectionContext *nca_fs_ctx; ///< Used to read NCA FS section data.
|
||||||
|
@ -190,8 +194,8 @@ NX_INLINE char *pfsGetEntryNameByIndexFromFileContext(PartitionFileSystemFileCon
|
||||||
return (ctx->name_table + fs_entry->name_offset);
|
return (ctx->name_table + fs_entry->name_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __PFS_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __PFS_H__ */
|
||||||
|
|
|
@ -20,16 +20,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __PROGRAM_INFO_H__
|
#ifndef __PROGRAM_INFO_H__
|
||||||
#define __PROGRAM_INFO_H__
|
#define __PROGRAM_INFO_H__
|
||||||
|
|
||||||
#include "npdm.h"
|
#include "npdm.h"
|
||||||
#include "nso.h"
|
#include "nso.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which program data (NPDM / NSO) is retrieved.
|
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which program data (NPDM / NSO) is retrieved.
|
||||||
PartitionFileSystemContext pfs_ctx; ///< PartitionFileSystemContext for the Program NCA ExeFS, which is where program data (NPDM / NSO) is stored.
|
PartitionFileSystemContext pfs_ctx; ///< PartitionFileSystemContext for the Program NCA ExeFS, which is where program data (NPDM / NSO) is stored.
|
||||||
|
@ -84,8 +84,8 @@ NX_INLINE void programInfoWriteNcaPatch(ProgramInfoContext *program_info_ctx, vo
|
||||||
if (program_info_ctx) npdmWriteNcaPatch(&(program_info_ctx->npdm_ctx), buf, buf_size, buf_offset);
|
if (program_info_ctx) npdmWriteNcaPatch(&(program_info_ctx->npdm_ctx), buf, buf_size, buf_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __PROGRAM_INFO_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __PROGRAM_INFO_H__ */
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __ROMFS_H__
|
#ifndef __ROMFS_H__
|
||||||
#define __ROMFS_H__
|
#define __ROMFS_H__
|
||||||
|
|
||||||
#include "nca.h"
|
#include "nca.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ROMFS_OLD_HEADER_SIZE 0x28
|
#define ROMFS_OLD_HEADER_SIZE 0x28
|
||||||
#define ROMFS_HEADER_SIZE 0x50
|
#define ROMFS_HEADER_SIZE 0x50
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ typedef struct {
|
||||||
u32 body_offset; ///< File data body offset.
|
u32 body_offset; ///< File data body offset.
|
||||||
} RomFileSystemInformationOld;
|
} RomFileSystemInformationOld;
|
||||||
|
|
||||||
|
NXDT_ASSERT(RomFileSystemInformationOld, ROMFS_OLD_HEADER_SIZE);
|
||||||
|
|
||||||
/// Header used by NCA2/NCA3 RomFS sections.
|
/// Header used by NCA2/NCA3 RomFS sections.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 header_size; ///< Header size. Must be equal to ROMFS_HEADER_SIZE.
|
u64 header_size; ///< Header size. Must be equal to ROMFS_HEADER_SIZE.
|
||||||
|
@ -62,6 +64,8 @@ typedef struct {
|
||||||
u64 body_offset; ///< File data body offset.
|
u64 body_offset; ///< File data body offset.
|
||||||
} RomFileSystemInformation;
|
} RomFileSystemInformation;
|
||||||
|
|
||||||
|
NXDT_ASSERT(RomFileSystemInformation, ROMFS_HEADER_SIZE);
|
||||||
|
|
||||||
/// Header union.
|
/// Header union.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
|
@ -73,6 +77,8 @@ typedef struct {
|
||||||
};
|
};
|
||||||
} RomFileSystemHeader;
|
} RomFileSystemHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(RomFileSystemHeader, ROMFS_HEADER_SIZE);
|
||||||
|
|
||||||
/// Directory entry. Always aligned to a 4-byte boundary past the directory name.
|
/// Directory entry. Always aligned to a 4-byte boundary past the directory name.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 parent_offset; ///< Parent directory offset.
|
u32 parent_offset; ///< Parent directory offset.
|
||||||
|
@ -84,6 +90,8 @@ typedef struct {
|
||||||
char name[]; ///< Name (UTF-8).
|
char name[]; ///< Name (UTF-8).
|
||||||
} RomFileSystemDirectoryEntry;
|
} RomFileSystemDirectoryEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(RomFileSystemDirectoryEntry, 0x18);
|
||||||
|
|
||||||
/// Directory entry. Always aligned to a 4-byte boundary past the file name.
|
/// Directory entry. Always aligned to a 4-byte boundary past the file name.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 parent_offset; ///< Parent directory offset.
|
u32 parent_offset; ///< Parent directory offset.
|
||||||
|
@ -95,6 +103,8 @@ typedef struct {
|
||||||
char name[]; ///< Name (UTF-8).
|
char name[]; ///< Name (UTF-8).
|
||||||
} RomFileSystemFileEntry;
|
} RomFileSystemFileEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(RomFileSystemFileEntry, 0x20);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcaFsSectionContext *nca_fs_ctx; ///< Used to read NCA FS section data.
|
NcaFsSectionContext *nca_fs_ctx; ///< Used to read NCA FS section data.
|
||||||
u64 offset; ///< RomFS offset (relative to the start of the NCA FS section).
|
u64 offset; ///< RomFS offset (relative to the start of the NCA FS section).
|
||||||
|
@ -203,8 +213,8 @@ NX_INLINE void romfsFreeFileEntryPatch(RomFileSystemFileEntryPatch *patch)
|
||||||
memset(patch, 0, sizeof(RomFileSystemFileEntryPatch));
|
memset(patch, 0, sizeof(RomFileSystemFileEntryPatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __ROMFS_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __ROMFS_H__ */
|
||||||
|
|
12
source/rsa.h
12
source/rsa.h
|
@ -22,13 +22,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __RSA_H__
|
||||||
|
#define __RSA_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __RSA_H__
|
|
||||||
#define __RSA_H__
|
|
||||||
|
|
||||||
#define RSA2048_SIG_SIZE 0x100
|
#define RSA2048_SIG_SIZE 0x100
|
||||||
#define RSA2048_PUBKEY_SIZE RSA2048_SIG_SIZE
|
#define RSA2048_PUBKEY_SIZE RSA2048_SIG_SIZE
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ const u8 *rsa2048GetCustomPublicKey(void);
|
||||||
/// Performs RSA-2048-OAEP decryption and verification. Used to decrypt the titlekey block from tickets with personalized crypto.
|
/// Performs RSA-2048-OAEP decryption and verification. Used to decrypt the titlekey block from tickets with personalized crypto.
|
||||||
bool rsa2048OaepDecryptAndVerify(void *dst, size_t dst_size, const void *signature, const void *modulus, const void *exponent, size_t exponent_size, const void *label_hash, size_t *out_size);
|
bool rsa2048OaepDecryptAndVerify(void *dst, size_t dst_size, const void *signature, const void *modulus, const void *exponent, size_t exponent_size, const void *label_hash, size_t *out_size);
|
||||||
|
|
||||||
#endif /* __RSA_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __RSA_H__ */
|
||||||
|
|
|
@ -21,15 +21,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __SAVE_H__
|
#ifndef __SAVE_H__
|
||||||
#define __SAVE_H__
|
#define __SAVE_H__
|
||||||
|
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IVFC_MAX_LEVEL 6
|
#define IVFC_MAX_LEVEL 6
|
||||||
|
|
||||||
#define SAVE_HEADER_SIZE 0x4000
|
#define SAVE_HEADER_SIZE 0x4000
|
||||||
|
@ -106,6 +106,8 @@ typedef struct {
|
||||||
u8 _0x190[0x70];
|
u8 _0x190[0x70];
|
||||||
} fs_layout_t;
|
} fs_layout_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(fs_layout_t, 0x200);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset;
|
u64 offset;
|
||||||
|
@ -114,12 +116,16 @@ typedef struct {
|
||||||
} duplex_info_t;
|
} duplex_info_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(duplex_info_t, 0x14);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; /* "DPFS". */
|
u32 magic; /* "DPFS". */
|
||||||
u32 version;
|
u32 version;
|
||||||
duplex_info_t layers[3];
|
duplex_info_t layers[3];
|
||||||
} duplex_header_t;
|
} duplex_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(duplex_header_t, 0x44);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 version;
|
u32 version;
|
||||||
u32 main_data_block_count;
|
u32 main_data_block_count;
|
||||||
|
@ -127,6 +133,8 @@ typedef struct {
|
||||||
u32 _0x0C;
|
u32 _0x0C;
|
||||||
} journal_map_header_t;
|
} journal_map_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(journal_map_header_t, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; /* "JNGL". */
|
u32 magic; /* "JNGL". */
|
||||||
u32 version;
|
u32 version;
|
||||||
|
@ -135,6 +143,8 @@ typedef struct {
|
||||||
u64 block_size;
|
u64 block_size;
|
||||||
} journal_header_t;
|
} journal_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(journal_header_t, 0x20);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; /* "SAVE". */
|
u32 magic; /* "SAVE". */
|
||||||
u32 version;
|
u32 version;
|
||||||
|
@ -142,6 +152,8 @@ typedef struct {
|
||||||
u64 block_size;
|
u64 block_size;
|
||||||
} save_fs_header_t;
|
} save_fs_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_fs_header_t, 0x18);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 block_size;
|
u64 block_size;
|
||||||
u64 allocation_table_offset;
|
u64 allocation_table_offset;
|
||||||
|
@ -154,6 +166,8 @@ typedef struct {
|
||||||
u32 file_table_block;
|
u32 file_table_block;
|
||||||
} fat_header_t;
|
} fat_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(fat_header_t, 0x30);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic; /* "RMAP". */
|
u32 magic; /* "RMAP". */
|
||||||
u32 version;
|
u32 version;
|
||||||
|
@ -163,6 +177,8 @@ typedef struct {
|
||||||
u8 _0x14[0x2C];
|
u8 _0x14[0x2C];
|
||||||
} remap_header_t;
|
} remap_header_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(remap_header_t, 0x40);
|
||||||
|
|
||||||
typedef struct remap_segment_ctx_t remap_segment_ctx_t;
|
typedef struct remap_segment_ctx_t remap_segment_ctx_t;
|
||||||
typedef struct remap_entry_ctx_t remap_entry_ctx_t;
|
typedef struct remap_entry_ctx_t remap_entry_ctx_t;
|
||||||
|
|
||||||
|
@ -232,6 +248,8 @@ typedef struct {
|
||||||
u64 commit_id;
|
u64 commit_id;
|
||||||
} extra_data_t;
|
} extra_data_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(extra_data_t, 0x70);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 logical_offset;
|
u64 logical_offset;
|
||||||
u64 hash_data_size;
|
u64 hash_data_size;
|
||||||
|
@ -239,6 +257,8 @@ typedef struct {
|
||||||
u32 reserved;
|
u32 reserved;
|
||||||
} ivfc_level_hdr_t;
|
} ivfc_level_hdr_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ivfc_level_hdr_t, 0x18);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 magic;
|
u32 magic;
|
||||||
u32 id;
|
u32 id;
|
||||||
|
@ -248,6 +268,8 @@ typedef struct {
|
||||||
u8 salt_source[0x20];
|
u8 salt_source[0x20];
|
||||||
} ivfc_save_hdr_t;
|
} ivfc_save_hdr_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(ivfc_save_hdr_t, 0xC0);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 cmac[0x10];
|
u8 cmac[0x10];
|
||||||
|
@ -270,6 +292,8 @@ typedef struct {
|
||||||
} save_header_t;
|
} save_header_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_header_t, 0x4000);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
duplex_storage_ctx_t layers[2];
|
duplex_storage_ctx_t layers[2];
|
||||||
duplex_storage_ctx_t data_layer;
|
duplex_storage_ctx_t data_layer;
|
||||||
|
@ -294,6 +318,8 @@ typedef struct {
|
||||||
u32 virtual_index;
|
u32 virtual_index;
|
||||||
} journal_map_entry_t;
|
} journal_map_entry_t;
|
||||||
|
|
||||||
|
NXDT_ASSERT(journal_map_entry_t, 0x8);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
journal_map_header_t *header;
|
journal_map_header_t *header;
|
||||||
journal_map_entry_t *entries;
|
journal_map_entry_t *entries;
|
||||||
|
@ -387,6 +413,8 @@ typedef struct {
|
||||||
} save_file_info_t;
|
} save_file_info_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_file_info_t, 0x14);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 next_directory;
|
u32 next_directory;
|
||||||
|
@ -395,6 +423,8 @@ typedef struct {
|
||||||
} save_find_position_t;
|
} save_find_position_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_find_position_t, 0x14);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 next_sibling;
|
u32 next_sibling;
|
||||||
|
@ -405,6 +435,8 @@ typedef struct {
|
||||||
} save_table_entry_t;
|
} save_table_entry_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_table_entry_t, 0x18);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 parent;
|
u32 parent;
|
||||||
|
@ -414,6 +446,8 @@ typedef struct {
|
||||||
} save_fs_list_entry_t;
|
} save_fs_list_entry_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
NXDT_ASSERT(save_fs_list_entry_t, 0x60);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 free_list_head_index;
|
u32 free_list_head_index;
|
||||||
u32 used_list_head_index;
|
u32 used_list_head_index;
|
||||||
|
@ -517,8 +551,8 @@ save_ctx_t *save_open_savefile(const char *path, u32 action);
|
||||||
void save_close_savefile(save_ctx_t *ctx);
|
void save_close_savefile(save_ctx_t *ctx);
|
||||||
bool save_get_fat_storage_from_file_entry_by_path(save_ctx_t *ctx, const char *path, allocation_table_storage_ctx_t *out_fat_storage, u64 *out_file_entry_size);
|
bool save_get_fat_storage_from_file_entry_by_path(save_ctx_t *ctx, const char *path, allocation_table_storage_ctx_t *out_fat_storage, u64 *out_file_entry_size);
|
||||||
|
|
||||||
#endif /* __SAVE_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SAVE_H__ */
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __SERVICES_H__
|
||||||
|
#define __SERVICES_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __SERVICES_H__
|
|
||||||
#define __SERVICES_H__
|
|
||||||
|
|
||||||
/* Hardware clocks expressed in MHz. */
|
/* Hardware clocks expressed in MHz. */
|
||||||
#define CPU_CLKRT_NORMAL 1020
|
#define CPU_CLKRT_NORMAL 1020
|
||||||
#define CPU_CLKRT_OVERCLOCKED 1785
|
#define CPU_CLKRT_OVERCLOCKED 1785
|
||||||
|
@ -53,8 +53,8 @@ void servicesChangeHardwareClockRates(u32 cpu_rate, u32 mem_rate);
|
||||||
/// Perfectly safe under development units. Not available in older Atmosphère releases.
|
/// Perfectly safe under development units. Not available in older Atmosphère releases.
|
||||||
Result servicesHasService(bool *out, const char *name);
|
Result servicesHasService(bool *out, const char *name);
|
||||||
|
|
||||||
#endif /* __SERVICES_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SERVICES_H__ */
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
#ifndef __SIGNATURE_H__
|
#ifndef __SIGNATURE_H__
|
||||||
#define __SIGNATURE_H__
|
#define __SIGNATURE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SignatureType_Rsa4096Sha1 = 0x10000,
|
SignatureType_Rsa4096Sha1 = 0x10000,
|
||||||
SignatureType_Rsa2048Sha1 = 0x10001,
|
SignatureType_Rsa2048Sha1 = 0x10001,
|
||||||
|
@ -39,24 +43,32 @@ typedef struct {
|
||||||
u8 padding[0x3C];
|
u8 padding[0x3C];
|
||||||
} SignatureBlockRsa4096;
|
} SignatureBlockRsa4096;
|
||||||
|
|
||||||
|
NXDT_ASSERT(SignatureBlockRsa4096, 0x240);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 sig_type; ///< SignatureType_Rsa2048Sha1, SignatureType_Rsa2048Sha256.
|
u32 sig_type; ///< SignatureType_Rsa2048Sha1, SignatureType_Rsa2048Sha256.
|
||||||
u8 signature[0x100];
|
u8 signature[0x100];
|
||||||
u8 padding[0x3C];
|
u8 padding[0x3C];
|
||||||
} SignatureBlockRsa2048;
|
} SignatureBlockRsa2048;
|
||||||
|
|
||||||
|
NXDT_ASSERT(SignatureBlockRsa2048, 0x140);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 sig_type; ///< SignatureType_Ecc480Sha1, SignatureType_Ecc480Sha256.
|
u32 sig_type; ///< SignatureType_Ecc480Sha1, SignatureType_Ecc480Sha256.
|
||||||
u8 signature[0x3C];
|
u8 signature[0x3C];
|
||||||
u8 padding[0x40];
|
u8 padding[0x40];
|
||||||
} SignatureBlockEcc480;
|
} SignatureBlockEcc480;
|
||||||
|
|
||||||
|
NXDT_ASSERT(SignatureBlockEcc480, 0x80);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 sig_type; ///< SignatureType_Hmac160Sha1.
|
u32 sig_type; ///< SignatureType_Hmac160Sha1.
|
||||||
u8 signature[0x14];
|
u8 signature[0x14];
|
||||||
u8 padding[0x28];
|
u8 padding[0x28];
|
||||||
} SignatureBlockHmac160;
|
} SignatureBlockHmac160;
|
||||||
|
|
||||||
|
NXDT_ASSERT(SignatureBlockHmac160, 0x40);
|
||||||
|
|
||||||
/// Helper inline functions.
|
/// Helper inline functions.
|
||||||
|
|
||||||
NX_INLINE u32 signatureGetSigType(void *buf, bool byteswap)
|
NX_INLINE u32 signatureGetSigType(void *buf, bool byteswap)
|
||||||
|
@ -100,4 +112,8 @@ NX_INLINE void *signatureGetPayload(void *buf, bool big_endian_sig_type)
|
||||||
return (signatureIsValidSigType(sig_type) ? (void*)((u8*)buf + signatureGetBlockSize(sig_type)) : NULL);
|
return (signatureIsValidSigType(sig_type) ? (void*)((u8*)buf + signatureGetBlockSize(sig_type)) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __SIGNATURE_H__ */
|
#endif /* __SIGNATURE_H__ */
|
||||||
|
|
16
source/tik.c
16
source/tik.c
|
@ -50,6 +50,8 @@ typedef struct {
|
||||||
u8 reserved[0x04];
|
u8 reserved[0x04];
|
||||||
} TikListEntry;
|
} TikListEntry;
|
||||||
|
|
||||||
|
NXDT_ASSERT(TikListEntry, 0x20);
|
||||||
|
|
||||||
/// 9.x+ CTR key entry in ES .data segment. Used to store CTR key/IV data for encrypted volatile tickets in ticket.bin and/or encrypted entries in ticket_list.bin.
|
/// 9.x+ CTR key entry in ES .data segment. Used to store CTR key/IV data for encrypted volatile tickets in ticket.bin and/or encrypted entries in ticket_list.bin.
|
||||||
/// This is always stored in pairs. The first entry holds the key/IV for the encrypted volatile ticket, while the second entry holds the key/IV for the encrypted entry in ticket_list.bin.
|
/// This is always stored in pairs. The first entry holds the key/IV for the encrypted volatile ticket, while the second entry holds the key/IV for the encrypted entry in ticket_list.bin.
|
||||||
/// First index in this list is always 0, and it's aligned to ES_CTRKEY_ENTRY_ALIGNMENT.
|
/// First index in this list is always 0, and it's aligned to ES_CTRKEY_ENTRY_ALIGNMENT.
|
||||||
|
@ -59,6 +61,8 @@ typedef struct {
|
||||||
u8 ctr[AES_BLOCK_SIZE]; ///< AES-128-CTR counter/IV. Always zeroed out.
|
u8 ctr[AES_BLOCK_SIZE]; ///< AES-128-CTR counter/IV. Always zeroed out.
|
||||||
} TikEsCtrKeyEntry9x;
|
} TikEsCtrKeyEntry9x;
|
||||||
|
|
||||||
|
NXDT_ASSERT(TikEsCtrKeyEntry9x, 0x24);
|
||||||
|
|
||||||
/// Lookup pattern for TikEsCtrKeyEntry9x.
|
/// Lookup pattern for TikEsCtrKeyEntry9x.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 idx1; ///< Always set to 0 (first entry).
|
u32 idx1; ///< Always set to 0 (first entry).
|
||||||
|
@ -66,6 +70,8 @@ typedef struct {
|
||||||
u32 idx2; ///< Always set to 1 (second entry).
|
u32 idx2; ///< Always set to 1 (second entry).
|
||||||
} TikEsCtrKeyPattern9x;
|
} TikEsCtrKeyPattern9x;
|
||||||
|
|
||||||
|
NXDT_ASSERT(TikEsCtrKeyPattern9x, 0x28);
|
||||||
|
|
||||||
/// Used to parse the eTicket device key retrieved from PRODINFO via setcalGetEticketDeviceKey().
|
/// Used to parse the eTicket device key retrieved from PRODINFO via setcalGetEticketDeviceKey().
|
||||||
/// Everything after the AES CTR is encrypted.
|
/// Everything after the AES CTR is encrypted.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -78,6 +84,8 @@ typedef struct {
|
||||||
u8 ghash[0x10];
|
u8 ghash[0x10];
|
||||||
} TikEticketDeviceKeyData;
|
} TikEticketDeviceKeyData;
|
||||||
|
|
||||||
|
NXDT_ASSERT(TikEticketDeviceKeyData, 0x240);
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
static SetCalRsa2048DeviceKey g_eTicketDeviceKey = {0};
|
static SetCalRsa2048DeviceKey g_eTicketDeviceKey = {0};
|
||||||
|
@ -380,7 +388,7 @@ static bool tikGetTitleKekEncryptedTitleKeyFromTicket(Ticket *tik)
|
||||||
switch(tik_common_block->titlekey_type)
|
switch(tik_common_block->titlekey_type)
|
||||||
{
|
{
|
||||||
case TikTitleKeyType_Common:
|
case TikTitleKeyType_Common:
|
||||||
/* No titlekek crypto used. */
|
/* No console-specific crypto used. Copy titlekek-encrypted titlekey right away. */
|
||||||
memcpy(tik->enc_titlekey, tik_common_block->titlekey_block, 0x10);
|
memcpy(tik->enc_titlekey, tik_common_block->titlekey_block, 0x10);
|
||||||
break;
|
break;
|
||||||
case TikTitleKeyType_Personalized:
|
case TikTitleKeyType_Personalized:
|
||||||
|
@ -393,7 +401,7 @@ static bool tikGetTitleKekEncryptedTitleKeyFromTicket(Ticket *tik)
|
||||||
|
|
||||||
eticket_devkey = (TikEticketDeviceKeyData*)g_eTicketDeviceKey.key;
|
eticket_devkey = (TikEticketDeviceKeyData*)g_eTicketDeviceKey.key;
|
||||||
|
|
||||||
/* Perform a RSA-OAEP decrypt operation to get the titlekey. */
|
/* Perform a RSA-OAEP decrypt operation to get the titlekek-encrypted titlekey. */
|
||||||
if (!rsa2048OaepDecryptAndVerify(out_keydata, 0x100, tik_common_block->titlekey_block, eticket_devkey->modulus, eticket_devkey->exponent, 0x100, g_nullHash, &out_keydata_size) || \
|
if (!rsa2048OaepDecryptAndVerify(out_keydata, 0x100, tik_common_block->titlekey_block, eticket_devkey->modulus, eticket_devkey->exponent, 0x100, g_nullHash, &out_keydata_size) || \
|
||||||
out_keydata_size < 0x10)
|
out_keydata_size < 0x10)
|
||||||
{
|
{
|
||||||
|
@ -401,7 +409,7 @@ static bool tikGetTitleKekEncryptedTitleKeyFromTicket(Ticket *tik)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy decrypted titlekey. */
|
/* Copy titlekek-encrypted titlekey. */
|
||||||
memcpy(tik->enc_titlekey, out_keydata, 0x10);
|
memcpy(tik->enc_titlekey, out_keydata, 0x10);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -589,7 +597,7 @@ static bool tikGetTicketEntryOffsetFromTicketList(save_ctx_t *save_ctx, u8 *buf,
|
||||||
if (!memcmp(entry->rights_id.c, id->c, sizeof(id->c)))
|
if (!memcmp(entry->rights_id.c, id->c, sizeof(id->c)))
|
||||||
{
|
{
|
||||||
/* Jackpot. */
|
/* Jackpot. */
|
||||||
*out_offset = (entry_offset << 5); /* (entry_offset / 0x20) * 0x400 */
|
*out_offset = (entry_offset << 5); /* (entry_offset / sizeof(TikListEntry)) * SIGNED_TIK_MAX_SIZE */
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
65
source/tik.h
65
source/tik.h
|
@ -20,25 +20,27 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __TIK_H__
|
#ifndef __TIK_H__
|
||||||
#define __TIK_H__
|
#define __TIK_H__
|
||||||
|
|
||||||
#include "signature.h"
|
#include "signature.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SIGNED_TIK_MAX_SIZE 0x400 /* Max ticket entry size in the ES ticket system savedata file. */
|
#define SIGNED_TIK_MAX_SIZE 0x400 /* Max ticket entry size in the ES ticket system savedata file. */
|
||||||
#define SIGNED_TIK_MIN_SIZE sizeof(TikSigHmac160) /* Assuming no ESV1/ESV2 records are available. */
|
#define SIGNED_TIK_MIN_SIZE sizeof(TikSigHmac160) /* Assuming no ESV1/ESV2 records are available. */
|
||||||
|
|
||||||
typedef enum {
|
#define GENERATE_TIK_STRUCT(sigtype, tiksize) \
|
||||||
TikType_None = 0,
|
\
|
||||||
TikType_SigRsa4096 = 1,
|
typedef struct { \
|
||||||
TikType_SigRsa2048 = 2,
|
SignatureBlock##sigtype sig_block; \
|
||||||
TikType_SigEcc480 = 3,
|
TikCommonBlock tik_common_block; \
|
||||||
TikType_SigHmac160 = 4
|
u8 es_section_record_data[]; \
|
||||||
} TikType;
|
} TikSig##sigtype; \
|
||||||
|
\
|
||||||
|
NXDT_ASSERT(TikSig##sigtype, tiksize);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TikTitleKeyType_Common = 0,
|
TikTitleKeyType_Common = 0,
|
||||||
|
@ -84,25 +86,7 @@ typedef struct {
|
||||||
u16 sect_hdr_entry_size;
|
u16 sect_hdr_entry_size;
|
||||||
} TikCommonBlock;
|
} TikCommonBlock;
|
||||||
|
|
||||||
typedef struct {
|
NXDT_ASSERT(TikCommonBlock, 0x180);
|
||||||
SignatureBlockRsa4096 sig_block; ///< sig_type field is stored using little endian byte order.
|
|
||||||
TikCommonBlock tik_common_block;
|
|
||||||
} TikSigRsa4096;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockRsa2048 sig_block; ///< sig_type field is stored using little endian byte order.
|
|
||||||
TikCommonBlock tik_common_block;
|
|
||||||
} TikSigRsa2048;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockEcc480 sig_block; ///< sig_type field is stored using little endian byte order.
|
|
||||||
TikCommonBlock tik_common_block;
|
|
||||||
} TikSigEcc480;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SignatureBlockHmac160 sig_block; ///< sig_type field is stored using little endian byte order.
|
|
||||||
TikCommonBlock tik_common_block;
|
|
||||||
} TikSigHmac160;
|
|
||||||
|
|
||||||
/// ESV1/ESV2 section records are placed right after the ticket data. These aren't available in TikTitleKeyType_Common tickets.
|
/// ESV1/ESV2 section records are placed right after the ticket data. These aren't available in TikTitleKeyType_Common tickets.
|
||||||
/// These are only used if the sect_* fields from the common block are non-zero (other than 'sect_hdr_offset').
|
/// These are only used if the sect_* fields from the common block are non-zero (other than 'sect_hdr_offset').
|
||||||
|
@ -164,6 +148,21 @@ typedef struct {
|
||||||
u32 ref_id_attr;
|
u32 ref_id_attr;
|
||||||
} TikESV1LimitedResourceRecord;
|
} TikESV1LimitedResourceRecord;
|
||||||
|
|
||||||
|
/// All tickets generated below use a little endian sig_type field.
|
||||||
|
GENERATE_TIK_STRUCT(Rsa4096, 0x3C0); /// RSA-4096 signature.
|
||||||
|
GENERATE_TIK_STRUCT(Rsa2048, 0x2C0); /// RSA-2048 signature.
|
||||||
|
GENERATE_TIK_STRUCT(Ecc480, 0x200); /// ECC signature.
|
||||||
|
GENERATE_TIK_STRUCT(Hmac160, 0x1C0); /// HMAC signature.
|
||||||
|
|
||||||
|
/// Ticket type.
|
||||||
|
typedef enum {
|
||||||
|
TikType_None = 0,
|
||||||
|
TikType_SigRsa4096 = 1,
|
||||||
|
TikType_SigRsa2048 = 2,
|
||||||
|
TikType_SigEcc480 = 3,
|
||||||
|
TikType_SigHmac160 = 4
|
||||||
|
} TikType;
|
||||||
|
|
||||||
/// Used to store ticket type, size and raw data, as well as titlekey data.
|
/// Used to store ticket type, size and raw data, as well as titlekey data.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 type; ///< TikType.
|
u8 type; ///< TikType.
|
||||||
|
@ -228,8 +227,8 @@ NX_INLINE bool tikIsPersonalizedTicket(Ticket *tik)
|
||||||
return (tik_common_block != NULL && tik_common_block->titlekey_type == TikTitleKeyType_Personalized);
|
return (tik_common_block != NULL && tik_common_block->titlekey_type == TikTitleKeyType_Personalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __TIK_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __TIK_H__ */
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __TITLE_H__
|
||||||
|
#define __TITLE_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __TITLE_H__
|
|
||||||
#define __TITLE_H__
|
|
||||||
|
|
||||||
#define TITLE_PATCH_TYPE_VALUE (u64)0x800
|
#define TITLE_PATCH_TYPE_VALUE (u64)0x800
|
||||||
|
|
||||||
#define TITLE_ADDONCONTENT_TYPE_VALUE (u64)0x1000
|
#define TITLE_ADDONCONTENT_TYPE_VALUE (u64)0x1000
|
||||||
|
@ -268,8 +268,8 @@ NX_INLINE u32 titleGetCountFromInfoBlock(TitleInfo *title_info)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __TITLE_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __TITLE_H__ */
|
||||||
|
|
14
source/ums.h
14
source/ums.h
|
@ -20,15 +20,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __UMS_H__
|
#ifndef __UMS_H__
|
||||||
#define __UMS_H__
|
#define __UMS_H__
|
||||||
|
|
||||||
#include <usbhsfs.h>
|
#include <usbhsfs.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Initializes the USB Mass Storage interface.
|
/// Initializes the USB Mass Storage interface.
|
||||||
bool umsInitialize(void);
|
bool umsInitialize(void);
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ bool umsIsDeviceInfoUpdated(void);
|
||||||
/// Returns NULL if an error occurs.
|
/// Returns NULL if an error occurs.
|
||||||
UsbHsFsDevice *umsGetDevices(u32 *out_count);
|
UsbHsFsDevice *umsGetDevices(u32 *out_count);
|
||||||
|
|
||||||
#endif /* __UMS_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __UMS_H__ */
|
||||||
|
|
14
source/usb.c
14
source/usb.c
|
@ -75,6 +75,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} UsbCommandHeader;
|
} UsbCommandHeader;
|
||||||
|
|
||||||
|
NXDT_ASSERT(UsbCommandHeader, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 app_ver_major;
|
u8 app_ver_major;
|
||||||
u8 app_ver_minor;
|
u8 app_ver_minor;
|
||||||
|
@ -84,6 +86,8 @@ typedef struct {
|
||||||
u8 reserved[0x4];
|
u8 reserved[0x4];
|
||||||
} UsbCommandStartSession;
|
} UsbCommandStartSession;
|
||||||
|
|
||||||
|
NXDT_ASSERT(UsbCommandStartSession, 0x10);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 file_size;
|
u64 file_size;
|
||||||
u32 filename_length;
|
u32 filename_length;
|
||||||
|
@ -92,6 +96,8 @@ typedef struct {
|
||||||
u8 reserved_2[0xF];
|
u8 reserved_2[0xF];
|
||||||
} UsbCommandSendFileProperties;
|
} UsbCommandSendFileProperties;
|
||||||
|
|
||||||
|
NXDT_ASSERT(UsbCommandSendFileProperties, 0x320);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
///< Expected response code.
|
///< Expected response code.
|
||||||
UsbStatusType_Success = 0,
|
UsbStatusType_Success = 0,
|
||||||
|
@ -116,6 +122,8 @@ typedef struct {
|
||||||
u8 reserved[0x6];
|
u8 reserved[0x6];
|
||||||
} UsbStatus;
|
} UsbStatus;
|
||||||
|
|
||||||
|
NXDT_ASSERT(UsbStatus, 0x10);
|
||||||
|
|
||||||
/// Imported from libusb, with some adjustments.
|
/// Imported from libusb, with some adjustments.
|
||||||
enum usb_bos_type {
|
enum usb_bos_type {
|
||||||
USB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1,
|
USB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1,
|
||||||
|
@ -150,6 +158,8 @@ struct usb_bos_descriptor {
|
||||||
u8 bNumDeviceCaps; ///< The number of separate device capability descriptors in the BOS.
|
u8 bNumDeviceCaps; ///< The number of separate device capability descriptors in the BOS.
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
NXDT_ASSERT(struct usb_bos_descriptor, 0x5);
|
||||||
|
|
||||||
/// Imported from libusb, with some adjustments.
|
/// Imported from libusb, with some adjustments.
|
||||||
struct usb_2_0_extension_descriptor {
|
struct usb_2_0_extension_descriptor {
|
||||||
u8 bLength;
|
u8 bLength;
|
||||||
|
@ -158,6 +168,8 @@ struct usb_2_0_extension_descriptor {
|
||||||
u32 bmAttributes; ///< usb_2_0_extension_attributes.
|
u32 bmAttributes; ///< usb_2_0_extension_attributes.
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
NXDT_ASSERT(struct usb_2_0_extension_descriptor, 0x7);
|
||||||
|
|
||||||
/// Imported from libusb, with some adjustments.
|
/// Imported from libusb, with some adjustments.
|
||||||
struct usb_ss_usb_device_capability_descriptor {
|
struct usb_ss_usb_device_capability_descriptor {
|
||||||
u8 bLength;
|
u8 bLength;
|
||||||
|
@ -170,6 +182,8 @@ struct usb_ss_usb_device_capability_descriptor {
|
||||||
u16 bU2DevExitLat; ///< U2 Device Exit Latency.
|
u16 bU2DevExitLat; ///< U2 Device Exit Latency.
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
NXDT_ASSERT(struct usb_ss_usb_device_capability_descriptor, 0xA);
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
static RwLock g_usbDeviceLock = {0};
|
static RwLock g_usbDeviceLock = {0};
|
||||||
|
|
12
source/usb.h
12
source/usb.h
|
@ -23,13 +23,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __USB_H__
|
|
||||||
#define __USB_H__
|
|
||||||
|
|
||||||
#define USB_TRANSFER_BUFFER_SIZE 0x800000 /* 8 MiB. */
|
#define USB_TRANSFER_BUFFER_SIZE 0x800000 /* 8 MiB. */
|
||||||
|
|
||||||
/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer.
|
/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer.
|
||||||
|
@ -73,8 +73,8 @@ NX_INLINE bool usbSendFilePropertiesCommon(u64 file_size, const char *filename)
|
||||||
return usbSendFileProperties(file_size, filename, 0);
|
return usbSendFileProperties(file_size, filename, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __USB_H__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* __USB_H__ */
|
||||||
|
|
|
@ -145,4 +145,4 @@ NX_INLINE void utilsSleep(u64 seconds)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __UTILS_H__ */
|
#endif /* __UTILS_H__ */
|
||||||
|
|
Loading…
Reference in a new issue