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>
8c42dfcf5SJoseph Chen #include <android_ab.h>
972c88b4aSJoseph Chen #include <bootm.h>
1072c88b4aSJoseph Chen #include <boot_rkimg.h>
1172c88b4aSJoseph Chen #include <image.h>
1272c88b4aSJoseph Chen #include <malloc.h>
1372c88b4aSJoseph Chen #include <sysmem.h>
1472c88b4aSJoseph Chen #include <asm/arch/fit.h>
1572c88b4aSJoseph Chen
1672c88b4aSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
1772c88b4aSJoseph Chen
do_boot_fit_storage(ulong * size)1872c88b4aSJoseph Chen static void *do_boot_fit_storage(ulong *size)
1972c88b4aSJoseph Chen {
2072c88b4aSJoseph Chen return fit_image_load_bootables(size);
2172c88b4aSJoseph Chen }
2272c88b4aSJoseph Chen
do_boot_fit_ram(char * const argv[],ulong * data_size)2372c88b4aSJoseph Chen static void *do_boot_fit_ram(char *const argv[], ulong *data_size)
2472c88b4aSJoseph Chen {
2572c88b4aSJoseph Chen void *fit;
2672c88b4aSJoseph Chen int size;
2772c88b4aSJoseph Chen
2872c88b4aSJoseph Chen fit = (void *)simple_strtoul(argv[1], NULL, 16);
2972c88b4aSJoseph Chen if (!fit || fdt_check_header(fit)) {
3072c88b4aSJoseph Chen FIT_I("Invalid header\n");
3172c88b4aSJoseph Chen return NULL;
3272c88b4aSJoseph Chen }
3372c88b4aSJoseph Chen
34a1daefc8SJoseph Chen size = fit_image_get_bootables_size(fit);
3572c88b4aSJoseph Chen if (!size) {
3672c88b4aSJoseph Chen FIT_I("Failed to get bootable image size\n");
3772c88b4aSJoseph Chen return NULL;
3872c88b4aSJoseph Chen }
3972c88b4aSJoseph Chen
4072c88b4aSJoseph Chen /* reserve this full FIT image */
4172c88b4aSJoseph Chen if (!sysmem_alloc_base(MEM_FIT_USER,
4272c88b4aSJoseph Chen (phys_addr_t)fit, ALIGN(size, 512)))
4372c88b4aSJoseph Chen return NULL;
4472c88b4aSJoseph Chen
4572c88b4aSJoseph Chen *data_size = size;
4672c88b4aSJoseph Chen
4772c88b4aSJoseph Chen return fit;
4872c88b4aSJoseph Chen }
4972c88b4aSJoseph Chen
5072c88b4aSJoseph Chen /*
5172c88b4aSJoseph Chen * argc == 1:
5272c88b4aSJoseph Chen * FIT image is loaded from storage(eg. CONFIG_BOOTCOMMAND).
5372c88b4aSJoseph Chen *
5472c88b4aSJoseph Chen * argc == 2:
5572c88b4aSJoseph Chen * FIT image is already in ram, the booflow is:
5672c88b4aSJoseph Chen * CLI cmd "bootm <fit_addr>" => do_bootm() =>
5772c88b4aSJoseph Chen * board_do_bootm() => boot_fit <fit_addr>
5872c88b4aSJoseph Chen */
do_boot_fit(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])5972c88b4aSJoseph Chen static int do_boot_fit(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
6072c88b4aSJoseph Chen {
6172c88b4aSJoseph Chen char *bootm_args[1];
6272c88b4aSJoseph Chen char fit_addr[12];
6372c88b4aSJoseph Chen ulong size;
6472c88b4aSJoseph Chen void *fit;
6572c88b4aSJoseph Chen int ret;
6672c88b4aSJoseph Chen
6772c88b4aSJoseph Chen if (argc > 2)
6872c88b4aSJoseph Chen return CMD_RET_USAGE;
6972c88b4aSJoseph Chen
7072c88b4aSJoseph Chen printf("## Booting FIT Image ");
7172c88b4aSJoseph Chen
7272c88b4aSJoseph Chen if (argc == 1)
7372c88b4aSJoseph Chen fit = do_boot_fit_storage(&size);
7472c88b4aSJoseph Chen else
7572c88b4aSJoseph Chen fit = do_boot_fit_ram(argv, &size);
7672c88b4aSJoseph Chen
7772c88b4aSJoseph Chen if (!fit) {
7872c88b4aSJoseph Chen FIT_I("No FIT image\n");
79e2c45c31SJoseph Chen goto out;
8072c88b4aSJoseph Chen }
8172c88b4aSJoseph Chen
8272c88b4aSJoseph Chen if (fdt_check_header(fit)) {
8372c88b4aSJoseph Chen FIT_I("Invalid FIT format\n");
84e2c45c31SJoseph Chen goto out;
8572c88b4aSJoseph Chen }
8672c88b4aSJoseph Chen
87a1daefc8SJoseph Chen /* fixup entry/load and alloc sysmem */
88a1daefc8SJoseph Chen if (fit_image_pre_process(fit))
89e2c45c31SJoseph Chen goto out;
9072c88b4aSJoseph Chen
9172c88b4aSJoseph Chen env_set("bootm-no-reloc", "y");
9272c88b4aSJoseph Chen snprintf(fit_addr, sizeof(fit_addr), "0x%lx", (ulong)fit);
9372c88b4aSJoseph Chen bootm_args[0] = fit_addr;
9472c88b4aSJoseph Chen
9572c88b4aSJoseph Chen printf("at %s with size 0x%08lx\n", fit_addr, size);
9672c88b4aSJoseph Chen
97c42dfcf5SJoseph Chen #ifdef CONFIG_ANDROID_AB
9865655839SJason Zhu char slot_suffix[3] = {0};
99*09a003a9SXuhui Lin char slot_info[21] = "android_slotsuffix=";
10065655839SJason Zhu
10165655839SJason Zhu if (ab_get_slot_suffix(slot_suffix))
10265655839SJason Zhu goto out;
10365655839SJason Zhu
10465655839SJason Zhu strcat(slot_info, slot_suffix);
10565655839SJason Zhu env_update("bootargs", slot_info);
106c42dfcf5SJoseph Chen #endif
107c42dfcf5SJoseph Chen
1082f96fde5SJoseph Chen smp_event2(SEVT_1, STID_17, (ulong)fit);
1092f96fde5SJoseph Chen
11072c88b4aSJoseph Chen ret = do_bootm_states(NULL, 0, ARRAY_SIZE(bootm_args), bootm_args,
11172c88b4aSJoseph Chen BOOTM_STATE_START |
11272c88b4aSJoseph Chen BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
11372c88b4aSJoseph Chen BOOTM_STATE_LOADOS |
11472c88b4aSJoseph Chen #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
11572c88b4aSJoseph Chen BOOTM_STATE_RAMDISK |
11672c88b4aSJoseph Chen #endif
11772c88b4aSJoseph Chen BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
11872c88b4aSJoseph Chen BOOTM_STATE_OS_GO, &images, 1);
11972c88b4aSJoseph Chen
120e2c45c31SJoseph Chen if (ret && argc != 1) {
121a1daefc8SJoseph Chen fit_image_fail_process(fit);
122b72261ddSJoseph Chen goto out;
123e2c45c31SJoseph Chen }
12472c88b4aSJoseph Chen
125b72261ddSJoseph Chen return CMD_RET_SUCCESS;
126e2c45c31SJoseph Chen out:
127b72261ddSJoseph Chen return CMD_RET_FAILURE;
12872c88b4aSJoseph Chen }
12972c88b4aSJoseph Chen
130b704ab33SJoseph Chen U_BOOT_CMD_ALWAYS(
13172c88b4aSJoseph Chen boot_fit, 2, 1, do_boot_fit,
13272c88b4aSJoseph Chen "Boot FIT Image from memory or boot/recovery partition",
13372c88b4aSJoseph Chen "boot_fit [addr]"
13472c88b4aSJoseph Chen );
135