GodMode9i/arm9/source/sector0.c

103 lines
2.7 KiB
C

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "utils.h"
#include "sector0.h"
// return 0 for valid NCSD header
int parse_ncsd(const uint8_t sector0[SECTOR_SIZE], int verbose) {
const ncsd_header_t * h = (ncsd_header_t *)sector0;
if (h->magic == 0x4453434e) {
if (verbose) {
//printf("NCSD magic found\n");
}
} else {
if (verbose) {
//printf("NCSD magic not found\n");
}
return -1;
}
if (verbose) {
//iprintf("size: %" PRIu32 " sectors, %s MB\n", h->size, to_mebi(h->size * SECTOR_SIZE));
//iprintf("media ID: %08" PRIx32 "%08" PRIx32 "\n", h->media_id_h, h->media_id_l);
}
for (unsigned i = 0; i < NCSD_PARTITIONS; ++i) {
unsigned fs_type = h->fs_types[i];
if (fs_type == 0) {
break;
}
const char *s_fs_type;
switch (fs_type) {
case 1:
s_fs_type = "Normal";
break;
case 3:
s_fs_type = "FIRM";
break;
case 4:
s_fs_type = "AGB_FIRM save";
break;
default:
if (verbose) {
//iprintf("invalid partition type %d\n", fs_type);
}
return -2;
}
if (verbose) {
// yes I use MB for "MiB", bite me
//iprintf("partition %u, %s, crypt: %" PRIu8 ", offset: 0x%08" PRIx32 ", length: 0x%08" PRIx32 "(%s MB)\n",
//i, s_fs_type, h->crypt_types[i],
//h->partitions[i].offset, h->partitions[i].length, to_mebi(h->partitions[i].length * SECTOR_SIZE));
}
}
return 0;
}
const mbr_partition_t ptable_DSi[MBR_PARTITIONS] = {
{0, {3, 24, 4}, 6, {15, 224, 59}, 0x00000877, 0x00066f89},
{0, {2, 206, 60}, 6, {15, 224, 190}, 0x0006784d, 0x000105b3},
{0, {2, 222, 191}, 1, {15, 224, 191}, 0x00077e5d, 0x000001a3},
{0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0}
};
const mbr_partition_t ptable_3DS[MBR_PARTITIONS] = {
{0, {4, 24, 0}, 6, {1, 160, 63}, 0x00000097, 0x00047da9},
{0, {4, 142, 64}, 6, {1, 160, 195}, 0x0004808d, 0x000105b3},
{0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0},
{0, {0, 0, 0}, 0, {0, 0, 0}, 0, 0}
};
// return 0 for valid MBR
int parse_mbr(const uint8_t sector0[SECTOR_SIZE], int is3DS, int verbose) {
const mbr_t *m = (mbr_t*)sector0;
const mbr_partition_t *ref_ptable; // reference partition table
int ret = 0;
if (m->boot_signature_0 != 0x55 || m->boot_signature_1 != 0xaa) {
//printf("invalid boot signature(0x55, 0xaa)\n");
ret = -1;
}
if (!is3DS) {
for (unsigned i = 0; i < sizeof(m->bootstrap); ++i) {
if (m->bootstrap[i]) {
//printf("bootstrap on DSi should be all zero\n");
ret = 0;
break;
}
}
ref_ptable = ptable_DSi;
} else {
ref_ptable = ptable_3DS;
}
// Only check the first two as those are the only ones we mount
// There's some variation in the 3rd
for(int i = 0; i < 2; i++) {
if (memcmp(&ref_ptable[i], &m->partitions[i], sizeof(mbr_partition_t))) {
//printf("invalid partition table\n");
ret = -2;
}
}
return ret;
}