This repository has been archived by the owner on Aug 30, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 93
/
BuildPiKernel64bit.sh
1398 lines (1179 loc) · 43.6 KB
/
BuildPiKernel64bit.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#
# WARNING: This script is meant to be ran in a *throwaway* Ubuntu 18.04.3 Virtual Machine (VM)
# - Absolutely no steps have been taken to make the process "secure" or "safe" for your main machine
# - It assumes the home directory is safe to build in (it's not on a main system)
# - It installs hundreds of development packages that you only need to build the image (would bog down a main system)
# - It chroots into at least 4 different images during the build and chroots leak (causing instability/security concerns)
# - If things go wrong with the type of commands used in the script your system can get borked *real quick* (like instantly)
# As long as you follow this warning the script is fairly painless to work with!
#
# More information available at:
# https://jamesachambers.com/raspberry-pi-4-ubuntu-server-desktop-18-04-3-image-unofficial/
# https://github.com/TheRemote/Ubuntu-Server-raspi4-unofficial
# CONFIGURATION
IMAGE_VERSION="28"
SOURCE_RELEASE="18.04.4"
TARGET_IMG="ubuntu-$SOURCE_RELEASE-preinstalled-server-arm64+raspi4.img"
TARGET_IMGXZ="ubuntu-$SOURCE_RELEASE-preinstalled-server-arm64+raspi4.img.xz"
DESKTOP_IMGXZ="ubuntu-$SOURCE_RELEASE-preinstalled-desktop-arm64+raspi4.img.xz"
DESKTOP_IMG="ubuntu-$SOURCE_RELEASE-preinstalled-desktop-arm64+raspi4.img"
XUBUNTU_DESKTOP_IMG="xubuntu-$SOURCE_RELEASE-preinstalled-desktop-arm64+raspi4.img"
XUBUNTU_DESKTOP_IMGXZ="xubuntu-$SOURCE_RELEASE-preinstalled-desktop-arm64+raspi4.img.xz"
SOURCE_IMG="ubuntu-$SOURCE_RELEASE-preinstalled-server-arm64+raspi3.img"
SOURCE_IMGXZ="ubuntu-$SOURCE_RELEASE-preinstalled-server-arm64+raspi3.img.xz"
RASPBIAN_IMG="2020-02-13-raspbian-buster-lite.img"
RASPBIAN_IMGZIP="2020-02-13-raspbian-buster-lite.img.zip"
UBUNTU_IMG="ubuntu-19.10.1-preinstalled-server-arm64+raspi3.img"
UBUNTU_IMGXZ="ubuntu-19.10.1-preinstalled-server-arm64+raspi3.img.xz"
export SLEEP_SHORT="0.1"
export SLEEP_LONG="1"
export MOUNT_IMG=""
export KERNEL_VERSION=""
# FUNCTIONS
function PrepareIMG {
while mountpoint -q /mnt/boot/firmware && ! sudo umount /mnt/boot/firmware; do
echo "/mnt/boot/firmware still mounted -- unmounting"
sync; sync
sleep "$SLEEP_SHORT"
done
while mountpoint -q /mnt && ! sudo umount /mnt; do
echo "/mnt still mounted -- unmounting"
sync; sync
sleep "$SLEEP_SHORT"
done
MountCheck=$(sudo losetup --list | grep "(deleted)" | awk 'NR==1{ print $1 }')
while [ -n "$MountCheck" ]; do
echo "Leftover image $MountCheck found -- removing"
sudo rm -rf $MountCheck
MountCheck=$(sudo losetup --list | grep "(deleted)" | awk 'NR==1{ print $1 }')
done
}
function MountIMG {
if [ -n "${MOUNT_IMG}" ]; then
echo "An image is already mounted on ${MOUNT_IMG}"
return 1
fi
if [ ! -e "${1}" ]; then
echo "Image ${1} does not exist!"
return 1
fi
echo "Mounting image ${1}"
MountCheck=$(sudo kpartx -avs "${1}")
echo "$MountCheck"
export MOUNT_IMG=$(echo "$MountCheck" | awk 'NR==1{ print $3 }')
export MOUNT_IMG="${MOUNT_IMG%p1}"
if [ -n "${MOUNT_IMG}" ]; then
sync; sync
sleep "$SLEEP_SHORT"
echo "Mounted ${1} on loop ${MOUNT_IMG}"
else
echo "Unable to mount ${1}: ${MOUNT_IMG} Check - $MountCheck"
export MOUNT_IMG=""
fi
sync; sync
sleep "$SLEEP_SHORT"
}
function MountIMGPartitions {
echo "Mounting partitions"
# % Mount the rootfs on /mnt (/)
sudo mount "/dev/mapper/${1}p2" /mnt
# % Mount the bootfs on /mnt/boot/firmware (/boot/firmware)
if [ -d "/mnt/boot/firmware" ]; then
sudo mount "/dev/mapper/${1}p1" /mnt/boot/firmware
else
sudo mount "/dev/mapper/${1}p1" /mnt/boot
fi
sync; sync
sleep "$SLEEP_SHORT"
}
function UnmountIMGPartitions {
sync; sync
# % Unmount boot and root partitions
echo "Unmounting partitions ..."
while mountpoint -q /mnt/boot/firmware && ! sudo umount /mnt/boot/firmware; do
sync; sync
sleep "$SLEEP_SHORT"
done
while mountpoint -q /mnt/boot && ! sudo umount /mnt/boot; do
sync; sync
sleep "$SLEEP_SHORT"
done
while mountpoint -q /mnt && ! sudo umount /mnt; do
sync; sync
sleep "$SLEEP_SHORT"
done
sync; sync
}
function UnmountIMG {
# % Unmount image and save changes
sync; sync
# % Check if image is mounted first
MountCheck=$(sudo losetup --list | grep "${1}")
if [ ! -n "$MountCheck" ]; then
echo "Unable to unmount $1 (not in losetup --list)"
UnmountIMGPartitions
export MOUNT_IMG=""
return
fi
echo "Unmounting $1"
UnmountIMGPartitions
sudo kpartx -dvs "$1"
sync; sync
sleep "$SLEEP_LONG"
# % Wait for loop to disappear from list before continuing
WaitLoops=0
while [ -n "$(sudo losetup --list | grep ${1})" ]; do
WaitLoops=$((WaitLoops+1))
if (( WaitLoops > 50 )); then
echo "Exceeded maximum wait time -- trying to force close"
sudo kpartx -dvs "${1}"
sudo losetup -D
fi
sync; sync
sleep "$SLEEP_SHORT"
done
export MOUNT_IMG=""
}
function CompactIMG {
echo "Compacting IMG file ${1}"
sudo rm -rf "${1}.2"
sudo virt-sparsify "${1}" "${1}.2"
sync; sync
sleep "$SLEEP_SHORT"
sudo rm -rf "${1}"
mv "${1}.2" "${1}"
sync; sync
sleep "$SLEEP_SHORT"
}
function BeforeCleanIMG {
echo "Cleaning IMG file (before)"
# % Remove flash-kernel hooks to prevent firmware updater from overriding our custom firmware
sudo rm -rf /mnt/etc/kernel/postinst.d/zz-flash-kernel
sudo rm -rf /mnt/etc/kernel/postrm.d/zz-flash-kernel
sudo rm -rf /mnt/etc/initramfs/post-update.d/flash-kernel
# Copy resolv.conf for chroot
sudo mkdir -p /mnt/run/systemd/resolve
sudo touch /mnt/run/systemd/resolve/stub-resolv.conf
sudo cat /run/systemd/resolve/stub-resolv.conf | sudo tee /mnt/run/systemd/resolve/stub-resolv.conf >/dev/null;
# Prepare chroot
sudo cp -f /usr/bin/qemu-aarch64-static /mnt/usr/bin
# % Remove incompatible RPI firmware / headers / modules
sudo chroot /mnt /bin/bash << EOF
apt purge linux-raspi2 linux-image-raspi2 linux-headers-raspi2 linux-firmware-raspi2 ureadahead libnih1 -y
apt update && apt dist-upgrade -y
EOF
sudo rm -rf /mnt/boot/firmware/*
sudo rm -rf /mnt/boot/initrd*
sudo rm -rf /mnt/boot/config*
sudo rm -rf /mnt/boot/vmlinu*
sudo rm -rf /mnt/boot/System.map*
sudo rm -rf /mnt/lib/firmware/*
sudo rm -rf /mnt/lib/modules/*
sudo rm -rf /mnt/usr/src/*
sudo rm -rf /mnt/usr/lib/linux-firmware-raspi2
sudo rm -rf /mnt/var/log/*.gz /mnt/var/log/*.log*
sudo rm -rf /mnt/var/lib/initramfs-tools/*
sudo rm -rf /mnt/var/lib/apt/lists/ports* /mnt/var/lib/apt/lists/*InRelease /mnt/var/lib/apt/lists/*-en /mnt/var/lib/apt/lists/*Packages
# % Remove old configuration files that we are replacing with our new ones
sudo rm -rf /mnt/etc/rc.local
sudo rm -rf /mnt/etc/fstab
sudo rm -rf /mnt/etc/default/crda
sudo rm -rf /mnt/etc/hosts
# Clear Python cache
sudo find /mnt -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
# Remove any crash files generated
sudo rm -rf /mnt/var/crash/*
sudo rm -rf /mnt/root/*
sync; sync
sleep "$SLEEP_LONG"
}
function AfterCleanIMG {
echo "Cleaning IMG file (after)"
# Clear apt cache
sudo rm -rf /mnt/var/lib/apt/lists/ports* /mnt/var/lib/apt/lists/*InRelease /mnt/var/lib/apt/lists/*-en /mnt/var/lib/apt/lists/*Packages
# Clear Python cache
sudo find /mnt -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
# Remove any crash files generated
sudo rm -rf /mnt/var/crash/*
sudo rm -rf /mnt/root/*
# Remove machine ID so all clones don't have the same one
sudo rm -rf /mnt/etc/machine-id
sudo touch /mnt/etc/machine-id
sync; sync
sleep "$SLEEP_LONG"
}
# Checks git to see if we have updates
function CheckGitUpdates {
git remote update > /dev/null
git pull > /dev/null
if [ ! -z "$(git status --porcelain)" ]; then
echo "Local files modified"
return 0
fi
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")
if [ $LOCAL = $REMOTE ]; then
# Up to date
echo "Up to date"
return 1
elif [ $LOCAL = $BASE ]; then
# Need to pull
echo "Need to pull"
return 0
elif [ $REMOTE = $BASE ]; then
# Need to push
echo "Need to push"
return 0
else
echo "Diverged"
# Diverged
return 0
fi
}
function SetGitTimestamps {
for FILE in $(git ls-files); do
TIME=$(git log --pretty=format:%cd -n 1 --date=iso -- "$FILE");
TIME=$(date --date="$TIME" +%Y%m%d%H%M.%S);
touch -m -t "$TIME" "$FILE";
done
}
function UpdateIMG {
# % Remove flash-kernel hooks to prevent update failure for "Unsupported Platform"
sudo rm -rf /mnt/etc/kernel/postinst.d/zz-flash-kernel
sudo rm -rf /mnt/etc/kernel/postrm.d/zz-flash-kernel
sudo rm -rf /mnt/etc/initramfs/post-update.d/flash-kernel
# Copy resolv.conf for chroot
sudo mkdir -p /mnt/run/systemd/resolve
sudo touch /mnt/run/systemd/resolve/stub-resolv.conf
sudo cat /run/systemd/resolve/stub-resolv.conf | sudo tee /mnt/run/systemd/resolve/stub-resolv.conf >/dev/null;
# Prepare chroot
if [ -d "/mnt/boot/firmware" ]; then
sudo cp -f /usr/bin/qemu-aarch64-static /mnt/usr/bin
else
sudo cp -f /usr/bin/qemu-arm-static /mnt/usr/bin
fi
# % Remove incompatible RPI firmware / headers / modules
sudo chroot /mnt /bin/bash << EOF
apt update && apt dist-upgrade -y
EOF
}
function ShrinkIMG {
MountIMG $1
tune2fs_output=$(sudo tune2fs -l "/dev/mapper/${MOUNT_IMG}p2")
currentsize=$(echo "$tune2fs_output" | grep '^Block count:' | tr -d ' ' | cut -d ':' -f 2)
blocksize=$(echo "$tune2fs_output" | grep '^Block size:' | tr -d ' ' | cut -d ':' -f 2)
minsize=$(sudo resize2fs -P "/dev/mapper/${MOUNT_IMG}p2" | tr -d ' ' | cut -d ':' -f 2)
extra_space=$(($currentsize - $minsize))
beforesize=$(ls -lh "$1" | cut -d ' ' -f 5)
parted_output=$(sudo parted -ms "$1" unit B print | tail -n 1)
partnum=$(echo "$parted_output" | cut -d ':' -f 1)
partstart=$(echo "$parted_output" | cut -d ':' -f 2 | tr -d 'B')
# Add 10000 blocks of free space
minsize=$(( $minsize + 10000 ))
sudo resize2fs -fp "/dev/mapper/${MOUNT_IMG}p2" $minsize
UnmountIMG "$1"
partnewsize=$(($minsize * $blocksize))
newpartend=$(($partstart + $partnewsize))
if ! sudo parted -s -a minimal "$1" rm "$partnum"; then
rc=$?
echo "parted failed: $rc"
return
fi
if ! sudo parted -s "$1" unit B mkpart primary "$partstart" "$newpartend"; then
rc=$?
echo "parted failed: $rc"
return
fi
#Truncate the file
if ! endresult=$(sudo parted -ms "$1" unit B print free); then
rc=$?
echo "parted failed: $rc"
return
fi
endresult=$(tail -1 <<< "$endresult" | cut -d ':' -f 2 | tr -d 'B')
if ! sudo truncate -s "$endresult" "$1"; then
rc=$?
echo "truncate failed: $rc"
return
fi
MountIMG "$1"
# Run e2fsck
echo "Running e2fsck"
sudo fsck.ext4 -pfv "/dev/mapper/${MOUNT_IMG}p2"
sync; sync
sleep "$SLEEP_SHORT"
UnmountIMG "$1"
CompactIMG $1
}
##################################################################################################################
# Get crosschain toolkit
cd ~
if [ ! -d "/opt/cross-pi-gcc-9.2.0-64" ]; then
# Install dependencies
echo "Installing cross pi build toolchain dependencies ..."
sudo apt-get install git curl unzip build-essential libgmp-dev libmpfr-dev libmpc-dev libssl-dev bison flex kpartx libguestfs-tools gawk gcc g++ gfortran cmake texinfo libncurses-dev pkg-config -y
curl --location "https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/latest/download" --output "cross-pi-gcc-9.2.0-64.tar.gz"
tar -xf "cross-pi-gcc-9.2.0-64.tar.gz"
rm -rf "cross-pi-gcc-9.2.0-64.tar.gz"
sudo mv cross-pi-gcc-9.2.0-64 /opt
fi
# Get latest QEMU
cd ~
if [ ! -d "qemu" ]; then
sudo apt-get build-dep qemu -y
git clone https://git.qemu.org/git/qemu.git --single-branch --depth=1
cd ~/qemu
git submodule init
git submodule update --recursive
./configure --static --target-list=aarch64-linux-user,arm-linux-user
make -j$(nproc)
cd aarch64-linux-user
sudo cp -f qemu-aarch64 qemu-aarch64-static
sudo cp -f qemu-aarch64-static /usr/bin
cd ..
cd arm-linux-user
sudo cp -f qemu-arm qemu-arm-static
sudo cp -f qemu-arm-static /usr/bin
fi
# PREPARE IMAGE
cd ~
PrepareIMG
# % Get Raspberry Pi 3 Ubuntu source image
if [ ! -f "$SOURCE_IMGXZ" ]; then
echo "Retrieving Ubuntu $SOURCE_RELEASE source image ..."
wget http://cdimage.ubuntu.com/ubuntu/releases/"$SOURCE_RELEASE"/release/"$SOURCE_IMGXZ"
fi
# % Get Ubuntu source image
if [ ! -f "$UBUNTU_IMGXZ" ]; then
echo "Retrieving Ubuntu 19.10.1 source image ..."
wget http://cdimage.ubuntu.com/ubuntu/releases/19.10.1/release/ubuntu-19.10.1-preinstalled-server-arm64+raspi3.img.xz
fi
if [ ! -f "$RASPBIAN_IMGZIP" ]; then
echo "Retrieving Raspbian source image ..."
curl --location "https://downloads.raspberrypi.org/raspbian_lite_latest" --output "$RASPBIAN_IMGZIP"
fi
# % Extract and compact our source image from the xz if the source image isn't present
if [ ! -f "$UBUNTU_IMG" ]; then
echo "Extracting Ubuntu 19.10.1 source image ..."
xzcat --threads=0 "$UBUNTU_IMGXZ" > "$UBUNTU_IMG"
MountIMG "$UBUNTU_IMG"
MountIMGPartitions "${MOUNT_IMG}"
UpdateIMG
sudo rm -rf ~/firmware-ubuntu-1910
sudo mkdir ~/firmware-ubuntu-1910
sudo cp -raf /mnt/lib/firmware/* ~/firmware-ubuntu-1910
sudo chown -R "$USER" ~/firmware-ubuntu-1910
UnmountIMG "$UBUNTU_IMG"
fi
# % Extract and compact our Raspbian image if not present
if [ ! -f "$RASPBIAN_IMG" ]; then
echo "Extracting Raspbian source image ..."
unzip $RASPBIAN_IMGZIP
MountIMG "$RASPBIAN_IMG"
MountIMGPartitions "${MOUNT_IMG}"
UpdateIMG
sudo rm -rf ~/firmware-raspbian
sudo mkdir ~/firmware-raspbian
sudo cp -raf /mnt/lib/firmware/* ~/firmware-raspbian
sudo chown -R "$USER" ~/firmware-raspbian
UnmountIMG "$RASPBIAN_IMG"
fi
# % Extract and compact our source image from the xz if the source image isn't present
cd ~
if [ ! -f "$SOURCE_IMG" ]; then
echo "Extracting Ubuntu $SOURCE_RELEASE source image ..."
xzcat --threads=0 "$SOURCE_IMGXZ" > "$SOURCE_IMG"
MountIMG "$SOURCE_IMG"
MountIMGPartitions "${MOUNT_IMG}"
sudo rm -rf ~/firmware-ubuntu-1804
sudo mkdir ~/firmware-ubuntu-1804
sudo cp -raf /mnt/lib/firmware/* ~/firmware-ubuntu-1804
sudo chown -R "$USER" ~/firmware-ubuntu-1804
BeforeCleanIMG
UpdateIMG
UnmountIMG "$SOURCE_IMG"
CompactIMG "$SOURCE_IMG"
fi
# % Create target image from Ubuntu source image
echo "Creating target image ..."
if [ -f "$TARGET_IMG" ]; then
sudo rm -rf "$TARGET_IMG"
fi
if [ -f "$DESKTOP_IMG" ]; then
sudo rm -rf "$DESKTOP_IMG"
fi
if [ -f "$XUBUNTU_DESKTOP_IMG" ]; then
sudo rm -rf "$XUBUNTU_DESKTOP_IMG"
fi
cp -vf "$SOURCE_IMG" "$TARGET_IMG"
# % Expands the target image by approximately 300MB to help us not run out of space and encounter errors
echo "Expanding target image free space ..."
truncate -s +1009715200 "$TARGET_IMG"
sync; sync
# GET USERLAND
cd ~
if [ ! -d "userland" ]; then
echo "Building userland ..."
git clone https://github.com/raspberrypi/userland userland --single-branch --branch=master --depth=1
cd userland
PATH=/opt/cross-pi-gcc-9.2.0-64/bin:$PATH LD_LIBRARY_PATH=/opt/cross-pi-gcc-9.2.0-64/lib:$LD_LIBRARY_PATH ./buildme --aarch64
cd build/arm-linux/release
sudo make package
sudo chown -R "$USER" .
tar -xf vmcs_host_apps-1.0.pre-1-Linux.tar.gz
SetGitTimestamps
fi
# GET FIRMWARE NON-FREE
cd ~
echo "Building firmware-nonfree ..."
if [ ! -d "firmware-nonfree" ]; then
git clone https://github.com/RPi-Distro/firmware-nonfree firmware-nonfree --single-branch --branch=master
cd firmware-nonfree
SetGitTimestamps
else
cd firmware-nonfree
if CheckGitUpdates; then
git reset --hard origin/master
SetGitTimestamps
fi
fi
# GET FIRMWARE
cd ~
echo "Building rpi-firmware ..."
if [ ! -d "firmware" ]; then
git clone https://github.com/raspberrypi/firmware firmware --single-branch --branch=master --depth=1
cd firmware
else
cd firmware
if CheckGitUpdates; then
git reset --hard origin/master
fi
fi
# MAKE FIRMWARE BUILD DIR
cd ~
sudo rm -rf firmware-build
mkdir firmware-build
cp --recursive --update --archive --no-preserve=ownership ~/firmware-ubuntu-1910/* ~/firmware-build
cp --recursive --update --archive --no-preserve=ownership ~/firmware-nonfree/* ~/firmware-build
cp --recursive --update --archive --no-preserve=ownership ~/firmware-raspbian/* ~/firmware-build
sudo rm -rf ~/firmware-build/.git
sudo rm -rf ~/firmware-build/.github
# % Remove unneeded firmware folders
sudo rm -rf ~/firmware-build/LICEN*
sudo rm -rf ~/firmware-build/WHENCE
sudo rm -rf ~/firmware-build/check_whence.py
sudo rm -rf ~/firmware-build/Makefile
sudo rm -rf ~/firmware-build/copy-firmware.sh
sudo rm -rf ~/firmware-build/PLUS.txt
sudo rm -rf ~/firmware-build/netronome
sudo rm -rf ~/firmware-build/amdgpu
sudo rm -rf ~/firmware-build/radeon
sudo rm -rf ~/firmware-build/raspberrypi
sudo rm -rf ~/firmware-build/debian
sudo rm -rf ~/firmware-build/*-raspi2
# BUILD KERNEL
cd ~
echo "Building kernel ..."
if [ ! -d "rpi-linux" ]; then
# Check out the 4.19.y kernel branch -- if building and future versions are available you can update which branch is checked out here
git clone https://github.com/raspberrypi/linux.git rpi-linux --single-branch --branch rpi-4.19.y --depth 1
cd ~/rpi-linux
git checkout origin/rpi-4.19.y
# Make copy of source code if not present
if [ ! -d "~/rpi-source" ]; then
mkdir -p ~/rpi-source
cp -rf ~/rpi-linux/* ~/rpi-source
rm ~/rpi-source/.git ~/rpi-source/.github
fi
# CONFIGURE / MAKE
PATH=/opt/cross-pi-gcc-9.2.0-64/bin:$PATH LD_LIBRARY_PATH=/opt/cross-pi-gcc-9.2.0-64/lib:$LD_LIBRARY_PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
# % Run conform_config scripts which fix kernel flags to work correctly in arm64
wget https://raw.githubusercontent.com/sakaki-/bcm2711-kernel-bis/master/conform_config.sh
chmod +x conform_config.sh
./conform_config.sh
rm -rf conform_config.sh
wget https://raw.githubusercontent.com/TheRemote/Ubuntu-Server-raspi4-unofficial/master/conform_config_jamesachambers.sh
chmod +x conform_config_jamesachambers.sh
./conform_config_jamesachambers.sh
rm -rf conform_config_jamesachambers.sh
# % This pulls the latest config from the repository -- if building yourself/customizing comment out
#rm -rf .config
#wget https://raw.githubusercontent.com/TheRemote/Ubuntu-Server-raspi4-unofficial/master/.config
# % Run prepare to register all our .config changes
cd ~/rpi-linux
PATH=/opt/cross-pi-gcc-9.2.0-64/bin:$PATH LD_LIBRARY_PATH=/opt/cross-pi-gcc-9.2.0-64/lib:$LD_LIBRARY_PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- prepare dtbs
# % Prepare and build the rpi-linux source - create debian packages to make it easy to update the image
PATH=/opt/cross-pi-gcc-9.2.0-64/bin:$PATH LD_LIBRARY_PATH=/opt/cross-pi-gcc-9.2.0-64/lib:$LD_LIBRARY_PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- DTC_FLAGS="-@ -H epapr" LOCALVERSION=-"${IMAGE_VERSION}" KDEB_PKGVERSION="${IMAGE_VERSION}" deb-pkg
export KERNEL_VERSION=`cat ~/rpi-linux/include/generated/utsrelease.h | sed -e 's/.*"\(.*\)".*/\1/'`
# % Make DTBOs
# % Build kernel modules
PATH=/opt/cross-pi-gcc-9.2.0-64/bin:$PATH LD_LIBRARY_PATH=/opt/cross-pi-gcc-9.2.0-64/lib:$LD_LIBRARY_PATH sudo make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- DEPMOD=echo MODLIB=./lib/modules/"${KERNEL_VERSION}" INSTALL_FW_PATH=./lib/firmware modules_install
sudo depmod --basedir . "${KERNEL_VERSION}"
sudo chown -R "$USER" .
else
export KERNEL_VERSION=`cat ~/rpi-linux/include/generated/utsrelease.h | sed -e 's/.*"\(.*\)".*/\1/'`
fi
# PREPARE IMAGE
cd ~
MountIMG "$TARGET_IMG"
# Run fdisk
# % Get the starting offset of the root partition
PART_START=$(sudo parted "/dev/${MOUNT_IMG}" -ms unit s p | grep ":ext4" | cut -f 2 -d: | sed 's/[^0-9]//g')
# % Perform fdisk to correct the partition table
sudo fdisk "/dev/${MOUNT_IMG}" << EOF
p
d
2
n
p
2
$PART_START
p
w
EOF
UnmountIMG "$TARGET_IMG"
MountIMG "$TARGET_IMG"
# Run e2fsck
echo "Running e2fsck"
sudo e2fsck -fva "/dev/mapper/${MOUNT_IMG}p2"
sync; sync
sleep "$SLEEP_SHORT"
UnmountIMG "$TARGET_IMG"
MountIMG "$TARGET_IMG"
# Run resize2fs
echo "Running resize2fs"
sudo resize2fs -p "/dev/mapper/${MOUNT_IMG}p2"
sync; sync
sleep "$SLEEP_SHORT"
UnmountIMG "$TARGET_IMG"
# Compact image after our file operations
CompactIMG "$TARGET_IMG"
MountIMG "$TARGET_IMG"
MountIMGPartitions "${MOUNT_IMG}"
# CREATE FILES FOR UPDATER
cd ~
sudo rm -rf ~/updates
mkdir -p ~/updates/bootfs/overlays
mkdir -p ~/updates/rootfs/boot
mkdir -p ~/updates/rootfs/home
mkdir -p ~/updates/rootfs/usr/bin
mkdir -p ~/updates/rootfs/usr/lib/aarch64-linux-gnu
mkdir -p ~/updates/rootfs/usr/lib/"${KERNEL_VERSION}"/overlays
mkdir -p ~/updates/rootfs/usr/lib/"${KERNEL_VERSION}"/broadcom
mkdir -p ~/updates/rootfs/lib/firmware
mkdir -p ~/updates/rootfs/lib/modules/"${KERNEL_VERSION}"
mkdir -p ~/updates/rootfs/include/interface/vcos/generic
mkdir -p ~/updates/rootfs/usr/src/"${KERNEL_VERSION}"
mkdir -p ~/updates/rootfs/etc/
mkdir -p ~/updates/rootfs/etc/flash-kernel
mkdir -p ~/updates/rootfs/etc/flash-kernel/dtbs
cp --recursive --update --archive --no-preserve=ownership ~/firmware-build/* ~/updates/rootfs/lib/firmware
cp --recursive --update --archive --no-preserve=ownership ~/rpi-linux/lib/modules/* ~/updates/rootfs/lib/modules
cp --recursive --update --archive --no-preserve=ownership ~/rpi-source/* ~/updates/rootfs/usr/src/"${KERNEL_VERSION}"
sync; sync
sleep "$SLEEP_SHORT"
# % Copy overlays / image / firmware
cp -rf ~/rpi-linux/arch/arm64/boot/dts/broadcom/*.dtb ~/updates/bootfs
cp -rf ~/rpi-linux/arch/arm64/boot/dts/broadcom/*.dtb ~/updates/rootfs/etc/flash-kernel/dtbs
cp -rf ~/rpi-linux/arch/arm64/boot/dts/overlays/*.dtb* ~/updates/bootfs/overlays
cp -rf ~/rpi-linux/arch/arm64/boot/dts/overlays/README ~/updates/bootfs/overlays
cp -rf ~/rpi-linux/arch/arm64/boot/dts/broadcom/*.dtb ~/updates/rootfs/usr/lib/"${KERNEL_VERSION}"/overlays
cp -rf ~/rpi-linux/arch/arm64/boot/dts/overlays/*.dtb* ~/updates/rootfs/usr/lib/"${KERNEL_VERSION}"/broadcom
cp -rf ~/rpi-linux/arch/arm64/boot/dts/overlays/README ~/updates/rootfs/usr/lib/"${KERNEL_VERSION}"/overlays
# Create network-config
cat << EOF | tee ~/updates/bootfs/network-config >/dev/null
# This file contains a netplan-compatible configuration which cloud-init
# will apply on first-boot. Please refer to the cloud-init documentation and
# the netplan reference for full details:
#
# https://cloudinit.readthedocs.io/
# https://netplan.io/reference
#
# Some additional examples are commented out below
version: 2
ethernets:
eth0:
dhcp4: true
optional: true
#wifis:
# wlan0:
# dhcp4: true
# optional: true
# access-points:
# homessid:
# password: "S3kr1t"
# myotherlan:
# password: "correct battery horse staple"
# workssid:
# auth:
# key-management: eap
# method: peap
# identity: "[email protected]"
# password: "passw0rd"
# ca-certificate: /etc/my_ca.pem
EOF
# Create meta-data
cat << EOF | tee ~/updates/bootfs/meta-data >/dev/null
# This is the meta-data configuration file for cloud-init. Typically this just
# contains the instance_id. Please refer to the cloud-init documentation for
# more information:
#
# https://cloudinit.readthedocs.io/
instance_id: cloud-image
EOF
# Create user-data
cat << EOF | tee ~/updates/bootfs/user-data >/dev/null
#cloud-config
# This is the user-data configuration file for cloud-init. By default this sets
# up an initial user called "ubuntu" with password "ubuntu", which must be
# changed at first login. However, many additional actions can be initiated on
# first boot from this file. The cloud-init documentation has more details:
#
# https://cloudinit.readthedocs.io/
#
# Some additional examples are provided in comments below the default
# configuration.
# Enable password authentication with the SSH daemon
ssh_pwauth: true
# On first boot, set the (default) ubuntu user's password to "ubuntu" and
# expire user passwords
chpasswd:
expire: true
list:
- ubuntu:ubuntu
EOF
# % Unmount and copy firmware copy to overlapping firmware folder
while mountpoint -q /mnt/boot/firmware && ! sudo umount /mnt/boot/firmware; do
sync; sync
sleep "$SLEEP_SHORT"
done
sudo cp -rf ~/firmware/boot/*.elf /mnt/boot/firmware/
sudo cp -rf ~/firmware/boot/*.dat /mnt/boot/firmware/
sudo cp -rf ~/firmware/boot/*.bin /mnt/boot/firmware/
sudo mount "/dev/mapper/${MOUNT_IMG}p1" /mnt/boot/firmware
cp -rf ~/rpi-linux/arch/arm64/boot/Image ~/updates/rootfs/boot/kernel8.img
cp -rf ~/rpi-linux/vmlinux ~/updates/rootfs/boot/vmlinux-"${KERNEL_VERSION}"
cp -rf ~/rpi-linux/System.map ~/updates/rootfs/boot/System.map-"${KERNEL_VERSION}"
cp -rf ~/rpi-linux/Module.symvers ~/updates/rootfs/boot/Module.symvers-"${KERNEL_VERSION}"
cp -rf ~/rpi-linux/Module.symvers ~/updates/rootfs/usr/src/"${KERNEL_VERSION}"/Module.symvers
cp -rf ~/rpi-linux/.config ~/updates/rootfs/boot/config-"${KERNEL_VERSION}"
sync; sync
sleep "$SLEEP_SHORT"
# % Copy the new kernel modules
echo "Installing kernel modules ..."
cp -rf ~/rpi-linux/lib/modules/* ~/updates/rootfs/lib/modules
cp -rf ~/rpi-linux/arch/arm64/boot/dts/broadcom/*.dtb ~/updates/bootfs
cp -rf ~/rpi-linux/arch/arm64/boot/dts/overlays/*.dtb* ~/updates/bootfs/overlays
# % Copy new Raspberry Pi userland
cp -rf ~/userland/build/arm-linux/release/vmcs_host_apps-1.0.pre-1-Linux/bin/* ~/updates/rootfs/usr/bin
cp -rf ~/userland/build/arm-linux/release/vmcs_host_apps-1.0.pre-1-Linux/lib/* ~/updates/rootfs/usr/lib/aarch64-linux-gnu
cp -rf ~/userland/build/arm-linux/release/vmcs_host_apps-1.0.pre-1-Linux/include/* ~/updates/rootfs/usr/include
# % Copy kernel and gpu firmware start*.elf, fixup*.dat and bootcode.bin files
cp -rf ~/firmware/boot/*.elf ~/updates/bootfs
cp -rf ~/firmware/boot/*.dat ~/updates/bootfs
cp -rf ~/firmware/boot/*.bin ~/updates/bootfs
cp -rf ~/rpi-linux/arch/arm64/boot/Image ~/updates/bootfs/kernel8.img
sync; sync
sleep "$SLEEP_SHORT"
# % Copy updater script into home folder
cp -f ~/Updater.sh ~/updates/rootfs/home/Updater.sh
cp -f ~/raspi-config ~/updates/rootfs/usr/bin/raspi-config
# % Create cmdline.txt
cat << EOF | tee ~/updates/bootfs/cmdline.txt >/dev/null
snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_compat_alsa=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 fsck.repair=yes fsck.mode=auto root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
EOF
# % Create config.txt
cat << EOF | tee ~/updates/bootfs/config.txt >/dev/null
# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1
# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1
# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16
# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720
# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1
# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1
# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2
# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4
# uncomment for composite PAL
#sdtv_mode=2
# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=spi=on
#dtparam=i2s=on
#dtparam=i2c_arm=on
#dtparam=i2c1=on
#dtparam=i2c0=on
# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
[pi4]
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
arm_64bit=1
#device_tree_address=0x03000000
[all]
#dtoverlay=vc4-fkms-v3d
EOF
# % Copy bootfs and rootfs
sudo cp -rf ~/updates/bootfs/* /mnt/boot/firmware
sudo cp -rf ~/updates/rootfs/* /mnt
sync; sync
sleep "$SLEEP_SHORT"
# % Remove initramfs actions for invalid existing kernels, then create a new link to our new custom kernel
sha1sum=$(sha1sum /mnt/boot/vmlinux-"${KERNEL_VERSION}")
sudo mkdir -p /mnt/var/lib/initramfs-tools
echo "$sha1sum /boot/vmlinux-${KERNEL_VERSION}" | sudo tee -a /mnt/var/lib/initramfs-tools/"${KERNEL_VERSION}" >/dev/null;
# QUIRKS
cd ~
# % Add udev rule so users can use vcgencmd without sudo
sudo touch /mnt/etc/udev/rules.d/10-local-rpi.rules
echo "SUBSYSTEM==\"vchiq\", GROUP=\"video\", MODE=\"0660\"" | sudo tee /mnt/etc/udev/rules.d/10-local-rpi.rules >/dev/null
# % Startup tweaks to fix common issues
sudo touch /mnt/etc/ubuntufixes.sh
cat << \EOF | sudo tee /mnt/etc/ubuntufixes.sh >/dev/null
#!/bin/bash
#
# Ubuntu Fixes
# More information available at:
# https://jamesachambers.com/raspberry-pi-4-ubuntu-server-desktop-18-04-3-image-unofficial/
# https://github.com/TheRemote/Ubuntu-Server-raspi4-unofficial
#
echo "Running Ubuntu fixes ..."
# Fix sound by setting tsched = 0 and disabling analog mapping so Pulse maps the devices in stereo
if [ -n "`which pulseaudio`" ]; then
GrepCheck=$(cat /etc/pulse/default.pa | grep "tsched=0")
if [ -z "$GrepCheck" ]; then
echo "Fixing PulseAudio ..."
sed -i "s:load-module module-udev-detect:load-module module-udev-detect tsched=0:g" /etc/pulse/default.pa
systemctl restart systemd-modules-load
else
GrepCheck=$(cat /etc/pulse/default.pa | grep "tsched=0 tsched=0")
if [ ! -z "$GrepCheck" ]; then
sed -i 's/tsched=0//g' /etc/pulse/default.pa
sed -i "s:load-module module-udev-detect:load-module module-udev-detect tsched=0:g" /etc/pulse/default.pa
systemctl restart systemd-modules-load
fi
fi
GrepCheck=$(cat /usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf | grep "device-strings = fake")
if [ -z "$GrepCheck" ]; then
sed -i '/^\[Mapping analog-mono\]/,+1s/device-strings = hw\:\%f.*/device-strings = fake\:\%f/' /usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf
sed -i '/^\[Mapping multichannel-output\]/,+1s/device-strings = hw\:\%f.*/device-strings = fake\:\%f/' /usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf
pulseaudio -k
pulseaudio --start
fi
fi
# Fix cups
if [ -f /etc/modules-load.d/cups-filters.conf ]; then
echo "Fixing cups ..."
rm -f /etc/modules-load.d/cups-filters.conf
fi
# Makes udev mounts visible
if [ "$(systemctl show systemd-udevd | grep 'MountFlags' | cut -d = -f 2)" != "shared" ]; then
if [ ! -d "/etc/systemd/system/systemd-udevd.service.d/" ]; then
mkdir -p "/etc/systemd/system/systemd-udevd.service.d/"
fi
OverrideFile=/etc/systemd/system/systemd-udevd.service.d/override.conf
read -r -d '' Override << EOF2
[Service]
MountFlags=shared
EOF2
if [ -f "$OverrideFile" ]; then
echo "$OverrideFile exists..."
if grep -q 'MountFlags' $OverrideFile; then
echo "Applying udev MountFlags fix to existing $OverrideFile"
sed -i 's/MountFlags=.*/MountFlags=shared/g' $OverrideFile
else
echo "Appending udev MountFlags fix to $OverrideFile"
cat << EOF2 >> "$OverrideFile"
$Override
EOF2
fi
else
echo "Creating $OverrideFile to apply udev MountFlags fix"
cat << EOF2 > "$OverrideFile"
$Override
EOF2
fi
systemctl daemon-reload
service systemd-udevd --full-restart
unset Override
unset OverrideFile
fi
# Remove triggerhappy bugged socket that causes problems for udev on Pis
if [ -f /lib/systemd/system/triggerhappy.socket ]; then
echo "Fixing triggerhappy ..."
sudo rm -rf /lib/systemd/system/triggerhappy.socket
systemctl daemon-reload
fi
# Add proposed apt archive
GrepCheck=$(cat /etc/apt/sources.list | grep "ubuntu-ports bionic-proposed")
if [ -z "$GrepCheck" ]; then
cat << EOF2 | tee -a /etc/apt/sources.list >/dev/null
deb http://ports.ubuntu.com/ubuntu-ports bionic-proposed restricted main multiverse universe
EOF2
touch /etc/apt/preferences.d/proposed-updates
cat << EOF2 | tee /etc/apt/preferences.d/proposed-updates >/dev/null
Package: *
Pin: release a=bionic-proposed
Pin-Priority: 400
EOF2
fi
# Fix Cannot access /dev/virtio-ports/com.redhat.spice.0
if [ -f "/usr/share/gdm/autostart/LoginWindow/spice-vdagent.desktop" ]; then
GrepCheck=$(cat /usr/share/gdm/autostart/LoginWindow/spice-vdagent.desktop | grep "X-GNOME-Autostart-enabled=false")
if [ -z "$GrepCheck" ]; then
echo "Fixing spice-vdagent ..."
echo 'X-GNOME-Autostart-enabled=false' | tee -a /usr/share/gdm/autostart/LoginWindow/spice-vdagent.desktop >/dev/null