luckfox-pico-sdk/sysdrv/source/uboot/u-boot/common/spl/spl_boot_image.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

306 lines
8.8 KiB
C

/*
* (C) Copyright 2023 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <android_image.h>
#include <crypto.h>
#include <image.h>
#include <mp_boot.h>
#include <part.h>
#include <spl.h>
#include <asm/io.h>
#define BLK_CNT(_num_bytes, _block_size) \
((_num_bytes + _block_size - 1) / _block_size)
#ifdef CONFIG_ANDROID_BOOT_IMAGE
static int android_check_header(const struct andr_img_hdr *hdr)
{
return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
}
static void print_hash(const char *label, u8 *hash, int len)
{
int i;
printf("%s:\n 0x", label ? : "Hash");
for (i = 0; i < len; i++)
printf("%02x", hash[i]);
printf("\n");
}
#if 0
static void spl_android_print_contents(const struct andr_img_hdr *hdr)
{
const char * const p = IMAGE_INDENT_STRING;
/* os_version = ver << 11 | lvl */
u32 os_ver = hdr->os_version >> 11;
u32 os_lvl = hdr->os_version & ((1U << 11) - 1);
u32 header_version = hdr->header_version;
printf("%skernel size: %x\n", p, hdr->kernel_size);
printf("%skernel address: %x\n", p, hdr->kernel_addr);
printf("%sramdisk size: %x\n", p, hdr->ramdisk_size);
printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr);
printf("%ssecond size: %x\n", p, hdr->second_size);
printf("%ssecond address: %x\n", p, hdr->second_addr);
printf("%stags address: %x\n", p, hdr->tags_addr);
printf("%spage size: %x\n", p, hdr->page_size);
printf("%sheader_version: %x\n", p, header_version);
/* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) */
printf("%sos_version: %x (ver: %u.%u.%u, level: %u.%u)\n",
p, hdr->os_version,
(os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F,
(os_lvl >> 4) + 2000, os_lvl & 0x0F);
printf("%sname: %s\n", p, hdr->name);
printf("%scmdline: %s\n", p, hdr->cmdline);
if (header_version == 1 || header_version == 2) {
printf("%srecovery dtbo size: %x\n", p, hdr->recovery_dtbo_size);
printf("%srecovery dtbo offset: %llx\n", p, hdr->recovery_dtbo_offset);
printf("%sheader size: %x\n", p, hdr->header_size);
}
if (header_version == 2 || header_version == 3) {
printf("%sdtb size: %x\n", p, hdr->dtb_size);
printf("%sdtb addr: %llx\n", p, hdr->dtb_addr);
}
if (header_version >= 3) {
printf("%scmdline: %s\n", p, hdr->total_cmdline);
printf("%svendor ramdisk size: %x\n", p, hdr->vendor_ramdisk_size);
printf("%svendor page size: %x\n", p, hdr->vendor_page_size);
printf("%svendor header version: %d\n", p, hdr->vendor_header_version);
printf("%svendor header size: %x\n", p, hdr->vendor_header_size);
}
if (header_version >= 4) {
printf("%svendor ramdisk table size: %x\n",
p, hdr->vendor_ramdisk_table_size);
printf("%svendor ramdisk table entry num: %x\n",
p, hdr->vendor_ramdisk_table_entry_num);
printf("%svendor ramdisk table entry size: %x\n",
p, hdr->vendor_ramdisk_table_entry_size);
printf("%svendor bootconfig size: %d\n",
p, hdr->vendor_bootconfig_size);
}
}
#endif
static ulong android_size(struct andr_img_hdr *hdr)
{
ulong len;
len = hdr->page_size +
ALIGN(hdr->kernel_size, hdr->page_size) +
ALIGN(hdr->ramdisk_size, hdr->page_size) +
ALIGN(hdr->second_size, hdr->page_size);
if (hdr->header_version > 0)
len += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
if (hdr->header_version > 1)
len += ALIGN(hdr->dtb_size, hdr->page_size);
#if 0
spl_android_print_contents(hdr);
#endif
return len;
}
int spl_load_android(struct task_data *data)
{
struct spl_load_info *info = &data->info;
void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
disk_partition_t part;
ulong blkcnt;
debug("== Android: load start\n");
if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
printf("No boot partition\n");
return -ENOENT;
}
blkcnt = BLK_CNT(sizeof(struct andr_img_hdr), info->bl_len);
if (info->read(info, part.start, blkcnt, buf) != blkcnt)
return -EIO;
if (android_check_header(buf))
return -EINVAL;
blkcnt = BLK_CNT(android_size(buf), info->bl_len);
if (info->read(info, part.start, blkcnt, buf) != blkcnt)
return -EIO;
data->boot_addr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
data->boot_size = blkcnt * info->bl_len;
flush_dcache_range((ulong)data, (ulong)data + sizeof(*data));
flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
debug("== Android: load 0x%08lx size OK\n", blkcnt * info->bl_len);
return 0;
}
#ifdef CONFIG_ARMV8_CE_SHA1
int spl_hash_android(struct task_data *data)
{
struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
sha1_context ctx;
uchar hash[32];
void *buf;
printf("== Android: hash start\n");
if (hdr->header_version >= 3)
return -EINVAL;
sha1_starts(&ctx);
buf = (void *)hdr + hdr->page_size;
sha1_update(&ctx, (const uchar *)buf, hdr->kernel_size);
sha1_update(&ctx, (const uchar *)&hdr->kernel_size, sizeof(hdr->kernel_size));
buf += ALIGN(hdr->kernel_size, hdr->page_size);
sha1_update(&ctx, (const uchar *)buf, hdr->ramdisk_size);
sha1_update(&ctx, (const uchar *)&hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
sha1_update(&ctx, (const uchar *)buf, hdr->second_size);
sha1_update(&ctx, (const uchar *)&hdr->second_size, sizeof(hdr->second_size));
if (hdr->header_version > 0) {
buf += ALIGN(hdr->second_size, hdr->page_size);
sha1_update(&ctx, (const uchar *)buf, hdr->recovery_dtbo_size);
sha1_update(&ctx, (const uchar *)&hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
}
if (hdr->header_version > 1) {
buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
sha1_update(&ctx, (const uchar *)buf, hdr->dtb_size);
sha1_update(&ctx, (const uchar *)&hdr->dtb_size, sizeof(hdr->dtb_size));
}
sha1_finish(&ctx, hash);
if (memcmp(hash, hdr->id, 20)) {
print_hash("Hash from header", (u8 *)hdr->id, 20);
print_hash("Hash real", (u8 *)hash, 20);
return -EBADFD;
}
printf("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
return 0;
}
#else
int spl_hash_android(struct task_data *data)
{
struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
struct udevice *dev;
sha_context ctx;
uchar hash[32];
void *buf;
debug("== Android: hash start\n");
if (hdr->header_version >= 3)
return -EINVAL;
ctx.algo = CRYPTO_SHA1;
dev = crypto_get_device(ctx.algo);
if (!dev) {
printf("No crypto device for sha1\n");
return -ENODEV;
}
ctx.length = hdr->kernel_size + sizeof(hdr->kernel_size) +
hdr->ramdisk_size + sizeof(hdr->ramdisk_size) +
hdr->second_size + sizeof(hdr->second_size);
if (hdr->header_version > 0)
ctx.length += hdr->recovery_dtbo_size + sizeof(hdr->recovery_dtbo_size);
if (hdr->header_version > 1)
ctx.length += hdr->dtb_size + sizeof(hdr->dtb_size);
crypto_sha_init(dev, &ctx);
buf = (void *)hdr + hdr->page_size;
crypto_sha_update(dev, buf, hdr->kernel_size);
crypto_sha_update(dev, &hdr->kernel_size, sizeof(hdr->kernel_size));
buf += ALIGN(hdr->kernel_size, hdr->page_size);
crypto_sha_update(dev, buf, hdr->ramdisk_size);
crypto_sha_update(dev, &hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
crypto_sha_update(dev, buf, hdr->second_size);
crypto_sha_update(dev, &hdr->second_size, sizeof(hdr->second_size));
if (hdr->header_version > 0) {
buf += ALIGN(hdr->second_size, hdr->page_size);
crypto_sha_update(dev, buf, hdr->recovery_dtbo_size);
crypto_sha_update(dev, &hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
}
if (hdr->header_version > 1) {
buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
crypto_sha_update(dev, buf, hdr->dtb_size);
crypto_sha_update(dev, &hdr->dtb_size, sizeof(hdr->dtb_size));
}
crypto_sha_final(dev, &ctx, hash);
if (memcmp(hash, hdr->id, 20)) {
print_hash("Hash from header", (u8 *)hdr->id, 20);
print_hash("Hash real", (u8 *)hash, 20);
return -EBADFD;
}
debug("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
return 0;
}
#endif
#endif
#ifdef CONFIG_ROCKCHIP_FIT_IMAGE
int spl_load_fit(struct task_data *data)
{
struct spl_load_info *info = &data->info;
void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
disk_partition_t part;
ulong blkcnt;
int size;
debug("== FIT: load start\n");
if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
printf("No boot partition\n");
return -ENOENT;
}
blkcnt = BLK_CNT(sizeof(struct fdt_header), info->bl_len);
if (info->read(info, part.start, blkcnt, buf) != blkcnt)
return -EIO;
if (fdt_check_header(buf))
return -EINVAL;
size = fit_get_totalsize(buf, &size);
blkcnt = BLK_CNT(size, info->bl_len);
if (info->read(info, part.start, blkcnt, buf) != blkcnt)
return -EIO;
flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
debug("== FIT: load 0x%08x size OK\n", size);
return 0;
}
#endif