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 return hdr->kernel_addr; 42 } 43 44 void android_image_set_comp(struct andr_img_hdr *hdr, u32 comp) 45 { 46 android_kernel_comp_type = comp; 47 } 48 49 u32 android_image_get_comp(const struct andr_img_hdr *hdr) 50 { 51 return android_kernel_comp_type; 52 } 53 54 int android_image_parse_kernel_comp(const struct andr_img_hdr *hdr) 55 { 56 ulong kaddr = android_image_get_kernel_addr(hdr); 57 return bootm_parse_comp((const unsigned char *)kaddr); 58 } 59 60 /** 61 * android_image_get_kernel() - processes kernel part of Android boot images 62 * @hdr: Pointer to image header, which is at the start 63 * of the image. 64 * @verify: Checksum verification flag. Currently unimplemented. 65 * @os_data: Pointer to a ulong variable, will hold os data start 66 * address. 67 * @os_len: Pointer to a ulong variable, will hold os data length. 68 * 69 * This function returns the os image's start address and length. Also, 70 * it appends the kernel command line to the bootargs env variable. 71 * 72 * Return: Zero, os start address and length on success, 73 * otherwise on failure. 74 */ 75 int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, 76 ulong *os_data, ulong *os_len) 77 { 78 u32 kernel_addr = android_image_get_kernel_addr(hdr); 79 80 /* 81 * Not all Android tools use the id field for signing the image with 82 * sha1 (or anything) so we don't check it. It is not obvious that the 83 * string is null terminated so we take care of this. 84 */ 85 strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE); 86 andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; 87 if (strlen(andr_tmp_str)) 88 printf("Android's image name: %s\n", andr_tmp_str); 89 90 printf("Kernel load addr 0x%08x size %u KiB\n", 91 kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); 92 93 int len = 0; 94 if (*hdr->cmdline) { 95 debug("Kernel command line: %s\n", hdr->cmdline); 96 len += strlen(hdr->cmdline); 97 } 98 99 char *bootargs = env_get("bootargs"); 100 if (bootargs) 101 len += strlen(bootargs); 102 103 char *newbootargs = malloc(len + 2); 104 if (!newbootargs) { 105 puts("Error: malloc in android_image_get_kernel failed!\n"); 106 return -ENOMEM; 107 } 108 *newbootargs = '\0'; 109 110 if (bootargs) { 111 strcpy(newbootargs, bootargs); 112 strcat(newbootargs, " "); 113 } 114 if (*hdr->cmdline) 115 strcat(newbootargs, hdr->cmdline); 116 117 env_set("bootargs", newbootargs); 118 119 if (os_data) { 120 *os_data = (ulong)hdr; 121 *os_data += hdr->page_size; 122 } 123 if (os_len) 124 *os_len = hdr->kernel_size; 125 return 0; 126 } 127 128 int android_image_check_header(const struct andr_img_hdr *hdr) 129 { 130 return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); 131 } 132 133 ulong android_image_get_end(const struct andr_img_hdr *hdr) 134 { 135 ulong end; 136 /* 137 * The header takes a full page, the remaining components are aligned 138 * on page boundary 139 */ 140 end = (ulong)hdr; 141 end += hdr->page_size; 142 end += ALIGN(hdr->kernel_size, hdr->page_size); 143 end += ALIGN(hdr->ramdisk_size, hdr->page_size); 144 end += ALIGN(hdr->second_size, hdr->page_size); 145 146 if (hdr->header_version >= 1) 147 end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); 148 149 return end; 150 } 151 152 u32 android_image_get_ksize(const struct andr_img_hdr *hdr) 153 { 154 return hdr->kernel_size; 155 } 156 157 void android_image_set_kload(struct andr_img_hdr *hdr, u32 load_address) 158 { 159 hdr->kernel_addr = load_address; 160 } 161 162 ulong android_image_get_kload(const struct andr_img_hdr *hdr) 163 { 164 return android_image_get_kernel_addr(hdr); 165 } 166 167 int android_image_get_ramdisk(const struct andr_img_hdr *hdr, 168 ulong *rd_data, ulong *rd_len) 169 { 170 if (!hdr->ramdisk_size) { 171 *rd_data = *rd_len = 0; 172 return -1; 173 } 174 175 printf("RAM disk load addr 0x%08x size %u KiB\n", 176 hdr->ramdisk_addr, DIV_ROUND_UP(hdr->ramdisk_size, 1024)); 177 178 *rd_data = (unsigned long)hdr; 179 *rd_data += hdr->page_size; 180 *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); 181 182 *rd_len = hdr->ramdisk_size; 183 return 0; 184 } 185 186 int android_image_get_fdt(const struct andr_img_hdr *hdr, 187 ulong *rd_data) 188 { 189 if (!hdr->second_size) { 190 *rd_data = 0; 191 return -1; 192 } 193 /* 194 * If kernel dtb is enabled, we have read kernel dtb in 195 * init_kernel_dtb() -> rockchip_read_dtb_file() and may have been 196 * done(optional) selection: 197 * 198 * 1. apply fdt overlay; 199 * 2. select fdt by adc or gpio; 200 * 201 * After that, we didn't update dtb at all untill run here, it's fine to 202 * pass current fdt to kernel. 203 */ 204 #if defined(CONFIG_USING_KERNEL_DTB) 205 *rd_data = (ulong)gd->fdt_blob; 206 207 /* 208 * If kernel dtb is disabled and support rockchip image, we need to call 209 * rockchip_read_dtb_file() to get dtb with some optional selection. 210 */ 211 #elif defined(CONFIG_RKIMG_BOOTLOADER) 212 ulong fdt_addr = 0; 213 int ret; 214 215 /* Get resource addr and fdt addr */ 216 fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); 217 if (!fdt_addr) { 218 printf("No Found FDT Load Address.\n"); 219 return -1; 220 } 221 222 ret = rockchip_read_dtb_file((void *)fdt_addr); 223 if (ret < 0) { 224 printf("%s: failed to read dtb file, ret=%d\n", __func__, ret); 225 return ret; 226 } 227 228 *rd_data = fdt_addr; 229 230 /* 231 * If kernel dtb is disabled and not support rockchip image, 232 * get dtb from second position. 233 */ 234 #else 235 *rd_data = (unsigned long)hdr; 236 *rd_data += hdr->page_size; 237 *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); 238 *rd_data += ALIGN(hdr->ramdisk_size, hdr->page_size); 239 240 printf("FDT load addr 0x%08x size %u KiB\n", 241 hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024)); 242 #endif 243 244 return 0; 245 } 246 247 long android_image_load(struct blk_desc *dev_desc, 248 const disk_partition_t *part_info, 249 unsigned long load_address, 250 unsigned long max_size) { 251 void *buf; 252 long blk_cnt = 0; 253 long blk_read = 0; 254 u32 comp; 255 u32 kload_addr; 256 257 if (max_size < part_info->blksz) 258 return -1; 259 260 /* We don't know the size of the Android image before reading the header 261 * so we don't limit the size of the mapped memory. 262 */ 263 buf = map_sysmem(load_address, 0 /* size */); 264 265 /* Read the Android boot.img header and a few parts of 266 * the head of kernel image. 267 */ 268 if (blk_dread(dev_desc, part_info->start, 8, buf) != 8) 269 blk_read = -1; 270 271 if (!blk_read && android_image_check_header(buf) != 0) { 272 printf("** Invalid Android Image header **\n"); 273 blk_read = -1; 274 } 275 276 277 if (!blk_read) { 278 blk_cnt = (android_image_get_end(buf) - (ulong)buf + 279 part_info->blksz - 1) / part_info->blksz; 280 comp = android_image_parse_kernel_comp(buf); 281 /* 282 * We should load a compressed kernel Image 283 * to high memory 284 */ 285 if (comp != IH_COMP_NONE) { 286 load_address += android_image_get_ksize(buf) * 3; 287 load_address = env_get_ulong("kernel_addr_c", 16, load_address); 288 unmap_sysmem(buf); 289 buf = map_sysmem(load_address, 0 /* size */); 290 } 291 292 if (blk_cnt * part_info->blksz > max_size) { 293 debug("Android Image too big (%lu bytes, max %lu)\n", 294 android_image_get_end(buf) - (ulong)buf, 295 max_size); 296 blk_read = -1; 297 } else { 298 debug("Loading Android Image (%lu blocks) to 0x%lx... ", 299 blk_cnt, load_address); 300 blk_read = blk_dread(dev_desc, part_info->start, 301 blk_cnt, buf); 302 } 303 304 /* 305 * zImage is not need to decompress 306 * kernel will handle decompress itself 307 */ 308 if (comp != IH_COMP_NONE && comp != IH_COMP_ZIMAGE) { 309 kload_addr = env_get_ulong("kernel_addr_r", 16, 0x02080000); 310 android_image_set_kload(buf, kload_addr); 311 android_image_set_comp(buf, comp); 312 } else { 313 android_image_set_comp(buf, IH_COMP_NONE); 314 } 315 316 } 317 318 unmap_sysmem(buf); 319 320 debug("%lu blocks read: %s\n", 321 blk_read, (blk_read == blk_cnt) ? "OK" : "ERROR"); 322 if (blk_read != blk_cnt) 323 return -1; 324 325 return load_address; 326 } 327 328 #if !defined(CONFIG_SPL_BUILD) 329 /** 330 * android_print_contents - prints out the contents of the Android format image 331 * @hdr: pointer to the Android format image header 332 * 333 * android_print_contents() formats a multi line Android image contents 334 * description. 335 * The routine prints out Android image properties 336 * 337 * returns: 338 * no returned results 339 */ 340 void android_print_contents(const struct andr_img_hdr *hdr) 341 { 342 const char * const p = IMAGE_INDENT_STRING; 343 /* os_version = ver << 11 | lvl */ 344 u32 os_ver = hdr->os_version >> 11; 345 u32 os_lvl = hdr->os_version & ((1U << 11) - 1); 346 u32 header_version = hdr->header_version; 347 348 printf("%skernel size: %x\n", p, hdr->kernel_size); 349 printf("%skernel address: %x\n", p, hdr->kernel_addr); 350 printf("%sramdisk size: %x\n", p, hdr->ramdisk_size); 351 printf("%sramdisk addrress: %x\n", p, hdr->ramdisk_addr); 352 printf("%ssecond size: %x\n", p, hdr->second_size); 353 printf("%ssecond address: %x\n", p, hdr->second_addr); 354 printf("%stags address: %x\n", p, hdr->tags_addr); 355 printf("%spage size: %x\n", p, hdr->page_size); 356 printf("%sheader_version: %x\n", p, header_version); 357 /* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) 358 * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) */ 359 printf("%sos_version: %x (ver: %u.%u.%u, level: %u.%u)\n", 360 p, hdr->os_version, 361 (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F, 362 (os_lvl >> 4) + 2000, os_lvl & 0x0F); 363 printf("%sname: %s\n", p, hdr->name); 364 printf("%scmdline: %s\n", p, hdr->cmdline); 365 366 if (header_version >= 1) { 367 printf("%srecovery dtbo size: %x\n", p, hdr->recovery_dtbo_size); 368 printf("%srecovery dtbo offset: %llx\n", p, hdr->recovery_dtbo_offset); 369 printf("%sheader size: %x\n", p, hdr->header_size); 370 } 371 } 372 #endif 373