2010-12-08 08:26:18 +01:00
|
|
|
#ifndef NANDBIN_H
|
|
|
|
#define NANDBIN_H
|
|
|
|
|
|
|
|
#include "includes.h"
|
2010-12-14 06:58:44 +01:00
|
|
|
#include "blocks0to7.h"
|
2010-12-15 09:11:56 +01:00
|
|
|
#include "nandspare.h"
|
2010-12-19 23:24:54 +01:00
|
|
|
|
2010-12-08 08:26:18 +01:00
|
|
|
struct fst_t
|
|
|
|
{
|
2010-12-10 04:50:08 +01:00
|
|
|
quint8 filename[ 0xc ];
|
2010-12-08 08:26:18 +01:00
|
|
|
quint8 attr;
|
2010-12-17 00:37:30 +01:00
|
|
|
quint8 wtf;
|
2010-12-08 08:26:18 +01:00
|
|
|
quint16 sub;
|
|
|
|
quint16 sib;
|
|
|
|
quint32 size;
|
|
|
|
quint32 uid;
|
|
|
|
quint16 gid;
|
|
|
|
quint32 x3;
|
2010-12-15 09:11:56 +01:00
|
|
|
quint16 fst_pos;//not really part of the nand structure, but needed when calculating hmac data
|
2010-12-08 08:26:18 +01:00
|
|
|
};
|
|
|
|
// class to deal with an encrypted wii nand dump
|
|
|
|
// basic usage... create an object, set a path, call InitNand. then you can get the detailed list of entries with GetTree()
|
|
|
|
// extract files with GetFile()
|
2010-12-21 21:01:39 +01:00
|
|
|
//! so far, all functions for writing to the nand are highly untested. it is not recommended to try to use this code productively!!
|
|
|
|
//! you should verify anything written with this code before attempting to install it on you wii
|
2010-12-10 04:50:08 +01:00
|
|
|
|
|
|
|
//once InitNand() is called, you can get the contents of the nand in a nice QTreeWidgetItem* with GetTree()
|
2010-12-08 08:26:18 +01:00
|
|
|
class NandBin : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
2010-12-10 04:50:08 +01:00
|
|
|
//creates a NandBin object. if a path is given, it will call SetPath() on that path. though you cant check the return value
|
2010-12-08 08:26:18 +01:00
|
|
|
NandBin( QObject * parent = 0, const QString &path = QString() );
|
2010-12-10 04:50:08 +01:00
|
|
|
|
|
|
|
//destroys this object, and all its used resources ( closes the nand.bin file and deletes the filetree )
|
2010-12-08 08:26:18 +01:00
|
|
|
~NandBin();
|
2010-12-10 04:50:08 +01:00
|
|
|
|
2010-12-19 23:24:54 +01:00
|
|
|
//create a "blank" nand at the given path, with spare data and keeys.bin appended to the end
|
|
|
|
//keys should be a 0x400 byte array containing a keys.bin from bootmii
|
|
|
|
//first8 should be a bytearray containing 0x108000 bytes - the first 8 blocks of the nand with spare data
|
|
|
|
//badBlocks is a list of blocks to be marked bad, in the range 8 - 4079
|
2010-12-23 17:17:46 +01:00
|
|
|
bool CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks = QList<quint16>() );
|
2010-12-19 23:24:54 +01:00
|
|
|
|
2010-12-10 04:50:08 +01:00
|
|
|
//sets the path of this object to path. returns false if it cannot open an already existing file
|
|
|
|
//keys.bin should be in this same path if they are to be used
|
2010-12-08 08:26:18 +01:00
|
|
|
bool SetPath( const QString &path );
|
2010-12-08 09:05:23 +01:00
|
|
|
|
|
|
|
//try to read the filesystem and create a tree from its contents
|
2010-12-10 04:50:08 +01:00
|
|
|
//this takes care of the stuff like reading the keys, finding teh superblock, and creating the QTreeWidgetItem* tree
|
2010-12-08 09:05:23 +01:00
|
|
|
//icons given here will be the ones used when asking for that tree
|
2010-12-23 17:17:46 +01:00
|
|
|
bool InitNand( const QIcon &dirs = QIcon(), const QIcon &files = QIcon() );
|
2010-12-08 08:26:18 +01:00
|
|
|
|
|
|
|
//get a root item containing children that are actually entries in the nand dump
|
|
|
|
//the root itself is just a container to hold them all and can be deleted once its children are taken
|
2010-12-10 04:50:08 +01:00
|
|
|
//! all returned items are cloned and it is up to you to delete them !
|
|
|
|
//text is assigned to the items as follows...
|
|
|
|
// 0 name
|
|
|
|
// 1 entry #
|
|
|
|
// 2 size
|
|
|
|
// 3 uid
|
|
|
|
// 4 gid
|
|
|
|
// 5 x3
|
|
|
|
// 6 mode
|
|
|
|
// 7 attr
|
2010-12-08 08:26:18 +01:00
|
|
|
QTreeWidgetItem *GetTree();
|
|
|
|
|
|
|
|
//extracts an item( and all its children ) to a directory
|
|
|
|
//this function is BLOCKING and will block the current thread, so if done in the gui thread, it will freeze your GUI till it returns
|
|
|
|
bool ExtractToDir( QTreeWidgetItem *item, const QString &path );
|
|
|
|
|
|
|
|
//print a little info about the free space
|
|
|
|
void ShowInfo();
|
|
|
|
|
|
|
|
//set this to change ":" in names to "-" on etracting.
|
|
|
|
//theres more illegal characters in FAT, but thes seems to be the only one that happens on the nand FS
|
|
|
|
void SetFixNamesForFAT( bool fix = true );
|
|
|
|
|
2010-12-10 04:50:08 +01:00
|
|
|
//returns the data that makes up the file of a given entry#
|
2010-12-23 17:17:46 +01:00
|
|
|
const QByteArray GetFile( quint16 entry );
|
2010-12-10 04:50:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
//get data for a given path
|
|
|
|
//! this function is slower than the above one, as it first iterates through the QTreeWidgetItems till it finds the right ono
|
|
|
|
//! and then end up calling the above one anyways.
|
|
|
|
//the path should be a file, not folder
|
|
|
|
//returns an empty array on failure
|
|
|
|
//path should start with "/" and items should be delimited by "/"
|
|
|
|
//ie... /title/00000001/00000002/data/setting.txt
|
|
|
|
const QByteArray GetData( const QString &path );
|
|
|
|
|
2010-12-11 11:12:50 +01:00
|
|
|
//returns the fats for this nand.
|
|
|
|
const QList<quint16> GetFats() { return fats; }
|
|
|
|
|
|
|
|
//get the fats for a given file
|
|
|
|
const QList<quint16> GetFatsForFile( quint16 i );
|
|
|
|
|
2010-12-17 00:37:30 +01:00
|
|
|
//recurse folders and files and get all fats used for them
|
|
|
|
//! this is probably a more expensive function than you want to use
|
|
|
|
//! it was added only to aid in checking for bugs and lost clusters
|
|
|
|
const QList<quint16> GetFatsForEntry( quint16 i );
|
|
|
|
|
|
|
|
//use the above function to search and display lost clusters
|
|
|
|
void ShowLostClusters();
|
|
|
|
|
2010-12-14 06:58:44 +01:00
|
|
|
const Blocks0to7 BootBlocks(){ return bootBlocks; }
|
|
|
|
const QList<Boot2Info> Boot2Infos();
|
|
|
|
quint8 Boot1Version();
|
|
|
|
|
2010-12-23 17:17:46 +01:00
|
|
|
const QByteArray GetPage( quint32 pageNo, bool withEcc = false );
|
2010-12-15 09:11:56 +01:00
|
|
|
|
2010-12-17 00:37:30 +01:00
|
|
|
//create new entry
|
|
|
|
//returns the index of the entry on success, or 0 on error
|
|
|
|
quint16 CreateEntry( const QString &path, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm );
|
|
|
|
|
|
|
|
//delete a file/folder
|
|
|
|
bool Delete( const QString &path );
|
|
|
|
|
|
|
|
//sets the data for a given file ( overwrites existing data )
|
2010-12-23 17:17:46 +01:00
|
|
|
bool SetData( quint16 idx, const QByteArray &data );
|
2010-12-17 00:37:30 +01:00
|
|
|
|
|
|
|
//overloads the above function
|
2010-12-23 17:17:46 +01:00
|
|
|
bool SetData( const QString &path, const QByteArray &data );
|
2010-12-17 00:37:30 +01:00
|
|
|
|
2010-12-18 22:07:58 +01:00
|
|
|
//write the current changes to the metadata( if you dont do this, then none of the other stuff youve done wont be saved )
|
2010-12-21 21:01:39 +01:00
|
|
|
// but at the same time, you probably dont need to overuse this. ( no need to write metadata every time you make a single change )
|
2010-12-18 22:07:58 +01:00
|
|
|
bool WriteMetaData();
|
|
|
|
|
|
|
|
//functions to verify spare data
|
|
|
|
bool CheckEcc( quint32 pageNo );
|
|
|
|
bool CheckHmacData( quint16 entry );
|
|
|
|
|
|
|
|
//verify hmac stuff for a given supercluster
|
|
|
|
//expects 0x7f00 - 0x7ff0
|
|
|
|
bool CheckHmacMeta( quint16 clNo );
|
|
|
|
|
2011-01-18 20:30:36 +01:00
|
|
|
//wipe out all data within the nand FS, leaving only the root entry
|
|
|
|
//preserve all bad/reserved clusters
|
|
|
|
//if secure is true, overwrite old file data with 0xff
|
|
|
|
bool Format( bool secure = true );
|
|
|
|
|
|
|
|
//get the path of this nand
|
|
|
|
const QString FilePath();
|
|
|
|
|
2010-12-10 04:50:08 +01:00
|
|
|
|
2010-12-08 08:26:18 +01:00
|
|
|
private:
|
|
|
|
QByteArray key;
|
|
|
|
qint32 loc_super;
|
|
|
|
qint32 loc_fat;
|
|
|
|
qint32 loc_fst;
|
2010-12-18 22:07:58 +01:00
|
|
|
quint16 currentSuperCluster;
|
|
|
|
quint32 superClusterVersion;
|
2010-12-08 08:26:18 +01:00
|
|
|
QString extractPath;
|
2010-12-10 04:50:08 +01:00
|
|
|
QString nandPath;
|
2010-12-08 08:26:18 +01:00
|
|
|
QFile f;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
bool fatNames;
|
2010-12-08 09:05:23 +01:00
|
|
|
QIcon groupIcon;
|
|
|
|
QIcon keyIcon;
|
2010-12-08 08:26:18 +01:00
|
|
|
|
2010-12-15 09:11:56 +01:00
|
|
|
NandSpare spare;//used to handle the hmac mumbojumbo
|
|
|
|
|
2010-12-11 11:12:50 +01:00
|
|
|
//read all the fst and remember them rather than seeking back and forth in the file all the time
|
|
|
|
// uses ~120KiB RAM
|
|
|
|
bool fstInited;
|
|
|
|
fst_t fsts[ 0x17ff ];
|
|
|
|
|
|
|
|
//cache the fat to keep from having to look them up repeatedly
|
|
|
|
// uses ~64KiB
|
|
|
|
QList<quint16>fats;
|
|
|
|
|
2010-12-08 08:26:18 +01:00
|
|
|
int GetDumpType( quint64 fileSize );
|
|
|
|
bool GetKey( int type );
|
2010-12-23 17:17:46 +01:00
|
|
|
const QByteArray ReadKeyfile( const QString &path, quint8 type );//type 0 for nand key, type 1 for hmac
|
2010-12-08 08:26:18 +01:00
|
|
|
qint32 FindSuperblock();
|
|
|
|
quint16 GetFAT( quint16 fat_entry );
|
|
|
|
fst_t GetFST( quint16 entry );
|
2010-12-23 17:17:46 +01:00
|
|
|
const QByteArray GetCluster( quint16 cluster_entry, bool decrypt = true );
|
|
|
|
const QByteArray GetFile( fst_t fst );
|
2010-12-08 08:26:18 +01:00
|
|
|
|
2010-12-23 17:17:46 +01:00
|
|
|
const QString FstName( fst_t fst );
|
2010-12-08 09:05:23 +01:00
|
|
|
bool ExtractFST( quint16 entry, const QString &path, bool singleFile = false );
|
2010-12-23 17:17:46 +01:00
|
|
|
bool ExtractDir( fst_t fst, const QString &parent );
|
|
|
|
bool ExtractFile( fst_t fst, const QString &parent );
|
2010-12-08 08:26:18 +01:00
|
|
|
|
2010-12-17 00:37:30 +01:00
|
|
|
QTreeWidgetItem *CreateItem( QTreeWidgetItem *parent, const QString &name, quint32 size, quint16 entry, quint32 uid, quint32 gid, quint32 x3, quint8 attr, quint8 wtf);
|
|
|
|
|
2010-12-08 08:26:18 +01:00
|
|
|
|
|
|
|
|
|
|
|
QTreeWidgetItem *root;
|
|
|
|
bool AddChildren( QTreeWidgetItem *parent, quint16 entry );
|
2010-12-10 04:50:08 +01:00
|
|
|
QTreeWidgetItem *ItemFromPath( const QString &path );
|
|
|
|
QTreeWidgetItem *FindItem( const QString &s, QTreeWidgetItem *parent );
|
2010-12-08 08:26:18 +01:00
|
|
|
|
2010-12-14 06:58:44 +01:00
|
|
|
//holds info about boot1 & 2
|
|
|
|
Blocks0to7 bootBlocks;
|
|
|
|
|
2010-12-23 17:17:46 +01:00
|
|
|
bool WriteCluster( quint32 pageNo, const QByteArray &data, const QByteArray &hmac );
|
|
|
|
bool WriteDecryptedCluster( quint32 pageNo, const QByteArray &data, fst_t fst, quint16 idx );
|
|
|
|
bool WritePage( quint32 pageNo, const QByteArray &data );
|
2010-12-15 09:11:56 +01:00
|
|
|
|
2010-12-17 00:37:30 +01:00
|
|
|
quint16 CreateNode( const QString &name, quint32 uid, quint16 gid, quint8 attr, quint8 user_perm, quint8 group_perm, quint8 other_perm );
|
|
|
|
|
|
|
|
bool DeleteItem( QTreeWidgetItem *item );
|
|
|
|
//find a parent entry for a path to be created - "/title/00000001" should give the entry for "/title"
|
|
|
|
QTreeWidgetItem *GetParent( const QString &path );
|
|
|
|
|
|
|
|
QTreeWidgetItem *ItemFromEntry( quint16 i, QTreeWidgetItem *parent = NULL );
|
|
|
|
QTreeWidgetItem *ItemFromEntry( const QString &i, QTreeWidgetItem *parent = NULL );
|
|
|
|
|
2010-12-08 08:26:18 +01:00
|
|
|
signals:
|
2010-12-10 04:50:08 +01:00
|
|
|
//connect to these to receive messages from this object
|
2010-12-21 21:01:39 +01:00
|
|
|
//so far, many errors are only outputting to qDebug() and qWarning().
|
2010-12-08 08:26:18 +01:00
|
|
|
void SendError( QString );
|
|
|
|
void SendText( QString );
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // NANDBIN_H
|