Ejemplo n.º 1
0
void MainWindow::install()
{
    ui->statusLabel->setFont(getFont(ui->statusLabel, FONT_STATUSLABEL_RATIO));
    ui->statusProgressBar->setFont(getFont(ui->statusProgressBar, FONT_PROGRESSBAR_RATIO));

    qApp->processEvents();
    /* Find out what device we are running on */
    logger->addLine("Detecting device we are running on");
    device = targetList->getTarget(utils->getOSMCDev());
    if (device == NULL)
    {
        haltInstall("unsupported device"); /* No tr here as not got lang yet */
        return;
    }
    /* Mount the BOOT filesystem */
    logger->addLine("Mounting boot filesystem");
    bool hasMount = false;
    hasMount = utils->mountPartition(device, MNT_BOOT);
    if (! hasMount && utils->getOSMCDev() == "atv")
    {
        /* Super hacky for Apple TV 1st gen. Sometimes no internal disk */
        hasMount = utils->mountPartition(device, "/dev/sda1");
        device->setRoot("/dev/sda2");
    }
    if (! hasMount)
    {
        haltInstall("could not mount bootfs");
        return;
    }
    /* Sanity check: need filesystem.tar.xz */
    QFile fileSystem(QString(MNT_BOOT) + "/filesystem.tar.xz");
    if (! fileSystem.exists())
    {
        haltInstall("no filesystem found");
        return;
    }
    /* Load in preseeded values */
    preseed = new PreseedParser();
    if (preseed->isLoaded())
    {
        logger->addLine("Preseed file found, will attempt to parse");
        /* Locales */
        locale = preseed->getStringValue("globe/locale");
        if (! locale.isEmpty())
        {
            logger->addLine("Found a definition for globalisation: " + locale);
            QTranslator translator;
            if (translator.load(qApp->applicationDirPath() + "/osmc_" + locale + ".qm"))
            {
                logger->addLine("Translation loaded successfully!");
                qApp->installTranslator(&translator);
                ui->retranslateUi(this);
            }
            else
                logger->addLine("Could not load translation");
        }
        /* Install target */
        installTarget = preseed->getStringValue("target/storage");
        if (! installTarget.isEmpty())
        {
            logger->addLine("Found a definition for storage: " + installTarget);
            if (installTarget == "nfs")
            {
                QString nfsPath = preseed->getStringValue("target/storagePath");
                if (! nfsPath.isEmpty())
                {
                    device->setRoot(nfsPath);
                    useNFS = true;
                }
            }
            if (installTarget == "usb")
            {
                /* Behaviour for handling USB installs */
                if (utils->getOSMCDev() == "rbp1") { device->setRoot("/dev/sda1"); }
                if (utils->getOSMCDev() == "rbp2") { device->setRoot("/dev/sda1"); }
                if (utils->getOSMCDev() == "vero1") { device->setRoot("/dev/sda1"); }
                for (int i = 0; i <= 60; i++)
                {
                    ui->statusLabel->setText(tr("USB install:") + " " + QString::number(60 - i) + " " + ("seconds to remove device before data loss"));
                    qApp->processEvents();
                    system("/bin/sleep 1");
                }
            }
        }
        /* Bring up network if using NFS */
        if (useNFS)
        {
            logger->addLine("NFS installation chosen, must bring up network");
            nw = new Network();
            nw->setIP(preseed->getStringValue("network/ip"));
            nw->setMask(preseed->getStringValue("network/mask"));
            nw->setGW(preseed->getStringValue("network/gw"));
            nw->setDNS1(preseed->getStringValue("network/dns1"));
            nw->setDNS2(preseed->getStringValue("network/dns2"));
            if (! nw->isDefined())
            {
                logger->addLine("Either network preseed definition incomplete, or user wants DHCP");
                nw->setAuto();
            }
            logger->addLine("Attempting to bring up eth0");
            ui->statusLabel->setText(tr("Configuring Network"));
            nw->bringUp();
        }
    }
    else
    {
        logger->addLine("No preseed file was found");
    }
    /* If !nfs, create necessary partitions */
    if (! useNFS)
    {
        logger->addLine("Creating root partition");
        ui->statusLabel->setText(tr("Formatting device"));
        qApp->processEvents(); /* Force GUI update */
        QString rootBase = device->getRoot();
        if (rootBase.contains("mmcblk"))
            rootBase.chop(2);
        else
            rootBase.chop(1);
        logger->addLine("From a root partition of " + device->getRoot() + ", I have deduced a base device of " + rootBase);
        if (device->hasRootChanged() && utils->getOSMCDev() != "atv")
        {
            logger->addLine("Must mklabel as root fs is on another device");
            utils->mklabel(rootBase, false);
            utils->mkpart(rootBase, "ext4", "4096s", "100%");
            utils->fmtpart(device->getRoot(), "ext4");
        }
        else
        {
            int size = utils->getPartSize(rootBase, (device->getBootFS() == "vfat" ? "fat32" : "ext4"));
            if (size == -1)
            {
                logger->addLine("Issue getting size of device");
                haltInstall(tr("cannot work out partition size"));
                return;
            }
            logger->addLine("Determined " + QString::number(size) + " MB as end of first partition");
            utils->mkpart(rootBase, "ext4", QString::number(size + 2) + "M", "100%");
            utils->fmtpart(device->getRoot(), "ext4");
        }
    }
    /* Mount root filesystem */
    if (useNFS)
        bc = new BootloaderConfig(device, nw, utils, logger);
    else
        bc = new BootloaderConfig(device, NULL, utils, logger);
    logger->addLine("Mounting root");
    if ( ! utils->mountPartition(device, MNT_ROOT))
    {
        logger->addLine("Error occured trying to mount root of " + device->getRoot());
        haltInstall(tr("can't mount root"));
        return;
    }
    if (useNFS)
        system("rm -rf /mnt/root/*"); /* BusyBox tar does not like overwrites. Clear nfsroot first */
   /* Extract root filesystem */
   ui->statusLabel->setText(tr("Installing files"));
   logger->addLine("Extracting files to root filesystem");
   ui->statusProgressBar->setMinimum(0);
   ui->statusProgressBar->setMaximum(100);

   QThread* thread = new QThread(this);
   ExtractWorker *worker = new ExtractWorker(fileSystem.fileName(), MNT_ROOT, logger);
   worker->moveToThread(thread);
   connect(thread, SIGNAL(started()), worker, SLOT(extract()));
   connect(worker, SIGNAL(progressUpdate(unsigned)), this, SLOT(setProgress(unsigned)));
   connect(worker, SIGNAL(error(QString)), this, SLOT(haltInstall(QString)));
   connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
   connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
   connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
   connect(thread, SIGNAL(finished()), this, SLOT(finished()));
   thread->start();
}
Ejemplo n.º 2
0
void MainWindow::install()
{
    ui->statusLabel->setFont(getFont(ui->statusLabel, FONT_STATUSLABEL_RATIO));
    ui->statusProgressBar->setFont(getFont(ui->statusProgressBar, FONT_PROGRESSBAR_RATIO));

    qApp->processEvents();
    /* Find out what device we are running on */
    logger->addLine("Detecting device we are running on");
    device = targetList->getTarget(utils->getOSMCDev());
    if (device == NULL)
    {
        haltInstall("unsupported device"); /* No tr here as not got lang yet */
        return;
    }
    /* Mount the BOOT filesystem */
    logger->addLine("Mounting boot filesystem");
    bool hasMount = false;
    hasMount = utils->mountPartition(device, MNT_BOOT);
    if (! hasMount && utils->getOSMCDev() == "atv")
    {
        /* Super hacky for Apple TV 1st gen. Sometimes no internal disk */
        hasMount = utils->mountPartition(device, "/dev/sda1");
        device->setRoot("/dev/sda2");
        device->setBootNeedsFormat(false);
    }
    if (! hasMount)
    {
        haltInstall("could not mount bootfs");
        return;
    }
    /* Sanity check: need filesystem.tar.xz */
    QFile fileSystem(QString(MNT_BOOT) + "/filesystem.tar.xz");
    if (! fileSystem.exists())
    {
        haltInstall("no filesystem found");
        return;
    }
    /* Load in preseeded values */
    preseed = new PreseedParser();
    if (preseed->isLoaded())
    {
        logger->addLine("Preseed file found, will attempt to parse");
        /* Locales */
        locale = preseed->getStringValue("globe/locale");
        if (! locale.isEmpty())
        {
            logger->addLine("Found a definition for globalisation: " + locale);
            QTranslator translator;
            if (translator.load(qApp->applicationDirPath() + "/osmc_" + locale + ".qm"))
            {
                logger->addLine("Translation loaded successfully!");
                qApp->installTranslator(&translator);
                ui->retranslateUi(this);
            }
            else
                logger->addLine("Could not load translation");
        }
        /* Install target */
        installTarget = preseed->getStringValue("target/storage");
        if (! installTarget.isEmpty())
        {
            logger->addLine("Found a definition for storage: " + installTarget);
            if (installTarget == "nfs")
            {
                QString nfsPath = preseed->getStringValue("target/storagePath");
                if (! nfsPath.isEmpty())
                {
                    device->setRoot(nfsPath);
                    useNFS = true;
                }
            }
            if (installTarget == "usb")
            {
                /* Behaviour for handling USB installs */
                if (utils->getOSMCDev() == "rbp1") { device->setRoot("/dev/sda1"); }
                if (utils->getOSMCDev() == "rbp2") { device->setRoot("/dev/sda1"); }
                if (utils->getOSMCDev() == "vero1") { device->setRoot("/dev/sda1"); }
                if (utils->getOSMCDev() == "atv") { device->setRoot("/dev/sda1"); } /* It's not USB, it's the internal disk.. but this is a hack */
                for (int i = 0; i <= 60; i++)
                {
                    ui->statusLabel->setText(tr("USB install:") + " " + QString::number(60 - i) + " " + ("seconds to remove device before data loss"));
                    qApp->processEvents();
                    system("/bin/sleep 1");
                }
            }
        }
        /* Bring up network if using NFS */
        if (useNFS)
        {
            logger->addLine("NFS installation chosen, must bring up network");
            nw = new Network();
            nw->setIP(preseed->getStringValue("network/ip"));
            nw->setMask(preseed->getStringValue("network/mask"));
            nw->setGW(preseed->getStringValue("network/gw"));
            nw->setDNS1(preseed->getStringValue("network/dns1"));
            nw->setDNS2(preseed->getStringValue("network/dns2"));
            if (! nw->isDefined())
            {
                logger->addLine("Either network preseed definition incomplete, or user wants DHCP");
                nw->setAuto();
            }
            logger->addLine("Attempting to bring up eth0");
            ui->statusLabel->setText(tr("Configuring Network"));
            nw->bringUp();
        }
    }
    else
    {
        logger->addLine("No preseed file was found");
    }
    /* If !nfs, create necessary partitions */
    if (! useNFS)
    {
        logger->addLine("Creating root partition");
        ui->statusLabel->setText(tr("Formatting device"));
        qApp->processEvents(); /* Force GUI update */
        QString rootBase = device->getRoot();
        if (rootBase.contains("mmcblk"))
            rootBase.chop(2);
        else
            rootBase.chop(1);
        logger->addLine("From a root partition of " + device->getRoot() + ", I have deduced a base device of " + rootBase);
        if (device->hasRootChanged() && utils->getOSMCDev() != "atv") // && utils.getOSMCDev() != "pc" eventually.. -- cause we want boot there too.
        {
            logger->addLine("Must mklabel as root fs is on another device");
            utils->mklabel(rootBase, false);
            utils->mkpart(rootBase, "ext4", "4096s", "100%");
            utils->fmtpart(device->getRoot(), "ext4");
        }
        else
        {
            if (! device->doesBootNeedsFormat())
            {
                int size = utils->getPartSize(rootBase, device->getBootFS());
                if (size == -1)
                {
                    logger->addLine("Issue getting size of device");
                    haltInstall(tr("cannot work out partition size"));
                    return;
                }
                if (device->deviceUsesGPT())
                {
                    /* GPT is too clever: has secondary header; so we need to trash it and recreate the partition layout */
                    /* NB: for some reason on 4.x this does not work all the time. So we have some parted patches to make sure it does */
                    logger->addLine("We are using GPT. I need to erase the first 512 bytes and reconstruct the partition table");
                    QString ddCmd = "/bin/dd if=/dev/zero of=" + rootBase + " bs=512 count=1 conv=fsync";
                    system(ddCmd.toLocal8Bit());
                    int fd;
                    QFile dev(rootBase);
                    dev.open(fd, QIODevice::ReadOnly);
                    ioctl(fd, BLKRRPART, NULL);
                    ioctl(fd, BLKFLSBUF, NULL);
                    dev.close();
                    utils->updateDevTable();
                    utils->updateDevTable();
                    if (utils->getOSMCDev() == "atv")
                    {
                        logger->addLine("Re-creating Apple TV partition structure");
                        utils->mklabel(rootBase, true);
                        utils->updateDevTable();
                        utils->mkpart(rootBase, "hfsplus", "40s", "256M");
                        /* We don't format /boot */
                        utils->setflag(rootBase, "1 atvrecv", true);
                        utils->updateDevTable();
                    }
                }
                logger->addLine("Determined " + QString::number(size) + " MB as end of first partition");
                utils->mkpart(rootBase, "ext4", QString::number(size + 2) + "M", "100%");
                utils->fmtpart(device->getRoot(), "ext4");
            }
            else
            {
                /* We have to create the partition structure for /boot too */
                logger->addLine("Must mklabel as rootfs is on another device");
                utils->mklabel(rootBase, true); /* GPT favoured on PC */
                logger->addLine("Making boot partition as this type of system needs one");
                if (utils->getOSMCDev() == "atv")
                {
                    utils->mkpart(rootBase, device->getBootFS(), "40s", "256M"); /* Hack to hard-code this for now */
                    utils->setflag(rootBase, "1 atvrecv", true);
                    utils->fmtpart(device->getBoot(), "hfsplus");
                }
                utils->updateDevTable();
                logger->addLine("Making root partition");
                int size = utils->getPartSize(rootBase, device->getBootFS());
                if (size == -1)
                {
                    logger->addLine("Issue getting size of device");
                    haltInstall(tr("cannot work out partition size"));
                    return;
                }
                logger->addLine("Determined " + QString::number(size) + " MB as end of first partition");
                utils->mkpart(rootBase, "ext4", QString::number(size + 2) + "M", "100%");
                utils->fmtpart(device->getRoot(), "ext4");
            }
        }
    }
    /* Mount root filesystem */
    if (useNFS)
        bc = new BootloaderConfig(device, nw, utils, logger, preseed);
    else
        bc = new BootloaderConfig(device, NULL, utils, logger, preseed);
    logger->addLine("Mounting root");
    if ( ! utils->mountPartition(device, MNT_ROOT))
    {
        logger->addLine("Error occured trying to mount root of " + device->getRoot());
        haltInstall(tr("can't mount root"));
        return;
    }
    if (useNFS)
        system("rm -rf /mnt/root/*"); /* BusyBox tar does not like overwrites. Clear nfsroot first */
   /* Extract root filesystem */
   ui->statusLabel->setText(tr("Installing files"));
   logger->addLine("Extracting files to root filesystem");
   ui->statusProgressBar->setMinimum(0);
   ui->statusProgressBar->setMaximum(100);

   QThread* thread = new QThread(this);
   ExtractWorker *worker = new ExtractWorker(fileSystem.fileName(), MNT_ROOT, logger);
   worker->moveToThread(thread);
   connect(thread, SIGNAL(started()), worker, SLOT(extract()));
   connect(worker, SIGNAL(progressUpdate(unsigned)), this, SLOT(setProgress(unsigned)));
   connect(worker, SIGNAL(error(QString)), this, SLOT(haltInstall(QString)));
   connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
   connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
   connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
   connect(thread, SIGNAL(finished()), this, SLOT(finished()));
   thread->start();
}