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) 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 blknum = DIV_ROUND_UP(size, blksz); 150 if (!sysmem_alloc_base(MEM_RAMDISK, (phys_addr_t)raddr, 151 blknum * blksz)) 152 return -ENOMEM; 153 154 /* fdt */ 155 image_multi_getimg(hdr, 2, &data, &size); 156 blknum = DIV_ROUND_UP(size, blksz); 157 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)faddr, 158 blknum * blksz)) 159 return -ENOMEM; 160 161 env_set_hex("fdt_high", faddr); 162 env_set_hex("initrd_high", raddr); 163 env_set("bootm-reloc-at", "y"); 164 165 return 0; 166 } 167 168 int uimage_sysmem_free_each(image_header_t *img) 169 { 170 ulong raddr, kaddr, faddr; 171 172 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 173 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 174 faddr = env_get_ulong("fdt_addr_r", 16, 0); 175 176 sysmem_free((phys_addr_t)img); 177 sysmem_free((phys_addr_t)raddr); 178 sysmem_free((phys_addr_t)kaddr); 179 sysmem_free((phys_addr_t)faddr); 180 181 return 0; 182 } 183 184 int rockchip_read_uimage_dtb(void *fdt_addr, char **hash, int *hash_size) 185 { 186 struct blk_desc *dev_desc; 187 disk_partition_t part; 188 image_header_t *hdr; 189 char *part_name; 190 ulong data, offset; 191 ulong size; 192 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 193 ulong dst; 194 int idx = 3; 195 #else 196 int idx = 2; 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 /* reserve enough space before fdt */ 226 dst = (ulong)fdt_addr - 227 ALIGN(size, dev_desc->blksz) - CONFIG_SYS_FDT_PAD; 228 229 ret = uimage_load_one(dev_desc, &part, offset, size, (void *)dst); 230 if (ret) { 231 UIMG_I("Failed to load resource file, ret=%d\n", ret); 232 return ret; 233 } 234 235 if (!sysmem_alloc_base(MEM_RESOURCE, (phys_addr_t)dst, 236 ALIGN(size, RK_BLK_SIZE))) 237 return -ENOMEM; 238 239 ret = resource_create_ram_list(dev_desc, (void *)dst); 240 if (ret) { 241 UIMG_I("Failed to create resource list, ret=%d\n", ret); 242 return ret; 243 } 244 245 printf("Found DTB in uImage.%d\n", idx); 246 ret = rockchip_read_resource_dtb(fdt_addr, hash, hash_size); 247 #else 248 printf("DTB(uimage.%d): rk-kernel.dtb\n", idx); 249 ret = uimage_load_one(dev_desc, &part, offset, size, fdt_addr); 250 #endif 251 if (ret) { 252 UIMG_I("Failed to load fdt, ret=%d\n", ret); 253 return ret; 254 } 255 256 return 0; 257 } 258