db845c: Enable booting from mmc-sdcard

This is an experimental build configuration and only used to
boot AOSP on mmc sdcard on DB845c and RB5 in the LKFT lab.
Regular users should not enable this build flag and should
boot from UFS instead.

Booting from external sdcards will help prevent the internal
emmc/ufs wear off in the long run and extend the lab-life of
most of our devboards.

Set TARGET_SDCARD_BOOT=true at build time to build and boot
AOSP from mmc sdcard. This device configuration need atleast
16GB sdcard to boot from. As of today, 1st AOSP/main boot
with Linux kernel v6.7 on a 16GB Samsung EVO+ SDHCI sdcard
takes just under 3mins to boot to UI and subsequent reboot
to UI takes just over 1min.

Using U-Boot to partition and flash mmc sdcard:
To avoid flashing anything on internal UFS and boot solely
from a sdcard, we are switching to chainloading U-Boot from
ABL bootloader. For now we are using an upstream U-Boot fork
for DB845c and RB5 and its currently under work-in-progress:
https://source.devboardsforandroid.linaro.org/platform/external/u-boot/
Since upstream U-Boot only support boot image header version
2, so we are also using the same. It also helps us load and
boot with boot.img from RAM using "fastboot boot boot.img"
command in the lab. In the long run we plan to switch to
AOSP/external/u-boot project to catch up with all the
Android bootloader features. We are using U-Boot "gpt" and
"fastboot" commands to create partition table on external
sdcard and flash AOSP super and userdata images. Follow the
U-Boot instructions here to prepare a sdcard to boot AOSP:
https://devboardsforandroid.linaro.org/en/latest/devices/rb3.html#booting-aosp-from-mmc-sdcard

Loading UFS driver from vendor_dlkm partition:
The AOSP's first_stage_init mount take the first platform
block device it finds and continues with it, irrespective of
the androidboot.boot_devices bootarg. This is a blocker for
us to boot from mmc sdcard because first_stage_init always
tried to look for and mount UFS partitions. In order to
avoid touching first_stage_init boot / mount flow in
AOSP/system/core project, we will be loading UFS driver from
vendor_dlkm partition so that UFS gets probed later in the
boot cycle.

Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Change-Id: I20cd89df8b5f1fdb1bf712232284d6d754518d8f
diff --git a/db845c.mk b/db845c.mk
index 1f271bc..72b2c26 100644
--- a/db845c.mk
+++ b/db845c.mk
@@ -12,6 +12,8 @@
   TARGET_USES_BOOT_HDR_V3 ?= false
 endif
 
+TARGET_SDCARD_BOOT ?= false
+
 # Product overrides
 PRODUCT_NAME := db845c
 PRODUCT_DEVICE := db845c
diff --git a/db845c/BoardConfig.mk b/db845c/BoardConfig.mk
index 1d00b6c..881dbc7 100644
--- a/db845c/BoardConfig.mk
+++ b/db845c/BoardConfig.mk
@@ -19,14 +19,30 @@
 
 TARGET_NO_KERNEL := false
 BOARD_INCLUDE_DTB_IN_BOOTIMG := true
