This commit is contained in:
刘可亮
2024-06-04 19:00:30 +08:00
parent 990c72f5be
commit 0a13af6a1d
1668 changed files with 342810 additions and 37726 deletions

View File

@@ -121,6 +121,21 @@ menu "Upgrading"
bool "Write to NOR support"
default y
depends on AIC_BOOTLOADER_SPINOR_SUPPORT
config AICUPG_LOG_BUFFER_SUPPORT
bool "Support to get log buffer from device"
default y
if AICUPG_LOG_BUFFER_SUPPORT
config AICUPG_LOG_BUFFER_ADDR
hex "Log buffer start address"
default 0x100000 if AIC_CHIP_D21X
default 0x30040000 if AIC_CHIP_D12X
default 0x30040000 if AIC_CHIP_D13X
config AICUPG_LOG_BUFFER_SIZE
hex "Log buffer size"
default 0x3000 if AIC_CHIP_D21X
default 0x3000 if AIC_CHIP_D12X
default 0x3000 if AIC_CHIP_D13X
endif
endmenu # "Upgrading settings"
menu "Commands"
@@ -171,6 +186,11 @@ menu "Commands"
bool "boot progress bar"
default n
config AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE
int "progress bar rotate degress (0/90/270)"
default 0
depends on AIC_BOOTLOADER_CMD_PROGRESS_BAR
config AIC_BOOTLOADER_CMD_FB_CONSOLE
bool "fb console support"
default y

View File

@@ -8,6 +8,7 @@ cwd = GetCurrentDir()
src = Glob('run.c')
src += Glob('reset.c')
src += Glob('aicupg.c')
src += Glob('aicupg_erase.c')
src += Glob('ram_boot.c')
src += Glob('crc32.c')
if GetDepend('AIC_BOOTLOADER_CMD_PROGRESS_BAR'):

View File

@@ -308,6 +308,8 @@ static int do_fat_upg(int intf, char *const blktype)
pr_err("set blk dev failed.\n");
return ret;
}
#else
pr_err("udisk upgrade disabled.\n");
#endif
} else if (!strcmp(blktype, "mmc")) {
#if defined(AICUPG_SDCARD_ENABLE)
@@ -322,6 +324,8 @@ static int do_fat_upg(int intf, char *const blktype)
pr_err("set blk dev failed.\n");
return ret;
}
#else
pr_err("sdcard upgrade disabled.\n");
#endif
} else {
return ret;
@@ -352,9 +356,9 @@ static int do_fat_upg(int intf, char *const blktype)
pr_warn("No protected partition.\n");
else
pr_info("Protected=%s\n", protection);
do_fat_upg_by_single_image(image_name, protection);
ret = do_fat_upg_by_single_image(image_name, protection);
} else {
do_fat_upg_in_direct_mode(file_buf, actread);
ret = do_fat_upg_in_direct_mode(file_buf, actread);
}
err:

View File

@@ -0,0 +1,301 @@
/*
* Copyright (c) 2023, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Wu Dehuang <dehuang.wu@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <console.h>
#include <aic_core.h>
#include <aic_common.h>
#include <aic_errno.h>
#include <aic_utils.h>
#if defined(AICUPG_NOR_ARTINCHIP)
#include <sfud.h>
#endif
#if defined(AICUPG_NAND_ARTINCHIP)
#include <spinand_port.h>
#endif
#if defined(AICUPG_MMC_ARTINCHIP)
#include <mmc.h>
#endif
#define AIC_IMAGE_MAGIC 0x20434941
#define AIC_PAGE_TABLE 0x50434941
#define AIC_SPL_SIZE (128 * 1024)
#define AICUPG_ERASE_HELP \
"ArtInChip data erase command for upgdrading mode:\n" \
"erase [boot]\n" \
" Erase boot program in flash/mmc\n" \
"erase <offset> <length>\n" \
" Erase data in flash/mmc\n"
#define OP_STORAGE_SPINOR 1
#define OP_STORAGE_SPINAND 2
#define OP_STORAGE_MMC 3
static void aicupg_erase_help(void)
{
puts(AICUPG_ERASE_HELP);
}
#if defined(AICUPG_NOR_ARTINCHIP)
extern sfud_flash *sfud_probe(u32 spi_bus);
static int spinor_erase_boot(sfud_flash *flash)
{
u8 data[256];
u32 head;
int i, err;
/* Two image backup */
for (i = 0; i < 2; i++) {
err = sfud_read(flash, i * AIC_SPL_SIZE, 256, data);
if (err) {
printf("Failed to read data from spinor.\n");
return -1;
}
memcpy(&head, data, 4);
if (head == AIC_IMAGE_MAGIC) {
err = sfud_erase(flash, i * AIC_SPL_SIZE, AIC_SPL_SIZE);
if (err) {
printf("Failed to erase spinor.\n");
return -1;
}
}
}
return 0;
}
#endif
static int do_spinor_erase(int argc, char *argv[])
{
int err = -1;
#if defined(AICUPG_NOR_ARTINCHIP)
sfud_flash *flash;
unsigned long offset, length;
flash = sfud_probe(0);
if (!flash) {
printf("Failed to init spinor\n");
return -1;
}
if ((argc == 2) && (!strcmp(argv[1], "boot")))
return spinor_erase_boot(flash);
/* erase <offset> <length> */
if (argc != 3) {
aicupg_erase_help();
return -1;
}
offset = strtol(argv[1], NULL, 0);
length = strtol(argv[2], NULL, 0);
if (offset % 0x1000) {
printf("The start offset is not alignment with 4KB.\n");
return -1;
}
if (length % 0x1000) {
printf("The length is not alignment with 4KB.\n");
return -1;
}
err = sfud_erase(flash, offset, length);
if (err) {
printf("Failed to erase spinor.\n");
return -1;
}
#endif
return err;
}
#if defined(AICUPG_NAND_ARTINCHIP)
#define SPL_CANDIDATE_BLOCK_NUM 18
extern int nand_spl_get_candidate_blocks(u32 *blks, u32 size);
static int spinand_erase_boot(struct aic_spinand *flash)
{
u32 spl_blocks[SPL_CANDIDATE_BLOCK_NUM];
u32 offset, blk_size, head;
int ret, i;
u8 *data;
data = aicos_malloc_align(0, 4096, CACHE_LINE_SIZE);
if (!data) {
printf("Failed to malloc buffer.\n");
return -1;
}
nand_spl_get_candidate_blocks(spl_blocks, SPL_CANDIDATE_BLOCK_NUM);
blk_size = flash->info->page_size * flash->info->pages_per_eraseblock;
for (i = 0; i < SPL_CANDIDATE_BLOCK_NUM; i++) {
offset = spl_blocks[i] * blk_size;
ret = spinand_read(flash, data, offset, flash->info->page_size);
if (ret) {
printf("Failed to read data from spinand.\n");
return -1;
}
memcpy(&head, data, 4);
if (head == AIC_PAGE_TABLE) {
ret = spinand_erase(flash, offset, blk_size);
if (ret) {
printf("Failed to erase spinand.\n");
return -1;
}
}
}
aicos_free_align(0, data);
return ret;
}
#endif
static int do_spinand_erase(int argc, char *argv[])
{
int ret = -1;
#if defined(AICUPG_NAND_ARTINCHIP)
unsigned long offset, length;
struct aic_spinand *flash;
u32 blk_size;
flash = spinand_probe(0);
if (!flash) {
printf("Failed to init spinand\n");
return -1;
}
if ((argc == 2) && (!strcmp(argv[1], "boot")))
return spinand_erase_boot(flash);
/* erase <offset> <length> */
if (argc != 3) {
aicupg_erase_help();
return -1;
}
offset = strtol(argv[1], NULL, 0);
length = strtol(argv[2], NULL, 0);
blk_size = flash->info->page_size * flash->info->pages_per_eraseblock;
if (offset % blk_size) {
printf("The start offset is not alignment with block size.\n");
return -1;
}
if (length % blk_size) {
printf("The length is not alignment with block size.\n");
return -1;
}
ret = spinand_erase(flash, offset, length);
if (ret) {
printf("Failed to erase spinand.\n");
return -1;
}
#endif
return ret;
}
#if defined(AICUPG_MMC_ARTINCHIP)
static int mmc_erase_boot(struct aic_sdmc *host)
{
u32 blkoffset, blkcnt, head;
u8 data[512];
memset(data, 0, 512);
blkcnt = (AIC_SPL_SIZE / 512);
for (int i = 0; i < 2; i++) {
blkoffset = 34 + i * blkcnt;
mmc_bread(host, blkoffset, 1, (void *)data);
memcpy(&head, data, 4);
if (head == AIC_IMAGE_MAGIC) {
memset(data, 0, 512);
mmc_bwrite(host, blkoffset, 1, (void *)data);
}
}
return 0;
}
#endif
static int do_mmc_erase(int argc, char *argv[])
{
int ret = -1;
#if defined(AICUPG_MMC_ARTINCHIP)
unsigned long offset, length, grp_size;
u32 blkoffset, blkcnt;
struct aic_sdmc *host;
ret = mmc_init(0);
if (ret) {
printf("sdmc init failed.\n");
return ret;
}
host = find_mmc_dev_by_index(0);
if (host== NULL) {
printf("can't find mmc device!");
return -1;
}
if ((argc == 2) && (!strcmp(argv[1], "boot")))
return mmc_erase_boot(host);
/* erase <offset> <length> */
if (argc != 3) {
aicupg_erase_help();
return -1;
}
offset = strtol(argv[1], NULL, 0);
length = strtol(argv[2], NULL, 0);
grp_size = host->dev->erase_grp_size * 512;
if (offset % grp_size) {
printf("The start offset is not alignment with group size %ld.\n",
grp_size);
return -1;
}
if (length % grp_size) {
printf("The length is not alignment with group size: %ld.\n", grp_size);
return -1;
}
blkoffset = offset / 512;
blkcnt = length / 512;
mmc_berase(host, blkoffset, blkcnt);
ret = 0;
#endif
return ret;
}
static int do_aicupg_erase(int argc, char *argv[])
{
int ret = -1, target;
target = 0;
#if defined(AICUPG_MMC_ARTINCHIP)
/* When Flash and eMMC/SD are all enabled, the MMC priority is low */
target = OP_STORAGE_MMC;
#endif
#if defined(AICUPG_NOR_ARTINCHIP)
target = OP_STORAGE_SPINOR;
#endif
#if defined(AICUPG_NAND_ARTINCHIP)
target = OP_STORAGE_SPINAND;
#endif
if (target == OP_STORAGE_SPINOR)
ret = do_spinor_erase(argc, argv);
if (target == OP_STORAGE_SPINAND)
ret = do_spinand_erase(argc, argv);
if (target == OP_STORAGE_MMC)
ret = do_mmc_erase(argc, argv);
return ret;
}
CONSOLE_CMD(erase, do_aicupg_erase, "Erase command in upgrading mode.");

