diff --git a/files/distros.ps1 b/files/distros.ps1 new file mode 100644 index 0000000..970211d --- /dev/null +++ b/files/distros.ps1 @@ -0,0 +1,31 @@ +@( + @{ + name='Linux Mint - Cinnamon - 19.3'; + url='http://mirrors.kernel.org/linuxmint/stable/19.3/linuxmint-19.3-cinnamon-64bit.iso'; + }, + @{ + name='Linux Mint - MATE - 19.3'; + url='http://mirrors.kernel.org/linuxmint/stable/19.3/linuxmint-19.3-mata-64bit.iso'; + }, + @{ + name='Linux Mint - Xfce - 19.3'; + url='http://mirrors.kernel.org/linuxmint/stable/19.3/linuxmint-19.3-xfce-64bit.iso'; + }, + @{ + name='Ubuntu 18.04/LTS'; + url='http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso'; + }, + @{ + name='Ubuntu 19.10'; + url='http://releases.ubuntu.com/19.10/ubuntu-19.10-desktop-amd64.iso'; + }, + @{ + name='Pop!_OS - 18.04/LTS'; + url='https://pop-iso.sfo2.cdn.digitaloceanspaces.com/18.04/amd64/intel/58/pop-os_18.04_amd64_intel_58.iso'; + }, + @{ + name='Pop!_OS - 19.10'; + url='https://pop-iso.sfo2.cdn.digitaloceanspaces.com/19.10/amd64/intel/11/pop-os_19.10_amd64_intel_11.iso'; + } +) + diff --git a/files/grub.cfg b/files/grub.cfg index b6d8911..9ad24b1 100644 --- a/files/grub.cfg +++ b/files/grub.cfg @@ -2,9 +2,12 @@ # Copyright (c) Michael Slattery under GPLv3 with NO warranty. # For more info see https://www.gnu.org/licenses/gpl-3.0.html#section15 +# get values for iso_file +source '/boot/grub/grub.var.cfg' + set ALLUSERSPROFILE='/ProgramData' set tunic_dir="${ALLUSERSPROFILE}/tunic" -set iso_path="${tunic_dir}/linux.iso" +set iso_path="${tunic_dir}/${iso_file}" set timeout=2 @@ -16,7 +19,7 @@ menuentry "Tunic Automatic Linux Installer" { loopback loop ($root)$iso_path echo 'Loading Linux kernel...' - linux (loop)/casper/vmlinuz file=/isodevice${tunic_dir}/preseed.cfg automatic-ubiquity boot=casper iso-scan/filename=${iso_path} toram noprompt init=/bin/sh -- -c "losetup -d /dev/loop0; umount /isodevice; exec /sbin/init" + linux (loop)/casper/vmlinuz file=/isodevice${tunic_dir}/preseed.cfg automatic-ubiquity boot=casper iso-scan/filename=${iso_path} toram noprompt -- echo 'Loading ramdisk...' initrd (loop)/casper/initrd.lz @@ -29,7 +32,7 @@ menuentry "Try out Linux without install" { loopback loop ($root)$iso_path echo 'Loading Linux kernel...' - linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=${iso_path} toram noprompt init=/bin/sh -- -c "losetup -d /dev/loop0; umount /isodevice; exec /sbin/init" + linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=${iso_path} toram noprompt -- echo 'Loading ramdisk...' initrd (loop)/casper/initrd.lz diff --git a/files/preseed.cfg b/files/preseed.cfg index 94fbd69..d4b20ba 100644 --- a/files/preseed.cfg +++ b/files/preseed.cfg @@ -2,8 +2,12 @@ # Copyright (c) Michael Slattery under GPLv3 with NO warranty. # For more info see https://www.gnu.org/licenses/gpl-3.0.html#section15 -d-i preseed/early_command string \ - sed -i '/grub-failed/,/exit 1/d' /root/usr/share/grub-installer/grub-installer || true; +d-i partman/early_command string \ + losetup -d /dev/loop0 || true; \ + umount /isodevice || true; + +ubiquity ubiquity/success_command string \ + in-target sed 's/^\(GRUB_CMDLINE_LINUX="\).*$/\1" #tunic/' /etc/default/grub || true; # Partition @@ -13,14 +17,14 @@ d-i partman/unmount_active boolean true d-i partman-auto/disk string /dev/sd$( [char]((Get-Partition -driveletter $global:letter).diskNumber + 97) ) d-i partman-auto/choose_recipe select atomic -$( if( $data.installType -eq $DUALBOOT ) { "d-i partman-auto/init_automatically_partition select biggest_free" } else { "" }) -$( if( $data.installType -eq $FULLBOOT ) { "d-i partman-auto/init_automatically_partition select Guided - use entire disk" } else { "" }) -$( if( $data.installType -eq $FULLBOOT ) { "d-i partman-auto/method string regular" } else { "" }) +$( if( $global:data.installType -eq $DUALBOOT ) { "d-i partman-auto/init_automatically_partition select biggest_free" } else { "" }) +$( if( $global:data.installType -eq $FULLBOOT ) { "d-i partman-auto/init_automatically_partition select Guided - use entire disk" } else { "" }) +$( if( $global:data.installType -eq $FULLBOOT ) { "d-i partman-auto/method string regular" } else { "" }) -$( if( $data.installType -ne $CUSTOMBOOT ) { "d-i partman-partitioning/confirm_write_new_label boolean true" } else { "" }) -$( if( $data.installType -ne $CUSTOMBOOT ) { "d-i partman/choose_partition select finish" } else { "" }) -$( if( $data.installType -ne $CUSTOMBOOT ) { "d-i partman/confirm boolean true" } else { "" }) -$( if( $data.installType -ne $CUSTOMBOOT ) { "d-i partman/confirm_nooverwrite boolean true" } else { "" }) +$( if( $global:data.installType -ne $CUSTOMBOOT ) { "d-i partman-partitioning/confirm_write_new_label boolean true" } else { "" }) +$( if( $global:data.installType -ne $CUSTOMBOOT ) { "d-i partman/choose_partition select finish" } else { "" }) +$( if( $global:data.installType -ne $CUSTOMBOOT ) { "d-i partman/confirm boolean true" } else { "" }) +$( if( $global:data.installType -ne $CUSTOMBOOT ) { "d-i partman/confirm_nooverwrite boolean true" } else { "" }) # Locale @@ -28,7 +32,7 @@ d-i debian-installer/locale string $( (get-culture).ietfLanguageTag.replace('-', d-i debian-installer/language string $( (get-culture).TwoLetterISOLanguageName ) d-i debian-installer/country string $( (New-Object System.Globalization.RegionInfo (Get-Culture).Name).TwoLetterISORegionName.toLower() ) d-i time/zone string $( getLinuxTimezone ) -d-i clock-setup/utc boolean $( ($data.installType -ne $DUALBOOT).toString().toLower() ) +d-i clock-setup/utc boolean $( ($global:data.installType -ne $DUALBOOT).toString().toLower() ) # Keyboard @@ -38,12 +42,12 @@ d-i console-setup/ask_detect boolean false # User -d-i passwd/user-fullname string $( $data.fullname ) -d-i passwd/username string $( $data.username ) -d-i passwd/user-password password $( $data.password ) -d-i passwd/user-password-again password $( $data.password ) +d-i passwd/user-fullname string $( $global:data.fullname ) +d-i passwd/username string $( $global:data.username ) +d-i passwd/user-password password $( $global:data.password ) +d-i passwd/user-password-again password $( $global:data.password ) d-i user-setup/allow-password-weak boolean true -d-i netcfg/get_hostname string $( $data.hostname ) +d-i netcfg/get_hostname string $( $global:data.hostname ) # Packages diff --git a/tunic.ps1 b/tunic.ps1 index f1f53d8..d879d5b 100644 --- a/tunic.ps1 +++ b/tunic.ps1 @@ -2,18 +2,15 @@ # Copyright (c) Michael Slattery under GPLv3 with NO warranty. # For more info see https://www.gnu.org/licenses/gpl-3.0.html#section15 -# Automated install of an ISO file +# Automated install of an iso_path if( $args[0] -eq 'noop') { exit } # for syntax checking -$global:iso_url='http://mirrors.kernel.org/linuxmint/stable/19.3/linuxmint-19.3-cinnamon-64bit.iso' $global:shim_url = 'https://github.com/pop-os/iso/blob/master/data/efi/shimx64.efi.signed?raw=true' $global:letter = $env:HOMEDRIVE[0] $global:root_dir="${letter}:" $global:tunic_dir="${env:ALLUSERSPROFILE}\tunic" -$global:tunic_data="${tunic_dir}" -$global:iso = "${tunic_data}\linux.iso" $global:MIN_DISK_GB = 15 @@ -32,15 +29,28 @@ function initData() { mkdir "$global:tunic_dir" | out-null } + $distros = . files/distros.ps1 + $userInfo = ( Get-WMIObject Win32_UserAccount | where caption -eq (whoami) ) $global:data = @{ installType = $DUALBOOT; fullname = $userInfo.fullName; username = $userInfo.name.toLower(); hostname = $userInfo.psComputerName; + iso_url = $distros[0].url } } +function getUrlFile($url) { + return $url -replace '^.*/', '' -replace '[?#].*$', '' +} + +function getUrlPath($url) { + $file = getUrlFile($url) + return "${tunic_dir}\${file}" +} + + # Disable swap, hibernate, restore, error reports, dumps function disableSwap() { Write-Host "Disabling swap..." @@ -150,17 +160,19 @@ function checks() { } function downloadIso() { - if ( -not (Test-Path "$global:iso") ) { - $ciso = 'Z:\Downloads\linuxmint-19.3-cinnamon-64bit.iso' + $iso_path = getUrlPath($global:data.iso_url) + $iso_file = getUrlFile($global:data.iso_url) + if ( -not (Test-Path "$iso_path") ) { + $ciso = "Z:\Downloads\$iso_file" if ( Test-Path "$ciso" ) { - copy "$ciso" "$global:iso" + copy "$ciso" "$iso_path" } else { try { - (New-Object System.Net.WebClient).DownloadFile($global:iso_url, "$global:iso") + (New-Object System.Net.WebClient).DownloadFile($global:data.iso_url, "$iso_path") #TODO: save to temp and move after. #TODO: verify integrity } catch { - Remove-Item "$global:iso" + Remove-Item "$iso_path" Throw "Download failed" } } @@ -246,10 +258,13 @@ function installGrub() { $grub_path="${efi}${grub_dir}" if ( -not (Test-Path "$grub_path") ) { + $iso_file = getUrlFile($global:data.iso_url) + $iso_path = getUrlPath($global:data.iso_url) + $usb = $false while( -not $usb ) { try { - $usb = "$(( mount-diskimage -imagepath "$iso" | get-volume ).driveletter):" + $usb = "$(( mount-diskimage -imagepath "$iso_path" | get-volume ).driveletter):" } catch { # If mount runs too early after boot an error may occur sleep 10 @@ -263,8 +278,9 @@ function installGrub() { (New-Object System.Net.WebClient).DownloadFile($shim_url, "$grub_path\shimx64.efi") } copy "files\grub.cfg" "$grub_path\." + set-content -path "$grub_path\grub.var.cfg" -value "set iso_file='$iso_file'" - dismount-diskimage -imagepath "$global:iso" | out-null + dismount-diskimage -imagepath "$iso_path" | out-null } # Boot Entry @@ -324,7 +340,7 @@ function repartition() { $global:partc = (get-partition -driveletter $letter) # size entered in GUI - $linusSizeNum = $data.linuxSize * 1GB + $linusSizeNum = $global:data.linuxSize * 1GB $shrinkBy = $linuxSizeNum - $global:gap @@ -336,7 +352,6 @@ function repartition() { } function calcGui() { -write-host 'calcGui' $global:form.activate() [System.Windows.Forms.Application]::DoEvents() @@ -377,9 +392,12 @@ function initFields() { checks initData - $fullname.text = $data.fullname - $username.text = $data.username - $hostname.text = $data.hostname + $fullname.text = $global:data.fullname + $username.text = $global:data.username + $hostname.text = $global:data.hostname + + $distroName.items.addRange($distros % { $_.name }) + $distroName.selectedIndex = 0 } function checkFields() { @@ -487,6 +505,27 @@ function gui() { $main.controls.add($bootGroup) + $distroPanel = New-Object system.Windows.Forms.TableLayoutPanel + $distroPanel.autosize = $true + $distroPanel.Dock = [System.Windows.Forms.DockStyle]::Fill + $distroPanel.padding = 5 + $distroPanel.columnCount = 2 + $row = 0 + + $distroLabel = New-Object system.Windows.Forms.Label + $distroLabel.text = "Distro" + $distroLabel.AutoSize = $true + + $global:distroName = New-Object system.Windows.Forms.ComboBox + $distroName.width = 180 + $distroName.AutoSize = $true + + $distroPanel.controls.add($distroLabel, 0, $row) + $distroPanel.controls.add($distroName, 1, $row) + $row++ + + $main.controls.add($distroPanel) + $global:sizeGroup = New-Object system.Windows.Forms.GroupBox $sizeGroup.text = "C: Drive" $sizeGroup.autosize = $true @@ -896,17 +935,18 @@ function gui() { }) $installButton.add_click({ - $data.username = $username.text - $data.fullname = $fullname.text - $data.hostname = $hostname.text + $global:data.username = $username.text + $global:data.fullname = $fullname.text + $global:data.hostname = $hostname.text + $global:data.password = $password.text if( $dualBootRadio.checked ) { - $data.installType = $DUALBOOT + $global:data.installType = $DUALBOOT } elseif( $fullBootRadio.checked ) { - $data.installType = $FULLBOOT + $global:data.installType = $FULLBOOT } else { - $data.installType = $CUSTOMBOOT + $global:data.installType = $CUSTOMBOOT } - $data.linuxSize = [double]::parse( $global:linuxSize.text ) + $global:data.iso_url = $distros[ $distroName.selectedIndex ].url if( -not (checkFields) ) { return @@ -931,7 +971,9 @@ function gui() { $global:progress.visible = $true #TODO: Run as PSJob, remove doevents - if( $data.installType -eq $DUALBOOT ) { + if( $global:data.installType -eq $DUALBOOT ) { + $global:data.linuxSize = [double]::parse( $global:linuxSize.text ) + $global:defragStatus.text = 'In Progress' [System.Windows.Forms.Application]::DoEvents() defrag @@ -958,7 +1000,7 @@ function gui() { $global:rebootStatus.text = 'In Progress' [System.Windows.Forms.Application]::DoEvents() - #Restart-Computer -force + Restart-Computer -force } }) @@ -970,10 +1012,10 @@ function gui() { # User will have 'tunic' password. function fullDisk() { initData - $data.installType = $FULLBOOT - $data.password = 'tunic' + $global:data.installType = $FULLBOOT + $global:data.password = 'tunic' - if( $data.installType -eq $DUALBOOT ) { + if( $global:data.installType -eq $DUALBOOT ) { write-host 'Defragmenting...' defrag write-host 'Repartitioning...'