mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Wipe more legacy code that has already been rewritten.
This commit is contained in:
parent
84f651eae8
commit
4ab8f44003
5 changed files with 1 additions and 820 deletions
|
@ -87,7 +87,7 @@ int main(int argc, char *argv[])
|
|||
while(true)
|
||||
{
|
||||
consoleClear();
|
||||
printf("select an user application to generate a cnmt xml for.\npress b to exit.\n\n");
|
||||
printf("select an user application to generate xmls for.\npress b to exit.\n\n");
|
||||
printf("title: %u / %u\n", selected_idx + 1, app_count);
|
||||
printf("selected title: %016lX - %s\n\n", app_metadata[selected_idx]->title_id, app_metadata[selected_idx]->lang_entry.name);
|
||||
|
||||
|
|
329
legacy/nca.c
329
legacy/nca.c
|
@ -931,332 +931,3 @@ bool patchCnmtNca(u8 *ncaBuf, u64 ncaBufSize, cnmt_xml_program_info *xml_program
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool generateProgramInfoXml(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys, bool useCustomAcidRsaPubKey, char **outBuf, u64 *outBufSize)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !dec_nca_header || !decrypted_nca_keys || !outBuf || !outBufSize)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to generate \"programinfo.xml\"!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dec_nca_header->fs_headers[0].partition_type != NCA_FS_HEADER_PARTITION_PFS0 || dec_nca_header->fs_headers[0].fs_type != NCA_FS_HEADER_FSTYPE_PFS0)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: Program NCA section #0 doesn't hold a PFS0 partition!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dec_nca_header->fs_headers[0].pfs0_superblock.pfs0_size)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid size for PFS0 partition in Program NCA section #0!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dec_nca_header->fs_headers[0].crypt_type != NCA_FS_HEADER_CRYPT_CTR)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid AES crypt type for Program NCA section #0! (0x%02X)", __func__, dec_nca_header->fs_headers[0].crypt_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 i;
|
||||
|
||||
bool proceed = true, success = false;
|
||||
|
||||
u64 section_offset;
|
||||
u64 nca_pfs0_offset;
|
||||
|
||||
pfs0_header nca_pfs0_header;
|
||||
pfs0_file_entry *nca_pfs0_entries = NULL;
|
||||
char *nca_pfs0_str_table = NULL;
|
||||
|
||||
u64 nca_pfs0_str_table_offset;
|
||||
u64 nca_pfs0_data_offset;
|
||||
|
||||
Aes128CtrContext aes_ctx;
|
||||
|
||||
char *programInfoXml = NULL;
|
||||
char tmp[NAME_BUF_LEN] = {'\0'};
|
||||
|
||||
u32 npdmEntry = 0;
|
||||
npdm_t npdm_header;
|
||||
u8 *npdm_acid_section = NULL;
|
||||
|
||||
u64 npdm_acid_section_b64_size = 0;
|
||||
char *npdm_acid_section_b64 = NULL;
|
||||
|
||||
u32 acid_flags = 0;
|
||||
|
||||
section_offset = ((u64)dec_nca_header->section_entries[0].media_start_offset * (u64)MEDIA_UNIT_SIZE);
|
||||
nca_pfs0_offset = (section_offset + dec_nca_header->fs_headers[0].pfs0_superblock.pfs0_offset);
|
||||
|
||||
if (!section_offset || section_offset < NCA_FULL_HEADER_LENGTH || !nca_pfs0_offset)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid offsets for Program NCA section #0!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate initial CTR
|
||||
unsigned char ctr[0x10];
|
||||
u64 ofs = (section_offset >> 4);
|
||||
|
||||
for(i = 0; i < 0x8; i++)
|
||||
{
|
||||
ctr[i] = dec_nca_header->fs_headers[0].section_ctr[0x08 - i - 1];
|
||||
ctr[0x10 - i - 1] = (unsigned char)(ofs & 0xFF);
|
||||
ofs >>= 8;
|
||||
}
|
||||
|
||||
u8 ctr_key[NCA_KEY_AREA_KEY_SIZE];
|
||||
memcpy(ctr_key, decrypted_nca_keys + (NCA_KEY_AREA_KEY_SIZE * 2), NCA_KEY_AREA_KEY_SIZE);
|
||||
aes128CtrContextCreate(&aes_ctx, ctr_key, ctr);
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, nca_pfs0_offset, &nca_pfs0_header, sizeof(pfs0_header), false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read Program NCA section #0 PFS0 partition header!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__builtin_bswap32(nca_pfs0_header.magic) != PFS0_MAGIC)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid magic word for Program NCA section #0 PFS0 partition! Wrong KAEK? (0x%08X)\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__, __builtin_bswap32(nca_pfs0_header.magic));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nca_pfs0_header.file_cnt || !nca_pfs0_header.str_table_size)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: Program NCA section #0 PFS0 partition is empty! Wrong KAEK?\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
nca_pfs0_entries = calloc(nca_pfs0_header.file_cnt, sizeof(pfs0_file_entry));
|
||||
if (!nca_pfs0_entries)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for Program NCA section #0 PFS0 partition entries!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, nca_pfs0_offset + sizeof(pfs0_header), nca_pfs0_entries, (u64)nca_pfs0_header.file_cnt * sizeof(pfs0_file_entry), false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read Program NCA section #0 PFS0 partition entries!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nca_pfs0_str_table_offset = (nca_pfs0_offset + sizeof(pfs0_header) + ((u64)nca_pfs0_header.file_cnt * sizeof(pfs0_file_entry)));
|
||||
|
||||
nca_pfs0_str_table = calloc((u64)nca_pfs0_header.str_table_size, sizeof(char));
|
||||
if (!nca_pfs0_str_table)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for Program NCA section #0 PFS0 string table!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, nca_pfs0_str_table_offset, nca_pfs0_str_table, (u64)nca_pfs0_header.str_table_size, false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read Program NCA section #0 PFS0 string table!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nca_pfs0_data_offset = (nca_pfs0_str_table_offset + (u64)nca_pfs0_header.str_table_size);
|
||||
|
||||
// Allocate memory for the programinfo.xml contents, making sure there's enough space
|
||||
programInfoXml = calloc(NSP_XML_BUFFER_SIZE, sizeof(char));
|
||||
if (!programInfoXml)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the \"programinfo.xml\" contents!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(programInfoXml, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \
|
||||
"<ProgramInfo>\n" \
|
||||
" <SdkVersion>%u_%u_%u</SdkVersion>\n", dec_nca_header->sdk_major, dec_nca_header->sdk_minor, dec_nca_header->sdk_micro);
|
||||
|
||||
// Retrieve the main.npdm contents
|
||||
bool found_npdm = false;
|
||||
for(i = 0; i < nca_pfs0_header.file_cnt; i++)
|
||||
{
|
||||
char *curFilename = (nca_pfs0_str_table + nca_pfs0_entries[i].filename_offset);
|
||||
|
||||
if (strlen(curFilename) == 9 && !strncasecmp(curFilename, "main.npdm", 9) && nca_pfs0_entries[i].file_size > 0)
|
||||
{
|
||||
found_npdm = true;
|
||||
npdmEntry = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_npdm)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the \"programinfo.xml\" contents!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Read the META header from the NPDM
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, nca_pfs0_data_offset + nca_pfs0_entries[npdmEntry].file_offset, &npdm_header, sizeof(npdm_t), false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read NPDM entry header from Program NCA section #0 PFS0!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (__builtin_bswap32(npdm_header.magic) != META_MAGIC)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid NPDM META magic word! Wrong KAEK? (0x%08X)\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__, __builtin_bswap32(npdm_header.magic));
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Allocate memory for the ACID section
|
||||
npdm_acid_section = malloc(npdm_header.acid_size);
|
||||
if (!npdm_acid_section)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the Program NCA NPDM ACID section contents!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, nca_pfs0_data_offset + nca_pfs0_entries[npdmEntry].file_offset + (u64)npdm_header.acid_offset, npdm_acid_section, (u64)npdm_header.acid_size, false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read ACID section from Program NCA NPDM!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// If we're dealing with a gamecard title, replace the ACID public key with the patched one
|
||||
if (useCustomAcidRsaPubKey) memcpy(npdm_acid_section + (u64)NPDM_SIGNATURE_SIZE, rsa_get_public_key(), (u64)NPDM_SIGNATURE_SIZE);
|
||||
|
||||
sprintf(tmp, " <BuildTarget>%u</BuildTarget>\n", ((npdm_header.mmu_flags & 0x01) ? 64 : 32));
|
||||
strcat(programInfoXml, tmp);
|
||||
|
||||
// Default this one to Release
|
||||
strcat(programInfoXml, " <BuildType>Release</BuildType>\n");
|
||||
|
||||
// Retrieve the Base64 conversion length for the whole ACID section
|
||||
mbedtls_base64_encode(NULL, 0, &npdm_acid_section_b64_size, npdm_acid_section, (u64)npdm_header.acid_size);
|
||||
if (npdm_acid_section_b64_size <= (u64)npdm_header.acid_size)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid Base64 conversion length for the ACID section from Program NCA NPDM!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
npdm_acid_section_b64 = calloc(npdm_acid_section_b64_size + 1, sizeof(char));
|
||||
if (!npdm_acid_section_b64)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the Base64 converted ACID section from Program NCA NPDM!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Perform the Base64 conversion
|
||||
if (mbedtls_base64_encode((unsigned char*)npdm_acid_section_b64, npdm_acid_section_b64_size + 1, &npdm_acid_section_b64_size, npdm_acid_section, (u64)npdm_header.acid_size) != 0)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: Base64 conversion failed for the ACID section from Program NCA NPDM!", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcat(programInfoXml, " <Desc>");
|
||||
strcat(programInfoXml, npdm_acid_section_b64);
|
||||
strcat(programInfoXml, "</Desc>\n");
|
||||
|
||||
// TO-DO: Add more ACID flags?
|
||||
|
||||
acid_flags = *((u32*)(&(npdm_acid_section[0x20C])));
|
||||
|
||||
strcat(programInfoXml, " <DescFlags>\n");
|
||||
|
||||
sprintf(tmp, " <Production>%s</Production>\n", ((acid_flags & 0x01) ? "true" : "false"));
|
||||
strcat(programInfoXml, tmp);
|
||||
|
||||
sprintf(tmp, " <UnqualifiedApproval>%s</UnqualifiedApproval>\n", ((acid_flags & 0x02) ? "true" : "false"));
|
||||
strcat(programInfoXml, tmp);
|
||||
|
||||
strcat(programInfoXml, " </DescFlags>\n");
|
||||
|
||||
// Middleware list
|
||||
strcat(programInfoXml, " <MiddlewareList>\n");
|
||||
|
||||
for(i = 0; i < nca_pfs0_header.file_cnt; i++)
|
||||
{
|
||||
nso_header_t nsoHeader;
|
||||
char *curFilename = (nca_pfs0_str_table + nca_pfs0_entries[i].filename_offset);
|
||||
u64 curFileOffset = (nca_pfs0_data_offset + nca_pfs0_entries[i].file_offset);
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, curFileOffset, &nsoHeader, sizeof(nso_header_t), false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read 0x%016lX bytes from \"%s\" in Program NCA section #0 PFS0 partition!", __func__, sizeof(nso_header_t), curFilename);
|
||||
proceed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if we're dealing with a NSO
|
||||
if (__builtin_bswap32(nsoHeader.magic) != NSO_MAGIC) continue;
|
||||
|
||||
// Retrieve middleware list from this NSO
|
||||
if (!retrieveMiddlewareListFromNso(ncmStorage, ncaId, &aes_ctx, curFilename, curFileOffset, &nsoHeader, programInfoXml))
|
||||
{
|
||||
proceed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!proceed) goto out;
|
||||
|
||||
strcat(programInfoXml, " </MiddlewareList>\n");
|
||||
|
||||
// Leave these fields empty (for now)
|
||||
strcat(programInfoXml, " <DebugApiList />\n");
|
||||
strcat(programInfoXml, " <PrivateApiList />\n");
|
||||
|
||||
// Symbols list from main NSO
|
||||
strcat(programInfoXml, " <UnresolvedApiList>\n");
|
||||
|
||||
for(i = 0; i < nca_pfs0_header.file_cnt; i++)
|
||||
{
|
||||
nso_header_t nsoHeader;
|
||||
char *curFilename = (nca_pfs0_str_table + nca_pfs0_entries[i].filename_offset);
|
||||
u64 curFileOffset = (nca_pfs0_data_offset + nca_pfs0_entries[i].file_offset);
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, &aes_ctx, curFileOffset, &nsoHeader, sizeof(nso_header_t), false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read 0x%016lX bytes from \"%s\" in Program NCA section #0 PFS0 partition!", __func__, sizeof(nso_header_t), curFilename);
|
||||
proceed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if we're dealing with the main NSO
|
||||
if (strlen(curFilename) != 4 || strncmp(curFilename, "main", 4) != 0 || __builtin_bswap32(nsoHeader.magic) != NSO_MAGIC) continue;
|
||||
|
||||
// Retrieve symbols list from main NSO
|
||||
if (!retrieveSymbolsListFromNso(ncmStorage, ncaId, &aes_ctx, curFilename, curFileOffset, &nsoHeader, programInfoXml)) proceed = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!proceed) goto out;
|
||||
|
||||
strcat(programInfoXml, " </UnresolvedApiList>\n");
|
||||
|
||||
// Leave this field empty (for now)
|
||||
strcat(programInfoXml, " <FsAccessControlData />\n");
|
||||
|
||||
strcat(programInfoXml, "</ProgramInfo>");
|
||||
|
||||
*outBuf = programInfoXml;
|
||||
*outBufSize = strlen(programInfoXml);
|
||||
|
||||
success = true;
|
||||
|
||||
out:
|
||||
if (npdm_acid_section_b64) free(npdm_acid_section_b64);
|
||||
|
||||
if (npdm_acid_section) free(npdm_acid_section);
|
||||
|
||||
if (!success && programInfoXml) free(programInfoXml);
|
||||
|
||||
if (nca_pfs0_str_table) free(nca_pfs0_str_table);
|
||||
|
||||
if (nca_pfs0_entries) free(nca_pfs0_entries);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -365,6 +365,4 @@ 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 generateProgramInfoXml(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, nca_header_t *dec_nca_header, u8 *decrypted_nca_keys, bool useCustomAcidRsaPubKey, char **outBuf, u64 *outBufSize);
|
||||
|
||||
#endif
|
||||
|
|
430
legacy/nso.c
430
legacy/nso.c
|
@ -1,430 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nso.h"
|
||||
#include "lz4.h"
|
||||
#include "util.h"
|
||||
#include "ui.h"
|
||||
|
||||
/* Extern variables */
|
||||
|
||||
extern int breaks;
|
||||
extern int font_height;
|
||||
|
||||
/* Statically allocated variables */
|
||||
|
||||
static u8 *nsoBinaryData = NULL;
|
||||
static u64 nsoBinaryDataSize = 0;
|
||||
|
||||
static u64 nsoBinaryTextSectionOffset = 0;
|
||||
static u64 nsoBinaryTextSectionSize = 0;
|
||||
|
||||
static u64 nsoBinaryRodataSectionOffset = 0;
|
||||
static u64 nsoBinaryRodataSectionSize = 0;
|
||||
|
||||
static u64 nsoBinaryDataSectionOffset = 0;
|
||||
static u64 nsoBinaryDataSectionSize = 0;
|
||||
|
||||
void freeNsoBinaryData()
|
||||
{
|
||||
if (nsoBinaryData)
|
||||
{
|
||||
free(nsoBinaryData);
|
||||
nsoBinaryData = NULL;
|
||||
}
|
||||
|
||||
nsoBinaryDataSize = 0;
|
||||
|
||||
nsoBinaryTextSectionOffset = 0;
|
||||
nsoBinaryTextSectionSize = 0;
|
||||
|
||||
nsoBinaryRodataSectionOffset = 0;
|
||||
nsoBinaryRodataSectionSize = 0;
|
||||
|
||||
nsoBinaryDataSectionOffset = 0;
|
||||
nsoBinaryDataSectionSize = 0;
|
||||
}
|
||||
|
||||
bool loadNsoBinaryData(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *aes_ctx, u64 nso_base_offset, nso_header_t *nsoHeader)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !aes_ctx || !nso_base_offset || !nsoHeader)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to load .text, .rodata and .data sections from NSO in Program NCA!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 i;
|
||||
|
||||
u8 *nsoTextSection = NULL;
|
||||
u64 nsoTextSectionSize = 0;
|
||||
|
||||
u8 *nsoRodataSection = NULL;
|
||||
u64 nsoRodataSectionSize = 0;
|
||||
|
||||
u8 *nsoDataSection = NULL;
|
||||
u64 nsoDataSectionSize = 0;
|
||||
|
||||
u8 *curCompressedSection;
|
||||
u64 curCompressedSectionSize;
|
||||
u64 curCompressedSectionOffset;
|
||||
u8 curSectionFlag;
|
||||
|
||||
u8 *curDecompressedSection;
|
||||
u64 curDecompressedSectionSize;
|
||||
|
||||
bool success = true;
|
||||
|
||||
freeNsoBinaryData();
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
curCompressedSection = NULL;
|
||||
curCompressedSectionSize = (i == 0 ? (u64)nsoHeader->text_compressed_size : (i == 1 ? (u64)nsoHeader->rodata_compressed_size : (u64)nsoHeader->data_compressed_size));
|
||||
curCompressedSectionOffset = (nso_base_offset + (i == 0 ? (u64)nsoHeader->text_segment_header.file_offset : (i == 1 ? (u64)nsoHeader->rodata_segment_header.file_offset : (u64)nsoHeader->data_segment_header.file_offset)));
|
||||
curSectionFlag = (1 << i);
|
||||
|
||||
curDecompressedSection = NULL;
|
||||
curDecompressedSectionSize = (i == 0 ? (u64)nsoHeader->text_segment_header.decompressed_size : (i == 1 ? (u64)nsoHeader->rodata_segment_header.decompressed_size : (u64)nsoHeader->data_segment_header.decompressed_size));
|
||||
|
||||
// Load section
|
||||
curCompressedSection = malloc(curCompressedSectionSize);
|
||||
if (!curCompressedSection)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the compressed %s section from NSO in Program NCA!", __func__, (i == 0 ? ".text" : (i == 1 ? ".rodata" : ".data")));
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!processNcaCtrSectionBlock(ncmStorage, ncaId, aes_ctx, curCompressedSectionOffset, curCompressedSection, curCompressedSectionSize, false))
|
||||
{
|
||||
breaks++;
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to read 0x%016lX bytes %s section from NSO in Program NCA!", __func__, curCompressedSectionSize, (i == 0 ? ".text" : (i == 1 ? ".rodata" : ".data")));
|
||||
free(curCompressedSection);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nsoHeader->flags & curSectionFlag)
|
||||
{
|
||||
if (curDecompressedSectionSize <= curCompressedSectionSize)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid decompressed size for %s section from NSO in Program NCA!", __func__, (i == 0 ? ".text" : (i == 1 ? ".rodata" : ".data")));
|
||||
free(curCompressedSection);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Uncompress section
|
||||
curDecompressedSection = malloc(curDecompressedSectionSize);
|
||||
if (!curDecompressedSection)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate memory for the decompressed %s section from NSO in Program NCA!", __func__, (i == 0 ? ".text" : (i == 1 ? ".rodata" : ".data")));
|
||||
free(curCompressedSection);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (LZ4_decompress_safe((const char*)curCompressedSection, (char*)curDecompressedSection, (int)curCompressedSectionSize, (int)curDecompressedSectionSize) != (int)curDecompressedSectionSize)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to decompress %s section from NSO in Program NCA!", __func__, (i == 0 ? ".text" : (i == 1 ? ".rodata" : ".data")));
|
||||
free(curDecompressedSection);
|
||||
free(curCompressedSection);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
free(curCompressedSection);
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
nsoTextSection = curDecompressedSection;
|
||||
nsoTextSectionSize = curDecompressedSectionSize;
|
||||
break;
|
||||
case 1:
|
||||
nsoRodataSection = curDecompressedSection;
|
||||
nsoRodataSectionSize = curDecompressedSectionSize;
|
||||
break;
|
||||
case 2:
|
||||
nsoDataSection = curDecompressedSection;
|
||||
nsoDataSectionSize = curDecompressedSectionSize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
nsoTextSection = curCompressedSection;
|
||||
nsoTextSectionSize = curCompressedSectionSize;
|
||||
break;
|
||||
case 1:
|
||||
nsoRodataSection = curCompressedSection;
|
||||
nsoRodataSectionSize = curCompressedSectionSize;
|
||||
break;
|
||||
case 2:
|
||||
nsoDataSection = curCompressedSection;
|
||||
nsoDataSectionSize = curCompressedSectionSize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curCompressedSection = curDecompressedSection = NULL;
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Calculate full binary size
|
||||
u64 finalTextSectionSize = nsoTextSectionSize;
|
||||
u64 finalRodataSectionSize = nsoRodataSectionSize;
|
||||
|
||||
nsoBinaryDataSize = nsoTextSectionSize;
|
||||
|
||||
if ((u64)nsoHeader->rodata_segment_header.memory_offset > nsoBinaryDataSize)
|
||||
{
|
||||
nsoBinaryDataSize += ((u64)nsoHeader->rodata_segment_header.memory_offset - nsoBinaryDataSize);
|
||||
} else
|
||||
if ((u64)nsoHeader->rodata_segment_header.memory_offset < nsoBinaryDataSize)
|
||||
{
|
||||
finalTextSectionSize -= (nsoBinaryDataSize - (u64)nsoHeader->rodata_segment_header.memory_offset);
|
||||
nsoBinaryDataSize -= (nsoBinaryDataSize - (u64)nsoHeader->rodata_segment_header.memory_offset);
|
||||
}
|
||||
|
||||
nsoBinaryDataSize += nsoRodataSectionSize;
|
||||
|
||||
if ((u64)nsoHeader->data_segment_header.memory_offset > nsoBinaryDataSize)
|
||||
{
|
||||
nsoBinaryDataSize += ((u64)nsoHeader->data_segment_header.memory_offset - nsoBinaryDataSize);
|
||||
} else
|
||||
if ((u64)nsoHeader->data_segment_header.memory_offset < nsoBinaryDataSize)
|
||||
{
|
||||
finalRodataSectionSize -= (nsoBinaryDataSize - (u64)nsoHeader->data_segment_header.memory_offset);
|
||||
nsoBinaryDataSize -= (nsoBinaryDataSize - (u64)nsoHeader->data_segment_header.memory_offset);
|
||||
}
|
||||
|
||||
nsoBinaryDataSize += nsoDataSectionSize;
|
||||
|
||||
nsoBinaryData = calloc(nsoBinaryDataSize, sizeof(u8));
|
||||
if (nsoBinaryData)
|
||||
{
|
||||
memcpy(nsoBinaryData, nsoTextSection, finalTextSectionSize);
|
||||
memcpy(nsoBinaryData + (u64)nsoHeader->rodata_segment_header.memory_offset, nsoRodataSection, finalRodataSectionSize);
|
||||
memcpy(nsoBinaryData + (u64)nsoHeader->data_segment_header.memory_offset, nsoDataSection, nsoDataSectionSize);
|
||||
|
||||
nsoBinaryTextSectionOffset = 0;
|
||||
nsoBinaryTextSectionSize = finalTextSectionSize;
|
||||
|
||||
nsoBinaryRodataSectionOffset = (u64)nsoHeader->rodata_segment_header.memory_offset;
|
||||
nsoBinaryRodataSectionSize = finalRodataSectionSize;
|
||||
|
||||
nsoBinaryDataSectionOffset = (u64)nsoHeader->data_segment_header.memory_offset;
|
||||
nsoBinaryDataSectionSize = nsoDataSectionSize;
|
||||
} else {
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to allocate %lu bytes for full decompressed NSO in Program NCA!", __func__, nsoBinaryDataSize);
|
||||
nsoBinaryDataSize = 0;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsoTextSection) free(nsoTextSection);
|
||||
if (nsoRodataSection) free(nsoRodataSection);
|
||||
if (nsoDataSection) free(nsoDataSection);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool retrieveMiddlewareListFromNso(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *aes_ctx, const char *nso_filename, u64 nso_base_offset, nso_header_t *nsoHeader, char *programInfoXml)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !aes_ctx || !nso_filename || !strlen(nso_filename) || !nso_base_offset || !nsoHeader || !programInfoXml)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to retrieve middleware list from NSO in Program NCA!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 i;
|
||||
|
||||
char tmp[NAME_BUF_LEN] = {'\0'};
|
||||
|
||||
if (!loadNsoBinaryData(ncmStorage, ncaId, aes_ctx, nso_base_offset, nsoHeader)) return false;
|
||||
|
||||
for(i = 0; i < nsoBinaryRodataSectionSize; i++)
|
||||
{
|
||||
char *curStr = ((char*)nsoBinaryData + nsoBinaryRodataSectionOffset + i);
|
||||
|
||||
if (strncmp(curStr, "SDK MW+", 7) != 0) continue;
|
||||
|
||||
// Found a match
|
||||
char *mwDev = (curStr + 7);
|
||||
char *mwName = (strchr(mwDev, '+') + 1);
|
||||
|
||||
// Filter nnSdk entries
|
||||
if (!strncasecmp(mwName, "NintendoSdk_nnSdk", 17))
|
||||
{
|
||||
i += strlen(curStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(tmp, " <Middleware>\n" \
|
||||
" <ModuleName>%s</ModuleName>\n" \
|
||||
" <VenderName>%.*s</VenderName>\n" \
|
||||
" <NsoName>%s</NsoName>\n" \
|
||||
" </Middleware>\n", \
|
||||
mwName, \
|
||||
(int)(mwName - mwDev - 1), mwDev, \
|
||||
nso_filename);
|
||||
|
||||
strcat(programInfoXml, tmp);
|
||||
|
||||
// Update counter
|
||||
i += strlen(curStr);
|
||||
}
|
||||
|
||||
freeNsoBinaryData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool retrieveSymbolsListFromNso(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *aes_ctx, const char *nso_filename, u64 nso_base_offset, nso_header_t *nsoHeader, char *programInfoXml)
|
||||
{
|
||||
if (!ncmStorage || !ncaId || !aes_ctx || !nso_filename || !strlen(nso_filename) || !nso_base_offset || !nsoHeader || !programInfoXml)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid parameters to retrieve symbols list from NSO in Program NCA!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 i;
|
||||
|
||||
bool success = false;
|
||||
|
||||
char tmp[NAME_BUF_LEN] = {'\0'};
|
||||
|
||||
u32 mod_magic_offset;
|
||||
u32 mod_magic;
|
||||
s32 dynamic_section_offset;
|
||||
|
||||
bool armv7;
|
||||
|
||||
u64 dynamic_block_size;
|
||||
u64 dynamic_block_cnt;
|
||||
|
||||
bool found_strtab = false;
|
||||
u64 symbol_str_table_offset = 0;
|
||||
|
||||
bool found_symtab = false;
|
||||
u64 symbol_table_offset = 0;
|
||||
|
||||
bool found_strsz = false;
|
||||
u64 symbol_str_table_size = 0;
|
||||
|
||||
char *symbol_str_table = NULL;
|
||||
|
||||
u64 cur_symbol_table_offset = 0;
|
||||
|
||||
if (!loadNsoBinaryData(ncmStorage, ncaId, aes_ctx, nso_base_offset, nsoHeader)) return false;
|
||||
|
||||
mod_magic_offset = *((u32*)(&(nsoBinaryData[0x04])));
|
||||
mod_magic = *((u32*)(&(nsoBinaryData[mod_magic_offset])));
|
||||
dynamic_section_offset = ((s32)mod_magic_offset + *((s32*)(&(nsoBinaryData[mod_magic_offset + 0x04]))));
|
||||
|
||||
if (__builtin_bswap32(mod_magic) != MOD_MAGIC)
|
||||
{
|
||||
uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid MOD0 magic word in decompressed NSO from Program NCA! (0x%08X)", __func__, __builtin_bswap32(mod_magic));
|
||||
goto out;
|
||||
}
|
||||
|
||||
armv7 = (*((u64*)(&(nsoBinaryData[dynamic_section_offset]))) > (u64)0xFFFFFFFF || *((u64*)(&(nsoBinaryData[dynamic_section_offset + 0x10]))) > (u64)0xFFFFFFFF);
|
||||
|
||||
// Read dynamic section
|
||||
dynamic_block_size = (armv7 ? 0x08 : 0x10);
|
||||
dynamic_block_cnt = ((nsoBinaryDataSize - dynamic_section_offset) / dynamic_block_size);
|
||||
|
||||
for(i = 0; i < dynamic_block_cnt; i++)
|
||||
{
|
||||
if ((nsoBinaryDataSize - dynamic_section_offset - (i * dynamic_block_size)) < dynamic_block_size) break;
|
||||
|
||||
u64 tag = (armv7 ? (u64)(*((u32*)(&(nsoBinaryData[dynamic_section_offset + (i * dynamic_block_size)])))) : *((u64*)(&(nsoBinaryData[dynamic_section_offset + (i * dynamic_block_size)]))));
|
||||
u64 val = (armv7 ? (u64)(*((u32*)(&(nsoBinaryData[dynamic_section_offset + (i * dynamic_block_size) + 0x04])))) : *((u64*)(&(nsoBinaryData[dynamic_section_offset + (i * dynamic_block_size) + 0x08]))));
|
||||
|
||||
if (!tag) break;
|
||||
|
||||
if (tag == DT_STRTAB && !found_strtab)
|
||||
{
|
||||
// Retrieve symbol string table offset
|
||||
symbol_str_table_offset = val;
|
||||
found_strtab = true;
|
||||
}
|
||||
|
||||
if (tag == DT_SYMTAB && !found_symtab)
|
||||
{
|
||||
// Retrieve symbol table offset
|
||||
symbol_table_offset = val;
|
||||
found_symtab = true;
|
||||
}
|
||||
|
||||
if (tag == DT_STRSZ && !found_strsz)
|
||||
{
|
||||
// Retrieve symbol string table size
|
||||
symbol_str_table_size = val;
|
||||
found_strsz = true;
|
||||
}
|
||||
|
||||
if (found_strtab && found_symtab && found_strsz) break;
|
||||
}
|
||||
|
||||
if (!found_strtab || !found_symtab || !found_strsz)
|
||||
{
|
||||
// Nothing to do here if we can't find what we need
|
||||
success = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Point to the symbol string table
|
||||
symbol_str_table = ((char*)nsoBinaryData + symbol_str_table_offset);
|
||||
|
||||
// Retrieve symbol list
|
||||
cur_symbol_table_offset = symbol_table_offset;
|
||||
while(true)
|
||||
{
|
||||
if (symbol_table_offset < symbol_str_table_offset && cur_symbol_table_offset >= symbol_str_table_offset) break;
|
||||
|
||||
u32 st_name = *((u32*)(&(nsoBinaryData[cur_symbol_table_offset])));
|
||||
u8 st_info = (armv7 ? nsoBinaryData[cur_symbol_table_offset + 0x0C] : nsoBinaryData[cur_symbol_table_offset + 0x04]);
|
||||
//u8 st_other = (armv7 ? nsoBinaryData[cur_symbol_table_offset + 0x0D] : nsoBinaryData[cur_symbol_table_offset + 0x05]);
|
||||
u16 st_shndx = (armv7 ? *((u16*)(&(nsoBinaryData[cur_symbol_table_offset + 0x0E]))) : *((u16*)(&(nsoBinaryData[cur_symbol_table_offset + 0x06]))));
|
||||
u64 st_value = (armv7 ? (u64)(*((u32*)(&(nsoBinaryData[cur_symbol_table_offset + 0x04])))) : *((u64*)(&(nsoBinaryData[cur_symbol_table_offset + 0x08]))));
|
||||
//u64 st_size = (armv7 ? (u64)(*((u32*)(&(nsoBinaryData[cur_symbol_table_offset + 0x08])))) : *((u64*)(&(nsoBinaryData[cur_symbol_table_offset + 0x10]))));
|
||||
|
||||
//u8 st_vis = (st_other & 0x03);
|
||||
u8 st_type = (st_info & 0x0F);
|
||||
//u8 st_bind = (st_info >> 0x04);
|
||||
|
||||
if (st_name >= symbol_str_table_size) break;
|
||||
|
||||
cur_symbol_table_offset += (armv7 ? 0x10 : 0x18);
|
||||
|
||||
// TO-DO: Add more filters?
|
||||
if (!st_shndx && !st_value && st_type != ST_OBJECT)
|
||||
{
|
||||
sprintf(tmp, " <UnresolvedApi>\n" \
|
||||
" <ApiName>%s</ApiName>\n" \
|
||||
" <NsoName>%s</NsoName>\n" \
|
||||
" </UnresolvedApi>\n", \
|
||||
symbol_str_table + st_name, \
|
||||
nso_filename);
|
||||
|
||||
strcat(programInfoXml, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
out:
|
||||
freeNsoBinaryData();
|
||||
|
||||
return success;
|
||||
}
|
58
legacy/nso.h
58
legacy/nso.h
|
@ -1,58 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef __NSO_H__
|
||||
#define __NSO_H__
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
#define NSO_MAGIC (u32)0x4E534F30 // "NSO0"
|
||||
#define MOD_MAGIC (u32)0x4D4F4430 // "MOD0"
|
||||
|
||||
#define DT_STRTAB 0x05
|
||||
#define DT_SYMTAB 0x06
|
||||
#define DT_STRSZ 0x0A
|
||||
|
||||
#define ST_OBJECT 0x01
|
||||
|
||||
typedef struct {
|
||||
u32 file_offset;
|
||||
u32 memory_offset;
|
||||
u32 decompressed_size;
|
||||
} PACKED segment_header_t;
|
||||
|
||||
typedef struct {
|
||||
u32 region_offset;
|
||||
u32 region_size;
|
||||
} PACKED rodata_extent_t;
|
||||
|
||||
typedef struct {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 reserved1;
|
||||
u32 flags;
|
||||
segment_header_t text_segment_header;
|
||||
u32 module_offset;
|
||||
segment_header_t rodata_segment_header;
|
||||
u32 module_file_size;
|
||||
segment_header_t data_segment_header;
|
||||
u32 bss_size;
|
||||
u8 elf_note_build_id[0x20];
|
||||
u32 text_compressed_size;
|
||||
u32 rodata_compressed_size;
|
||||
u32 data_compressed_size;
|
||||
u8 reserved2[0x1C];
|
||||
rodata_extent_t rodata_api_info;
|
||||
rodata_extent_t rodata_dynstr;
|
||||
rodata_extent_t rodata_dynsym;
|
||||
u8 text_decompressed_hash[0x20];
|
||||
u8 rodata_decompressed_hash[0x20];
|
||||
u8 data_decompressed_hash[0x20];
|
||||
} PACKED nso_header_t;
|
||||
|
||||
// Retrieves the middleware list from a NSO stored in a partition from a NCA file
|
||||
bool retrieveMiddlewareListFromNso(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *aes_ctx, const char *nso_filename, u64 nso_base_offset, nso_header_t *nsoHeader, char *programInfoXml);
|
||||
|
||||
// Retrieves the symbols list from a NSO stored in a partition from a NCA file
|
||||
bool retrieveSymbolsListFromNso(NcmContentStorage *ncmStorage, const NcmContentId *ncaId, Aes128CtrContext *aes_ctx, const char *nso_filename, u64 nso_base_offset, nso_header_t *nsoHeader, char *programInfoXml);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue