123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #!/bin/bash
- #See the block of "echos" in main() for description of this script
- # This file is part of PrawnOS (https://www.prawnos.com)
- # Copyright (c) 2018 Hal Emmerich <hal@halemmerich.com>
- # PrawnOS is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License version 2
- # as published by the Free Software Foundation.
- # PrawnOS is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- # You should have received a copy of the GNU General Public License
- # along with PrawnOS. If not, see <https://www.gnu.org/licenses/>.
- RESOURCES=/InstallResources
- # Grab the boot device, which is either /dev/sda for usb or /dev/mmcblk0 for an sd card
- BOOT_DEVICE=$(mount | head -n 1 | cut -d '2' -f 1)
- main() {
- echo "---------------------------------------------------------------------------------------------------------------------"
- echo "PrawnOS Install or Expand Script"
- echo "Installation sets up the internal emmc partitions, root encryption, and copies the filesystem from the"
- echo "current boot device to the target device. The target device cannot be the current boot device"
- echo
- echo "Expansion simply targets the booted device, and expands the filesystem to fill the entire thing instead of just 2GB."
- echo "Because of this, root encryption cannot be setup"
- echo
- echo "For installation, this script can be quit and re-ran at any point."
- echo "Unfortunately for expansion this is not the case"
- echo "---------------------------------------------------------------------------------------------------------------------"
- echo
- echo "Expand or Install?: "
- echo "The currently booted device is ${BOOT_DEVICE}"
- while true; do
- read -r -p "[I]nstall or [E]xpand?" IE
- case $IE in
- [Ii]* ) install; break;;
- [Ee]* ) expand; break;;
- * ) echo "Please answer I or E";;
- esac
- done
- }
- #Now to pick the install target: internal, sd, or usb
- #if target is usb, and boot device is usb, target is sdb
- #and whether to enable crypto
- install() {
- echo "Pick an install target. This can be the Internal Emmc, an SD card, or a USB device"
- echo "Please ensure you have only have the booted device and the desired target device inserted."
- echo "The currently booted device is ${BOOT_DEVICE}"
- while true; do
- read -r -p "[I]nternal Emmc, [S]D card, or [U]SB device?: " ISU
- case $ISU in
- [Ii]* ) TARGET=/dev/mmcblk2p; break;;
- [Ss]* ) TARGET=/dev/mmcblk0p; break;;
- [Uu]* ) TARGET=USB; break;;
- * ) echo "Please answer I, S, or U";;
- esac
- done
- if [[ $TARGET == "USB" ]]
- then
- if [[ $BOOT_DEVICE == "/dev/sda" ]]
- then
- TARGET=/dev/sdb
- else
- TARGET=/dev/sda
- fi
- fi
- if [[ "$TARGET" == "$BOOT_DEVICE" ]]
- then
- echo "Can't install to booted device, please ensure you have *only* the booted device and target device inserted"
- exit
- fi
- #cut off the "p" if we are using an sd card or internal emmc, doesn't change TARGET if we are using usb
- TARGET_NO_P=$(echo $TARGET | cut -d 'p' -f 1)
- if [ ! -e $TARGET_NO_P ];
- then
- echo "${TARGET_NO_P} does not exist, have you plugged in your target sd card or usb device?"
- exit 1
- fi
- #Now on to the installation, basically copy InstallToInternal.sh
- while true; do
- read -r -p "This will ERASE ALL DATA ON ${TARGET_NO_P} and reboot when finished, do you want to continue? [y/N]" yn
- case $yn in
- [Yy]* ) break;;
- [Nn]* ) exit;;
- * ) echo "Please answer y or n";;
- esac
- done
- # Only try to unmount if the device is mounted
- # If it is, try anyway, the dd will (likely) take care of it anyway
- if findmnt ${TARGET}1 > /dev/null
- then
- umount ${TARGET}1 || /bin/true
- fi
- if findmnt ${TARGET}2 > /dev/null
- then
- umount ${TARGET}2 || /bin/true
- fi
- if [[ $TARGET == "/dev/mmcblk2p" ]]
- then
- emmc_partition
- else
- external_partition $TARGET_NO_P
- fi
- KERNEL_PARTITION=${TARGET}1
- ROOT_PARTITION=${TARGET}2
- CRYPTO=false
- echo Writing kernel partition
- dd if=/dev/zero of=$KERNEL_PARTITION bs=512 count=65536
- dd if=${BOOT_DEVICE}1 of=$KERNEL_PARTITION conv=notrunc
- #Handle full disk encryption
- echo "Would you like to setup full disk encrytion using LUKs/DmCrypt?"
- select yn in "Yes" "No"
- do
- case $yn,$REPLY in
- Yes,*|*,Yes )
- CRYPTO=true
- # Since iteration count is based on cpu power, and the rk3288 isn't as fast as a usual
- # desktop cpu, manually supply -i 15000 for security at the cost of a slightly slower unlock
- dmesg -n 2
- echo "Enter the password you would like to use to unlock the encrypted root partition at boot"
- cryptsetup -q -y -s 512 luksFormat -i 15000 $ROOT_PARTITION || exit 1
- echo "Now unlock the newly created encrypted root partition so we can mount it and install the filesystem"
- cryptsetup luksOpen $ROOT_PARTITION luksroot || exit 1
- dmesg -n 7
- ROOT_PARTITION=/dev/mapper/luksroot
- break
- ;;
- No,*|*,No )
- break
- ;;
- * )
- echo "Invalid Option, please enter Yes or No, 1 or 2"
- ;;
- esac
- done
- echo Writing Filesystem, this will take about 4 minutes...
- mkfs.ext4 -F -b 1024 $ROOT_PARTITION
- INSTALL_MOUNT=/mnt/install_mount
- mkdir -p $INSTALL_MOUNT/
- mount $ROOT_PARTITION $INSTALL_MOUNT/
- rsync -ah --info=progress2 --info=name0 --numeric-ids -x / $INSTALL_MOUNT/
- #Remove the live-fstab and install a base fstab
- rm $INSTALL_MOUNT/etc/fstab
- echo "${ROOT_PARTITION} / ext4 defaults,noatime 0 1" > $INSTALL_MOUNT/etc/fstab
- while true; do
- read -r -p "Install a desktop environment and the supporting packages? [Y/n]" ins
- case $ins in
- [Yy]* ) install_packages $INSTALL_MOUNT; break;;
- [Nn]* ) break;;
- * ) echo "Please answer y or n";;
- esac
- done
- umount $ROOT_PARTITION
- echo Running fsck
- e2fsck -p -f $ROOT_PARTITION
- if [[ $CRYPTO == "true" ]]
- then
- # unmount and close encrypted storage
- # let things settle, otherwise cryptsetup complainssss
- sleep 2
- cryptsetup luksClose luksroot
- fi
- echo "Please remove the booted device after power off is complete"
- while true; do
- read -r -p "Reboot? [y/N]" re
- case $re in
- [Yy]* ) reboot;;
- [Nn]* ) exit;;
- * ) echo "Please answer y or n";;
- esac
- done
- }
- #Setup partition map on internal emmc
- emmc_partition() {
- #disable dmesg, writing the partition map tries to write the the first gpt table, which is unmodifiable
- dmesg -D
- echo Writing partition map to internal emmc
- DISK_SZ="$(blockdev --getsz /dev/mmcblk2)"
- echo Total disk size is: $DISK_SZ
- if [ $DISK_SZ = 30785536 ]
- then
- echo Detected Emmc Type 1
- sfdisk /dev/mmcblk2 < $RESOURCES/mmc.partmap
- elif [ $DISK_SZ = 30777344 ]
- then
- echo Detected Emmc Type 2
- sfdisk /dev/mmcblk2 < $RESOURCES/mmc_type2.partmap
- else
- echo ERROR! Not a known EMMC type, please open an issue on github or send SolidHal an email with the Total disk size reported above
- echo Try a fallback value? This will allow installation to continue, at the cost of a very small amoutnt of disk space. This may not work.
- select yn in "Yes" "No"
- do
- case $yn,$REPLY in
- Yes,*|*,Yes )
- echo Trying Emmc Type 2
- sfdisk /dev/mmcblk2 < $RESOURCES/mmc_type2.partmap
- break
- ;;
- * )
- echo "Invalid Option, please enter Yes or No, 1 or 2"
- ;;
- esac
- done
- fi
- dmesg -E
- }
- #Setup partition map for external bootable device, aka usb or sd card
- external_partition() {
- EXTERNAL_TARGET=$1
- kernel_start=8192
- kernel_size=65536
- #wipe the partition map, cgpt doesn't like anything weird in the primary or backup partition maps
- sgdisk -Z $EXTERNAL_TARGET
- partprobe $EXTERNAL_TARGET
- #make the base gpt partition map
- parted --script $EXTERNAL_TARGET mklabel gpt
- cgpt create $EXTERNAL_TARGET
- #must use cgpt to make the kernel partition, as we need the -S, -T, and -P variables
- cgpt add -i 1 -t kernel -b $kernel_start -s $kernel_size -l Kernel -S 1 -T 5 -P 10 $EXTERNAL_TARGET
- #Now the main filesystem
- #cgpt doesn't seem to handle this part correctly
- sgdisk -N 2 $EXTERNAL_TARGET
- #Set the type to "data"
- sgdisk -t 2:0700 $EXTERNAL_TARGET
- #Name it "properly" - Probably not required, but looks nice
- sgdisk -c 2:Root $EXTERNAL_TARGET
- #Reload the partition mapping
- partprobe $EXTERNAL_TARGET
- }
- #simply expand to fill the current boot device
- expand() {
- # need to strip the "p" if BOOT_DEVICE is an sd card or emmc
- BOOT_DEVICE_NO_P=$(echo $BOOT_DEVICE | cut -d 'p' -f 1)
- if [[ $BOOT_DEVICE == "/dev/mmcblk2" ]]
- then
- echo "Can't expand to fill internal emmc, install will have done this already"
- exit
- fi
- #Make the boot partition fille the whole drive
- #Delete the partition
- sgdisk -d 2 $BOOT_DEVICE_NO_P
- #Make new partition map entry, with full size
- sgdisk -N 2 $BOOT_DEVICE_NO_P
- #Set the type to "data"
- sgdisk -t 2:0700 $BOOT_DEVICE_NO_P
- #Name it "properly" - Probably not required, but looks nice
- sgdisk -c 2:Root $BOOT_DEVICE_NO_P
- #Reload the partition mapping
- partprobe $BOOT_DEVICE_NO_P
- #Force the filesystem to fill the new partition
- resize2fs -f ${BOOT_DEVICE}2
- echo "/dev/${BOOT_DEVICE}2 / ext4 defaults,noatime 0 1" > /etc/fstab
- while true; do
- read -r -p "Install a desktop environment and the supporting packages? [Y/n]" ins
- case $ins in
- [Yy]* ) /InstallResources/InstallPackages.sh; reboot;;
- [Nn]* ) exit;;
- * ) echo "Please answer y or n";;
- esac
- done
- }
- #Install all packages, desktop environment to target device
- install_packages() {
- TARGET_MOUNT=$1
- echo "Installing Packages"
- mount -t proc proc $TARGET_MOUNT/proc/
- mount --rbind /sys $TARGET_MOUNT/sys/
- mount --rbind /dev $TARGET_MOUNT/dev/
- chroot $TARGET_MOUNT/ ./InstallResources/InstallPackages.sh
- umount $TARGET_MOUNT/proc/
- mount --make-rprivate /sys
- mount --make-rprivate /dev
- umount -R $TARGET_MOUNT/sys/
- umount -R $TARGET_MOUNT/dev/
- }
- #call the main function, script technically starts here
- #Organized this way so that main can come before the functions it calls
- main "$@"; exit
|