From 8f75b6b923126fa3b1e7c72bbf6dcc94f3beefc9 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Mon, 17 Jul 2023 01:03:05 +0200 Subject: [PATCH] *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. --- code_templates/nxdt_rw_poc.c | 42 +++---- code_templates/system_title_dumper.c | 4 +- code_templates/xml_generator.c | 4 +- include/core/bfttf.h | 2 +- include/core/bktr.h | 15 ++- include/core/cert.h | 6 +- include/core/cnmt.h | 9 +- include/core/config.h | 4 +- include/core/fs_ext.h | 9 +- include/core/gamecard.h | 74 +++++++------ include/core/mem.h | 7 +- include/core/nacp.h | 46 +++++--- include/core/nca.h | 27 +++-- include/core/nca_storage.h | 5 +- include/core/npdm.h | 155 ++++++++++++++------------ include/core/nso.h | 4 +- include/core/nxdt_utils.h | 3 +- include/core/romfs.h | 3 +- include/core/smc.h | 4 +- include/core/tik.h | 17 ++- include/core/title.h | 5 +- include/core/usb.h | 3 +- libs/libusbhsfs | 2 +- romfs/default_config.json | 2 +- source/core/bfttf.c | 2 +- source/core/config.c | 6 +- source/core/gamecard.c | 14 +-- source/core/mem.c | 157 ++++++++++++++++----------- source/core/nca.c | 10 +- source/core/nxdt_log.c | 7 +- source/core/nxdt_utils.c | 7 +- source/core/tik.c | 6 +- source/core/usb.c | 7 +- source/exception_handler.cpp | 8 +- 34 files changed, 387 insertions(+), 289 deletions(-) diff --git a/code_templates/nxdt_rw_poc.c b/code_templates/nxdt_rw_poc.c index e10b198..713f46a 100644 --- a/code_templates/nxdt_rw_poc.c +++ b/code_templates/nxdt_rw_poc.c @@ -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) diff --git a/code_templates/system_title_dumper.c b/code_templates/system_title_dumper.c index f5bdb1b..7ccac71 100644 --- a/code_templates/system_title_dumper.c +++ b/code_templates/system_title_dumper.c @@ -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; } diff --git a/code_templates/xml_generator.c b/code_templates/xml_generator.c index f11546f..9f35b75 100644 --- a/code_templates/xml_generator.c +++ b/code_templates/xml_generator.c @@ -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; } diff --git a/include/core/bfttf.h b/include/core/bfttf.h index 1774374..afc019a 100644 --- a/include/core/bfttf.h +++ b/include/core/bfttf.h @@ -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. diff --git a/include/core/bktr.h b/include/core/bktr.h index f8f2cdb..cdffa96 100644 --- a/include/core/bktr.h +++ b/include/core/bktr.h @@ -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 { diff --git a/include/core/cert.h b/include/core/cert.h index f1f05e9..5f1698f 100644 --- a/include/core/cert.h +++ b/include/core/cert.h @@ -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. diff --git a/include/core/cnmt.h b/include/core/cnmt.h index df8ca42..de65735 100644 --- a/include/core/cnmt.h +++ b/include/core/cnmt.h @@ -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) diff --git a/include/core/config.h b/include/core/config.h index 25a5df4..232dc0e 100644 --- a/include/core/config.h +++ b/include/core/config.h @@ -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. diff --git a/include/core/fs_ext.h b/include/core/fs_ext.h index 795e4c0..30a5030 100644 --- a/include/core/fs_ext.h +++ b/include/core/fs_ext.h @@ -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); diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 4fba7b5..50114f5 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -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. diff --git a/include/core/mem.h b/include/core/mem.h index b84ac2e..10aeba0 100644 --- a/include/core/mem.h +++ b/include/core/mem.h @@ -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. diff --git a/include/core/nacp.h b/include/core/nacp.h index c4f26bc..b4a7e28 100644 --- a/include/core/nacp.h +++ b/include/core/nacp.h @@ -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; diff --git a/include/core/nca.h b/include/core/nca.h index b27a9e9..4faef57 100644 --- a/include/core/nca.h +++ b/include/core/nca.h @@ -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 { diff --git a/include/core/nca_storage.h b/include/core/nca_storage.h index 460938c..0bfaa21 100644 --- a/include/core/nca_storage.h +++ b/include/core/nca_storage.h @@ -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. diff --git a/include/core/npdm.h b/include/core/npdm.h index 980c233..7668560 100644 --- a/include/core/npdm.h +++ b/include/core/npdm.h @@ -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); } diff --git a/include/core/nso.h b/include/core/nso.h index 645456f..1685c59 100644 --- a/include/core/nso.h +++ b/include/core/nso.h @@ -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 { diff --git a/include/core/nxdt_utils.h b/include/core/nxdt_utils.h index be5036f..10c7576 100644 --- a/include/core/nxdt_utils.h +++ b/include/core/nxdt_utils.h @@ -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. diff --git a/include/core/romfs.h b/include/core/romfs.h index cb777a2..dcb1286 100644 --- a/include/core/romfs.h +++ b/include/core/romfs.h @@ -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. diff --git a/include/core/smc.h b/include/core/smc.h index 360e473..0e54725 100644 --- a/include/core/smc.h +++ b/include/core/smc.h @@ -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 { diff --git a/include/core/tik.h b/include/core/tik.h index bac2132..10c45ed 100644 --- a/include/core/tik.h +++ b/include/core/tik.h @@ -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. diff --git a/include/core/title.h b/include/core/title.h index e0a3168..692431d 100644 --- a/include/core/title.h +++ b/include/core/title.h @@ -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. diff --git a/include/core/usb.h b/include/core/usb.h index cbe5c50..2cc86d6 100644 --- a/include/core/usb.h +++ b/include/core/usb.h @@ -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. diff --git a/libs/libusbhsfs b/libs/libusbhsfs index 55f5a14..a11eb0d 160000 --- a/libs/libusbhsfs +++ b/libs/libusbhsfs @@ -1 +1 @@ -Subproject commit 55f5a140770b10899e3c5e3a08243471fe8e9ba7 +Subproject commit a11eb0d7083fba72aade29d3f9b35070d5510c3d diff --git a/romfs/default_config.json b/romfs/default_config.json index 65060f9..97e33fe 100644 --- a/romfs/default_config.json +++ b/romfs/default_config.json @@ -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": { diff --git a/source/core/bfttf.c b/source/core/bfttf.c index 8c0c29a..19b2e36 100644 --- a/source/core/bfttf.c +++ b/source/core/bfttf.c @@ -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; diff --git a/source/core/config.c b/source/core/config.c index 51d2cb4..93cbbb8 100644 --- a/source/core/config.c +++ b/source/core/config.c @@ -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; diff --git a/source/core/gamecard.c b/source/core/gamecard.c index abe1766..66c1b24 100644 --- a/source/core/gamecard.c +++ b/source/core/gamecard.c @@ -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. */ diff --git a/source/core/mem.c b/source/core/mem.c index f324a38..f9af4bd 100644 --- a/source/core/mem.c +++ b/source/core/mem.c @@ -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; } diff --git a/source/core/nca.c b/source/core/nca.c index dd34838..b770c90 100644 --- a/source/core/nca.c +++ b/source/core/nca.c @@ -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) { diff --git a/source/core/nxdt_log.c b/source/core/nxdt_log.c index be5f276..c78a45c 100644 --- a/source/core/nxdt_log.c +++ b/source/core/nxdt_log.c @@ -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); diff --git a/source/core/nxdt_utils.c b/source/core/nxdt_utils.c index 0270ccd..81574c4 100644 --- a/source/core/nxdt_utils.c +++ b/source/core/nxdt_utils.c @@ -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: diff --git a/source/core/tik.c b/source/core/tik.c index a77c773..1c33b83 100644 --- a/source/core/tik.c +++ b/source/core/tik.c @@ -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; diff --git a/source/core/usb.c b/source/core/usb.c index ae033f1..84f9017 100644 --- a/source/core/usb.c +++ b/source/core/usb.c @@ -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 { diff --git a/source/exception_handler.cpp b/source/exception_handler.cpp index 500d61c..00fa423 100644 --- a/source/exception_handler.cpp +++ b/source/exception_handler.cpp @@ -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) : \