1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-12-22 16:42:11 +00:00

*FormattedStringToBuffer: relax input validation

Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code.

Other changes include:

* bfttf: rename BfttfFontType_Total -> BfttfFontType_Count.
* config: rename "append_authoringtool_data" -> "generate_authoringtool_data".
* fs_ext: update FsGameCardCertificate struct
* gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out.
* mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable.
* npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs.
* tik: force byte-for-byte memory lookup while dumping volatile tickets.
* libs: update libusbhsfs to latest commit.
* codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged.
* PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values.
* nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
This commit is contained in:
Pablo Curiel 2023-07-17 01:03:05 +02:00
parent 51b17f35fe
commit 8f75b6b923
34 changed files with 387 additions and 289 deletions

View file

@ -257,8 +257,8 @@ static void setNspEnableVideoCaptureOption(u32 idx);
static u32 getNspDisableHdcpOption(void);
static void setNspDisableHdcpOption(u32 idx);
static u32 getNspAppendAuthoringToolDataOption(void);
static void setNspAppendAuthoringToolDataOption(u32 idx);
static u32 getNspGenerateAuthoringToolDataOption(void);
static void setNspGenerateAuthoringToolDataOption(u32 idx);
static u32 getTicketRemoveConsoleDataOption(void);
static void setTicketRemoveConsoleDataOption(u32 idx);
@ -589,13 +589,13 @@ static MenuElement *g_nspMenuElements[] = {
.userdata = NULL
},
&(MenuElement){
.str = "nsp: append authoringtool data",
.str = "nsp: generate authoringtool data",
.child_menu = NULL,
.task_func = NULL,
.element_options = &(MenuElementOption){
.selected = 1,
.getter_func = &getNspAppendAuthoringToolDataOption,
.setter_func = &setNspAppendAuthoringToolDataOption,
.getter_func = &getNspGenerateAuthoringToolDataOption,
.setter_func = &setNspGenerateAuthoringToolDataOption,
.options = g_noYesStrings
},
.userdata = NULL
@ -876,11 +876,11 @@ static char path[FS_MAX_PATH] = {0};
int main(int argc, char *argv[])
{
int ret = 0;
int ret = EXIT_SUCCESS;
if (!utilsInitializeResources(argc, (const char**)argv))
{
ret = -1;
ret = EXIT_FAILURE;
goto end;
}
@ -1356,7 +1356,6 @@ int main(int argc, char *argv[])
if (btn_held & (HidNpadButton_StickLDown | HidNpadButton_StickRDown | HidNpadButton_StickLUp | HidNpadButton_StickRUp | HidNpadButton_ZL | HidNpadButton_ZR)) svcSleepThread(40000000); // 40 ms
}
end:
freeNcaFsSectionsList();
freeNcaList();
@ -1367,6 +1366,7 @@ end:
titleFreeUserApplicationData(&user_app_data);
end:
utilsCloseResources();
consoleExit(NULL);
@ -4716,7 +4716,7 @@ static void nspThreadFunc(void *arg)
bool patch_screenshot = (bool)getNspEnableScreenshotsOption();
bool patch_video_capture = (bool)getNspEnableVideoCaptureOption();
bool patch_hdcp = (bool)getNspDisableHdcpOption();
bool append_authoringtool_data = (bool)getNspAppendAuthoringToolDataOption();
bool generate_authoringtool_data = (bool)getNspGenerateAuthoringToolDataOption();
bool success = false;
u64 free_space = 0;
@ -4783,7 +4783,7 @@ static void nspThreadFunc(void *arg)
}
// determine if we should initialize programinfo ctx
if (append_authoringtool_data)
if (generate_authoringtool_data)
{
program_count = titleGetContentCountByType(title_info, NcmContentType_Program);
if (program_count && !(program_info_ctx = calloc(program_count, sizeof(ProgramInfoContext))))
@ -4794,7 +4794,7 @@ static void nspThreadFunc(void *arg)
}
// determine if we should initialize nacp ctx
if (patch_sua || patch_screenshot || patch_video_capture || patch_hdcp || append_authoringtool_data)
if (patch_sua || patch_screenshot || patch_video_capture || patch_hdcp || generate_authoringtool_data)
{
control_count = titleGetContentCountByType(title_info, NcmContentType_Control);
if (control_count && !(nacp_ctx = calloc(control_count, sizeof(NacpContext))))
@ -4805,7 +4805,7 @@ static void nspThreadFunc(void *arg)
}
// determine if we should initialize legalinfo ctx
if (append_authoringtool_data)
if (generate_authoringtool_data)
{
legal_info_count = titleGetContentCountByType(title_info, NcmContentType_LegalInformation);
if (legal_info_count && !(legal_info_ctx = calloc(legal_info_count, sizeof(LegalInfoContext))))
@ -4923,7 +4923,7 @@ static void nspThreadFunc(void *arg)
goto end;
}
if (append_authoringtool_data && !nacpGenerateAuthoringToolXml(cur_nacp_ctx, title_info->version.value, cnmtGetRequiredTitleVersion(&cnmt_ctx)))
if (generate_authoringtool_data && !nacpGenerateAuthoringToolXml(cur_nacp_ctx, title_info->version.value, cnmtGetRequiredTitleVersion(&cnmt_ctx)))
{
consolePrint("nacp xml failed (%s)\n", cur_nca_ctx->content_id_str);
goto end;
@ -4972,7 +4972,7 @@ static void nspThreadFunc(void *arg)
// generate cnmt xml right away even though we don't yet have all the data we need
// This is because we need its size to calculate the full nsp size
if (append_authoringtool_data && !cnmtGenerateAuthoringToolXml(&cnmt_ctx, nca_ctx, title_info->content_count))
if (generate_authoringtool_data && !cnmtGenerateAuthoringToolXml(&cnmt_ctx, nca_ctx, title_info->content_count))
{
consolePrint("cnmt xml #1 failed\n");
goto end;
@ -5019,7 +5019,7 @@ static void nspThreadFunc(void *arg)
}
// add cnmt xml info
if (append_authoringtool_data)
if (generate_authoringtool_data)
{
sprintf(entry_name, "%s.cnmt.xml", meta_nca_ctx->content_id_str);
if (!pfsAddEntryInformationToFileContext(&pfs_file_ctx, entry_name, cnmt_ctx.authoring_tool_xml_size, &(meta_nca_ctx->content_type_ctx_data_idx)))
@ -5030,7 +5030,7 @@ static void nspThreadFunc(void *arg)
}
// add content type ctx data info
u32 limit = append_authoringtool_data ? (title_info->content_count - 1) : 0;
u32 limit = generate_authoringtool_data ? (title_info->content_count - 1) : 0;
for(u32 i = 0; i < limit; i++)
{
bool ret = false;
@ -5275,7 +5275,7 @@ static void nspThreadFunc(void *arg)
}
}
if (append_authoringtool_data)
if (generate_authoringtool_data)
{
// regenerate cnmt xml
if (!cnmtGenerateAuthoringToolXml(&cnmt_ctx, nca_ctx, title_info->content_count))
@ -5643,14 +5643,14 @@ static void setNspDisableHdcpOption(u32 idx)
configSetBoolean("nsp/disable_hdcp", (bool)idx);
}
static u32 getNspAppendAuthoringToolDataOption(void)
static u32 getNspGenerateAuthoringToolDataOption(void)
{
return (u32)configGetBoolean("nsp/append_authoringtool_data");
return (u32)configGetBoolean("nsp/generate_authoringtool_data");
}
static void setNspAppendAuthoringToolDataOption(u32 idx)
static void setNspGenerateAuthoringToolDataOption(u32 idx)
{
configSetBoolean("nsp/append_authoringtool_data", (bool)idx);
configSetBoolean("nsp/generate_authoringtool_data", (bool)idx);
}
static u32 getTicketRemoveConsoleDataOption(void)

View file

