The Qualcomm Snapdragon888 hardware development kit (HDK) is a single-board computer (SBC) built on the Snapdragon 888 mobile platform.
Specifications:
- CPU: Qualcomm Kryo 680 (4xCortex-A73 + 4xCortex-A53)
- GPU: Qualcomm Adreno 660 GPU
- SoC: SM8350P - Codename
lahaina
- Model Name: HDK8350
- Arch: ARM64
The stock OS shipped with the board is Android 11.
Mainline Linux kernel support was added in release v5.13-rc1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/qcom/sm8350-hdk.dts?h=v5.13-rc1
Power control
The board is powered via a DC Power Jack 12V/5A DC input.
Serial console
The UART serial console can be accessed via the USB 2.0 micro-B port.
Network connectivity
The board has a standard Gigabit Ethernet RJ45 connector for Ethernet connectivity.
Wi-Fi 802.11a/b/g/n/ac/ax 2.4/5GHz is also supported.
Fastboot
The stock bootloader supports the fastboot protocol via the USB 3.1 Type C port.
The board can be booted in fastboot mode by keeping the vol-
button pressed along with the PON
button.
The stock Android bootloader can be forced to enter fastboot mode at every boot, by wiping the boot_a
/boot_b
partitions:
fastboot erase boot_X
Bootloader
The SM8350-HDK board runs XBL (eXtensible BootLoader), which contains:
- A SBL (Secondary BootLoader) that initializes the RAM
- The UEFI firmware; this in turn loads abl. abl is built on top of Tianocore/EDK2 and contains a UEFI application that implements both the fastboot protocol and a Linux bootloader.
The stock Android bootloader allows to load kernel images up to 49.5MB in size (uncompressed): see https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/blob/LA.UM.9.12.r1-14600-SMxx50.QSSI13.0/QcomModulePkg/QcomModulePkg.dec#L149).
The memory layout can be changed to enable bigger images if needed, see e.g. https://git.linaro.org/landing-teams/working/qualcomm/abl.git/commit/?id=d8a9dc3ccc0342e77ba5251ab675b4a86ae737c1.
Arbitrary kernel+dtb+ramdisk combinations can be loaded by the stock Android bootloader using the fastboot boot
command, without flashing the images onto the device.
A bootable image can be built using the mkbootimg
tool (included in the android-tools-mkbootimg
package for Debian) - e.g.:
$ mkbootimg --kernel Image+dtb --pagesize 4096 --base 0x80000000 --ramdisk bullseye-initramfs-arm64.cpio.gz -o boot.img
Note: Extra command line options can be appended through the --cmdline
option.
The dtb blob has been appended to the kernel Image first, with:
$ cat Image.gz sm8350-hdk.dtb > Image+dtb
The image can then be loaded on the device with:
$ fastboot boot boot.img
Lab notes and trouble shooting
-
The board powers on automatically as soon the USB-C cable is connected, without the need to press the
PON
button. -
In order to switch off the power completely, the USB-C cable needs to be unplugged along with the main power adapter jack.
-
An YKUSH switchable hub can be used to automate the connection/disconnection of the USB-C cable in LAVA.
-
The bootable slot can be set using the following command:
$ fastboot set_active <a/b>
-
ABL keeps count of the successful boots on the active slot. Userspace is supposed to mark the slot as bootable upon success. This does not happen when booting Linux distros such as Debian; ABL marks the active slot as unbootable after a few attempts and eventually switches to the
_b
slot (i.e. theSlot _a is unbootable, trying alternate slot
error is printed and fastboot reportsFAILED (remote: 'Failed to load/authenticate boot image: Load Error')
). A way to circumvent the problem when not implementing a/b updates is to runfastboot set_active a
before booting/flashing the image. In LAVA, this can be added as a command in the boot action:- boot: method: fastboot commands: - 'set_active a' ...
Board setup for LAVA integration
In order to setup the board for automation in LAVA using fastboot
and keeping the stock bootloader, the boards needs to be set up to enter fastboot mode at boot:
- Install
fastboot
on the host (e.g.apt install fastboot
on Debian). - Connect a USB-to-USB micro-B cable to the USB 2.0 micro-B port.
- Power on the board by connecting the power.
- While keeping the
vol-
button pressed, press thePON
button for ~1 second. The bootloader will enter fastboot mode and the following should be reported in the serial console:KeyPress:2, BootReason:0 Fastboot=1, Recovery:0
- Connect the USB-to-USB type-C cable to the USB 3.1 Type C port.
- Check that the device is correctly detected by the host:
$ fastboot devices 3658e3af fastboot
- Wipe the
boot
anddtbo
partitions:$ fastboot erase boot_a $ fastboot erase dtbo_a
- Power cycle the board; the bootloader should enter fastboot mode automatically.
Example LAVA job definitions for ramdisk and NFS tests
Notes:
-
The
download
deploy method can be used to fetch the kernel image, the dtb blob and the ramdisk archive; thepostprocess
command can then be used to assemble the boot image. Any extra command line option needs to be specified in the--cmdline
option on themkbootimg
command. -
Docker images with support for
fastboot
andmkbootimg
are available in the health-check-docker registry. These can be used to assemble the boot image within the LAVA job and to boot the board without the need to installmkbootimg
orfastboot
on the dispatchers. This also help preventing concurrency problems when trying to access more than one fastboot device at once on the same worker (see: https://docs.lavasoftware.org/lava/integrate-fastboot.html#fastboot). -
When booting just a ramdisk in LAVA, the test overlay can be unpacked after the boot+login phase using the
transfer_overlay
property. -
NFS boot using the latest stable kernel (i.e.
v5.19.14
at the time of writing) configured w/ the stock defconfig fails; the drivers for the onboard USB controller and for the onboard USB to Ethernet Controller (i.e. LAN7800 -> http://ww1.microchip.com/downloads/en/DeviceDoc/50002552A.pdf) come up too late in the boot process, preventing the IP from being assigned in time for mounting the NFS (both drivers are compiled as modules). NFS boot succeeds with the following changes in the defconfig:--- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -379,7 +379,7 @@ CONFIG_USB_BRCMSTB=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_RTL8152=m -CONFIG_USB_LAN78XX=m +CONFIG_USB_LAN78XX=y CONFIG_USB_USBNET=m CONFIG_USB_NET_DM9601=m CONFIG_USB_NET_SR9800=m @@ -1193,7 +1193,7 @@ CONFIG_PHY_HISI_INNO_USB2=y CONFIG_PHY_MVEBU_CP110_COMPHY=y CONFIG_PHY_MTK_TPHY=y CONFIG_PHY_QCOM_PCIE2=m -CONFIG_PHY_QCOM_QMP=m +CONFIG_PHY_QCOM_QMP=y CONFIG_PHY_QCOM_QUSB2=m CONFIG_PHY_QCOM_USB_HS=y CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y
Example LAVA jobs for ramdisk and NFS boot are reported below for reference.
Ramdisk
device_type: sm8350-hdk
job_name: sm8350-hdk ramdisk test
timeouts:
job:
minutes: 10
action:
minutes: 5
connection:
minutes: 1
priority: high
visibility: public
actions:
- deploy:
to: downloads
images:
kernel:
url: https://images.collabora.com/qa/kernel/linux-v5.19.14/arm64/defconfig/gcc-10/Image
dtb:
url: https://images.collabora.com/qa/kernel/linux-v5.19.14/arm64/defconfig/gcc-10/dtbs/qcom/sm8350-hdk.dtb
ramdisk:
url: https://gitlab.collabora.com/lava/health-check-images/-/jobs/artifacts/main/raw/bullseye/bullseye-initramfs-arm64.cpio.gz?job=build+bullseye+image:+[arm64,+initramfs]
compression: gz
format: cpio.newc
overlays:
modules:
url: https://images.collabora.com/qa/kernel/linux-v5.19.14/arm64/defconfig/gcc-10/modules.tar.xz
compression: xz
format: tar
path: /
postprocess:
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
steps:
- gzip Image
- cat Image.gz sm8350-hdk.dtb > Image.gz+dtb
- mkbootimg --kernel Image.gz+dtb --ramdisk bullseye-initramfs-arm64.cpio.gz --pagesize 4096 --base 0x80000000 -o boot.img
- deploy:
to: fastboot
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
images:
boot:
url: downloads://boot.img
- boot:
method: fastboot
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
commands:
- 'set_active a'
auto_login:
login_prompt: 'login:'
username: 'user'
password_prompt: 'Password:'
password: user
login_commands:
- sudo su
- /usr/lib/systemd/systemd-time-wait-sync
transfer_overlay:
transfer_method: http
download_command: wget -S --progress=dot:giga
unpack_command: tar -C / -xzf
prompts:
- 'user@health'
- 'root@health'
- test:
definitions:
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: dmesg/dmesg.yaml
name: dmesg-tests
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: temperature/temperature.yaml
name: temperature-tests
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: network/network.yaml
name: network-tests
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: network/device_ip.yaml
name: device-ip-tests
NFS
device_type: sm8350-hdk
job_name: sm8350-hdk nfs test
timeouts:
job:
minutes: 10
action:
minutes: 5
connection:
minutes: 1
priority: high
visibility: public
actions:
- deploy:
to: nfs
nfsrootfs:
url: https://gitlab.collabora.com/lava/health-check-images/-/jobs/artifacts/main/raw/bullseye/bullseye-rootfs-arm64.tar.gz?job=build+bullseye+image:+[arm64,+rootfs]
compression: gz
modules:
url: https://images.collabora.com/lava/boot/sm8350-hdk/modules.tar.gz
compression: gz
- deploy:
to: downloads
images:
kernel:
url: https://images.collabora.com/lava/boot/sm8350-hdk/Image.gz
dtb:
url: https://images.collabora.com/lava/boot/sm8350-hdk/sm8350-hdk.dtb
ramdisk:
url: https://gitlab.collabora.com/lava/health-check-images/-/jobs/artifacts/main/raw/bullseye/bullseye-rootfs-arm64-initramfs.gz?job=build+bullseye+image:+[arm64,+rootfs]
compression: gz
format: cpio.newc
overlays:
modules:
url: https://images.collabora.com/lava/boot/sm8350-hdk/modules.tar.gz
compression: gz
format: tar
path: /
postprocess:
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
steps:
- cat Image.gz sm8350-hdk.dtb > Image.gz+dtb
- mkbootimg --kernel Image.gz+dtb --cmdline "console=ttyMSM0,115200n8 root=/dev/nfs rw nfsroot=$NFS_SERVER_IP:$NFS_ROOTFS,tcp,hard rootwait ip=dhcp" --ramdisk bullseye-rootfs-arm64-initramfs.gz --pagesize 4096 --base 0x80000000 -o boot.img
- deploy:
to: fastboot
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
images:
boot:
url: downloads://boot.img
- boot:
method: fastboot
docker:
image: registry.gitlab.collabora.com/lava/health-check-docker
commands:
- 'set_active a'
auto_login:
login_prompt: 'login:'
username: 'user'
password_prompt: 'Password:'
password: user
login_commands:
- sudo su
- /usr/lib/systemd/systemd-time-wait-sync
prompts:
- 'user@health'
- 'root@health'
- test:
definitions:
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: dmesg/dmesg.yaml
name: dmesg-tests
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: temperature/temperature.yaml
name: temperature-tests
- repository: https://gitlab.collabora.com/lava/functional-tests.git
from: git
history: no
path: network/network.yaml
name: network-tests