mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-09 20:21:45 +00:00
108 lines
4.1 KiB
C
108 lines
4.1 KiB
C
|
/*
|
||
|
* Copyright (c) 2020 DarkMatterCore
|
||
|
*
|
||
|
* This program 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.
|
||
|
*
|
||
|
* This program 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 <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "pfs0.h"
|
||
|
#include "utils.h"
|
||
|
|
||
|
#define PFS0_NCA_FS_HEADER_LAYER_COUNT 2
|
||
|
|
||
|
#define NPDM_META_MAGIC 0x4D455441 /* "META" */
|
||
|
|
||
|
bool pfs0InitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx)
|
||
|
{
|
||
|
if (!out || !nca_fs_ctx || nca_fs_ctx->section_type != NcaFsSectionType_PartitionFs || !nca_fs_ctx->header || nca_fs_ctx->header->fs_type != NcaFsType_PartitionFs || \
|
||
|
nca_fs_ctx->header->hash_type != NcaHashType_HierarchicalSha256)
|
||
|
{
|
||
|
LOGFILE("Invalid parameters!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Fill context */
|
||
|
out->nca_fs_ctx = nca_fs_ctx;
|
||
|
out->hash_info = &(nca_fs_ctx->header->hash_info.hierarchical_sha256);
|
||
|
out->offset = 0;
|
||
|
out->size = 0;
|
||
|
out->is_exefs = false;
|
||
|
out->header_size = 0;
|
||
|
out->header = NULL;
|
||
|
|
||
|
if (!out->hash_info->hash_block_size || out->hash_info->layer_count != PFS0_NCA_FS_HEADER_LAYER_COUNT || out->hash_info->hash_data_layer_info.offset >= out->nca_fs_ctx->section_size || \
|
||
|
!out->hash_info->hash_data_layer_info.size || (out->hash_info->hash_data_layer_info.offset + out->hash_info->hash_data_layer_info.size) > out->nca_fs_ctx->section_size || \
|
||
|
out->hash_info->hash_target_layer_info.offset >= out->nca_fs_ctx->section_size || !out->hash_info->hash_target_layer_info.size || \
|
||
|
(out->hash_info->hash_target_layer_info.offset + out->hash_info->hash_target_layer_info.size) > out->nca_fs_ctx->section_size)
|
||
|
{
|
||
|
LOGFILE("Invalid HierarchicalSha256 block!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
out->offset = out->hash_info->hash_target_layer_info.offset;
|
||
|
out->size = out->hash_info->hash_target_layer_info.size;
|
||
|
|
||
|
/* Read partial PFS0 header */
|
||
|
u32 magic = 0;
|
||
|
PartitionFileSystemHeader pfs0_header = {0};
|
||
|
|
||
|
u64 main_npdm_offset = 0;
|
||
|
PartitionFileSystemEntry *main_npdm_entry = NULL;
|
||
|
|
||
|
if (!ncaReadFsSection(nca_fs_ctx, &pfs0_header, sizeof(PartitionFileSystemHeader), out->offset))
|
||
|
{
|
||
|
LOGFILE("Failed to read partial PFS0 header!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
magic = __builtin_bswap32(pfs0_header.magic);
|
||
|
if (magic != PFS0_MAGIC)
|
||
|
{
|
||
|
LOGFILE("Invalid PFS0 magic word! (0x%08X)", magic);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!pfs0_header.entry_count || !pfs0_header.name_table_size)
|
||
|
{
|
||
|
LOGFILE("Invalid PFS0 entry count / name table size!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Calculate full PFS0 header size */
|
||
|
out->header_size = (sizeof(PartitionFileSystemHeader) + (pfs0_header.entry_count * sizeof(PartitionFileSystemEntry)) + pfs0_header.name_table_size);
|
||
|
|
||
|
/* Allocate memory for the full PFS0 header */
|
||
|
out->header = calloc(out->header_size, sizeof(u8));
|
||
|
if (!out->header)
|
||
|
{
|
||
|
LOGFILE("Unable to allocate 0x%lX bytes buffer for the full PFS0 header!", out->header_size);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Read full PFS0 header */
|
||
|
if (!ncaReadFsSection(nca_fs_ctx, out->header, out->header_size, out->offset))
|
||
|
{
|
||
|
LOGFILE("Failed to read full PFS0 header!");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Check if we're dealing with an ExeFS section */
|
||
|
if ((main_npdm_entry = pfs0GetEntryByName(out, "main.npdm")) != NULL && pfs0GetEntryDataOffset(out, main_npdm_entry, &main_npdm_offset) && \
|
||
|
ncaReadFsSection(out->nca_fs_ctx, &magic, sizeof(u32), main_npdm_offset) && __builtin_bswap32(magic) == NPDM_META_MAGIC) out->is_exefs = true;
|
||
|
|
||
|
return true;
|
||
|
}
|