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 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 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 187 int uimage_init_resource(struct blk_desc *dev_desc) 188 { 189 disk_partition_t part; 190 ulong data, offset, size; 191 image_header_t *hdr; 192 char *part_name = PART_BOOT; 193 int ret, idx = 3; 194 void *buf; 195 196 if (!dev_desc) 197 return -ENODEV; 198 199 #ifndef CONFIG_ANDROID_AB 200 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 201 part_name = PART_RECOVERY; 202 #endif 203 if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { 204 UIMG_I("No %s partition\n", part_name); 205 return -ENODEV; 206 } 207 208 hdr = uimage_get_hdr(dev_desc, &part); 209 if (!hdr) 210 return -EAGAIN; 211 212 image_multi_getimg(hdr, idx, &data, &size); 213 offset = data - (ulong)hdr; 214 free(hdr); 215 216 buf = memalign(ARCH_DMA_MINALIGN, ALIGN(size, dev_desc->blksz)); 217 if (!buf) 218 return -ENOMEM; 219 220 printf("RESC: '%s', blk@0x%08lx\n", part.name, 221 part.start + (offset / dev_desc->blksz)); 222 ret = uimage_load_one(dev_desc, &part, offset, size, buf); 223 if (ret) 224 return ret; 225 226 ret = resource_setup_ram_list(dev_desc, buf); 227 if (ret) { 228 UIMG_I("Failed to setup resource ram list, ret=%d\n", ret); 229 return ret; 230 } 231 232 return 0; 233 } 234 #endif 235