mirror of
https://github.com/martravi/wiiqt.git
synced 2024-11-22 09:09:18 +01:00
* nandBin: add format()
* ohneswanzenegger: allow using format on an already existing nand.bin
This commit is contained in:
parent
2ccd125bb3
commit
d0b90a46d9
@ -48,7 +48,14 @@ bool NandBin::SetPath( const QString &path )
|
||||
|
||||
return ret;
|
||||
}
|
||||
#if 0 // apparently you dont need any extra reserved blocks for the thing to boot?
|
||||
const QString NandBin::FilePath()
|
||||
{
|
||||
if( !f.isOpen() )
|
||||
return QString();
|
||||
return QFileInfo( f ).absoluteFilePath();
|
||||
}
|
||||
|
||||
//#if 0 // apparently you dont need any extra reserved blocks for the thing to boot?
|
||||
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||
{
|
||||
#ifndef NAND_BIN_CAN_WRITE
|
||||
@ -73,7 +80,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
}
|
||||
|
||||
f.write( first8 );
|
||||
QByteArray block( 0x4200, 0xff );//generic empty block
|
||||
QByteArray block( 0x4200, 0xff );//generic empty cluster
|
||||
for( quint16 i = 0; i < 0x7fc0; i++ )
|
||||
f.write( block );
|
||||
|
||||
@ -87,7 +94,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
//setup variables
|
||||
nandPath = path;
|
||||
currentSuperCluster = 0x7f00;
|
||||
superClusterVersion = 0xf0000000;
|
||||
superClusterVersion = 1;
|
||||
type = 2;
|
||||
fats.clear();
|
||||
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
||||
@ -100,16 +107,6 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
{
|
||||
fats << 0xfffc;
|
||||
}
|
||||
//find 90 blocks to reserve. they always appear to be close to the end of the nand
|
||||
//TODO - this isnt always 90, all my nands have a different number, and 90 is right in the middle
|
||||
//quint16 bCnt = badBlocks.size();
|
||||
/*quint16 offset = 0;
|
||||
for( quint16 i = 0; i < bCnt; i++ )
|
||||
{
|
||||
if( i >= 3998 )
|
||||
offset++;
|
||||
}*/
|
||||
|
||||
//mark all the "normal" blocks - free, or bad
|
||||
for( quint16 i = 0x40; i < 0x7f00; i++ )
|
||||
{
|
||||
@ -119,7 +116,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
fats << 0xfffe;
|
||||
|
||||
}
|
||||
//mark the 90 reserved ones from above and reserve the superclusters
|
||||
//reserve the superclusters
|
||||
for( quint16 i = 0x7f00; i < 0x8000; i++ )
|
||||
{
|
||||
fats << 0xfffc;
|
||||
@ -156,8 +153,67 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
|
||||
return true;
|
||||
}
|
||||
//#endif
|
||||
|
||||
bool NandBin::Format( bool secure )
|
||||
{
|
||||
#ifndef NAND_BIN_CAN_WRITE
|
||||
qWarning() << __FILE__ << "was built without write support";
|
||||
return false;
|
||||
#endif
|
||||
//#if 0 // this boots ok on real HW
|
||||
if( !f.isOpen() || fats.size() != 0x8000 )
|
||||
{
|
||||
qWarning() << "NandBin::Format -> error" << hex << fats.size() << f.isOpen();
|
||||
return false;
|
||||
}
|
||||
|
||||
//mark any currently used clusters free
|
||||
QByteArray cluster( 0x4200, 0xff );//generic empty cluster
|
||||
for( quint16 i = 0x40; i < 0x7f00; i++ )
|
||||
{
|
||||
if( fats.at( i ) >= 0xf000 && fats.at( i ) != 0xfffe ) //preserve special marked ones
|
||||
continue;
|
||||
|
||||
fats[ i ] = 0xfffe; //free the cluster
|
||||
if( !secure )
|
||||
continue;
|
||||
|
||||
f.seek( 0x4200 * i ); //overwrite anything there with the unused cluster
|
||||
f.write( cluster );
|
||||
}
|
||||
|
||||
//reset fsts
|
||||
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
||||
for( quint16 i = 0; i < 0x17ff; i++ )
|
||||
fsts[ i ].fst_pos = i;
|
||||
|
||||
//make the root item
|
||||
fsts[ 0 ].filename[ 0 ] = '/';
|
||||
fsts[ 0 ].attr = 0x16;
|
||||
fsts[ 0 ].sib = 0xffff;
|
||||
fsts[ 0 ].sub = 0xffff;
|
||||
|
||||
//write the metada to each of the superblocks
|
||||
for( quint8 i = 0; i < 0x10; i++ )
|
||||
{
|
||||
if( !WriteMetaData() )
|
||||
{
|
||||
qWarning() << "NandBin::Format -> error writing superblock" << i;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//build the tree
|
||||
if( root )
|
||||
delete root;
|
||||
root = new QTreeWidgetItem( QStringList() << nandPath );
|
||||
AddChildren( root, 0 );
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#if 0 // this boots ok on real HW. trap15 thinks these reserved blocks are IOS's way of marking ones it thinks are bad
|
||||
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||
{
|
||||
#ifndef NAND_BIN_CAN_WRITE
|
||||
@ -283,7 +339,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
||||
|
||||
return true;
|
||||
}
|
||||
//#endif
|
||||
#endif
|
||||
QTreeWidgetItem *NandBin::GetTree()
|
||||
{
|
||||
//qDebug() << "NandBin::GetTree()";
|
||||
|
@ -134,6 +134,14 @@ public:
|
||||
//expects 0x7f00 - 0x7ff0
|
||||
bool CheckHmacMeta( quint16 clNo );
|
||||
|
||||
//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();
|
||||
|
||||
|
||||
private:
|
||||
QByteArray key;
|
||||
|
@ -266,6 +266,7 @@ void MainWindow::on_pushButton_nandPath_clicked()
|
||||
return;
|
||||
|
||||
ui->lineEdit_nandPath->setText( f );
|
||||
InitNand( ui->lineEdit_nandPath->text() );
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_CachePathBrowse_clicked()
|
||||
@ -451,8 +452,7 @@ bool MainWindow::InitNand( const QString &path )
|
||||
shared = SharedContentMap( ba );
|
||||
if( !shared.Check() )//i really dont want to create a new one and rewrite all the contents to match it
|
||||
ShowMessage( "<b>Something about the shared map isnt right, but im using it anyways</b>" );
|
||||
}
|
||||
//nand.Delete( "/title/00000001/00000002/content/title.tmd" );
|
||||
}
|
||||
|
||||
nandInited = true;
|
||||
ui->menuContent->setEnabled( true );
|
||||
@ -899,3 +899,90 @@ void MainWindow::on_actionWrite_meta_entries_triggered()
|
||||
{
|
||||
AddStuffToMetaFolder();
|
||||
}
|
||||
|
||||
//content -> format
|
||||
void MainWindow::on_actionFormat_triggered()
|
||||
{
|
||||
if( nand.FilePath().isEmpty() )
|
||||
return;
|
||||
if( QMessageBox::warning( this, tr( "Format" ), \
|
||||
tr( "You are about to format<br>%1.<br><br>This cannot be undone. Are you sure you want to do it?" ).arg( nand.FilePath() ),\
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
|
||||
return;
|
||||
|
||||
ShowMessage( "Formatting nand..." );
|
||||
if( !nand.Format() )
|
||||
{
|
||||
ShowMessage( "<b>Error! This nand may be broken now :(</b>" );
|
||||
return;
|
||||
}
|
||||
|
||||
//add folders to root
|
||||
if( !nand.CreateEntry( "/sys", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 )
|
||||
|| !nand.CreateEntry( "/ticket", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 )
|
||||
|| !nand.CreateEntry( "/title", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_READ )
|
||||
|| !nand.CreateEntry( "/shared1", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 )
|
||||
|| !nand.CreateEntry( "/shared2", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW )
|
||||
|| !nand.CreateEntry( "/import", 0, 0, NAND_DIR, NAND_RW, NAND_RW, 0 )
|
||||
|| !nand.CreateEntry( "/meta", 0x1000, 1, NAND_DIR, NAND_RW, NAND_RW, NAND_RW )
|
||||
|| !nand.CreateEntry( "/tmp", 0, 0, NAND_DIR, NAND_RW, NAND_RW, NAND_RW ) )
|
||||
{
|
||||
ShowMessage( "<b>Error! Can't create base folders in the new nand.</b>" );
|
||||
return;
|
||||
}
|
||||
//add cert.sys
|
||||
quint16 handle = nand.CreateEntry( "/sys/cert.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, NAND_READ );
|
||||
if( !handle || !nand.SetData( handle, QByteArray( (const char*)&certs_dat, CERTS_DAT_SIZE ) ) )
|
||||
{
|
||||
ShowMessage( "<b>Error! Can't cert.sys.</b>" );
|
||||
return;
|
||||
}
|
||||
|
||||
//wipe all user-created entries from uid.sys
|
||||
QByteArray uidData = uid.Data();
|
||||
QBuffer buf( &uidData );
|
||||
buf.open( QIODevice::ReadWrite );
|
||||
|
||||
quint64 tid;
|
||||
quint16 titles = 0;
|
||||
quint32 cnt = uidData.size() / 12;
|
||||
for( quint32 i = 0; i < cnt; i++ )
|
||||
{
|
||||
buf.seek( i * 12 );
|
||||
buf.read( (char*)&tid, 8 );
|
||||
tid = qFromBigEndian( tid );
|
||||
quint32 upper = ( ( tid >> 32 ) & 0xffffffff );
|
||||
quint32 lower = ( tid & 0xffffffff );
|
||||
qDebug() << hex << i << QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ) << upper << lower << QChar( ( lower >> 24 ) & 0xff ) << ( lower & 0xffffff00 );
|
||||
if( ( upper == 0x10001 && ( ( lower >> 24 ) & 0xff ) != 0x48 ) || //a channel, not starting with 'H'
|
||||
( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition
|
||||
break;
|
||||
titles++;
|
||||
}
|
||||
buf.close();
|
||||
|
||||
uidData.resize( 12 * titles );
|
||||
hexdump12( uidData );
|
||||
uid = UIDmap( uidData );
|
||||
|
||||
//clear content.map
|
||||
shared = SharedContentMap();
|
||||
if( !nand.CreateEntry( "/sys/uid.sys", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
||||
{
|
||||
ShowMessage( "<b>Error! Can't /sys/uid.sys</b>" );
|
||||
return;
|
||||
}
|
||||
if( !nand.CreateEntry( "/shared1/content.map", 0, 0, NAND_FILE, NAND_RW, NAND_RW, 0 ) )
|
||||
{
|
||||
ShowMessage( "<b>Error! Can't /shared1/content.map</b>" );
|
||||
return;
|
||||
}
|
||||
|
||||
//commit
|
||||
if( !nand.WriteMetaData() || !UpdateTree() )
|
||||
{
|
||||
ShowMessage( "<b>Error finalizing formatting!</b>" );
|
||||
return;
|
||||
}
|
||||
ShowMessage( "Done!" );
|
||||
}
|
||||
|
@ -62,7 +62,8 @@ public slots:
|
||||
void ReceiveTitleFromNus( NusJob job );
|
||||
|
||||
private slots:
|
||||
void on_actionWrite_meta_entries_triggered();
|
||||
void on_actionFormat_triggered();
|
||||
void on_actionWrite_meta_entries_triggered();
|
||||
void on_pushButton_CachePathBrowse_clicked();
|
||||
void on_actionAbout_triggered();
|
||||
void on_pushButton_initNand_clicked();
|
||||
|
@ -198,6 +198,7 @@
|
||||
<addaction name="actionFlush"/>
|
||||
<addaction name="actionSetting_txt"/>
|
||||
<addaction name="actionWrite_meta_entries"/>
|
||||
<addaction name="actionFormat"/>
|
||||
</widget>
|
||||
<addaction name="menuNand_Dump"/>
|
||||
<addaction name="menuContent"/>
|
||||
@ -248,6 +249,11 @@
|
||||
<string>Write meta entries</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFormat">
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
@ -353,7 +353,7 @@ QByteArray NewNandBin::GetCleanUid( QByteArray old )
|
||||
quint32 lower = ( tid & 0xffffffff );
|
||||
//qDebug() << QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ) << hex << upper << lower << ( ( lower >> 24 ) & 0xff ) << ( lower & 0xffff00 );
|
||||
if( ( upper == 0x10001 && ( ( lower >> 24 ) & 0xff ) != 0x48 ) || //a channel, not starting with 'H'
|
||||
( upper == 0x10000 && ( ( lower & 0xffff00 ) == 0x555000 ) ) ) //a disc update partition
|
||||
( upper == 0x10000 && ( ( lower & 0xffffff00 ) == 0x555000 ) ) ) //a disc update partition
|
||||
break;
|
||||
|
||||
titles++;
|
||||
|
Loading…
Reference in New Issue
Block a user