mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
75 lines
2.5 KiB
C
75 lines
2.5 KiB
C
#include "ncsd.h"
|
|
#include "ncch.h"
|
|
|
|
u32 ValidateNcsdHeader(NcsdHeader* header) {
|
|
static const u8 zeroes[16] = { 0 };
|
|
if ((memcmp(header->magic, "NCSD", 4) != 0) || // check magic number
|
|
(memcmp(header->partitions_fs_type, zeroes, 8) != 0) || !header->mediaId) // prevent detection of NAND images
|
|
return 1;
|
|
|
|
u32 data_units = 0;
|
|
for (u32 i = 0; i < 8; i++) {
|
|
NcchPartition* partition = header->partitions + i;
|
|
if ((i == 0) && !partition->size) return 1; // first content must be there
|
|
else if (!partition->size) continue;
|
|
if (partition->offset < data_units)
|
|
return 1; // overlapping partitions, failed
|
|
data_units = partition->offset + partition->size;
|
|
}
|
|
if (data_units > header->size)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
u64 GetNcsdTrimmedSize(NcsdHeader* header) {
|
|
u32 data_units = 0;
|
|
for (u32 i = 0; i < 8; i++) {
|
|
NcchPartition* partition = header->partitions + i;
|
|
u32 partition_end = partition->offset + partition->size;
|
|
if (!partition->size) continue;
|
|
data_units = (partition_end > data_units) ? partition_end : data_units;
|
|
}
|
|
|
|
return data_units * NCSD_MEDIA_UNIT;
|
|
}
|
|
|
|
// on the fly decryptor for NCSD
|
|
u32 CryptNcsdSequential(void* data, u32 offset_data, u32 size_data, u16 crypto) {
|
|
// warning: this will only work for sequential processing
|
|
static NcsdHeader ncsd;
|
|
|
|
// fetch ncsd header from data
|
|
if ((offset_data == 0) && (size_data >= sizeof(NcsdHeader)))
|
|
memcpy(&ncsd, data, sizeof(NcsdHeader));
|
|
|
|
for (u32 i = 0; i < 8; i++) {
|
|
NcchPartition* partition = ncsd.partitions + i;
|
|
u32 offset_p = partition->offset * NCSD_MEDIA_UNIT;
|
|
u32 size_p = partition->size * NCSD_MEDIA_UNIT;
|
|
// check if partition in data
|
|
if ((offset_p >= offset_data + size_data) ||
|
|
(offset_data >= offset_p + size_p) ||
|
|
!size_p) {
|
|
continue; // section not in data
|
|
}
|
|
// determine data / offset / size
|
|
u8* data8 = (u8*)data;
|
|
u8* data_i = data8;
|
|
u32 offset_i = 0;
|
|
u32 size_i = size_p;
|
|
if (offset_p < offset_data)
|
|
offset_i = offset_data - offset_p;
|
|
else data_i = data8 + (offset_p - offset_data);
|
|
size_i = size_p - offset_i;
|
|
if (size_i > size_data - (data_i - data8))
|
|
size_i = size_data - (data_i - data8);
|
|
// decrypt ncch segment
|
|
if (CryptNcchSequential(data_i, offset_i, size_i, crypto) != 0)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|