View File

@@ -22,6 +22,26 @@
#define APPLICATION_PART "os"
#ifdef AIC_AB_SYSTEM_INTERFACE
#include <absystem.h>
char target[32] = { 0 };
#endif
static struct aic_partition *find_boot_part(struct aic_partition *part, char *name)
{
struct aic_partition *p = part;
while (p) {
if (!strcmp(p->name, name))
break;
p = p->next;
}
return p;
}
static int do_mmc_boot(int argc, char *argv[])
{
int ret = 0, mmc_id = 0;
@@ -57,13 +77,28 @@ static int do_mmc_boot(int argc, char *argv[])
}
part = parts;
while (part) {
if (!strcmp(part->name, APPLICATION_PART))
break;
part = part->next;
#ifdef AIC_AB_SYSTEM_INTERFACE
ret = aic_ota_check();
if (ret) {
printf("Aic ota check error.\n");
}
ret = aic_get_os_to_startup(target);
if (ret) {
printf("Aic get os fail, startup from %s default.\n", APPLICATION_PART);
part = find_boot_part(part, APPLICATION_PART);
} else {
part = find_boot_part(part, target);
printf("Start-up from %s\n", target);
}
#else
part = find_boot_part(part, APPLICATION_PART);
#endif
if (!part) {
printf("Failed to get application partition.\n");
goto out;
@@ -74,6 +109,7 @@ static int do_mmc_boot(int argc, char *argv[])
info.dev_type = DEVICE_MMC;
info.bl_len = MMC_BLOCK_SIZE;
entry_point = 0;
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;

View File

@@ -66,6 +66,7 @@ static int do_nand_boot(int argc, char *argv[])
info.bl_len = mtd->writesize;
info.dev_type = DEVICE_SPINAND;
entry_point = 0;
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;

View File

@@ -65,6 +65,7 @@ static int do_nor_boot(int argc, char *argv[])
info.bl_len = 1;
info.dev_type = DEVICE_SPINOR;
entry_point = 0;
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;

View File

@@ -13,10 +13,7 @@
#include <string.h>
#include <console.h>
#include <artinchip_fb.h>
#ifdef AIC_BOOTLOADER_CMD_FB_CONSOLE
#include <video_font_data.h>
#endif
#undef ALIGN_DOWM
#define ALIGN_DOWM(x, align) ((x) & ~(align - 1))
@@ -48,6 +45,12 @@ static void progress_bar_help(void)
puts(PROGRESS_BAR_HELP);
}
#if ((AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE != 0) && \
(AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE != 90) && \
(AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE != 270))
#error progress bar support rotate 0/90/270 degress
#endif
#ifdef AIC_BOOTLOADER_CMD_FB_CONSOLE
static u32 colour_fg = 0;
static u32 colour_bg = 0;
@@ -153,7 +156,11 @@ void aicfb_draw_rect(struct aicfb_screeninfo *info,
*(fb++) = red;
*(fb++) = 0xFF;
}
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
fb -= info->stride - width * pbytes;
#else
fb += info->stride - width * pbytes;
#endif
}
break;
case MPP_FMT_RGB_565:
@@ -164,7 +171,11 @@ void aicfb_draw_rect(struct aicfb_screeninfo *info,
| (blue >> 3);
fb += sizeof(uint16_t) / sizeof(*fb);
}
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
fb -= info->stride + width * pbytes;
#else
fb += info->stride - width * pbytes;
#endif
}
break;
default:
@@ -236,8 +247,13 @@ static void aicfb_console_put_string(struct aicfb_screeninfo *info,
int i;
for (s = str, i = 0; *s; s++, i++)
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
aicfb_console_putc(info, x, y - (i * VIDEO_FONT_WIDTH), *s);
#else
aicfb_console_putc(info, x + (i * VIDEO_FONT_WIDTH), y, *s);
#endif
#endif /* AIC_BOOTLOADER_CMD_FB_CONSOLE */
}
static void console_set_default_colors(struct aicfb_screeninfo *info)
@@ -256,7 +272,8 @@ static void console_set_default_colors(struct aicfb_screeninfo *info)
void aicfb_draw_bar(unsigned int value)
{
struct aicfb_screeninfo info;
unsigned int x, y, width, height;
unsigned int bar_x, bar_y, width, height;
unsigned int console_x, console_y;
static bool power_on = false;
char str[5];
@@ -273,30 +290,62 @@ void aicfb_draw_bar(unsigned int value)
console_set_default_colors(&info);
}
width = SPLIT_WIDTH(info.width);
height = BAR_HEIGHT;
x = (info.width - width) / 2;
y = (info.height - height) / 2;
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
width = BAR_HEIGHT;
height = SPLIT_WIDTH(info.height);
bar_x = (info.width - width) / 2;
bar_y = (info.height - height) / 2 + height;
console_x = bar_x + BAR_HEIGHT + 5;
console_y = info.height / 2;
#else
width = SPLIT_WIDTH(info.width);
height = BAR_HEIGHT;
bar_x = (info.width - width) / 2;
bar_y = (info.height - height) / 2;
console_x = info.width / 2;
console_y = bar_y + BAR_HEIGHT + 5;
#endif
if (value == 0) {
aicfb_draw_rect(&info, x, y, width, height, BAR_BACKGROUND_COLOR);
aicfb_console_put_string(&info, info.width / 2, y + BAR_HEIGHT + 5, "0%");
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE != 90)
console_x -= VIDEO_FONT_WIDTH;
#endif
aicfb_draw_rect(&info, bar_x, bar_y, width, height, BAR_BACKGROUND_COLOR);
aicfb_console_put_string(&info, console_x, console_y,"0%");
return;
}
if (value < 100)
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
height = height * value / 100;
#else
width = width * value / 100;
#endif
aicfb_draw_rect(&info, x, y, width, height, BAR_FILL_COLOR);
aicfb_draw_rect(&info, bar_x, bar_y, width, height, BAR_FILL_COLOR);
if (value == 100) {
aicfb_console_put_string(&info, info.width / 2, y + BAR_HEIGHT + 5,
"100%,Done!");
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
console_y += VIDEO_FONT_WIDTH;
#else
console_x -= VIDEO_FONT_WIDTH * 2;
#endif
aicfb_console_put_string(&info, console_x, console_y, "100%");
return;
}
#if (AIC_BOOTLOADER_CMD_PROGRESS_BAR_ROTATE == 90)
if (value >= 10)
console_y += (VIDEO_FONT_WIDTH >> 1);
#else
if (value < 10)
console_x -= VIDEO_FONT_WIDTH;
else
console_x -= VIDEO_FONT_HEIGHT + (VIDEO_FONT_WIDTH >> 1);
#endif
snprintf(str, sizeof(str), "%d%%", value);
aicfb_console_put_string(&info, info.width / 2, y + BAR_HEIGHT + 5, str);
aicfb_console_put_string(&info, console_x, console_y, str);
}
static int do_progress_bar(int argc, char *argv[])

