Files
luban-lite-t3e-pro/application/baremetal/bootloader/lib/aicupg/ram_fwc.c
刘可亮 0ef85b55da v1.1.0
2024-09-30 17:06:01 +08:00

172 lines
4.9 KiB
C

/*
* Copyright (c) 2023-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Wu Dehuang <dehuang.wu@artinchip.com>
*/
#include <string.h>
#include <aicupg.h>
#include <aic_core.h>
#include <aic_crc32.h>
#include "upg_internal.h"
struct artinchip_image_info {
char magic[8];
char platform[64];
char product[64];
char version[64];
char media_type[64];
u32 media_dev_id;
u8 media_id[64]; /* NAND ID or MMC ID */
u32 meta_offset; /* Meta Area start offset */
u32 meta_size; /* Meta Area size */
u32 file_offset; /* File data Area start offset */
u32 file_size; /* File data Area size */
};
static struct artinchip_image_info image_info;
void ram_fwc_start(struct fwc_info *fwc)
{
pr_debug("%s, FWC name %s\n", __func__, fwc->meta.name);
if (strcmp(fwc->meta.name, "image.info") != 0) {
fwc->priv = 0; /* Don't process it */
} else {
fwc->priv = &image_info;
memset(&image_info, 0, sizeof(image_info));
}
fwc->block_size = 1;
}
static enum upg_dev_type get_device_type(struct artinchip_image_info *info)
{
enum upg_dev_type type = UPG_DEV_TYPE_RAM;
pr_debug("%s, %s\n", __func__, info->media_type);
if (strcmp(info->media_type, "mmc") == 0)
type = UPG_DEV_TYPE_MMC;
else if (strcmp(info->media_type, "raw-nand") == 0)
type = UPG_DEV_TYPE_RAW_NAND;
else if (strcmp(info->media_type, "spi-nand") == 0)
type = UPG_DEV_TYPE_SPI_NAND;
else if (strcmp(info->media_type, "spi-nor") == 0)
type = UPG_DEV_TYPE_SPI_NOR;
return type;
}
enum upg_dev_type get_media_type(struct fwc_info *fwc)
{
enum upg_dev_type type = UPG_DEV_TYPE_RAM;
pr_debug("%s, %s\n", __func__, fwc->mpart.media.media_type);
if (strcmp(fwc->mpart.media.media_type, "mmc") == 0)
type = UPG_DEV_TYPE_MMC;
else if (strcmp(fwc->mpart.media.media_type, "raw-nand") == 0)
type = UPG_DEV_TYPE_RAW_NAND;
else if (strcmp(fwc->mpart.media.media_type, "spi-nand") == 0)
type = UPG_DEV_TYPE_SPI_NAND;
else if (strcmp(fwc->mpart.media.media_type, "spi-nor") == 0)
type = UPG_DEV_TYPE_SPI_NOR;
return type;
}
static s32 image_info_proc(struct fwc_info *fwc,
struct artinchip_image_info *info)
{
enum upg_dev_type type;
s32 ret = 0;
(void)ret;
type = get_device_type(info);
pr_info("Write to: %s(%d)\n", get_current_device_name(type), type);
#if defined(AICUPG_MMC_ARTINCHIP)
if (type == UPG_DEV_TYPE_MMC) {
/*
* STEP1: make GPT partitions
* If create GPT partitions failed, should RESP failure to HOST
*/
ret = mmc_fwc_prepare(fwc, info->media_dev_id);
if (ret < 0) {
pr_err("Create GPT partitions failed\n");
return ret;
}
}
#endif
#if defined(AICUPG_NAND_ARTINCHIP)
if (type == UPG_DEV_TYPE_SPI_NAND) {
/*
* When receive FWC: image info, it is going to start firmware
* upgrading, probe mtd device and create ubi volumes first.
*/
ret = nand_fwc_prepare(fwc, info->media_dev_id);
if (ret < 0) {
pr_err("NAND prepare failed\n");
return ret;
}
}
#endif
#if defined(AICUPG_NOR_ARTINCHIP)
if (type == UPG_DEV_TYPE_SPI_NOR) {
/*
* When receive FWC: image info, it is going to start firmware
* upgrading, probe mtd device first.
*/
ret = nor_fwc_prepare(fwc, info->media_dev_id);
if (ret < 0) {
pr_err("NOR prepare failed\n");
return ret;
}
}
#endif
return 0;
}
/*
* Current implementation, only one special RAM FWC need to be processed,
* image.info
* This FWC is the same with fiwmware image header, and we can get information
* about media type which firmware will be burn.
*
* This FWC will be sent before any FWC in "target" is coming.
*/
s32 ram_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len)
{
struct artinchip_image_info *info;
fwc->trans_size += len;
fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, len);
pr_debug("%s, data len %d, trans len %d\n", __func__, len, fwc->trans_size);
if (fwc->priv == 0)
return len;
/* Only process image info data */
if (len >= sizeof(*info)) {
info = (struct artinchip_image_info *)fwc->priv;
memcpy(info, buf, sizeof(*info));
image_info_proc(fwc, info);
}
pr_debug("%s, l: %d\n", __func__, __LINE__);
return len;
}
void ram_fwc_data_end(struct fwc_info *fwc)
{
struct artinchip_image_info *info;
enum upg_dev_type type;
if (fwc->priv) {
info = (struct artinchip_image_info *)fwc->priv;
type = get_device_type(info);
/* Switch device type for following FWCs */
set_current_device_type(type);
set_current_device_id(info->media_dev_id);
}
}