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 [ -n "${embed_kernel_initrd_dtb}" ]; 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 else 55 run manifestX 56 fi 57fi' 58setenv manifestX 'echo "***** ERROR: Unknown manifest version! *****";' 59setenv manifest1 ' 60env import -t ${scriptaddr} 0x8000 61if test "$Sha" != "$OldSha"; then 62 setenv serverip ${TftpServer} 63 setenv loadaddr 0x00200000 64 mmc dev 0 0; 65 setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg 66 setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb 67 setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg 68 setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg 69 setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv 70 mw.b ${scriptaddr} 0 0x8000 71 env export -b ${scriptaddr} 0x8000 72 mmc write ${scriptaddr} 0x1fc0 0x40 73else 74 echo "Already have ${Sha}. Booting..." 75fi' 76setenv manifest2 ' 77env import -t ${scriptaddr} 0x8000 78if test "$DFUethaddr" = "$ethaddr" || test "$DFUethaddr" = ""; then 79 if test "$Sha" != "$OldSha"; then 80 setenv serverip ${TftpServer} 81 setenv loadaddr 0x00200000 82 mmc dev 0 0; 83 setenv file $TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg 84 setenv file $UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb 85 setenv file $TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg 86 setenv file $RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg 87 setenv file $UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv 88 mw.b ${scriptaddr} 0 0x8000 89 env export -b ${scriptaddr} 0x8000 90 mmc write ${scriptaddr} 0x1fc0 0x40 91 else 92 echo "Already have ${Sha}. Booting..." 93 fi 94else 95 echo "Update ${Sha} is not for me. Booting..." 96fi' 97setenv tftpget1 ' 98if test "$file" != ""; then 99 mw.b ${loadaddr} 0 0x400000 100 tftp ${file} 101 if test $? = 0; then 102 setenv isGz 0 && setexpr isGz sub .*\\.gz\$ 1 ${file} 103 if test $isGz = 1; then 104 if test ${file} = ${UbootEnv}; then 105 echo "** gzipped env unsupported **" 106 else 107 setexpr boffset ${offset} * 0x200 108 gzwrite mmc 0 ${loadaddr} 0x${filesize} 100000 ${boffset} && echo Updated: ${file} 109 fi 110 elif test ${file} = ${UbootEnv}; then 111 env import -b ${loadaddr} && echo Updated: ${file} 112 else 113 if test $size = 0; then 114 setexpr x $filesize - 1 115 setexpr x $x / 0x1000 116 setexpr x $x + 1 117 setexpr x $x * 0x1000 118 setexpr x $x / 0x200 119 size=0x${x} 120 fi 121 mmc write ${loadaddr} ${offset} ${size} && echo Updated: ${file} 122 fi 123 fi 124 if test $? != 0; then 125 echo ** UPDATE FAILED: ${file} ** 126 fi 127fi' 128if mmc dev 1 0; then; else 129 run bootcmd_dhcp; 130fi 131if test -e mmc ${devnum}:${distro_bootpart} /boot/rootfs.gz; then 132 setenv loadaddr 0x00200000 133 mw.b ${loadaddr} 0 0x400000 134 load mmc ${devnum}:${distro_bootpart} ${loadaddr} /boot/rootfs.gz 135 gzwrite mmc ${devnum} ${loadaddr} 0x${filesize} 100000 0x1000000 136fi 137load mmc ${devnum}:${distro_bootpart} 0x06080000 /boot/boot.fit 138setenv bootargs "8250.nr_uarts=4 earlycon=uart8250,mmio32,0xff1a0000 console=ttyS2,1500000n8 loglevel=7 sdhci.debug_quirks=0x20000000 root=LABEL=ROOT" 139bootm 0x06080000 140EOF 141mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr 142 143# Write control script for PoE hat 144cat >/usr/local/bin/poe <<"EOF" 145#!/bin/bash 146 147if [ "$1" == "--start" ]; then 148 echo 146 > /sys/class/gpio/export 149 echo out > /sys/class/gpio/gpio146/direction 150 echo 0 > /sys/class/gpio/gpio146/value 151 echo 150 > /sys/class/gpio/export 152 echo out > /sys/class/gpio/gpio150/direction 153 echo 1 > /sys/class/gpio/gpio150/value 154 exit 0 155fi 156 157if [ "$1" == "--stop" ]; then 158 echo 0 > /sys/class/gpio/gpio146/value 159 echo 146 > /sys/class/gpio/unexport 160 echo 0 > /sys/class/gpio/gpio150/value 161 echo 150 > /sys/class/gpio/unexport 162 exit 0 163fi 164 165if [ ! -e /sys/class/gpio/gpio146/value ] || [ ! -e /sys/class/gpio/gpio150/value ]; then 166 echo "error: PoE service not initialized" 167 exit 1 168fi 169 170if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then 171 echo 0 > /sys/class/gpio/gpio150/value 172 exit 0 173fi 174 175if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then 176 echo 1 > /sys/class/gpio/gpio150/value 177 exit 0 178fi 179 180echo "usage: poe <0|1>" 181exit 1 182EOF 183chmod a+x /usr/local/bin/poe 184 185# Write service to start PoE control script 186cat >/etc/systemd/system/poe.service <<EOF 187[Unit] 188Description=PoE service 189ConditionPathExists=/usr/local/bin/poe 190 191[Service] 192Type=oneshot 193ExecStart=/usr/local/bin/poe --start 194ExecStop=/usr/local/bin/poe --stop 195RemainAfterExit=true 196StandardOutput=journal 197 198[Install] 199WantedBy=multi-user.target 200EOF 201 202# Write control script for status LEDs 203cat >/usr/local/bin/led <<"EOF" 204#!/bin/bash 205 206if [ "$1" == "--start" ]; then 207 echo 125 > /sys/class/gpio/export 208 echo out > /sys/class/gpio/gpio125/direction 209 chmod 666 /sys/class/gpio/gpio125/value 210 echo 0 > /sys/class/gpio/gpio125/value 211 exit 0 212fi 213 214if [ "$1" == "--stop" ]; then 215 echo 0 > /sys/class/gpio/gpio125/value 216 echo 125 > /sys/class/gpio/unexport 217 exit 0 218fi 219 220if [ ! -e /sys/class/gpio/gpio125/value ]; then 221 echo "error: led service not initialized" 222 exit 1 223fi 224 225if [ "$1" == "0" ] || [ "$1" == "off" ] || [ "$1" == "OFF" ]; then 226 echo 0 > /sys/class/gpio/gpio125/value 227 exit 0 228fi 229 230if [ "$1" == "1" ] || [ "$1" == "on" ] || [ "$1" == "ON" ]; then 231 echo 1 > /sys/class/gpio/gpio125/value 232 exit 0 233fi 234 235echo "usage: led <0|1>" 236exit 1 237EOF 238chmod a+x /usr/local/bin/led 239 240# Write service to start LED control script 241cat >/etc/systemd/system/led.service <<EOF 242[Unit] 243Description=led service 244ConditionPathExists=/usr/local/bin/led 245 246[Service] 247Type=oneshot 248ExecStart=/usr/local/bin/led --start 249ExecStop=/usr/local/bin/led --stop 250RemainAfterExit=true 251StandardOutput=journal 252 253[Install] 254WantedBy=multi-user.target 255EOF 256 257# Write control script for one-time SD-Card->eMMC duplication 258cat >/usr/local/bin/sd-dupe <<"EOF" 259#!/bin/bash 260led 0 261 262src_dev=mmcblk0 263dest_dev=mmcblk1 264part_num=p5 265 266if [ -e /dev/mmcblk0p5 ] && [ -e /dev/mmcblk1p5 ]; then 267 led 1 268 269 sgdisk -Z -a1 /dev/${dest_dev} 270 sgdisk -a1 -n:1:64:8127 -t:1:8301 -c:1:loader1 /dev/${dest_dev} 271 sgdisk -a1 -n:2:8128:8191 -t:2:8301 -c:2:env /dev/${dest_dev} 272 sgdisk -a1 -n:3:16384:24575 -t:3:8301 -c:3:loader2 /dev/${dest_dev} 273 sgdisk -a1 -n:4:24576:32767 -t:4:8301 -c:4:trust /dev/${dest_dev} 274 sgdisk -a1 -n:5:32768:- -A:5:set:2 -t:5:8305 -c:5:rootfs /dev/${dest_dev} 275 276 src_block_count=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block count:" | sed 's/.*: *//') 277 src_block_size=$(tune2fs -l /dev/${src_dev}${part_num} | grep "Block size:" | sed 's/.*: *//') 278 src_fs_size=$(( src_block_count*src_block_size )) 279 src_fs_size_m=$(( src_fs_size / 1024 / 1024 + 1 )) 280 281 dd if=/dev/${src_dev}p1 of=/dev/${dest_dev}p1 conv=sync,noerror status=progress 282 dd if=/dev/${src_dev}p2 of=/dev/${dest_dev}p2 conv=sync,noerror status=progress 283 dd if=/dev/${src_dev}p3 of=/dev/${dest_dev}p3 conv=sync,noerror status=progress 284 dd if=/dev/${src_dev}p4 of=/dev/${dest_dev}p4 conv=sync,noerror status=progress 285 286 echo "Writing ${src_fs_size_m} MB: /dev/${src_dev} -> /dev/${dest_dev}..." 287 dd if=/dev/${src_dev}${part_num} of=/dev/${dest_dev}${part_num} bs=1M conv=sync,noerror status=progress 288 289 echo "Expanding /dev/${dest_dev}${part_num} filesystem..." 290 e2fsck -fy /dev/${dest_dev}${part_num} 291 resize2fs /dev/${dest_dev}${part_num} 292 tune2fs -O has_journal /dev/${dest_dev}${part_num} 293 e2fsck -fy /dev/${dest_dev}${part_num} 294 sync /dev/${dest_dev} 295 296 echo "Cleaning up..." 297 mount /dev/${dest_dev}${part_num} /media 298 chroot /media /usr/local/bin/install-cleanup 299 300 if [ $? == 0 ]; then 301 echo "Successfully copied Rock Pi image!" 302 while true; do 303 led 1; sleep 0.5 304 led 0; sleep 0.5 305 done 306 else 307 echo "Error while copying Rock Pi image" 308 while true; do 309 led 1; sleep 0.1 310 led 0; sleep 0.1 311 done 312 fi 313else 314 echo "Expanding /dev/${dest_dev}${part_num} filesystem..." 315 e2fsck -fy /dev/${dest_dev}${part_num} 316 resize2fs /dev/${dest_dev}${part_num} 317 tune2fs -O has_journal /dev/${dest_dev}${part_num} 318 e2fsck -fy /dev/${dest_dev}${part_num} 319 sync /dev/${dest_dev} 320 321 echo "Cleaning up..." 322 /usr/local/bin/install-cleanup 323fi 324EOF 325chmod a+x /usr/local/bin/sd-dupe 326 327# Write one-shot service for SDCard->eMMC duplication 328cat >/etc/systemd/system/sd-dupe.service <<EOF 329[Unit] 330Description=Duplicate SD card rootfs to eMMC on Rock Pi 331ConditionPathExists=/usr/local/bin/sd-dupe 332After=led.service 333 334[Service] 335Type=simple 336ExecStart=/usr/local/bin/sd-dupe 337TimeoutSec=0 338StandardOutput=tty 339 340[Install] 341WantedBy=multi-user.target 342EOF 343 344# Write cleanup script for eMMC (after duplication) 345cat >/usr/local/bin/install-cleanup <<"EOF" 346#!/bin/bash 347MAC=$(ip link | grep eth0 -A1 | grep ether | sed 's/.*\(..:..:..:..:..:..\) .*/\1/' | tr -d :) 348sed -i "s,rockpi,rockpi-${MAC}," /etc/hosts 349sudo hostnamectl set-hostname "rockpi-${MAC}" 350 351rm -f /etc/machine-id 352rm -f /var/lib/dbus/machine-id 353dbus-uuidgen --ensure 354systemd-machine-id-setup 355 356systemctl disable sd-dupe 357rm -f /etc/systemd/system/sd-dupe.service 358rm -f /usr/local/bin/sd-dupe 359rm -f /usr/local/bin/install-cleanup 360EOF 361chmod a+x /usr/local/bin/install-cleanup 362 363systemctl enable poe 364systemctl enable led 365systemctl enable sd-dupe 366 367setup_dynamic_networking "en*" "" 368 369update_apt_sources bullseye 370 371setup_cuttlefish_user 372 373setup_and_build_cuttlefish 374setup_and_build_iptables 375 376install_and_cleanup_cuttlefish 377install_and_cleanup_iptables 378 379create_systemd_getty_symlinks ttyS0 hvc1 380 381apt-get purge -y vim-tiny 382bullseye_cleanup 383