From 8fed5e6ddf9fbb57929ffecd138623f9b059e272 Mon Sep 17 00:00:00 2001
From: Dzmitry Sankouski <dsankouski@gmail.com>
Date: Fri, 18 Nov 2022 12:39:33 +0300
Subject: [PATCH] starqltechn: automate dualbooting with u-boot

Dual boot PostmarketOS and Android with u-boot! It works by placing an additional u-boot FIT image,
and a script into overridden initramfs. Mentioned script is used to find and select image to boot.
User should enable dual-boot explicitly by enabling commented deviceinfo options,
and placing vendor boot image into device /boot directory, running 'pmbootstrap init' and
specifying vendor boot image location, if building locally.

deviceinfo_bootimg_override_initramfs:
- add android_boot_image.itb - u-boot FIT image assembled,
using extracted kernel and ramdisk from vendor image.
- add find_image_and_boot.itb - u-boot FIT image with a script
to find and boot needed image.

Set couple new options:
- deviceinfo_bootimg_override_header_info_using_vendor_image="true"
This overrides boot image header values, written in deviceinfo, by
extracted values from vendor image. This mainly needed to trick trustzone.

- deviceinfo_bootimg_vendor_android_boot_image="vendor_boot.img"
We're counting on vendor image to be on device's /boot directory in a file
with that name.

- deviceinfo_bootimg_vendor_device_tree_identifiers="qcom,msm-id\s*=\s*<0x141\s*0x20001>; qcom,board-id\s*=\s*<0x08\s*0x0e>;"
Identifiers to find a dtb, used by stock bootloader in vendor's boot image file.
---
 .../device-samsung-starqltechn/APKBUILD       | 14 +++-
 .../android_boot_image.its                    | 68 +++++++++++++++++++
 .../bootscript_android.sh                     | 22 ++++++
 .../device-samsung-starqltechn/deviceinfo     |  8 ++-
 .../find_image_and_boot.its                   | 32 +++++++++
 .../find_image_and_boot.sh                    | 48 +++++++++++++
 6 files changed, 188 insertions(+), 4 deletions(-)
 create mode 100644 device/testing/device-samsung-starqltechn/android_boot_image.its
 create mode 100644 device/testing/device-samsung-starqltechn/bootscript_android.sh
 create mode 100644 device/testing/device-samsung-starqltechn/find_image_and_boot.its
 create mode 100644 device/testing/device-samsung-starqltechn/find_image_and_boot.sh

diff --git a/device/testing/device-samsung-starqltechn/APKBUILD b/device/testing/device-samsung-starqltechn/APKBUILD
index ef3991303c0..b1b086104a9 100644
--- a/device/testing/device-samsung-starqltechn/APKBUILD
+++ b/device/testing/device-samsung-starqltechn/APKBUILD
@@ -2,14 +2,14 @@
 pkgname=device-samsung-starqltechn
 pkgdesc="Samsung Galaxy S9 SM-G9600"
 pkgver=0.2
-pkgrel=2
+pkgrel=3
 url="https://postmarketos.org"
 license="MIT"
 arch="aarch64"
 options="!check !archcheck"
 depends="postmarketos-base linux-postmarketos-qcom-sdm845 mkbootimg u-boot-starqltechn u-boot-tools dtc"
 makedepends="devicepkg-dev dtc"
