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