• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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