1 /* 2 * (C) Copyright 2019 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <boot_rkimg.h> 9 #include <image.h> 10 #include <malloc.h> 11 #include <sysmem.h> 12 #include <asm/arch/resource_img.h> 13 #include <asm/arch/uimage.h> 14 15 static int uimage_load_one(struct blk_desc *dev_desc, disk_partition_t *part, 16 int pos_off, int size, void *dst) 17 { 18 u32 blknum, blkoff; 19 u32 unused; 20 ulong blksz; 21 void *buf; 22 23 blksz = dev_desc->blksz; 24 blkoff = pos_off / blksz; 25 unused = pos_off - blkoff * blksz; 26 blknum = DIV_ROUND_UP(size, blksz) + !!unused; 27 28 if (!size) 29 return -EINVAL; 30 31 if (!IS_ALIGNED(unused, ARCH_DMA_MINALIGN)) { 32 buf = memalign(ARCH_DMA_MINALIGN, blknum * blksz); 33 if (!buf) 34 return -ENOMEM; 35 36 if (blk_dread(dev_desc, part->start + blkoff, 37 blknum, buf) != blknum) { 38 free(buf); 39 return -EIO; 40 } 41 42 memcpy(dst, buf + unused, size); 43 free(buf); 44 } else { 45 if (blk_dread(dev_desc, part->start + blkoff, 46 blknum, (void *)((ulong)dst - unused)) != blknum) 47 return -EIO; 48 } 49 50 return 0; 51 } 52 53 static image_header_t *uimage_get_hdr(struct blk_desc *dev_desc, 54 disk_partition_t *part) 55 { 56 image_header_t *hdr; 57 58 hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE); 59 if (!hdr) 60 return NULL; 61 62 if (blk_dread(dev_desc, part->start, 1, hdr) != 1) 63 goto err; 64 65 if (!image_check_magic(hdr) || (image_get_type(hdr) != IH_TYPE_MULTI)) 66 goto err; 67 68 return hdr; 69 err: 70 free(hdr); 71 return NULL; 72 } 73 74 void *uimage_load_bootables(void) 75 { 76 struct blk_desc *dev_desc; 77 disk_partition_t part; 78 image_header_t *hdr; 79 char *part_name; 80 ulong raddr; 81 ulong kaddr; 82 ulong faddr; 83 int blknum; 84 85 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 86 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 87 faddr = env_get_ulong("fdt_addr_r", 16, 0); 88 89 if (!faddr || !kaddr || !raddr) 90 return NULL; 91 92 dev_desc = rockchip_get_bootdev(); 93 if (!dev_desc) { 94 UIMG_I("No dev_desc\n"); 95 return NULL; 96 } 97 98 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 99 part_name = PART_RECOVERY; 100 else 101 part_name = PART_BOOT; 102 103 if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { 104 UIMG_I("No %s partition\n", part_name); 105 return NULL; 106 } 107 108 hdr = uimage_get_hdr(dev_desc, &part); 109 if (!hdr) 110 return NULL; 111 112 /* load */ 113 blknum = DIV_ROUND_UP(image_get_image_size(hdr), dev_desc->blksz); 114 hdr = sysmem_alloc(MEM_UIMAGE, blknum * dev_desc->blksz); 115 if (!hdr) 116 return NULL; 117 118 if (blk_dread(dev_desc, part.start, blknum, (void *)hdr) != blknum) { 119 UIMG_I("Failed to read %s data\n", part.name); 120 return NULL; 121 } 122 123 return hdr; 124 } 125 126 int uimage_sysmem_reserve_each(image_header_t *hdr, u32 *ramdisk_sz) 127 { 128 ulong raddr, kaddr, faddr; 129 ulong data, size; 130 int blknum; 131 int blksz = RK_BLK_SIZE; 132 133 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 134 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 135 faddr = env_get_ulong("fdt_addr_r", 16, 0); 136 137 if (!faddr || !kaddr || !raddr) 138 return -EINVAL; 139 140 /* kernel */ 141 image_multi_getimg(hdr, 0, &data, &size); 142 blknum = DIV_ROUND_UP(size, blksz); 143 if (!sysmem_alloc_base(MEM_KERNEL, (phys_addr_t)kaddr, 144 blknum * blksz)) 145 return -ENOMEM; 146 147 /* ramdisk */ 148 image_multi_getimg(hdr, 1, &data, &size); 149 *ramdisk_sz = size; 150 blknum = DIV_ROUND_UP(size, blksz); 151 if (size && !sysmem_alloc_base(MEM_RAMDISK, (phys_addr_t)raddr, 152 blknum * blksz)) 153 return -ENOMEM; 154 155 /* fdt */ 156 image_multi_getimg(hdr, 2, &data, &size); 157 blknum = DIV_ROUND_UP(size, blksz); 158 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)faddr, 159 blknum * blksz)) 160 return -ENOMEM; 161 162 env_set_hex("fdt_high", faddr); 163 env_set_hex("initrd_high", raddr); 164 env_set("bootm-reloc-at", "y"); 165 166 return 0; 167 } 168 169 int uimage_sysmem_free_each(image_header_t *img, u32 ramdisk_sz) 170 { 171 ulong raddr, kaddr, faddr; 172 173 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 174 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 175 faddr = env_get_ulong("fdt_addr_r", 16, 0); 176 177 sysmem_free((phys_addr_t)img); 178 sysmem_free((phys_addr_t)kaddr); 179 sysmem_free((phys_addr_t)faddr); 180 if (ramdisk_sz) 181 sysmem_free((phys_addr_t)raddr); 182 183 return 0; 184 } 185 186 int uimage_init_resource(void) 187 { 188 struct blk_desc *dev_desc; 189 disk_partition_t part; 190 image_header_t *hdr; 191 char *part_name; 192 ulong data, offset; 193 ulong size; 194 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 195 ulong dst; 196 int idx = 3; 197 #endif 198 int ret; 199 200 dev_desc = rockchip_get_bootdev(); 201 if (!dev_desc) { 202 printf("No dev_desc!\n"); 203 return ENODEV; 204 } 205 206 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 207 part_name = PART_RECOVERY; 208 else 209 part_name = PART_BOOT; 210 211 if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { 212 UIMG_I("No %s partition\n", part_name); 213 return -ENODEV; 214 } 215 216 hdr = uimage_get_hdr(dev_desc, &part); 217 if (!hdr) 218 return -ENODEV; 219 220 image_multi_getimg(hdr, idx, &data, &size); 221 offset = data - (ulong)hdr; 222 free(hdr); 223 224 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 225 ulong fdt_addr; 226 227 /* reserve enough space before fdt */ 228 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 229 dst = (ulong)fdt_addr - 230 ALIGN(size, dev_desc->blksz) - CONFIG_SYS_FDT_PAD; 231 ret = uimage_load_one(dev_desc, &part, offset, size, (void *)dst); 232 if (ret) { 233 UIMG_I("Failed to load resource file, ret=%d\n", ret); 234 return ret; 235 } 236 237 if (!sysmem_alloc_base(MEM_RESOURCE, (phys_addr_t)dst, 238 ALIGN(size, RK_BLK_SIZE))) 239 return -ENOMEM; 240 241 ret = resource_create_ram_list(dev_desc, (void *)dst); 242 if (ret) { 243 UIMG_I("Failed to create resource list, ret=%d\n", ret); 244 return ret; 245 } 246 #endif 247 248 return 0; 249 } 250