xref: /rk3399_rockchip-uboot/cmd/bootfit.c (revision a1daefc8e61099cd3e2c89eba707e5fa507c749b)
172c88b4aSJoseph Chen /*
272c88b4aSJoseph Chen  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
372c88b4aSJoseph Chen  *
472c88b4aSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
572c88b4aSJoseph Chen  */
672c88b4aSJoseph Chen 
772c88b4aSJoseph Chen #include <common.h>
872c88b4aSJoseph Chen #include <bootm.h>
972c88b4aSJoseph Chen #include <boot_rkimg.h>
1072c88b4aSJoseph Chen #include <image.h>
1172c88b4aSJoseph Chen #include <malloc.h>
1272c88b4aSJoseph Chen #include <sysmem.h>
1372c88b4aSJoseph Chen #include <asm/arch/fit.h>
1472c88b4aSJoseph Chen 
1572c88b4aSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
1672c88b4aSJoseph Chen 
1772c88b4aSJoseph Chen static void *do_boot_fit_storage(ulong *size)
1872c88b4aSJoseph Chen {
1972c88b4aSJoseph Chen 	return fit_image_load_bootables(size);
2072c88b4aSJoseph Chen }
2172c88b4aSJoseph Chen 
2272c88b4aSJoseph Chen static void *do_boot_fit_ram(char *const argv[], ulong *data_size)
2372c88b4aSJoseph Chen {
2472c88b4aSJoseph Chen 	void *fit;
2572c88b4aSJoseph Chen 	int size;
2672c88b4aSJoseph Chen 
2772c88b4aSJoseph Chen 	fit = (void *)simple_strtoul(argv[1], NULL, 16);
2872c88b4aSJoseph Chen 	if (!fit || fdt_check_header(fit)) {
2972c88b4aSJoseph Chen 		FIT_I("Invalid header\n");
3072c88b4aSJoseph Chen 		return NULL;
3172c88b4aSJoseph Chen 	}
3272c88b4aSJoseph Chen 
33*a1daefc8SJoseph Chen 	size = fit_image_get_bootables_size(fit);
3472c88b4aSJoseph Chen 	if (!size) {
3572c88b4aSJoseph Chen 		FIT_I("Failed to get bootable image size\n");
3672c88b4aSJoseph Chen 		return NULL;
3772c88b4aSJoseph Chen 	}
3872c88b4aSJoseph Chen 
3972c88b4aSJoseph Chen 	/* reserve this full FIT image */
4072c88b4aSJoseph Chen 	if (!sysmem_alloc_base(MEM_FIT_USER,
4172c88b4aSJoseph Chen 			       (phys_addr_t)fit, ALIGN(size, 512)))
4272c88b4aSJoseph Chen 		return NULL;
4372c88b4aSJoseph Chen 
4472c88b4aSJoseph Chen 	*data_size = size;
4572c88b4aSJoseph Chen 
4672c88b4aSJoseph Chen 	return fit;
4772c88b4aSJoseph Chen }
4872c88b4aSJoseph Chen 
4972c88b4aSJoseph Chen /*
5072c88b4aSJoseph Chen  * argc == 1:
5172c88b4aSJoseph Chen  *	FIT image is loaded from storage(eg. CONFIG_BOOTCOMMAND).
5272c88b4aSJoseph Chen  *
5372c88b4aSJoseph Chen  * argc == 2:
5472c88b4aSJoseph Chen  *	FIT image is already in ram, the booflow is:
5572c88b4aSJoseph Chen  *		CLI cmd "bootm <fit_addr>" => do_bootm() =>
5672c88b4aSJoseph Chen  *		board_do_bootm() => boot_fit <fit_addr>
5772c88b4aSJoseph Chen  */
5872c88b4aSJoseph Chen static int do_boot_fit(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
5972c88b4aSJoseph Chen {
6072c88b4aSJoseph Chen 	char *bootm_args[1];
6172c88b4aSJoseph Chen 	char fit_addr[12];
6272c88b4aSJoseph Chen 	ulong size;
6372c88b4aSJoseph Chen 	void *fit;
6472c88b4aSJoseph Chen 	int ret;
6572c88b4aSJoseph Chen 
6672c88b4aSJoseph Chen 	if (argc > 2)
6772c88b4aSJoseph Chen 		return CMD_RET_USAGE;
6872c88b4aSJoseph Chen 
6972c88b4aSJoseph Chen 	printf("## Booting FIT Image ");
7072c88b4aSJoseph Chen 
7172c88b4aSJoseph Chen 	if (argc == 1)
7272c88b4aSJoseph Chen 		fit = do_boot_fit_storage(&size);
7372c88b4aSJoseph Chen 	else
7472c88b4aSJoseph Chen 		fit = do_boot_fit_ram(argv, &size);
7572c88b4aSJoseph Chen 
7672c88b4aSJoseph Chen 	if (!fit) {
7772c88b4aSJoseph Chen 		FIT_I("No FIT image\n");
78e2c45c31SJoseph Chen 		goto out;
7972c88b4aSJoseph Chen 	}
8072c88b4aSJoseph Chen 
8172c88b4aSJoseph Chen 	if (fdt_check_header(fit)) {
8272c88b4aSJoseph Chen 		FIT_I("Invalid FIT format\n");
83e2c45c31SJoseph Chen 		goto out;
8472c88b4aSJoseph Chen 	}
8572c88b4aSJoseph Chen 
86*a1daefc8SJoseph Chen 	/* fixup entry/load and alloc sysmem */
87*a1daefc8SJoseph Chen 	if (fit_image_pre_process(fit))
88e2c45c31SJoseph Chen 		goto out;
8972c88b4aSJoseph Chen 
9072c88b4aSJoseph Chen 	env_set("bootm-no-reloc", "y");
9172c88b4aSJoseph Chen 	snprintf(fit_addr, sizeof(fit_addr), "0x%lx", (ulong)fit);
9272c88b4aSJoseph Chen 	bootm_args[0] = fit_addr;
9372c88b4aSJoseph Chen 
9472c88b4aSJoseph Chen 	printf("at %s with size 0x%08lx\n", fit_addr, size);
9572c88b4aSJoseph Chen 
9672c88b4aSJoseph Chen 	ret = do_bootm_states(NULL, 0, ARRAY_SIZE(bootm_args), bootm_args,
9772c88b4aSJoseph Chen 		BOOTM_STATE_START |
9872c88b4aSJoseph Chen 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
9972c88b4aSJoseph Chen 		BOOTM_STATE_LOADOS |
10072c88b4aSJoseph Chen #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
10172c88b4aSJoseph Chen 		BOOTM_STATE_RAMDISK |
10272c88b4aSJoseph Chen #endif
10372c88b4aSJoseph Chen 		BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
10472c88b4aSJoseph Chen 		BOOTM_STATE_OS_GO, &images, 1);
10572c88b4aSJoseph Chen 
106e2c45c31SJoseph Chen 	if (ret && argc != 1) {
107*a1daefc8SJoseph Chen 		fit_image_fail_process(fit);
108b72261ddSJoseph Chen 		goto out;
109e2c45c31SJoseph Chen 	}
11072c88b4aSJoseph Chen 
111b72261ddSJoseph Chen 	return CMD_RET_SUCCESS;
112e2c45c31SJoseph Chen out:
113b72261ddSJoseph Chen 	return CMD_RET_FAILURE;
11472c88b4aSJoseph Chen }
11572c88b4aSJoseph Chen 
11672c88b4aSJoseph Chen U_BOOT_CMD(
11772c88b4aSJoseph Chen 	boot_fit,  2,     1,      do_boot_fit,
11872c88b4aSJoseph Chen 	"Boot FIT Image from memory or boot/recovery partition",
11972c88b4aSJoseph Chen 	"boot_fit [addr]"
12072c88b4aSJoseph Chen );
121