Пример #1
0
bool InitDriveThread::partitionDrive()
{
    /* Partition layout:
     *
     * First 1MB (2048 blocks) kept empty for alignment
     * Followed by FAT partition of RESCUE_PARTITION_SIZE (default 1 GB)
     * Followed by extended partition spanning remainder of space
     */
    QByteArray partitionTable;
    int rescueBlocks = RESCUE_PARTITION_SIZE*1024*2;

    mbr_table extended_mbr;
    int startOfExtended = 2048+rescueBlocks + 5000 * 2048;  // reserve space for WinIoT
    int sizeOfDisk = sizeofSDCardInBlocks();
    int sizeOfExtended = sizeOfDisk - startOfExtended;

    partitionTable = "2048,"+QByteArray::number(rescueBlocks)+",0E\n"; /* FAT partition */
    partitionTable += "0,0\n";
    partitionTable += "0,0\n";
    partitionTable += QByteArray::number(startOfExtended)+","+QByteArray::number(sizeOfExtended)+",X\n"; /* Extended partition with all remaining space */

    /* Write out empty extended partition table with signature */
    memset(&extended_mbr, 0, sizeof extended_mbr);
    extended_mbr.signature[0] = 0x55;
    extended_mbr.signature[1] = 0xAA;
    QFile f("/dev/mmcblk0");
    f.open(f.ReadWrite);
    f.seek(((qint64)startOfExtended)*512L);
    f.write((char *) &extended_mbr, sizeof(extended_mbr));
    f.close();

    /* Write main partition table */
    QString cmd = QString("/sbin/sfdisk -uS /dev/mmcblk0");
    QProcess proc;
    proc.setProcessChannelMode(proc.MergedChannels);
    proc.start(cmd);
    proc.write(partitionTable);
    proc.closeWriteChannel();
    proc.waitForFinished(-1);
    QThread::msleep(500);

    return proc.exitCode() == 0;
}
Пример #2
0
bool InitDriveThread::zeroMbr()
{
    /* First 512 bytes should be enough to zero out the MBR, but we zero out 8 kb to make sure we also erase any
     * GPT primary header and get rid of any partitionless FAT headers.
     * also zero out the last 4 kb of the card to get rid of any secondary GPT header
     *
     * Using conv=fsync to make sure we get notified of write errors
     */
    return QProcess::execute("/bin/dd conv=fsync count=1 bs=8192 if=/dev/zero of="+_drive) == 0
        && QProcess::execute("/bin/dd conv=fsync count=8 bs=512 if=/dev/zero seek="+QString::number(sizeofSDCardInBlocks()-8)+" of="+_drive) == 0;
}
Пример #3
0
bool InitDriveThread::method_resizePartitions()
{
    int newStartOfRescuePartition = getFileContents("/sys/class/block/mmcblk0p1/start").trimmed().toInt();
    int newSizeOfRescuePartition  = sizeofBootFilesInKB()/1000 + 100;

    if (!umountSystemPartition())
    {
        emit error(tr("Error unmounting system partition."));
        return false;
    }

    if (!QFile::exists("/dev/mmcblk0p1"))
    {
        // 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 /dev/mmcblk0 --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("/dev/mmcblk0");
    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 = 8192; /* 4 MiB */
    }

    QString cmd = "/usr/sbin/parted --script /dev/mmcblk0 resize 1 "+QString::number(newStartOfRescuePartition)+"s "+QString::number(newSizeOfRescuePartition)+"M";
    qDebug() << "Executing" << cmd;
    QProcess p;
    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"));

    mbr_table extended_mbr;
    QByteArray partitionTable;
    int startOfOurPartition = getFileContents("/sys/class/block/mmcblk0p1/start").trimmed().toInt();
    int sizeOfOurPartition = getFileContents("/sys/class/block/mmcblk0p1/size").trimmed().toInt();
    int startOfExtended = startOfOurPartition + sizeOfOurPartition;
    // Align on 4 MiB boundary
    startOfExtended += 8192-(startOfExtended % 8192);

// BUGBUG - reserve space for WinIOT
    startOfExtended += 5000 * 2048;    
//

    int sizeOfDisk = sizeofSDCardInBlocks();
    int sizeOfExtended = sizeOfDisk - startOfExtended;

    partitionTable  = QByteArray::number(startOfOurPartition)+","+QByteArray::number(sizeOfOurPartition)+",0E\n"; /* FAT partition */
    partitionTable += "0,0\n";
    partitionTable += "0,0\n";
    partitionTable += QByteArray::number(startOfExtended)+","+QByteArray::number(sizeOfExtended)+",X\n"; /* Extended partition with all remaining space */
    qDebug() << "Writing partition table" << partitionTable;

    /* Write out extended partition table with settings logical partition */
    memset(&extended_mbr, 0, sizeof extended_mbr);
    extended_mbr.part[0].starting_sector = EBR_PARTITION_OFFSET;
    extended_mbr.part[0].nr_of_sectors = SETTINGS_PARTITION_SIZE;
    extended_mbr.part[0].id = 0x83;

    extended_mbr.signature[0] = 0x55;
    extended_mbr.signature[1] = 0xAA;
    f.open(f.ReadWrite);
    f.seek(((qint64)startOfExtended)*512L);
    f.write((char *) &extended_mbr, sizeof(extended_mbr));
    f.flush();
    f.close();

    /* Let sfdisk write a proper partition table */
    cmd = QString("/sbin/sfdisk -uS /dev/mmcblk0");
    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);

    /* For reasons unknown Linux sometimes
     * only finds /dev/mmcblk0p2 and /dev/mmcblk0p1 goes missing */
    if (!QFile::exists("/dev/mmcblk0p1"))
    {
        /* Probe again */
        QProcess::execute("/usr/sbin/partprobe");
        QThread::msleep(1500);
    }

    QProcess::execute("/sbin/mlabel p:RECOVERY");

    emit statusUpdate(tr("Mounting FAT partition"));
    if (!mountSystemPartition())
    {
        emit error(tr("Error mounting system partition."));
        return false;
    }

    return true;
}