#!/bin/sh #Script to install ChromeOS on top of ChromiumOS #Can be used to install on a disk drive or applied to a ChromiumOS image #If installing to a disk drive, you must run it from a different drive/USB #Parameters: #1 - ChromiumOS image, drive (ex: /dev/sda) or system partition (ex: /dev/sda3) (If partition: manually resize it to 4GB before running the script) #2 - ChromeOS image file to be installed #3 - [Optional] ChromeOS image from older device with TPM1.2 (ex: caroline image file) (needed for TPM2 images like eve to be able to login) flag_vtpm=false flag_tpm1=false flag_disk=false if ( ! test -z {,} ); then echo "Must be ran with \"sudo bash\""; exit 1; fi if [ $(whoami) != "root" ]; then echo "Please run with sudo"; exit 1; fi if [ -z "$2" ]; then echo "Missing parameters"; exit 1; fi if [ -b "$1" ]; then flag_image=false; elif [ -f "$1" ]; then flag_image=true; else echo "Invalid image or partition: $1"; exit 1; fi if [ ! -d /home/chronos ]; then mkdir /home/chronos; fi if [ ! -d /home/chronos/image ]; then mkdir /home/chronos/image; fi if [ ! -d /home/chronos/local ]; then mkdir /home/chronos/local; fi if [ ! -d /home/chronos/tpm1image ]; then mkdir /home/chronos/tpm1image; fi if [ ! -d /home/chronos/RAW ]; then mkdir /home/chronos/RAW; fi function cleanup_chromefy { sync umount /home/chronos/image 2>/dev/null umount /home/chronos/local 2>/dev/null umount /home/chronos/tpm1image 2>/dev/null losetup -d "$chromium_image" 2>/dev/null losetup -d "$chromeos_image" 2>/dev/null losetup -d "$chromeos_tpm1_image" 2>/dev/null rm -rf /home/chronos/RAW/* &>/dev/null } function abort_chromefy { echo "aborting..."; cleanup_chromefy exit 1 } function read_choice { while read choice; do case "$choice" in [yY]|[yY][eE][sS] ) choice=true; break;; [nN]|[nN][oO] ) choice=false; break;; * ) echo "Invalid choice";; esac done } function cp_ext { if [ -x "$(command -v rsync)" ]; then rsync --info=progress2 -ah "$@" else cp -av "$@" fi } function cp_ext_nodup { if [ -x "$(command -v rsync)" ]; then rsync --info=progress2 --ignore-existing -ah "$@" else cp -nav "$@" fi } #Checks if images are valid and mounts them if [ "$flag_image" = true ]; then chromium_image=`losetup --show -fP "$1"` mount "$chromium_image"p3 /home/chronos/local -o loop,rw 2>/dev/null if [ ! $? -eq 0 ]; then echo "Image $1 does not have a system partition (corrupted?)"; abort_chromefy; fi else chromium_image="$1"; fi if [ ! -f "$2" ]; then echo "Image $2 not found"; abort_chromefy; fi chromeos_image=`losetup --show -fP "$2"` if [ -b "$chromeos_image"p3 ]; then mount "$chromeos_image"p3 /home/chronos/image -o loop,ro 2>/dev/null else mount $2 /home/chronos/image -o loop,ro 2>/dev/null fi if [ ! $? -eq 0 ]; then echo "Image $2 does not have a system partition (corrupted?)"; abort_chromefy; fi if [ ! -z "$3" ]; then if tar -tf "$3" &>/dev/null && ! tar -ztf "$3" &>/dev/null; then flag_vtpm=true else flag_tpm1=true if [ ! -f "$3" ]; then echo "Image $3 not found"; abort_chromefy; fi chromeos_tpm1_image=`losetup --show -fP "$3"` mount "$chromeos_tpm1_image"p3 /home/chronos/tpm1image -o loop,ro 2>/dev/null if [ ! $? -eq 0 ]; then echo "Image $3 does not have a system partition (corrupted?)"; abort_chromefy; fi fi fi #Checks if disk or partition PART_LIST=`sfdisk -lq "$chromium_image" 2>/dev/null` PART_GRUB=`echo "$PART_LIST" | grep "^""$chromium_image""[^:]" | awk '{print $1}' | grep [^0-9]12$` PART_B=`echo "$PART_LIST" | grep "^""$chromium_image""[^:]" | awk '{print $1}' | grep [^0-9]5$` PART_A=`echo "$PART_LIST" | grep "^""$chromium_image""[^:]" | awk '{print $1}' | grep [^0-9]3$` PART_STATE=`echo "$PART_LIST" | grep "^""$chromium_image""[^:]" | awk '{print $1}' | grep [^0-9]1$` if [ "$flag_image" = false ]; then if [ ! -z "$PART_LIST" ]; then flag_disk=true umount "$1"?* 2>/dev/null if [ $(sudo sfdisk --part-type "$1" 3 2>/dev/null) != "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" ] then echo "Invalid device (Chromium/Chrome not installed)"; abort_chromefy fi else PART_A="$1" fi fi #Checks VTPM support if third parameter is a tar file (TPM emulator) if [ "$flag_image" = false ]; then mount "$PART_A" /home/chronos/local; fi KERNEL_LOCAL=`ls /lib/modules/ | egrep "^([0-9]{1,}\.)+[0-9]{1,}[^ ]*$" | tail -1` KERNEL_CHROMIUM=`ls /home/chronos/local/lib/modules/ | egrep "^([0-9]{1,}\.)+[0-9]{1,}[^ ]*$" | tail -1` VTPM_BUILTIN=`cat /home/chronos/local/lib/modules/"$KERNEL_CHROMIUM"/modules.builtin 2>/dev/null | grep tpm_vtpm_proxy.ko` VTPM_MODULE=`cat /home/chronos/local/lib/modules/"$KERNEL_CHROMIUM"/modules.dep 2>/dev/null | grep tpm_vtpm_proxy.ko` if [ "$flag_vtpm" = true ] && [ -z "$VTPM_BUILTIN" ] && [ -z "$VTPM_MODULE" ]; then echo "This Chromium image does not support VTPM proxy, use different image or TPM replacement method"; abort_chromefy fi if [ "$flag_vtpm" = true ]; then tar -xvf "$3" -C /home/chronos/RAW/ fi #Backups ChromiumOS /lib directory if needed chromium_root_dir="" flag_linux=true choice=false if [ -e "/usr/sbin/chromeos-install" ] && [ ! -z "$KERNEL_LOCAL" ] && [ "$KERNEL_LOCAL" = "$KERNEL_CHROMIUM" ]; then echo "Local ChromiumOS installation detected; use local files (y/n)?" read_choice fi if [ "$choice" = false ]; then chromium_root_dir="/home/chronos/RAW" flag_linux=false mkdir -p /home/chronos/RAW/usr/lib64 echo "Backing up kernel modules..." cp_ext /home/chronos/local/{lib,boot} /home/chronos/RAW/ cp_ext /home/chronos/local/usr/lib64/{dri,va} /home/chronos/RAW/usr/lib64/ if [ ! $? -eq 0 ]; then echo "Error while copying ChromiumOS files locally (insufficent disk space?)"; abort_chromefy; fi fi umount /home/chronos/local 2>/dev/null #Increases ROOT_A partition's size (if flashing on image) choice=false if [ "$flag_image" = true ]; then choice=true; elif [ "$flag_disk" = true ]; then echo "Resize the system partition (y/n)?"; read_choice; fi; if [ "$choice" = true ]; then START_NEWB=`expr $(sfdisk -o Device,End -lq "$chromium_image" | grep "^""$PART_GRUB"[[:space:]] | awk '{print $2}') + 1` END_NEWB=`expr $START_NEWB + 8191` UUID_B=`sfdisk --part-uuid "$chromium_image" 5` START_NEWA=`expr $END_NEWB + 1` END_NEWA=`expr $(sfdisk -o Device,Start -lq "$chromium_image" | grep "^""$PART_STATE"[[:space:]] | awk '{print $2}') - 1` UUID_A=`sfdisk --part-uuid "$chromium_image" 3` #Deletes third (ROOT_A) and fifth (ROOT_B) partitions flock "$chromium_image" sfdisk --delete $chromium_image 5 flock "$chromium_image" sfdisk --delete $chromium_image 3 #Recreates the fifth partition with 4MB = 4194304 echo -e 'n\n5\n'"$START_NEWB"'\n'"$END_NEWB"'\nw' | flock "$chromium_image" fdisk "$chromium_image" if [ -z "$PART_B" ]; then PART_B=`flock "$chromium_image" sfdisk -lq "$chromium_image" 2>/dev/null | grep "^""$chromium_image""[^:]" | awk '{print $1}' | grep [^0-9]5$`; fi flock "$chromium_image" resize2fs "$PART_B" flock "$chromium_image" sfdisk --part-label "$chromium_image" 5 "ROOT-B" flock "$chromium_image" sfdisk --part-type "$chromium_image" 5 "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" flock "$chromium_image" sfdisk --part-uuid "$chromium_image" 5 "$UUID_B" flock "$chromium_image" e2label "$PART_B" "ROOT-B" yes | mkfs.ext4 "$PART_B" #Recreates the third partition with the remaining space echo -e 'n\n3\n'"$START_NEWA"'\n'"$END_NEWA"'\nw' | flock "$chromium_image" fdisk "$chromium_image" flock "$chromium_image" hdparm -z "$chromium_image" # flock "$chromium_image" dd bs=512 count=`expr $END_NEWA + 1 - $START_NEWA` if=/dev/zero of="$PART_A" flock "$chromium_image" yes | mke2fs -S "$PART_A" flock "$chromium_image" e2fsck -y -v -C 0 "$PART_A" flock "$chromium_image" resize2fs "$PART_A" flock "$chromium_image" sfdisk --part-label "$chromium_image" 3 "ROOT-A" flock "$chromium_image" sfdisk --part-type "$chromium_image" 3 "3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" flock "$chromium_image" sfdisk --part-uuid "$chromium_image" 3 "$UUID_A" flock "$chromium_image" e2label "$PART_A" "ROOT-A" yes | mkfs.ext4 "$PART_A" #Searches and fixes errors at filesystem-3, then remounts e2fsck -f -y -v -C 0 "$PART_A" fi #Mounts ChromiumOS system partition if [ "$flag_image" = false ]; then umount "$PART_A" 2>/dev/null yes | mkfs.ext4 "$PART_A" mount "$PART_A" /home/chronos/local if [ ! $? -eq 0 ]; then echo "Partition $PART_A inexistent"; abort_chromefy; fi else mount "$PART_A" /home/chronos/local -o loop,rw,sync 2>/dev/null if [ ! $? -eq 0 ]; then echo "Something went wrong while changing $1 partition table (corrupted?)"; abort_chromefy; fi fi #Copies all ChromeOS system files echo "Copying ChromeOS system files..." cp_ext /home/chronos/image/* /home/chronos/local umount /home/chronos/image #Copies modules and certificates from ChromiumOS rm -rf /home/chronos/local/lib/firmware rm -rf /home/chronos/local/lib/modules/ echo "Copying kernel modules..." cp_ext "$chromium_root_dir"/{lib,boot} /home/chronos/local/ cp_ext_nodup "$chromium_root_dir"/usr/lib64/{dri,va} /home/chronos/local/usr/lib64/ #Extra GPU drivers rm -rf /home/chronos/local/etc/modprobe.d/alsa*.conf echo "Is your wireless card bcm43xx? Answer no if unsure (y/n)" read_choice if [ "$choice" = true ]; then # enable bcm43xx wifi cat > /home/chronos/local/lib/modprobe.d/blacklist.conf < /home/chronos/local/lib/udev/rules.d/60-evdev-apple-touchpad.rules < /home/chronos/local/lib/udev/rules.d/90-powerd-id-apple-touchpad.rules </home/chronos/local/etc/init/_vtpm.conf </dev/null; mkdir -p /home/chronos/local 2>/dev/null;SRC="${SRC}";DST="${DST}" SRC_EFIPART=`flock "${SRC}" sfdisk -lq "${SRC}" 2>/dev/null | grep "^""${SRC}""[^:]" | awk '{print $1}' | grep [^0-9]12$` EFIPART=`flock "${DST}" sfdisk -lq "${DST}" 2>/dev/null | grep "^""${DST}""[^:]" | awk '{print $1}' | grep [^0-9]12$` dd if="${SRC_EFIPART}" of="${EFIPART}" bs=4k status=progress mount "$EFIPART" /home/chronos/local 2>/dev/null OLD_UUID=`cat /home/chronos/local/efi/boot/grub.cfg | grep -m 1 "PARTUUID=" | awk -v FS="(PARTUUID=)" '{print $2}' | awk '{print $1}'` OLD_UUID_LEGACY=`cat /home/chronos/local/syslinux/usb.A.cfg | grep -m 1 "PARTUUID=" | awk -v FS="(PARTUUID=)" '{print $2}' | awk '{print $1}'` PARTUUID=`flock "${DST}" sfdisk --part-uuid "${DST}" 3`; sed -i "s/$OLD_UUID/$PARTUUID/" /home/chronos/local/efi/boot/grub.cfg sed -i "s/$OLD_UUID_LEGACY/$PARTUUID/" /home/chronos/local/syslinux/usb.A.cfg sync; umount /home/chronos/local 2>/dev/null; rmdir /home/chronos/local 2>/dev/null echo "EFI: Partition UUID $OLD_UUID changed to $PARTUUID"; echo "Legacy: Partition UUID $OLD_UUID_LEGACY changed to $PARTUUID"; echo EOF CHROMEOS_INSTALL_FIX_GRUB="${CHROMEOS_INSTALL_FIX_GRUB//\\/\\\\}" CHROMEOS_INSTALL_FIX_GRUB="${CHROMEOS_INSTALL_FIX_GRUB//$'\n'/\\n}" sed -i 's/DEFINE_boolean skip_postinstall ${FLAGS_FALSE}/DEFINE_boolean skip_postinstall ${FLAGS_TRUE}/g' /home/chronos/local/usr/sbin/chromeos-install sed -i "s/^[ \t]*do_post_install[ \t]*\$/${CHROMEOS_INSTALL_FIX_GRUB////\\/}/g" /home/chronos/local/usr/sbin/chromeos-install #Fix write_gpt.sh to create an ESP that's big enough tmp_esp_size="$(grep 'PARTITION_SIZE_EFI_SYSTEM' /home/chronos/local/usr/sbin/write_gpt.sh|tail -n1)" esp_size="${tmp_esp_size#*=}" sed -i "s/$esp_size/536870912/g" /home/chronos/local/usr/sbin/write_gpt.sh #Expose the internal camera to android container internal_camera=`dmesg | grep uvcvideo -m 1 | awk -F '[()]' '{print $2}'` original_camera=`sed -nr 's,^camera0.module0.usb_vid_pid=(.*),\1,p' /home/chronos/local/etc/camera/camera_characteristics.conf` if [ ! -z $internal_camera ] && [ ! -z $original_camera ] then sudo sed -i -e "s/${original_camera%:*}/${internal_camera%:*}/" -e "s/${original_camera##*:}/${internal_camera##*:}/" /home/chronos/local/lib/udev/rules.d/50-camera.rules sudo sed -i "s/$original_camera/$internal_camera/" /home/chronos/local/etc/camera/camera_characteristics.conf fi cleanup_chromefy echo if [ "$flag_image" = false ]; then echo "ChromeOS installed, you can now reboot" else echo "ChromeOS image created: this is for personal use only, distribute at your own risk" fi