bool InitDriveThread::formatSettingsPartition() { return QProcess::execute("/usr/sbin/mkfs.ext4 -L SETTINGS "+partdev(_drive, SETTINGS_PARTNR)) == 0; }
bool InitDriveThread::mountSystemPartition() { return QProcess::execute("mount "+partdev(_drive, 1)+" /mnt") == 0 || QProcess::execute("mount "+_drive+" /mnt") == 0; }
BootSelectionDialog::BootSelectionDialog( const QString &drive, //PINN drive where boot partitions are stored for DSI mod const QString &defaultPartition, //Could be provided on cmdline. Only used if no previoous OS had been used. bool stickyBoot, //Use Stickyboot i.e. when NOT going through recovery menu bool dsi, //Adapt config.txt according to fitted monitor QWidget *parent) : QDialog(parent), _countdown(11), _dsi(dsi), ui(new Ui::BootSelectionDialog), _inSelection(false), _drive(drive.toAscii()) { setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint); ui->setupUi(this); QRect s = QApplication::desktop()->screenGeometry(); if (s.height() < 500) resize(s.width()-10, s.height()-100); QDir dir; dir.mkdir("/settings"); if (QProcess::execute("mount -o remount,ro /settings") != 0 && QProcess::execute("mount -t ext4 -o ro "+partdev(drive, SETTINGS_PARTNR)+" /settings") != 0) { QMessageBox::critical(this, tr("Cannot display boot menu"), tr("Error mounting settings partition")); return; } _altered=false; cec->setWindow("bootSelection"); cec->setMenu("any"); connect(cec, SIGNAL(keyPress(int)), this, SLOT(onKeyPress(int))); /* Also mount recovery partition as it may contain icons we need */ if (QProcess::execute("mount -t vfat -o ro "+partdev(drive, 1)+" /mnt") != 0) { /* Not fatal if this fails */ } installed_os = Json::loadFromFile("/settings/installed_os.json").toList(); QSize currentsize = ui->list->iconSize(); QSettings settings("/settings/noobs.conf", QSettings::IniFormat, this); int oldSticky = settings.value("sticky_boot", 800).toInt(); foreach (QVariant v, installed_os) { QVariantMap m = v.toMap(); QString iconfilename = m.value("icon").toString(); QIcon icon; if (!iconfilename.isEmpty() && QFile::exists(iconfilename)) { icon = QIcon(iconfilename); QList<QSize> avs = icon.availableSizes(); if (avs.isEmpty()) { /* Icon file corrupt */ icon = QIcon(); } else { QSize iconsize = avs.first(); if (iconsize.width() > currentsize.width() || iconsize.height() > currentsize.height()) { /* Make all icons as large as the largest icon we have */ currentsize = QSize(qMax(iconsize.width(), currentsize.width()),qMax(iconsize.height(), currentsize.height())); ui->list->setIconSize(currentsize); } } } QString name = CORE(m.value("name").toString()); if (canBootOs(name, m)) { name=NICKNAME(m.value("name").toString()); QListWidgetItem *item = new QListWidgetItem(icon, name+"\n"+m.value("description").toString(), ui->list); item->setData(Qt::UserRole, m); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Unchecked); } }
bool InitDriveThread::method_resizePartitions() { uint newStartOfRescuePartition = getFileContents(sysclassblock(_drive, 1)+"/start").trimmed().toUInt(); uint newSizeOfRescuePartition = sizeofBootFilesInKB()*1.024/1000 + 100; if (!umountSystemPartition()) { emit error(tr("Error unmounting system partition.")); return false; } if (!QFile::exists(partdev(_drive, 1))) { // SD card does not have a MBR. // Warn user that their SD card does not have an MBR and ask // if they would like us to create one for them QMessageBox::StandardButton answer; emit query(tr("Would you like NOOBS to create one for you?\nWARNING: This will erase all data on your SD card"), tr("Error: No MBR present on SD Card"), &answer); if(answer == QMessageBox::Yes) { emit statusUpdate(tr("Zeroing partition table")); if (!zeroMbr()) { emit error(tr("Error zero'ing MBR/GPT. SD card may be broken or advertising wrong capacity.")); return false; } // Create MBR containing single FAT partition emit statusUpdate(tr("Writing new MBR")); QProcess proc; proc.setProcessChannelMode(proc.MergedChannels); proc.start("/usr/sbin/parted "+_drive+" --script -- mktable msdos mkpartfs primary fat32 8192s -1"); proc.waitForFinished(-1); if (proc.exitCode() != 0) { // Warn user if we failed to create an MBR on their card emit error(tr("Error creating MBR")+"\n"+proc.readAll()); return false; } qDebug() << "Created missing MBR on SD card. parted output:" << proc.readAll(); // Advise user that their SD card has now been formatted // suitably for installing NOOBS and that they will have to // re-copy the files before rebooting emit error(tr("SD card has now been formatted ready for NOOBS installation. Please re-copy the NOOBS files onto the card and reboot")); return false; } else { emit error(tr("SD card has not been formatted correctly. Please reformat using the SD Association Formatting Tool and try again.")); return false; } } emit statusUpdate(tr("Removing partitions 2,3,4")); QFile f(_drive); f.open(f.ReadWrite); // Seek to partition entry 2 f.seek(462); // Zero out partition 2,3,4 to prevent parted complaining about invalid constraints f.write(QByteArray(16*3, '\0')); f.flush(); // Tell Linux to re-read the partition table ioctl(f.handle(), BLKRRPART); f.close(); QThread::msleep(500); emit statusUpdate(tr("Resizing FAT partition")); /* Relocating the start of the FAT partition is a write intensive operation * only move it when it is not aligned on a MiB boundary already */ if (newStartOfRescuePartition < 2048 || newStartOfRescuePartition % 2048 != 0) { newStartOfRescuePartition = PARTITION_ALIGNMENT; /* 4 MiB */ } QString cmd = "/usr/sbin/parted --script "+_drive+" resize 1 "+QString::number(newStartOfRescuePartition)+"s "+QString::number(newSizeOfRescuePartition)+"M"; qDebug() << "Executing" << cmd; QProcess p; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); /* Suppress parted's big fat warning about its file system manipulation code not being robust. It distracts from any real error messages that may follow it. */ env.insert("PARTED_SUPPRESS_FILE_SYSTEM_MANIPULATION_WARNING", "1"); p.setProcessEnvironment(env); p.setProcessChannelMode(p.MergedChannels); p.start(cmd); p.closeWriteChannel(); p.waitForFinished(-1); if (p.exitCode() != 0) { emit error(tr("Error resizing existing FAT partition")+"\n"+p.readAll()); return false; } qDebug() << "parted done, output:" << p.readAll(); QThread::msleep(500); emit statusUpdate(tr("Creating extended partition")); QByteArray partitionTable; uint startOfOurPartition = getFileContents(sysclassblock(_drive, 1)+"/start").trimmed().toUInt(); uint sizeOfOurPartition = getFileContents(sysclassblock(_drive, 1)+"/size").trimmed().toUInt(); uint startOfExtended = startOfOurPartition+sizeOfOurPartition; // Align start of settings partition on 4 MiB boundary uint startOfSettings = startOfExtended + PARTITION_GAP; if (startOfSettings % PARTITION_ALIGNMENT != 0) startOfSettings += PARTITION_ALIGNMENT-(startOfSettings % PARTITION_ALIGNMENT); // Primary partitions partitionTable = QByteArray::number(startOfOurPartition)+","+QByteArray::number(sizeOfOurPartition)+",0E\n"; /* FAT partition */ partitionTable += QByteArray::number(startOfExtended)+",,E\n"; /* Extended partition with all remaining space */ partitionTable += "0,0\n"; partitionTable += "0,0\n"; // Logical partitions partitionTable += QByteArray::number(startOfSettings)+","+QByteArray::number(SETTINGS_PARTITION_SIZE)+",L\n"; /* Settings partition */ qDebug() << "Writing partition table" << partitionTable; /* Let sfdisk write a proper partition table */ cmd = QString("/sbin/sfdisk -uS --force "+_drive); QProcess proc; proc.setProcessChannelMode(proc.MergedChannels); proc.start(cmd); proc.write(partitionTable); proc.closeWriteChannel(); proc.waitForFinished(-1); if (proc.exitCode() != 0) { emit error(tr("Error creating extended partition")+"\n"+proc.readAll()); return false; } qDebug() << "sfdisk done, output:" << proc.readAll(); QThread::msleep(500); QProcess::execute("/sbin/mlabel -i "+partdev(_drive, 1)+" ::RECOVERY"); return true; }
bool InitDriveThread::formatBootPartition() { return QProcess::execute("/sbin/mkfs.fat -n RECOVERY "+partdev(_drive, 1)) == 0; }