📄 image.c
字号:
/* * Copyright (C) 2008 dhewg, #wiidev efnet * based on code by: * Copyright (C) 2006 Mike Melanson (mike at multimedia.cx) * * some functions are taken from * http://git.infradead.org/?p=users/segher/wii.git * Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org> * 21:14:49 <@segher> i'll happily grant you to license the whole as v3, btw * * this file is part of wiifuse * http://wiibrew.org/index.php?title=Wiifuse * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include "global.h"#include "io.h"#include "tree.h"#include "metadata.h"#include "image.h"u8 image_parse_header (struct part_header *header, u8 *buffer) { memset (header, 0, sizeof (struct part_header)); header->console = buffer[0]; header->is_gc = (header->console == 'G') || (header->console == 'D') || (header->console == 'P') || (header->console == 'U'); header->is_wii = (header->console == 'R') || (header->console == '_') || (header->console == 'H') || (header->console == '0') || (header->console == '4'); header->gamecode[0] = buffer[1]; header->gamecode[1] = buffer[2]; header->region = buffer[3]; header->publisher[0] = buffer[4]; header->publisher[1] = buffer[5]; header->has_magic = get_be32 (&buffer[0x18]) == 0x5d1c9ea3; strncpy (header->name, (char *) (&buffer[0x20]), 0x60); header->dol_offset = get_be32 (&buffer[0x420]); header->fst_offset = get_be32 (&buffer[0x424]); header->fst_size = get_be32 (&buffer[0x428]); if (header->is_wii) { header->dol_offset *= 4llu; header->fst_offset *= 4llu; header->fst_size *= 4llu; } return header->is_gc || header->is_wii;}u32 parse_fst (u8 *fst, const char *names, u32 i, struct tree *tree, struct image_file *image, u32 part) { u64 offset; u32 size; const char *name; u32 j; struct tree *node; name = names + (get_be32 (fst + 12 * i) & 0x00ffffff); size = get_be32 (fst + 12 * i + 8); if (i == 0) { for (j = 1; j < size; ) j = parse_fst (fst, names, j, tree, image, part); return size; } if (fst[12 * i]) { LOG (3, " fst dir: %s", name); node = tree_add_dir (part, tree, name); for (j = i + 1; j < size; ) j = parse_fst (fst, names, j, node, image, part); return size; } else { offset = get_be32(fst + 12 * i + 4); if (image->parts[part].header.is_wii) offset *= 4llu; LOG (3, " fst file: %s offset: 0x%016llx size: 0x%08x", name, offset, size); tree_add_file (part, tree, name, offset, size); image->nfiles++; image->nbytes += size; return i + 1; }}u8 get_partitions (struct image_file *image) { u8 buffer[16]; u64 part_tbl_offset; u64 chan_tbl_offset; u32 i; u8 title_key[16]; u8 iv[16]; u8 partition_key[16]; u32 nchans; io_read (buffer, 16, image, 0x40000); image->nparts = 1 + get_be32 (buffer); nchans = get_be32 (&buffer[8]); LOG (1, "number of partitions: %u", image->nparts); LOG (1, "number of channels: %u", nchans); image->nparts += nchans; if (image->nparts == 1) return 0; part_tbl_offset = get_be32 (&buffer[4]) * 4ull; chan_tbl_offset = get_be32 (&buffer[12]) * 4ull; LOG (1, "partition table offset: 0x%016llx", part_tbl_offset); LOG (1, "channel table offset: 0x%016llx", chan_tbl_offset); image->parts = (struct partition *) malloc (image->nparts * sizeof (struct partition)); memset (image->parts, 0, image->nparts * sizeof (struct partition)); for (i = 1; i < image->nparts; ++i) { LOG (1, "found partition: %u", i); if (i < image->nparts - nchans) { io_read (buffer, 8, image, part_tbl_offset + (i - 1) * 8); switch (get_be32 (&buffer[4])) { case 0: image->parts[i].type = PART_DATA; break; case 1: image->parts[i].type = PART_UPDATE; break; case 2: image->parts[i].type = PART_INSTALLER; break; default: break; } } else { io_read (buffer, 8, image, chan_tbl_offset + (i - 3) * 8); image->parts[i].type = PART_VC; image->parts[i].chan_id[0] = buffer[4]; image->parts[i].chan_id[1] = buffer[5]; image->parts[i].chan_id[2] = buffer[6]; image->parts[i].chan_id[3] = buffer[7]; } image->parts[i].offset = get_be32 (buffer) * 4ull; LOG (1, "partition offset: 0x%016llx", image->parts[i].offset); tmd_load (image, i); if (image->parts[i].tmd == NULL) { LOG_ERR ("partition %u has no valid tmd", i); continue; } sprintf (image->parts[i].title_id_str, "%016llx", image->parts[i].tmd->title_id); image->parts[i].is_encrypted = 1; image->parts[i].cached_block = 0xffffffff; memset (title_key, 0, 16); memset (iv, 0, 16); io_read (title_key, 16, image, image->parts[i].offset + 0x1bf); io_read (iv, 8, image, image->parts[i].offset + 0x1dc); AES_cbc_encrypt (title_key, partition_key, 16, &image->key, iv, 0); AES_set_decrypt_key (partition_key, 128, &image->parts[i].key); sprintf (image->parts[i].key_c, "0x" "%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x", partition_key[0], partition_key[1], partition_key[2], partition_key[3], partition_key[4], partition_key[5], partition_key[6], partition_key[7], partition_key[8], partition_key[9], partition_key[10], partition_key[11], partition_key[12], partition_key[13], partition_key[14], partition_key[15]); io_read (buffer, 8, image, image->parts[i].offset + 0x2b8); image->parts[i].data_offset = get_be32 (buffer) * 4ull; image->parts[i].data_size = get_be32 (&buffer[4]) * 4ull; LOG (1, "partition data offset: 0x%016llx", image->parts[i].data_offset); LOG (1, "partition data size: 0x%016llx", image->parts[i].data_size); } return image->nparts == 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -