1#!/bin/bash 2# 3# Copyright (C) 2021 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18set -e 19set -u 20 21SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) 22 23. $SCRIPT_DIR/bullseye-common.sh 24 25sed -i "s,debian,rockpi," /etc/hosts 26sed -i "s,debian,rockpi," /etc/hostname 27 28# Build U-Boot FIT based on the Debian initrd 29if [[ "${embed_kernel_initrd_dtb}" = "1" ]]; then 30 mkimage -f auto -A arm64 -O linux -T kernel -C none -a 0x02080000 \ 31 -d /boot/vmlinuz-$(uname -r) -i /boot/initrd.img-$(uname -r) \ 32 -b /boot/dtb/rockchip/rk3399-rock-pi-4b.dtb /boot/boot.fit 33fi 34 35# Write U-Boot script to /boot 36cat >/boot/boot.cmd <<"EOF" 37setenv start_poe 'gpio set 150; gpio clear 146' 38run start_poe 39setenv bootcmd_dhcp ' 40mw.b ${scriptaddr} 0 0x8000 41mmc dev 0 0 42mmc read ${scriptaddr} 0x1fc0 0x40 43env import -b ${scriptaddr} 0x8000 44mw.b ${scriptaddr} 0 0x8000 45if dhcp ${scriptaddr} manifest.txt; then 46 setenv OldSha ${Sha} 47 setenv Sha 48 env import -t ${scriptaddr} 0x8000 ManifestVersion 49 echo "Manifest version $ManifestVersion"; 50 if test "$ManifestVersion" = "1"; then 51 run manifest1 52 elif test "$ManifestVersion" = "2"; then 53 run manifest2 54 elif test "$ManifestVersion" = "3"; then 55 run manifest3 56 else 57 run manifestX 58 fi 59fi' 60setenv manifestX 'echo "***** ERROR: Unknown manifest version! *****";' 61setenv manifest1 ' 62env import -t ${scriptaddr} 0x8000 63if test "$Sha" != "$OldSha"; then 64 setenv serverip ${TftpServer} 65 setenv loadaddr 0x00200000 66 mmc dev 0 0; 67 setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg 68 setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb 69 setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg 70 setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg 71 setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv 72 mw.b ${scriptaddr} 0 0x8000 73 env export -b ${scriptaddr} 0x8000 74 mmc write ${scriptaddr} 0x1fc0 0x40 75else 76 echo "Already have ${Sha}. Booting..." 77fi' 78setenv manifest2 ' 79env import -t ${scriptaddr} 0x8000 80if test "$DFUethaddr" = "$ethaddr" || test "$DFUethaddr" = ""; then 81 if test "$Sha" != "$OldSha"; then 82 setenv serverip ${TftpServer} 83 setenv loadaddr 0x00200000 84 mmc dev 0 0; 85 setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg 86 setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb 87 setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg 88 setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg 89 setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv 90 mw.b ${scriptaddr} 0 0x8000 91 env export -b ${scriptaddr} 0x8000 92 mmc write ${scriptaddr} 0x1fc0 0x40 93 else 94 echo "Already have ${Sha}. Booting..." 95 fi 96else 97 echo "Update ${Sha} is not for me. Booting..." 98fi' 99setenv manifest3 ' 100env import -t ${scriptaddr} 0x8000 101if test "$DFUethaddr" = "$ethaddr" || test "$DFUethaddr" = ""; then 102 if test "$Sha" != "$OldSha"; then 103 setenv serverip ${TftpServer} 104 setenv loadaddr 0x00200000 105 mmc dev 0 0; 106 setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg 107 setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv 108 setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb 109 setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg 110 setenv file $EspImg; offset=0x8000; size=0x40000; run tftpget1; setenv EspImg 111 setenv file $RootfsImg; offset=0x48000; size=0; run tftpget1; setenv RootfsImg 112 mw.b ${scriptaddr} 0 0x8000 113 env export -b ${scriptaddr} 0x8000 114 mmc write ${scriptaddr} 0x1fc0 0x40 115 else 116 echo "Already have ${Sha}. Booting..." 117 fi 118else 119 echo "Update ${Sha} is not for me. Booting..." 120fi' 121setenv tftpget1 ' 122if test "$file" != ""; then 123 mw.b ${loadaddr} 0 0x400000 124 tftp ${file} 125 if test $? = 0; then 126 setenv isGz 0 && setexpr isGz sub .*\\.gz\$ 1 ${file} 127 if test $isGz = 1; then 128 if test ${file} = ${UbootEnv}; then 129 echo "** gzipped env unsupported **" 130 else 131 setexpr boffset ${offset} * 0x200 132 gzwrite mmc 0 ${loadaddr} 0x${filesize} 100000 ${boffset} && echo Updated: ${file} 133 fi 134 elif test ${file} = ${UbootEnv}; then 135 env import -b ${loadaddr} && echo Updated: ${file} 136 else 137 if test $size = 0; then 138 setexpr x $filesize - 1 139 setexpr x $x / 0x1000 140 setexpr x $x + 1 141 setexpr x $x * 0x1000 142 setexpr x $x / 0x200 143 size=0x${x} 144 fi 145 mmc write ${loadaddr} ${offset} ${size} && echo Updated: ${file} 146 fi 147 fi 148 if test $? != 0; then 149 echo ** UPDATE FAILED: ${file} ** 150 fi 151fi' 152if mmc dev 1 0; then; else 153 run bootcmd_dhcp; 154fi 155if bcb load 0 misc; then 156 # valid BCB found 157 if bcb test command = bootonce-bootloader; then 158 bcb clear command; bcb store 159 setenv autoload no; dhcp 160 fastboot udp 161 reset 162 elif bcb test command = boot-recovery; then 163 bcb clear command; bcb store 164 # we don't have recovery, reboot. 165 reset 166 fi 167fi 168if test -e mmc ${devnum}:${distro_bootpart} /boot/rootfs.gz; then 169 setenv loadaddr 0x00200000 170 mw.b ${loadaddr} 0 0x400000 171 load mmc ${devnum}:${distro_bootpart} ${loadaddr} /boot/rootfs.gz 172 gzwrite mmc ${devnum} ${loadaddr} 0x${filesize} 100000 0x9100000 173fi 174load mmc ${devnum}:${distro_bootpart} 0x06080000 /boot/boot.fit 175setenv bootargs "net.ifnames=0 8250.nr_uarts=4 earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 kvm-arm.mode=nvhe sdhci.debug_quirks=0x20000000 root=LABEL=ROOT" 176bootm 0x06080000 177EOF 178mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr 179 180# Write control script for PoE hat 181cat >/usr/local/bin/poe <<"EOF" 182#!/bin/bash 183 184if [ "$1" == "--start" ]; then 185 echo 146 > /sys/class/gpio/export 186 echo out > /sys/class/gpio/gpio146/direction 187 echo 0 > /sys/class/gpio/gpio146/value 188 echo 150 > /sys/class/gpio/export 189 echo out > /sys/class/gpio/gpio150/direction 190 echo 1 > /sys/class/gpio/gpio150/value 191 exit 0 192fi 193 194if [ "$1" == "--stop" ]; then 195 echo 0 > /sys/class/gpio/gpio146/value 196 echo 146 > /sys/class/gpio/unexport 197 echo 0 > /sys/class/gpio/gpio150/value 198 echo 150 > /sys/class/gpio/unexport 199 exit 0 200fi 201 202if [ ! -e /sys/class/gpio/gpio146/value ] || [ ! -e /sys/class/gpio/gpio150/value ]; then 203 echo "error: PoE service not initialized" 204 exit 1 205fi 206 207if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then 208 echo 0 > /sys/class/gpio/gpio150/value 209 exit 0 210fi 211 212if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then 213 echo 1 > /sys/class/gpio/gpio150/value 214 exit 0 215fi 216 217echo "usage: poe <0|1>" 218exit 1 219EOF 220chmod a+x /usr/local/bin/poe 221 222# Write service to start PoE control script 223cat >/etc/systemd/system/poe.service <<EOF 224[Unit] 225Description=PoE service 226ConditionPathExists=/usr/local/bin/poe 227 228[Service] 229Type=oneshot 230ExecStart=/usr/local/bin/poe --start 231ExecStop=/usr/local/bin/poe --stop 232RemainAfterExit=true 233StandardOutput=journal 234 235[Install] 236WantedBy=multi-user.target 237EOF 238 239# Write control script for status LEDs 240cat >/usr/local/bin/led <<"EOF" 241#!/bin/bash 242 243if [ "$1" == "--start" ]; then 244 echo 125 > /sys/class/gpio/export 245 echo out > /sys/class/gpio/gpio125/direction 246 chmod 666 /sys/class/gpio/gpio125/value 247 echo 0 > /sys/class/gpio/gpio125/value 248 exit 0 249fi 250 251if [ "$1" == "--stop" ]; then 252 echo 0 > /sys/class/gpio/gpio125/value 253 echo 125 > /sys/class/gpio/unexport 254 exit 0 255fi 256 257if [ ! -e /sys/class/gpio/gpio125/value ]; then 258 echo "error: led service not initialized" 259 exit 1 260fi 261 262if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then 263 echo 0 > /sys/class/gpio/gpio125/value 264 exit 0 265fi 266 267if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then 268 echo 1 > /sys/class/gpio/gpio125/value 269 exit 0 270fi 271 272echo "usage: led <0|1>" 273exit 1 274EOF 275chmod a+x /usr/local/bin/led 276 277# Write service to start LED control script 278cat >/etc/systemd/system/led.service <<EOF 279[Unit] 280Description=led service 281ConditionPathExists=/usr/local/bin/led 282 283[Service] 284Type=oneshot 285ExecStart=/usr/local/bin/led --start 286ExecStop=/usr/local/bin/led --stop 287RemainAfterExit=true 288StandardOutput=journal 289 290[Install] 291WantedBy=multi-user.target 292EOF 293 294# Write control script for one-time SD-Card->eMMC duplication 295cat >/usr/local/bin/sd-dupe <<"EOF" 296#!/bin/bash 297led 0 298 299src_dev=mmcblk0 300dest_dev=mmcblk1 301part_num=p7 302 303if [ -e "/dev/${src_dev}" ] && [ -e "/dev/${dest_dev}" ]; then 304 led 1 305 306 sgdisk -Z /dev/${dest_dev} 307 308 sgdisk -a1 -n:1:64:8127 -t:1:8301 -c:1:idbloader /dev/${dest_dev} 309 sgdisk -a1 -n:2:8128:+64 -t:2:8301 -c:2:uboot_env /dev/${dest_dev} 310 sgdisk -n:3:8M:+4M -t:3:8301 -c:3:uboot /dev/${dest_dev} 311 sgdisk -n:4:12M:+4M -t:4:8301 -c:4:trust /dev/${dest_dev} 312 sgdisk -n:5:16M:+1M -t:5:8301 -c:5:misc /dev/${dest_dev} 313 sgdisk -n:6:17M:+128M -t:6:ef00 -c:6:esp -A:6:set:0 /dev/${dest_dev} 314 sgdisk -n:7:145M:0 -t:7:8305 -c:7:rootfs -A:7:set:2 /dev/${dest_dev} 315 316 src_block_count=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block count:" | sed 's/.*: *//') 317 src_block_size=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block size:" | sed 's/.*: *//') 318 src_fs_size=$(( src_block_count*src_block_size )) 319 src_fs_size_m=$(( src_fs_size / 1024 / 1024 + 1 )) 320 321 dd if=/dev/${src_dev}p1 of=/dev/${dest_dev}p1 conv=sync,noerror status=progress 322 dd if=/dev/${src_dev}p2 of=/dev/${dest_dev}p2 conv=sync,noerror status=progress 323 dd if=/dev/${src_dev}p3 of=/dev/${dest_dev}p3 conv=sync,noerror status=progress 324 dd if=/dev/${src_dev}p4 of=/dev/${dest_dev}p4 conv=sync,noerror status=progress 325 dd if=/dev/${src_dev}p5 of=/dev/${dest_dev}p5 conv=sync,noerror status=progress 326 327 echo "Writing ${src_fs_size_m} MB: /dev/${src_dev} -> /dev/${dest_dev}..." 328 dd if=/dev/${src_dev}${part_num} of=/dev/${dest_dev}${part_num} bs=1M conv=sync,noerror status=progress 329 330 echo "Expanding /dev/${dest_dev}${part_num} filesystem..." 331 e2fsck -fy /dev/${dest_dev}${part_num} 332 resize2fs /dev/${dest_dev}${part_num} 333 tune2fs -O has_journal /dev/${dest_dev}${part_num} 334 e2fsck -fy /dev/${dest_dev}${part_num} 335 sync /dev/${dest_dev} 336 337 echo "Cleaning up..." 338 mount /dev/${dest_dev}${part_num} /media 339 chroot /media /usr/local/bin/install-cleanup 340 341 if [ $? == 0 ]; then 342 echo "Successfully copied Rock Pi image!" 343 while true; do 344 led 1; sleep 0.5 345 led 0; sleep 0.5 346 done 347 else 348 echo "Error while copying Rock Pi image" 349 while true; do 350 led 1; sleep 0.1 351 led 0; sleep 0.1 352 done 353 fi 354else 355 echo "Expanding /dev/${dest_dev}${part_num} filesystem..." 356 e2fsck -fy /dev/${dest_dev}${part_num} 357 resize2fs /dev/${dest_dev}${part_num} 358 tune2fs -O has_journal /dev/${dest_dev}${part_num} 359 e2fsck -fy /dev/${dest_dev}${part_num} 360 sync /dev/${dest_dev} 361 362 echo "Cleaning up..." 363 /usr/local/bin/install-cleanup 364fi 365EOF 366chmod a+x /usr/local/bin/sd-dupe 367 368# Write one-shot service for SDCard->eMMC duplication 369cat >/etc/systemd/system/sd-dupe.service <<EOF 370[Unit] 371Description=Duplicate SD card rootfs to eMMC on Rock Pi 372ConditionPathExists=/usr/local/bin/sd-dupe 373After=led.service 374 375[Service] 376Type=simple 377ExecStart=/usr/local/bin/sd-dupe 378TimeoutSec=0 379StandardOutput=tty 380 381[Install] 382WantedBy=multi-user.target 383EOF 384 385# Write cleanup script for eMMC (after duplication) 386cat >/usr/local/bin/install-cleanup <<"EOF" 387#!/bin/bash 388MAC=$(ip link | grep eth0 -A1 | grep ether | sed 's/.*\(..:..:..:..:..:..\) .*/\1/' | tr -d :) 389sed -i "s,rockpi,rockpi-${MAC}," /etc/hosts 390sudo hostnamectl set-hostname "rockpi-${MAC}" 391 392rm -f /etc/machine-id 393rm -f /var/lib/dbus/machine-id 394dbus-uuidgen --ensure 395systemd-machine-id-setup 396 397systemctl disable sd-dupe 398rm -f /etc/systemd/system/sd-dupe.service 399rm -f /usr/local/bin/sd-dupe 400rm -f /usr/local/bin/install-cleanup 401EOF 402chmod a+x /usr/local/bin/install-cleanup 403 404systemctl enable poe 405systemctl enable led 406systemctl enable sd-dupe 407 408setup_dynamic_networking "eth0" "" 409 410update_apt_sources bullseye "" 411 412setup_cuttlefish_user 413 414setup_and_build_cuttlefish 415setup_and_build_iptables 416 417install_and_cleanup_cuttlefish 418install_and_cleanup_iptables 419 420create_systemd_getty_symlinks ttyS2 421 422setup_grub "net.ifnames=0 8250.nr_uarts=4 earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 kvm-arm.mode=nvhe sdhci.debug_quirks=0x20000000" 423 424apt-get purge -y vim-tiny 425rm -f /etc/network/interfaces.d/eth0.conf 426bullseye_cleanup 427