-ifeq ($(TARGET_USES_BOOT_HDR_V3), true)
- BOARD_BOOT_HEADER_VERSION := 3
- BOARD_KERNEL_CMDLINE += androidboot.hardware=db845c androidboot.boot_devices=soc@0/1d84000.ufshc
- BOARD_KERNEL_CMDLINE += androidboot.verifiedbootstate=orange
-else
- BOARD_BOOT_HEADER_VERSION := 4
- BOARD_BOOTCONFIG += androidboot.hardware=db845c androidboot.boot_devices=soc@0/1d84000.ufshc
- BOARD_BOOTCONFIG += androidboot.verifiedbootstate=orange
+ifeq ($(TARGET_SDCARD_BOOT), true)
+  BOARD_BOOT_HEADER_VERSION := 2
+  # Older kernel versions define mmc@ nodes as sdhci@ nodes in their device tree
+  ifneq ($(filter 5.4 5.10 5.15, $(TARGET_KERNEL_USE)),)
+    BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc@0/8804000.sdhci
+  else
+    BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc@0/8804000.mmc
+  endif
+  BOARD_KERNEL_CMDLINE += androidboot.hardware=db845c
+  BOARD_KERNEL_CMDLINE += androidboot.verifiedbootstate=orange
+  # In case we are booting from U-Boot directly and androidboot.slot_suffix
+  # is not set. Otherwise we run into the following error:
+  # "init: [libfstab] Error updating for slotselect"
+  BOARD_KERNEL_CMDLINE += androidboot.slot_suffix=_a
+else ifeq ($(TARGET_USES_BOOT_HDR_V3), true)
+    BOARD_BOOT_HEADER_VERSION := 3
+    BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc@0/1d84000.ufshc
+    BOARD_KERNEL_CMDLINE += androidboot.hardware=db845c
+    BOARD_KERNEL_CMDLINE += androidboot.verifiedbootstate=orange
+  else
+    BOARD_BOOT_HEADER_VERSION := 4
+    BOARD_BOOTCONFIG += androidboot.boot_devices=soc@0/1d84000.ufshc
+    BOARD_BOOTCONFIG += androidboot.hardware=db845c
+    BOARD_BOOTCONFIG += androidboot.verifiedbootstate=orange
 endif
 BOARD_MKBOOTIMG_ARGS := --header_version $(BOARD_BOOT_HEADER_VERSION)
 BOARD_KERNEL_BASE := 0x80000000
@@ -40,12 +56,18 @@
 
 # Image Configuration
 BOARD_BOOTIMAGE_PARTITION_SIZE := 100663296 #96M
-BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 100663296 #96M
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 21474836480 #20G
 BOARD_FLASH_BLOCK_SIZE := 4096
-# Super partition
-BOARD_SUPER_PARTITION_SIZE := 12437225472
-BOARD_DB_DYNAMIC_PARTITIONS_SIZE := 12433031168 # Reserve 4M for DAP metadata
+ifeq ($(TARGET_SDCARD_BOOT), true)
+  BOARD_USERDATAIMAGE_PARTITION_SIZE := 8589934592 #8G
+  BOARD_SUPER_PARTITION_SIZE := 4294967296 #4G
+  BOARD_DB_DYNAMIC_PARTITIONS_SIZE := 4290772992 # Reserve 4M for DAP metadata
+  BOARD_SEPOLICY_DIRS += device/linaro/dragonboard/shared/utils/sdcard-boot/sepolicy/
+else
+  BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 100663296 #96M
+  BOARD_USERDATAIMAGE_PARTITION_SIZE := 21474836480 #20G
+  BOARD_SUPER_PARTITION_SIZE := 12437225472
+  BOARD_DB_DYNAMIC_PARTITIONS_SIZE := 12433031168 # Reserve 4M for DAP metadata
+endif
 BOARD_SUPER_PARTITION_METADATA_DEVICE := super
 BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE := true
 BOARD_DB_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor system_ext product
