GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
|
||||
obj-$(CONFIG_CMD_HW_GUNZIP) += cmd_hw_gunzip.o
|
||||
|
||||
obj-$(if $(CONFIG_LOTUS_DISABLE_DOWNLOAD),,y) += download_process.o
|
||||
obj-y += getinfo.o
|
||||
obj-y += misc.o
|
||||
|
||||
obj-$(CONFIG_EXT4_SPARSE) += unsparse.o
|
||||
obj-y += shutdown.o
|
||||
obj-$(CONFIG_QS_MCU) += mcu.o
|
||||
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, "HW GUNZIP"
|
||||
|
||||
#include <common.h>
|
||||
#include <memalign.h>
|
||||
#include <linux/lotus/hw_decompress.h>
|
||||
#include <mmc.h>
|
||||
#include <linux/lotus/flash_read.h>
|
||||
#include <asm/cache.h>
|
||||
#include <usb.h>
|
||||
#include <linux/lotus/timestamp.h>
|
||||
#include <irq_func.h>
|
||||
#include <dm/device.h>
|
||||
#include <serial.h>
|
||||
#include <linux/lotus/tags.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#define HW_GUNZIP_STEP_MIN 0x20000
|
||||
#define DEFAULT_STEP (256 * 1024)
|
||||
|
||||
static bool decomp_done = false;
|
||||
|
||||
int decompress_by_step(void *dst, uint dst_len, void *src, uint *z_len,
|
||||
ulong offset, uint step)
|
||||
{
|
||||
uint cur_read_size = step;
|
||||
uchar *buffer = src;
|
||||
hw_decompress_op_type op_type;
|
||||
uint cur_offset;
|
||||
int ret = -1;
|
||||
int head_size = sizeof(image_header_t) + HW_GZIP_HEAD_SIZE;
|
||||
uint size;
|
||||
|
||||
if (!dst || !buffer)
|
||||
return -EINVAL;
|
||||
|
||||
if (!step)
|
||||
step = DEFAULT_STEP;
|
||||
|
||||
cur_read_size = step;
|
||||
|
||||
ret = flash_read(offset, cur_read_size, buffer);
|
||||
if (ret < 0) {
|
||||
pr_err("Fail to read from flash\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = image_get_size((image_header_t *)buffer) + sizeof(image_header_t);
|
||||
if (size < step) {
|
||||
pr_err("Invalid image size, %u(size) less than %u(step)\n", size, step);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dcache_disable();
|
||||
hw_dec_init();
|
||||
|
||||
ret = hw_dec_decompress_ex(HW_DECOMPRESS_OP_START,
|
||||
dst, &dst_len, buffer + head_size, cur_read_size - head_size);
|
||||
if (ret != 0) {
|
||||
pr_err("hw decompress start failed(%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_offset = cur_read_size;
|
||||
while (cur_offset < size) {
|
||||
if ((cur_offset + step) < size) {
|
||||
cur_read_size = step;
|
||||
op_type = HW_DECOMPRESS_OP_CONTINUE;
|
||||
} else {
|
||||
cur_read_size = size - cur_offset;
|
||||
op_type = HW_DECOMPRESS_OP_END;
|
||||
}
|
||||
|
||||
ret = flash_read(offset + cur_offset, cur_read_size, buffer + cur_offset);
|
||||
if (ret < 0) {
|
||||
pr_err("Read flash failed(%d).\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_debug("Decompress 0x%p to 0x%p, size 0x%x\n", buffer + cur_offset, dst, cur_read_size);
|
||||
|
||||
ret = hw_dec_decompress_ex(op_type,
|
||||
dst, &dst_len, buffer + cur_offset, cur_read_size);
|
||||
if (ret != 0) {
|
||||
pr_err("hw decompress failed.(%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_offset += cur_read_size;
|
||||
}
|
||||
|
||||
if (z_len)
|
||||
*z_len = size;
|
||||
ret = 0;
|
||||
out:
|
||||
hw_dec_uinit();
|
||||
dcache_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hw_gunzip(void *dst, uint dst_len, void *src, uint *src_len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (decomp_done)
|
||||
return 0;
|
||||
|
||||
dcache_disable();
|
||||
|
||||
hw_dec_init();
|
||||
|
||||
ret = hw_dec_decompress_ex(HW_DECOMPRESS_OP_ONCE, (uchar *)dst,
|
||||
&dst_len, (uchar *)src, *src_len);
|
||||
if (ret != 0) {
|
||||
pr_err("hw decompress fail!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
hw_dec_uinit();
|
||||
|
||||
dcache_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_hw_gunzip(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc != 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
uintptr_t src = simple_strtoul(argv[1], NULL, 16); /* 1: src argc, 16: base */
|
||||
uintptr_t dst = simple_strtoul(argv[2], NULL, 16); /* 2: dst argc, 16: base */
|
||||
|
||||
if (src & 0xf || dst & 0xf) {
|
||||
pr_err("src[0x%lx] or dst[0x%lx] NOT 16Byte-aligned!\n", src, dst);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
uint magic_num0 = *(uint *)(src + HEAD_MAGIC_NUM0_OFFSET);
|
||||
uint magic_num1 = *(uint *)(src + HEAD_MAGIC_NUM1_OFFSET);
|
||||
if ((magic_num0 != HEAD_MAGIC_NUM0) || (magic_num1 != HEAD_MAGIC_NUM1)) {
|
||||
pr_err("Invalid image!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
uint comp_len = *(uint *)(src + COMPRESSED_SIZE_OFFSET);
|
||||
uint uncomp_len = *(uint *)(src + UNCOMPRESSED_SIZE_OFFSET);
|
||||
|
||||
ret = hw_gunzip((void *)dst, uncomp_len, (uchar *)(src + HW_GZIP_HEAD_SIZE), &comp_len);
|
||||
if (ret != 0) {
|
||||
pr_err("hw gunzip fail!(%d)\n", ret);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int read_dtb(ulong offset, uint image_size,
|
||||
ulong src_addr, uint src_size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (src_size & (FLASH_ALIGNED_SIZE - 1))
|
||||
src_size = src_size & ~(FLASH_ALIGNED_SIZE - 1);
|
||||
|
||||
ret = flash_read(offset + src_size, image_size - src_size,
|
||||
(uchar *)(src_addr + src_size));
|
||||
if (ret < 0) {
|
||||
pr_err("read DTB file failed(0x%x).\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_boothz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
uchar *src_addr = NULL;
|
||||
uchar *dst_addr = NULL;
|
||||
ulong offset;
|
||||
uint image_size;
|
||||
uint step;
|
||||
int ret;
|
||||
char *sub_cmd = NULL;
|
||||
char bootm_str[30];
|
||||
uint z_len = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 5:
|
||||
step = DEFAULT_STEP;
|
||||
break;
|
||||
case 6:
|
||||
if (isdigit(*(argv[5]))) {
|
||||
step = \
|
||||
(uint)(uintptr_t)simple_strtoul(argv[5], NULL, 16);
|
||||
} else {
|
||||
step = DEFAULT_STEP;
|
||||
sub_cmd = argv[5];
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (isdigit(*(argv[5])) || !isdigit(*(argv[6]))) {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
sub_cmd = argv[5];
|
||||
step = \
|
||||
(uint)(uintptr_t)simple_strtoul(argv[6], NULL, 16);
|
||||
default:
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (step < HW_GUNZIP_STEP_MIN) {
|
||||
pr_err("step less than 0x%x!\n", HW_GUNZIP_STEP_MIN);
|
||||
ret = CMD_RET_USAGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((step % HW_GUNZIP_STEP_MIN) != 0) {
|
||||
pr_err("step should be aligned with 0x%x!\n", HW_GUNZIP_STEP_MIN);
|
||||
ret = CMD_RET_USAGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
src_addr = (uchar *)(uintptr_t)simple_strtoul(argv[1], NULL, 16);
|
||||
dst_addr = (uchar *)(uintptr_t)simple_strtoul(argv[2], NULL, 16);
|
||||
offset = (ulong)simple_strtoul(argv[3], NULL, 16);
|
||||
image_size = (ulong)simple_strtoul(argv[4], NULL, 16);
|
||||
|
||||
ret = decompress_by_step(dst_addr, CONFIG_SYS_BOOTM_LEN, src_addr, &z_len, offset, step);
|
||||
if (ret != 0) {
|
||||
pr_err("Fail to get image from flash(%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
decomp_done = true;
|
||||
|
||||
ret = read_dtb(offset, image_size, (ulong)src_addr, z_len);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sub_cmd)
|
||||
run_command(sub_cmd, 0);
|
||||
|
||||
memset(bootm_str, 0, sizeof(bootm_str));
|
||||
snprintf(bootm_str, sizeof(bootm_str), "bootm 0x%p", src_addr);
|
||||
pr_info("%s\n", bootm_str);
|
||||
run_command(bootm_str, 0);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
hwgunzip, 3, 0, do_hw_gunzip,
|
||||
"uncompress file with hardware IP, eg:[ugzip compress_addr uncompress_addr]",
|
||||
"hwgunzip <src> <dst>\n"
|
||||
"src and dst must be 16Byte-aligned"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
boothz, 7, 0, do_boothz,
|
||||
"Read and decompress image by hardware: boothz <src> <dst> <flash offset> <size> [sub command | chunk size]",
|
||||
"<src> <dst> <flash offset> <size> [sub command | chunk size]\n"
|
||||
" <src> <dst> <flash offset> <size> <sub command> <chunk size>\n"
|
||||
" - Read image from <flash offset> to <src>, and decompress to <dst> by hardware decompressed module.\n"
|
||||
" eg:\n"
|
||||
" boothz 0x41000000 0x40008000 0x100000 0x400000\n"
|
||||
" boothz 0x41000000 0x40008000 0x100000 0x400000 xmediaapp\n"
|
||||
" boothz 0x41000000 0x40008000 0x100000 0x400000 0x40000\n"
|
||||
" boothz 0x41000000 0x40008000 0x100000 0x400000 xmediaapp 0x40000\n"
|
||||
" <src> and <dst> is DDR location, and must be 16Byte-aligned;\n"
|
||||
" <flash offset> and <size> must be flash-block-size-aligned;\n"
|
||||
" <chunk size> is one step size for reading and decompressing one time;\n"
|
||||
" <sub command> is a command that will be run after decompressing image and before going to kernel."
|
||||
);
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <serial.h>
|
||||
#include <usb.h>
|
||||
#include <crc16.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
|
||||
#define XHEAD 0xAB
|
||||
#define XCMD 0xCD
|
||||
#define ACK 0xAA /* ACK VALUE */
|
||||
#define NAK 0x55 /* NAK VALUE */
|
||||
|
||||
#define START_FRAME_LEN 5
|
||||
#define MAX_BUFF_SIZE 1024
|
||||
#define MAX_SEND_SIZE 20
|
||||
|
||||
static char recv_buf[MAX_BUFF_SIZE];
|
||||
|
||||
#undef DUMP_SWITCH
|
||||
#ifdef DUMP_SWITCH
|
||||
static void dump_buf(char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
char *p = buf;
|
||||
printf("%s->%d, buf=0x%.8x, len=%d\n",
|
||||
__FUNCTION__, __LINE__,
|
||||
(int)(buf), (int)(len));
|
||||
for (i = 0; i < (len); i++) {
|
||||
printf("0x%.2x ", *(p + i));
|
||||
if (!((i + 1) & 0x07))
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned short calc_crc16(const unsigned char *packet, unsigned long length)
|
||||
{
|
||||
unsigned short crc16 = 0;
|
||||
unsigned long i;
|
||||
|
||||
const unsigned short *crc16_table = get_crc16_table();
|
||||
if (crc16_table == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
crc16 = ((crc16 << 8) | /* fetches High or low 8 bit */
|
||||
packet[i]) ^ crc16_table[(crc16 >> 8) & 0xFF];
|
||||
|
||||
for (i = 0; i < 2; i++) /* 2: Cycle and fetches High or low 8 bit */
|
||||
crc16 = ((crc16 << 8) | 0) ^ crc16_table[(crc16 >> 8) & 0xFF];
|
||||
|
||||
return crc16;
|
||||
}
|
||||
|
||||
static int recv_byte(void)
|
||||
{
|
||||
if (serial_tstc())
|
||||
return serial_getc();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char recv_data(void)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
while (ret == -1)
|
||||
ret = recv_byte();
|
||||
|
||||
return (char)ret;
|
||||
}
|
||||
|
||||
void download_process(void)
|
||||
{
|
||||
int i = 0, cr = 0, ret = -1;
|
||||
unsigned int head_frame_len = 0;
|
||||
unsigned int cmd_len = 0;
|
||||
unsigned char send_buf[MAX_SEND_SIZE] = {0};
|
||||
unsigned short cksum;
|
||||
|
||||
do {
|
||||
do {
|
||||
do {
|
||||
cr = recv_byte();
|
||||
} while (cr != XHEAD);
|
||||
|
||||
head_frame_len = START_FRAME_LEN;
|
||||
recv_buf[0] = (char)cr;
|
||||
|
||||
/* RECV: head frame */
|
||||
for (i = 0; i < (head_frame_len - 1) && i < (sizeof(recv_buf) - 1); i++) {
|
||||
recv_buf[i + 1] = recv_data();
|
||||
}
|
||||
|
||||
/* crc check */
|
||||
cksum = calc_crc16((unsigned char*)recv_buf,3);
|
||||
if (cksum == (((unsigned char)recv_buf[3] << 8) | (unsigned char)recv_buf[4])) {
|
||||
/* init */
|
||||
cmd_len = (unsigned short)(((unsigned char)recv_buf[1] << 8) | (unsigned char)recv_buf[2]) + 3;
|
||||
if (cmd_len >= sizeof(recv_buf))
|
||||
goto head_fail;
|
||||
|
||||
/* SEND: ack */
|
||||
send_buf[0] = ACK;
|
||||
serial_putc(send_buf[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
head_fail:
|
||||
/* init */
|
||||
cmd_len = 0;
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
|
||||
/* SEND: nak */
|
||||
send_buf[0] = NAK;
|
||||
serial_putc(send_buf[0]);
|
||||
|
||||
} while (1);
|
||||
|
||||
do {
|
||||
do {
|
||||
cr = recv_byte();
|
||||
} while (cr != XCMD);
|
||||
|
||||
recv_buf[0] = (char)cr;
|
||||
|
||||
/* RECV: cmd data, cmd_len check in head flow */
|
||||
for (i = 0;i < (cmd_len - 1); i++) {
|
||||
recv_buf[i + 1] = recv_data();
|
||||
}
|
||||
|
||||
/* crc check */
|
||||
cksum = calc_crc16((unsigned char*)recv_buf, cmd_len - 2);
|
||||
if (cksum == (((unsigned char)recv_buf[cmd_len - 2] << 8) | (unsigned char)recv_buf[cmd_len - 1])) {
|
||||
/* SEND: ack wait result */
|
||||
send_buf[0] = ACK;
|
||||
serial_putc(send_buf[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
/* SEND: nak */
|
||||
send_buf[0] = NAK;
|
||||
serial_putc(send_buf[0]);
|
||||
#ifdef DUMP_SWITCH
|
||||
dump_buf(recv_buf, cmd_len);
|
||||
#endif
|
||||
} while (1);
|
||||
|
||||
/* clean crc */
|
||||
recv_buf[cmd_len - 1] = 0;
|
||||
recv_buf[cmd_len - 2] = 0;
|
||||
|
||||
/* cmd process */
|
||||
ret = run_command((recv_buf + 1), 0);
|
||||
if (ret != 0) {
|
||||
/* SEND: end flag */
|
||||
serial_puts("[EOT](ERROR)\n");
|
||||
} else{
|
||||
/* SEND: end flag */
|
||||
serial_puts("[EOT](OK)\n");
|
||||
}
|
||||
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void set_update_mode_flag(int flag)
|
||||
{
|
||||
#ifdef REG_UPDATE_MODE_FLAG
|
||||
writel(flag, REG_UPDATE_MODE_FLAG);
|
||||
#endif
|
||||
}
|
||||
|
||||
int is_bootstrap(void)
|
||||
{
|
||||
if (readl(REG_START_FLAG) == START_MAGIC)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_bootstrap_flag(u32 flag)
|
||||
{
|
||||
writel(flag, REG_START_FLAG);
|
||||
writel(flag, SYS_CTRL_REG_BASE + REG_SC_DDRT14);
|
||||
}
|
||||
|
||||
void usb_eth_init(void)
|
||||
{
|
||||
/* Support usb eth */
|
||||
run_command("usb start", 0);
|
||||
}
|
||||
|
||||
int is_usb_device_bootstrap(void)
|
||||
{
|
||||
if (readl(SYS_CTRL_REG_BASE + REG_SC_SYSBOOT9) == SELF_BOOT_TYPE_USBDEV)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void download_boot(void)
|
||||
{
|
||||
if (!is_bootstrap())
|
||||
return;
|
||||
|
||||
/* Enable uart output for download */
|
||||
serial_enable_output(true);
|
||||
|
||||
/* Clear flag */
|
||||
set_bootstrap_flag(0);
|
||||
|
||||
if (!is_usb_device_bootstrap())
|
||||
usb_eth_init();
|
||||
|
||||
serial_puts("start download process.\n");
|
||||
|
||||
/* Wait cmd from tool */
|
||||
for (;;) {
|
||||
if (is_usb_device_bootstrap()) {
|
||||
/* Clear updata mode flag */
|
||||
set_update_mode_flag(1);
|
||||
#ifdef CONFIG_USB_GADGET
|
||||
udc_connect();
|
||||
#else
|
||||
printf("[ERROR]: Downloading boot from usb NOT supported.\n");
|
||||
#endif
|
||||
} else
|
||||
download_process();
|
||||
}
|
||||
|
||||
serial_enable_output(false);
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/rawnand.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#if defined(CONFIG_FMC_SPI_NAND) \
|
||||
|| defined(CONFIG_FMC_NAND)
|
||||
#include <linux/lotus/nfc_common.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
#if defined(CONFIG_FMC_SPI_NAND) || defined(CONFIG_FMC_NAND) || \
|
||||
defined(CONFIG_FMC_SPI_NOR)
|
||||
static int print_mtd_info(const struct mtd_info_ex *mtd_info,const char *cmd)
|
||||
{
|
||||
unsigned int len, ix;
|
||||
|
||||
if (mtd_info == NULL || mtd_info->type == 0) { /* no find spi/nand */
|
||||
printf("no find ");
|
||||
if (*cmd == 's')
|
||||
printf("spi");
|
||||
else if (*cmd == 'n')
|
||||
printf("nand");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Block:%sB ", ultohstr(mtd_info->erasesize));
|
||||
printf("Chip:%sB*%d ",
|
||||
ultohstr(mtd_info->chipsize),
|
||||
mtd_info->numchips);
|
||||
|
||||
if (*cmd == 'n') {
|
||||
printf("Page:%sB ", ultohstr(mtd_info->pagesize));
|
||||
printf("OOB:%sB ", ultohstr(mtd_info->oobsize));
|
||||
#if defined(CONFIG_FMC_SPI_NAND) || defined(CONFIG_FMC_NAND)
|
||||
#ifdef CONFIG_CMD_NAND
|
||||
printf("ECC:%s ", nand_ecc_name(mtd_info->ecctype));
|
||||
#endif
|
||||
#else
|
||||
printf("ECC:%s ",
|
||||
get_ecctype_str((mtd_info->ecctype & 0x7)));
|
||||
#endif
|
||||
}
|
||||
printf("\nID:");
|
||||
|
||||
len = (mtd_info->id_length > 8 ? 8 : mtd_info->id_length); /* 8:len of max id */
|
||||
for (ix = 0; ix < len; ix++)
|
||||
printf("0x%02X ", mtd_info->ids[ix]);
|
||||
printf("\nName:\"%s\"\n", mtd_info->name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_getinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
char *cmd = NULL;
|
||||
|
||||
if (argc < 2) { /* 2:len of argv */
|
||||
cmd_usage(cmdtp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd = argv[1];
|
||||
if (strcmp(cmd, "bootmode") == 0) {
|
||||
switch (get_boot_media()) {
|
||||
default:
|
||||
case BOOT_MEDIA_UNKNOWN:
|
||||
printf("Boot from unknown device,"
|
||||
" please check your hardware config.\n");
|
||||
return -1;
|
||||
|
||||
case BOOT_MEDIA_NAND:
|
||||
printf("nand\n");
|
||||
break;
|
||||
|
||||
case BOOT_MEDIA_SPIFLASH:
|
||||
printf("spi\n");
|
||||
break;
|
||||
|
||||
case BOOT_MEDIA_EMMC:
|
||||
printf("emmc\n");
|
||||
break;
|
||||
|
||||
case BOOT_MEDIA_UFS:
|
||||
printf("ufs\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "version") == 0) {
|
||||
printf("version: %s\n", U_BOOT_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FMC_SPI_NAND) || defined(CONFIG_FMC_NAND)
|
||||
if (strcmp(cmd, "nand") == 0) {
|
||||
struct mtd_info_ex *mtd_info = NULL;
|
||||
mtd_info = get_nand_info();
|
||||
return print_mtd_info(mtd_info, cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FMC_SPI_NOR
|
||||
if (strcmp(cmd, "spi") == 0) {
|
||||
struct mtd_info_ex *mtd_info = NULL;
|
||||
mtd_info = get_spiflash_info();
|
||||
return print_mtd_info(mtd_info, cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
getinfo, CONFIG_SYS_MAXARGS, 1, do_getinfo,
|
||||
"print hardware information",
|
||||
"bootmode - get start memeory type e.g. nand/spi etc\n"
|
||||
"getinfo nand - get nand flash information\n"
|
||||
"getinfo spi - get spi flash information\n"
|
||||
"getinfo version - get system version\n"
|
||||
);
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, "LOAD MCU S2"
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/lotus/flash_read.h>
|
||||
#include <linux/lotus/image.h>
|
||||
|
||||
static int do_load_mcu_stage2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
int ret = -1;
|
||||
u32 res, aligned_offset, aligned_size;
|
||||
u32 total_size;
|
||||
u32 stage1_size;
|
||||
u32 mcu_offset = CONFIG_MCU_FW_AREA_POS;
|
||||
struct mcu_fw_head *fw_head = (struct mcu_fw_head *)MCU_SRAM_BASE;
|
||||
u8 *buf = (u8 *)CONFIG_MCU_FW_BUF_ADDR;
|
||||
u32 v;
|
||||
|
||||
if (CONFIG_LOAD_MCU_FW_FLAG == 0 || CONFIG_MCU_FW_AREA_LEN == 0)
|
||||
goto error;
|
||||
|
||||
if (fw_head->fw_magic != _MCU_FW_MAGIC) {
|
||||
pr_info("No MCU FW\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
total_size = fw_head->fw_total_size;
|
||||
stage1_size = fw_head->fw_stage1_size;
|
||||
if (total_size < stage1_size
|
||||
|| (((total_size + 1024 - 1) >> 10) & (~((1 << 10) - 1))) != 0) {
|
||||
pr_err("Invalid MCU FW size!Total: %u, Stage1: %u\n", total_size, stage1_size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = mcu_offset & (FLASH_ALIGNED_SIZE - 1);
|
||||
aligned_offset = rounddown(mcu_offset, FLASH_ALIGNED_SIZE);
|
||||
aligned_size = roundup(total_size + res, FLASH_ALIGNED_SIZE);
|
||||
if (aligned_size > CONFIG_MCU_FW_BUF_SIZE) {
|
||||
pr_err("No buffer for MCU FW!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = flash_read(aligned_offset, aligned_size, buf);
|
||||
if (ret != 0) {
|
||||
pr_err("Fail to read MCU area!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy((void *)MCU_SRAM_BASE + stage1_size, buf + res + stage1_size, total_size - stage1_size);
|
||||
memmove(buf, buf + res, total_size);
|
||||
|
||||
printf("MCU FW location in DDR: 0x%x, 0x%x Bytes\n", (u32)buf, total_size);
|
||||
|
||||
v = readl(REG_MCU_FW_DDR_SIZE);
|
||||
v &= ~((1 << 10) - 1);
|
||||
v |= (total_size + 1024 - 1) >> 10;
|
||||
writel(v, REG_MCU_FW_DDR_SIZE);
|
||||
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
/* Release MCU to stage2 */
|
||||
writel(0xbeef0001, SYS_CTRL_REG_BASE + REG_SC_SYSBOOT7);
|
||||
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
return 1;
|
||||
error:
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
loadmcustage2, 1, 0, do_load_mcu_stage2,
|
||||
"Load MCU Stage2",
|
||||
"loadmcustage2\n"
|
||||
""
|
||||
);
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <image.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <bootm.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <mapmem.h>
|
||||
#include <serial.h>
|
||||
#include <linux/lotus/flash_read.h>
|
||||
#include <linux/lotus/timestamp.h>
|
||||
|
||||
unsigned long ticks2usec(unsigned long ticks)
|
||||
{
|
||||
ulong tbclk = get_tbclk();
|
||||
|
||||
tbclk /= 1000000;
|
||||
ticks /= tbclk;
|
||||
return ((ulong)ticks);
|
||||
}
|
||||
|
||||
|
||||
unsigned long relocate_dtb(bootm_headers_t *bootm_hdr)
|
||||
{
|
||||
image_info_t os;
|
||||
void *image_buf;
|
||||
ulong image_size;
|
||||
|
||||
if (!bootm_hdr) {
|
||||
pr_err("Invalid params for %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
os = bootm_hdr->os;
|
||||
image_size = os.image_len;
|
||||
image_buf = map_sysmem(os.image_start, image_size);
|
||||
pr_info("Image addr 0x%lX, len 0x%lX\n", (ulong)image_buf, image_size);
|
||||
|
||||
memmove((char *)CONFIG_DTB_BASE, (char *)(image_buf + image_size), CONFIG_DTB_MAX_SIZE);
|
||||
|
||||
return CONFIG_DTB_BASE;
|
||||
}
|
||||
|
||||
void show_boot_timestamp(void)
|
||||
{
|
||||
char *show_timestamp;
|
||||
|
||||
TIME_STAMP(0);
|
||||
stopwatch_trigger();
|
||||
show_timestamp = env_get("timestamp");
|
||||
if (*show_timestamp == 'y') {
|
||||
serial_enable_output(true);
|
||||
timestamp_print(0);
|
||||
stopwatch_print();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_AUTOBOOT
|
||||
int board_run_command(const char *cmdline)
|
||||
{
|
||||
int ret = -1;
|
||||
int (*entry)(void *) = (void *)CONFIG_SBL_LOAD_ADDR;
|
||||
|
||||
ret = flash_read(CONFIG_SBL_OFFSET, CONFIG_SBL_SIZE, (void *)CONFIG_SBL_LOAD_ADDR);
|
||||
if (ret != 0) {
|
||||
pr_err("Fail to read from flash\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf ("## Starting SBL at 0x%08lX ...\n", (ulong)CONFIG_SBL_LOAD_ADDR);
|
||||
|
||||
dsb();
|
||||
isb();
|
||||
ret = entry(NULL);
|
||||
|
||||
printf ("## SBL terminated, ret = %d\n", ret);
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#define CFG_MAX_SHUTDOWN 10
|
||||
|
||||
static struct shutdown_ctrl {
|
||||
int count;
|
||||
void (*shutdown[CFG_MAX_SHUTDOWN])(void);
|
||||
} shutdown_ctrl = {0, {0}, };
|
||||
|
||||
void add_shutdown(void (*shutdown)(void))
|
||||
{
|
||||
if (shutdown_ctrl.count >= CFG_MAX_SHUTDOWN) {
|
||||
printf("Can't add shutdown function,"
|
||||
"Please increase CFG_MAX_SHUTDOWN count\n");
|
||||
return;
|
||||
}
|
||||
shutdown_ctrl.shutdown[shutdown_ctrl.count++]
|
||||
= shutdown;
|
||||
}
|
||||
|
||||
void do_shutdown(void)
|
||||
{
|
||||
int ix;
|
||||
for (ix = 0; ix < shutdown_ctrl.count; ix++)
|
||||
shutdown_ctrl.shutdown[ix]();
|
||||
}
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <div64.h>
|
||||
#include <mmc.h>
|
||||
#include <image-sparse.h>
|
||||
|
||||
/******************************************************************************/
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
#include <ufs.h>
|
||||
#define UFS_BLKSIZE_SHIFT (12)
|
||||
#endif
|
||||
|
||||
#define EMMC_BLKSIZE_SHIFT (9)
|
||||
#define SZ_1M_SHIFT (20)
|
||||
|
||||
/* #define DEBUG_EXT4 */
|
||||
|
||||
/******************************************************************************/
|
||||
void print_header_info(sparse_header_t *header)
|
||||
{
|
||||
#ifdef DEBUG_EXT4
|
||||
printf("sparse header info:\n");
|
||||
printf("magic: 0x%x\n", header->magic);
|
||||
printf("major_version: 0x%x\n", header->major_version);
|
||||
printf("minor_version: 0x%x\n", header->minor_version);
|
||||
printf("file_hdr_sz: %d\n", header->file_hdr_sz);
|
||||
printf("chunk_hdr_sz: %d\n", header->chunk_hdr_sz);
|
||||
printf("blk_sz: %d\n", header->blk_sz);
|
||||
printf("total_blks: %d\n", header->total_blks);
|
||||
printf("total_chunks: %d\n", header->total_chunks);
|
||||
printf("image_checksum: %d\n", header->image_checksum);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_chunk_info(const chunk_header_t *chunk)
|
||||
{
|
||||
#ifdef DEBUG_EXT4
|
||||
printf("\n");
|
||||
printf("chunk header info:\n");
|
||||
printf("chunk_type: 0x%x\n", chunk->chunk_type);
|
||||
printf("chunk_sz: %d\n", chunk->chunk_sz);
|
||||
printf("total_sz: %d\n", chunk->total_sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_unspare_header_info(const u8 *pbuf, sparse_header_t *sparse_header, char* is_sparse)
|
||||
{
|
||||
memcpy(sparse_header, pbuf, sizeof(sparse_header_t));
|
||||
|
||||
if (!is_sparse_image(sparse_header)) {
|
||||
*is_sparse = 0;
|
||||
return 0;
|
||||
}
|
||||
*is_sparse = 1;
|
||||
print_header_info(sparse_header);
|
||||
return 0;
|
||||
}
|
||||
static int check_parameter(sparse_header_t *header, u32 cnt, unsigned int type)
|
||||
{
|
||||
u64 img_size;
|
||||
|
||||
if (!is_sparse_image(header)) {
|
||||
printf("Invalid sparse format.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check header->blk_sz align to emmc block size */
|
||||
if (type == 0) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if (header->blk_sz & ((1 << EMMC_BLKSIZE_SHIFT) - 1)) {
|
||||
printf("image blk size %d is not aligned to 512Byte.\n", header->blk_sz);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
if (type == 1) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if (header->blk_sz & ((1 << UFS_BLKSIZE_SHIFT) - 1)) {
|
||||
printf("image blk size %d is not aligned to 512Byte.\n", header->blk_sz);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check fs img's real size is larger than partition size */
|
||||
img_size = (u64)(header->total_blks * header->blk_sz);
|
||||
if (type == 0) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if ((img_size >> EMMC_BLKSIZE_SHIFT) > (u64)cnt) {
|
||||
printf("partition size %d MB not enough.\n",
|
||||
(int)(cnt >> (SZ_1M_SHIFT - EMMC_BLKSIZE_SHIFT)));
|
||||
print_header_info(header);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
if (type == 1) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if ((img_size >> UFS_BLKSIZE_SHIFT) > (u64)cnt) {
|
||||
printf("partition size %d MB not enough.\n",
|
||||
(int)(cnt >> (SZ_1M_SHIFT - UFS_BLKSIZE_SHIFT)));
|
||||
print_header_info(header);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_writing_complete(u64 sparse_len, s32 *percent_complete, u32 cnt, u32 blk, unsigned int type)
|
||||
{
|
||||
u64 n;
|
||||
int percent;
|
||||
|
||||
if (type == 0) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
n = (u64)(sparse_len >> EMMC_BLKSIZE_SHIFT) * 100; /* 100: Percentage for complete */
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
if (type == 1) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
n = (u64)(sparse_len >> UFS_BLKSIZE_SHIFT) * 100; /* 100: Percentage for complete */
|
||||
#endif
|
||||
|
||||
do_div(n, cnt);
|
||||
percent = (int)n;
|
||||
if (percent != *percent_complete) {
|
||||
*percent_complete = percent;
|
||||
if (type == 0) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
printf("\rWriting at %d blk# "
|
||||
"-- %3d%% complete. \n",
|
||||
(int)(blk + (sparse_len >> EMMC_BLKSIZE_SHIFT)), percent);
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
if (type == 1) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
printf("\rWriting at %d blk# "
|
||||
"-- %3d%% complete.\n",
|
||||
(int)(blk + (sparse_len >> UFS_BLKSIZE_SHIFT)), percent);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int check_print_results(u64 dense_len, u64 sparse_len, u32 cnt, unsigned int type)
|
||||
{
|
||||
if (type == 0) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if (((u64)cnt << EMMC_BLKSIZE_SHIFT) != sparse_len) {
|
||||
printf("error: partition size %d MB != ext4 image size %d MB\n",
|
||||
(int)(cnt >> (SZ_1M_SHIFT - EMMC_BLKSIZE_SHIFT)),
|
||||
(int)(sparse_len >> SZ_1M_SHIFT));
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
if (type == 1) /* 0: ext4_unsparse 1: ufs_ext4_unsparse */
|
||||
if (((u64)cnt << UFS_BLKSIZE_SHIFT) != sparse_len) {
|
||||
printf("error: partition size %d MB != ext4 image size %d MB\n",
|
||||
(int)(cnt >> (SZ_1M_SHIFT - UFS_BLKSIZE_SHIFT)),
|
||||
(int)(sparse_len >> SZ_1M_SHIFT));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("sparse: %d MB / %d MB.\n", (int)(dense_len >> SZ_1M_SHIFT), (int)(sparse_len >> SZ_1M_SHIFT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext4_unsparse(struct mmc *mmc, u32 dev, u8 *pbuf, u32 blk, u32 cnt)
|
||||
{
|
||||
u32 i, num;
|
||||
u64 dense_len = 0;
|
||||
u64 sparse_len = 0;
|
||||
u32 chunk_len;
|
||||
s32 percent_complete = -1;
|
||||
chunk_header_t *chunk = NULL;
|
||||
sparse_header_t *header = (sparse_header_t *)pbuf;
|
||||
|
||||
check_parameter(header, cnt, 0);
|
||||
|
||||
/* skip the sparse header,to visit first chunk */
|
||||
pbuf += header->file_hdr_sz;
|
||||
|
||||
/* to visit each chunk */
|
||||
for (i = 0; i < header->total_chunks; i++) {
|
||||
/* here the chunk_header */
|
||||
chunk = (chunk_header_t *)pbuf;
|
||||
|
||||
/* go to next chunk's data */
|
||||
pbuf += header->chunk_hdr_sz;
|
||||
|
||||
switch (chunk->chunk_type) {
|
||||
case CHUNK_TYPE_RAW:
|
||||
|
||||
/* to calculate the length of each chunk */
|
||||
chunk_len = chunk->chunk_sz * header->blk_sz;
|
||||
|
||||
/* verify every chunk to asure it is valid */
|
||||
if (chunk->total_sz != (chunk_len + header->chunk_hdr_sz)) {
|
||||
printf("No.%d chunk size error.\n", i);
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dense_len += chunk_len;
|
||||
sparse_len += chunk_len;
|
||||
|
||||
if (sparse_len > ((u64)cnt << EMMC_BLKSIZE_SHIFT)) {
|
||||
printf("error: sparse size %d MB is "
|
||||
"larger than partiton size %d MB.\n",
|
||||
(int)(sparse_len >> SZ_1M_SHIFT),
|
||||
(int)(cnt >> (SZ_1M_SHIFT - EMMC_BLKSIZE_SHIFT)));
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
num = blk_dwrite(mmc_get_blk_desc(mmc), blk,
|
||||
(chunk_len >> EMMC_BLKSIZE_SHIFT), pbuf);
|
||||
if (num != (chunk_len >> EMMC_BLKSIZE_SHIFT)) {
|
||||
printf("Raw data: No.%d blocks written: %s.\n", num, "ERROR");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pbuf += chunk_len;
|
||||
blk += (chunk_len >> EMMC_BLKSIZE_SHIFT);
|
||||
break;
|
||||
|
||||
case CHUNK_TYPE_DONT_CARE:
|
||||
if (chunk->total_sz != header->chunk_hdr_sz) {
|
||||
printf("No.%d chunk size error.\n", i);
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
chunk_len = chunk->chunk_sz * header->blk_sz;
|
||||
sparse_len += chunk_len;
|
||||
|
||||
if (sparse_len > ((u64)cnt << EMMC_BLKSIZE_SHIFT)) {
|
||||
printf("error: sparse size %d MB is "
|
||||
"larger than partiton size %d MB.\n",
|
||||
(int)(sparse_len >> SZ_1M_SHIFT),
|
||||
(int)(cnt >> (SZ_1M_SHIFT - EMMC_BLKSIZE_SHIFT)));
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
blk += (chunk_len >> EMMC_BLKSIZE_SHIFT);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("sparse: unknow chunk type %04x.\n",
|
||||
chunk->chunk_type);
|
||||
return 1;
|
||||
}
|
||||
print_writing_complete(sparse_len, &percent_complete, cnt, blk, 0);
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
if (check_print_results(dense_len, sparse_len, cnt, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_UFS
|
||||
|
||||
int ufs_ext4_unsparse(const u8 *pbuf, u32 blk, u32 cnt)
|
||||
{
|
||||
u32 i, num;
|
||||
u64 dense_len = 0;
|
||||
u64 sparse_len = 0;
|
||||
u32 chunk_len;
|
||||
s32 percent_complete = -1;
|
||||
chunk_header_t *chunk = NULL;
|
||||
sparse_header_t *header = (sparse_header_t *)pbuf;
|
||||
|
||||
check_parameter(header, cnt, 1);
|
||||
/* skip the sparse header,to visit first chunk */
|
||||
pbuf += header->file_hdr_sz;
|
||||
|
||||
/* to visit each chunk */
|
||||
for (i = 0; i < header->total_chunks; i++) {
|
||||
/* here the chunk_header */
|
||||
chunk = (chunk_header_t *)pbuf;
|
||||
/* go to next chunk's data */
|
||||
pbuf += header->chunk_hdr_sz;
|
||||
|
||||
switch (chunk->chunk_type) {
|
||||
case CHUNK_TYPE_RAW:
|
||||
|
||||
/* to calculate the length of each chunk */
|
||||
chunk_len = chunk->chunk_sz * header->blk_sz;
|
||||
|
||||
/* verify every chunk to asure it is valid */
|
||||
if (chunk->total_sz
|
||||
!= (chunk_len + header->chunk_hdr_sz)) {
|
||||
printf("No.%d chunk size error.\n", i);
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dense_len += chunk_len;
|
||||
sparse_len += chunk_len;
|
||||
|
||||
if (sparse_len > ((u64)cnt << UFS_BLKSIZE_SHIFT)) {
|
||||
printf("error: sparse size %d MB is "
|
||||
"larger than partiton size %d MB.\n",
|
||||
(int)(sparse_len >> SZ_1M_SHIFT),
|
||||
(int)(cnt >> (SZ_1M_SHIFT - UFS_BLKSIZE_SHIFT)));
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ufs_write_storage((uint64_t)pbuf,
|
||||
(blk << UFS_BLKSIZE_SHIFT),
|
||||
chunk_len) == 0)
|
||||
num = chunk_len >> UFS_BLKSIZE_SHIFT;
|
||||
else
|
||||
num = 0;
|
||||
|
||||
if (num != (chunk_len >> UFS_BLKSIZE_SHIFT)) {
|
||||
printf("Raw data: No.%d blocks written: %s.\n",
|
||||
num, "ERROR");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pbuf += chunk_len;
|
||||
blk += (chunk_len >> UFS_BLKSIZE_SHIFT);
|
||||
break;
|
||||
|
||||
case CHUNK_TYPE_DONT_CARE:
|
||||
if (chunk->total_sz != header->chunk_hdr_sz) {
|
||||
printf("No.%d chunk size error.\n", i);
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
chunk_len = chunk->chunk_sz * header->blk_sz;
|
||||
sparse_len += chunk_len;
|
||||
|
||||
if (sparse_len > ((u64)cnt << UFS_BLKSIZE_SHIFT)) {
|
||||
printf("error: sparse size %d MB is "
|
||||
"larger than partiton size %d MB.\n",
|
||||
(int)(sparse_len >> SZ_1M_SHIFT),
|
||||
(int)(cnt >> (SZ_1M_SHIFT - UFS_BLKSIZE_SHIFT)));
|
||||
print_chunk_info(chunk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
blk += (chunk_len >> UFS_BLKSIZE_SHIFT);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("sparse: unknown chunk type %04x.\n",
|
||||
chunk->chunk_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_writing_complete(sparse_len, &percent_complete, cnt, blk, 1);
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
if (check_print_results(dense_len, sparse_len, cnt, 1))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UNSPARSE__
|
||||
#define __UNSPARSE__
|
||||
|
||||
int get_unspare_header_info(const u8 *pbuf, sparse_header_t *sparse_header, char *is_sparse);
|
||||
void print_chunk_info(chunk_header_t *chunk);
|
||||
int ext4_unsparse(struct mmc *mmc, u32 dev, u8 *pbuf, u32 blk, u32 cnt);
|
||||
void print_header_info(sparse_header_t *header);
|
||||
#endif
|
||||
Reference in New Issue
Block a user