1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

Update NPDM structs (thanks to 0Liam) + LegalInformation XML retrieval.

From now on, I'll delete code from the legacy codebase directory as soon as specific features from it are rewritten... Because it's a mess to navigate.
This commit is contained in:
Pablo Curiel 2020-10-09 05:58:53 -04:00
parent 4425666395
commit d1f0361725
12 changed files with 435 additions and 3018 deletions

View file

@ -23,6 +23,7 @@
#include "title.h"
#include "cnmt.h"
#include "nacp.h"
#include "legal_info.h"
static void consolePrint(const char *text, ...)
{
@ -64,6 +65,7 @@ int main(int argc, char *argv[])
ContentMetaContext cnmt_ctx = {0};
NacpContext nacp_ctx = {0};
LegalInfoContext legal_info_ctx = {0};
FILE *xml_fd = NULL;
char path[FS_MAX_PATH] = {0};
@ -188,7 +190,7 @@ int main(int argc, char *argv[])
consolePrint("nca ctx calloc succeeded\n");
u32 meta_idx = (user_app_data.app_info->content_count - 1), control_idx = 0;
u32 meta_idx = (user_app_data.app_info->content_count - 1), control_idx = 0, legal_idx = 0;
for(u32 i = 0, j = 0; i < user_app_data.app_info->content_count; i++)
{
@ -203,6 +205,8 @@ int main(int argc, char *argv[])
if (user_app_data.app_info->content_infos[i].content_type == NcmContentType_Control && user_app_data.app_info->content_infos[i].id_offset == 0) control_idx = j;
if (user_app_data.app_info->content_infos[i].content_type == NcmContentType_LegalInformation && user_app_data.app_info->content_infos[i].id_offset == 0) legal_idx = j;
consolePrint("%s nca initialize ctx succeeded\n", titleGetNcmContentTypeName(user_app_data.app_info->content_infos[i].content_type));
j++;
}
@ -231,7 +235,7 @@ int main(int argc, char *argv[])
{
consolePrint("cnmt xml succeeded\n");
sprintf(path, "sdmc:/%016lX_xml/%s.cnmt", app_metadata[selected_idx]->title_id, nca_ctx[meta_idx].content_id_str);
sprintf(path, "sdmc:/%016lX_xml/%s.cnmt", app_metadata[selected_idx]->title_id, cnmt_ctx.nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
@ -241,7 +245,7 @@ int main(int argc, char *argv[])
xml_fd = NULL;
}
sprintf(path, "sdmc:/%016lX_xml/%s.cnmt.xml", app_metadata[selected_idx]->title_id, nca_ctx[meta_idx].content_id_str);
sprintf(path, "sdmc:/%016lX_xml/%s.cnmt.xml", app_metadata[selected_idx]->title_id, cnmt_ctx.nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
@ -266,7 +270,7 @@ int main(int argc, char *argv[])
{
consolePrint("nacp xml succeeded\n");
sprintf(path, "sdmc:/%016lX_xml/%s.nacp", app_metadata[selected_idx]->title_id, nca_ctx[control_idx].content_id_str);
sprintf(path, "sdmc:/%016lX_xml/%s.nacp", app_metadata[selected_idx]->title_id, nacp_ctx.nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
@ -276,7 +280,7 @@ int main(int argc, char *argv[])
xml_fd = NULL;
}
sprintf(path, "sdmc:/%016lX_xml/%s.nacp.xml", app_metadata[selected_idx]->title_id, nca_ctx[control_idx].content_id_str);
sprintf(path, "sdmc:/%016lX_xml/%s.nacp.xml", app_metadata[selected_idx]->title_id, nacp_ctx.nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
@ -290,7 +294,7 @@ int main(int argc, char *argv[])
{
NacpIconContext *icon_ctx = &(nacp_ctx.icon_ctx[i]);
sprintf(path, "sdmc:/%016lX_xml/%s.nx.%s.jpg", app_metadata[selected_idx]->title_id, nca_ctx[control_idx].content_id_str, nacpGetLanguageString(icon_ctx->language));
sprintf(path, "sdmc:/%016lX_xml/%s.nx.%s.jpg", app_metadata[selected_idx]->title_id, nacp_ctx.nca_ctx->content_id_str, nacpGetLanguageString(icon_ctx->language));
xml_fd = fopen(path, "wb");
if (xml_fd)
@ -304,6 +308,24 @@ int main(int argc, char *argv[])
consolePrint("nacp xml failed\n");
}
if (!legalInfoInitializeContext(&legal_info_ctx, &(nca_ctx[legal_idx])))
{
consolePrint("legalinfo initialize ctx failed\n");
goto out2;
}
consolePrint("legalinfo initialize ctx succeeded\n");
sprintf(path, "sdmc:/%016lX_xml/%s.legalinfo.xml", app_metadata[selected_idx]->title_id, legal_info_ctx.nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
{
fwrite(legal_info_ctx.authoring_tool_xml, 1, legal_info_ctx.authoring_tool_xml_size, xml_fd);
fclose(xml_fd);
xml_fd = NULL;
}
out2:
if (exit_prompt)
{
@ -311,6 +333,8 @@ out2:
utilsWaitForButtonPress(KEY_NONE);
}
legalInfoFreeContext(&legal_info_ctx);
nacpFreeContext(&nacp_ctx);
cnmtFreeContext(&cnmt_ctx);

View file

@ -1,177 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <switch.h>
#include "ui.h"
#include "util.h"
int main(int argc, char *argv[])
{
int ret = 0;
bool exitMainLoop = false;
/* Initialize application resources */
if (!initApplicationResources(argc, argv))
{
ret = -1;
goto out;
}
/* Main application loop */
while(appletMainLoop())
{
UIResult result = uiProcess();
switch(result)
{
case resultShowMainMenu:
uiSetState(stateMainMenu);
break;
case resultShowGameCardMenu:
uiSetState(stateGameCardMenu);
break;
case resultShowXciDumpMenu:
uiSetState(stateXciDumpMenu);
break;
case resultDumpXci:
uiSetState(stateDumpXci);
break;
case resultShowNspDumpMenu:
uiSetState(stateNspDumpMenu);
break;
case resultShowNspAppDumpMenu:
uiSetState(stateNspAppDumpMenu);
break;
case resultShowNspPatchDumpMenu:
uiSetState(stateNspPatchDumpMenu);
break;
case resultShowNspAddOnDumpMenu:
uiSetState(stateNspAddOnDumpMenu);
break;
case resultDumpNsp:
uiSetState(stateDumpNsp);
break;
case resultShowHfs0Menu:
uiSetState(stateHfs0Menu);
break;
case resultShowRawHfs0PartitionDumpMenu:
uiSetState(stateRawHfs0PartitionDumpMenu);
break;
case resultDumpRawHfs0Partition:
uiSetState(stateDumpRawHfs0Partition);
break;
case resultShowHfs0PartitionDataDumpMenu:
uiSetState(stateHfs0PartitionDataDumpMenu);
break;
case resultDumpHfs0PartitionData:
uiSetState(stateDumpHfs0PartitionData);
break;
case resultShowHfs0BrowserMenu:
uiSetState(stateHfs0BrowserMenu);
break;
case resultHfs0BrowserGetList:
uiSetState(stateHfs0BrowserGetList);
break;
case resultShowHfs0Browser:
uiSetState(stateHfs0Browser);
break;
case resultHfs0BrowserCopyFile:
uiSetState(stateHfs0BrowserCopyFile);
break;
case resultShowExeFsMenu:
uiSetState(stateExeFsMenu);
break;
case resultShowExeFsSectionDataDumpMenu:
uiSetState(stateExeFsSectionDataDumpMenu);
break;
case resultDumpExeFsSectionData:
uiSetState(stateDumpExeFsSectionData);
break;
case resultShowExeFsSectionBrowserMenu:
uiSetState(stateExeFsSectionBrowserMenu);
break;
case resultExeFsSectionBrowserGetList:
uiSetState(stateExeFsSectionBrowserGetList);
break;
case resultShowExeFsSectionBrowser:
uiSetState(stateExeFsSectionBrowser);
break;
case resultExeFsSectionBrowserCopyFile:
uiSetState(stateExeFsSectionBrowserCopyFile);
break;
case resultShowRomFsMenu:
uiSetState(stateRomFsMenu);
break;
case resultShowRomFsSectionDataDumpMenu:
uiSetState(stateRomFsSectionDataDumpMenu);
break;
case resultDumpRomFsSectionData:
uiSetState(stateDumpRomFsSectionData);
break;
case resultShowRomFsSectionBrowserMenu:
uiSetState(stateRomFsSectionBrowserMenu);
break;
case resultRomFsSectionBrowserGetEntries:
uiSetState(stateRomFsSectionBrowserGetEntries);
break;
case resultShowRomFsSectionBrowser:
uiSetState(stateRomFsSectionBrowser);
break;
case resultRomFsSectionBrowserChangeDir:
uiSetState(stateRomFsSectionBrowserChangeDir);
break;
case resultRomFsSectionBrowserCopyFile:
uiSetState(stateRomFsSectionBrowserCopyFile);
break;
case resultRomFsSectionBrowserCopyDir:
uiSetState(stateRomFsSectionBrowserCopyDir);
break;
case resultDumpGameCardCertificate:
uiSetState(stateDumpGameCardCertificate);
break;
case resultShowSdCardEmmcMenu:
uiSetState(stateSdCardEmmcMenu);
break;
case resultShowSdCardEmmcTitleMenu:
uiSetState(stateSdCardEmmcTitleMenu);
break;
case resultShowSdCardEmmcOrphanPatchAddOnMenu:
uiSetState(stateSdCardEmmcOrphanPatchAddOnMenu);
break;
case resultShowSdCardEmmcBatchModeMenu:
uiSetState(stateSdCardEmmcBatchModeMenu);
break;
case resultSdCardEmmcBatchDump:
uiSetState(stateSdCardEmmcBatchDump);
break;
case resultShowTicketMenu:
uiSetState(stateTicketMenu);
break;
case resultDumpTicket:
uiSetState(stateDumpTicket);
break;
case resultShowUpdateMenu:
uiSetState(stateUpdateMenu);
break;
case resultUpdateNSWDBXml:
uiSetState(stateUpdateNSWDBXml);
break;
case resultUpdateApplication:
uiSetState(stateUpdateApplication);
break;
case resultExit:
exitMainLoop = true;
break;
default:
break;
}
if (exitMainLoop) break;
}
out:
/* Deinitialize application resources */
deinitApplicationResources();
return ret;
}

File diff suppressed because it is too large Load diff

View file

@ -289,12 +289,6 @@ typedef struct {
u64 block_size[2];
} nca_program_mod_data;
typedef struct {
char filename[100];
u64 icon_size;
u8 icon_data[0x20000];
} nacp_icons_ctx;
typedef struct {
u32 nca_index;
u64 xml_size;
@ -347,110 +341,6 @@ typedef struct {
bool missing_tik;
} title_rights_ctx;
typedef struct {
NcmStorageId storageId;
NcmContentStorage ncmStorage;
NcmContentId ncaId;
u8 idOffset;
Aes128CtrContext aes_ctx;
u64 exefs_offset; // Relative to NCA start
u64 exefs_size;
pfs0_header exefs_header;
u64 exefs_entries_offset; // Relative to NCA start
pfs0_file_entry *exefs_entries;
u64 exefs_str_table_offset; // Relative to NCA start
char *exefs_str_table;
u64 exefs_data_offset; // Relative to NCA start
} exefs_ctx_t;
typedef struct {
NcmStorageId storageId;
NcmContentStorage ncmStorage;
NcmContentId ncaId;
u8 idOffset;
Aes128CtrContext aes_ctx;
u64 section_offset; // Relative to NCA start
u64 section_size;
u64 romfs_offset; // Relative to NCA start
u64 romfs_size;
u64 romfs_dirtable_offset; // Relative to NCA start
u64 romfs_dirtable_size;
romfs_dir *romfs_dir_entries;
u64 romfs_filetable_offset; // Relative to NCA start
u64 romfs_filetable_size;
romfs_file *romfs_file_entries;
u64 romfs_filedata_offset; // Relative to NCA start
} romfs_ctx_t;
typedef struct {
u64 virt_offset;
u64 phys_offset;
u32 is_patch;
} PACKED bktr_relocation_entry_t;
typedef struct {
u32 _0x0;
u32 num_entries;
u64 virtual_offset_end;
bktr_relocation_entry_t entries[0x3FF0 / sizeof(bktr_relocation_entry_t)];
u8 padding[0x3FF0 % sizeof(bktr_relocation_entry_t)];
} PACKED bktr_relocation_bucket_t;
typedef struct {
u32 _0x0;
u32 num_buckets;
u64 total_size;
u64 bucket_virtual_offsets[0x3FF0 / sizeof(u64)];
bktr_relocation_bucket_t buckets[];
} PACKED bktr_relocation_block_t;
typedef struct {
u64 offset;
u32 _0x8;
u32 ctr_val;
} PACKED bktr_subsection_entry_t;
typedef struct {
u32 _0x0;
u32 num_entries;
u64 physical_offset_end;
bktr_subsection_entry_t entries[0x3FF];
} PACKED bktr_subsection_bucket_t;
typedef struct {
u32 _0x0;
u32 num_buckets;
u64 total_size;
u64 bucket_physical_offsets[0x3FF0 / sizeof(u64)];
bktr_subsection_bucket_t buckets[];
} PACKED bktr_subsection_block_t;
typedef struct {
NcmStorageId storageId;
NcmContentStorage ncmStorage;
NcmContentId ncaId;
u8 idOffset;
Aes128CtrContext aes_ctx;
u64 section_offset; // Relative to NCA start
u64 section_size;
bktr_superblock_t superblock;
bktr_relocation_block_t *relocation_block;
bktr_subsection_block_t *subsection_block;
u64 virtual_seek; // Relative to section start
u64 bktr_seek; // Relative to section start (patch BKTR section)
u64 base_seek; // Relative to section start (base application RomFS section)
u64 romfs_offset; // Relative to section start
u64 romfs_size;
u64 romfs_dirtable_offset; // Relative to section start
u64 romfs_dirtable_size;
romfs_dir *romfs_dir_entries;
u64 romfs_filetable_offset; // Relative to section start
u64 romfs_filetable_size;
romfs_file *romfs_file_entries;
u64 romfs_filedata_offset; // Relative to section start
bool use_base_romfs;
} bktr_ctx_t;
// Used in HFS0 / ExeFS / RomFS browsers
typedef struct {
u64 size;
@ -463,278 +353,6 @@ typedef struct {
browser_entry_size_info sizeInfo; // Only used if type == 2
} romfs_browser_entry;
typedef struct {
char name[0x200];
char publisher[0x100];
} Title;
typedef enum {
Language_AmericanEnglish = 0,
Language_BritishEnglish = 1,
Language_Japanese = 2,
Language_French = 3,
Language_German = 4,
Language_LatinAmericanSpanish = 5,
Language_Spanish = 6,
Language_Italian = 7,
Language_Dutch = 8,
Language_CanadianFrench = 9,
Language_Portuguese = 10,
Language_Russian = 11,
Language_Korean = 12,
Language_TraditionalChinese = 13,
Language_SimplifiedChinese = 14
} Language;
typedef enum {
StartupUserAccount_None = 0,
StartupUserAccount_Required = 1,
StartupUserAccount_RequiredWithNetworkServiceAccountAvailable = 2
} StartupUserAccount;
/* Introduced as of SDK 6.4.0 */
typedef enum {
UserAccountSwitchLock_Disable = 0,
UserAccountSwitchLock_Enable = 1
} UserAccountSwitchLock;
/* Introduced as of SDK 3.4.0 */
typedef enum {
AddOnContentRegistrationType_AllOnLaunch = 0,
AddOnContentRegistrationType_OnDemand = 1
} AddOnContentRegistrationType;
typedef struct {
u32 AttributeFlag_Demo : 1;
u32 AttributeFlag_RetailInteractiveDisplay : 1; /* Introduced as of SDK 3.4.0 */
} AttributeFlag;
typedef struct {
u32 SupportedLanguageFlag_AmericanEnglish : 1;
u32 SupportedLanguageFlag_BritishEnglish : 1;
u32 SupportedLanguageFlag_Japanese : 1;
u32 SupportedLanguageFlag_French : 1;
u32 SupportedLanguageFlag_German : 1;
u32 SupportedLanguageFlag_LatinAmericanSpanish : 1;
u32 SupportedLanguageFlag_Spanish : 1;
u32 SupportedLanguageFlag_Italian : 1;
u32 SupportedLanguageFlag_Dutch : 1;
u32 SupportedLanguageFlag_CanadianFrench : 1;
u32 SupportedLanguageFlag_Portuguese : 1;
u32 SupportedLanguageFlag_Russian : 1;
u32 SupportedLanguageFlag_Korean : 1;
u32 SupportedLanguageFlag_TraditionalChinese : 1;
u32 SupportedLanguageFlag_SimplifiedChinese : 1;
} SupportedLanguageFlag;
typedef struct {
u32 ParentalControlFlag_FreeCommunication : 1;
} ParentalControlFlag;
typedef enum {
Screenshot_Allow = 0,
Screenshot_Deny = 1
} Screenshot;
typedef enum {
VideoCapture_Disable = 0,
VideoCapture_Manual = 1,
VideoCapture_Enable = 2
} VideoCapture;
typedef enum {
DataLossConfirmation_None = 0,
DataLossConfirmation_Required = 1
} DataLossConfirmation;
typedef enum {
PlayLogPolicy_All = 0,
PlayLogPolicy_LogOnly = 1,
PlayLogPolicy_None = 2
} PlayLogPolicy;
typedef enum {
RatingAgeOrganization_CERO = 0,
RatingAgeOrganization_GRACGCRB = 1,
RatingAgeOrganization_GSRMR = 2,
RatingAgeOrganization_ESRB = 3,
RatingAgeOrganization_ClassInd = 4,
RatingAgeOrganization_USK = 5,
RatingAgeOrganization_PEGI = 6,
RatingAgeOrganization_PEGIPortugal = 7,
RatingAgeOrganization_PEGIBBFC = 8,
RatingAgeOrganization_Russian = 9,
RatingAgeOrganization_ACB = 10,
RatingAgeOrganization_OFLC = 11,
RatingAgeOrganization_IARCGeneric = 12 /* Introduced as of SDK 9.3.1 */
} RatingAgeOrganization;
typedef struct {
u8 cero;
u8 gracgcrb;
u8 gsrmr;
u8 esrb;
u8 class_ind;
u8 usk;
u8 pegi;
u8 pegi_portugal;
u8 pegibbfc;
u8 russian;
u8 acb;
u8 oflc;
u8 iarc_generic;
u8 reserved_1[0x13];
} RatingAge;
typedef enum {
LogoType_LicensedByNintendo = 0,
LogoType_DistributedByNintendo = 1, /* Removed in SDK 3.5.2 */
LogoType_Nintendo = 2
} LogoType;
typedef enum {
LogoHandling_Auto = 0,
LogoHandling_Manual = 1
} LogoHandling;
/* Introduced as of SDK 4.5.0 */
typedef enum {
RuntimeAddOnContentInstall_Deny = 0,
RuntimeAddOnContentInstall_AllowAppend = 1
} RuntimeAddOnContentInstall;
/* Introduced as of SDK 9.3.1 */
typedef enum {
RuntimeParameterDelivery_Always = 0,
RuntimeParameterDelivery_AlwaysIfUserStateMatched = 1,
RuntimeParameterDelivery_OnRestart = 2
} RuntimeParameterDelivery;
/* Introduced as of SDK 3.5.2 */
typedef enum {
CrashReport_Deny = 0,
CrashReport_Allow = 1
} CrashReport;
typedef enum {
Hdcp_None = 0,
Hdcp_Required = 1
} Hdcp;
/* Introduced as of SDK 7.6.0 */
typedef struct {
u8 StartupUserAccountOptionFlag_IsOptional : 1;
} StartupUserAccountOptionFlag;
/* Introduced as of SDK 5.3.0 */
typedef enum {
PlayLogQueryCapability_None = 0,
PlayLogQueryCapability_WhiteList = 1,
PlayLogQueryCapability_All = 2
} PlayLogQueryCapability;
/* Introduced as of SDK 5.3.0 */
typedef struct {
u8 RepairFlag_SuppressGameCardAccess : 1;
} RepairFlag;
/* Introduced as of SDK 6.4.0 */
typedef struct {
u8 RequiredNetworkServiceLicenseOnLaunchFlag_Common : 1;
} RequiredNetworkServiceLicenseOnLaunchFlag;
typedef struct {
u64 group_id;
u8 key[0x10];
} NeighborDetectionGroupConfiguration;
typedef struct {
NeighborDetectionGroupConfiguration send_group_configuration;
NeighborDetectionGroupConfiguration receivable_group_configurations[0x10];
} NeighborDetectionClientConfiguration;
/* Introduced as of SDK 7.6.0 */
typedef enum {
JitConfigurationFlag_None = 0,
JitConfigurationFlag_Enabled = 1
} JitConfigurationFlag;
typedef struct {
u64 jit_configuration_flag;
u64 memory_size;
} JitConfiguration;
typedef struct {
Title titles[0x10];
char isbn[0x25];
u8 startup_user_account;
u8 user_account_switch_lock; /* Old: touch_screen_usage (None, Supported, Required) */
u8 add_on_content_registration_type;
AttributeFlag attribute_flag;
SupportedLanguageFlag supported_language_flag;
ParentalControlFlag parental_control_flag;
u8 screenshot;
u8 video_capture;
u8 data_loss_confirmation;
u8 play_log_policy;
u64 presence_group_id;
RatingAge rating_ages;
char display_version[0x10];
u64 add_on_content_base_id;
u64 save_data_owner_id;
u64 user_account_save_data_size;
u64 user_account_save_data_journal_size;
u64 device_save_data_size;
u64 device_save_data_journal_size;
u64 bcat_delivery_cache_storage_size;
char application_error_code_category[0x8];
u64 local_communication_ids[0x8];
u8 logo_type;
u8 logo_handling;
u8 runtime_add_on_content_install;
u8 runtime_parameter_delivery;
u8 reserved_1[0x2];
u8 crash_report;
u8 hdcp;
u64 seed_for_pseudo_device_id;
char bcat_passphrase[0x41];
StartupUserAccountOptionFlag startup_user_account_option;
u8 reserved_2[0x6];
u64 user_account_save_data_size_max;
u64 user_account_save_data_journal_size_max;
u64 device_save_data_size_max;
u64 device_save_data_journal_size_max;
u64 temporary_storage_size;
u64 cache_storage_size;
u64 cache_storage_journal_size;
u64 cache_storage_data_and_journal_size_max;
u16 cache_storage_index_max;
u8 reserved_3[0x6];
u64 play_log_queryable_application_ids[0x10];
u8 play_log_query_capability;
RepairFlag repair_flag;
u8 program_index;
RequiredNetworkServiceLicenseOnLaunchFlag required_network_service_license_on_launch_flag;
u8 reserved_4[0x4];
NeighborDetectionClientConfiguration neighbor_detection_client_configuration;
JitConfiguration jit_configuration;
u8 reserved_5[0xC40];
} nacp_t;
char *getContentType(u8 type);
void generateCnmtXml(cnmt_xml_program_info *xml_program_info, cnmt_xml_content_info *xml_content_info, char *out);
void convertNcaSizeToU64(const u8 size[0x6], u64 *out);
void convertU64ToNcaSize(const u64 size, u8 out[0x6]);
bool readNcaDataByContentId(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, u64 offset, void *outBuf, size_t bufSize);
bool processNcaCtrSectionBlock(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *ctx, u64 offset, void *outBuf, size_t bufSize, bool encrypt);
bool readBktrSectionBlock(u64 offset, void *outBuf, size_t bufSize);
bool encryptNcaHeader(nca_header_t *input, u8 *outBuf, u64 outBufSize);
bool decryptNcaHeader(const u8 *ncaBuf, u64 ncaBufSize, nca_header_t *out, title_rights_ctx *rights_info, u8 *decrypted_nca_keys, bool retrieveTitleKeyData);
@ -747,16 +365,6 @@ bool retrieveCnmtNcaData(NcmStorageId curStorageId, u8 *ncaBuf, cnmt_xml_program
bool patchCnmtNca(u8 *ncaBuf, u64 ncaBufSize, cnmt_xml_program_info *xml_program_info, cnmt_xml_content_info *xml_content_info, nca_cnmt_mod_data *cnmt_mod);
bool parseExeFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
int parseRomFsEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
bool parseBktrEntryFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
bool generateProgramInfoXml(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys, bool useCustomAcidRsaPubKey, char **outBuf, u64 *outBufSize);
bool retrieveNacpDataFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys, char **out_nacp_xml, u64 *out_nacp_xml_size, nacp_icons_ctx **out_nacp_icons_ctx, u8 *out_nacp_icons_ctx_cnt);
bool retrieveLegalInfoXmlFromNca(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys, char **outBuf, u64 *outBufSize);
#endif

View file

@ -29,13 +29,15 @@
typedef enum {
BktrIndirectStorageIndex_Original = 0,
BktrIndirectStorageIndex_Patch = 1
} PACKED BktrIndirectStorageIndex;
} BktrIndirectStorageIndex;
#pragma pack(push, 1)
typedef struct {
u64 virtual_offset;
u64 physical_offset;
u32 indirect_storage_index; ///< BktrIndirectStorageIndex.
} PACKED BktrIndirectStorageEntry;
} BktrIndirectStorageEntry;
#pragma pack(pop)
typedef struct {
u32 index;
@ -43,7 +45,7 @@ typedef struct {
u64 end_offset;
BktrIndirectStorageEntry indirect_storage_entries[0x3FF0 / sizeof(BktrIndirectStorageEntry)];
u8 reserved[0x3FF0 % sizeof(BktrIndirectStorageEntry)];
} PACKED BktrIndirectStorageBucket;
} BktrIndirectStorageBucket;
typedef struct {
u32 index;
@ -51,20 +53,20 @@ typedef struct {
u64 virtual_size;
u64 virtual_offsets[0x3FF0 / sizeof(u64)];
BktrIndirectStorageBucket indirect_storage_buckets[];
} PACKED BktrIndirectStorageBlock;
} BktrIndirectStorageBlock;
typedef struct {
u64 offset;
u32 size;
u32 generation;
} PACKED BktrAesCtrExStorageEntry;
} BktrAesCtrExStorageEntry;
typedef struct {
u32 index;
u32 entry_count;
u64 end_offset;
BktrAesCtrExStorageEntry aes_ctr_ex_storage_entries[0x3FF];
} PACKED BktrAesCtrExStorageBucket;
} BktrAesCtrExStorageBucket;
typedef struct {
u32 index;
@ -72,7 +74,7 @@ typedef struct {
u64 physical_size;
u64 physical_offsets[0x3FF0 / sizeof(u64)];
BktrAesCtrExStorageBucket aes_ctr_ex_storage_buckets[];
} PACKED BktrAesCtrExStorageBlock;
} BktrAesCtrExStorageBlock;
typedef struct {
RomFileSystemContext base_romfs_ctx; ///< Base NCA RomFS context.

View file

@ -59,7 +59,7 @@ bool cnmtInitializeContext(ContentMetaContext *out, NcaContext *nca_ctx)
goto end;
}
/* Get Partition FS entry count. */
/* Get Partition FS entry count. Edge case, we should never trigger this. */
if (!(pfs_entry_count = pfsGetEntryCount(&(out->pfs_ctx))))
{
LOGFILE("Partition FS has no file entries!");
@ -100,8 +100,7 @@ bool cnmtInitializeContext(ContentMetaContext *out, NcaContext *nca_ctx)
/* Allocate memory for the raw CNMT data. */
out->raw_data_size = out->pfs_entry->size;
out->raw_data = malloc(out->raw_data_size);
if (!out->raw_data)
if (!(out->raw_data = malloc(out->raw_data_size)))
{
LOGFILE("Failed to allocate memory for the raw CNMT data!");
goto end;

89
source/legal_info.c Normal file
View file

@ -0,0 +1,89 @@
/*
* legal_info.c
*
* Copyright (c) 2020, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* nxdumptool is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "utils.h"
#include "legal_info.h"
#include "romfs.h"
bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx)
{
if (!out || !nca_ctx || !strlen(nca_ctx->content_id_str) || nca_ctx->content_type != NcmContentType_LegalInformation || nca_ctx->content_size < NCA_FULL_HEADER_LENGTH || \
(nca_ctx->storage_id != NcmStorageId_GameCard && !nca_ctx->ncm_storage) || (nca_ctx->storage_id == NcmStorageId_GameCard && !nca_ctx->gamecard_offset) || \
nca_ctx->header.content_type != NcaContentType_Manual || !out)
{
LOGFILE("Invalid parameters!");
return false;
}
RomFileSystemContext romfs_ctx = {0};
RomFileSystemFileEntry *xml_entry = NULL;
bool success = false;
/* Free output context beforehand. */
legalInfoFreeContext(out);
/* Initialize RomFS context. */
if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_contexts[0])))
{
LOGFILE("Failed to initialize RomFS context!");
goto end;
}
/* Retrieve RomFS file entry for 'legalinfo.xml'. */
if (!(xml_entry = romfsGetFileEntryByPath(&romfs_ctx, "/legalinfo.xml")))
{
LOGFILE("Failed to retrieve file entry for \"legalinfo.xml\" from RomFS!");
goto end;
}
//LOGFILE("Found 'legalinfo.xml' entry in LegalInformation NCA \"%s\".", nca_ctx->content_id_str);
/* Verify XML size. */
if (!xml_entry->size)
{
LOGFILE("Invalid XML size!");
goto end;
}
/* Allocate memory for the XML. */
out->authoring_tool_xml_size = xml_entry->size;
if (!(out->authoring_tool_xml = malloc(out->authoring_tool_xml_size)))
{
LOGFILE("Failed to allocate memory for the XML!");
goto end;
}
/* Read NACP data into memory buffer. */
if (!romfsReadFileEntryData(&romfs_ctx, xml_entry, out->authoring_tool_xml, out->authoring_tool_xml_size, 0))
{
LOGFILE("Failed to read XML!");
goto end;
}
success = true;
end:
romfsFreeContext(&romfs_ctx);
if (!success) legalInfoFreeContext(out);
return success;
}

46
source/legal_info.h Normal file
View file

@ -0,0 +1,46 @@
/*
* legal_info.h
*
* Copyright (c) 2020, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* nxdumptool is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __LEGAL_INFO_H__
#define __LEGAL_INFO_H__
#include "nca.h"
typedef struct {
NcaContext *nca_ctx; ///< Pointer to the NCA context for the LegalInformation NCA from which XML data is retrieved.
char *authoring_tool_xml; ///< Pointer to a dynamically allocated, NULL-terminated buffer that holds AuthoringTool-like XML data.
u64 authoring_tool_xml_size; ///< Size for the AuthoringTool-like XML. This is essentially the same as using strlen() on 'authoring_tool_xml'.
} LegalInfoContext;
/// Initializes a LegalInfoContext using a previously initialized NcaContext (which must belong to a LegalInformation NCA).
bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx);
/// Helper inline functions.
NX_INLINE void legalInfoFreeContext(LegalInfoContext *legal_info_ctx)
{
if (!legal_info_ctx) return;
if (legal_info_ctx->authoring_tool_xml) free(legal_info_ctx->authoring_tool_xml);
memset(legal_info_ctx, 0, sizeof(LegalInfoContext));
}
#endif /* __LEGAL_INFO_H__ */

View file

@ -239,8 +239,7 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx)
}
/* Allocate memory for the NACP data. */
out->data = malloc(sizeof(_NacpStruct));
if (!out->data)
if (!(out->data = malloc(sizeof(_NacpStruct))))
{
LOGFILE("Failed to allocate memory for the NACP data!");
goto end;

View file

@ -41,11 +41,6 @@ typedef struct {
u8 reserved : 3;
} NpdmMetaFlags;
typedef struct {
u32 offset;
u32 size;
} NpdmSectionHeader;
/// This is the start of every NPDM file.
/// This is followed by ACID and ACI0 sections, both with variable offsets and sizes.
typedef struct {
@ -63,15 +58,21 @@ typedef struct {
char name[0x10]; ///< Usually set to "Application".
char product_code[0x10]; ///< Usually zeroed out.
u8 reserved_4[0x30];
NpdmSectionHeader aci_section_header; ///< Offset value relative to the start of this header.
NpdmSectionHeader acid_section_header; ///< Offset value relative to the start of this header.
u32 aci_offset; ///< Offset value relative to the start of this header.
u32 aci_size;
u32 acid_offset; ///< Offset value relative to the start of this header.
u32 acid_size;
} NpdmMetaHeader;
typedef enum {
NpdmMemoryRegion_Application = 0,
NpdmMemoryRegion_Applet = 1,
NpdmMemoryRegion_SecureSystem = 2,
NpdmMemoryRegion_NonSecureSystem = 3
NpdmMemoryRegion_SystemSecure = 2,
NpdmMemoryRegion_SystemNonSecure = 3,
/// Old.
NpdmMemoryRegion_NonSecure = NpdmMemoryRegion_Application,
NpdmMemoryRegion_Secure = NpdmMemoryRegion_Applet
} NpdmMemoryRegion;
typedef struct {
@ -92,9 +93,12 @@ typedef struct {
NpdmAcidFlags flags;
u64 program_id_min;
u64 program_id_max;
NpdmSectionHeader fs_access_control_section_header; ///< Offset value relative to the start of this header.
NpdmSectionHeader srv_access_control_section_header; ///< Offset value relative to the start of this header.
NpdmSectionHeader kernel_capability_section_header; ///< Offset value relative to the start of this header.
u32 fs_access_control_offset; ///< Offset value relative to the start of this header.
u32 fs_access_control_size;
u32 srv_access_control_offset; ///< Offset value relative to the start of this header.
u32 srv_access_control_size;
u32 kernel_capability_offset; ///< Offset value relative to the start of this header.
u32 kernel_capability_size;
u8 reserved_2[0x8];
} NpdmAcidHeader;
@ -105,9 +109,12 @@ typedef struct {
u8 reserved_1[0xC];
u64 program_id;
u8 reserved_2[0x8];
NpdmSectionHeader fs_access_control_section_header; ///< Offset value relative to the start of this header.
NpdmSectionHeader srv_access_control_section_header; ///< Offset value relative to the start of this header.
NpdmSectionHeader kernel_capability_section_header; ///< Offset value relative to the start of this header.
u32 fs_access_control_offset; ///< Offset value relative to the start of this header.
u32 fs_access_control_size;
u32 srv_access_control_offset; ///< Offset value relative to the start of this header.
u32 srv_access_control_size;
u32 kernel_capability_offset; ///< Offset value relative to the start of this header.
u32 kernel_capability_size;
u8 reserved_3[0x8];
} NpdmAciHeader;
@ -195,9 +202,8 @@ typedef struct {
} NpdmAciFsAccessControlDescriptorContentOwnerBlock;
typedef enum {
NpdmAccessibility_Read = 1,
NpdmAccessibility_Write = 2,
NpdmAccessibility_ReadWrite = 3
NpdmAccessibility_Read = BIT(0),
NpdmAccessibility_Write = BIT(1)
} NpdmAccessibility;
/// Placed after NpdmAciFsAccessControlDescriptor / NpdmAciFsAccessControlDescriptorContentOwnerBlock if the 'content_owner_info_size' member from NpdmAciFsAccessControlDescriptor is greater than zero.
@ -207,24 +213,46 @@ typedef struct {
u8 accessibility[]; ///< 'save_data_owner_id_count' NpdmAccessibility fields.
} NpdmAciFsAccessControlDescriptorSaveDataOwnerBlock;
/// SrvAccessControl descriptor. Part of the ACID and ACI0 section bodies.
/// This descriptor is composed of a variable number of NpdmSrvAccessControlDescriptorEntry elements, each one with a variable size.
/// Since the total number of services isn't stored anywhere, this descriptor must be parsed until its total size is reached.
typedef struct {
u8 name_length : 3; ///< Service name length minus 1.
u8 reserved : 4;
u8 is_server : 1; ///< Indicates if the service is allowed to be registered.
} NpdmSrvAccessControlEntryDescriptor;
char name[]; ///< Service name, stored without a NULL terminator. Supports the "*" wildcard character.
} NpdmSrvAccessControlDescriptorEntry;
/// SrvAccessControl descriptor. Part of the ACID and ACI0 section bodies.
/// This descriptor is composed of a variable number of NpdmSrvAccessControlEntry elements, each one with a variable size.
/// Since the total number of services isn't stored anywhere, this descriptor must be parsed until its total size is reached.
typedef struct {
NpdmSrvAccessControlEntryDescriptor descriptor;
char name[]; ///< Service name, stored without a NULL terminator. Supports the "*" wildcard character.
} NpdmSrvAccessControlEntry;
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;
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;
/// ThreadInfo entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 3; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 entry_value : NpdmKernelCapabilityEntryNumber_ThreadInfo; ///< Always set to NpdmKernelCapabilityEntryValue_ThreadInfo.
u32 padding : 1; ///< Always set to zero.
u32 lowest_priority : 6;
u32 highest_priority : 6;
u32 min_core_number : 8;
@ -234,153 +262,153 @@ typedef struct {
/// System call table.
typedef enum {
///< System calls for index 0.
NpdmSystemCallIds_Unknown1 = BIT(0),
NpdmSystemCallIds_SetHeapSize = BIT(1),
NpdmSystemCallIds_SetMemoryPermission = BIT(2),
NpdmSystemCallIds_SetMemoryAttribute = BIT(3),
NpdmSystemCallIds_MapMemory = BIT(4),
NpdmSystemCallIds_UnmapMemory = BIT(5),
NpdmSystemCallIds_QueryMemory = BIT(6),
NpdmSystemCallIds_ExitProcess = BIT(7),
NpdmSystemCallIds_CreateThread = BIT(8),
NpdmSystemCallIds_StartThread = BIT(9),
NpdmSystemCallIds_ExitThread = BIT(10),
NpdmSystemCallIds_SleepThread = BIT(11),
NpdmSystemCallIds_GetThreadPriority = BIT(12),
NpdmSystemCallIds_SetThreadPriority = BIT(13),
NpdmSystemCallIds_GetThreadCoreMask = BIT(14),
NpdmSystemCallIds_SetThreadCoreMask = BIT(15),
NpdmSystemCallIds_GetCurrentProcessorNumber = BIT(16),
NpdmSystemCallIds_SignalEvent = BIT(17),
NpdmSystemCallIds_ClearEvent = BIT(18),
NpdmSystemCallIds_MapSharedMemory = BIT(19),
NpdmSystemCallIds_UnmapSharedMemory = BIT(20),
NpdmSystemCallIds_CreateTransferMemory = BIT(21),
NpdmSystemCallIds_CloseHandle = BIT(22),
NpdmSystemCallIds_ResetSignal = BIT(23),
NpdmSystemCallId_Reserved1 = BIT(0),
NpdmSystemCallId_SetHeapSize = BIT(1),
NpdmSystemCallId_SetMemoryPermission = BIT(2),
NpdmSystemCallId_SetMemoryAttribute = BIT(3),
NpdmSystemCallId_MapMemory = BIT(4),
NpdmSystemCallId_UnmapMemory = BIT(5),
NpdmSystemCallId_QueryMemory = BIT(6),
NpdmSystemCallId_ExitProcess = BIT(7),
NpdmSystemCallId_CreateThread = BIT(8),
NpdmSystemCallId_StartThread = BIT(9),
NpdmSystemCallId_ExitThread = BIT(10),
NpdmSystemCallId_SleepThread = BIT(11),
NpdmSystemCallId_GetThreadPriority = BIT(12),
NpdmSystemCallId_SetThreadPriority = BIT(13),
NpdmSystemCallId_GetThreadCoreMask = BIT(14),
NpdmSystemCallId_SetThreadCoreMask = BIT(15),
NpdmSystemCallId_GetCurrentProcessorNumber = BIT(16),
NpdmSystemCallId_SignalEvent = BIT(17),
NpdmSystemCallId_ClearEvent = BIT(18),
NpdmSystemCallId_MapSharedMemory = BIT(19),
NpdmSystemCallId_UnmapSharedMemory = BIT(20),
NpdmSystemCallId_CreateTransferMemory = BIT(21),
NpdmSystemCallId_CloseHandle = BIT(22),
NpdmSystemCallId_ResetSignal = BIT(23),
///< System calls for index 1.
NpdmSystemCallIds_WaitSynchronization = BIT(0),
NpdmSystemCallIds_CancelSynchronization = BIT(1),
NpdmSystemCallIds_ArbitrateLock = BIT(2),
NpdmSystemCallIds_ArbitrateUnlock = BIT(3),
NpdmSystemCallIds_WaitProcessWideKeyAtomic = BIT(4),
NpdmSystemCallIds_SignalProcessWideKey = BIT(5),
NpdmSystemCallIds_GetSystemTick = BIT(6),
NpdmSystemCallIds_ConnectToNamedPort = BIT(7),
NpdmSystemCallIds_SendSyncRequestLight = BIT(8),
NpdmSystemCallIds_SendSyncRequest = BIT(9),
NpdmSystemCallIds_SendSyncRequestWithUserBuffer = BIT(10),
NpdmSystemCallIds_SendAsyncRequestWithUserBuffer = BIT(11),
NpdmSystemCallIds_GetProcessId = BIT(12),
NpdmSystemCallIds_GetThreadId = BIT(13),
NpdmSystemCallIds_Break = BIT(14),
NpdmSystemCallIds_OutputDebugString = BIT(15),
NpdmSystemCallIds_ReturnFromException = BIT(16),
NpdmSystemCallIds_GetInfo = BIT(17),
NpdmSystemCallIds_FlushEntireDataCache = BIT(18),
NpdmSystemCallIds_FlushDataCache = BIT(19),
NpdmSystemCallIds_MapPhysicalMemory = BIT(20),
NpdmSystemCallIds_UnmapPhysicalMemory = BIT(21),
NpdmSystemCallIds_GetDebugFutureThreadInfo = BIT(22),
NpdmSystemCallIds_GetLastThreadInfo = BIT(23),
NpdmSystemCallId_WaitSynchronization = BIT(0),
NpdmSystemCallId_CancelSynchronization = BIT(1),
NpdmSystemCallId_ArbitrateLock = BIT(2),
NpdmSystemCallId_ArbitrateUnlock = BIT(3),
NpdmSystemCallId_WaitProcessWideKeyAtomic = BIT(4),
NpdmSystemCallId_SignalProcessWideKey = BIT(5),
NpdmSystemCallId_GetSystemTick = BIT(6),
NpdmSystemCallId_ConnectToNamedPort = BIT(7),
NpdmSystemCallId_SendSyncRequestLight = BIT(8),
NpdmSystemCallId_SendSyncRequest = BIT(9),
NpdmSystemCallId_SendSyncRequestWithUserBuffer = BIT(10),
NpdmSystemCallId_SendAsyncRequestWithUserBuffer = BIT(11),
NpdmSystemCallId_GetProcessId = BIT(12),
NpdmSystemCallId_GetThreadId = BIT(13),
NpdmSystemCallId_Break = BIT(14),
NpdmSystemCallId_OutputDebugString = BIT(15),
NpdmSystemCallId_ReturnFromException = BIT(16),
NpdmSystemCallId_GetInfo = BIT(17),
NpdmSystemCallId_FlushEntireDataCache = BIT(18),
NpdmSystemCallId_FlushDataCache = BIT(19),
NpdmSystemCallId_MapPhysicalMemory = BIT(20),
NpdmSystemCallId_UnmapPhysicalMemory = BIT(21),
NpdmSystemCallId_GetDebugFutureThreadInfo = BIT(22), ///< Old: SystemCallId_GetFutureThreadInfo.
NpdmSystemCallId_GetLastThreadInfo = BIT(23),
///< System calls for index 2.
NpdmSystemCallIds_GetResourceLimitLimitValue = BIT(0),
NpdmSystemCallIds_GetResourceLimitCurrentValue = BIT(1),
NpdmSystemCallIds_SetThreadActivity = BIT(2),
NpdmSystemCallIds_GetThreadContext3 = BIT(3),
NpdmSystemCallIds_WaitForAddress = BIT(4),
NpdmSystemCallIds_SignalToAddress = BIT(5),
NpdmSystemCallIds_SynchronizePreemptionState = BIT(6),
NpdmSystemCallIds_Unknown2 = BIT(7),
NpdmSystemCallIds_Unknown3 = BIT(8),
NpdmSystemCallIds_Unknown4 = BIT(9),
NpdmSystemCallIds_Unknown5 = BIT(10),
NpdmSystemCallIds_Unknown6 = BIT(11),
NpdmSystemCallIds_KernelDebug = BIT(12),
NpdmSystemCallIds_ChangeKernelTraceState = BIT(13),
NpdmSystemCallIds_Unknown7 = BIT(14),
NpdmSystemCallIds_Unknown8 = BIT(15),
NpdmSystemCallIds_CreateSession = BIT(16),
NpdmSystemCallIds_AcceptSession = BIT(17),
NpdmSystemCallIds_ReplyAndReceiveLight = BIT(18),
NpdmSystemCallIds_ReplyAndReceive = BIT(19),
NpdmSystemCallIds_ReplyAndReceiveWithUserBuffer = BIT(20),
NpdmSystemCallIds_CreateEvent = BIT(21),
NpdmSystemCallIds_Unknown9 = BIT(22),
NpdmSystemCallIds_Unknown10 = BIT(23),
NpdmSystemCallId_GetResourceLimitLimitValue = BIT(0),
NpdmSystemCallId_GetResourceLimitCurrentValue = BIT(1),
NpdmSystemCallId_SetThreadActivity = BIT(2),
NpdmSystemCallId_GetThreadContext3 = BIT(3),
NpdmSystemCallId_WaitForAddress = BIT(4),
NpdmSystemCallId_SignalToAddress = BIT(5),
NpdmSystemCallId_SynchronizePreemptionState = BIT(6),
NpdmSystemCallId_Reserved2 = BIT(7),
NpdmSystemCallId_Reserved3 = BIT(8),
NpdmSystemCallId_Reserved4 = BIT(9),
NpdmSystemCallId_Reserved5 = BIT(10),
NpdmSystemCallId_Reserved6 = BIT(11),
NpdmSystemCallId_KernelDebug = BIT(12),
NpdmSystemCallId_ChangeKernelTraceState = BIT(13),
NpdmSystemCallId_Reserved7 = BIT(14),
NpdmSystemCallId_Reserved8 = BIT(15),
NpdmSystemCallId_CreateSession = BIT(16),
NpdmSystemCallId_AcceptSession = BIT(17),
NpdmSystemCallId_ReplyAndReceiveLight = BIT(18),
NpdmSystemCallId_ReplyAndReceive = BIT(19),
NpdmSystemCallId_ReplyAndReceiveWithUserBuffer = BIT(20),
NpdmSystemCallId_CreateEvent = BIT(21),
NpdmSystemCallId_Reserved9 = BIT(22),
NpdmSystemCallId_Reserved10 = BIT(23),
///< System calls for index 3.
NpdmSystemCallIds_MapPhysicalMemoryUnsafe = BIT(0),
NpdmSystemCallIds_UnmapPhysicalMemoryUnsafe = BIT(1),
NpdmSystemCallIds_SetUnsafeLimit = BIT(2),
NpdmSystemCallIds_CreateCodeMemory = BIT(3),
NpdmSystemCallIds_ControlCodeMemory = BIT(4),
NpdmSystemCallIds_SleepSystem = BIT(5),
NpdmSystemCallIds_ReadWriteRegister = BIT(6),
NpdmSystemCallIds_SetProcessActivity = BIT(7),
NpdmSystemCallIds_CreateSharedMemory = BIT(8),
NpdmSystemCallIds_MapTransferMemory = BIT(9),
NpdmSystemCallIds_UnmapTransferMemory = BIT(10),
NpdmSystemCallIds_CreateInterruptEvent = BIT(11),
NpdmSystemCallIds_QueryPhysicalAddress = BIT(12),
NpdmSystemCallIds_QueryIoMapping = BIT(13),
NpdmSystemCallIds_CreateDeviceAddressSpace = BIT(14),
NpdmSystemCallIds_AttachDeviceAddressSpace = BIT(15),
NpdmSystemCallIds_DetachDeviceAddressSpace = BIT(16),
NpdmSystemCallIds_MapDeviceAddressSpaceByForce = BIT(17),
NpdmSystemCallIds_MapDeviceAddressSpaceAligned = BIT(18),
NpdmSystemCallIds_MapDeviceAddressSpace = BIT(19),
NpdmSystemCallIds_UnmapDeviceAddressSpace = BIT(20),
NpdmSystemCallIds_InvalidateProcessDataCache = BIT(21),
NpdmSystemCallIds_StoreProcessDataCache = BIT(22),
NpdmSystemCallIds_FlushProcessDataCache = BIT(23),
NpdmSystemCallId_MapPhysicalMemoryUnsafe = BIT(0),
NpdmSystemCallId_UnmapPhysicalMemoryUnsafe = BIT(1),
NpdmSystemCallId_SetUnsafeLimit = BIT(2),
NpdmSystemCallId_CreateCodeMemory = BIT(3),
NpdmSystemCallId_ControlCodeMemory = BIT(4),
NpdmSystemCallId_SleepSystem = BIT(5),
NpdmSystemCallId_ReadWriteRegister = BIT(6),
NpdmSystemCallId_SetProcessActivity = BIT(7),
NpdmSystemCallId_CreateSharedMemory = BIT(8),
NpdmSystemCallId_MapTransferMemory = BIT(9),
NpdmSystemCallId_UnmapTransferMemory = BIT(10),
NpdmSystemCallId_CreateInterruptEvent = BIT(11),
NpdmSystemCallId_QueryPhysicalAddress = BIT(12),
NpdmSystemCallId_QueryIoMapping = BIT(13),
NpdmSystemCallId_CreateDeviceAddressSpace = BIT(14),
NpdmSystemCallId_AttachDeviceAddressSpace = BIT(15),
NpdmSystemCallId_DetachDeviceAddressSpace = BIT(16),
NpdmSystemCallId_MapDeviceAddressSpaceByForce = BIT(17),
NpdmSystemCallId_MapDeviceAddressSpaceAligned = BIT(18),
NpdmSystemCallId_MapDeviceAddressSpace = BIT(19),
NpdmSystemCallId_UnmapDeviceAddressSpace = BIT(20),
NpdmSystemCallId_InvalidateProcessDataCache = BIT(21),
NpdmSystemCallId_StoreProcessDataCache = BIT(22),
NpdmSystemCallId_FlushProcessDataCache = BIT(23),
///< System calls for index 4.
NpdmSystemCallIds_DebugActiveProcess = BIT(0),
NpdmSystemCallIds_BreakDebugProcess = BIT(1),
NpdmSystemCallIds_TerminateDebugProcess = BIT(2),
NpdmSystemCallIds_GetDebugEvent = BIT(3),
NpdmSystemCallIds_ContinueDebugEvent = BIT(4),
NpdmSystemCallIds_GetProcessList = BIT(5),
NpdmSystemCallIds_GetThreadList = BIT(6),
NpdmSystemCallIds_GetDebugThreadContext = BIT(7),
NpdmSystemCallIds_SetDebugThreadContext = BIT(8),
NpdmSystemCallIds_QueryDebugProcessMemory = BIT(9),
NpdmSystemCallIds_ReadDebugProcessMemory = BIT(10),
NpdmSystemCallIds_WriteDebugProcessMemory = BIT(11),
NpdmSystemCallIds_SetHardwareBreakPoint = BIT(12),
NpdmSystemCallIds_GetDebugThreadParam = BIT(13),
NpdmSystemCallIds_Unknown11 = BIT(14),
NpdmSystemCallIds_GetSystemInfo = BIT(15),
NpdmSystemCallIds_CreatePort = BIT(16),
NpdmSystemCallIds_ManageNamedPort = BIT(17),
NpdmSystemCallIds_ConnectToPort = BIT(18),
NpdmSystemCallIds_SetProcessMemoryPermission = BIT(19),
NpdmSystemCallIds_MapProcessMemory = BIT(20),
NpdmSystemCallIds_UnmapProcessMemory = BIT(21),
NpdmSystemCallIds_QueryProcessMemory = BIT(22),
NpdmSystemCallIds_MapProcessCodeMemory = BIT(23),
NpdmSystemCallId_DebugActiveProcess = BIT(0),
NpdmSystemCallId_BreakDebugProcess = BIT(1),
NpdmSystemCallId_TerminateDebugProcess = BIT(2),
NpdmSystemCallId_GetDebugEvent = BIT(3),
NpdmSystemCallId_ContinueDebugEvent = BIT(4),
NpdmSystemCallId_GetProcessList = BIT(5),
NpdmSystemCallId_GetThreadList = BIT(6),
NpdmSystemCallId_GetDebugThreadContext = BIT(7),
NpdmSystemCallId_SetDebugThreadContext = BIT(8),
NpdmSystemCallId_QueryDebugProcessMemory = BIT(9),
NpdmSystemCallId_ReadDebugProcessMemory = BIT(10),
NpdmSystemCallId_WriteDebugProcessMemory = BIT(11),
NpdmSystemCallId_SetHardwareBreakPoint = BIT(12),
NpdmSystemCallId_GetDebugThreadParam = BIT(13),
NpdmSystemCallId_Reserved11 = BIT(14),
NpdmSystemCallId_GetSystemInfo = BIT(15),
NpdmSystemCallId_CreatePort = BIT(16),
NpdmSystemCallId_ManageNamedPort = BIT(17),
NpdmSystemCallId_ConnectToPort = BIT(18),
NpdmSystemCallId_SetProcessMemoryPermission = BIT(19),
NpdmSystemCallId_MapProcessMemory = BIT(20),
NpdmSystemCallId_UnmapProcessMemory = BIT(21),
NpdmSystemCallId_QueryProcessMemory = BIT(22),
NpdmSystemCallId_MapProcessCodeMemory = BIT(23),
///< System calls for index 5.
NpdmSystemCallIds_UnmapProcessCodeMemory = BIT(0),
NpdmSystemCallIds_CreateProcess = BIT(1),
NpdmSystemCallIds_StartProcess = BIT(2),
NpdmSystemCallIds_TerminateProcess = BIT(3),
NpdmSystemCallIds_GetProcessInfo = BIT(4),
NpdmSystemCallIds_CreateResourceLimit = BIT(5),
NpdmSystemCallIds_SetResourceLimitLimitValue = BIT(6),
NpdmSystemCallIds_CallSecureMonitor = BIT(7),
NpdmSystemCallIds_Count = 0x80 ///< Total values supported by this enum.
} NpdmSystemCallIds;
NpdmSystemCallId_UnmapProcessCodeMemory = BIT(0),
NpdmSystemCallId_CreateProcess = BIT(1),
NpdmSystemCallId_StartProcess = BIT(2),
NpdmSystemCallId_TerminateProcess = BIT(3),
NpdmSystemCallId_GetProcessInfo = BIT(4),
NpdmSystemCallId_CreateResourceLimit = BIT(5),
NpdmSystemCallId_SetResourceLimitLimitValue = BIT(6),
NpdmSystemCallId_CallSecureMonitor = BIT(7),
NpdmSystemCallId_Count = 0x80 ///< Total values supported by this enum.
} NpdmSystemCallId;
/// EnableSystemCalls entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 4; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 system_call_ids : 24; ///< NpdmSystemCallIds.
u32 index : 3; ///< System calls index.
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.
} NpdmEnableSystemCalls;
typedef enum {
@ -389,34 +417,39 @@ typedef enum {
} NpdmPermissionType;
typedef enum {
NpdmMapType_Io = 0,
NpdmMapType_Static = 1
} NpdmMapType;
NpdmMappingType_Io = 0,
NpdmMappingType_Static = 1
} NpdmMappingType;
/// MemoryMapType1 entry for the KernelCapability descriptor.
/// Always followed by a MemoryMapType2 entry.
typedef struct {
u32 entry_number : 6; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
u32 permission_type : 1; ///< NpdmPermissionType.
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.
} NpdmMemoryMapType1;
/// MemoryMapType2 entry for the KernelCapability descriptor.
/// Always preceded by a MemoryMapType1 entry.
typedef struct {
u32 entry_number : 6; ///< All bits set to one.
u32 reserved_1 : 1; ///< Always set to zero.
u32 size : 20; ///< size << 12.
u32 reserved_2 : 4;
u32 map_type : 1; ///< NpdmMapType.
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 size : 20; ///< size << 12.
u32 reserved : 4;
u32 mapping_type : 1; ///< NpdmMappingType.
} NpdmMemoryMapType2;
/// MemoryMap entry for the KernelCapability descriptor.
/// These are always stored in pairs of MemoryMapType1 + MemoryMapType2 entries.
typedef struct {
union {
NpdmMemoryMapType1 type1;
NpdmMemoryMapType2 type2;
};
} NpdmMemoryMap;
/// IoMemoryMap entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 7; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
u32 entry_value : NpdmKernelCapabilityEntryNumber_IoMemoryMap; ///< Always set to NpdmKernelCapabilityEntryValue_IoMemoryMap.
u32 padding : 1; ///< Always set to zero.
u32 begin_address : 24; ///< begin_address << 12.
} NpdmIoMemoryMap;
typedef enum {
@ -428,22 +461,22 @@ typedef enum {
/// MemoryRegionMap entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 10; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
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 region_type_3 : 6; ///< NpdmRegionType.
u32 permission_type_3 : 1; ///< NpdmPermissionType.
u32 entry_value : NpdmKernelCapabilityEntryNumber_MemoryRegionMap; ///< Always set to NpdmKernelCapabilityEntryValue_MemoryRegionMap.
u32 padding : 1; ///< Always set to zero.
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 region_type_3 : 6; ///< NpdmRegionType.
u32 permission_type_3 : 1; ///< NpdmPermissionType.
} NpdmMemoryRegionMap;
/// EnableInterrupts entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 11; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 interrupt_number_1 : 10; ///< 0x3FF means empty.
u32 interrupt_number_2 : 10; ///< 0x3FF means empty.
u32 entry_value : NpdmKernelCapabilityEntryNumber_EnableInterrupts; ///< Always set to NpdmKernelCapabilityEntryValue_EnableInterrupts.
u32 padding : 1; ///< Always set to zero.
u32 interrupt_number_1 : 10; ///< 0x3FF means empty.
u32 interrupt_number_2 : 10; ///< 0x3FF means empty.
} NpdmEnableInterrupts;
typedef enum {
@ -455,35 +488,35 @@ typedef enum {
/// MiscParams entry for the KernelCapability descriptor.
/// Defaults to 0 if this entry doesn't exist.
typedef struct {
u32 entry_number : 13; ///< All bits set to one.
u32 reserved_1 : 1; ///< Always set to zero.
u32 program_type : 3; ///< NpdmProgramType.
u32 reserved_2 : 15;
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscParams; ///< Always set to NpdmKernelCapabilityEntryValue_MiscParams.
u32 padding : 1; ///< Always set to zero.
u32 program_type : 3; ///< NpdmProgramType.
u32 reserved : 15;
} NpdmMiscParams;
/// KernelVersion entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 14; ///< All bits set to one.
u32 reserved : 1; ///< Always set to zero.
u32 entry_value : NpdmKernelCapabilityEntryNumber_KernelVersion; ///< Always set to NpdmKernelCapabilityEntryValue_KernelVersion.
u32 padding : 1; ///< Always set to zero.
u32 minor_version : 4;
u32 major_version : 13;
} NpdmKernelVersion;
/// HandleTableSize entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 15; ///< All bits set to one.
u32 reserved_1 : 1; ///< Always set to zero.
u32 entry_value : NpdmKernelCapabilityEntryNumber_HandleTableSize; ///< Always set to NpdmKernelCapabilityEntryValue_HandleTableSize.
u32 padding : 1; ///< Always set to zero.
u32 handle_table_size : 10;
u32 reserved_2 : 6;
u32 reserved : 6;
} NpdmHandleTableSize;
/// MiscFlags entry for the KernelCapability descriptor.
typedef struct {
u32 entry_number : 16; ///< All bits set to one.
u32 reserved_1 : 1; ///< Always set to zero.
u32 entry_value : NpdmKernelCapabilityEntryNumber_MiscFlags; ///< Always set to NpdmKernelCapabilityEntryValue_MiscFlags.
u32 padding : 1; ///< Always set to zero.
u32 enable_debug : 1;
u32 force_debug : 1;
u32 reserved_2 : 13;
u32 reserved : 13;
} NpdmMiscFlags;
/// KernelCapability descriptor. Part of the ACID and ACI0 section bodies.
@ -491,6 +524,12 @@ typedef struct {
/// The entry type is identified by a pattern of "01...11" (zero followed by ones) in the low u16, counting from the LSB. The variable number of ones must never exceed 16 (entirety of the low u16).
typedef struct {
u32 value;
} NpdmKernelCapabilityEntry;
} NpdmKernelCapabilityDescriptorEntry;
/// Returns a value that can be compared to values from the NpdmKernelCapabilityEntryValue enum.
NX_INLINE u32 npdmGetKernelCapabilityDescriptorEntryValue(NpdmKernelCapabilityDescriptorEntry *entry)
{
return (entry ? (((entry->value + 1) & ~entry->value) - 1) : 0);
}
#endif /* __NPDM_H__ */

