* nandBin: add format()

* ohneswanzenegger: allow using format on an already existing nand.bin
This commit is contained in:
giantpune@gmail.com 2011-01-18 19:30:36 +00:00
parent 2ccd125bb3
commit d0b90a46d9
6 changed files with 178 additions and 20 deletions

View File

@ -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()";

View File

@ -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;

View File

@ -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!" );
}

View File

@ -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();

View File

@ -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/>

View File

@ -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++;