1e39c2b5dSJoseph Chen /*
2e39c2b5dSJoseph Chen * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3e39c2b5dSJoseph Chen *
4e39c2b5dSJoseph Chen * SPDX-License-Identifier: GPL-2.0+
5e39c2b5dSJoseph Chen */
6e39c2b5dSJoseph Chen
7e39c2b5dSJoseph Chen #include <common.h>
8e39c2b5dSJoseph Chen #include <bootm.h>
9e39c2b5dSJoseph Chen #include <boot_rkimg.h>
10e39c2b5dSJoseph Chen #include <console.h>
11e39c2b5dSJoseph Chen #include <image.h>
12e39c2b5dSJoseph Chen #include <malloc.h>
13e39c2b5dSJoseph Chen #include <sysmem.h>
14e39c2b5dSJoseph Chen #include <linux/libfdt.h>
15e39c2b5dSJoseph Chen #include <asm/arch/hotkey.h>
16e39c2b5dSJoseph Chen #include <asm/arch/resource_img.h>
17e39c2b5dSJoseph Chen #include <asm/arch/boot_mode.h>
18e39c2b5dSJoseph Chen #include <asm/arch/uimage.h>
19e39c2b5dSJoseph Chen
20e39c2b5dSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
21e39c2b5dSJoseph Chen
do_boot_uimage_storage(void)22e39c2b5dSJoseph Chen static void *do_boot_uimage_storage(void)
23e39c2b5dSJoseph Chen {
24e39c2b5dSJoseph Chen return uimage_load_bootables();
25e39c2b5dSJoseph Chen }
26e39c2b5dSJoseph Chen
do_boot_uimage_ram(char * const argv[])27e39c2b5dSJoseph Chen static void *do_boot_uimage_ram(char *const argv[])
28e39c2b5dSJoseph Chen {
29e39c2b5dSJoseph Chen image_header_t *hdr;
30e39c2b5dSJoseph Chen int blknum;
31e39c2b5dSJoseph Chen
32e39c2b5dSJoseph Chen hdr = (void *)simple_strtoul(argv[1], NULL, 16);
33e39c2b5dSJoseph Chen if (!hdr || !image_check_magic(hdr)) {
34e39c2b5dSJoseph Chen UIMG_I("Invalid header");
35e39c2b5dSJoseph Chen return NULL;
36e39c2b5dSJoseph Chen }
37e39c2b5dSJoseph Chen
38e39c2b5dSJoseph Chen if (image_get_type(hdr) != IH_TYPE_MULTI) {
39e39c2b5dSJoseph Chen UIMG_I("Invalid multi images\n");
40e39c2b5dSJoseph Chen return NULL;
41e39c2b5dSJoseph Chen }
42e39c2b5dSJoseph Chen
43e39c2b5dSJoseph Chen /* reserve this full uImage */
44e39c2b5dSJoseph Chen blknum = DIV_ROUND_UP(image_get_image_size(hdr), RK_BLK_SIZE);
45e39c2b5dSJoseph Chen if (!sysmem_alloc_base(MEM_UIMAGE_USER, (phys_addr_t)hdr,
46e39c2b5dSJoseph Chen blknum * RK_BLK_SIZE))
47e39c2b5dSJoseph Chen return NULL;
48e39c2b5dSJoseph Chen
49e39c2b5dSJoseph Chen return hdr;
50e39c2b5dSJoseph Chen }
51e39c2b5dSJoseph Chen
do_boot_uimage(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])52e39c2b5dSJoseph Chen static int do_boot_uimage(cmd_tbl_t *cmdtp, int flag,
53e39c2b5dSJoseph Chen int argc, char *const argv[])
54e39c2b5dSJoseph Chen {
55e39c2b5dSJoseph Chen char *bootm_args[1];
56e39c2b5dSJoseph Chen image_header_t *img;
57e39c2b5dSJoseph Chen char uimg_addr[12];
58a86a723eSJoseph Chen u32 ramdisk_sz = 0;
59e39c2b5dSJoseph Chen int ret;
60e39c2b5dSJoseph Chen
61e39c2b5dSJoseph Chen if (argc > 2)
62e39c2b5dSJoseph Chen return CMD_RET_USAGE;
63e39c2b5dSJoseph Chen
64e39c2b5dSJoseph Chen printf("\n## Booting Multi uImage ");
65e39c2b5dSJoseph Chen
66e39c2b5dSJoseph Chen if (argc == 1)
67e39c2b5dSJoseph Chen img = do_boot_uimage_storage();
68e39c2b5dSJoseph Chen else
69e39c2b5dSJoseph Chen img = do_boot_uimage_ram(argv);
70e39c2b5dSJoseph Chen
71e39c2b5dSJoseph Chen if (!img) {
72e39c2b5dSJoseph Chen UIMG_I("Failed to load multi images\n");
73bfbe8759SJoseph Chen goto out;
74e39c2b5dSJoseph Chen }
75e39c2b5dSJoseph Chen
76a86a723eSJoseph Chen if (uimage_sysmem_reserve_each(img, &ramdisk_sz))
77bfbe8759SJoseph Chen goto out;
78e39c2b5dSJoseph Chen
79e39c2b5dSJoseph Chen snprintf(uimg_addr, sizeof(uimg_addr), "0x%lx", (ulong)img);
80e39c2b5dSJoseph Chen bootm_args[0] = uimg_addr;
81e39c2b5dSJoseph Chen
82e39c2b5dSJoseph Chen printf("at %s\n", uimg_addr);
83e39c2b5dSJoseph Chen
84e39c2b5dSJoseph Chen ret = do_bootm_states(NULL, 0, ARRAY_SIZE(bootm_args), bootm_args,
85e39c2b5dSJoseph Chen BOOTM_STATE_START |
86e39c2b5dSJoseph Chen BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
87e39c2b5dSJoseph Chen BOOTM_STATE_LOADOS |
88e39c2b5dSJoseph Chen #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
89e39c2b5dSJoseph Chen BOOTM_STATE_RAMDISK |
90e39c2b5dSJoseph Chen #endif
91e39c2b5dSJoseph Chen BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
92e39c2b5dSJoseph Chen BOOTM_STATE_OS_GO, &images, 1);
93e39c2b5dSJoseph Chen
94bfbe8759SJoseph Chen if (ret && argc != 1) {
95a86a723eSJoseph Chen uimage_sysmem_free_each(img, ramdisk_sz);
96*36c66887SJoseph Chen goto out;
97bfbe8759SJoseph Chen }
98e39c2b5dSJoseph Chen
99*36c66887SJoseph Chen return CMD_RET_SUCCESS;
100bfbe8759SJoseph Chen out:
101*36c66887SJoseph Chen return CMD_RET_FAILURE;
102e39c2b5dSJoseph Chen }
103e39c2b5dSJoseph Chen
104e39c2b5dSJoseph Chen U_BOOT_CMD(
105e39c2b5dSJoseph Chen boot_uimage, 2, 1, do_boot_uimage,
106e39c2b5dSJoseph Chen "Boot Legacy uImage from memory or boot(recovery) partitions",
107e39c2b5dSJoseph Chen "boot_uimage [addr]"
108e39c2b5dSJoseph Chen );
109