xref: /rk3399_rockchip-uboot/cmd/bootfit.c (revision 72c88b4aeab783608403392ce2bacfc08574bb48)
1*72c88b4aSJoseph Chen /*
2*72c88b4aSJoseph Chen  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3*72c88b4aSJoseph Chen  *
4*72c88b4aSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5*72c88b4aSJoseph Chen  */
6*72c88b4aSJoseph Chen 
7*72c88b4aSJoseph Chen #include <common.h>
8*72c88b4aSJoseph Chen #include <bootm.h>
9*72c88b4aSJoseph Chen #include <boot_rkimg.h>
10*72c88b4aSJoseph Chen #include <image.h>
11*72c88b4aSJoseph Chen #include <malloc.h>
12*72c88b4aSJoseph Chen #include <sysmem.h>
13*72c88b4aSJoseph Chen #include <asm/arch/fit.h>
14*72c88b4aSJoseph Chen 
15*72c88b4aSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
16*72c88b4aSJoseph Chen 
17*72c88b4aSJoseph Chen static void *do_boot_fit_storage(ulong *size)
18*72c88b4aSJoseph Chen {
19*72c88b4aSJoseph Chen 	return fit_image_load_bootables(size);
20*72c88b4aSJoseph Chen }
21*72c88b4aSJoseph Chen 
22*72c88b4aSJoseph Chen static void *do_boot_fit_ram(char *const argv[], ulong *data_size)
23*72c88b4aSJoseph Chen {
24*72c88b4aSJoseph Chen 	void *fit;
25*72c88b4aSJoseph Chen 	int size;
26*72c88b4aSJoseph Chen 
27*72c88b4aSJoseph Chen 	fit = (void *)simple_strtoul(argv[1], NULL, 16);
28*72c88b4aSJoseph Chen 	if (!fit || fdt_check_header(fit)) {
29*72c88b4aSJoseph Chen 		FIT_I("Invalid header\n");
30*72c88b4aSJoseph Chen 		return NULL;
31*72c88b4aSJoseph Chen 	}
32*72c88b4aSJoseph Chen 
33*72c88b4aSJoseph Chen 	size = fit_image_get_bootable_size(fit);
34*72c88b4aSJoseph Chen 	if (!size) {
35*72c88b4aSJoseph Chen 		FIT_I("Failed to get bootable image size\n");
36*72c88b4aSJoseph Chen 		return NULL;
37*72c88b4aSJoseph Chen 	}
38*72c88b4aSJoseph Chen 
39*72c88b4aSJoseph Chen 	/* reserve this full FIT image */
40*72c88b4aSJoseph Chen 	if (!sysmem_alloc_base(MEM_FIT_USER,
41*72c88b4aSJoseph Chen 			       (phys_addr_t)fit, ALIGN(size, 512)))
42*72c88b4aSJoseph Chen 		return NULL;
43*72c88b4aSJoseph Chen 
44*72c88b4aSJoseph Chen 	*data_size = size;
45*72c88b4aSJoseph Chen 
46*72c88b4aSJoseph Chen 	return fit;
47*72c88b4aSJoseph Chen }
48*72c88b4aSJoseph Chen 
49*72c88b4aSJoseph Chen /*
50*72c88b4aSJoseph Chen  * argc == 1:
51*72c88b4aSJoseph Chen  *	FIT image is loaded from storage(eg. CONFIG_BOOTCOMMAND).
52*72c88b4aSJoseph Chen  *
53*72c88b4aSJoseph Chen  * argc == 2:
54*72c88b4aSJoseph Chen  *	FIT image is already in ram, the booflow is:
55*72c88b4aSJoseph Chen  *		CLI cmd "bootm <fit_addr>" => do_bootm() =>
56*72c88b4aSJoseph Chen  *		board_do_bootm() => boot_fit <fit_addr>
57*72c88b4aSJoseph Chen  */
58*72c88b4aSJoseph Chen static int do_boot_fit(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
59*72c88b4aSJoseph Chen {
60*72c88b4aSJoseph Chen 	char *bootm_args[1];
61*72c88b4aSJoseph Chen 	char fit_addr[12];
62*72c88b4aSJoseph Chen 	ulong size;
63*72c88b4aSJoseph Chen 	void *fit;
64*72c88b4aSJoseph Chen 	int ret;
65*72c88b4aSJoseph Chen 
66*72c88b4aSJoseph Chen 	if (argc > 2)
67*72c88b4aSJoseph Chen 		return CMD_RET_USAGE;
68*72c88b4aSJoseph Chen 
69*72c88b4aSJoseph Chen 	printf("## Booting FIT Image ");
70*72c88b4aSJoseph Chen 
71*72c88b4aSJoseph Chen 	if (argc == 1)
72*72c88b4aSJoseph Chen 		fit = do_boot_fit_storage(&size);
73*72c88b4aSJoseph Chen 	else
74*72c88b4aSJoseph Chen 		fit = do_boot_fit_ram(argv, &size);
75*72c88b4aSJoseph Chen 
76*72c88b4aSJoseph Chen 	if (!fit) {
77*72c88b4aSJoseph Chen 		FIT_I("No FIT image\n");
78*72c88b4aSJoseph Chen 		return -EBADF;
79*72c88b4aSJoseph Chen 	}
80*72c88b4aSJoseph Chen 
81*72c88b4aSJoseph Chen 	if (fdt_check_header(fit)) {
82*72c88b4aSJoseph Chen 		FIT_I("Invalid FIT format\n");
83*72c88b4aSJoseph Chen 		return -EBADF;
84*72c88b4aSJoseph Chen 	}
85*72c88b4aSJoseph Chen 
86*72c88b4aSJoseph Chen 	/* reserve memory to avoid memory overlap and fixup entry & load !! */
87*72c88b4aSJoseph Chen 	if (fit_image_fixup_and_sysmem_rsv(fit))
88*72c88b4aSJoseph Chen 		return -ENOMEM;
89*72c88b4aSJoseph Chen 
90*72c88b4aSJoseph Chen 	env_set("bootm-no-reloc", "y");
91*72c88b4aSJoseph Chen 	snprintf(fit_addr, sizeof(fit_addr), "0x%lx", (ulong)fit);
92*72c88b4aSJoseph Chen 	bootm_args[0] = fit_addr;
93*72c88b4aSJoseph Chen 
94*72c88b4aSJoseph Chen 	printf("at %s with size 0x%08lx\n", fit_addr, size);
95*72c88b4aSJoseph Chen 
96*72c88b4aSJoseph Chen 	ret = do_bootm_states(NULL, 0, ARRAY_SIZE(bootm_args), bootm_args,
97*72c88b4aSJoseph Chen 		BOOTM_STATE_START |
98*72c88b4aSJoseph Chen 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
99*72c88b4aSJoseph Chen 		BOOTM_STATE_LOADOS |
100*72c88b4aSJoseph Chen #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
101*72c88b4aSJoseph Chen 		BOOTM_STATE_RAMDISK |
102*72c88b4aSJoseph Chen #endif
103*72c88b4aSJoseph Chen 		BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
104*72c88b4aSJoseph Chen 		BOOTM_STATE_OS_GO, &images, 1);
105*72c88b4aSJoseph Chen 
106*72c88b4aSJoseph Chen 	if (ret && argc != 1)
107*72c88b4aSJoseph Chen 		fit_sysmem_free_each(fit);
108*72c88b4aSJoseph Chen 
109*72c88b4aSJoseph Chen 	return ret;
110*72c88b4aSJoseph Chen }
111*72c88b4aSJoseph Chen 
112*72c88b4aSJoseph Chen U_BOOT_CMD(
113*72c88b4aSJoseph Chen 	boot_fit,  2,     1,      do_boot_fit,
114*72c88b4aSJoseph Chen 	"Boot FIT Image from memory or boot/recovery partition",
115*72c88b4aSJoseph Chen 	"boot_fit [addr]"
116*72c88b4aSJoseph Chen );
117