View File

@@ -105,6 +105,7 @@ static int do_xip_boot(int argc, char *argv[])
info.bl_len = 1;
info.priv = (void *)((unsigned long)mtd->start + FLASH_XIP_BASE);
entry_point = 0;
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;

View File

@@ -23,6 +23,8 @@ extern "C" {
#define UPG_PROTO_CMD_FREE_MEM_BUF 0x09
#define UPG_PROTO_CMD_SET_UPG_CFG 0x0A
#define UPG_PROTO_CMD_SET_UPG_END 0x0B
#define UPG_PROTO_CMD_GET_LOG_SIZE 0x0C
#define UPG_PROTO_CMD_GET_LOG_DATA 0x0D
#define UPG_PROTO_CMD_SET_FWC_META 0x10
#define UPG_PROTO_CMD_GET_BLOCK_SIZE 0x11
#define UPG_PROTO_CMD_SEND_FWC_DATA 0x12
@@ -43,11 +45,9 @@ extern "C" {
/* "UPGR" */
#define UPG_CMD_RESP_MAGIC (0x52475055)
#ifdef AIC_BOOTLOADER_PSRAM_EN
#define DATA_WRITE_ONCE_SIZE (1024 * 1024)
#else
#define DATA_WRITE_ONCE_SIZE (20 * 1024)
#endif
#define DATA_WRITE_ONCE_MAX_SIZE (1024 * 1024)
#define DATA_WRITE_ONCE_MID_SIZE (64 * 1024)
#define DATA_WRITE_ONCE_MIN_SIZE (20 * 1024)
struct cmd_header {
u32 magic; /* "UPGC" */
@@ -115,11 +115,6 @@ s32 aicupg_get_upg_mode(void);
s32 aicupg_data_packet_write(u8 *data, s32 len);
s32 aicupg_data_packet_read(u8 *data, s32 len);
/*SD card upgrade function*/
//s32 aicupg_sd_write(struct image_header_upgrade *header, struct mmc *mmc,
// struct disk_partition part_info);
//s32 aicupg_mmc_create_gpt_part(u32 mmc_id, bool is_sdupg);
/*fat upgrade function*/
s32 aicupg_fat_write(char *image_name, char *protection,
struct image_header_upgrade *header);

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,7 @@ MEMORY
{
/* The last 256KB for bootloader */
SRAM_SW : ORIGIN = 0x30040000, LENGTH = 0x8000
PSRAM_BOOT_SW : ORIGIN = 0x40200100, LENGTH = 0x200000
PSRAM_BOOT_SW : ORIGIN = 0x40200100, LENGTH = AIC_PSRAM_SIZE - 0x200000
}
PROVIDE (__sram_start = 0x30040000);
@@ -57,7 +57,7 @@ PROVIDE (__sram_end = 0x30040000 + AIC_SRAM_SIZE);
PROVIDE (__min_heap_size = 0x200);
PROVIDE (__heap_start = __psram_sw_heap_start);
PROVIDE (__heap_end = 0x40400000);
PROVIDE (__heap_end = 0x40000000 + AIC_PSRAM_SIZE);
REGION_ALIAS("REGION_TEXT" , PSRAM_BOOT_SW);
REGION_ALIAS("REGION_RODATA" , PSRAM_BOOT_SW);

View File

@@ -74,12 +74,12 @@ PROVIDE (__sram_end = 0x30040000 + AIC_SRAM_TOTAL_SIZE);
PROVIDE (__min_heap_size = 0x200);
#ifdef AIC_BOOTLOADER_PSRAM_EN
PROVIDE (__heap_start = 0x40000000);
/* Limit bootloader's heap to 8MB */
PROVIDE (__heap_end = 0x40000000 + 0x800000);
PROVIDE (__heap_end = 0x40000000 + AIC_PSRAM_SIZE);
#else
PROVIDE (__heap_start = 0x300E0000);
PROVIDE (__heap_end = 0x30100000);
PROVIDE (__heap_end = 0x300FF000);
#endif
REGION_ALIAS("REGION_TEXT" , SRAM_SW);
REGION_ALIAS("REGION_RODATA" , SRAM_SW);
REGION_ALIAS("REGION_DATA" , SRAM_SW);

View File

@@ -134,14 +134,25 @@ int aic_get_os_to_startup(char *target_os)
#endif
if (strncmp(next, "A", 2) == 0) {
memcpy(target_os, APPLICATION_PART, strlen(APPLICATION_PART));
ret = fw_env_write("osAB_now", "A");
} else if (strncmp(next, "B", 2) == 0) {
memcpy(target_os, APPLICATION_PART_REDUNDAND,
strlen(APPLICATION_PART_REDUNDAND));
ret = fw_env_write("osAB_now", "B");
} else {
ret = -1;
pr_err("Invalid osAB_next\n");
goto err_write_next_os;
}
if (ret) {
pr_err("osAB_now write fail\n");
goto err_write_next_os;
}
fw_env_flush();
err_write_next_os:
fw_env_close();
return ret;
}

View File

@@ -27,6 +27,8 @@ if GetDepend('AIC_BOOTLOADER_FATFS_SUPPORT'):
src += Glob('upg_fat_direct_mmc.c')
src += Glob('upg_fat_direct_nor.c')
src += Glob('upg_fat_direct_nand.c')
if GetDepend('AICUPG_LOG_BUFFER_SUPPORT'):
src += Glob('log_buf.c')
CPPPATH = [cwd]
ASFLAGS = ''

View File

@@ -12,7 +12,9 @@
#include <console.h>
#include <aic_common.h>
#include "upg_internal.h"
#ifdef AICUPG_LOG_BUFFER_SUPPORT
#include <log_buf.h>
#endif
#define BOOT_STAGE_UBOOT 1
/*
* UPG_PROTO_CMD_GET_HWINFO at BROM stage is use to provide hardware data
@@ -482,8 +484,8 @@ static s32 CMD_RUN_SHELL_STR_write_input_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_ARG) {
/*
* Enter recv argument state
*/
* Enter recv argument state
*/
if (len < 4)
return 0;
memcpy(&shinfo->cmdlen, buf, 4);
@@ -496,9 +498,9 @@ static s32 CMD_RUN_SHELL_STR_write_input_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_DATA_IN) {
/*
* Enter recv data state, all command string should be sent in
* one packet.
*/
* Enter recv data state, all command string should be sent in
* one packet.
*/
if (((len - clen) != shinfo->cmdlen) ||
(shinfo->cmdlen >= MAX_SHELL_CMD_STR_LEN)) {
@@ -531,9 +533,9 @@ static s32 CMD_RUN_SHELL_STR_read_output_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
aicupg_gen_resp(&resp, cmd->cmd, shinfo->result, 0);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
@@ -859,6 +861,157 @@ static void CMD_SET_UPG_END_end(struct upg_cmd *cmd)
}
}
static void CMD_GET_LOG_SIZE_start(struct upg_cmd *cmd, s32 cmd_data_len)
{
cmd_state_init(cmd, CMD_STATE_START);
}
static s32 CMD_GET_LOG_SIZE_write_input_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
/* No input data for this command */
return 0;
}
static s32 CMD_GET_LOG_SIZE_read_output_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct resp_header resp;
u32 siz = 0, val = 0;
if (cmd->state == CMD_STATE_START)
cmd_state_set_next(cmd, CMD_STATE_RESP);
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
aicupg_gen_resp(&resp, cmd->cmd, 0, 4);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
cmd_state_set_next(cmd, CMD_STATE_DATA_OUT);
}
if (siz == len)
return siz;
if (cmd->state == CMD_STATE_DATA_OUT) {
#ifdef AICUPG_LOG_BUFFER_SUPPORT
val = log_buf_get_len();
#else
val = 0;
#endif
memcpy(buf, &val, 4);
siz += 4;
cmd_state_set_next(cmd, CMD_STATE_END);
}
return siz;
}
static void CMD_GET_LOG_SIZE_end(struct upg_cmd *cmd)
{
cmd_state_set_next(cmd, CMD_STATE_IDLE);
}
static void CMD_GET_LOG_DATA_start(struct upg_cmd *cmd, s32 cmd_data_len)
{
static struct cmd_rw_priv read_log;
read_log.addr = 0;
read_log.len = 0;
read_log.index = 0;
cmd->priv = &read_log;
cmd_state_init(cmd, CMD_STATE_START);
}
static s32 CMD_GET_LOG_DATA_write_input_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct cmd_rw_priv *priv;
u32 val, clen = 0;
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return 0;
if (cmd->state == CMD_STATE_START)
cmd_state_set_next(cmd, CMD_STATE_ARG);
if (cmd->state == CMD_STATE_ARG) {
/*
* Enter recv argument state
*/
if (len < 4)
return 0;
memcpy(&val, buf, 4);
#ifdef AICUPG_LOG_BUFFER_SUPPORT
if (val > log_buf_get_len())
val = log_buf_get_len();
#endif
priv->len = val;
clen += 4;
cmd_state_set_next(cmd, CMD_STATE_RESP);
}
return clen;
}
static s32 CMD_GET_LOG_DATA_read_output_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct cmd_rw_priv *priv;
struct resp_header resp;
u32 siz = 0;
#ifdef AICUPG_LOG_BUFFER_SUPPORT
char *p;
#endif
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return 0;
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
siz = priv->len;
aicupg_gen_resp(&resp, cmd->cmd, 0, siz);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
cmd_state_set_next(cmd, CMD_STATE_DATA_OUT);
}
if (siz == len)
return siz;
if (cmd->state == CMD_STATE_DATA_OUT) {
/* Enter read DATA state */
p = (char *)buf;
#ifdef AICUPG_LOG_BUFFER_SUPPORT
log_buf_read(p, len - siz);
#endif
priv->index += (len - siz);
siz += (len - siz);
if (priv->index >= priv->len)
cmd_state_set_next(cmd, CMD_STATE_END);
}
return siz;
}
static void CMD_GET_LOG_DATA_end(struct upg_cmd *cmd)
{
struct cmd_rw_priv *priv;
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return;
if (cmd->state == CMD_STATE_END) {
priv->addr = 0;
priv->len = 0;
priv->index = 0;
cmd->priv = 0;
cmd_state_set_next(cmd, CMD_STATE_IDLE);
}
}
static struct upg_cmd basic_cmd_list[] = {
{
UPG_PROTO_CMD_GET_HWINFO,
@@ -930,6 +1083,20 @@ static struct upg_cmd basic_cmd_list[] = {
CMD_FREE_MEM_BUF_read_output_data,
CMD_FREE_MEM_BUF_end,
},
{
UPG_PROTO_CMD_GET_LOG_SIZE,
CMD_GET_LOG_SIZE_start,
CMD_GET_LOG_SIZE_write_input_data,
CMD_GET_LOG_SIZE_read_output_data,
CMD_GET_LOG_SIZE_end,
},
{
UPG_PROTO_CMD_GET_LOG_DATA,
CMD_GET_LOG_DATA_start,
CMD_GET_LOG_DATA_write_input_data,
CMD_GET_LOG_DATA_read_output_data,
CMD_GET_LOG_DATA_end,
},
};
struct upg_cmd *find_basic_command(struct cmd_header *h)

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2023, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Wu Dehuang <dehuang.wu@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <aic_core.h>
#include <aic_common.h>
#include <aic_errno.h>
#include <log_buf.h>
#define AIC_LOG_MAGIC 0x4C434941
struct log_buffer {
int magic;
int istart;
int icurr;
int buf_size;
char buf[];
};
#ifdef AICUPG_LOG_BUFFER_SUPPORT
#define LOG_BUF_ADDR AICUPG_LOG_BUFFER_ADDR
#define LOG_BUF_SIZE AICUPG_LOG_BUFFER_SIZE
#else
#define LOG_BUF_ADDR 0
#define LOG_BUF_SIZE 0
#endif
int log_buf_init(void)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log;
void *buff;
int size;
buff = (void *)LOG_BUF_ADDR;
size = (int)LOG_BUF_SIZE;
if (!buff || (size < sizeof(*log)))
return -1;
log = buff;
if (log->magic == AIC_LOG_MAGIC)
return 0;
log->istart = 0;
log->icurr = 0;
log->buf_size = size - sizeof(*log);
log->magic = AIC_LOG_MAGIC;
#endif
return 0;
}
int log_buf_get_len(void)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
if (!log)
return 0;
return (log->icurr + log->buf_size - log->istart) % log->buf_size;
#endif
return 0;
}
int log_buf_write(char *in, int len)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
int dolen, freelen;
char *ps;
if (!log)
return 0;
if (log->magic != AIC_LOG_MAGIC)
return 0;
dolen = len;
freelen = log->buf_size - 1 - log_buf_get_len();
if (freelen == 0)
return 0;
if (dolen > freelen)
dolen = freelen;
len = dolen;
ps = in;
while (dolen) {
log->buf[log->icurr % log->buf_size] = *ps;
log->icurr = (log->icurr + 1) % log->buf_size;
dolen--;
ps++;
}
return len;
#endif
return 0;
}
int log_buf_read(char *out, int len)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
int dolen, loglen;
char *pd;
if (!log)
return 0;
if (log->magic != AIC_LOG_MAGIC)
return 0;
dolen = len;
loglen = log_buf_get_len();
if (dolen > loglen)
dolen = loglen;
len = dolen;
pd = out;
while (dolen) {
*pd = log->buf[log->istart % log->buf_size];
log->istart = (log->istart + 1) % log->buf_size;
dolen--;
pd++;
}
return len;
#endif
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2023, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Wu Dehuang <dehuang.wu@artinchip.com>
*/
#ifndef _LOG_BUF_H_
#define _LOG_BUF_H_
int log_buf_init(void);
int log_buf_get_len(void);
int log_buf_write(char *in, int len);
int log_buf_read(char *out, int len);
#endif