-source="deviceinfo boot_image.its payload_mock.dts bootscript.sh"
+source="deviceinfo boot_image.its android_boot_image.its payload_mock.dts bootscript.sh bootscript_android.sh find_image_and_boot.its find_image_and_boot.sh"
 
 build() {
 	devicepkg_build $startdir $pkgname
@@ -27,12 +27,20 @@ package() {
 		"$pkgdir"/usr/share/u-boot/starqltechn/
 	install -D -m644 "$srcdir/"bootscript.sh \
 		"$pkgdir"/usr/share/u-boot/starqltechn/
+	install -D -m644 "$srcdir/"bootscript_android.sh \
+		"$pkgdir"/usr/share/u-boot/starqltechn/
+	install -D -m644 "$srcdir/"find_image_and_boot.sh \
+		"$pkgdir"/usr/share/u-boot/starqltechn/
 }
 
 
 sha512sums="
-1a51b1a75a7ab23b0011d2952e716b6d98a3a395578a99e278d8eda4c921ce015ce1f0e386a88b89e9f657edc867f00fffd11e550a91ec9ede2769d8cbfd1718  deviceinfo
+9815c6429da9df84ca802c53a68b2352edb6756dfdfa9c61b8cda3eb97ec3d28e7f4158256a868d7efd4ce0da6616f215e64111d59e335c604b1b987a66080fa  deviceinfo
 8ecd6621738b14fecfb8bb32f06fa86053649f46d6ef7e50cdc6dd44175d459a8b5f185e0b1d6168d23d6b8474ea31ae9aaf306385eb106df6489e6838b4fbe1  boot_image.its
+31dc6cf933881ac4f9512d3e78e73c151420a307058227028c4a62f8121d6b37d0f89eb9ffa3d871a0cc50767ca1ee16e0167e82021ba61562222e94969c233b  android_boot_image.its
 ba782c324c14cf0947c752b51a607ae1b08def885b0cf0afe89d1fcade3491ab2f547551eb08bd8074f608dac46bdcdf75c5c633bd7a15e6eb63a10f30994c82  payload_mock.dts
 fc9a353946a061b964b8d85ba40a55aabd5dc51ad079ce9013473fb2031f2bea7f987dc437f3e7b515e7f1eccc16c7ba0c616926f59f98382b1193e6875b50f3  bootscript.sh
+592f9480155676878a6484850b7f9526cbbe591cecb5d4acf3c71bda5826aea69fcf10324787c12f40189f0aa3ceeb65ab7836c4708afc476960cae9fae7f09b  bootscript_android.sh
+26bb890f50b6430917bb0c79fe198aa2ca8e36c618560d3867f3135bec57fd8b2dd6467c7e5d9389ac8159ccbe24f629a9c845488741fba2aa53e38b7887f6a1  find_image_and_boot.its
+bfc5da4030dd48e4de0a0c1803f583ffa8b09a712e48121096125e7906141b811e9b0c22392518f8bc270def57bfb16343a20b4a8309427bae69d2eb21c24577  find_image_and_boot.sh
 "
diff --git a/device/testing/device-samsung-starqltechn/android_boot_image.its b/device/testing/device-samsung-starqltechn/android_boot_image.its
new file mode 100644
index 00000000000..a49434dd1ac
--- /dev/null
+++ b/device/testing/device-samsung-starqltechn/android_boot_image.its
@@ -0,0 +1,68 @@
+/dts-v1/;
+
+/ {
+        description = "Samsung S9 SM-G9600 starqltechn Android FIT Image";
+        #address-cells = <1>;
+
+        images {
+                prebootscript {
+                        description = "pre Boot script";
+                        data = /incbin/("bootscript_android.sh");
+                        type = "script";
+                        compression = "none";
+                        load = <0x90000000>;
+                        entry = <0x90000000>;
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+                bootscript {
+                        description = "Boot script";
+                        data = /incbin/("bootscript_android.sh");
+                        type = "script";
+                        compression = "none";
+                        load = <0x90000000>;
+                        entry = <0x90000000>;
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+                kernel {
+                        description = "Kernel";
+                        data = /incbin/("vendor_android_boot/vendor_boot.img-kernel");
+                        type = "kernel";
+                        arch = "arm64";
+                        os = "linux";
+                        compression = "gzip";
+                        load = <0x80200000>;
+                        entry = <0x80200000>;
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+                initrd {
+                        description = "Initrd";
+                        compression = "none";
+                        data = /incbin/("vendor_android_boot/vendor_boot.img-ramdisk");
+                        type = "ramdisk";
+                        arch = "arm64";
+                        load = <0x84000000>;
+                        os = "linux";
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+        };
+
+        configurations {
+                default = "standard";
+                standard {
+                        description = "Standard Boot";
+                        kernel = "kernel";
+                        ramdisk = "initrd";
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+        };
+};
diff --git a/device/testing/device-samsung-starqltechn/bootscript_android.sh b/device/testing/device-samsung-starqltechn/bootscript_android.sh
new file mode 100644
index 00000000000..90879e20bfd
--- /dev/null
+++ b/device/testing/device-samsung-starqltechn/bootscript_android.sh
@@ -0,0 +1,22 @@
+echo "Booting Android"
+echo "searching for KASLR address..."
+
+addr=0x80000038
+addr2=0x80000050
+
+setenv arm64 0x644d5241
+until itest *$addr == 0x644d5241 && itest *$addr2 == 0x6d3a8; do
+	setexpr addr $addr + 0x1000
+	setexpr addr2 $addr2 + 0x1000
+done
+setexpr addr $addr - 0x38
+echo "KASLR address is 0x$addr"
+setenv bootm_low "0x$addr"
+setenv bootm_size 0x5000000
+
+fdt addr $prevbl_initrd_start_addr
+fdt set "/images/kernel" "load" "<0x$addr>"
+fdt set "/images/kernel" "entry" "<0x$addr>"
+fdt addr $prevbl_fdt_addr
+fdt print "/chosen"
+bootm $image_address#standard $image_address#standard $prevbl_fdt_addr
diff --git a/device/testing/device-samsung-starqltechn/deviceinfo b/device/testing/device-samsung-starqltechn/deviceinfo
index 63ea8a31536..3ee2ac30535 100644
--- a/device/testing/device-samsung-starqltechn/deviceinfo
+++ b/device/testing/device-samsung-starqltechn/deviceinfo
@@ -26,7 +26,13 @@ deviceinfo_bootimg_dtb_second="false"
 deviceinfo_bootimg_override_payload="u-boot.bin"
 deviceinfo_bootimg_override_payload_compression="gzip"
 deviceinfo_bootimg_override_payload_append_dtb="payload_mock.dtb"
-deviceinfo_bootimg_override_initramfs="boot_image.itb"
+deviceinfo_bootimg_override_initramfs="find_image_and_boot.itb boot_image.itb"
+# uncomment to dual boot PostmarketOS with Android
+# deviceinfo_bootimg_override_initramfs="find_image_and_boot.itb android_boot_image.itb boot_image.itb"
+# uncomment and place vendor boot image in /boot/vendor_boot.img file to dual boot PostmarketOS with Android
+# deviceinfo_bootimg_override_header_info_using_vendor_image="true"
+# deviceinfo_bootimg_vendor_android_boot_image="vendor_boot.img"
+# deviceinfo_bootimg_vendor_device_tree_identifiers="qcom,msm-id\s*=\s*<0x141\s*0x20001>; qcom,board-id\s*=\s*<0x08\s*0x0e>;"
 deviceinfo_flash_offset_base="0x00000000"
 deviceinfo_flash_offset_kernel="0x00008000"
 deviceinfo_flash_offset_ramdisk="0x02000000"
diff --git a/device/testing/device-samsung-starqltechn/find_image_and_boot.its b/device/testing/device-samsung-starqltechn/find_image_and_boot.its
new file mode 100644
index 00000000000..c315e6d5a0c
--- /dev/null
+++ b/device/testing/device-samsung-starqltechn/find_image_and_boot.its
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/ {
+        description = "Samsung S9 SM-G9600 starqltechn boot script";
+        #address-cells = <1>;
+
+        images {
+                bootscript {
+                        description = "Boot script";
+                        data = /incbin/("find_image_and_boot.sh");
+                        type = "script";
+                        compression = "none";
+                        load = <0x90000000>;
+                        entry = <0x90000000>;
+                        hash {
+                                algo = "sha1";
+                        };
+                };
+
+                 prebootscript {
+                         description = "pre boot script";
+                         data = /incbin/("find_image_and_boot.sh");
+                         type = "script";
+                         compression = "none";
+                         load = <0x90000000>;
+                         entry = <0x90000000>;
+                         hash {
+                                 algo = "sha1";
+                         };
+                 };
+        };
+};
diff --git a/device/testing/device-samsung-starqltechn/find_image_and_boot.sh b/device/testing/device-samsung-starqltechn/find_image_and_boot.sh
new file mode 100644
index 00000000000..daf2b3a4215
--- /dev/null
+++ b/device/testing/device-samsung-starqltechn/find_image_and_boot.sh
@@ -0,0 +1,48 @@
+echo "searching for FIT images..."
+
+ramdisk_addr=0xa2000000
+image_addresses_start=0x80000000
+image_addresses=$image_addresses_start
+image_number=0
+md $ramdisk_addr 4
+
+doodfeed=0xedfe0dd0
+if itest $ramdisk_addr <= 0xa6001000; then
+	echo "true"
+fi
+
+if itest $ramdisk_addr >= 0xa0001000; then
+	echo "false"
+fi
+
+while itest $ramdisk_addr <= 0xa6001000; do
+	if itest *$ramdisk_addr == $doodfeed; then
+		echo "address at $ramdisk_addr matches"
+		if itest $image_number != 0; then
+			echo "######## image $image_number found at $ramdisk_addr ########"
+			iminfo $ramdisk_addr
+			mw $image_addresses $ramdisk_addr 1
+			setexpr image_addresses $image_addresses + 4
+		fi
+		setexpr image_number $image_number + 1
+	fi
+	setexpr ramdisk_addr $ramdisk_addr + 0x1000
+done
+
+if itest $image_number <= 1; then
+	echo "No images found!"
+fi
+
+if itest "${key_vol_down}" -eq "1"; then
+	echo "key down pressed, booting 2nd image"
+	setexpr image_address $image_addresses_start + 4
+	setexpr image_address *$image_address
+	echo "image_address: $image_address"
+	source $image_address:bootscript
+else
+	echo "key down NOT pressed, booting 1st image"
+	setexpr image_address $image_addresses_start
+	setexpr image_address *$image_address
+	echo "image_address: $image_address"
+	source $image_address:bootscript
+fi
-- 
GitLab