rockchip: add bootrkp command

Add support for booting system from rockchip
format partition.

Change-Id: I513d2f2f53dcb1a578447c1ea112b2e4e7c9838a
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
This commit is contained in:
Andy Yan 2017-08-29 17:21:04 +08:00 committed by Kever Yang
parent 08dcd37c06
commit 4d5d72683f
3 changed files with 207 additions and 0 deletions

View File

@ -192,6 +192,12 @@ config ROCKCHIP_RESOURCE_IMAGE
This enables support to get dtb or logo files from
rockchip resource image format partition.
config ROCKCHIP_PARTITION_BOOT
bool "Enable support for booting system from rockchip format partition"
depends on ROCKCHIP_RESOURCE_IMAGE
help
This enables support for bootimg system from rockchip format partition
source "arch/arm/mach-rockchip/rk3036/Kconfig"
source "arch/arm/mach-rockchip/rk3188/Kconfig"
source "arch/arm/mach-rockchip/rk322x/Kconfig"

View File

@ -26,6 +26,7 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
obj-$(CONFIG_ROCKCHIP_BLOCK_API) += blk.o
obj-$(CONFIG_ROCKCHIP_PARAM) += rockchip_parameter.o
obj-$(CONFIG_ROCKCHIP_RESOURCE_IMAGE) += resource_img.o
obj-$(CONFIG_ROCKCHIP_PARTITION_BOOT) += bootrkp.o
obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o
obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o

View File

@ -0,0 +1,200 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <config.h>
#include <linux/list.h>
#include <malloc.h>
#include <asm/arch/resource_img.h>
#include "rockchip_parameter.h"
#include "rockchip_blk.h"
#define TAG_KERNEL 0x4C4E524B
#define PART_MISC "misc"
#define PART_KERNEL "kernel"
#define PART_BOOT "boot"
#define PART_RECOVERY "recovery"
#define DTB_FILE "rk-kernel.dtb"
#define BOOTLOADER_MESSAGE_OFFSET_IN_MISC (16 * 1024)
#define BOOTLOADER_MESSAGE_BLK_OFFSET (BOOTLOADER_MESSAGE_OFFSET_IN_MISC >> 9)
enum android_boot_mode {
ANDROID_BOOT_MODE_NORMAL = 0,
/* "recovery" mode is triggered by the "reboot recovery" command or
* equivalent adb/fastboot command. It can also be triggered by writing
* "boot-recovery" in the BCB message. This mode should boot the
* recovery kernel.
*/
ANDROID_BOOT_MODE_RECOVERY,
/* "bootloader" mode is triggered by the "reboot bootloader" command or
* equivalent adb/fastboot command. It can also be triggered by writing
* "bootonce-bootloader" in the BCB message. This mode should boot into
* fastboot.
*/
ANDROID_BOOT_MODE_BOOTLOADER,
};
struct bootloader_message {
char command[32];
char status[32];
char recovery[768];
/*
* The 'recovery' field used to be 1024 bytes. It has only ever
* been used to store the recovery command line, so 768 bytes
* should be plenty. We carve off the last 256 bytes to store the
* stage string (for multistage packages) and possible future
* expansion.
*/
char stage[32];
char slot_suffix[32];
char reserved[192];
};
struct rockchip_image {
uint32_t tag;
uint32_t size;
int8_t image[1];
uint32_t crc;
};
static int read_boot_mode_from_misc(struct blk_part *misc)
{
struct bootloader_message *bmsg;
int size = DIV_ROUND_UP(sizeof(struct bootloader_message),
RK_BLK_SIZE) * RK_BLK_SIZE;
int ret = 0;
bmsg = memalign(ARCH_DMA_MINALIGN, size);
ret = blkdev_read(bmsg, misc->from + BOOTLOADER_MESSAGE_BLK_OFFSET,
size >> 9);
if (ret < 0)
goto out;
if (!strcmp(bmsg->command, "boot-recovery")) {
printf("boot mode: recovery\n");
ret = ANDROID_BOOT_MODE_RECOVERY;
} else {
printf("boot mode: normal\n");
ret = ANDROID_BOOT_MODE_NORMAL;
}
out:
free(bmsg);
return ret;
}
/*
* non-OTA packaged kernel.img & boot.img
* return the image size on success, and a
* negative value on error.
*/
static int read_rockchip_image(struct blk_part *part, void *dst)
{
struct rockchip_image *img;
int header_len = 8;
int cnt;
int ret;
img = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE);
if (!img) {
printf("out of memory\n");
return -ENOMEM;
}
/* read first block with header imformation */
ret = blkdev_read(img, part->from, 1);
if (ret < 0)
goto err;
if (img->tag != TAG_KERNEL) {
printf("%s: invalid image tag\n", part->name);
goto err;
}
memcpy(dst, img->image, RK_BLK_SIZE - header_len);
/*
* read the rest blks
* total size = image size + 8 bytes header + 4 bytes crc32
*/
cnt = DIV_ROUND_UP(img->size + 8 + 4, RK_BLK_SIZE);
ret = blkdev_read(dst + RK_BLK_SIZE - header_len,
part->from + 1, cnt - 1);
if (!ret)
ret = img->size;
err:
free(img);
return ret;
}
static int do_bootrkp(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
ulong fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0);
ulong ramdisk_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
ulong kernel_addr_r = env_get_ulong("kernel_addr_r", 16, 0x480000);
struct blk_part *boot;
struct blk_part *kernel;
struct blk_part *misc;
int ramdisk_size;
int kernel_size;
int fdt_size;
int boot_mode;
int ret = 0;
char cmdbuf[64];
misc = rockchip_get_blk_part(PART_MISC);
if (misc)
boot_mode = read_boot_mode_from_misc(misc);
else
boot_mode = ANDROID_BOOT_MODE_RECOVERY;
if (boot_mode == ANDROID_BOOT_MODE_RECOVERY)
boot = rockchip_get_blk_part(PART_RECOVERY);
else
boot = rockchip_get_blk_part(PART_BOOT);
kernel = rockchip_get_blk_part(PART_KERNEL);
if (!kernel || !boot) {
ret = CMD_RET_FAILURE;
goto out;
}
kernel_size = read_rockchip_image(kernel, (void *)kernel_addr_r);
if (kernel_size < 0) {
ret = CMD_RET_FAILURE;
goto out;
}
ramdisk_size = read_rockchip_image(boot, (void *)ramdisk_addr_r);
if (ramdisk_size < 0) {
ret = CMD_RET_FAILURE;
goto out;
}
fdt_size = rockchip_read_resource_file((void *)fdt_addr_r, DTB_FILE, 0, 0);
if (fdt_size < 0) {
ret = CMD_RET_FAILURE;
goto out;
}
printf("kernel_size:0x%ulx ramdisk_size:0x%x\n", kernel_size, ramdisk_size);
sprintf(cmdbuf, "booti 0x%lx 0x%lx:0x%x 0x%lx",
kernel_addr_r, ramdisk_addr_r, ramdisk_size, fdt_addr_r);
run_command(cmdbuf, 0);
out:
return ret;
}
U_BOOT_CMD(
bootrkp, CONFIG_SYS_MAXARGS, 1, do_bootrkp,
"boot Linux Image image from rockchip partition storage",
""
);