View File

@@ -50,6 +50,23 @@ s32 mmc_fwc_prepare(struct fwc_info *fwc, u32 mmc_id)
return ret;
}
struct aic_partition *mmc_fwc_get_part_by_name(struct fwc_info *fwc, char *name)
{
struct aicupg_mmc_priv *priv;
struct aic_partition *parts = NULL;
priv = (struct aicupg_mmc_priv *)fwc->priv;
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, name))
return parts;
parts = parts->next;
}
return NULL;
}
static unsigned long mmc_write(struct blk_desc *block_dev, u64 start,
u64 blkcnt, void *buffer)
{
@@ -115,6 +132,71 @@ out:
free(priv);
}
s32 mmc_fwc_sparse_fill(struct aicupg_mmc_priv *priv, struct aic_partition *parts, u64 chunk_blkcnt, uint32_t fill_val)
{
u32 blks, remain_blks, redund_blks, erase_group;
u32 *fill_buf, fill_buf_num_blks, fill_blks = 0;
int i, j;
fill_buf = (u32 *)aicos_malloc_align(0, ROUNDUP(SPARSE_FILLBUF_SIZE, CACHE_LINE_SIZE), CACHE_LINE_SIZE);
if (!fill_buf) {
pr_err("Malloc failed for: CHUNK_TYPE_FILL\n");
return 0;
}
for (i = 0; i < (SPARSE_FILLBUF_SIZE / sizeof(fill_val)); i++)
fill_buf[i] = fill_val;
// When using 0 fill, it is faster to use erase than write
if (chunk_blkcnt >= 0x400 && fill_val == 0x0) { // 512K
// 1. Fill part start blocks to align by group. 1 group = 1024 blocks
remain_blks = ROUNDUP((parts->start / MMC_BLOCK_SIZE) + priv->blkstart, 0x400) - ((parts->start / MMC_BLOCK_SIZE) + priv->blkstart);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blks, (u8 *)fill_buf);
if (blks < remain_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blks);
goto out;
}
fill_blks += blks;
// 2. Erase by group for faster speed,
erase_group = (chunk_blkcnt - remain_blks) / 0x400;
blks = mmc_berase(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, erase_group * 0x400);
if (blks != (erase_group * 0x400)) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Erase failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, erase_group * 0x400);
goto out;
}
fill_blks += blks;
// 3. Fill of remaining blocks
redund_blks = chunk_blkcnt - remain_blks - (erase_group * 0x400);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, redund_blks, (u8 *)fill_buf);
if (blks < redund_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, redund_blks);
goto out;
}
fill_blks += blks;
} else {
fill_buf_num_blks = SPARSE_FILLBUF_SIZE / MMC_BLOCK_SIZE;
for (i = 0; i < chunk_blkcnt;) {
j = chunk_blkcnt - i;
if (j > fill_buf_num_blks)
j = fill_buf_num_blks;
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, j, (u8 *)fill_buf);
if (blks < j) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, j);
goto out;
}
fill_blks += blks;
i += j;
}
}
out:
aicos_free_align(0, fill_buf);
return fill_blks;
}
s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
{
struct aicupg_mmc_priv *priv;
@@ -126,9 +208,7 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
u32 chunk;
u64 chunk_data_sz, chunk_blkcnt, remain_blkcnt;
u32 total_blocks = 0, blks;
u32 remain_blks, redund_blks, erase_group;
u32 *fill_buf, fill_val, fill_buf_num_blks;
int i, j, break_flag = 0;
u32 fill_val;
wbuf = malloc(ROUNDUP(len + MMC_BLOCK_SIZE, fwc->block_size));
if (!wbuf) {
@@ -153,16 +233,11 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
total_len = (priv->remain_len + len);
remain = total_len;
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, fwc->meta.partition))
break;
parts = parts->next;
}
if (!parts)
parts = mmc_fwc_get_part_by_name(fwc, fwc->meta.partition);
if (!parts) {
pr_err("not find %s part info.\n", fwc->meta.partition);
goto out;
}
sheader = &(priv->sparse_header);
if (is_sparse_image(wbuf)) {
@@ -171,11 +246,6 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
wbuf += sheader->file_hdr_sz;
clen += sheader->file_hdr_sz;
remain -= sheader->file_hdr_sz;
if (sheader->file_hdr_sz > sizeof(sparse_header_t)) {
wbuf += (sheader->file_hdr_sz - sizeof(sparse_header_t));
clen += (sheader->file_hdr_sz - sizeof(sparse_header_t));
remain -= (sheader->file_hdr_sz - sizeof(sparse_header_t));
}
pr_info("=== Sparse Image Header ===\n");
pr_info("magic: 0x%x\n", sheader->magic);
pr_info("major_version: 0x%x\n", sheader->major_version);
@@ -194,17 +264,11 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
/* Read and skip over chunk header */
cheader = (chunk_header_t *)wbuf;
if (cheader->chunk_type != CHUNK_TYPE_RAW) {
pr_debug("=== Chunk Header ===\n");
pr_debug("chunk_type: 0x%x\n", cheader->chunk_type);
pr_debug("chunk_data_sz: 0x%x\n", cheader->chunk_sz);
pr_debug("total_size: 0x%x\n", cheader->total_sz);
}
if (cheader->chunk_type != CHUNK_TYPE_RAW &&
cheader->chunk_type != CHUNK_TYPE_FILL &&
cheader->chunk_type != CHUNK_TYPE_DONT_CARE &&
cheader->chunk_type != CHUNK_TYPE_CRC32) {
cheader->chunk_type != CHUNK_TYPE_CRC32 &&
priv->cur_chunk_remain_data_sz) {
cheader = &(priv->chunk_header);
chunk_data_sz = priv->cur_chunk_remain_data_sz;
} else {
@@ -212,69 +276,50 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
clen += sheader->chunk_hdr_sz;
remain -= sheader->chunk_hdr_sz;
memcpy(&(priv->chunk_header), cheader, sizeof(chunk_header_t));
if (sheader->chunk_hdr_sz > sizeof(chunk_header_t)) {
/*
* Skip the remaining bytes in a header that is longer
* than we expected.
*/
wbuf += (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
clen += (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
remain -= (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
}
chunk_data_sz = ((u64)sheader->blk_sz) * cheader->chunk_sz;
priv->cur_chunk_remain_data_sz = chunk_data_sz;
priv->cur_chunk_burned_data_sz = 0;
pr_debug("=== Chunk Header ===\n");
pr_debug("chunk_type: 0x%x\n", cheader->chunk_type);
pr_debug("chunk_size: 0x%x\n", cheader->chunk_sz);
pr_debug("total_size: 0x%x\n", cheader->total_sz);
pr_debug("=== Chunk DEBUG ===\n");
pr_debug("chunk_id: %u\t", chunk);
pr_debug("chunk_offset: %u\t", fwc->trans_size + clen);
pr_debug("chunk_number: %u\n", cheader->total_sz - sheader->chunk_hdr_sz);
}
chunk_blkcnt = DIV_ROUND_UP(chunk_data_sz, MMC_BLOCK_SIZE);
if (priv->blkstart + chunk_blkcnt > (parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
goto out;
}
remain_blkcnt = remain / MMC_BLOCK_SIZE;
switch (cheader->chunk_type) {
case CHUNK_TYPE_RAW:
if (cheader->total_sz !=
(sheader->chunk_hdr_sz + chunk_data_sz +
priv->cur_chunk_burned_data_sz)) {
if (cheader->total_sz != (sheader->chunk_hdr_sz + chunk_data_sz + priv->cur_chunk_burned_data_sz)) {
pr_err("Bogus chunk size for chunk type Raw\n");
goto out;
}
if (priv->blkstart + chunk_blkcnt >
(parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
goto out;
}
if (remain_blkcnt > chunk_blkcnt &&
(remain - chunk_data_sz) >= 16) {
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
chunk_blkcnt, wbuf);
if (blks <
chunk_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
blks);
if (remain_blkcnt > chunk_blkcnt && (remain - chunk_data_sz) >= 16) {
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, chunk_blkcnt, wbuf);
if (blks < chunk_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, blks);
goto out;
}
remain = remain - chunk_data_sz;
priv->cur_chunk_remain_data_sz = 0;
priv->cur_chunk_burned_data_sz += chunk_data_sz;
} else {
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
remain_blkcnt, wbuf);
if (blks <
remain_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
blks);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blkcnt, wbuf);
if (blks < remain_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, blks);
goto out;
}
priv->cur_chunk_remain_data_sz -=
remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_burned_data_sz +=
remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_remain_data_sz -= remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_burned_data_sz += remain_blkcnt * MMC_BLOCK_SIZE;
remain = remain % MMC_BLOCK_SIZE;
}
@@ -282,122 +327,31 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
total_blocks += blks;
wbuf += blks * MMC_BLOCK_SIZE;
clen += blks * MMC_BLOCK_SIZE;
if ((priv->cur_chunk_remain_data_sz > 0 &&
(remain > 0 && remain < MMC_BLOCK_SIZE)) ||
remain < sizeof(chunk_header_t))
break_flag = 1;
break;
case CHUNK_TYPE_FILL:
if (cheader->total_sz !=
(sheader->chunk_hdr_sz + sizeof(uint32_t))) {
if (cheader->total_sz != (sheader->chunk_hdr_sz + sizeof(uint32_t))) {
pr_err("Bogus chunk size for chunk type FILL\n");
goto out;
}
fill_buf = (u32 *)aicos_malloc_align(
0, ROUNDUP(SPARSE_FILLBUF_SIZE, CACHE_LINE_SIZE),
CACHE_LINE_SIZE);
if (!fill_buf) {
pr_err("Malloc failed for: CHUNK_TYPE_FILL\n");
goto out;
}
fill_val = *(uint32_t *)wbuf;
wbuf = (u8 *)wbuf + sizeof(u32);
clen += sizeof(uint32_t);
remain -= sizeof(uint32_t);
if (remain < sizeof(chunk_header_t))
break_flag = 1;
if (priv->blkstart + chunk_blkcnt >
(parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
pr_debug("FILL with \t 0x%08x\n", fill_val);
blks = mmc_fwc_sparse_fill(priv, parts, chunk_blkcnt, fill_val);
if (blks != chunk_blkcnt) {
pr_err("CHUNK_TYPE_FILL FILL failed.\n");
goto out;
}
for (i = 0; i < (SPARSE_FILLBUF_SIZE / sizeof(fill_val)); i++)
fill_buf[i] = fill_val;
remain_blks =
ROUNDUP((parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
0x400) -
((parts->start / MMC_BLOCK_SIZE) + priv->blkstart);
if (chunk_blkcnt >= (remain_blks + 0x400) &&
fill_val == 0x0) { // 512K
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
remain_blks, (u8 *)fill_buf);
if (blks <
remain_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
remain_blks);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
erase_group = (chunk_blkcnt - remain_blks) / 0x400;
blks = mmc_berase(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
erase_group * 0x400);
if (blks !=
(erase_group *
0x400)) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Erase failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
erase_group * 0x400);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
redund_blks =
chunk_blkcnt - remain_blks - (erase_group * 0x400);
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
redund_blks, (u8 *)fill_buf);
if (blks <
redund_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
redund_blks);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
} else {
fill_buf_num_blks = SPARSE_FILLBUF_SIZE / MMC_BLOCK_SIZE;
for (i = 0; i < chunk_blkcnt;) {
j = chunk_blkcnt - i;
if (j > fill_buf_num_blks)
j = fill_buf_num_blks;
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
j, (u8 *)fill_buf);
if (blks <
j) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
j);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
i += j;
}
}
priv->blkstart += blks;
total_blocks += DIV_ROUND_UP(chunk_data_sz, sheader->blk_sz);
free(fill_buf);
break;
case CHUNK_TYPE_DONT_CARE:
@@ -421,13 +375,13 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
cheader = &(priv->chunk_header);
}
if (break_flag)
if ((priv->cur_chunk_remain_data_sz > 0 && (remain > 0 && remain < MMC_BLOCK_SIZE)) || remain < sizeof(chunk_header_t))
break;
}
priv->remain_len = remain;
priv->cur_chunk = chunk;
if (priv->remain_len) {
priv->cur_chunk = chunk;
memcpy(priv->remain_data, wbuf, priv->remain_len);
}
@@ -436,8 +390,7 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
pr_debug("%s, data len %d, trans len %d\n", __func__, len, fwc->trans_size);
out:
if (p)
free(p);
free(p);
return len;
}
@@ -455,14 +408,7 @@ s32 mmc_fwc_raw_write(struct fwc_info *fwc, u8 *buf, s32 len)
goto out;
}
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, fwc->meta.partition))
break;
parts = parts->next;
}
parts = mmc_fwc_get_part_by_name(fwc, fwc->meta.partition);
if (!parts)
pr_err("not find %s part info.\n", fwc->meta.partition);

