rockchip: add basic uimage code

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Change-Id: Idaf6d9e1888fde4e750435a0484636945442cbe2
This commit is contained in:
Joseph Chen 2020-02-07 12:03:32 +08:00 committed by Jianhong Chen
parent 059c50ac0b
commit 191c6877bc
4 changed files with 284 additions and 0 deletions

View File

@ -0,0 +1,18 @@
/*
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ROCKCHIP_UIMAGE_H_
#define __ROCKCHIP_UIMAGE_H_
#define UIMG_I(fmt, args...) printf("uImage: "fmt, ##args)
void *uimage_load_bootables(void);
int uimage_sysmem_free_each(image_header_t *img);
int uimage_sysmem_reserve_each(image_header_t *hdr);
int rockchip_read_uimage_dtb(void *fdt_addr, char **hash, int *hash_size);
#endif

View File

@ -592,6 +592,14 @@ config ROCKCHIP_FIT_IMAGE
help
This enables loading dtb from fit image.
config ROCKCHIP_UIMAGE
bool "Enable support for legacy uImage"
depends on !FIT_SIGNATURE && USING_KERNEL_DTB
select CMD_BOOT_UIMAGE
default n
help
This enables loading dtb from uImage image.
config ROCKCHIP_EARLY_DISTRO_DTB
bool "Enable support for distro dtb early"
depends on DISTRO_DEFAULTS && USING_KERNEL_DTB && CMD_FS_GENERIC

View File

@ -30,6 +30,7 @@ obj-y += hotkey.o
obj-$(CONFIG_USING_KERNEL_DTB) += kernel_dtb.o
obj-$(CONFIG_ROCKCHIP_FIT_IMAGE) += fit.o
obj-$(CONFIG_ROCKCHIP_UIMAGE) += uimage.o
obj-$(CONFIG_ROCKCHIP_SMCCC) += rockchip_smccc.o
obj-$(CONFIG_ROCKCHIP_VENDOR_PARTITION) += vendor.o
obj-$(CONFIG_ROCKCHIP_RESOURCE_IMAGE) += resource_img.o

View File

@ -0,0 +1,257 @@
/*
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <boot_rkimg.h>
#include <image.h>
#include <malloc.h>
#include <sysmem.h>
#include <asm/arch/resource_img.h>
#include <asm/arch/uimage.h>
static 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)
{
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);
blknum = DIV_ROUND_UP(size, blksz);
if (!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)
{
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)raddr);
sysmem_free((phys_addr_t)kaddr);
sysmem_free((phys_addr_t)faddr);
return 0;
}
int rockchip_read_uimage_dtb(void *fdt_addr, char **hash, int *hash_size)
{
struct blk_desc *dev_desc;
disk_partition_t part;
image_header_t *hdr;
char *part_name;
ulong data, offset;
ulong size;
#ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
ulong dst;
int idx = 3;
#else
int idx = 2;
#endif
int ret;
dev_desc = rockchip_get_bootdev();
if (!dev_desc) {
printf("No dev_desc!\n");
return ENODEV;
}
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 -ENODEV;
}
hdr = uimage_get_hdr(dev_desc, &part);
if (!hdr)
return -ENODEV;
image_multi_getimg(hdr, idx, &data, &size);
offset = data - (ulong)hdr;
free(hdr);
#ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
/* reserve enough space before fdt */
dst = (ulong)fdt_addr -
ALIGN(size, dev_desc->blksz) - CONFIG_SYS_FDT_PAD;
ret = uimage_load_one(dev_desc, &part, offset, size, (void *)dst);
if (ret) {
UIMG_I("Failed to load resource file, ret=%d\n", ret);
return ret;
}
if (!sysmem_alloc_base(MEM_RESOURCE, (phys_addr_t)dst,
ALIGN(size, RK_BLK_SIZE)))
return -ENOMEM;
ret = resource_create_ram_list(dev_desc, (void *)dst);
if (ret) {
UIMG_I("Failed to create resource list, ret=%d\n", ret);
return ret;
}
printf("Found DTB in uImage.%d\n", idx);
ret = rockchip_read_resource_dtb(fdt_addr, hash, hash_size);
#else
printf("DTB(uimage.%d): rk-kernel.dtb\n", idx);
ret = uimage_load_one(dev_desc, &part, offset, size, fdt_addr);
#endif
if (ret) {
UIMG_I("Failed to load fdt, ret=%d\n", ret);
return ret;
}
return 0;
}