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 1872c88b4aSJoseph Chen static void *do_boot_fit_storage(ulong *size) 1972c88b4aSJoseph Chen { 2072c88b4aSJoseph Chen return fit_image_load_bootables(size); 2172c88b4aSJoseph Chen } 2272c88b4aSJoseph Chen 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 */ 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}; 9965655839SJason Zhu char slot_info[21] = "android_slotsufix="; 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 108*2f96fde5SJoseph Chen smp_event2(SEVT_1, STID_17, (ulong)fit); 109*2f96fde5SJoseph 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