@ -262,11 +262,11 @@ static void dumpFsSection(TitleInfo *info, NcaFsSectionContext *nca_fs_ctx)
int main(int argc, char *argv[])
{
int ret = 0;
int ret = EXIT_SUCCESS;
if (!utilsInitializeResources(argc, (const char**)argv))
{
ret = -1;
ret = EXIT_FAILURE;
goto out;
}

View file

@ -81,11 +81,11 @@ static void writeFile(void *buf, size_t buf_size, const char *path)
int main(int argc, char *argv[])
{
int ret = 0;
int ret = EXIT_SUCCESS;
if (!utilsInitializeResources(argc, (const char**)argv))
{
ret = -1;
ret = EXIT_FAILURE;
goto out;
}

View file

@ -37,7 +37,7 @@ typedef enum {
BfttfFontType_ChineseSimplified = 3, ///< Simplified Chinese.
BfttfFontType_ExtChineseSimplified = 4, ///< Extended Simplified Chinese.
BfttfFontType_ChineseTraditional = 5, ///< Traditional Chinese.
BfttfFontType_Total = 6 ///< Total fonts supported by this enum.
BfttfFontType_Count = 6 ///< Total fonts supported by this enum.
} BfttfFontType;
/// Loosely based on PlFontData.

View file

@ -70,7 +70,8 @@ NXDT_ASSERT(BucketTreeOffsetNode, BKTR_NODE_SIZE);
/// IndirectStorage-related elements.
typedef enum {
BucketTreeIndirectStorageIndex_Original = 0,
BucketTreeIndirectStorageIndex_Patch = 1
BucketTreeIndirectStorageIndex_Patch = 1,
BucketTreeIndirectStorageIndex_Count = 2 ///< Total values supported by this enum.
} BucketTreeIndirectStorageIndex;
#pragma pack(push, 1)
@ -86,7 +87,8 @@ NXDT_ASSERT(BucketTreeIndirectStorageEntry, BKTR_INDIRECT_ENTRY_SIZE);
/// AesCtrExStorage-related elements.
typedef enum {
BucketTreeAesCtrExStorageEncryption_Enabled = 0,
BucketTreeAesCtrExStorageEncryption_Disabled = 1
BucketTreeAesCtrExStorageEncryption_Disabled = 1,
BucketTreeAesCtrExStorageEncryption_Count = 2 ///< Total values supported by this enum.
} BucketTreeAesCtrExStorageEncryption;
typedef struct {
@ -100,10 +102,11 @@ NXDT_ASSERT(BucketTreeAesCtrExStorageEntry, BKTR_AES_CTR_EX_ENTRY_SIZE);
/// CompressedStorage-related elements.
typedef enum {
BucketTreeCompressedStorageCompressionType_None = 0,
BucketTreeCompressedStorageCompressionType_Zero = 1,
BucketTreeCompressedStorageCompressionType_2 = 2,
BucketTreeCompressedStorageCompressionType_LZ4 = 3
BucketTreeCompressedStorageCompressionType_None = 0,
BucketTreeCompressedStorageCompressionType_Zero = 1,
BucketTreeCompressedStorageCompressionType_2 = 2,
BucketTreeCompressedStorageCompressionType_LZ4 = 3,
BucketTreeCompressedStorageCompressionType_Count = 4 ///< Total values supported by this enum.
} BucketTreeCompressedStorageCompressionType;
typedef struct {

View file

@ -46,7 +46,8 @@ NXDT_ASSERT(CertSig##sigtype##PubKey##pubkeytype, certsize);
typedef enum {
CertPubKeyType_Rsa4096 = 0,
CertPubKeyType_Rsa2048 = 1,
CertPubKeyType_Ecc480 = 2
CertPubKeyType_Ecc480 = 2,
CertPubKeyType_Count = 3 ///< Total values supported by this enum.
} CertPubKeyType;
/// Placed after the certificate signature block.
@ -121,7 +122,8 @@ typedef enum {
CertType_SigEcc480_PubKeyEcc480 = 9,
CertType_SigHmac160_PubKeyRsa4096 = 10,
CertType_SigHmac160_PubKeyRsa2048 = 11,
CertType_SigHmac160_PubKeyEcc480 = 12
CertType_SigHmac160_PubKeyEcc480 = 12,
CertType_Count = 13 ///< Total values supported by this enum.
} CertType;
/// Used to store certificate type, size and raw data.

View file

@ -34,6 +34,7 @@ extern "C" {
/// Equivalent to NcmContentMetaAttribute.
typedef enum {
ContentMetaAttribute_None = 0,
ContentMetaAttribute_IncludesExFatDriver = BIT(0),
ContentMetaAttribute_Rebootless = BIT(1),
ContentMetaAttribute_Compacted = BIT(2), ///< One or more NCAs use SparseInfo data.
@ -41,6 +42,7 @@ typedef enum {
} ContentMetaAttribute;
typedef enum {
ContentMetaInstallState_None = 0,
ContentMetaInstallState_Committed = BIT(0),
ContentMetaInstallState_Count = 1 ///< Total values supported by this enum.
} ContentMetaInstallState;
@ -98,6 +100,7 @@ typedef struct {
NXDT_ASSERT(ContentMetaPatchMetaExtendedHeader, 0x18);
typedef enum {
ContentMetaContentAccessibility_None = 0,
ContentMetaContentAccessibility_Individual = BIT(0),
ContentMetaContentAccessibility_Count = 1 ///< Total values supported by this enum.
} ContentMetaContentAccessibility;
@ -149,7 +152,8 @@ typedef enum {
ContentMetaFirmwareVariationVersion_Invalid = 0,
ContentMetaFirmwareVariationVersion_V1 = 1,
ContentMetaFirmwareVariationVersion_V2 = 2,
ContentMetaFirmwareVariationVersion_Unknown = 3
ContentMetaFirmwareVariationVersion_Unknown = 3,
ContentMetaFirmwareVariationVersion_Count = 4 ///< Total values supported by this enum.
} ContentMetaFirmwareVariationVersion;
/// Header for the extended data region in the SystemUpdate title, pointed to by the extended header.
@ -240,7 +244,8 @@ NXDT_ASSERT(ContentMetaPatchDeltaHeader, 0x28);
typedef enum {
ContentMetaUpdateType_ApplyAsDelta = 0,
ContentMetaUpdateType_Overwrite = 1,
ContentMetaUpdateType_Create = 2
ContentMetaUpdateType_Create = 2,
ContentMetaUpdateType_Count = 3 ///< Total values supported by this enum.
} ContentMetaUpdateType;
#pragma pack(push, 1)

View file

@ -33,14 +33,14 @@ extern "C" {
typedef enum {
ConfigOutputStorage_SdCard = 0,
ConfigOutputStorage_UsbHost = 1,
ConfigOutputStorage_Count = 2
ConfigOutputStorage_Count = 2 ///< Total values supported by this enum.
} ConfigOutputStorage;
typedef enum {
ConfigChecksumLookupMethod_None = 0,
ConfigChecksumLookupMethod_NSWDB = 1,
ConfigChecksumLookupMethod_NoIntro = 2,
ConfigChecksumLookupMethod_Count = 3
ConfigChecksumLookupMethod_Count = 3 ///< Total values supported by this enum.
} ConfigChecksumLookupMethod;
/// Initializes the configuration interface.

View file

@ -32,14 +32,15 @@ extern "C" {
/// Located at offset 0x7000 in the gamecard image.
typedef struct {
u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the data.
u32 magic; ///< "CERT".
u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the data.
u32 magic; ///< "CERT".
u32 version;
u8 kek_index;
u8 reserved[0x7];
u8 device_id[0x10];
u8 t1_card_device_id[0x10];
u8 iv[0x10];
u8 data[0xD0]; ///< Encrypted using the IV from this struct and an unknown key.
u8 hw_key[0x10]; ///< Encrypted.
u8 data[0xC0]; ///< Encrypted.
} FsGameCardCertificate;
NXDT_ASSERT(FsGameCardCertificate, 0x200);

View file

@ -40,20 +40,6 @@ extern "C" {
#define GAMECARD_CERTIFICATE_OFFSET 0x7000
/// Plaintext area. Dumped from FS program memory.
/// Overall structure may change with each new LAFW version.
typedef struct {
u32 asic_security_mode; ///< Determines how the Lotus ASIC initialised the gamecard security mode. Usually 0xFFFFFFF9.
u32 asic_status; ///< Bitmask of the internal gamecard interface status. Usually 0x20000000.
FsCardId1 card_id1;
FsCardId2 card_id2;
u8 card_uid[0x40];
u8 reserved[0x190];
u8 asic_session_hash[0x20]; ///< Changes with each gamecard (re)insertion.
} GameCardSpecificData;
NXDT_ASSERT(GameCardSpecificData, 0x200);
/// Encrypted using AES-128-ECB with the common titlekek generator key (stored in the .rodata segment from the Lotus firmware).
typedef struct {
union {
@ -78,18 +64,6 @@ typedef struct {
NXDT_ASSERT(GameCardInitialData, 0x200);
/// Plaintext area. Dumped from FS program memory.
/// This struct is returned by Lotus command "ChangeToSecureMode" (0xF). This means it is only available *after* the gamecard secure area has been mounted.
/// A copy of the gamecard header without the RSA-2048 signature and a plaintext GameCardInfo precedes this struct in FS program memory.
typedef struct {
GameCardSpecificData specific_data;
FsGameCardCertificate certificate;
u8 reserved[0x200];
GameCardInitialData initial_data;
} GameCardSecurityInformation;
NXDT_ASSERT(GameCardSecurityInformation, 0x800);
/// Encrypted using AES-128-CTR with the key and IV/counter from the `GameCardTitleKeyAreaEncryption` section. Assumed to be all zeroes in retail gamecards.
typedef struct {
u8 titlekey[0x10]; ///< Decrypted titlekey from the `GameCardInitialData` section.
@ -117,9 +91,36 @@ typedef struct {
NXDT_ASSERT(GameCardKeyArea, 0x1000);
/// Plaintext area. Dumped from FS program memory.
/// Overall structure may change with each new LAFW version.
typedef struct {
u32 asic_security_mode; ///< Determines how the Lotus ASIC initialised the gamecard security mode. Usually 0xFFFFFFF9.
u32 asic_status; ///< Bitmask of the internal gamecard interface status. Usually 0x20000000.
FsCardId1 card_id1;
FsCardId2 card_id2;
u8 card_uid[0x40];
u8 reserved[0x190];
u8 asic_session_hash[0x20]; ///< Changes with each gamecard (re)insertion.
} GameCardSpecificData;
NXDT_ASSERT(GameCardSpecificData, 0x200);
/// Plaintext area. Dumped from FS program memory.
/// This struct is returned by Lotus command "ChangeToSecureMode" (0xF). This means it is only available *after* the gamecard secure area has been mounted.
/// A copy of the gamecard header without the RSA-2048 signature and a plaintext GameCardInfo precedes this struct in FS program memory.
typedef struct {
GameCardSpecificData specific_data;
FsGameCardCertificate certificate;
u8 reserved[0x200];
GameCardInitialData initial_data;
} GameCardSecurityInformation;
NXDT_ASSERT(GameCardSecurityInformation, 0x800);
typedef enum {
GameCardKekIndex_Version0 = 0,
GameCardKekIndex_VersionForDev = 1
GameCardKekIndex_VersionForDev = 1,
GameCardKekIndex_Count = 2 ///< Total values supported by this enum.
} GameCardKekIndex;
typedef struct {
@ -139,17 +140,20 @@ typedef enum {
} GameCardRomSize;
typedef enum {
GameCardFlags_None = 0,
GameCardFlags_AutoBoot = BIT(0),
GameCardFlags_HistoryErase = BIT(1),
GameCardFlags_RepairTool = BIT(2),
GameCardFlags_DifferentRegionCupToTerraDevice = BIT(3),
GameCardFlags_DifferentRegionCupToGlobalDevice = BIT(4),
GameCardFlags_HasCa10Certificate = BIT(7)
GameCardFlags_HasCa10Certificate = BIT(7),
GameCardFlags_Count = 6 ///< Total values supported by this enum.
} GameCardFlags;
typedef enum {
GameCardSelSec_ForT1 = 1,
GameCardSelSec_ForT2 = 2
GameCardSelSec_ForT2 = 2,
GameCardSelSec_Count = 2 ///< Total values supported by this enum.
} GameCardSelSec;
typedef enum {
@ -159,7 +163,7 @@ typedef enum {
GameCardFwVersion_Since900NUP = 3, ///< upp_version >= 603979776 (9.0.0-0.0) in GameCardInfo. Seems to be unused.
GameCardFwVersion_Since1100NUP = 4, ///< upp_version >= 738197504 (11.0.0-0.0) in GameCardInfo.
GameCardFwVersion_Since1200NUP = 5, ///< upp_version >= 805306368 (12.0.0-0.0) in GameCardInfo.
GameCardFwVersion_Count = 6
GameCardFwVersion_Count = 6 ///< Total values supported by this enum.
} GameCardFwVersion;
typedef enum {
@ -170,7 +174,7 @@ typedef enum {
typedef enum {
GameCardCompatibilityType_Normal = 0,
GameCardCompatibilityType_Terra = 1,
GameCardCompatibilityType_Count = 2
GameCardCompatibilityType_Count = 2 ///< Total values supported by this enum.
} GameCardCompatibilityType;
/// Encrypted using AES-128-CBC with the XCI header key (found in FS program memory under HOS 9.0.0+) and the IV from `GameCardHeader`.
@ -187,7 +191,8 @@ typedef struct {
u8 reserved_1[0x3];
u64 upp_hash; ///< Checksum for the update partition. The exact way it's calculated is currently unknown.
u64 upp_id; ///< Must match GAMECARD_UPDATE_TID.
u8 reserved_2[0x38];
u8 reserved_2[0x28];
u8 unknown[0x10]; ///< Unknown purpose. It's not zeroed out in recent (2021+?) gamecards.
} GameCardInfo;
NXDT_ASSERT(GameCardInfo, 0x70);
@ -227,7 +232,8 @@ typedef enum {
GameCardStatus_LotusAsicFirmwareUpdateRequired = 3, ///< A gamecard has been inserted, but a LAFW update is needed before being able to read the secure storage area.
///< Operations on the normal storage area are still possible, though.
GameCardStatus_InsertedAndInfoNotLoaded = 4, ///< A gamecard has been inserted, but an unexpected error unrelated to both "nogc" patch and LAFW version occurred.
GameCardStatus_InsertedAndInfoLoaded = 5 ///< A gamecard has been inserted and all required information could be successfully retrieved from it.
GameCardStatus_InsertedAndInfoLoaded = 5, ///< A gamecard has been inserted and all required information could be successfully retrieved from it.
GameCardStatus_Count = 6 ///< Total values supported by this enum.
} GameCardStatus;
typedef enum {
@ -242,7 +248,7 @@ typedef enum {
LotusAsicDeviceType_Dev = 1,
LotusAsicDeviceType_Prod = 2,
LotusAsicDeviceType_Prod2Dev = 3,
LotusAsicDeviceType_Count = 4 ///< Not a real value.
LotusAsicDeviceType_Count = 4 ///< Total values supported by this enum.
} LotusAsicDeviceType;
/// Plaintext Lotus ASIC firmware (LAFW) blob. Dumped from FS program memory.

View file

@ -30,9 +30,12 @@ extern "C" {
#endif
typedef enum {
MemoryProgramSegmentType_None = 0,
MemoryProgramSegmentType_Text = BIT(0),
MemoryProgramSegmentType_Rodata = BIT(1),
MemoryProgramSegmentType_Data = BIT(2)
MemoryProgramSegmentType_Data = BIT(2),
MemoryProgramSegmentType_All = (MemoryProgramSegmentType_Data | MemoryProgramSegmentType_Rodata | MemoryProgramSegmentType_Text),
MemoryProgramSegmentType_Limit = (MemoryProgramSegmentType_All + 1) ///< Placed here for convenience.
} MemoryProgramSegmentType;
typedef struct {
@ -43,7 +46,7 @@ typedef struct {
} MemoryLocation;
/// Retrieves memory segment (.text, .rodata, .data) data from a running program.
/// These are memory pages with read permission (Perm_R) enabled and type MemType_CodeStatic or MemType_CodeMutable.
/// These are memory pages with read permission (Perm_R) enabled, with type MemType_CodeStatic or MemType_CodeMutable and no MemoryAttribute flag set.
bool memRetrieveProgramMemorySegment(MemoryLocation *location);
/// Retrieves full memory data from a running program.

View file

@ -64,6 +64,7 @@ typedef enum {
} NacpAddOnContentRegistrationType;
typedef enum {
NacpAttribute_None = 0,
NacpAttribute_Demo = BIT(0),
NacpAttribute_RetailInteractiveDisplay = BIT(1),
NacpAttribute_DownloadPlay = BIT(2), ///< Removed.
@ -96,23 +97,24 @@ typedef enum {
} NacpLanguage;
typedef enum {
NacpSupportedLanguage_AmericanEnglish = BIT(0),
NacpSupportedLanguage_BritishEnglish = BIT(1),
NacpSupportedLanguage_Japanese = BIT(2),
NacpSupportedLanguage_French = BIT(3),
NacpSupportedLanguage_German = BIT(4),
NacpSupportedLanguage_LatinAmericanSpanish = BIT(5),
NacpSupportedLanguage_Spanish = BIT(6),
NacpSupportedLanguage_Italian = BIT(7),
NacpSupportedLanguage_Dutch = BIT(8),
NacpSupportedLanguage_CanadianFrench = BIT(9),
NacpSupportedLanguage_Portuguese = BIT(10),
NacpSupportedLanguage_Russian = BIT(11),
NacpSupportedLanguage_Korean = BIT(12),
NacpSupportedLanguage_TraditionalChinese = BIT(13),
NacpSupportedLanguage_SimplifiedChinese = BIT(14),
NacpSupportedLanguage_BrazilianPortuguese = BIT(15),
NacpSupportedLanguage_Count = 16, ///< Total values supported by this enum. Should always match NacpLanguage_Count.
NacpSupportedLanguage_None = 0,
NacpSupportedLanguage_AmericanEnglish = BIT(NacpLanguage_AmericanEnglish),
NacpSupportedLanguage_BritishEnglish = BIT(NacpLanguage_BritishEnglish),
NacpSupportedLanguage_Japanese = BIT(NacpLanguage_Japanese),
NacpSupportedLanguage_French = BIT(NacpLanguage_French),
NacpSupportedLanguage_German = BIT(NacpLanguage_German),
NacpSupportedLanguage_LatinAmericanSpanish = BIT(NacpLanguage_LatinAmericanSpanish),
NacpSupportedLanguage_Spanish = BIT(NacpLanguage_Spanish),
NacpSupportedLanguage_Italian = BIT(NacpLanguage_Italian),
NacpSupportedLanguage_Dutch = BIT(NacpLanguage_Dutch),
NacpSupportedLanguage_CanadianFrench = BIT(NacpLanguage_CanadianFrench),
NacpSupportedLanguage_Portuguese = BIT(NacpLanguage_Portuguese),
NacpSupportedLanguage_Russian = BIT(NacpLanguage_Russian),
NacpSupportedLanguage_Korean = BIT(NacpLanguage_Korean),
NacpSupportedLanguage_TraditionalChinese = BIT(NacpLanguage_TraditionalChinese),
NacpSupportedLanguage_SimplifiedChinese = BIT(NacpLanguage_SimplifiedChinese),
NacpSupportedLanguage_BrazilianPortuguese = BIT(NacpLanguage_BrazilianPortuguese),
NacpSupportedLanguage_Count = NacpLanguage_Count, ///< Total values supported by this enum.
///< Old.
NacpSupportedLanguage_Taiwanese = NacpSupportedLanguage_TraditionalChinese,
@ -120,6 +122,7 @@ typedef enum {
} NacpSupportedLanguage;
typedef enum {
NacpParentalControl_None = 0,
NacpParentalControl_FreeCommunication = BIT(0),
NacpParentalControl_Count = 1 ///< Total values supported by this enum.
} NacpParentalControl;
@ -249,6 +252,7 @@ typedef enum {
} NacpHdcp;
typedef enum {
NacpStartupUserAccountOption_None = 0,
NacpStartupUserAccountOption_IsOptional = BIT(0),
NacpStartupUserAccountOption_Count = 1 ///< Total values supported by this enum.
} NacpStartupUserAccountOption;
@ -260,6 +264,7 @@ typedef enum {
} NacpRuntimeUpgrade;
typedef enum {
NacpSupportingLimitedApplicationLicenses_None = 0,
NacpSupportingLimitedApplicationLicenses_Demo = BIT(0),
NacpSupportingLimitedApplicationLicenses_Count = 1 ///< Total values supported by this enum.
} NacpSupportingLimitedApplicationLicenses;
@ -272,16 +277,19 @@ typedef enum {
} NacpPlayLogQueryCapability;
typedef enum {
NacpRepair_None = 0,
NacpRepair_SuppressGameCardAccess = BIT(0),
NacpRepair_Count = 1 ///< Total values supported by this enum.
} NacpRepair;
typedef enum {
NacpRequiredNetworkServiceLicenseOnLaunch_None = 0,
NacpRequiredNetworkServiceLicenseOnLaunch_Common = BIT(0),
NacpRequiredNetworkServiceLicenseOnLaunch_Count = 1 ///< Total values supported by this enum.
} NacpRequiredNetworkServiceLicenseOnLaunch;
typedef enum {
NacpJitConfigurationFlag_None = 0,
NacpJitConfigurationFlag_Enabled = BITL(0),
NacpJitConfigurationFlag_Count = 1 ///< Total values supported by this enum.
} NacpJitConfigurationFlag;
@ -295,7 +303,8 @@ NXDT_ASSERT(NacpJitConfiguration, 0x10);
typedef enum {
NacpRequiredAddOnContentsSetDescriptorFlag_None = 0,
NacpRequiredAddOnContentsSetDescriptorFlag_Continue = 1
NacpRequiredAddOnContentsSetDescriptorFlag_Continue = 1,
NacpRequiredAddOnContentsSetDescriptorFlag_Count = 2 ///< Total values supported by this enum.
} NacpRequiredAddOnContentsSetDescriptorFlag;
typedef struct {
@ -312,6 +321,7 @@ typedef struct {
NXDT_ASSERT(NacpRequiredAddOnContentsSetBinaryDescriptor, 0x40);
typedef enum {
NacpPlayReportPermission_None = 0,
NacpPlayReportPermission_TargetMarketing = BIT(0),
NacpPlayReportPermission_Count = 1 ///< Total values supported by this enum.
} NacpPlayReportPermission;

View file

@ -62,7 +62,8 @@ extern "C" {
typedef enum {
NcaDistributionType_Download = 0,
NcaDistributionType_GameCard = 1
NcaDistributionType_GameCard = 1,
NcaDistributionType_Count = 2 ///< Total values supported by this enum.
} NcaDistributionType;
typedef enum {
@ -71,7 +72,8 @@ typedef enum {
NcaContentType_Control = 2,
NcaContentType_Manual = 3,
NcaContentType_Data = 4,
NcaContentType_PublicData = 5
NcaContentType_PublicData = 5,
NcaContentType_Count = 6 ///< Total values supported by this enum.
} NcaContentType;
/// 'NcaKeyGeneration_Current' will always point to the last known key generation value.
@ -101,7 +103,7 @@ typedef enum {
NcaKeyAreaEncryptionKeyIndex_Application = 0,
NcaKeyAreaEncryptionKeyIndex_Ocean = 1,
NcaKeyAreaEncryptionKeyIndex_System = 2,
NcaKeyAreaEncryptionKeyIndex_Count = 3
NcaKeyAreaEncryptionKeyIndex_Count = 3 ///< Total values supported by this enum.
} NcaKeyAreaEncryptionKeyIndex;
/// 'NcaSignatureKeyGeneration_Current' will always point to the last known key generation value.
@ -172,7 +174,8 @@ NXDT_ASSERT(NcaHeader, 0x400);
typedef enum {
NcaFsType_RomFs = 0,
NcaFsType_PartitionFs = 1
NcaFsType_PartitionFs = 1,
NcaFsType_Count = 2 ///< Total values supported by this enum.
} NcaFsType;
typedef enum {
@ -182,7 +185,8 @@ typedef enum {
NcaHashType_HierarchicalIntegrity = 3, ///< Used by NcaFsType_RomFs.
NcaHashType_AutoSha3 = 4,
NcaHashType_HierarchicalSha3256 = 5, ///< Used by NcaFsType_PartitionFs.
NcaHashType_HierarchicalIntegritySha3 = 6 ///< Used by NcaFsType_RomFs.
NcaHashType_HierarchicalIntegritySha3 = 6, ///< Used by NcaFsType_RomFs.
NcaHashType_Count = 7 ///< Total values supported by this enum.
} NcaHashType;
typedef enum {
@ -192,13 +196,15 @@ typedef enum {
NcaEncryptionType_AesCtr = 3,
NcaEncryptionType_AesCtrEx = 4,
NcaEncryptionType_AesCtrSkipLayerHash = 5,
NcaEncryptionType_AesCtrExSkipLayerHash = 6
NcaEncryptionType_AesCtrExSkipLayerHash = 6,
NcaEncryptionType_Count = 7 ///< Total values supported by this enum.
} NcaEncryptionType;
typedef enum {
NcaMetaDataHashType_None = 0,
NcaMetaDataHashType_HierarchicalIntegrity = 1,
NcaMetaDataHashType_HierarchicalIntegritySha3 = 2
NcaMetaDataHashType_HierarchicalIntegritySha3 = 2,
NcaMetaDataHashType_Count = 3 ///< Total values supported by this enum.
} NcaMetaDataHashType;
typedef struct {
@ -408,9 +414,10 @@ typedef struct {
} NcaFsSectionContext;
typedef enum {
NcaVersion_Nca0 = 0,
NcaVersion_Nca2 = 2,
NcaVersion_Nca3 = 3
NcaVersion_Nca0 = 0,
NcaVersion_Nca2 = 1,
NcaVersion_Nca3 = 2,
NcaVersion_Count = 3 ///< Total values supported by this enum.
} NcaVersion;
typedef struct {

View file

@ -31,11 +31,12 @@ extern "C" {
#endif
typedef enum {
NcaStorageBaseStorageType_Invalid = 0, /* Placeholder. */
NcaStorageBaseStorageType_Invalid = 0, ///< Placeholder.
NcaStorageBaseStorageType_Regular = 1,
NcaStorageBaseStorageType_Sparse = 2,
NcaStorageBaseStorageType_Indirect = 3,
NcaStorageBaseStorageType_Compressed = 4
NcaStorageBaseStorageType_Compressed = 4,
NcaStorageBaseStorageType_Count = 5 ///< Total values supported by this enum.
} NcaStorageBaseStorageType;
/// Used to perform multi-layered reads within a single NCA FS section.

View file

@ -52,7 +52,8 @@ typedef enum {
NpdmProcessAddressSpace_AddressSpace32Bit = 0,
NpdmProcessAddressSpace_AddressSpace64BitOld = 1,
NpdmProcessAddressSpace_AddressSpace32BitNoReserved = 2,
NpdmProcessAddressSpace_AddressSpace64Bit = 3
NpdmProcessAddressSpace_AddressSpace64Bit = 3,
NpdmProcessAddressSpace_Count = 4 ///< Total values supported by this enum.
} NpdmProcessAddressSpace;
typedef struct {
@ -95,6 +96,7 @@ typedef enum {
NpdmMemoryRegion_Applet = 1,
NpdmMemoryRegion_SecureSystem = 2,
NpdmMemoryRegion_NonSecureSystem = 3,
NpdmMemoryRegion_Count = 4, ///< Total values supported by this enum.
/// Old.
NpdmMemoryRegion_NonSecure = NpdmMemoryRegion_Application,
@ -153,6 +155,7 @@ typedef struct {
NXDT_ASSERT(NpdmAciHeader, 0x40);
typedef enum {
NpdmFsAccessControlFlags_None = 0,
NpdmFsAccessControlFlags_ApplicationInfo = BITL(0),
NpdmFsAccessControlFlags_BootModeControl = BITL(1),
NpdmFsAccessControlFlags_Calibration = BITL(2),
@ -193,7 +196,8 @@ typedef enum {
NpdmFsAccessControlFlags_DeviceTreeBlob = BITL(37),
NpdmFsAccessControlFlags_NotifyErrorContextServiceReady = BITL(38),
NpdmFsAccessControlFlags_Debug = BITL(62),
NpdmFsAccessControlFlags_FullPermission = BITL(63)
NpdmFsAccessControlFlags_FullPermission = BITL(63),
NpdmFsAccessControlFlags_Count = 64 ///< Total values supported by this enum.
} NpdmFsAccessControlFlags;
/// FsAccessControl descriptor. Part of the ACID section body.
@ -246,9 +250,11 @@ typedef struct {
NXDT_ASSERT(NpdmFsAccessControlDataContentOwnerBlock, 0x4);
typedef enum {
NpdmAccessibility_None = 0,
NpdmAccessibility_Read = BIT(0),
NpdmAccessibility_Write = BIT(1),
NpdmAccessibility_ReadWrite = NpdmAccessibility_Read | NpdmAccessibility_Write
NpdmAccessibility_ReadWrite = (NpdmAccessibility_Read | NpdmAccessibility_Write),
NpdmAccessibility_Count = 3 ///< Total values supported by this enum.
} NpdmAccessibility;
/// Placed after NpdmFsAccessControlData / NpdmFsAccessControlDataContentOwnerBlock if the 'save_data_owner_info_size' member from NpdmFsAccessControlData is greater than zero.
@ -273,35 +279,35 @@ typedef struct {
NXDT_ASSERT(NpdmSrvAccessControlDescriptorEntry, 0x1);
typedef enum {
NpdmKernelCapabilityEntryNumber_ThreadInfo = 3,
NpdmKernelCapabilityEntryNumber_EnableSystemCalls = 4,
NpdmKernelCapabilityEntryNumber_MemoryMap = 6,
NpdmKernelCapabilityEntryNumber_IoMemoryMap = 7,
NpdmKernelCapabilityEntryNumber_MemoryRegionMap = 10,
NpdmKernelCapabilityEntryNumber_EnableInterrupts = 11,
NpdmKernelCapabilityEntryNumber_MiscParams = 13,
NpdmKernelCapabilityEntryNumber_KernelVersion = 14,
NpdmKernelCapabilityEntryNumber_HandleTableSize = 15,
NpdmKernelCapabilityEntryNumber_MiscFlags = 16
} NpdmKernelCapabilityEntryNumber;
NpdmKernelCapabilityEntryBitmaskSize_ThreadInfo = 3,
NpdmKernelCapabilityEntryBitmaskSize_EnableSystemCalls = 4,
NpdmKernelCapabilityEntryBitmaskSize_MemoryMap = 6,
NpdmKernelCapabilityEntryBitmaskSize_IoMemoryMap = 7,
NpdmKernelCapabilityEntryBitmaskSize_MemoryRegionMap = 10,
NpdmKernelCapabilityEntryBitmaskSize_EnableInterrupts = 11,
NpdmKernelCapabilityEntryBitmaskSize_MiscParams = 13,
NpdmKernelCapabilityEntryBitmaskSize_KernelVersion = 14,
NpdmKernelCapabilityEntryBitmaskSize_HandleTableSize = 15,
NpdmKernelCapabilityEntryBitmaskSize_MiscFlags = 16
} NpdmKernelCapabilityEntryBitmaskSize;
typedef enum {
NpdmKernelCapabilityEntryValue_ThreadInfo = BIT(NpdmKernelCapabilityEntryNumber_ThreadInfo) - 1,
NpdmKernelCapabilityEntryValue_EnableSystemCalls = BIT(NpdmKernelCapabilityEntryNumber_EnableSystemCalls) - 1,
NpdmKernelCapabilityEntryValue_MemoryMap = BIT(NpdmKernelCapabilityEntryNumber_MemoryMap) - 1,
NpdmKernelCapabilityEntryValue_IoMemoryMap = BIT(NpdmKernelCapabilityEntryNumber_IoMemoryMap) - 1,
NpdmKernelCapabilityEntryValue_MemoryRegionMap = BIT(NpdmKernelCapabilityEntryNumber_MemoryRegionMap) - 1,
NpdmKernelCapabilityEntryValue_EnableInterrupts = BIT(NpdmKernelCapabilityEntryNumber_EnableInterrupts) - 1,
NpdmKernelCapabilityEntryValue_MiscParams = BIT(NpdmKernelCapabilityEntryNumber_MiscParams) - 1,
NpdmKernelCapabilityEntryValue_KernelVersion = BIT(NpdmKernelCapabilityEntryNumber_KernelVersion) - 1,
NpdmKernelCapabilityEntryValue_HandleTableSize = BIT(NpdmKernelCapabilityEntryNumber_HandleTableSize) - 1,
NpdmKernelCapabilityEntryValue_MiscFlags = BIT(NpdmKernelCapabilityEntryNumber_MiscFlags) - 1
} NpdmKernelCapabilityEntryValue;
NpdmKernelCapabilityEntryBitmaskPattern_ThreadInfo = BIT(NpdmKernelCapabilityEntryBitmaskSize_ThreadInfo) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_EnableSystemCalls = BIT(NpdmKernelCapabilityEntryBitmaskSize_EnableSystemCalls) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_MemoryMap = BIT(NpdmKernelCapabilityEntryBitmaskSize_MemoryMap) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_IoMemoryMap = BIT(NpdmKernelCapabilityEntryBitmaskSize_IoMemoryMap) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_MemoryRegionMap = BIT(NpdmKernelCapabilityEntryBitmaskSize_MemoryRegionMap) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_EnableInterrupts = BIT(NpdmKernelCapabilityEntryBitmaskSize_EnableInterrupts) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_MiscParams = BIT(NpdmKernelCapabilityEntryBitmaskSize_MiscParams) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_KernelVersion = BIT(NpdmKernelCapabilityEntryBitmaskSize_KernelVersion) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_HandleTableSize = BIT(NpdmKernelCapabilityEntryBitmaskSize_HandleTableSize) - 1,
NpdmKernelCapabilityEntryBitmaskPattern_MiscFlags = BIT(NpdmKernelCapabilityEntryBitmaskSize_MiscFlags) - 1
} NpdmKernelCapabilityEntryBitmaskPattern;
/// ThreadInfo entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_ThreadInfo; ///< Always set to NpdmKernelCapabilityEntryValue_ThreadInfo.
u32 padding : 1; ///< Always set to zero.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_ThreadInfo; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_ThreadInfo.
u32 padding : 1; ///< Always set to zero.
u32 lowest_priority : 6;
u32 highest_priority : 6;
u32 min_core_number : 8;
@ -312,6 +318,8 @@ NXDT_ASSERT(NpdmThreadInfo, 0x4);
/// System call table.
typedef enum {
NpdmSystemCallId_None = 0,
///< System calls for index 0.
NpdmSystemCallId_Reserved1 = BIT(0), ///< SVC 0x00.
NpdmSystemCallId_SetHeapSize = BIT(1), ///< SVC 0x01.
@ -525,39 +533,41 @@ typedef enum {
/// EnableSystemCalls entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_EnableSystemCalls; ///< Always set to NpdmKernelCapabilityEntryValue_EnableSystemCalls.
u32 padding : 1; ///< Always set to zero.
u32 system_call_ids : 24; ///< NpdmSystemCallId.
u32 index : 3; ///< System calls index.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_EnableSystemCalls; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_EnableSystemCalls.
u32 padding : 1; ///< Always set to zero.
u32 system_call_ids : 24; ///< NpdmSystemCallId.
u32 index : 3; ///< System calls index.
} NpdmEnableSystemCalls;
NXDT_ASSERT(NpdmEnableSystemCalls, 0x4);
typedef enum {
NpdmPermissionType_RW = 0,
NpdmPermissionType_RO = 1
NpdmPermissionType_RW = 0,
NpdmPermissionType_RO = 1,
NpdmPermissionType_Count = 2 ///< Total values supported by this enum.
} NpdmPermissionType;
typedef enum {
NpdmMappingType_Io = 0,
NpdmMappingType_Static = 1
NpdmMappingType_Static = 1,
NpdmMappingType_Count = 2 ///< Total values supported by this enum.
} NpdmMappingType;
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
u32 permission_type : 1; ///< NpdmPermissionType.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_MemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
u32 permission_type : 1; ///< NpdmPermissionType.
} NpdmMemoryMapType1;
NXDT_ASSERT(NpdmMemoryMapType1, 0x4);
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 size : 20; ///< size << 12.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_MemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 size : 20; ///< size << 12.
u32 reserved : 4;
u32 mapping_type : 1; ///< NpdmMappingType.
u32 mapping_type : 1; ///< NpdmMappingType.
} NpdmMemoryMapType2;
NXDT_ASSERT(NpdmMemoryMapType2, 0x4);
@ -575,9 +585,9 @@ NXDT_ASSERT(NpdmMemoryMap, 0x4);
/// IoMemoryMap entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_IoMemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_IoMemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_IoMemoryMap; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_IoMemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
} NpdmIoMemoryMap;
NXDT_ASSERT(NpdmIoMemoryMap, 0x4);
@ -586,29 +596,30 @@ typedef enum {
NpdmRegionType_NoMapping = 0,
NpdmRegionType_KernelTraceBuffer = 1,
NpdmRegionType_OnMemoryBootImage = 2,
NpdmRegionType_DTB = 3
NpdmRegionType_DTB = 3,
NpdmRegionType_Count = 4 ///< Total values supported by this enum.
} NpdmRegionType;
/// MemoryRegionMap entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryRegionMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryRegionMap.
u32 padding : 1; ///< Always set to zero.
u32 region_type_0 : 6; ///< NpdmRegionType.
u32 permission_type_0 : 1; ///< NpdmPermissionType.
u32 region_type_1 : 6; ///< NpdmRegionType.
u32 permission_type_1 : 1; ///< NpdmPermissionType.
u32 region_type_2 : 6; ///< NpdmRegionType.
u32 permission_type_2 : 1; ///< NpdmPermissionType.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_MemoryRegionMap; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_MemoryRegionMap.
u32 padding : 1; ///< Always set to zero.
u32 region_type_0 : 6; ///< NpdmRegionType.
u32 permission_type_0 : 1; ///< NpdmPermissionType.
u32 region_type_1 : 6; ///< NpdmRegionType.
u32 permission_type_1 : 1; ///< NpdmPermissionType.
u32 region_type_2 : 6; ///< NpdmRegionType.
u32 permission_type_2 : 1; ///< NpdmPermissionType.
} NpdmMemoryRegionMap;
NXDT_ASSERT(NpdmMemoryRegionMap, 0x4);
/// EnableInterrupts entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_EnableInterrupts; ///< Always set to NpdmKernelCapabilityEntryValue_EnableInterrupts.
u32 padding : 1; ///< Always set to zero.
u32 interrupt_number_0 : 10; ///< 0x3FF means empty.
u32 interrupt_number_1 : 10; ///< 0x3FF means empty.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_EnableInterrupts; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_EnableInterrupts.
u32 padding : 1; ///< Always set to zero.
u32 interrupt_number_0 : 10; ///< 0x3FF means empty.
u32 interrupt_number_1 : 10; ///< 0x3FF means empty.
} NpdmEnableInterrupts;
NXDT_ASSERT(NpdmEnableInterrupts, 0x4);
@ -616,15 +627,16 @@ NXDT_ASSERT(NpdmEnableInterrupts, 0x4);
typedef enum {
NpdmProgramType_System = 0,
NpdmProgramType_Application = 1,
NpdmProgramType_Applet = 2
NpdmProgramType_Applet = 2,
NpdmProgramType_Count = 3 ///< Total values supported by this enum.
} NpdmProgramType;
/// MiscParams entry for the KernelCapability descriptor.
/// Defaults to 0 if this entry doesn't exist.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscParams; ///< Always set to NpdmKernelCapabilityEntryValue_MiscParams.
u32 padding : 1; ///< Always set to zero.
u32 program_type : 3; ///< NpdmProgramType.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_MiscParams; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_MiscParams.
u32 padding : 1; ///< Always set to zero.
u32 program_type : 3; ///< NpdmProgramType.
u32 reserved : 15;
} NpdmMiscParams;
@ -633,18 +645,18 @@ NXDT_ASSERT(NpdmMiscParams, 0x4);
/// KernelVersion entry for the KernelCapability descriptor.
/// This is derived from/equivalent to SDK version.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_KernelVersion; ///< Always set to NpdmKernelCapabilityEntryValue_KernelVersion.
u32 padding : 1; ///< Always set to zero.
u32 minor_version : 4; ///< SDK minor version.
u32 major_version : 13; ///< SDK major version + 4.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_KernelVersion; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_KernelVersion.
u32 padding : 1; ///< Always set to zero.
u32 minor_version : 4; ///< SDK minor version.
u32 major_version : 13; ///< SDK major version + 4.
} NpdmKernelVersion;
NXDT_ASSERT(NpdmKernelVersion, 0x4);
/// HandleTableSize entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_HandleTableSize; ///< Always set to NpdmKernelCapabilityEntryValue_HandleTableSize.
u32 padding : 1; ///< Always set to zero.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_HandleTableSize; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_HandleTableSize.
u32 padding : 1; ///< Always set to zero.
u32 handle_table_size : 10;
u32 reserved : 6;
} NpdmHandleTableSize;
@ -653,8 +665,8 @@ NXDT_ASSERT(NpdmHandleTableSize, 0x4);
/// MiscFlags entry for the KernelCapability descriptor.
typedef struct {
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscFlags; ///< Always set to NpdmKernelCapabilityEntryValue_MiscFlags.
u32 padding : 1; ///< Always set to zero.
u32 bitmask : NpdmKernelCapabilityEntryBitmaskSize_MiscFlags; ///< Always set to NpdmKernelCapabilityEntryBitmaskPattern_MiscFlags.
u32 padding : 1; ///< Always set to zero.
u32 enable_debug : 1;
u32 force_debug : 1;
u32 reserved : 13;
@ -707,7 +719,8 @@ NX_INLINE bool npdmIsValidContext(NpdmContext *npdm_ctx)
((npdm_ctx->aci_header->kernel_capability_size && npdm_ctx->aci_kc_descriptor) || (!npdm_ctx->aci_header->kernel_capability_size && !npdm_ctx->aci_kc_descriptor)));
}
NX_INLINE u32 npdmGetKernelCapabilityDescriptorEntryValue(NpdmKernelCapabilityDescriptorEntry *entry)
/// Returns a value that can be loooked up in the NpdmKernelCapabilityEntryBitmaskPattern enum.
NX_INLINE u32 npdmGetKernelCapabilityDescriptorEntryBitmaskPattern(NpdmKernelCapabilityDescriptorEntry *entry)
{
return (entry ? (((entry->value + 1) & ~entry->value) - 1) : 0);
}

View file

@ -34,12 +34,14 @@ extern "C" {
#define NSO_MOD_MAGIC 0x4D4F4430 /* "MOD0". */
typedef enum {
NsoFlags_None = 0,
NsoFlags_TextCompress = BIT(0), ///< Determines if .text segment is LZ4-compressed.
NsoFlags_RoCompress = BIT(1), ///< Determines if .rodata segment is LZ4-compressed.
NsoFlags_DataCompress = BIT(2), ///< Determines if .data segment is LZ4-compressed.
NsoFlags_TextHash = BIT(3), ///< Determines if .text segment hash must be checked during load.
NsoFlags_RoHash = BIT(4), ///< Determines if .rodata segment hash must be checked during load.
NsoFlags_DataHash = BIT(5) ///< Determines if .data segment hash must be checked during load.
NsoFlags_DataHash = BIT(5), ///< Determines if .data segment hash must be checked during load.
NsoFlags_Count = 6 ///< Total values supported by this enum.
} NsoFlags;
typedef struct {

View file

@ -49,7 +49,8 @@ typedef enum {
UtilsCustomFirmwareType_Unknown = 0,
UtilsCustomFirmwareType_Atmosphere = 1,
UtilsCustomFirmwareType_SXOS = 2,
UtilsCustomFirmwareType_ReiNX = 3
UtilsCustomFirmwareType_ReiNX = 3,
UtilsCustomFirmwareType_Count = 4 ///< Total values supported by this enum.
} UtilsCustomFirmwareType;
/// Used to handle parsed data from a GitHub release JSON.

View file

@ -134,7 +134,8 @@ typedef struct {
typedef enum {
RomFileSystemPathIllegalCharReplaceType_None = 0,
RomFileSystemPathIllegalCharReplaceType_IllegalFsChars = 1,
RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly = 2
RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly = 2,
RomFileSystemPathIllegalCharReplaceType_Count = 3 ///< Total values supported by this enum.
} RomFileSystemPathIllegalCharReplaceType;
/// Initializes a RomFS or Patch RomFS context.

View file

@ -34,7 +34,7 @@ typedef enum {
SmcKeyType_NormalOnly = 1,
SmcKeyType_RecoveryOnly = 2,
SmcKeyType_NormalAndRecovery = 3,
SmcKeyType_Count = 4
SmcKeyType_Count = 4 ///< Total values supported by this enum.
} SmcKeyType;
typedef enum {
@ -45,7 +45,7 @@ typedef enum {
SmcSealKey_ReencryptDeviceUniqueData = 4,
SmcSealKey_ImportSslKey = 5,
SmcSealKey_ImportEsClientCertKey = 6,
SmcSealKey_Count = 7
SmcSealKey_Count = 7 ///< Total values supported by this enum.
} SmcSealKey;
typedef struct {

View file

@ -43,7 +43,8 @@ NXDT_ASSERT(TikSig##sigtype, tiksize);
typedef enum {
TikTitleKeyType_Common = 0,
TikTitleKeyType_Personalized = 1
TikTitleKeyType_Personalized = 1,
TikTitleKeyType_Count = 2 ///< Total values supported by this enum.
} TikTitleKeyType;
typedef enum {
@ -52,16 +53,19 @@ typedef enum {
TikLicenseType_Trial = 2,
TikLicenseType_Rental = 3,
TikLicenseType_Subscription = 4,
TikLicenseType_Service = 5
TikLicenseType_Service = 5,
TikLicenseType_Count = 6 ///< Total values supported by this enum.
} TikLicenseType;
typedef enum {
TikPropertyMask_None = 0,
TikPropertyMask_PreInstallation = BIT(0),
TikPropertyMask_SharedTitle = BIT(1),
TikPropertyMask_AllContents = BIT(2),
TikPropertyMask_DeviceLinkIndepedent = BIT(3),
TikPropertyMask_Volatile = BIT(4), ///< Used to determine if the ticket copy inside ticket.bin should be encrypted or not.
TikPropertyMask_ELicenseRequired = BIT(5) ///< Used to determine if the console should connect to the Internet to perform elicense verification.
TikPropertyMask_ELicenseRequired = BIT(5), ///< Used to determine if the console should connect to the Internet to perform elicense verification.
TikPropertyMask_Count = 6 ///< Total values supported by this enum.
} TikPropertyMask;
/// Placed after the ticket signature block.
@ -92,12 +96,14 @@ NXDT_ASSERT(TikCommonBlock, 0x180);
/// Each ESV2 section record is followed by a 'record_count' number of ESV1 records, each one of 'record_size' size.
typedef enum {
TikSectionType_None = 0,
TikSectionType_Permanent = 1,
TikSectionType_Subscription = 2,
TikSectionType_Content = 3,
TikSectionType_ContentConsumption = 4,
TikSectionType_AccessTitle = 5,
TikSectionType_LimitedResource = 6
TikSectionType_LimitedResource = 6,
TikSectionType_Count = 7 ///< Total values supported by this enum.
} TikSectionType;
typedef struct {
@ -159,7 +165,8 @@ typedef enum {
TikType_SigRsa4096 = 1,
TikType_SigRsa2048 = 2,
TikType_SigEcc480 = 3,
TikType_SigHmac160 = 4
TikType_SigHmac160 = 4,
TikType_Count = 5 ///< Total values supported by this enum.
} TikType;
/// Used to store ticket type, size and raw data, as well as titlekey data.

View file

@ -77,13 +77,14 @@ typedef enum {
///< Gamecards: "{Name1} [{Id1}][v{Version1}] + ... + {NameN} [{IdN}][v{VersionN}]".
TitleNamingConvention_IdAndVersionOnly = 1, ///< Individual titles: "{Id}_v{Version}_{Type}".
///< Gamecards: "{TitleId1}_v{TitleVersion1}_{TitleType1} + ... + {TitleIdN}_v{TitleVersionN}_{TitleTypeN}".
TitleNamingConvention_Count = 2
TitleNamingConvention_Count = 2 ///< Total values supported by this enum.
} TitleNamingConvention;
typedef enum {
TitleFileNameIllegalCharReplaceType_None = 0,
TitleFileNameIllegalCharReplaceType_IllegalFsChars = 1,
TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly = 2
TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly = 2,
TitleFileNameIllegalCharReplaceType_Count = 3 ///< Total values supported by this enum.
} TitleFileNameIllegalCharReplaceType;
/// Initializes the title interface.

View file

@ -38,7 +38,8 @@ typedef enum {
UsbHostSpeed_None = 0,
UsbHostSpeed_FullSpeed = 1, ///< USB 1.x.
UsbHostSpeed_HighSpeed = 2, ///< USB 2.0.
UsbHostSpeed_SuperSpeed = 3 ///< USB 3.0.
UsbHostSpeed_SuperSpeed = 3, ///< USB 3.0.
UsbHostSpeed_Count = 4 ///< Total values supported by this enum.
} UsbHostSpeed;
/// Initializes the USB interface, input and output endpoints and allocates an internal transfer buffer.

@ -1 +1 @@
Subproject commit 55f5a140770b10899e3c5e3a08243471fe8e9ba7
Subproject commit a11eb0d7083fba72aade29d3f9b35070d5510c3d

View file

@ -18,7 +18,7 @@
"enable_screenshots": false,
"enable_video_capture": false,
"disable_hdcp": false,
"append_authoringtool_data": false,
"generate_authoringtool_data": false,
"lookup_checksum": true
},
"ticket": {

View file

@ -208,7 +208,7 @@ void bfttfExit(void)
bool bfttfGetFontByType(BfttfFontData *font_data, u8 font_type)
{
if (!font_data || font_type >= BfttfFontType_Total)
if (!font_data || font_type >= BfttfFontType_Count)
{
LOG_MSG_ERROR("Invalid parameters!");
return false;

View file

@ -240,7 +240,7 @@ static bool configValidateJsonNspObject(const struct json_object *obj)
{
bool ret = false, set_download_distribution_found = false, remove_console_data_found = false, remove_titlekey_crypto_found = false;
bool disable_linked_account_requirement_found = false, enable_screenshots_found = false, enable_video_capture_found = false, disable_hdcp_found = false;
bool append_authoringtool_data_found = false, lookup_checksum_found = false;
bool generate_authoringtool_data_found = false, lookup_checksum_found = false;
if (!jsonValidateObject(obj)) goto end;
@ -254,12 +254,12 @@ static bool configValidateJsonNspObject(const struct json_object *obj)
CONFIG_VALIDATE_FIELD(Boolean, enable_video_capture);
CONFIG_VALIDATE_FIELD(Boolean, disable_hdcp);
CONFIG_VALIDATE_FIELD(Boolean, lookup_checksum);
CONFIG_VALIDATE_FIELD(Boolean, append_authoringtool_data);
CONFIG_VALIDATE_FIELD(Boolean, generate_authoringtool_data);
goto end;
}
ret = (set_download_distribution_found && remove_console_data_found && remove_titlekey_crypto_found && disable_linked_account_requirement_found && \
enable_screenshots_found && enable_video_capture_found && disable_hdcp_found && append_authoringtool_data_found && lookup_checksum_found);
enable_screenshots_found && enable_video_capture_found && disable_hdcp_found && generate_authoringtool_data_found && lookup_checksum_found);
end:
return ret;

View file

@ -582,19 +582,14 @@ static bool gamecardReadLotusAsicFirmwareBlob(void)
/* Temporarily set the segment mask to .data. */
g_fsProgramMemory.mask = MemoryProgramSegmentType_Data;
/* Retrieve full FS program memory dump. */
ret = memRetrieveProgramMemorySegment(&g_fsProgramMemory);
/* Clear segment mask. */
g_fsProgramMemory.mask = 0;
if (!ret)
/* Retrieve FS .data segment memory dump. */
if (!memRetrieveProgramMemorySegment(&g_fsProgramMemory))
{
LOG_MSG_ERROR("Failed to retrieve FS .data segment dump!");
goto end;
}
/* Look for the LAFW ReadFw blob in the FS .data memory dump. */
/* Look for the LAFW ReadFw blob in the FS .data segment memory dump. */
for(u64 offset = 0; offset < g_fsProgramMemory.data_size; offset++)
{
if ((g_fsProgramMemory.data_size - offset) < sizeof(LotusAsicFirmwareBlob)) break;
@ -635,6 +630,8 @@ static bool gamecardReadLotusAsicFirmwareBlob(void)
end:
memFreeMemoryLocation(&g_fsProgramMemory);
g_fsProgramMemory.mask = MemoryProgramSegmentType_None;
return ret;
}
@ -953,6 +950,7 @@ static bool gamecardReadSecurityInformation(GameCardSecurityInformation *out)
if (memcmp(g_fsProgramMemory.data + offset, &(g_gameCardHeader.package_id), sizeof(g_gameCardHeader.package_id)) != 0) continue;
sha256CalculateHash(tmp_hash, g_fsProgramMemory.data + offset, sizeof(GameCardInitialData));
if (!memcmp(tmp_hash, g_gameCardHeader.initial_data_hash, SHA256_HASH_SIZE))
{
/* Jackpot. */

View file

@ -23,8 +23,14 @@
#include "nxdt_utils.h"
#include "mem.h"
#define MEMLOG_DEBUG(fmt, ...) LOG_MSG_BUF_DEBUG(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
#define MEMLOG_ERROR(fmt, ...) LOG_MSG_BUF_ERROR(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
#define MEMLOG_DEBUG(fmt, ...) LOG_MSG_BUF_DEBUG(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
#define MEMLOG_ERROR(fmt, ...) LOG_MSG_BUF_ERROR(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
#define MEM_PID_BUF_SIZE 300
#define MEM_INVALID_SEGMENT_PAGE_TYPE(x) ((x) != MemType_CodeStatic && (x) != MemType_CodeMutable)
#define MEM_INVALID_FS_PAGE_TYPE(x) ((x) == MemType_Unmapped || (x) == MemType_Io || (x) == MemType_ThreadLocal || (x) == MemType_Reserved)
/* Global variables. */
@ -43,7 +49,7 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id);
bool memRetrieveProgramMemorySegment(MemoryLocation *location)
{
if (!location || !location->program_id || !location->mask || location->mask >= BIT(3))
if (!location || !location->program_id || !location->mask || location->mask >= MemoryProgramSegmentType_Limit)
{
LOG_MSG_ERROR("Invalid parameters!");
return false;
@ -76,7 +82,7 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
u32 page_info = 0;
u64 addr = 0, last_text_addr = 0;
u8 segment = 1, mem_type = 0;
u8 segment = MemoryProgramSegmentType_Text, mem_type = 0;
u8 *tmp = NULL;
bool success = true;
@ -98,8 +104,9 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
#if LOG_LEVEL < LOG_LEVEL_NONE
/* LOG_*() macros will be useless if the target program is the FS sysmodule. */
/* This is because any FS I/O operation *will* lock up the console while FS itself is being debugged. */
/* So we'll just temporarily log data to a char array using LOG_MSG_BUF_*() macros, then write it all out after calling svcCloseHandle(). */
/* So we'll just log data to a temporary buffer using LOG_MSG_BUF_*() macros, then write it all out to the logfile after calling svcCloseHandle(). */
/* However, we must prevent other threads from logging data as well in order to avoid a lock up, so we'll temporarily lock the logfile mutex. */
/* We don't need to take care of manually (re)allocating memory for our buffer -- the log handler ABI takes care of that for us. */
logControlMutex(true);
#endif
@ -112,11 +119,12 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
if (is_segment && location->program_id == FS_SYSMODULE_TID)
{
/* Only look for the FS .text segment address if we haven't previously retrieved it. */
/* Locate the "real" FS .text segment, since Atmosphère emuMMC has two. */
/* We'll only look for it if we haven't previously retrieved it, though. */
if (!g_fsTextSegmentAddr)
{
/* Locate the "real" FS .text segment, since Atmosphère emuMMC has two. */
do {
/* Query memory page info. */
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
if (R_FAILED(rc))
{
@ -125,27 +133,39 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
goto end;
}
mem_type = (u8)(mem_info.type & MemState_Type);
addr = (mem_info.addr + mem_info.size);
/* Filter out unwanted memory pages. */
if (MEM_INVALID_SEGMENT_PAGE_TYPE(mem_type) || mem_info.attr || (mem_info.perm & Perm_Rx) != Perm_Rx) continue;
#if LOG_LEVEL == LOG_LEVEL_DEBUG
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (#1) (program %016lX, page 0x%X, debug handle 0x%X, address 0x%lX):\r\n" \
"- addr: 0x%lX\r\n- size: 0x%lX\r\n- type: 0x%X\r\n- attr: 0x%X\r\n- perm: 0x%X\r\n- ipc_refcount: 0x%X\r\n- device_refcount: 0x%X", \
location->program_id, page_info, debug_handle, addr, \
mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, mem_info.ipc_refcount, mem_info.device_refcount);
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (FS .text segment lookup) (program %016lX, page 0x%X, debug handle 0x%X):\r\n" \
"- addr: 0x%lX\r\n" \
"- size: 0x%lX\r\n" \
"- type: 0x%X\r\n" \
"- attr: 0x%X\r\n" \
"- perm: 0x%X\r\n" \
"- ipc_refcount: 0x%X\r\n" \
"- device_refcount: 0x%X", \
location->program_id, page_info, debug_handle, mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, \
mem_info.ipc_refcount, mem_info.device_refcount);
#endif
mem_type = (u8)(mem_info.type & 0xFF);
if ((mem_info.perm & Perm_X) && (mem_type == MemType_CodeStatic || mem_type == MemType_CodeMutable)) last_text_addr = mem_info.addr;
addr = (mem_info.addr + mem_info.size);
/* Update .text segment address. */
last_text_addr = mem_info.addr;
} while(addr != 0);
g_fsTextSegmentAddr = last_text_addr;
MEMLOG_DEBUG("FS .text segment address: 0x%lX.", g_fsTextSegmentAddr);
}
/* Update variable so we can start reading data right from this address in the next steps. */
addr = g_fsTextSegmentAddr;
}
do {
/* Query memory page info. */
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
if (R_FAILED(rc))
{
@ -154,45 +174,51 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
break;
}
mem_type = (u8)(mem_info.type & MemState_Type);
addr = (mem_info.addr + mem_info.size);
/* Filter out unwanted memory pages. */
if (mem_info.attr || !(mem_info.perm & Perm_R) || \
(is_segment && (MEM_INVALID_SEGMENT_PAGE_TYPE(mem_type) || !(((segment <<= 1) >> 1) & location->mask))) || \
(!is_segment && location->program_id == FS_SYSMODULE_TID && MEM_INVALID_FS_PAGE_TYPE(mem_type))) continue;
#if LOG_LEVEL == LOG_LEVEL_DEBUG
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (#2) (program %016lX, page 0x%X, debug handle 0x%X, address 0x%lX):\r\n" \
"- addr: 0x%lX\r\n- size: 0x%lX\r\n- type: 0x%X\r\n- attr: 0x%X\r\n- perm: 0x%X\r\n- ipc_refcount: 0x%X\r\n- device_refcount: 0x%X", \
location->program_id, page_info, debug_handle, addr, \
mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, mem_info.ipc_refcount, mem_info.device_refcount);
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (program %016lX, page 0x%X, debug handle 0x%X):\r\n" \
"- addr: 0x%lX\r\n" \
"- size: 0x%lX\r\n" \
"- type: 0x%X\r\n" \
"- attr: 0x%X\r\n" \
"- perm: 0x%X\r\n" \
"- ipc_refcount: 0x%X\r\n" \
"- device_refcount: 0x%X", \
location->program_id, page_info, debug_handle, mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, \
mem_info.ipc_refcount, mem_info.device_refcount);
#endif
mem_type = (u8)(mem_info.type & 0xFF);
/* Code to allow for bitmasking segments. */
if ((mem_info.perm & Perm_R) && ((!is_segment && !mem_info.attr && (location->program_id != FS_SYSMODULE_TID || (location->program_id == FS_SYSMODULE_TID && mem_type != MemType_Unmapped && \
mem_type != MemType_Io && mem_type != MemType_ThreadLocal && mem_type != MemType_Reserved))) || (is_segment && (mem_type == MemType_CodeStatic || mem_type == MemType_CodeMutable) && \
(((segment <<= 1) >> 1) & location->mask))))
/* Reallocate data buffer. */
tmp = realloc(location->data, location->data_size + mem_info.size);
if (!tmp)
{
/* Reallocate data buffer. */
tmp = realloc(location->data, location->data_size + mem_info.size);
if (!tmp)
{
MEMLOG_ERROR("Failed to resize segment data buffer to 0x%lX bytes for program %016lX!", location->data_size + mem_info.size, location->program_id);
success = false;
break;
}
location->data = tmp;
tmp = NULL;
rc = svcReadDebugProcessMemory(location->data + location->data_size, debug_handle, mem_info.addr, mem_info.size);
if (R_FAILED(rc))
{
MEMLOG_ERROR("svcReadDebugProcessMemory failed for program %016lX! (0x%X).", location->program_id, rc);
success = false;
break;
}
location->data_size += mem_info.size;
MEMLOG_ERROR("Failed to resize segment data buffer to 0x%lX bytes for program %016lX!", location->data_size + mem_info.size, location->program_id);
success = false;
break;
}
addr = (mem_info.addr + mem_info.size);
} while(addr != 0 && segment < BIT(3));
location->data = tmp;
tmp = NULL;
/* Read memory page. */
rc = svcReadDebugProcessMemory(location->data + location->data_size, debug_handle, mem_info.addr, mem_info.size);
if (R_FAILED(rc))
{
MEMLOG_ERROR("svcReadDebugProcessMemory failed for program %016lX! (0x%X).", location->program_id, rc);
success = false;
break;
}
/* Increase data buffer size. */
location->data_size += mem_info.size;
} while(addr != 0 && segment < MemoryProgramSegmentType_Limit);
end:
/* Close debug handle. */
@ -243,6 +269,8 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
u32 i = 0, num_processes = 0;
u64 *pids = NULL;
bool success = false;
if (program_id > BOOT_SYSMODULE_TID && program_id != SPL_SYSMODULE_TID)
{
/* If not a kernel process, get process ID from pm:dmnt. */
@ -250,7 +278,7 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
if (R_FAILED(rc))
{
MEMLOG_ERROR("pmdmntGetProcessId failed for program %016lX! (0x%X).", program_id, rc);
return false;
goto end;
}
MEMLOG_DEBUG("Process ID (%016lX): 0x%lX.", program_id, pid);
@ -260,27 +288,26 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
if (R_FAILED(rc))
{
MEMLOG_ERROR("svcDebugActiveProcess failed for program %016lX! (0x%X).", program_id, rc);
return false;
goto end;
}
} else {
/* Otherwise, query svc for the process list. */
pids = calloc(300, sizeof(u64));
pids = calloc(MEM_PID_BUF_SIZE, sizeof(u64));
if (!pids)
{
MEMLOG_ERROR("Failed to allocate memory for PID list!");
return false;
goto end;
}
MEMLOG_DEBUG("svcDebugActiveProcess returned %u process IDs.", num_processes);
rc = svcGetProcessList((s32*)&num_processes, pids, 300);
rc = svcGetProcessList((s32*)&num_processes, pids, MEM_PID_BUF_SIZE);
if (R_FAILED(rc))
{
MEMLOG_ERROR("svcGetProcessList failed! (0x%X).", rc);
free(pids);
return false;
goto end;
}
MEMLOG_DEBUG("svcGetProcessList returned %u process IDs.", num_processes);
/* Perform a lookup using the retrieved process list. */
for(i = 0; i < num_processes; i++)
{
@ -295,7 +322,7 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
MEMLOG_DEBUG("Debug handle (process 0x%lX): 0x%X.", pids[i], debug_handle);
/* Get debug event using the debug handle. */
/* This will let us know the program ID from the current process ID. */
/* This will let us know the program ID for the current process ID. */
rc = svcGetDebugEvent((u8*)&d, debug_handle);
if (R_SUCCEEDED(rc))
{
@ -310,19 +337,23 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
debug_handle = INVALID_HANDLE;
}
free(pids);
if (i == num_processes)
{
MEMLOG_ERROR("Unable to find program %016lX in kernel process list! (0x%X).", program_id, rc);
return false;
goto end;
}
}
MEMLOG_DEBUG("Debug handle (%016lX): 0x%X.", program_id, debug_handle);
MEMLOG_DEBUG("Output debug handle for program ID %016lX: 0x%X.", program_id, debug_handle);
/* Set output debug handle. */
*out = debug_handle;
return true;
/* Update output flag. */
success = true;
end:
if (pids) free(pids);
return success;
}

View file

@ -856,7 +856,7 @@ static bool ncaInitializeFsSectionContext(NcaContext *nca_ctx, u32 section_idx)
}
}
if (fs_ctx->hash_type == NcaHashType_Auto || fs_ctx->hash_type == NcaHashType_AutoSha3 || fs_ctx->hash_type > NcaHashType_HierarchicalIntegritySha3)
if (fs_ctx->hash_type == NcaHashType_Auto || fs_ctx->hash_type == NcaHashType_AutoSha3 || fs_ctx->hash_type >= NcaHashType_Count)
{
LOG_MSG_ERROR("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", section_idx, nca_ctx->content_id_str, fs_ctx->hash_type);
goto end;
@ -880,7 +880,7 @@ static bool ncaInitializeFsSectionContext(NcaContext *nca_ctx, u32 section_idx)
}
}
if (fs_ctx->encryption_type == NcaEncryptionType_Auto || fs_ctx->encryption_type > NcaEncryptionType_AesCtrExSkipLayerHash)
if (fs_ctx->encryption_type == NcaEncryptionType_Auto || fs_ctx->encryption_type >= NcaEncryptionType_Count)
{
LOG_MSG_ERROR("Invalid encryption type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", section_idx, nca_ctx->content_id_str, fs_ctx->encryption_type);
goto end;
@ -1017,7 +1017,7 @@ static bool ncaInitializeFsSectionContext(NcaContext *nca_ctx, u32 section_idx)
/* Initialize crypto data. */
if ((!nca_ctx->rights_id_available || (nca_ctx->rights_id_available && nca_ctx->titlekey_retrieved)) && fs_ctx->encryption_type > NcaEncryptionType_None && \
fs_ctx->encryption_type <= NcaEncryptionType_AesCtrExSkipLayerHash)
fs_ctx->encryption_type < NcaEncryptionType_Count)
{
/* Initialize the partial AES counter for this section. */
aes128CtrInitializePartialCtr(fs_ctx->ctr, fs_ctx->header.aes_ctr_upper_iv.value, fs_ctx->section_offset);
@ -1137,7 +1137,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
static bool _ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size, u64 offset)
{
if (!g_ncaCryptoBuffer || !ctx || !ctx->enabled || !ctx->nca_ctx || ctx->section_idx >= NCA_FS_HEADER_COUNT || ctx->section_offset < sizeof(NcaHeader) || \
ctx->section_type >= NcaFsSectionType_Invalid || ctx->encryption_type == NcaEncryptionType_Auto || ctx->encryption_type > NcaEncryptionType_AesCtrExSkipLayerHash || \
ctx->section_type >= NcaFsSectionType_Invalid || ctx->encryption_type == NcaEncryptionType_Auto || ctx->encryption_type >= NcaEncryptionType_Count || \
!out || !read_size || (offset + read_size) > ctx->section_size)
{
LOG_MSG_ERROR("Invalid NCA FS section header parameters!");
@ -1685,7 +1685,7 @@ static void *ncaGenerateEncryptedFsSectionBlock(NcaFsSectionContext *ctx, const
bool success = false;
if (!g_ncaCryptoBuffer || !ctx || !ctx->enabled || ctx->has_sparse_layer || ctx->has_compression_layer || !ctx->nca_ctx || ctx->section_idx >= NCA_FS_HEADER_COUNT || \
ctx->section_offset < sizeof(NcaHeader) || ctx->hash_type <= NcaHashType_None || ctx->hash_type == NcaHashType_AutoSha3 || ctx->hash_type > NcaHashType_HierarchicalIntegritySha3 || \
ctx->section_offset < sizeof(NcaHeader) || ctx->hash_type <= NcaHashType_None || ctx->hash_type == NcaHashType_AutoSha3 || ctx->hash_type >= NcaHashType_Count || \
ctx->encryption_type == NcaEncryptionType_Auto || ctx->encryption_type == NcaEncryptionType_AesCtrEx || ctx->encryption_type >= NcaEncryptionType_AesCtrExSkipLayerHash || \
ctx->section_type >= NcaFsSectionType_Invalid || !data || !data_size || (data_offset + data_size) > ctx->section_size || !out_block_size || !out_block_offset)
{

View file

@ -72,7 +72,7 @@ __attribute__((format(printf, 5, 6))) void logWriteFormattedStringToLogFile(u8 l
__attribute__((format(printf, 7, 8))) void logWriteFormattedStringToBuffer(char **dst, size_t *dst_size, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, ...)
{
if (!dst || !dst_size || (!*dst && *dst_size) || (*dst && !*dst_size) || level < LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
if (!dst || !dst_size || level < LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
va_list args;
@ -85,7 +85,8 @@ __attribute__((format(printf, 7, 8))) void logWriteFormattedStringToBuffer(char
struct tm ts = {0};
struct timespec now = {0};
if (dst_str_len >= dst_cur_size) return;
/* Sanity check. */
if (dst_cur_size && dst_str_len >= dst_cur_size) return;
va_start(args, fmt);
@ -106,7 +107,7 @@ __attribute__((format(printf, 7, 8))) void logWriteFormattedStringToBuffer(char
log_str_len = (size_t)(str1_len + str2_len + 3);
if (!dst_cur_size || log_str_len > (dst_cur_size - dst_str_len))
if (!dst_ptr || !dst_cur_size || log_str_len > (dst_cur_size - dst_str_len))
{
/* Update buffer size. */
dst_cur_size = (dst_str_len + log_str_len);

View file

@ -501,7 +501,7 @@ void utilsJoinThread(Thread *thread)
__attribute__((format(printf, 3, 4))) bool utilsAppendFormattedStringToBuffer(char **dst, size_t *dst_size, const char *fmt, ...)
{
if (!dst || !dst_size || (!*dst && *dst_size) || (*dst && !*dst_size) || !fmt || !*fmt)
if (!dst || !dst_size || !fmt || !*fmt)
{
LOG_MSG_ERROR("Invalid parameters!");
return false;
@ -517,6 +517,7 @@ __attribute__((format(printf, 3, 4))) bool utilsAppendFormattedStringToBuffer(ch
bool success = false;
/* Sanity check. */
if (dst_cur_size && dst_str_len >= dst_cur_size)
{
LOG_MSG_ERROR("String length is equal to or greater than the provided buffer size! (0x%lX >= 0x%lX).", dst_str_len, dst_cur_size);
@ -535,7 +536,7 @@ __attribute__((format(printf, 3, 4))) bool utilsAppendFormattedStringToBuffer(ch
formatted_str_len_cast = (size_t)(formatted_str_len + 1);
if (!dst_cur_size || formatted_str_len_cast > (dst_cur_size - dst_str_len))
if (!dst_ptr || !dst_cur_size || formatted_str_len_cast > (dst_cur_size - dst_str_len))
{
/* Update buffer size. */
dst_cur_size = (dst_str_len + formatted_str_len_cast);
@ -561,6 +562,8 @@ __attribute__((format(printf, 3, 4))) bool utilsAppendFormattedStringToBuffer(ch
/* Generate formatted string. */
vsprintf(dst_ptr + dst_str_len, fmt, args);
/* Update output flag. */
success = true;
end:

View file

@ -36,8 +36,6 @@
#define TIK_LIST_STORAGE_PATH "/ticket_list.bin"
#define TIK_DB_STORAGE_PATH "/ticket.bin"
#define ES_CTRKEY_ENTRY_ALIGNMENT 0x8
/* Type definitions. */
/// Used to parse ticket_list.bin entries.
@ -52,7 +50,7 @@ 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.
/// 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.
typedef struct {
u32 idx; ///< Entry index.
u8 key[AES_128_KEY_SIZE]; ///< AES-128-CTR key.
@ -637,7 +635,7 @@ static bool tikRetrieveTicketEntryFromTicketBin(save_ctx_t *save_ctx, u8 *buf, u
}
/* Retrieve the CTR key/IV from ES program memory in order to decrypt this ticket. */
for(u64 i = 0; i < g_esMemoryLocation.data_size; i += ES_CTRKEY_ENTRY_ALIGNMENT)
for(u64 i = 0; i < g_esMemoryLocation.data_size; i++)
{
if ((g_esMemoryLocation.data_size - i) < (sizeof(TikEsCtrKeyEntry9x) * 2)) break;

View file

@ -61,7 +61,8 @@ typedef enum {
UsbCommandType_SendFileProperties = 1,
UsbCommandType_CancelFileTransfer = 2,
UsbCommandType_SendNspHeader = 3,
UsbCommandType_EndSession = 4
UsbCommandType_EndSession = 4,
UsbCommandType_Count = 5 ///< Total values supported by this enum.
} UsbCommandType;
typedef struct {
@ -108,7 +109,9 @@ typedef enum {
UsbStatusType_UnsupportedCommand = 5,
UsbStatusType_UnsupportedAbiVersion = 6,
UsbStatusType_MalformedCommand = 7,
UsbStatusType_HostIoError = 8
UsbStatusType_HostIoError = 8,
UsbStatusType_Count = 9 ///< Total values supported by this enum.
} UsbStatusType;
typedef struct {

View file

@ -61,7 +61,7 @@ namespace nxdt::utils {
if (R_FAILED(rc)) LOG_MSG_ERROR("svcQueryMemory failed! (0x%X).", rc);
}
#if LOG_LEVEL <= LOG_LEVEL_ERROR
#if LOG_LEVEL < LOG_LEVEL_NONE
static bool UnwindStack(u64 *out_stack_trace, u32 *out_stack_trace_size, size_t max_stack_trace_size, u64 cur_fp)
{
if (!out_stack_trace || !out_stack_trace_size || !max_stack_trace_size || !cur_fp)
@ -90,7 +90,7 @@ namespace nxdt::utils {
return (*out_stack_trace_size > 0);
}
#endif /* LOG_LEVEL <= LOG_LEVEL_ERROR */
#endif /* LOG_LEVEL < LOG_LEVEL_NONE */
static void NORETURN AbortProgramExecution(std::string str)
{
@ -164,7 +164,7 @@ extern "C" {
break;
}
#if LOG_LEVEL <= LOG_LEVEL_ERROR
#if LOG_LEVEL < LOG_LEVEL_NONE
char *exception_str = NULL;
size_t exception_str_size = 0;
@ -220,7 +220,7 @@ extern "C" {
/* Free exception info string. */
if (exception_str) free(exception_str);
#endif /* LOG_LEVEL <= LOG_LEVEL_ERROR */
#endif /* LOG_LEVEL < LOG_LEVEL_NONE */
/* Abort program execution. */
crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : \