#!/bin/bash # # Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set -e set -u SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) . $SCRIPT_DIR/bullseye-common.sh sed -i "s,debian,rockpi," /etc/hosts sed -i "s,debian,rockpi," /etc/hostname # Build U-Boot FIT based on the Debian initrd if [ -n "${embed_kernel_initrd_dtb}" ]; then mkimage -f auto -A arm64 -O linux -T kernel -C none -a 0x02080000 \ -d /boot/vmlinuz-$(uname -r) -i /boot/initrd.img-$(uname -r) \ -b /boot/dtb/rockchip/rk3399-rock-pi-4b.dtb /boot/boot.fit fi # Write U-Boot script to /boot cat >/boot/boot.cmd <<"EOF" setenv start_poe 'gpio set 150; gpio clear 146' run start_poe setenv bootcmd_dhcp ' mw.b ${scriptaddr} 0 0x8000 mmc dev 0 0 mmc read ${scriptaddr} 0x1fc0 0x40 env import -b ${scriptaddr} 0x8000 mw.b ${scriptaddr} 0 0x8000 if dhcp ${scriptaddr} manifest.txt; then setenv OldSha ${Sha} setenv Sha env import -t ${scriptaddr} 0x8000 ManifestVersion echo "Manifest version $ManifestVersion"; if test "$ManifestVersion" = "1"; then run manifest1 elif test "$ManifestVersion" = "2"; then run manifest2 else run manifestX fi fi' setenv manifestX 'echo "***** ERROR: Unknown manifest version! *****";' setenv manifest1 ' env import -t ${scriptaddr} 0x8000 if test "$Sha" != "$OldSha"; then setenv serverip ${TftpServer} setenv loadaddr 0x00200000 mmc dev 0 0; setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv mw.b ${scriptaddr} 0 0x8000 env export -b ${scriptaddr} 0x8000 mmc write ${scriptaddr} 0x1fc0 0x40 else echo "Already have ${Sha}. Booting..." fi' setenv manifest2 ' env import -t ${scriptaddr} 0x8000 if test "$DFUethaddr" = "$ethaddr" || test "$DFUethaddr" = ""; then if test "$Sha" != "$OldSha"; then setenv serverip ${TftpServer} setenv loadaddr 0x00200000 mmc dev 0 0; setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv mw.b ${scriptaddr} 0 0x8000 env export -b ${scriptaddr} 0x8000 mmc write ${scriptaddr} 0x1fc0 0x40 else echo "Already have ${Sha}. Booting..." fi else echo "Update ${Sha} is not for me. Booting..." fi' setenv tftpget1 ' if test "$file" != ""; then mw.b ${loadaddr} 0 0x400000 tftp ${file} if test $? = 0; then setenv isGz 0 && setexpr isGz sub .*\\.gz\$ 1 ${file} if test $isGz = 1; then if test ${file} = ${UbootEnv}; then echo "** gzipped env unsupported **" else setexpr boffset ${offset} * 0x200 gzwrite mmc 0 ${loadaddr} 0x${filesize} 100000 ${boffset} && echo Updated: ${file} fi elif test ${file} = ${UbootEnv}; then env import -b ${loadaddr} && echo Updated: ${file} else if test $size = 0; then setexpr x $filesize - 1 setexpr x $x / 0x1000 setexpr x $x + 1 setexpr x $x * 0x1000 setexpr x $x / 0x200 size=0x${x} fi mmc write ${loadaddr} ${offset} ${size} && echo Updated: ${file} fi fi if test $? != 0; then echo ** UPDATE FAILED: ${file} ** fi fi' if mmc dev 1 0; then; else run bootcmd_dhcp; fi if test -e mmc ${devnum}:${distro_bootpart} /boot/rootfs.gz; then setenv loadaddr 0x00200000 mw.b ${loadaddr} 0 0x400000 load mmc ${devnum}:${distro_bootpart} ${loadaddr} /boot/rootfs.gz gzwrite mmc ${devnum} ${loadaddr} 0x${filesize} 100000 0x1000000 fi load mmc ${devnum}:${distro_bootpart} 0x06080000 /boot/boot.fit setenv bootargs "8250.nr_uarts=4 earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 sdhci.debug_quirks=0x20000000 root=LABEL=ROOT" bootm 0x06080000 EOF mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr # Write control script for PoE hat cat >/usr/local/bin/poe <<"EOF" #!/bin/bash if [ "$1" == "--start" ]; then echo 146 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio146/direction echo 0 > /sys/class/gpio/gpio146/value echo 150 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio150/direction echo 1 > /sys/class/gpio/gpio150/value exit 0 fi if [ "$1" == "--stop" ]; then echo 0 > /sys/class/gpio/gpio146/value echo 146 > /sys/class/gpio/unexport echo 0 > /sys/class/gpio/gpio150/value echo 150 > /sys/class/gpio/unexport exit 0 fi if [ ! -e /sys/class/gpio/gpio146/value ] || [ ! -e /sys/class/gpio/gpio150/value ]; then echo "error: PoE service not initialized" exit 1 fi if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then echo 0 > /sys/class/gpio/gpio150/value exit 0 fi if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then echo 1 > /sys/class/gpio/gpio150/value exit 0 fi echo "usage: poe <0|1>" exit 1 EOF chmod a+x /usr/local/bin/poe # Write service to start PoE control script cat >/etc/systemd/system/poe.service </usr/local/bin/led <<"EOF" #!/bin/bash if [ "$1" == "--start" ]; then echo 125 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio125/direction chmod 666 /sys/class/gpio/gpio125/value echo 0 > /sys/class/gpio/gpio125/value exit 0 fi if [ "$1" == "--stop" ]; then echo 0 > /sys/class/gpio/gpio125/value echo 125 > /sys/class/gpio/unexport exit 0 fi if [ ! -e /sys/class/gpio/gpio125/value ]; then echo "error: led service not initialized" exit 1 fi if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then echo 0 > /sys/class/gpio/gpio125/value exit 0 fi if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then echo 1 > /sys/class/gpio/gpio125/value exit 0 fi echo "usage: led <0|1>" exit 1 EOF chmod a+x /usr/local/bin/led # Write service to start LED control script cat >/etc/systemd/system/led.service <eMMC duplication cat >/usr/local/bin/sd-dupe <<"EOF" #!/bin/bash led 0 src_dev=mmcblk0 dest_dev=mmcblk1 part_num=p5 if [ -e /dev/mmcblk0p5 ] && [ -e /dev/mmcblk1p5 ]; then led 1 sgdisk -Z -a1 /dev/${dest_dev} sgdisk -a1 -n:1:64:8127 -t:1:8301 -c:1:loader1 /dev/${dest_dev} sgdisk -a1 -n:2:8128:8191 -t:2:8301 -c:2:env /dev/${dest_dev} sgdisk -a1 -n:3:16384:24575 -t:3:8301 -c:3:loader2 /dev/${dest_dev} sgdisk -a1 -n:4:24576:32767 -t:4:8301 -c:4:trust /dev/${dest_dev} sgdisk -a1 -n:5:32768:- -A:5:set:2 -t:5:8305 -c:5:rootfs /dev/${dest_dev} src_block_count=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block count:" | sed 's/.*: *//') src_block_size=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block size:" | sed 's/.*: *//') src_fs_size=$(( src_block_count*src_block_size )) src_fs_size_m=$(( src_fs_size / 1024 / 1024 + 1 )) dd if=/dev/${src_dev}p1 of=/dev/${dest_dev}p1 conv=sync,noerror status=progress dd if=/dev/${src_dev}p2 of=/dev/${dest_dev}p2 conv=sync,noerror status=progress dd if=/dev/${src_dev}p3 of=/dev/${dest_dev}p3 conv=sync,noerror status=progress dd if=/dev/${src_dev}p4 of=/dev/${dest_dev}p4 conv=sync,noerror status=progress echo "Writing ${src_fs_size_m} MB: /dev/${src_dev} -> /dev/${dest_dev}..." dd if=/dev/${src_dev}${part_num} of=/dev/${dest_dev}${part_num} bs=1M conv=sync,noerror status=progress echo "Expanding /dev/${dest_dev}${part_num} filesystem..." e2fsck -fy /dev/${dest_dev}${part_num} resize2fs /dev/${dest_dev}${part_num} tune2fs -O has_journal /dev/${dest_dev}${part_num} e2fsck -fy /dev/${dest_dev}${part_num} sync /dev/${dest_dev} echo "Cleaning up..." mount /dev/${dest_dev}${part_num} /media chroot /media /usr/local/bin/install-cleanup if [ $? == 0 ]; then echo "Successfully copied Rock Pi image!" while true; do led 1; sleep 0.5 led 0; sleep 0.5 done else echo "Error while copying Rock Pi image" while true; do led 1; sleep 0.1 led 0; sleep 0.1 done fi else echo "Expanding /dev/${dest_dev}${part_num} filesystem..." e2fsck -fy /dev/${dest_dev}${part_num} resize2fs /dev/${dest_dev}${part_num} tune2fs -O has_journal /dev/${dest_dev}${part_num} e2fsck -fy /dev/${dest_dev}${part_num} sync /dev/${dest_dev} echo "Cleaning up..." /usr/local/bin/install-cleanup fi EOF chmod a+x /usr/local/bin/sd-dupe # Write one-shot service for SDCard->eMMC duplication cat >/etc/systemd/system/sd-dupe.service </usr/local/bin/install-cleanup <<"EOF" #!/bin/bash MAC=$(ip link | grep eth0 -A1 | grep ether | sed 's/.*\(..:..:..:..:..:..\) .*/\1/' | tr -d :) sed -i "s,rockpi,rockpi-${MAC}," /etc/hosts sudo hostnamectl set-hostname "rockpi-${MAC}" rm -f /etc/machine-id rm -f /var/lib/dbus/machine-id dbus-uuidgen --ensure systemd-machine-id-setup systemctl disable sd-dupe rm -f /etc/systemd/system/sd-dupe.service rm -f /usr/local/bin/sd-dupe rm -f /usr/local/bin/install-cleanup EOF chmod a+x /usr/local/bin/install-cleanup systemctl enable poe systemctl enable led systemctl enable sd-dupe setup_dynamic_networking "en*" "" update_apt_sources bullseye setup_cuttlefish_user setup_and_build_cuttlefish setup_and_build_iptables install_and_cleanup_cuttlefish install_and_cleanup_iptables create_systemd_getty_symlinks ttyS0 hvc1 apt-get purge -y vim-tiny bullseye_cleanup