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;
|
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 )
|
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||||
{
|
{
|
||||||
#ifndef NAND_BIN_CAN_WRITE
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
@ -73,7 +80,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.write( first8 );
|
f.write( first8 );
|
||||||
QByteArray block( 0x4200, 0xff );//generic empty block
|
QByteArray block( 0x4200, 0xff );//generic empty cluster
|
||||||
for( quint16 i = 0; i < 0x7fc0; i++ )
|
for( quint16 i = 0; i < 0x7fc0; i++ )
|
||||||
f.write( block );
|
f.write( block );
|
||||||
|
|
||||||
@ -87,7 +94,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
//setup variables
|
//setup variables
|
||||||
nandPath = path;
|
nandPath = path;
|
||||||
currentSuperCluster = 0x7f00;
|
currentSuperCluster = 0x7f00;
|
||||||
superClusterVersion = 0xf0000000;
|
superClusterVersion = 1;
|
||||||
type = 2;
|
type = 2;
|
||||||
fats.clear();
|
fats.clear();
|
||||||
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
memset( &fsts, 0, sizeof( fst_t ) * 0x17ff );
|
||||||
@ -100,16 +107,6 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
{
|
{
|
||||||
fats << 0xfffc;
|
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
|
//mark all the "normal" blocks - free, or bad
|
||||||
for( quint16 i = 0x40; i < 0x7f00; i++ )
|
for( quint16 i = 0x40; i < 0x7f00; i++ )
|
||||||
{
|
{
|
||||||
@ -119,7 +116,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
fats << 0xfffe;
|
fats << 0xfffe;
|
||||||
|
|
||||||
}
|
}
|
||||||
//mark the 90 reserved ones from above and reserve the superclusters
|
//reserve the superclusters
|
||||||
for( quint16 i = 0x7f00; i < 0x8000; i++ )
|
for( quint16 i = 0x7f00; i < 0x8000; i++ )
|
||||||
{
|
{
|
||||||
fats << 0xfffc;
|
fats << 0xfffc;
|
||||||
@ -156,8 +153,67 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
bool NandBin::Format( bool secure )
|
||||||
|
{
|
||||||
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
|
qWarning() << __FILE__ << "was built without write support";
|
||||||
|
return false;
|
||||||
#endif
|
#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 )
|
bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByteArray &first8, const QList<quint16> &badBlocks )
|
||||||
{
|
{
|
||||||
#ifndef NAND_BIN_CAN_WRITE
|
#ifndef NAND_BIN_CAN_WRITE
|
||||||
@ -283,7 +339,7 @@ bool NandBin::CreateNew( const QString &path, const QByteArray &keys, const QByt
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//#endif
|
#endif
|
||||||
QTreeWidgetItem *NandBin::GetTree()
|
QTreeWidgetItem *NandBin::GetTree()
|
||||||
{
|
{
|
||||||
//qDebug() << "NandBin::GetTree()";
|
//qDebug() << "NandBin::GetTree()";
|
||||||
|
@ -134,6 +134,14 @@ public:
|
|||||||
//expects 0x7f00 - 0x7ff0
|
//expects 0x7f00 - 0x7ff0
|
||||||
bool CheckHmacMeta( quint16 clNo );
|
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:
|
private:
|
||||||
QByteArray key;
|
QByteArray key;
|
||||||
|
@ -266,6 +266,7 @@ void MainWindow::on_pushButton_nandPath_clicked()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ui->lineEdit_nandPath->setText( f );
|
ui->lineEdit_nandPath->setText( f );
|
||||||
|
InitNand( ui->lineEdit_nandPath->text() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_pushButton_CachePathBrowse_clicked()
|
void MainWindow::on_pushButton_CachePathBrowse_clicked()
|
||||||
@ -451,8 +452,7 @@ bool MainWindow::InitNand( const QString &path )
|
|||||||
shared = SharedContentMap( ba );
|
shared = SharedContentMap( ba );
|
||||||
if( !shared.Check() )//i really dont want to create a new one and rewrite all the contents to match it
|
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>" );
|
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;
|
nandInited = true;
|
||||||
ui->menuContent->setEnabled( true );
|
ui->menuContent->setEnabled( true );
|
||||||
@ -899,3 +899,90 @@ void MainWindow::on_actionWrite_meta_entries_triggered()
|
|||||||
{
|
{
|
||||||
AddStuffToMetaFolder();
|
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 );
|
void ReceiveTitleFromNus( NusJob job );
|
||||||
|
|
||||||
private slots:
|
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_pushButton_CachePathBrowse_clicked();
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
void on_pushButton_initNand_clicked();
|
void on_pushButton_initNand_clicked();
|
||||||
|
@ -198,6 +198,7 @@
|
|||||||
<addaction name="actionFlush"/>
|
<addaction name="actionFlush"/>
|
||||||
<addaction name="actionSetting_txt"/>
|
<addaction name="actionSetting_txt"/>
|
||||||
<addaction name="actionWrite_meta_entries"/>
|
<addaction name="actionWrite_meta_entries"/>
|
||||||
|
<addaction name="actionFormat"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuNand_Dump"/>
|
<addaction name="menuNand_Dump"/>
|
||||||
<addaction name="menuContent"/>
|
<addaction name="menuContent"/>
|
||||||
@ -248,6 +249,11 @@
|
|||||||
<string>Write meta entries</string>
|
<string>Write meta entries</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionFormat">
|
||||||
|
<property name="text">
|
||||||
|
<string>Format</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -353,7 +353,7 @@ QByteArray NewNandBin::GetCleanUid( QByteArray old )
|
|||||||
quint32 lower = ( tid & 0xffffffff );
|
quint32 lower = ( tid & 0xffffffff );
|
||||||
//qDebug() << QString( "%1" ).arg( tid, 16, 16, QChar( '0' ) ) << hex << upper << lower << ( ( lower >> 24 ) & 0xff ) << ( lower & 0xffff00 );
|
//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'
|
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;
|
break;
|
||||||
|
|
||||||
titles++;
|
titles++;
|
||||||
|
Loading…
Reference in New Issue
Block a user