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