#!/bin/bash -e # # Copyright (c) 2013-2023 Robert Nelson # Portions copyright (c) 2014 Charles Steinkuehler # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. #This script assumes, these packages are installed, as network may not be setup #dosfstools initramfs-tools rsync u-boot-tools version_message="1.20230304.0: Fix dd locations..." # #mke2fs -c #Check the device for bad blocks before creating the file system. #If this option is specified twice, then a slower read-write test is #used instead of a fast read-only test. mkfs_options="" #mkfs_options="-c" #mkfs_options="-cc" if ! id | grep -q root; then echo "must be run as root" exit fi source="/dev/mmcblk0" destination="/dev/mmcblk1" flush_cache () { sync blockdev --flushbufs ${destination} } broadcast () { if [ "x${message}" != "x" ] ; then echo "${message}" #echo "${message}" > /dev/tty0 || true fi } write_failure () { message="writing to [${destination}] failed..." ; broadcast message="-----------------------------" ; broadcast flush_cache umount ${destination}p1 > /dev/null 2>&1 || true umount ${destination}p2 > /dev/null 2>&1 || true } check_running_system () { message="copying: [${source}] -> [${destination}]" ; broadcast message="lsblk:" ; broadcast message="`lsblk || true`" ; broadcast message="-----------------------------" ; broadcast message="df -h | grep rootfs:" ; broadcast message="`df -h | grep rootfs || true`" ; broadcast message="-----------------------------" ; broadcast if [ ! -b "${destination}" ] ; then message="Error: [${destination}] does not exist" ; broadcast write_failure fi if [ ! -f /boot/config-$(uname -r) ] ; then zcat /proc/config.gz > /boot/config-$(uname -r) fi if [ -f /boot/initrd.img-$(uname -r) ] ; then update-initramfs -u -k $(uname -r) else update-initramfs -c -k $(uname -r) fi flush_cache } dd_bootloader () { message="Writing bootloader to [${destination}]" ; broadcast unset dd_spl_uboot if [ ! "x${dd_spl_uboot_count}" = "x" ] ; then dd_spl_uboot="${dd_spl_uboot}count=${dd_spl_uboot_count} " fi if [ ! "x${dd_spl_uboot_seek}" = "x" ] ; then dd_spl_uboot="${dd_spl_uboot}seek=${dd_spl_uboot_seek} " fi if [ ! "x${dd_spl_uboot_conf}" = "x" ] ; then dd_spl_uboot="${dd_spl_uboot}conv=${dd_spl_uboot_conf} " fi if [ ! "x${dd_spl_uboot_bs}" = "x" ] ; then dd_spl_uboot="${dd_spl_uboot}bs=${dd_spl_uboot_bs}" fi unset dd_uboot if [ ! "x${dd_uboot_count}" = "x" ] ; then dd_uboot="${dd_uboot}count=${dd_uboot_count} " fi if [ ! "x${dd_uboot_seek}" = "x" ] ; then dd_uboot="${dd_uboot}seek=${dd_uboot_seek} " fi if [ ! "x${dd_uboot_conf}" = "x" ] ; then dd_uboot="${dd_uboot}conv=${dd_uboot_conf} " fi if [ ! "x${dd_uboot_bs}" = "x" ] ; then dd_uboot="${dd_uboot}bs=${dd_uboot_bs}" fi message="dd if=${dd_spl_uboot_backup} of=${destination} ${dd_spl_uboot}" ; broadcast echo "-----------------------------" dd if=${dd_spl_uboot_backup} of=${destination} ${dd_spl_uboot} echo "-----------------------------" message="dd if=${dd_uboot_backup} of=${destination} ${dd_uboot}" ; broadcast echo "-----------------------------" dd if=${dd_uboot_backup} of=${destination} ${dd_uboot} message="-----------------------------" ; broadcast } format_boot () { message="mkfs.vfat -F 16 ${destination}p1 -n ${boot_label}" ; broadcast echo "-----------------------------" LC_ALL=C mkfs.vfat -F 16 ${destination}p1 -n ${boot_label} echo "-----------------------------" flush_cache } format_root () { message="mkfs.ext4 ${ext4_options} ${destination}p2 -L ${rootfs_label}" ; broadcast echo "-----------------------------" LC_ALL=C mkfs.ext4 ${ext4_options} ${destination}p2 -L ${rootfs_label} echo "-----------------------------" flush_cache } format_single_root () { message="mkfs.ext4 ${ext4_options} ${destination}p1 -L ${boot_label}" ; broadcast echo "-----------------------------" LC_ALL=C mkfs.ext4 ${ext4_options} ${destination}p1 -L ${boot_label} echo "-----------------------------" flush_cache } copy_boot () { message="Copying: ${source}p1 -> ${destination}p1" ; broadcast mkdir -p /tmp/boot/ || true mount ${destination}p1 /tmp/boot/ -o sync if [ -f /boot/uboot/MLO ] ; then #Make sure the BootLoader gets copied first: cp -v /boot/uboot/MLO /tmp/boot/MLO || write_failure flush_cache cp -v /boot/uboot/u-boot-dtb.img /tmp/boot/u-boot-dtb.img || write_failure flush_cache fi message="rsync: /boot/uboot/ -> /tmp/boot/" ; broadcast rsync -aAXx /boot/uboot/ /tmp/boot/ --exclude={MLO,u-boot-dtb.img,uEnv.txt} || write_failure flush_cache flush_cache umount /tmp/boot/ || umount -l /tmp/boot/ || write_failure flush_cache umount /boot/uboot || umount -l /boot/uboot || true } copy_rootfs () { message="Copying: ${source}p${media_rootfs} -> ${destination}p${media_rootfs}" ; broadcast mkdir -p /tmp/rootfs/ || true mount ${destination}p${media_rootfs} /tmp/rootfs/ -o async,noatime message="rsync: / -> /tmp/rootfs/" ; broadcast rsync -aAXx /* /tmp/rootfs/ --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/media/*,/lost+found,/lib/modules/*,/uEnv.txt} || write_failure flush_cache if [ -d /tmp/rootfs/etc/ssh/ ] ; then #ssh keys will now get regenerated on the next bootup touch /tmp/rootfs/etc/ssh/ssh.regenerate flush_cache fi mkdir -p /tmp/rootfs/lib/modules/$(uname -r)/ || true message="Copying: Kernel modules" ; broadcast message="rsync: /lib/modules/$(uname -r)/ -> /tmp/rootfs/lib/modules/$(uname -r)/" ; broadcast rsync -aAXx /lib/modules/$(uname -r)/* /tmp/rootfs/lib/modules/$(uname -r)/ || write_failure flush_cache message="Copying: ${source}p${media_rootfs} -> ${destination}p${media_rootfs} complete" ; broadcast message="-----------------------------" ; broadcast message="Final System Tweaks:" ; broadcast unset root_uuid root_uuid=$(/sbin/blkid -c /dev/null -s UUID -o value ${destination}p${media_rootfs}) if [ "${root_uuid}" ] ; then sed -i -e 's:uuid=:#uuid=:g' /tmp/rootfs/boot/uEnv.txt echo "uuid=${root_uuid}" >> /tmp/rootfs/boot/uEnv.txt message="UUID=${root_uuid}" ; broadcast root_uuid="UUID=${root_uuid}" else #really a failure... root_uuid="${source}p${media_rootfs}" fi message="Generating: /etc/fstab" ; broadcast echo "# /etc/fstab: static file system information." > /tmp/rootfs/etc/fstab echo "#" >> /tmp/rootfs/etc/fstab echo "${root_uuid} / ext4 noatime,errors=remount-ro 0 1" >> /tmp/rootfs/etc/fstab echo "debugfs /sys/kernel/debug debugfs defaults 0 0" >> /tmp/rootfs/etc/fstab cat /tmp/rootfs/etc/fstab #message="/boot/uEnv.txt: disabling eMMC flasher script" ; broadcast #script="cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh" #sed -i -e 's:'$script':#'$script':g' /tmp/rootfs/boot/uEnv.txt #cat /tmp/rootfs/boot/uEnv.txt message="-----------------------------" ; broadcast flush_cache umount /tmp/rootfs/ || umount -l /tmp/rootfs/ || write_failure message="Syncing: ${destination}" ; broadcast #https://github.com/beagleboard/meta-beagleboard/blob/master/contrib/bone-flash-tool/emmc.sh#L158-L159 # force writeback of eMMC buffers sync dd if=${destination} of=/dev/null count=100000 message="Syncing: ${destination} complete" ; broadcast message="-----------------------------" ; broadcast if [ -f /boot/debug.txt ] ; then message="This script has now completed its task" ; broadcast message="-----------------------------" ; broadcast message="debug: enabled" ; broadcast inf_loop else mount message="eMMC has been flashed:" ; broadcast message="-----------------------------" ; broadcast flush_cache fi } partition_drive () { message="Erasing: ${destination}" ; broadcast flush_cache dd if=/dev/zero of=${destination} bs=1M count=108 sync dd if=${destination} of=/dev/null bs=1M count=108 sync flush_cache message="Erasing: ${destination} complete" ; broadcast message="-----------------------------" ; broadcast if [ -f /boot/SOC.sh ] ; then . /boot/SOC.sh fi #Debian Stretch; mfks.ext4 default to metadata_csum,64bit disable till u-boot works again.. unset ext4_options unset test_mke2fs LC_ALL=C mkfs.ext4 -V &> /tmp/mkfs test_mkfs=$(cat /tmp/mkfs | grep mke2fs | grep 1.43 || true) if [ "x${test_mkfs}" = "x" ] ; then ext4_options="${mkfs_options}" else ext4_options="${mkfs_options} -O ^metadata_csum,^64bit" fi if [ "x${dd_spl_uboot_backup}" = "x" ] ; then spl_uboot_name=MLO dd_spl_uboot_count="2" dd_spl_uboot_seek="1" dd_spl_uboot_conf="" dd_spl_uboot_bs="128k" dd_spl_uboot_backup=/opt/backup/uboot/MLO echo "spl_uboot_name=${spl_uboot_name}" >> /boot/SOC.sh echo "dd_spl_uboot_count=2" >> /boot/SOC.sh echo "dd_spl_uboot_seek=1" >> /boot/SOC.sh echo "dd_spl_uboot_conf=" >> /boot/SOC.sh echo "dd_spl_uboot_bs=128k" >> /boot/SOC.sh echo "dd_spl_uboot_name=${dd_spl_uboot_name}" >> /boot/SOC.sh fi if [ ! -f /opt/backup/uboot/MLO ] ; then echo "[ERROR] MLO was not copied [https://forum.digikey.com/t/debian-getting-started-with-the-beaglebone-black/12967]" exit 2 fi if [ "x${dd_uboot_backup}" = "x" ] ; then uboot_name=u-boot-dtb.img dd_uboot_count="4" dd_uboot_seek="1" dd_uboot_conf="" dd_uboot_bs="384k" dd_uboot_backup=/opt/backup/uboot/u-boot-dtb.img echo "uboot_name=${uboot_name}" >> /boot/SOC.sh echo "dd_uboot_count=4" >> /boot/SOC.sh echo "dd_uboot_seek=1" >> /boot/SOC.sh echo "dd_uboot_conf=" >> /boot/SOC.sh echo "dd_uboot_bs=384k" >> /boot/SOC.sh echo "boot_name=u-boot-dtb.img" >> /boot/SOC.sh echo "dd_uboot_name=${dd_uboot_name}" >> /boot/SOC.sh fi if [ ! -f /opt/backup/uboot/u-boot-dtb.img ] ; then echo "[ERROR] u-boot-dtb.img was not copied [https://forum.digikey.com/t/debian-getting-started-with-the-beaglebone-black/12967]" exit 2 fi dd_bootloader boot_fstype="ext4" if [ "x${boot_fstype}" = "xfat" ] ; then conf_boot_startmb=${conf_boot_startmb:-"4"} conf_boot_endmb=${conf_boot_endmb:-"96"} sfdisk_fstype=${sfdisk_fstype:-"0xE"} boot_label=${boot_label:-"BEAGLEBONE"} rootfs_label=${rootfs_label:-"rootfs"} message="Formatting: ${destination}" ; broadcast sfdisk_options="--force --Linux --in-order --unit M" sfdisk_boot_startmb="${conf_boot_startmb}" sfdisk_boot_size_mb="${conf_boot_endmb}" sfdisk_rootfs_startmb=$(($sfdisk_boot_startmb + $sfdisk_boot_size_mb)) test_sfdisk=$(LC_ALL=C sfdisk --help | grep -m 1 -e "--in-order" || true) if [ "x${test_sfdisk}" = "x" ] ; then message="sfdisk: [2.26.x or greater]" ; broadcast sfdisk_options="--force" sfdisk_boot_startmb="${sfdisk_boot_startmb}M" sfdisk_boot_size_mb="${sfdisk_boot_size_mb}M" sfdisk_rootfs_startmb="${sfdisk_rootfs_startmb}M" fi message="sfdisk: [sfdisk ${sfdisk_options} ${destination}]" ; broadcast message="sfdisk: [${sfdisk_boot_startmb},${sfdisk_boot_size_mb},${sfdisk_fstype},*]" ; broadcast message="sfdisk: [${sfdisk_rootfs_startmb},,,-]" ; broadcast LC_ALL=C sfdisk ${sfdisk_options} "${destination}" <<-__EOF__ ${sfdisk_boot_startmb},${sfdisk_boot_size_mb},${sfdisk_fstype},* ${sfdisk_rootfs_startmb},,,- __EOF__ flush_cache format_boot format_root message="Formatting: ${destination} complete" ; broadcast message="-----------------------------" ; broadcast copy_boot media_rootfs="2" copy_rootfs else conf_boot_startmb=${conf_boot_startmb:-"4"} sfdisk_fstype=${sfdisk_fstype:-"L"} if [ "x${sfdisk_fstype}" = "x0x83" ] ; then sfdisk_fstype="L" fi boot_label=${boot_label:-"BEAGLEBONE"} if [ "x${boot_label}" = "xBOOT" ] ; then boot_label="rootfs" fi message="Formatting: ${destination}" ; broadcast sfdisk_options="--force --Linux --in-order --unit M" sfdisk_boot_startmb="${conf_boot_startmb}" test_sfdisk=$(LC_ALL=C sfdisk --help | grep -m 1 -e "--in-order" || true) if [ "x${test_sfdisk}" = "x" ] ; then message="sfdisk: [2.26.x or greater]" ; broadcast if [ "x${bootrom_gpt}" = "xenable" ] ; then sfdisk_options="--force --label gpt" else sfdisk_options="--force" fi sfdisk_boot_startmb="${sfdisk_boot_startmb}M" fi message="sfdisk: [$(LC_ALL=C sfdisk --version)]" ; broadcast message="sfdisk: [sfdisk ${sfdisk_options} ${destination}]" ; broadcast message="sfdisk: [${sfdisk_boot_startmb},,${sfdisk_fstype},*]" ; broadcast LC_ALL=C sfdisk ${sfdisk_options} "${destination}" <<-__EOF__ ${sfdisk_boot_startmb},,${sfdisk_fstype},* __EOF__ flush_cache format_single_root message="Formatting: ${destination} complete" ; broadcast message="-----------------------------" ; broadcast media_rootfs="1" copy_rootfs fi } clear message="-----------------------------" ; broadcast message="Version: [${version_message}]" ; broadcast message="-----------------------------" ; broadcast check_running_system partition_drive #