diff --git a/device-common.mk b/device-common.mk
index c8756d9..a37f726 100644
--- a/device-common.mk
+++ b/device-common.mk
@@ -18,7 +18,14 @@
 TARGET_MODS := $(wildcard $(TARGET_KERNEL_DIR)/*.ko)
 
 BOARD_DO_NOT_STRIP_VENDOR_RAMDISK_MODULES := true
-BOARD_VENDOR_RAMDISK_KERNEL_MODULES := $(TARGET_MODS)
+BOARD_DO_NOT_STRIP_GENERIC_RAMDISK_MODULES := true
+ifeq ($(TARGET_SDCARD_BOOT), true)
+  # UFS module filename varies from ufs_qcom.ko to ufs-qcom.ko across different kernel versions
+  BOARD_VENDOR_KERNEL_MODULES := $(wildcard $(TARGET_KERNEL_DIR)/ufs*qcom.ko)
+  BOARD_GENERIC_RAMDISK_KERNEL_MODULES := $(filter-out $(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_MODS))
+else
+  BOARD_VENDOR_RAMDISK_KERNEL_MODULES := $(TARGET_MODS)
+endif
 
 PRODUCT_SHIPPING_API_LEVEL := 31
 
@@ -63,10 +70,24 @@
     system_ext \
     vendor
 
+ifeq ($(TARGET_SDCARD_BOOT), true)
+  ifneq ($(filter 5.4 5.10 5.15, $(TARGET_KERNEL_USE)),)
+    PRODUCT_COPY_FILES += \
+        device/linaro/dragonboard/shared/utils/sdcard-boot/fstab.sdhci:$(TARGET_COPY_OUT_RAMDISK)/first_stage_ramdisk/fstab.$(TARGET_HARDWARE) \
+        device/linaro/dragonboard/shared/utils/sdcard-boot/fstab.sdhci:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(TARGET_HARDWARE)
+  else
+    PRODUCT_COPY_FILES += \
+        device/linaro/dragonboard/shared/utils/sdcard-boot/fstab.mmc:$(TARGET_COPY_OUT_RAMDISK)/first_stage_ramdisk/fstab.$(TARGET_HARDWARE) \
+        device/linaro/dragonboard/shared/utils/sdcard-boot/fstab.mmc:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(TARGET_HARDWARE)
+  endif
+else
+  PRODUCT_COPY_FILES += \
+      device/linaro/dragonboard/fstab.common:$(TARGET_COPY_OUT_RAMDISK)/first_stage_ramdisk/fstab.$(TARGET_HARDWARE) \
+      device/linaro/dragonboard/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(TARGET_HARDWARE)
+endif
+
 PRODUCT_COPY_FILES += \
     $(TARGET_KERNEL_DIR)/Image.gz:kernel \
-    device/linaro/dragonboard/fstab.common:$(TARGET_COPY_OUT_RAMDISK)/first_stage_ramdisk/fstab.$(TARGET_HARDWARE) \
-    device/linaro/dragonboard/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(TARGET_HARDWARE) \
     device/linaro/dragonboard/init.common.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.$(TARGET_HARDWARE).rc \
     device/linaro/dragonboard/init.common.usb.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.$(TARGET_HARDWARE).usb.rc \
     frameworks/base/data/keyboards/Generic.kl:$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/$(TARGET_HARDWARE).kl
diff --git a/shared/utils/dlkm_loader/device.mk b/shared/utils/dlkm_loader/device.mk
index 57b951f..d4df84c 100644
--- a/shared/utils/dlkm_loader/device.mk
+++ b/shared/utils/dlkm_loader/device.mk
@@ -2,5 +2,10 @@
 PRODUCT_PACKAGES += dlkm_loader
 
 # List of modules that should not load automatically
+ifeq ($(TARGET_SDCARD_BOOT), true)
+PRODUCT_COPY_FILES += \
+    device/linaro/dragonboard/shared/utils/dlkm_loader/vendor_ramdisk.modules.blocklist:$(TARGET_COPY_OUT_RAMDISK)/lib/modules/modules.blocklist
+else
 PRODUCT_COPY_FILES += \
     device/linaro/dragonboard/shared/utils/dlkm_loader/vendor_ramdisk.modules.blocklist:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/lib/modules/modules.blocklist
+endif
diff --git a/shared/utils/init.utils.rc b/shared/utils/init.utils.rc
index 38d8d00..a17edfd 100644
--- a/shared/utils/init.utils.rc
+++ b/shared/utils/init.utils.rc
@@ -26,7 +26,7 @@
     disabled
     oneshot
 
-service rmtfs /vendor/bin/rmtfs -o /dev/block/platform/soc@0/1d84000.ufshc/by-name -P -r -s
+service rmtfs /vendor/bin/rmtfs -o /dev/block/by-name -P -r -s
     class core
     user root
     group system
diff --git a/shared/utils/sdcard-boot/fstab.mmc b/shared/utils/sdcard-boot/fstab.mmc
new file mode 100644
index 0000000..387a0cd
--- /dev/null
+++ b/shared/utils/sdcard-boot/fstab.mmc
@@ -0,0 +1,11 @@
+system		/system		erofs	ro				wait,logical,first_stage_mount,slotselect
+/dev/block/platform/soc@0/8804000.mmc/by-name/userdata	/data		ext4	discard,noatime,noauto_da_alloc,data=ordered,user_xattr,barrier=1,inlinecrypt	latemount,wait,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota
+/dev/block/platform/soc@0/8804000.mmc/by-name/metadata	/metadata	ext4	noatime,nosuid,nodev,discard					wait,formattable,first_stage_mount,check
+/dev/block/platform/soc@0/8804000.mmc/by-name/misc /misc emmc defaults defaults
+/devices/platform/soc@0/a8f8800.usb/*/usb*		auto	auto	defaults	voldmanaged=usb1:auto
+/devices/platform/soc@0/1c00000.pci/*/usb*		auto	auto	defaults	voldmanaged=usb2:auto
+vendor		/vendor		erofs	ro				wait,logical,first_stage_mount,slotselect
+system_ext	/system_ext	erofs	ro				wait,logical,first_stage_mount,slotselect
+product		/product	erofs	ro				wait,logical,first_stage_mount,slotselect
+system_dlkm	/system_dlkm	erofs	ro				wait,logical,first_stage_mount,slotselect
+vendor_dlkm	/vendor_dlkm	erofs	ro				wait,logical,first_stage_mount,slotselect
diff --git a/shared/utils/sdcard-boot/fstab.sdhci b/shared/utils/sdcard-boot/fstab.sdhci
new file mode 100644
index 0000000..c385ba6
--- /dev/null
+++ b/shared/utils/sdcard-boot/fstab.sdhci
@@ -0,0 +1,11 @@
+system		/system		erofs	ro				wait,logical,first_stage_mount,slotselect
+/dev/block/platform/soc@0/8804000.sdhci/by-name/userdata	/data		ext4	discard,noatime,noauto_da_alloc,data=ordered,user_xattr,barrier=1,inlinecrypt	latemount,wait,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota
+/dev/block/platform/soc@0/8804000.sdhci/by-name/metadata	/metadata	ext4	noatime,nosuid,nodev,discard					wait,formattable,first_stage_mount,check
+/dev/block/platform/soc@0/8804000.sdhci/by-name/misc /misc emmc defaults defaults
+/devices/platform/soc@0/a8f8800.usb/*/usb*		auto	auto	defaults	voldmanaged=usb1:auto
+/devices/platform/soc@0/1c00000.pci/*/usb*		auto	auto	defaults	voldmanaged=usb2:auto
+vendor		/vendor		erofs	ro				wait,logical,first_stage_mount,slotselect
+system_ext	/system_ext	erofs	ro				wait,logical,first_stage_mount,slotselect
+product		/product	erofs	ro				wait,logical,first_stage_mount,slotselect
+system_dlkm	/system_dlkm	erofs	ro				wait,logical,first_stage_mount,slotselect
+vendor_dlkm	/vendor_dlkm	erofs	ro				wait,logical,first_stage_mount,slotselect
diff --git a/shared/utils/sdcard-boot/sepolicy/file_contexts b/shared/utils/sdcard-boot/sepolicy/file_contexts
new file mode 100644
index 0000000..79d5de8
--- /dev/null
+++ b/shared/utils/sdcard-boot/sepolicy/file_contexts
@@ -0,0 +1,15 @@
+/dev/block/platform/soc@0/8804000\.mmc/by-name/fsc		u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/fsg		u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/modemst[12]	u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/metadata		u:object_r:metadata_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/super		u:object_r:super_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/userdata		u:object_r:userdata_block_device:s0
+/dev/block/platform/soc@0/8804000\.mmc/by-name/misc		u:object_r:misc_block_device:s0
+
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/fsc		u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/fsg		u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/modemst[12]	u:object_r:modem_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/metadata		u:object_r:metadata_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/super		u:object_r:super_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/userdata		u:object_r:userdata_block_device:s0
+/dev/block/platform/soc@0/8804000\.sdhci/by-name/misc		u:object_r:misc_block_device:s0