View file

@ -314,16 +314,19 @@ end:
RomFileSystemFileEntry *romfsGetFileEntryByPath(RomFileSystemContext *ctx, const char *path)
{
size_t path_len = 0;
u8 content_type = 0;
char *path_dup = NULL, *filename = NULL;
RomFileSystemFileEntry *file_entry = NULL;
RomFileSystemDirectoryEntry *dir_entry = NULL;
if (!ctx || !ctx->file_table || !ctx->file_table_size || !path || *path != '/' || (path_len = strlen(path)) <= 1)
if (!ctx || !ctx->file_table || !ctx->file_table_size || !ctx->nca_fs_ctx || !ctx->nca_fs_ctx->nca_ctx || !path || *path != '/' || (path_len = strlen(path)) <= 1)
{
LOGFILE("Invalid parameters!");
return NULL;
}
content_type = ((NcaContext*)ctx->nca_fs_ctx->nca_ctx)->content_type;
/* Duplicate path. */
if (!(path_dup = strdup(path)))
{
@ -359,10 +362,9 @@ RomFileSystemFileEntry *romfsGetFileEntryByPath(RomFileSystemContext *ctx, const
/* Retrieve file entry. */
if (!(file_entry = romfsGetChildFileEntryByName(ctx, dir_entry, filename)))
{
/* Only log error if we're not dealing with NACP icons. */
int res = strncmp("/icon_", path, 6);
if (res != 0 || (res == 0 && ((NcaContext*)ctx->nca_fs_ctx->nca_ctx)->content_type != NcmContentType_Control))
LOGFILE("Failed to retrieve file entry by name for \"%s\"! (\"%s\").", filename, path);
/* Only log error if we're not dealing with NACP icons or a LegalInformation XML. */
bool skip_log = ((!strncmp(path, "/icon_", 6) && content_type == NcmContentType_Control) || (!strncmp(path, "/legalinfo.xml", 14) && content_type == NcmContentType_LegalInformation));
if (!skip_log) LOGFILE("Failed to retrieve file entry by name for \"%s\"! (\"%s\").", filename, path);
}
end:

View file

@ -3,19 +3,21 @@ todo:
nca: functions for fs section lookup? (could just let the user choose...)
nca: function to write re-encrypted nca headers / nca fs headers (don't forget nca0 please)
nca: function to patch the private npdm acid signature from a program nca + patch the acid signature from the nca header
nca: add encrypted header to nca context, avoid re-encrypting the plaintext header in place
nca: use hash instead of dirty_header flag?
tik: option to wipe elicense property mask
tik: automatically dump tickets to the SD card?
tik: use dumped tickets when the original ones can't be found in the ES savefile?
gamecard: hfs0 filelist generation functions
gamecard: hfs0 functions to display filelist
pfs0: filelist generation functions
pfs0: functions to display filelist
pfs0: full header aligned to 0x20 (nsp)
romfs: filelist generation functions
romfs: functions to display filelist
bktr: filelist generation functions (wrappers for romfs filelist generation functions)
bktr: functions to display filelist (wrappers for romfs functions tbh)
title: more functions for title lookup (filters, patches / aoc, etc.)
title: more functions for content lookup (based on id?)