/* * (C) Copyright 2019 Rockchip Electronics Co., Ltd * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include int uimage_load_one(struct blk_desc *dev_desc, disk_partition_t *part, int pos_off, int size, void *dst) { u32 blknum, blkoff; u32 unused; ulong blksz; void *buf; blksz = dev_desc->blksz; blkoff = pos_off / blksz; unused = pos_off - blkoff * blksz; blknum = DIV_ROUND_UP(size, blksz) + !!unused; if (!size) return -EINVAL; if (!IS_ALIGNED(unused, ARCH_DMA_MINALIGN)) { buf = memalign(ARCH_DMA_MINALIGN, blknum * blksz); if (!buf) return -ENOMEM; if (blk_dread(dev_desc, part->start + blkoff, blknum, buf) != blknum) { free(buf); return -EIO; } memcpy(dst, buf + unused, size); free(buf); } else { if (blk_dread(dev_desc, part->start + blkoff, blknum, (void *)((ulong)dst - unused)) != blknum) return -EIO; } return 0; } static image_header_t *uimage_get_hdr(struct blk_desc *dev_desc, disk_partition_t *part) { image_header_t *hdr; hdr = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE); if (!hdr) return NULL; if (blk_dread(dev_desc, part->start, 1, hdr) != 1) goto err; if (!image_check_magic(hdr) || (image_get_type(hdr) != IH_TYPE_MULTI)) goto err; return hdr; err: free(hdr); return NULL; } void *uimage_load_bootables(void) { struct blk_desc *dev_desc; disk_partition_t part; image_header_t *hdr; char *part_name; ulong raddr; ulong kaddr; ulong faddr; int blknum; raddr = env_get_ulong("ramdisk_addr_r", 16, 0); kaddr = env_get_ulong("kernel_addr_r", 16, 0); faddr = env_get_ulong("fdt_addr_r", 16, 0); if (!faddr || !kaddr || !raddr) return NULL; dev_desc = rockchip_get_bootdev(); if (!dev_desc) { UIMG_I("No dev_desc\n"); return NULL; } if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) part_name = PART_RECOVERY; else part_name = PART_BOOT; if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { UIMG_I("No %s partition\n", part_name); return NULL; } hdr = uimage_get_hdr(dev_desc, &part); if (!hdr) return NULL; /* load */ blknum = DIV_ROUND_UP(image_get_image_size(hdr), dev_desc->blksz); hdr = sysmem_alloc(MEM_UIMAGE, blknum * dev_desc->blksz); if (!hdr) return NULL; if (blk_dread(dev_desc, part.start, blknum, (void *)hdr) != blknum) { UIMG_I("Failed to read %s data\n", part.name); return NULL; } return hdr; } int uimage_sysmem_reserve_each(image_header_t *hdr, u32 *ramdisk_sz) { ulong raddr, kaddr, faddr; ulong data, size; int blknum; int blksz = RK_BLK_SIZE; raddr = env_get_ulong("ramdisk_addr_r", 16, 0); kaddr = env_get_ulong("kernel_addr_r", 16, 0); faddr = env_get_ulong("fdt_addr_r", 16, 0); if (!faddr || !kaddr || !raddr) return -EINVAL; /* kernel */ image_multi_getimg(hdr, 0, &data, &size); blknum = DIV_ROUND_UP(size, blksz); if (!sysmem_alloc_base(MEM_KERNEL, (phys_addr_t)kaddr, blknum * blksz)) return -ENOMEM; /* ramdisk */ image_multi_getimg(hdr, 1, &data, &size); *ramdisk_sz = size; blknum = DIV_ROUND_UP(size, blksz); if (size && !sysmem_alloc_base(MEM_RAMDISK, (phys_addr_t)raddr, blknum * blksz)) return -ENOMEM; /* fdt */ image_multi_getimg(hdr, 2, &data, &size); blknum = DIV_ROUND_UP(size, blksz); if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)faddr, blknum * blksz)) return -ENOMEM; env_set_hex("fdt_high", faddr); env_set_hex("initrd_high", raddr); env_set("bootm-reloc-at", "y"); return 0; } int uimage_sysmem_free_each(image_header_t *img, u32 ramdisk_sz) { ulong raddr, kaddr, faddr; raddr = env_get_ulong("ramdisk_addr_r", 16, 0); kaddr = env_get_ulong("kernel_addr_r", 16, 0); faddr = env_get_ulong("fdt_addr_r", 16, 0); sysmem_free((phys_addr_t)img); sysmem_free((phys_addr_t)kaddr); sysmem_free((phys_addr_t)faddr); if (ramdisk_sz) sysmem_free((phys_addr_t)raddr); return 0; } #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE int uimage_init_resource(struct blk_desc *dev_desc) { disk_partition_t part; ulong data, offset, size; image_header_t *hdr; char *part_name = PART_BOOT; int ret, idx = 3; void *buf; if (!dev_desc) return -ENODEV; #ifndef CONFIG_ANDROID_AB if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) part_name = PART_RECOVERY; #endif if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { UIMG_I("No %s partition\n", part_name); return -ENODEV; } hdr = uimage_get_hdr(dev_desc, &part); if (!hdr) return -EAGAIN; image_multi_getimg(hdr, idx, &data, &size); offset = data - (ulong)hdr; free(hdr); buf = memalign(ARCH_DMA_MINALIGN, ALIGN(size, dev_desc->blksz)); if (!buf) return -ENOMEM; printf("RESC: '%s', blk@0x%08lx\n", part.name, part.start + (offset / dev_desc->blksz)); ret = uimage_load_one(dev_desc, &part, offset, size, buf); if (ret) return ret; ret = resource_setup_ram_list(dev_desc, buf); if (ret) { UIMG_I("Failed to setup resource ram list, ret=%d\n", ret); return ret; } return 0; } #endif