[PATCH v2 2/5] board: samsung: e850-96: Add routines for checking boot dev

Sam Protsenko semen.protsenko at linaro.org
Mon Oct 27 07:14:49 CET 2025


Implement functionality to check the current boot device (a device where
the SoC ROM code is loading the bootloaders from). The boot device order
can be changed using the SW1 DIP switch on the E850-96 board (which
controls XOM SoC lines), as stated in [1].

The boot device information is requested from EL3 software using the
corresponding SMC call, which in turn reads it from iRAM memory, which
was written by the ROM code. New routines decode that data and allow the
user to check the current boot device, boot order, etc. That API can be
used further to implement different code flows depending on the current
boot device, e.g.:

  - on eMMC boot: obtain the firmware binaries from eMMC
  - on USB boot: download the firmware over USB instead

No functional change; this patch only adds new functionality but it's
not used yet.

[1] doc/board/samsung/e850-96.rst

Signed-off-by: Sam Protsenko <semen.protsenko at linaro.org>
---
Changes in v2:
  - (none)

 board/samsung/e850-96/Makefile  |  2 +-
 board/samsung/e850-96/bootdev.c | 99 +++++++++++++++++++++++++++++++++
 board/samsung/e850-96/bootdev.h | 23 ++++++++
 3 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 board/samsung/e850-96/bootdev.c
 create mode 100644 board/samsung/e850-96/bootdev.h

diff --git a/board/samsung/e850-96/Makefile b/board/samsung/e850-96/Makefile
index 76b8d47994e8..e9c62d3181fd 100644
--- a/board/samsung/e850-96/Makefile
+++ b/board/samsung/e850-96/Makefile
@@ -3,4 +3,4 @@
 # Copyright (C) 2024, Linaro Limited
 # Sam Protsenko <semen.protsenko at linaro.org>
 
-obj-y := e850-96.o fw.o acpm.o pmic.o
+obj-y := e850-96.o fw.o acpm.o pmic.o bootdev.o
diff --git a/board/samsung/e850-96/bootdev.c b/board/samsung/e850-96/bootdev.c
new file mode 100644
index 000000000000..7d5ae7128f49
--- /dev/null
+++ b/board/samsung/e850-96/bootdev.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Author: Sam Protsenko <semen.protsenko at linaro.org>
+ *
+ * Routines for checking current boot device.
+ */
+
+#include <linux/arm-smccc.h>
+#include <vsprintf.h>
+#include "bootdev.h"
+
+/* Flag from BL2 bootloader in RAM */
+#define BL2_TAG_ADDR			0x80000000	/* DRAM base */
+#define BL2_TAG				0xabcdef
+
+/* Boot device info location in iRAM (only accessible from EL3) */
+#define IRAM_BASE			0x02020000
+#define BOOTDEVICE_INFO_ADDR		(IRAM_BASE + 0x64)
+
+/* SMC call for getting boot device information from EL3 monitor */
+#define SMC_CMD_CHECK_SECOND_BOOT	-233
+
+/* Boot device constants for the encoded boot device info value */
+#define BD_NO_DEVICE			0x0
+#define BD_UFS				0x1
+#define BD_EMMC				0x2
+#define BD_ERROR			0x3
+#define BD_USB				0x4
+#define BD_SDMMC			0x5
+#define BD_UFS_CARD			0x6
+#define BD_SPI				0x7
+
+/* If BL2 bootloader wasn't executed, it means U-Boot is running via JTAG */
+static bool bootdev_is_jtag_session(void)
+{
+	u32 bl2_tag_val = *(u32 *)BL2_TAG_ADDR;
+
+	return bl2_tag_val != BL2_TAG;
+}
+
+/* Obtain boot device information encoded in 32-bit value */
+static u32 bootdev_get_info(void)
+{
+	u32 info;
+
+	/*
+	 * On regular boot U-Boot is executed by BL2 bootloader, and is running
+	 * in EL1 mode, so the boot device information has to be obtained via
+	 * SMC call from EL3 software (EL3 monitor), which can read that info
+	 * from the protected iRAM memory. If U-Boot is running via TRACE32 JTAG
+	 * (in EL3 mode), read the boot device info directly from iRAM, as EL3
+	 * software might not be available.
+	 */
+	if (bootdev_is_jtag_session()) {
+		info = *(u32 *)BOOTDEVICE_INFO_ADDR;
+	} else {
+		struct arm_smccc_res res;
+
+		arm_smccc_smc(SMC_CMD_CHECK_SECOND_BOOT, 0, 0, 0, 0, 0, 0, 0,
+			      &res);
+		info = (u32)res.a2;
+	}
+
+	return info;
+}
+
+enum bootdev bootdev_get_current(void)
+{
+	u32 info, magic, order, dev;
+
+	info = bootdev_get_info();
+	magic = info >> 24;
+	order = info & 0xf;
+	dev = (info >> (4 * order)) & 0xf;
+
+	if (magic != 0xcb)
+		panic("Abnormal boot");
+
+	switch (dev) {
+	case BD_UFS:
+		return BOOTDEV_UFS;
+	case BD_EMMC:
+		return BOOTDEV_EMMC;
+	case BD_USB:
+		return BOOTDEV_USB;
+	case BD_SDMMC:
+		return BOOTDEV_SD;
+	default:
+		return BOOTDEV_ERROR;
+	}
+
+	return BOOTDEV_ERROR;
+}
+
+bool bootdev_is_usb(void)
+{
+	return bootdev_get_current() == BOOTDEV_USB;
+}
diff --git a/board/samsung/e850-96/bootdev.h b/board/samsung/e850-96/bootdev.h
new file mode 100644
index 000000000000..5f454bf00901
--- /dev/null
+++ b/board/samsung/e850-96/bootdev.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2025 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko at linaro.org>
+ */
+
+#ifndef __E850_96_BOOTDEV_H
+#define __E850_96_BOOTDEV_H
+
+#include <stdbool.h>
+
+enum bootdev {
+	BOOTDEV_ERROR,
+	BOOTDEV_SD,
+	BOOTDEV_EMMC,
+	BOOTDEV_USB,
+	BOOTDEV_UFS,
+};
+
+enum bootdev bootdev_get_current(void);
+bool bootdev_is_usb(void);
+
+#endif /* __E850_96_BOOTDEV_H */
-- 
2.39.5



More information about the U-Boot mailing list