1 /* 2 * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <image.h> 9 #include <android_image.h> 10 #include <malloc.h> 11 #include <mapmem.h> 12 #include <errno.h> 13 #ifdef CONFIG_RKIMG_BOOTLOADER 14 #include <asm/arch/resource_img.h> 15 #endif 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 20 #define ANDROID_ARG_FDT_FILENAME "rk-kernel.dtb" 21 22 static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; 23 static u32 android_kernel_comp_type = IH_COMP_NONE; 24 25 static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) 26 { 27 /* 28 * All the Android tools that generate a boot.img use this 29 * address as the default. 30 * 31 * Even though it doesn't really make a lot of sense, and it 32 * might be valid on some platforms, we treat that adress as 33 * the default value for this field, and try to execute the 34 * kernel in place in such a case. 35 * 36 * Otherwise, we will return the actual value set by the user. 37 */ 38 if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) 39 return (ulong)hdr + hdr->page_size; 40 41 #ifdef CONFIG_ARCH_ROCKCHIP 42 /* 43 * If kernel is compressed, kernel_addr is set as decompressed address 44 * after compressed being loaded to ram, so let's use it. 45 */ 46 if (android_kernel_comp_type != IH_COMP_NONE && 47 android_kernel_comp_type != IH_COMP_ZIMAGE) 48 return hdr->kernel_addr; 49 50 /* 51 * Compatble with rockchip legacy packing with kernel/ramdisk/second 52 * address base from 0x60000000(SDK versiont < 8.1), these are invalid 53 * address, so we calc it by real size. 54 */ 55 return (ulong)hdr + hdr->page_size; 56 #else 57 return hdr->kernel_addr; 58 #endif 59 60 } 61 62 void android_image_set_comp(struct andr_img_hdr *hdr, u32 comp) 63 { 64 android_kernel_comp_type = comp; 65 } 66 67 u32 android_image_get_comp(const struct andr_img_hdr *hdr) 68 { 69 return android_kernel_comp_type; 70 } 71 72 int android_image_parse_kernel_comp(const struct andr_img_hdr *hdr) 73 { 74 ulong kaddr = android_image_get_kernel_addr(hdr); 75 return bootm_parse_comp((const unsigned char *)kaddr); 76 } 77 78 /** 79 * android_image_get_kernel() - processes kernel part of Android boot images 80 * @hdr: Pointer to image header, which is at the start 81 * of the image. 82 * @verify: Checksum verification flag. Currently unimplemented. 83 * @os_data: Pointer to a ulong variable, will hold os data start 84 * address. 85 * @os_len: Pointer to a ulong variable, will hold os data length. 86 * 87 * This function returns the os image's start address and length. Also, 88 * it appends the kernel command line to the bootargs env variable. 89 * 90 * Return: Zero, os start address and length on success, 91 * otherwise on failure. 92 */ 93 int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, 94 ulong *os_data, ulong *os_len) 95 { 96 u32 kernel_addr = android_image_get_kernel_addr(hdr); 97 98 /* 99 * Not all Android tools use the id field for signing the image with 100 * sha1 (or anything) so we don't check it. It is not obvious that the 101 * string is null terminated so we take care of this. 102 */ 103 strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE); 104 andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; 105 if (strlen(andr_tmp_str)) 106 printf("Android's image name: %s\n", andr_tmp_str); 107 108 printf("Kernel load addr 0x%08x size %u KiB\n", 109 kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); 110 111 int len = 0; 112 if (*hdr->cmdline) { 113 debug("Kernel command line: %s\n", hdr->cmdline); 114 len += strlen(hdr->cmdline); 115 } 116 117 char *bootargs = env_get("bootargs"); 118 if (bootargs) 119 len += strlen(bootargs); 120 121 char *newbootargs = malloc(len + 2); 122 if (!newbootargs) { 123 puts("Error: malloc in android_image_get_kernel failed!\n"); 124 return -ENOMEM; 125 } 126 *newbootargs = '\0'; 127 128 if (bootargs) { 129 strcpy(newbootargs, bootargs); 130 strcat(newbootargs, " "); 131 } 132 if (*hdr->cmdline) 133 strcat(newbootargs, hdr->cmdline); 134 135 env_set("bootargs", newbootargs); 136 137 if (os_data) { 138 *os_data = (ulong)hdr; 139 *os_data += hdr->page_size; 140 } 141 if (os_len) 142 *os_len = hdr->kernel_size; 143 return 0; 144 } 145 146 int android_image_check_header(const struct andr_img_hdr *hdr) 147 { 148 return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); 149 } 150 151 ulong android_image_get_end(const struct andr_img_hdr *hdr) 152 { 153 ulong end; 154 /* 155 * The header takes a full page, the remaining components are aligned 156 * on page boundary 157 */ 158 end = (ulong)hdr; 159 end += hdr->page_size; 160 end += ALIGN(hdr->kernel_size, hdr->page_size); 161 end += ALIGN(hdr->ramdisk_size, hdr->page_size); 162 end += ALIGN(hdr->second_size, hdr->page_size); 163 164 if (hdr->header_version >= 1) 165 end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); 166 167 return end; 168 } 169 170 u32 android_image_get_ksize(const struct andr_img_hdr *hdr) 171 { 172 return hdr->kernel_size; 173 } 174 175 void android_image_set_kload(struct andr_img_hdr *hdr, u32 load_address) 176 { 177 hdr->kernel_addr = load_address; 178 } 179 180 ulong android_image_get_kload(const struct andr_img_hdr *hdr) 181 { 182 return android_image_get_kernel_addr(hdr); 183 } 184 185 int android_image_get_ramdisk(const struct andr_img_hdr *hdr, 186 ulong *rd_data, ulong *rd_len) 187 { 188 if (!hdr->ramdisk_size) { 189 *rd_data = *rd_len = 0; 190 return -1; 191 } 192 193 *rd_data = (unsigned long)hdr; 194 *rd_data += hdr->page_size; 195 *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); 196 *rd_len = hdr->ramdisk_size; 197 198 printf("RAM disk load addr 0x%08lx size %u KiB\n", 199 *rd_data, DIV_ROUND_UP(hdr->ramdisk_size, 1024)); 200 201 return 0; 202 } 203 204 int android_image_get_fdt(const struct andr_img_hdr *hdr, 205 ulong *rd_data) 206 { 207 if (!hdr->second_size) { 208 *rd_data = 0; 209 return -1; 210 } 211 /* 212 * If kernel dtb is enabled, it means we have read kernel dtb before do_bootm(), 213 * that's: init_kernel_dtb() -> rockchip_read_dtb_file(). 214 * And maybe some operations(optional) are done: 215 * 216 * 1. apply fdt overlay; 217 * 2. select fdt by adc or gpio; 218 * 219 * After that, we didn't update dtb at all untill run here, it's fine to 220 * pass current fdt to kernel. 221 * 222 * This case has higher priority then the others(#elif, #else...). 223 */ 224 #if defined(CONFIG_USING_KERNEL_DTB) 225 *rd_data = (ulong)gd->fdt_blob; 226 227 /* 228 * If kernel dtb is disabled, it means kernel dtb is not read before do_bootm(), 229 * we need to read it from boot.img/recovery.img now. 230 * 231 * For rockchip AOSP firmware(CONFIG_RKIMG_BOOTLOADER), we pack resource.img in 232 * second position. we need read kernel dtb by rockchip_read_dtb_file() which 233 * can do the above "some operations(optional)". 234 */ 235 #elif defined(CONFIG_RKIMG_BOOTLOADER) 236 ulong fdt_addr = 0; 237 int ret; 238 239 /* Get resource addr and fdt addr */ 240 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 241 if (!fdt_addr) { 242 printf("No Found FDT Load Address.\n"); 243 return -1; 244 } 245 246 ret = rockchip_read_dtb_file((void *)fdt_addr); 247 if (ret < 0) { 248 printf("%s: failed to read dtb file, ret=%d\n", __func__, ret); 249 return ret; 250 } 251 252 *rd_data = fdt_addr; 253 254 /* 255 * If kernel dtb is disabled and it's not rockchip AOSP firmware, kernel dtb is 256 * in second position, let't read it directly. 257 */ 258 #else 259 *rd_data = (unsigned long)hdr; 260 *rd_data += hdr->page_size; 261 *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); 262 *rd_data += ALIGN(hdr->ramdisk_size, hdr->page_size); 263 264 printf("FDT load addr 0x%08x size %u KiB\n", 265 hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024)); 266 #endif 267 268 return 0; 269 } 270 271 long android_image_load(struct blk_desc *dev_desc, 272 const disk_partition_t *part_info, 273 unsigned long load_address, 274 unsigned long max_size) { 275 void *buf; 276 long blk_cnt = 0; 277 long blk_read = 0; 278 u32 comp; 279 u32 kload_addr; 280 u32 blkcnt; 281 struct andr_img_hdr *hdr; 282 283 if (max_size < part_info->blksz) 284 return -1; 285 286 /* 287 * Read the Android boot.img header and a few parts of 288 * the head of kernel image(2 blocks maybe enough). 289 */ 290 blkcnt = DIV_ROUND_UP(sizeof(*hdr), 512) + 2; 291 hdr = memalign(ARCH_DMA_MINALIGN, blkcnt * 512); 292 if (!hdr) { 293 printf("%s: no memory\n", __func__); 294 return -1; 295 } 296 297 if (blk_dread(dev_desc, part_info->start, blkcnt, hdr) != blkcnt) 298 blk_read = -1; 299 300 if (!blk_read && android_image_check_header(hdr) != 0) { 301 printf("** Invalid Android Image header **\n"); 302 blk_read = -1; 303 } 304 305 /* page_size for image header */ 306 load_address -= hdr->page_size; 307 308 /* We don't know the size of the Android image before reading the header 309 * so we don't limit the size of the mapped memory. 310 */ 311 buf = map_sysmem(load_address, 0 /* size */); 312 if (!blk_read) { 313 blk_cnt = (android_image_get_end(hdr) - (ulong)hdr + 314 part_info->blksz - 1) / part_info->blksz; 315 comp = android_image_parse_kernel_comp(hdr); 316 /* 317 * We should load a compressed kernel Image 318 * to high memory 319 */ 320 if (comp != IH_COMP_NONE) { 321 load_address += android_image_get_ksize(hdr) * 3; 322 load_address = env_get_ulong("kernel_addr_c", 16, load_address); 323 load_address -= hdr->page_size; 324 unmap_sysmem(buf); 325 buf = map_sysmem(load_address, 0 /* size */); 326 } 327 328 if (blk_cnt * part_info->blksz > max_size) { 329 debug("Android Image too big (%lu bytes, max %lu)\n", 330 android_image_get_end(hdr) - (ulong)hdr, 331 max_size); 332 blk_read = -1; 333 } else { 334 debug("Loading Android Image (%lu blocks) to 0x%lx... ", 335 blk_cnt, load_address); 336 blk_read = blk_dread(dev_desc, part_info->start, 337 blk_cnt, buf); 338 } 339 340 /* 341 * zImage is not need to decompress 342 * kernel will handle decompress itself 343 */ 344 if (comp != IH_COMP_NONE && comp != IH_COMP_ZIMAGE) { 345 kload_addr = env_get_ulong("kernel_addr_r", 16, 0x02080000); 346 android_image_set_kload(buf, kload_addr); 347 android_image_set_comp(buf, comp); 348 } else { 349 android_image_set_comp(buf, IH_COMP_NONE); 350 } 351 352 } 353 354 free(hdr); 355 unmap_sysmem(buf); 356 357 debug("%lu blocks read: %s\n", 358 blk_read, (blk_read == blk_cnt) ? "OK" : "ERROR"); 359 if (blk_read != blk_cnt) 360 return -1; 361 362 return load_address; 363 } 364 365 #if !defined(CONFIG_SPL_BUILD) 366 /** 367 * android_print_contents - prints out the contents of the Android format image 368 * @hdr: pointer to the Android format image header 369 * 370 * android_print_contents() formats a multi line Android image contents 371 * description. 372 * The routine prints out Android image properties 373 * 374 * returns: 375 * no returned results 376 */ 377 void android_print_contents(const struct andr_img_hdr *hdr) 378 { 379 const char * const p = IMAGE_INDENT_STRING; 380 /* os_version = ver << 11 | lvl */ 381 u32 os_ver = hdr->os_version >> 11; 382 u32 os_lvl = hdr->os_version & ((1U << 11) - 1); 383 u32 header_version = hdr->header_version; 384 385 printf("%skernel size: %x\n", p, hdr->kernel_size); 386 printf("%skernel address: %x\n", p, hdr->kernel_addr); 387 printf("%sramdisk size: %x\n", p, hdr->ramdisk_size); 388 printf("%sramdisk addrress: %x\n", p, hdr->ramdisk_addr); 389 printf("%ssecond size: %x\n", p, hdr->second_size); 390 printf("%ssecond address: %x\n", p, hdr->second_addr); 391 printf("%stags address: %x\n", p, hdr->tags_addr); 392 printf("%spage size: %x\n", p, hdr->page_size); 393 printf("%sheader_version: %x\n", p, header_version); 394 /* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) 395 * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) */ 396 printf("%sos_version: %x (ver: %u.%u.%u, level: %u.%u)\n", 397 p, hdr->os_version, 398 (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F, 399 (os_lvl >> 4) + 2000, os_lvl & 0x0F); 400 printf("%sname: %s\n", p, hdr->name); 401 printf("%scmdline: %s\n", p, hdr->cmdline); 402 403 if (header_version >= 1) { 404 printf("%srecovery dtbo size: %x\n", p, hdr->recovery_dtbo_size); 405 printf("%srecovery dtbo offset: %llx\n", p, hdr->recovery_dtbo_offset); 406 printf("%sheader size: %x\n", p, hdr->header_size); 407 } 408 } 409 #endif 410