From 3b9f3620b8a26b8b2d580371eefd140791d124e4 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:39 +0530 Subject: board: samsung: exynos-mobile: simplify parsing RAM banks from device tree Remove the baked-in bank addresses used for figuring out RAM banks from device tree. Instead, sequentially fill in the bank addresses and sizes, and doing away with an extra array for specifying bases. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 38 +++++++++++------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 8ef38816abf..915bda64082 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -27,7 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; struct exynos_board_info { const char *name; const char *chip; - const u64 *const dram_bank_bases; char serial[64]; @@ -54,10 +53,6 @@ static struct mm_region exynos_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { struct mm_region *mem_map = exynos_mem_map; -static const u64 exynos7870_common_dram_bank_bases[CONFIG_NR_DRAM_BANKS] = { - 0x40000000, 0x80000000, 0x100000000, -}; - static const char *exynos_prev_bl_get_bootargs(void) { void *prev_bl_fdt_base = (void *)get_prev_bl_fdt_addr(); @@ -157,7 +152,6 @@ static struct exynos_board_info exynos_board_info_match[] = { /* Samsung Galaxy A2 Core */ .name = "a2corelte", .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, .match = exynos7870_fdt_match, .match_model = "A260", .match_max_rev = U8_MAX, @@ -165,7 +159,6 @@ static struct exynos_board_info exynos_board_info_match[] = { /* Samsung Galaxy J6 */ .name = "j6lte", .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, .match = exynos7870_fdt_match, .match_model = "J600", .match_max_rev = U8_MAX, @@ -173,18 +166,17 @@ static struct exynos_board_info exynos_board_info_match[] = { /* Samsung Galaxy J7 Prime */ .name = "on7xelte", .chip = "exynos7870", - .dram_bank_bases = exynos7870_common_dram_bank_bases, .match = exynos7870_fdt_match, .match_model = "G610", .match_max_rev = U8_MAX, }, }; -static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, - const void *fdt_base) +static void exynos_parse_dram_banks(const void *fdt_base) { u64 mem_addr, mem_size = 0; - u32 na, ns, i, j; + u32 na, ns, i; + int index = 1; int offset; if (fdt_check_header(fdt_base) < 0) @@ -199,6 +191,9 @@ static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, continue; for (i = 0; ; i++) { + if (index > CONFIG_NR_DRAM_BANKS) + break; + mem_addr = fdtdec_get_addr_size_fixed(fdt_base, offset, "reg", i, na, ns, &mem_size, false); @@ -208,17 +203,12 @@ static void exynos_parse_dram_banks(const struct exynos_board_info *board_info, if (!mem_size) continue; - for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) { - if (board_info->dram_bank_bases[j] != mem_addr) - continue; - - mem_map[j + 1].phys = mem_addr; - mem_map[j + 1].virt = mem_addr; - mem_map[j + 1].size = mem_size; - mem_map[j + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE; - break; - } + mem_map[index].phys = mem_addr; + mem_map[index].virt = mem_addr; + mem_map[index].size = mem_size; + mem_map[index].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + index++; } } } @@ -334,7 +324,7 @@ int board_early_init_f(void) return -ENODATA; board_info = (const struct exynos_board_info *)gd->board_type; - exynos_parse_dram_banks(board_info, gd->fdt_blob); + exynos_parse_dram_banks(gd->fdt_blob); /* * Some devices have multiple variants based on the amount of * memory and internal storage. The lowest bank base has been @@ -342,7 +332,7 @@ int board_early_init_f(void) * For variants with more memory, the previous bootloader should * overlay the devicetree with the required extra memory ranges. */ - exynos_parse_dram_banks(board_info, (const void *)get_prev_bl_fdt_addr()); + exynos_parse_dram_banks((const void *)get_prev_bl_fdt_addr()); return 0; } -- cgit v1.2.3 From 23ad0660c11b72a9f720362c801e2e47e9ecd4dc Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:40 +0530 Subject: board: samsung: exynos-mobile: resolve env vars without board_info data Move environment variable setup procedure to exynos_env_setup(). This function is independent of data from exynos_board_info as it is due for removal in the succeding commits. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 89 +++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 17 deletions(-) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 915bda64082..c17d7052b1c 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -18,6 +18,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -213,6 +214,76 @@ static void exynos_parse_dram_banks(const void *fdt_base) } } +static void exynos_env_setup(void) +{ + const char *bootargs = exynos_prev_bl_get_bootargs(); + const char *dev_compatible, *soc_compatible; + char *ptr; + char buf[128]; + int nr_compatibles; + int offset; + int ret; + + if (bootargs) { + /* Read the cmdline property which stores the serial number. */ + ret = cmdline_get_arg(bootargs, "androidboot.serialno", &offset); + if (ret > 0) { + strlcpy(buf, bootargs + offset, ret); + env_set("serial#", buf); + } + } + + nr_compatibles = ofnode_read_string_count(ofnode_root(), "compatible"); + if (nr_compatibles < 2) { + log_warning("%s: expected 2 or more compatible strings\n", + __func__); + return; + } + + ret = ofnode_read_string_index(ofnode_root(), "compatible", + nr_compatibles - 1, &soc_compatible); + if (ret) { + log_warning("%s: failed to read SoC compatible\n", + __func__); + return; + } + + ret = ofnode_read_string_index(ofnode_root(), "compatible", 0, + &dev_compatible); + if (ret) { + log_warning("%s: failed to read device compatible\n", + __func__); + return; + } + + /* , => platform = */ + ptr = strchr(soc_compatible, ','); + if (ptr) + soc_compatible = ptr + 1; + env_set("platform", soc_compatible); + + /* , => board = - */ + strlcpy(buf, dev_compatible, sizeof(buf) - 1); + ptr = strchr(buf, ','); + if (ptr) + *ptr = '-'; + env_set("board", buf); + + /* + * NOTE: Board name usually goes as -, but + * upstream device trees for Exynos SoCs are -. + * Extraction of from the board name is required. + */ + ptr = strchr(dev_compatible, ','); + if (ptr) + dev_compatible = ptr + 1; + + /* EFI booting requires the path to correct DTB, specify it here. */ + snprintf(buf, sizeof(buf), "exynos/%s-%s.dtb", soc_compatible, + dev_compatible); + env_set("fdtfile", buf); +} + static int exynos_fastboot_setup(void) { struct blk_desc *blk_dev; @@ -371,23 +442,7 @@ int board_init(void) int misc_init_r(void) { - const struct exynos_board_info *board_info; - char buf[128]; - - if (!gd->board_type) - return -ENODATA; - board_info = (const struct exynos_board_info *)gd->board_type; - - env_set("platform", board_info->chip); - env_set("board", board_info->name); - - if (strlen(board_info->serial)) - env_set("serial#", board_info->serial); - - /* EFI booting requires the path to correct dtb, specify it here. */ - snprintf(buf, sizeof(buf), "exynos/%s-%s.dtb", board_info->chip, - board_info->name); - env_set("fdtfile", buf); + exynos_env_setup(); return exynos_fastboot_setup(); } -- cgit v1.2.3 From 6220037e7c1bb2086f862bc031b2bfd14009d865 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:41 +0530 Subject: board: samsung: exynos-mobile: disable MULTI_DTB_FIT support MULTI_DTB_FIT allowed a single U-Boot image to be booted in multiple devices, but it was not a scalable solution; as more devices are added, the U-Boot binary is bound to increase, space taken up by devicetrees which are not even used. The other approach is to be able to build separate images for multiple devices using the same "board" defined in U-Boot. This is used by qcom_phone to support muitiple devices. Follow the said approach for Exynos devices as well, disable MULTI_DTB_FIT for this board. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 154 ---------------------------- 1 file changed, 154 deletions(-) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index c17d7052b1c..412dfa7555c 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -25,17 +24,6 @@ DECLARE_GLOBAL_DATA_PTR; #define lmb_alloc(size, addr) \ lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE) -struct exynos_board_info { - const char *name; - const char *chip; - - char serial[64]; - - int (*const match)(struct exynos_board_info *); - const char *match_model; - const u8 match_max_rev; -}; - /* * The memory mapping includes all DRAM banks, along with the * peripheral block, and a sentinel at the end. This is filled in @@ -85,94 +73,6 @@ static const char *exynos_prev_bl_get_bootargs(void) return bootargs_prop->data; } -static int exynos7870_fdt_match(struct exynos_board_info *board_info) -{ - const char *prev_bl_bootargs; - int val, ret; - - prev_bl_bootargs = exynos_prev_bl_get_bootargs(); - if (!prev_bl_bootargs) - return -1; - - /* - * Read the cmdline property which stores the - * bootloader/firmware version. An example value of the option - * can be: "J600GDXU3ARH5". This can be used to verify the model - * of the device. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.bootloader", &val); - if (ret < 0) { - log_err("%s: unable to find property for bootloader version (%d)\n", - __func__, ret); - return -1; - } - - if (strncmp(prev_bl_bootargs + val, board_info->match_model, - strlen(board_info->match_model))) - return -1; - - /* - * Read the cmdline property which stores the hardware revision. - * This is required to allow selecting one of multiple dtbs - * available of a single device, varying in hardware changes in - * different revisions. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.revision", &val); - if (ret < 0) - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.hw_rev", &val); - if (ret < 0) { - log_err("%s: unable to find property for bootloader revision (%d)\n", - __func__, ret); - return -1; - } - - if (strtoul(prev_bl_bootargs + val, NULL, 10) > board_info->match_max_rev) - return -1; - - /* - * Read the cmdline property which stores the serial number. - * Store this in the board info struct. - */ - ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.serialno", &val); - if (ret > 0) - strlcpy(board_info->serial, prev_bl_bootargs + val, ret); - - return 0; -} - -/* - * This array is used for matching the models and revisions with the - * devicetree used by U-Boot. This allows a single U-Boot to work on - * multiple devices. - * - * Entries are kept in lexicographical order of board SoCs, followed by - * board names. - */ -static struct exynos_board_info exynos_board_info_match[] = { - { - /* Samsung Galaxy A2 Core */ - .name = "a2corelte", - .chip = "exynos7870", - .match = exynos7870_fdt_match, - .match_model = "A260", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J6 */ - .name = "j6lte", - .chip = "exynos7870", - .match = exynos7870_fdt_match, - .match_model = "J600", - .match_max_rev = U8_MAX, - }, { - /* Samsung Galaxy J7 Prime */ - .name = "on7xelte", - .chip = "exynos7870", - .match = exynos7870_fdt_match, - .match_model = "G610", - .match_max_rev = U8_MAX, - }, -}; - static void exynos_parse_dram_banks(const void *fdt_base) { u64 mem_addr, mem_size = 0; @@ -331,46 +231,6 @@ static int exynos_fastboot_setup(void) return 0; } -int board_fit_config_name_match(const char *name) -{ - struct exynos_board_info *board_info; - char buf[128]; - unsigned int i; - int ret; - - /* - * Iterate over exynos_board_info_match[] to select the - * appropriate board info struct. If not found, exit. - */ - for (i = 0; i < ARRAY_SIZE(exynos_board_info_match); i++) { - board_info = exynos_board_info_match + i; - snprintf(buf, sizeof(buf), "%s-%s", board_info->chip, - board_info->name); - - if (!strcmp(name, buf)) - break; - } - if (i == ARRAY_SIZE(exynos_board_info_match)) - return -1; - - /* - * Execute match logic for the target board. This is separated - * as the process may be different for multiple boards. - */ - ret = board_info->match(board_info); - if (ret) - return ret; - - /* - * Store the correct board info struct in gd->board_type to - * allow other functions to access it. - */ - gd->board_type = (ulong)board_info; - log_debug("%s: device detected: %s\n", __func__, name); - - return 0; -} - int timer_init(void) { ofnode timer_node; @@ -389,21 +249,7 @@ int timer_init(void) int board_early_init_f(void) { - const struct exynos_board_info *board_info; - - if (!gd->board_type) - return -ENODATA; - board_info = (const struct exynos_board_info *)gd->board_type; - exynos_parse_dram_banks(gd->fdt_blob); - /* - * Some devices have multiple variants based on the amount of - * memory and internal storage. The lowest bank base has been - * observed to have the same memory range in all board variants. - * For variants with more memory, the previous bootloader should - * overlay the devicetree with the required extra memory ranges. - */ - exynos_parse_dram_banks((const void *)get_prev_bl_fdt_addr()); return 0; } -- cgit v1.2.3 From e215c1a558f0c01cdefd9cf90b190bb220c058b6 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 3 Feb 2026 18:38:42 +0530 Subject: board: samsung: exynos-mobile: enable OF_BOARD support OF_BOARD allows to choose the internal device tree in runtime. Use it to pass the external FDT as an internal one if it is not present. This approach is also used by qcom-phone, and it reduces boot image size. It is expected that an external FDT is present as U-Boot is packaged as an Android boot image. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 412dfa7555c..1f61f28de5f 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -231,6 +231,15 @@ static int exynos_fastboot_setup(void) return 0; } +int board_fdt_blob_setup(void **fdtp) +{ + /* If internal FDT is not available, use the external FDT instead. */ + if (fdt_check_header(*fdtp)) + *fdtp = (void *)get_prev_bl_fdt_addr(); + + return 0; +} + int timer_init(void) { ofnode timer_node; -- cgit v1.2.3 From db0fe21bd38f27f570ce16670ccad567efd596f4 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 24 Feb 2026 21:07:09 +0530 Subject: board: samsung: exynos-mobile: use blkmap for booting from userdata subpartitions Some distributions tend to provide a single combined image with EFS and the system root filesystem. Flashing it as-is in a single partition (usually done in userdata partition as it is the largest) is not bootable as U-Boot does not understand subpartitions. Use blkmap to map the userdata partition into its own block device. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 45 +++++++++++++++++++++++++++ board/samsung/exynos-mobile/exynos-mobile.env | 5 +++ 2 files changed, 50 insertions(+) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index 1f61f28de5f..c5e1b186ae3 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -184,6 +184,45 @@ static void exynos_env_setup(void) env_set("fdtfile", buf); } +static int exynos_blk_env_setup(void) +{ + const char *blk_ifname; + int blk_dev = 0; + struct blk_desc *blk_desc; + struct disk_partition info = {0}; + unsigned long largest_part_start = 0, largest_part_size = 0; + int i; + + blk_ifname = "mmc"; + blk_desc = blk_get_dev(blk_ifname, blk_dev); + if (!blk_desc) { + log_err("%s: required mmc device not available\n", __func__); + return -ENODEV; + } + + for (i = 1; i < CONFIG_EFI_PARTITION_ENTRIES_NUMBERS; i++) { + if (part_get_info(blk_desc, i, &info)) + continue; + + if (info.start > largest_part_size) { + largest_part_start = info.start; + largest_part_size = info.size; + } + } + + if (largest_part_size) { + env_set("blkmap_blk_ifname", blk_ifname); + env_set_ulong("blkmap_blk_dev", blk_dev); + env_set_ulong("blkmap_blk_nr", largest_part_start); + env_set_hex("blkmap_size_r", largest_part_size); + } else { + log_warning("%s: no qualified partition for blkmap, skipping\n", + __func__); + } + + return 0; +} + static int exynos_fastboot_setup(void) { struct blk_desc *blk_dev; @@ -297,7 +336,13 @@ int board_init(void) int misc_init_r(void) { + int ret; + exynos_env_setup(); + ret = exynos_blk_env_setup(); + if (ret) + return ret; + return exynos_fastboot_setup(); } diff --git a/board/samsung/exynos-mobile/exynos-mobile.env b/board/samsung/exynos-mobile/exynos-mobile.env index aa2e89afbac..33f767319b5 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.env +++ b/board/samsung/exynos-mobile/exynos-mobile.env @@ -2,6 +2,11 @@ stdin=serial,button-kbd stdout=serial,vidconsole stderr=serial,vidconsole +blkmapcmd=blkmap create root; + blkmap map root 0 ${blkmap_size_r} linear ${blkmap_blk_ifname} ${blkmap_blk_dev} ${blkmap_blk_nr} + +preboot=run blkmapcmd + bootdelay=0 bootcmd=bootefi bootmgr; pause; bootmenu -- cgit v1.2.3 From 0e61fc5364dc6b4af88b44ea2e1aa9d84c9f1ca7 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Tue, 24 Feb 2026 21:07:10 +0530 Subject: board: samsung: exynos-mobile: add EFI capsule update support Add support for EFI capsule updates via U-Boot's DFU. This flashes the boot partition with the new image provided in the capsule. Signed-off-by: Kaustabh Chakraborty Signed-off-by: Minkyu Kang --- board/samsung/exynos-mobile/exynos-mobile.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'board') diff --git a/board/samsung/exynos-mobile/exynos-mobile.c b/board/samsung/exynos-mobile/exynos-mobile.c index c5e1b186ae3..6b2b1523663 100644 --- a/board/samsung/exynos-mobile/exynos-mobile.c +++ b/board/samsung/exynos-mobile/exynos-mobile.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -24,6 +26,19 @@ DECLARE_GLOBAL_DATA_PTR; #define lmb_alloc(size, addr) \ lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE) +struct efi_fw_image fw_images[] = { + { + .fw_name = u"UBOOT_BOOT_PARTITION", + .image_index = 1, + }, +}; + +struct efi_capsule_update_info update_info = { + .dfu_string = NULL, + .images = fw_images, + .num_images = ARRAY_SIZE(fw_images), +}; + /* * The memory mapping includes all DRAM banks, along with the * peripheral block, and a sentinel at the end. This is filled in @@ -191,6 +206,7 @@ static int exynos_blk_env_setup(void) struct blk_desc *blk_desc; struct disk_partition info = {0}; unsigned long largest_part_start = 0, largest_part_size = 0; + static char dfu_string[32]; int i; blk_ifname = "mmc"; @@ -204,6 +220,14 @@ static int exynos_blk_env_setup(void) if (part_get_info(blk_desc, i, &info)) continue; + if (!update_info.dfu_string && + !strncasecmp(info.name, "boot", strlen("boot"))) { + snprintf(dfu_string, sizeof(dfu_string), + "mmc %d=u-boot.bin part %d %d", blk_dev, + blk_dev, i); + update_info.dfu_string = dfu_string; + } + if (info.start > largest_part_size) { largest_part_start = info.start; largest_part_size = info.size; -- cgit v1.2.3