Esempio n. 1
0
/* On USB root drives we create a dummy recovery and settings partition.
 * Just in case the user wants to start booting from HDD later */
bool InitDriveThread::formatUsbDrive()
{
    zeroMbr();
    partitionDrive();
    setDiskId();
    formatBootPartition();
    formatSettingsPartition();

    return true;
}
Esempio n. 2
0
bool InitDriveThread::method_reformatDrive()
{
    emit statusUpdate(tr("Saving boot files to memory"));
    if (!saveBootFiles() )
    {
        emit error(tr("Error saving boot files to memory. SD card may be damaged."));
        return false;
    }
    if (!umountSystemPartition())
    {
        emit error(tr("Error unmounting system partition."));
        return false;
    }

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

    emit statusUpdate(tr("Creating partitions"));

    if (!partitionDrive())
    {
        emit error(tr("Error partitioning"));
        return false;
    }

    emit statusUpdate(tr("Formatting boot partition (fat)"));
    if (!formatBootPartition())
    {
       emit error(tr("Error formatting boot partition (fat)"));
       return false;
    }

    emit statusUpdate(tr("Copying boot files to storage"));
    mountSystemPartition();
    restoreBootFiles();
    umountSystemPartition();

    return true;
}
Esempio n. 3
0
void DriveFormatThread::run()
{
    if (_reformatBoot)
    {
        emit statusUpdate(tr("Saving boot files to memory"));

        if (!_i->saveBootFiles() )
        {
            emit error(tr("Error saving boot files to memory. Not enough memory to save all files currently on SD card?"));
            return;
        }
        _i->umountSystemPartition();
    }

    emit statusUpdate(tr("Zeroing partition table"));
    if (!zeroMbr())
    {
        emit error(tr("Error zero'ing MBR"));
        return;
    }

    emit statusUpdate(tr("Creating partitions"));

    if (!partitionDrive())
    {
        emit error(tr("Error partitioning"));
        return;
    }

    if (_reformatBoot)
    {
        /* A10 devices need to have u-boot written to the spare space before the first partition */
        if (QFile::exists("/tmp/boot/u-boot.bin") && QFile::exists("/tmp/boot/sunxi-spl.bin"))
        {
            emit statusUpdate(tr("Installing u-boot SPL"));
            if (!installUbootSPL())
            {
                emit error(tr("Error writing u-boot to disk"));
                return;
            }
        }

        emit statusUpdate(tr("Formatting boot partition (fat)"));
        if (!formatBootPartition())
        {
            emit error(tr("Error formatting boot partition (vfat)"));
            return;
        }

        emit statusUpdate(tr("Copying boot files to storage"));
        _i->mountSystemPartition();
        _i->restoreBootFiles();

        emit statusUpdate(tr("Finish writing boot files to disk (sync)"));
        sync();
    }

    emit statusUpdate(tr("Formatting data partition (%1)").arg(_fs));
    if (!formatDataPartition())
    {
        emit error(tr("Error Formatting data partition (%1)").arg(_fs));
        return;
    }

    emit statusUpdate(tr("Mounting and initializing data partition"));
    _i->initializeDataPartition(_datadev);

    emit statusUpdate(tr("Editing cmdline.txt"));

    /* Data dev setting */
    QFile f("/boot/cmdline.txt");
    f.open(QIODevice::ReadWrite);
    QByteArray line = f.readAll().trimmed();
    if (_fs == "btrfs")
        line += " fstype=btrfs";
    if (_iscsi)
        line += " datadev=iscsi";
    else
        line += " datadev="+_datadev;
    f.seek(0);
    f.write(line.trimmed());
    f.close();

    /* Data dev setting in uEnv.txt (for A10 devices) */
    f.setFileName("/boot/uEnv.txt");
    f.open(QIODevice::ReadWrite);
    line = f.readAll().trimmed();
    if (_fs == "btrfs")
        line += " fstype=btrfs";
    if (_iscsi)
        line += " datadev=iscsi";
    else
        line += " datadev="+_datadev;
    f.seek(0);
    f.write(line.trimmed());
    f.close();

    /* Overscan setting */
    bool configchanged = false;
    f.setFileName("/boot/config.txt");
    f.open(QIODevice::ReadOnly);
    QByteArray configdata = f.readAll();
    f.close();
    bool overscanCurrentlyDisabled = configdata.contains("disable_overscan=1");

    if (_i->disableOverscan() && !overscanCurrentlyDisabled)
    {
        configdata += "\ndisable_overscan=1";
        configchanged = true;
    }
    else if (!_i->disableOverscan() && overscanCurrentlyDisabled)
    {
        configdata.replace("disable_overscan=1", "");
        configchanged = true;
    }
    if (configchanged)
    {
        f.open(QIODevice::WriteOnly);
        f.write(configdata.trimmed());
        f.close();
    }

    /* Finished */
    emit statusUpdate(tr("Unmounting boot partition"));
    _i->umountSystemPartition();

    emit statusUpdate(tr("Finish writing to disk (sync)"));
    sync();

    emit completed();
}
Esempio n. 4
0
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::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;
}