View File

@@ -204,7 +204,7 @@ s32 nand_fwc_uffs_write(struct fwc_info *fwc, u8 *buf, s32 len)
int total_len = 0, remain_offset = 0;
u8 *wbuf = NULL, *pbuf = NULL;
wbuf = malloc(ROUNDUP(len, fwc->block_size));
wbuf = aicos_malloc_align(0, ROUNDUP(len, fwc->block_size), CACHE_LINE_SIZE);
if (!wbuf) {
pr_err("malloc failed.\n");
return 0;
@@ -291,13 +291,13 @@ s32 nand_fwc_uffs_write(struct fwc_info *fwc, u8 *buf, s32 len)
pr_debug("%s, data len %d, trans len %d\n", __func__, len, fwc->trans_size);
free(wbuf);
aicos_free_align(0, wbuf);
return len;
out:
if (wbuf)
free(wbuf);
aicos_free_align(0, wbuf);
return ret;
}

View File

@@ -256,9 +256,7 @@ static s32 spl_build_page_table(struct aicupg_nand_spl *spl,
pr_debug("%s, going to generate page table.\n", __func__);
slice_size = spl->mtd->writesize;
pt->head.page_size = PAGE_SIZE_2KB;
if (spl->mtd->writesize == 4096)
pt->head.page_size = PAGE_SIZE_4KB;
pt->head.page_size = spl->mtd->writesize;
page_per_blk = spl->mtd->erasesize / spl->mtd->writesize;
page_data = malloc(PAGE_MAX_SIZE);
@@ -455,7 +453,7 @@ out:
static s32 verify_page_table(struct aicupg_nand_spl *spl, u32 blkidx,
struct nand_page_table *pt, u32 len)
{
u8 page_data[PAGE_TABLE_USE_SIZE] = { 0 };
u8 page_data[PAGE_MAX_SIZE] = { 0 };
ulong offset;
u32 sumval;
s32 ret;
@@ -639,3 +637,15 @@ s32 nand_fwc_spl_write(u32 totalsiz, u8 *buf, s32 len)
return len;
}
int nand_spl_get_candidate_blocks(u32 *blks, u32 size)
{
if (!blks || size < SPL_CANDIDATE_BLOCK_NUM) {
pr_err("Invalid parameter.\n");
return -1;
}
memcpy(blks, spl_candidate_block_table,
sizeof(u32) * SPL_CANDIDATE_BLOCK_NUM);
return 0;
}

View File

@@ -27,10 +27,6 @@ extern "C" {
#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
#define PAGE_SIZE_1KB 1
#define PAGE_SIZE_2KB 2
#define PAGE_SIZE_4KB 4
#define MAX_DUPLICATED_PART 4
#ifdef AIC_NFTL_SUPPORT
@@ -51,8 +47,8 @@ struct aicupg_nand_priv {
struct nand_page_table_head {
char magic[4]; /* AICP: AIC Page table */
u32 entry_cnt;
u8 page_size; /* 0: No page size info; 1: 1KB; 2: 2KB; 4: 4KB */
u8 pad[11]; /* Padding it to fit size 20 bytes */
u16 page_size;
u8 pad[10]; /* Padding it to fit size 20 bytes */
};
/*
@@ -90,6 +86,7 @@ s32 nand_fwc_spl_reserve_blocks(struct aicupg_nand_priv *priv);
s32 nand_fwc_spl_prepare(struct aicupg_nand_priv *priv, u32 datasiz,
u32 blksiz);
s32 nand_fwc_spl_write(u32 totalsiz, u8 *buf, s32 len);
int nand_spl_get_candidate_blocks(u32 *blks, u32 size);
#ifdef __cplusplus
}

View File

@@ -26,8 +26,10 @@
#endif
#define RECV_SIZE_USE_DMA 512
#define TRANS_DATA_BUFF_SIZE (64 * 1024)
#define TRANS_DATA_BUFF_MAX_SIZE (64 * 1024)
#define TRANS_DATA_BUFF_MIN_SIZE (20 * 1024)
static u8 *trans_pkt_buf = NULL;
static u32 trans_pkt_siz = 0;
static void trans_send_csw(struct phy_data_rw *rw, u32 tag, u8 status, u32 rest)
{
@@ -56,10 +58,15 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
}
if (!trans_pkt_buf) {
trans_pkt_buf = aicos_malloc_align(0, TRANS_DATA_BUFF_SIZE, CACHE_LINE_SIZE);
trans_pkt_siz = TRANS_DATA_BUFF_MAX_SIZE;
trans_pkt_buf = aicos_malloc_align(0, trans_pkt_siz, CACHE_LINE_SIZE);
if (!trans_pkt_buf) {
pr_err("malloc trans pkt buf failed.\n");
return -1;
trans_pkt_siz = TRANS_DATA_BUFF_MIN_SIZE;
trans_pkt_buf = aicos_malloc_align(0, trans_pkt_siz, CACHE_LINE_SIZE);
if (!trans_pkt_buf) {
pr_err("malloc trans pkt buf(%u) failed.\n", trans_pkt_siz);
return -1;
}
}
}
@@ -87,8 +94,8 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
rest = data_len;
total = 0;
while (rest > 0) {
if (rest >= TRANS_DATA_BUFF_SIZE)
slice = TRANS_DATA_BUFF_SIZE;
if (rest >= trans_pkt_siz)
slice = trans_pkt_siz;
else
slice = rest;
@@ -121,8 +128,8 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
rest = data_len;
total = 0;
while (rest > 0) {
if (rest >= TRANS_DATA_BUFF_SIZE)
slice = TRANS_DATA_BUFF_SIZE;
if (rest >= trans_pkt_siz)
slice = trans_pkt_siz;
else
slice = rest;

View File

@@ -19,11 +19,45 @@
static u32 image_size = 0;
static u64 write_size = 0;
static void *upg_fat_malloc_align(struct fwc_info *fwc, u32 *size, size_t align)
{
void *ptr = NULL;
switch (*size) {
case DATA_WRITE_ONCE_MAX_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MAX_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
case DATA_WRITE_ONCE_MID_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MID_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
case DATA_WRITE_ONCE_MIN_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MIN_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
default:
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
}
return ptr;
}
static void upg_fat_free_align(void *mem)
{
aicos_free_align(0, mem);
}
#define FRAME_LIST_SIZE 4096
static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
{
struct fwc_info *fwc;
int offset, write_once_size, len, remaining_size;
u32 offset, write_once_size, len, remaining_size;
u8 *buf;
s32 ret;
ulong actread, total_len = 0;
@@ -48,18 +82,18 @@ static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
/*start write data*/
start_us = aic_get_time_us();
media_data_write_start(fwc);
/*config write size once*/
write_once_size = DATA_WRITE_ONCE_SIZE;
if (write_once_size % fwc->block_size)
write_once_size = (write_once_size / fwc->block_size) * fwc->block_size;
write_once_size = DATA_WRITE_ONCE_MAX_SIZE;
/*malloc buf memory*/
buf = aicos_malloc_align(0, write_once_size, FRAME_LIST_SIZE);
buf = upg_fat_malloc_align(fwc, &write_once_size, FRAME_LIST_SIZE);
if (!buf) {
pr_err("Error: malloc buf failed.\n");
ret = -1;
goto err;
}
memset((void *)buf, 0, write_once_size);
offset = 0;
@@ -99,13 +133,13 @@ static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
(total_len * 1000000 / start_us) / 1024 / 1024,
(total_len * 1000000 / start_us) / 1024 % 1024);
aicos_free_align(0, buf);
upg_fat_free_align(buf);
aicos_free_align(0, fwc);
return total_len;
err:
if (buf)
aicos_free_align(0, buf);
upg_fat_free_align(buf);
if (fwc)
aicos_free_align(0, fwc);
return 0;

View File

@@ -29,14 +29,13 @@ void boot_app(void *app)
return;
#ifndef LPKG_USING_FDTLIB
ep = image_get_entry_point(app);
if (!ep) {
printf("Entry point is null.\n");
while(1)
continue;
}
#else
ep = app;
#endif
if (!ep) {
printf("Entry point is null, Run APP failure.\n");
return;
}
boot_time_trace("Run APP");
boot_time_show();
dev = aic_get_boot_device();

View File

@@ -30,7 +30,11 @@
#include <usbhost.h>
#include <usbdevice.h>
#include <boot_rom.h>
#include <ram_param.h>
#include <hal_axicfg.h>
#ifdef AICUPG_LOG_BUFFER_SUPPORT
#include <log_buf.h>
#endif
extern size_t __heap_start;
extern size_t __heap_end;
@@ -54,9 +58,33 @@ struct hal_axicfg_table axi_cfg_table[HAL_AXICFG_PORT_MAX] = {
};
#endif
static void aic_board_heap_init(enum boot_device bd)
{
size_t heap_size, heap_start, real_ram_size = 0, config_ram_size = 0;
#ifdef AIC_PSRAM_SIZE
config_ram_size = AIC_PSRAM_SIZE;
#elif AIC_DRAM_TOTAL_SIZE
config_ram_size = AIC_DRAM_TOTAL_SIZE;
#endif
real_ram_size = aic_get_ram_size();
if (config_ram_size != real_ram_size)
pr_warn("config ram size(0x%x) is not equal real ram size(0x%x)\n", (u32)config_ram_size, (u32)real_ram_size);
heap_size = ((size_t)&__heap_end) - ((size_t)&__heap_start);
/* Limit bootloader's heap to 2MB */
if (bd != BD_UDISK && bd != BD_SDFAT32 && bd != BD_USB && heap_size > 0x200000)
heap_size = 0x200000;
heap_start = (size_t)&__heap_end - heap_size;
heap_init((void *)heap_start, heap_size);
}
static int board_init(enum boot_device bd)
{
size_t heap_size, heap_start;
int cons_uart;
/* target/<chip>/<board>/board.c */
@@ -73,21 +101,14 @@ static int board_init(enum boot_device bd)
}
#endif
heap_size = ((size_t)&__heap_end) - ((size_t)&__heap_start);
if (bd != BD_UDISK && bd != BD_SDFAT32 && heap_size > 0x200000)
heap_size = 0x200000;
heap_start = (size_t)&__heap_end - heap_size;
heap_init((void *)heap_start, heap_size);
boot_time_trace("Heap init done");
cons_uart = AIC_BOOTLOADER_CONSOLE_UART;
uart_init(cons_uart);
stdio_set_uart(cons_uart);
boot_time_trace("Console UART ready");
aic_board_heap_init(bd);
boot_time_trace("Heap init done");
return 0;
}
@@ -96,6 +117,17 @@ void show_banner(void)
printf("\ntinySPL [Built on %s %s]\n", __DATE__, __TIME__);
}
int bl_upgmode_detect(void)
{
enum aic_reboot_reason r;
r = aic_get_reboot_reason();
if (r == REBOOT_REASON_BL_UPGRADE)
return 1;
return 0;
}
int main(void)
{
enum boot_device bd;
@@ -113,6 +145,13 @@ int main(void)
#endif
bd = aic_get_boot_device();
if (bl_upgmode_detect())
bd = BD_USB;
#ifdef AICUPG_LOG_BUFFER_SUPPORT
log_buf_init();
#endif
board_init(bd);
#ifdef AIC_DMA_DRV
drv_dma_init();

View File

@@ -22,7 +22,7 @@ static int do_reset_boot(int argc, char *argv[])
{
#ifdef AIC_WDT_DRV
wdt_init();
printf("Going to reboot ...\n");
printf("Restarting system ...\n");
#endif
#ifdef AIC_WRI_DRV
aic_set_reboot_reason(REBOOT_REASON_CMD_REBOOT);
@@ -40,7 +40,10 @@ CONSOLE_CMD(reboot, do_reset_boot, "Reboot device.");
static int cmd_aicupg(int argc, char **argv)
{
#ifdef AIC_WRI_DRV
aic_set_reboot_reason(REBOOT_REASON_UPGRADE);
if ((argc == 2) && !strcmp(argv[1], "gotobl"))
aic_set_reboot_reason(REBOOT_REASON_BL_UPGRADE);
else
aic_set_reboot_reason(REBOOT_REASON_UPGRADE);
#endif
do_reset_boot(0, NULL);
return 0;

View File

@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <board.h>
#include <hal_syscfg.h>
#include <aic_core.h>
@@ -22,6 +23,10 @@
#include "drv_dma.h"
#endif
#ifdef AIC_USING_SID
#include "efuse.h"
#endif
#ifdef AIC_OSR_CE_DRV
#include <osrce.h>
#endif
@@ -55,11 +60,11 @@ extern void lv_port_indev_init(void);
extern void lv_user_gui_init(void);
#endif
extern void show_version(void);
void show_banner(void)
{
printf("%s\n", BANNER);
printf("Welcome to ArtInChip Luban-Lite %d.%d [Baremetal - Built on %s %s]\n",
LL_VERSION, LL_SUBVERSION, __DATE__, __TIME__);
}
static int board_init(void)
@@ -76,7 +81,11 @@ static int board_init(void)
uart_init(cons_uart);
stdio_set_uart(cons_uart);
#ifdef AIC_USING_SID
efuse_init();
#endif
show_banner();
show_version();
return 0;
}
@@ -125,8 +134,10 @@ int main(void)
#endif
#ifdef AIC_USING_SDMC1
mmc_init(1);
#ifdef AIC_SD_USING_HOTPLUG
sdcard_hotplug_init();
#endif
#endif
#if defined(LPKG_USING_DFS_ELMFAT) && defined(AIC_USING_SDMC0)
if (dfs_mount("mmc0p2", "/rodata", "elm", 0, DEVICE_TYPE_SDMC_DISK) < 0)
@@ -231,6 +242,10 @@ int main(void)
extern void msc_storage_init(char *path);
msc_storage_init(MSC_STORAGE_PATH);
#endif
#ifdef LPKG_CHERRYUSB_DEVICE_MTP_TEMPLATE
extern void mtp_init(char *path);
mtp_init(ROOT_PATH);
#endif
#ifdef LPKG_CHERRYUSB_DEVICE_MIDI_TEMPLATE
extern void midi_init(void);
midi_init();
@@ -241,6 +256,12 @@ int main(void)
#endif
#endif
#ifdef AIC_SD_USING_HOTPLUG
while (1) {
sdcard_hotplug_act();
}
#endif
#ifdef AIC_CONSOLE_BARE_DRV
/* Console shell loop */
console_init();