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