第一次提交

This commit is contained in:
2025-11-08 13:26:19 +08:00
commit 5854ac5b6e
10570 changed files with 4746154 additions and 0 deletions

4590
middleware/dloader/dloader.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,238 @@
/*
* dloader.h
*
* Copyright (c) 2020 SemiDrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#ifndef _DLOADER_H_
#define _DLOADER_H_
#include <debug.h>
#include <disk/disk.h>
#define MAX_DEV_INST_OF_DISK 3
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MD5_LEN
#define MD5_LEN 16
#endif
#ifndef MAX_GPT_NAME_SIZE
#define MAX_GPT_NAME_SIZE 72
#endif
#define DL_DEBUG_ON 1
#if DL_DEBUG_ON
#define ERROR(format, args...) \
ssdk_printf(SSDK_CRIT, "[ERROR]DLOADER:%s %d " format "", __func__, \
__LINE__, ##args);
#define DBG(format, args...) \
ssdk_printf(SSDK_CRIT, "[DEBUG]DLOADER:%s %d " format "", __func__, \
__LINE__, ##args);
#else
#define ERROR(format, args...)
#define DBG(format, args...)
#endif
#define SPARSE_HEADER_MAGIC 0xed26ff3a
#define CHUNK_TYPE_RAW 0xCAC1
#define CHUNK_TYPE_FILL 0xCAC2
#define CHUNK_TYPE_DONT_CARE 0xCAC3
#define CHUNK_TYPE_CRC 0xCAC4
typedef enum dl_err_code {
ERR_NONE = 0,
ERR_UNKNOWN = 0x1,
ERR_FLASH1_INIT_FAIL,
ERR_EMMC1_INIT_FAIL,
ERR_SD1_INIT_FAIL,
ERR_PRI_PTB_NOT_MATCH,
ERR_SUB_PTB_NOT_MATCH,
ERR_PT_NOT_FOUND,
ERR_IMAGE_TOO_LARGE,
ERR_IMAGE_FORMAT_ERR,
ERR_PRI_PTB_NOT_FLASH,
ERR_SUB_PTB_NOT_FLASH,
ERR_PT_READ_FAIL,
ERR_PT_FLASH_FAIL,
ERR_PT_ERASE_FAIL,
ERR_PT_OVERLAP,
ERR_PT_FULL_NAME_FORMAT,
ERR_INVALID_BLOCK_SIZE,
ERR_SPARSE_IMAGE_SIZE_TOO_LOW,
ERR_SPARSE_IMAGE_HEADER,
ERR_SPARSE_IMAGE_BUFFERED,
ERR_SPARSE_IMAGE_CHUNK_HEADER,
ERR_SPARSE_IMAGE_CHUNK_TOO_LARGE,
ERR_SPARSE_IMAGE_CHUNK_NOT_MATCH,
ERR_SPARSE_IMAGE_CHUNK_UNKNOWN,
ERR_SPARSE_IMAGE_MALLOC,
ERR_SPARSE_IMAGE_DO_NOT_SUPPORT,
ERR_HASH_FAIL,
ERR_EFUSE_INDEX,
ERR_EFUSE_BURN,
ERR_EFUSE_READ,
ERR_SWITCH_PART,
ERR_CMD_ERROR,
ERR_PT_BASE_ERROR,
ERR_PT_SIZE_ERROR,
ERR_PTNAME_NOT_EXIST,
ERR_DISK_NOT_EXIST,
ERR_DISK_OPEN_ERROR,
ERR_PARTITION_READ_ERROR,
HYPER_FLASH_FUSE_READ_ERROR,
HYPER_FLASH_FUSE_WRITE_ERROR,
HYPER_FLASH_FUSE_VAL_ERROR,
VERIFY_SIZE_ERROR,
CAN_NOT_FIND_A_DOWNLOAD_FUNCTION,
CAN_NOT_FIND_A_ERASE_FUNCTION,
CAN_NOT_FIND_A_VERIFY_FUNCTION,
ERR_HASH_FAIL_FROM_PC,
ERR_DL_FUSE_SIZE_CHECK_FAIL,
ERR_DL_FUSE_LENGTH_CHECK_FAIL,
ERR_DL_FUSE_ACTION_TYPE_NOT_FIND,
ERR_DL_FUSE_CRC_CHECK_FAIL,
ERR_DL_FUSE_ENC_INIT_FAIL,
ERR_DL_FUSE_ENC_FAIL,
ERR_DL_FUSE_MALLOC_FAIL,
ERR_DL_FUSE_GEN_DATA_FAIL,
ERR_DL_FUSE_READBACK_VERIFY_FAIL,
ERR_GET_SFS_FORM_MSFS_FAIL,
ERR_MAX,
} DL_ERR_CODE_E;
typedef enum partition_type_enum {
TYPE_PT_UNKNOWN = 0,
TYPE_PRI_PTB,
TYPE_PRI_PT,
TYPE_SUB_PTB,
TYPE_SUB_PT,
TYPE_SUB_PT_WHOLE,
TYPE_ALL_PT, /* only for erase all partitions in the gpt */
TYPE_NOT_IN_GPT = 0x100,
TYPE_BOOT_PACK0,
TYPE_BOOT_PACK1,
TYPE_BOOT_PACK2,
TYPE_SAFETY_SFS_PT,
TYPE_SAFETY_RFD_PT,
TYPE_ADD_DIRECT,
} PARTITION_TYPE_E;
typedef enum dev_inst_enum {
FLASH_DEV_INST = 0,
EMMC_USER_SPACE_DEV_INST = 0,
EMMC_BOOT1_DEV_INST = 1,
EMMC_BOOT2_DEV_INST = 2,
EMMC_DEV_INST_MAX,
} DEV_INST_E;
typedef enum disk_type_enum {
MMC,
NORFLASH,
RAMDISK,
USBDISK,
ALLDISK,
STORAGE_TYPE_NM,
} DISK_TYPE_E;
struct ptb_dl_name {
struct list_node node;
char *name;
};
/* record downloaded state */
typedef struct dl_state {
const char download_name[MAX_GPT_NAME_SIZE + 1];
const char disk_name[MAX_GPT_NAME_SIZE + 1];
const char disk_boot1_name[MAX_GPT_NAME_SIZE + 1];
const char disk_boot2_name[MAX_GPT_NAME_SIZE + 1];
DISK_TYPE_E disk_type;
struct disk_dev *disk_inst[MAX_DEV_INST_OF_DISK];
uint32_t block_size;
uint32_t erase_size;
uint64_t capacity;
struct partition_device *ptdev;
uint64_t ptb_offset;
PARTITION_TYPE_E partiton_type;
char ptname[MAX_GPT_NAME_SIZE + 1];
char sub_ptbname[MAX_GPT_NAME_SIZE + 1];
const uint64_t boot_offset;
} DL_STATE_T;
typedef struct command_table {
PARTITION_TYPE_E partiton_type;
DISK_TYPE_E disk_type;
DL_ERR_CODE_E(*flash_callback)
(DL_STATE_T *ds, void *data, unsigned sz, uint8_t sparse_data);
DL_ERR_CODE_E (*erase_cmd_callback)(DL_STATE_T *ds);
DL_ERR_CODE_E (*verify_cmd_callback)(DL_STATE_T *ds);
char *download_cmd_name;
char *erase_cmd_name;
} COMMAND_TABLE_T;
typedef struct download_type_table {
char *ptname;
uint8_t is_sub_pt;
char *type_name;
PARTITION_TYPE_E partiton_type;
} DOWNLOAD_TYPE_TABLE_T;
typedef struct sparse_header {
uint32_t magic; /* 0xed26ff3a */
uint16_t
major_version; /* (0x1) - reject images with higher major versions */
uint16_t minor_version; /* (0x0) - allow images with higer minor versions */
uint16_t file_hdr_sz; /* 28 bytes for first revision of the file format */
uint16_t chunk_hdr_sz; /* 12 bytes for first revision of the file format */
uint32_t blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
uint32_t total_blks; /* total blocks in the non-sparse output image */
uint32_t total_chunks; /* total chunks in the sparse input image */
uint32_t image_checksum; /* CRC32 checksum of the original data, counting
"don't care" */
/* as 0. Standard 802.3 polynomial, use a Public Domain */
/* table implementation */
} sparse_header_t;
typedef struct chunk_header {
uint16_t
chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
uint16_t reserved1;
uint32_t chunk_sz; /* in blocks in output image */
uint32_t total_sz; /* in bytes of chunk input file including chunk header
and data */
} chunk_header_t;
extern void *dl_scratch_base;
extern uint32_t dl_scratch_sz;
extern void *dl_data_base;
extern uint32_t dl_data_sz;
extern DL_STATE_T *parse_partition_name(const char *full_ptname,
DL_ERR_CODE_E *err);
extern int dloader_init(void);
extern void read_sfs(DL_STATE_T *ds);
extern void read_rfd(DL_STATE_T *ds);
extern uint8_t md5_received[MD5_LEN];
extern DL_ERR_CODE_E dl_cmd_flash(const char *arg, void *data, unsigned sz);
extern DL_ERR_CODE_E dl_cmd_erase(const char *arg, void *data, unsigned sz);
int dl_disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size);
int dl_disk_write(struct disk_dev *dev, disk_addr_t addr, uint8_t *src,
disk_size_t size);
int dl_disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size);
char *response_error(enum dl_err_code err, const char *pname);
#endif

View File

@@ -0,0 +1,139 @@
/**
* @file partition_disk_io.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <compiler.h>
#include <debug.h>
#include <disk.h>
#include <md5.h>
#include <param.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "dloader.h"
/**
* @brief dl_disk_read
*
* @param dev disk device
* @param addr read addr
* @param dst data destination
* @param size read size
* @return int 0 success other if failed
*/
int dl_disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (!dev->block_size || !IS_ALIGNED(addr, dev->block_size) ||
!IS_ALIGNED(size, dev->block_size)) {
ERROR("addr 0x%llx or size 0x%llx not aligned to block_size = %d\r\n",
addr, size, dev->block_size);
return -1;
}
if (!IS_ALIGNED(dst, dev->info->mem_align_size)) {
ERROR("mem addresses 0x%p not aligned to 0x%x\r\n", dst,
dev->info->mem_align_size);
return -1;
}
return disk_read_block(dev, addr / (dev->block_size), dst,
size / (dev->block_size));
#else
return disk_read(dev, addr, dst, size);
#endif
}
/**
* @brief dl_disk_write
*
* @param dev disk device
* @param addr write addr
* @param src data source
* @param size write size
* @return int 0 success other if failed
*/
int dl_disk_write(struct disk_dev *dev, disk_addr_t addr, uint8_t *src,
disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (!dev->block_size || !IS_ALIGNED(addr, dev->block_size) ||
!IS_ALIGNED(size, dev->block_size)) {
ERROR("addr 0x%llx or size 0x%llx not aligned to block_size = %d\r\n",
addr, size, dev->block_size);
return -1;
}
if (!IS_ALIGNED(src, dev->info->mem_align_size)) {
ERROR("mem addresses 0x%p not aligned to 0x%x\r\n", src,
dev->info->mem_align_size);
return -1;
}
return disk_write_block(dev, addr / (dev->block_size), src,
size / (dev->block_size));
#else
return disk_write(dev, addr, src, size);
#endif
}
/**
* @brief dloader disk erase
*
* @param dev disk device
* @param addr erase addr
* @param size erase size
* @return int 0 success
*/
int dl_disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size)
{
#if CONFIG_DLOADER_BLOCK_IO_MODE
if (NULL == dev || NULL == dev->info) {
ERROR("no disk device node\r\n");
return -1;
}
if (strstr(dev->info->disk_name, "flash")) {
if (!dev->info->erase_size ||
!IS_ALIGNED(addr, dev->info->erase_size) ||
!IS_ALIGNED(size, dev->info->erase_size)) {
ERROR(
"addr 0x%llx or size 0x%llx not aligned to erase_size = %d\r\n",
addr, size, dev->info->erase_size);
return -1;
}
return disk_erase_group(dev, addr / (dev->info->erase_size),
size / (dev->info->erase_size),
DISK_ERASE_DEFAULT);
} else {
return disk_erase(dev, addr, size, DISK_ERASE_DEFAULT);
}
#else
return disk_erase(dev, addr, size, DISK_ERASE_DEFAULT);
#endif
}

View File

@@ -0,0 +1,70 @@
#include <dloader.h>
#include <dloader_usb_fastboot.h>
#include <fuse_bin.h>
static DL_ERR_CODE_E dloader_convert_return_value(FUSE_ERR_CODE_E ret)
{
DL_ERR_CODE_E err = ERR_NONE;
switch (ret) {
case ERR_NONE:
err = ERR_NONE;
break;
case ERR_UNKNOWN:
err = ERR_UNKNOWN;
break;
case ERR_FUSE_BIN_SIZE_CHECK_FAIL:
err = ERR_DL_FUSE_SIZE_CHECK_FAIL;
break;
case ERR_FUSE_BIN_LENGTH_CHECK_FAIL:
err = ERR_DL_FUSE_LENGTH_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND:
err = ERR_DL_FUSE_ACTION_TYPE_NOT_FIND;
break;
case ERR_FUSE_BIN_CRC_CHECK_FAIL:
err = ERR_DL_FUSE_CRC_CHECK_FAIL;
break;
case ERR_FUSE_BIN_ENC_INIT_FAIL:
err = ERR_DL_FUSE_ENC_INIT_FAIL;
break;
case ERR_FUSE_BIN_ENC_FAIL:
err = ERR_DL_FUSE_ENC_FAIL;
break;
case ERR_FUSE_BIN_MALLOC_FAIL:
err = ERR_DL_FUSE_MALLOC_FAIL;
break;
case ERR_FUSE_BIN_GEN_DATA_FAIL:
err = ERR_DL_FUSE_GEN_DATA_FAIL;
break;
case ERR_FUSE_BIN_READ_FAIL:
err = ERR_EFUSE_READ;
break;
case ERR_FUSE_BIN_WRITE_FAIL:
err = ERR_EFUSE_BURN;
break;
case ERR_FUSE_BIN_READBACK_VERIFY_FAIL:
err = ERR_DL_FUSE_READBACK_VERIFY_FAIL;
break;
default:
break;
}
return err;
}
void fastboot_cmd_fuse_bin(fastboot_t *fb, const char *arg, void *data,
unsigned sz)
{
FUSE_ERR_CODE_E ret;
DL_ERR_CODE_E err;
ret = fuse_bin(data, sz);
err = dloader_convert_return_value(ret);
if (err) {
ERROR("fuse bin error\r\n");
fastboot_common_fail(fb, response_error(err, arg));
} else {
DBG("fuse bin success\r\n");
}
fastboot_common_okay(fb, "");
}

View File

@@ -0,0 +1,4 @@
#include <dloader_usb_fastboot.h>
void fastboot_cmd_fuse_bin(fastboot_t *fb, const char *arg, void *data,
unsigned sz);

View File

@@ -0,0 +1,566 @@
/**
* @file dloader_test.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
#include <CLI.h>
#include <armv7-r/cache.h>
#include <board.h>
#include <ctype.h>
#include <debug.h>
#include <md5.h>
#include <param.h>
#include <part.h>
#include <partition_parser.h>
#include <sd_boot_img.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include "checksum/crc32.h"
#include "dloader.h"
#if CONFIG_E3104 == 0
#define DL_TEST_STACK_SIZE 8192
#define DL_TEST_ARGV_NUM 10
#define DL_TEST_ARGV_LEN 50
#if CONFIG_DLOADER_BLOCK_IO_MODE
#define DL_LENGTH_ALIGN 512
#else
#define DL_LENGTH_ALIGN 128
#endif
#define DL_ADDR_ALIGN 512
#define DL_MD5RAM_ALIGN 512
#define DL_MD5DISK_ALIGN 512
typedef struct dl_test_arg {
int argc;
char argv[DL_TEST_ARGV_NUM][DL_TEST_ARGV_LEN];
} dl_test_arg_t;
static dl_test_arg_t dl_test_arg = {0};
static SemaphoreHandle_t new_msg_event;
static TaskHandle_t dloader_process_thread;
extern uint32_t sfs_get_image_base(DL_STATE_T *ds, uint8_t num);
extern int32_t get_bpt_info(struct bpt *bpt, uint8_t *buffer, uint32_t len);
/**
* @brief hexdump an buffer. The addresss could be set
* @param disk_addr
* @param ptr
* @param len
*/
static void dl_hexdump(uint64_t disk_addr, const void *ptr, size_t len)
{
addr_t address = (addr_t)ptr;
size_t count;
for (count = 0; count < len; count += 16) {
union {
uint32_t buf[4];
uint8_t cbuf[16];
} u;
size_t s = ROUNDUP(MIN(len - count, 16), 4);
size_t i;
printf("0x%08x: ", (uint32_t)disk_addr);
for (i = 0; i < s / 4; i++) {
u.buf[i] = ((const uint32_t *)address)[i];
printf("%08x ", u.buf[i]);
}
for (; i < 4; i++) {
printf(" ");
}
printf("|");
for (i = 0; i < 16; i++) {
unsigned char c = u.cbuf[i];
if (i < s && isprint(c)) {
printf("%c", c);
} else {
printf(".");
}
}
printf("|\n");
address += 16;
disk_addr += 16;
}
}
/**
* @brief Get the inst num of disk
* @param partiton_type
* @return uint8_t
*/
static uint8_t get_inst_num(PARTITION_TYPE_E partiton_type)
{
uint8_t inst_num = 0;
if (TYPE_BOOT_PACK0 == partiton_type)
inst_num = 1;
else if (TYPE_BOOT_PACK1 == partiton_type)
inst_num = 2;
DBG("disk_inst= %d\n", inst_num);
return inst_num;
}
static uint8_t read_bpt(DL_STATE_T *ds, uint8_t bpt_num)
{
struct bpt *bpt = NULL;
struct iib *iib = NULL;
uint64_t addr = 0;
uint64_t length = 0;
uint8_t inst_num = 0;
uint32_t crc32_val = 0;
uint32_t i = 0;
if (ds->disk_type == NORFLASH) {
addr = sfs_get_image_base(ds, bpt_num);
inst_num = 0;
} else if (0 == bpt_num) {
addr = 0;
inst_num = 1;
} else if (1 == bpt_num) {
addr = 0;
inst_num = 2;
} else if (2 == bpt_num) {
addr = 0x5000;
inst_num = 0;
}
length = 0x1000;
DBG("read inst %d addr 0x%llx, len %lld for BPT\n", inst_num, addr, length);
memset((uint8_t *)dl_scratch_base, 0, length);
if (dl_disk_read(ds->disk_inst[inst_num], addr, (uint8_t *)dl_scratch_base,
length)) {
ERROR("read storage failed\n");
return 1;
}
crc32_val = sfs_crc32(0, (uint8_t *)dl_scratch_base, 0xFEC);
bpt = (struct bpt *)pvPortMallocAligned(sizeof(struct bpt), ds->block_size);
if (0 != get_bpt_info(bpt, (uint8_t *)dl_scratch_base, length)) {
free(bpt);
return 1;
} else {
DBG("bpt->tag = 0x%08x\n", bpt->tag);
DBG("bpt->size = 0x%x\n", bpt->size);
DBG("bpt->sec_version = 0x%08x\n", bpt->sec_version);
DBG("bpt->hash_alg = 0x%x\n", bpt->hash_alg);
DBG("bpt->crc32 = 0x%08x(crc32_val=0x%08x)\n",
bpt->crc32, crc32_val);
DBG("bpt->pac_serial_num = 0x%08x\n", bpt->pac_serial_num);
DBG("bpt->inver_pac_serial_num = 0x%08x\n", bpt->inver_pac_serial_num);
for (i = 0; i < 8; i++) {
iib = &bpt->iib[i];
if ((iib->tag != IIB_TAG)) {
DBG("iib[%d] is none\n", i);
break;
}
DBG("--------\n");
DBG("iib[%d]->tag = 0x%x\n", i, iib->tag);
DBG("iib[%d]->size = 0x%x\n", i, iib->size);
DBG("iib[%d]->image_type = 0x%x\n", i, iib->image_type);
DBG("iib[%d]->target_core = 0x%x\n", i, iib->target_core);
DBG("iib[%d]->decryp_ctl = 0x%x\n", i, iib->decryp_ctl);
DBG("iib[%d]->dev_logic_page = 0x%08x\n", i, iib->dev_logic_page);
DBG("iib[%d]->image_size = 0x%08x\n", i, iib->image_size);
DBG("iib[%d]->load_base = 0x%08x\n", i, iib->load_base);
DBG("iib[%d]->entry_point = 0x%08x\n", i, iib->entry_point);
}
free(bpt);
return 0;
}
}
/**
* @brief dloader test thread
* @param arg
*/
static void dloader_test_thread(void *arg)
{
uint64_t length_total = 0;
uint32_t total_sec = 0;
uint32_t left_sec = 0;
uint32_t i = 0;
uint8_t inst_num = 0;
char *addrsuffix;
uint32_t crc32_val = 0;
uint8_t md5_calc[MD5_LEN] = {0};
struct MD5Context context;
DL_STATE_T *ds = NULL;
uint64_t addr = 0;
uint64_t length = 0;
DL_ERR_CODE_E err;
while (true) {
if (pdTRUE != xSemaphoreTake(new_msg_event, portMAX_DELAY)) {
break;
}
DBG("dloader thread active\n");
ds = NULL;
inst_num = 0;
crc32_val = 0;
memset(md5_calc, 0, MD5_LEN);
/* disk read test */
if (!strcmp(dl_test_arg.argv[0], "read")) {
if (dl_test_arg.argc < 2) {
ERROR("dl read need at least 2 arg\n");
continue;
}
ds = parse_partition_name((const char *)dl_test_arg.argv[1], &err);
if (!ds) {
ERROR("partition name error\n");
continue;
}
if (ds->disk_type == MMC)
inst_num = get_inst_num(ds->partiton_type);
/* read sfs */
if (!strcmp(ds->ptname, "sfs") && (ds->disk_type == NORFLASH)) {
DBG("read sfs\n");
read_sfs(ds);
continue;
}
if (!strcmp(ds->ptname, "rfd") && (ds->disk_type == NORFLASH)) {
DBG("read rfd\n");
read_rfd(ds);
continue;
}
/* read partition table */
if (!strcmp(ds->ptname, "partition")) {
DBG("read partition\n");
ptdev_read_table(ds->ptdev);
ptdev_dump(ds->ptdev);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt0")) {
read_bpt(ds, 0);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt1")) {
read_bpt(ds, 1);
continue;
}
/* read a partition address in storage device */
else if (!strcmp(ds->ptname, "bpt2")) {
read_bpt(ds, 2);
continue;
}
/* read a partition address in storage device */
else if (dl_test_arg.argc <= 3 && 0 == inst_num) {
if (!ds->ptdev) {
ERROR("partition is null\n");
continue;
}
addr = ptdev_get_offset(ds->ptdev, ds->ptname);
length = ptdev_get_size(ds->ptdev, ds->ptname);
DBG("read partition cmd addr 0x%llx, len %lld\n", addr, length);
if (dl_test_arg.argc == 3) {
DBG("argv[2] = %s(0x%08x)\n", dl_test_arg.argv[2],
atoi(dl_test_arg.argv[2]));
length = atoi(dl_test_arg.argv[2]);
DBG("length is changed to %lld\n", length);
}
if (!length || addr % DL_ADDR_ALIGN ||
length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_LENGTH_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_LENGTH_ALIGN);
if (dl_disk_read(ds->disk_inst[0], addr,
(uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN)) {
ERROR("read storage failed\n");
continue;
}
dl_hexdump(addr, (void *)dl_scratch_base, DL_LENGTH_ALIGN);
addr += DL_LENGTH_ALIGN;
}
continue;
}
/* read any address in storage device */
else if (dl_test_arg.argc == 4) {
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[3]);
DBG("read addr cmd addr 0x%llx, len %lld\n", addr, length);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN ||
!length) {
ERROR("do not align\n");
continue;
}
if (dl_disk_read(ds->disk_inst[inst_num], addr,
(uint8_t *)dl_scratch_base,
MIN(length, dl_scratch_sz))) {
ERROR("read storage failed\n");
continue;
}
dl_hexdump((uint64_t)atoi(dl_test_arg.argv[2]),
(void *)dl_scratch_base, atoi(dl_test_arg.argv[3]));
crc32_val = crc32(0, (uint8_t *)dl_scratch_base,
MIN(length, dl_scratch_sz));
DBG("crc32_val = 0x%08x\n", crc32_val);
}
}
/* md5 calc for disk */
else if (!strcmp(dl_test_arg.argv[0], "md5disk")) {
if (dl_test_arg.argc != 4) {
ERROR("md5disk need 4 arg\n");
continue;
}
ds = parse_partition_name((const char *)dl_test_arg.argv[1], &err);
if (!ds) {
ERROR("partition name error\n");
continue;
}
if (ds->disk_type == MMC)
inst_num = get_inst_num(ds->partiton_type);
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[3]);
printf("disk md5 cmd addr 0x%llx, len %lld\n", addr, length);
MD5Init(&context);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_LENGTH_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_LENGTH_ALIGN);
if (dl_disk_read(ds->disk_inst[inst_num], addr,
(uint8_t *)dl_scratch_base, DL_LENGTH_ALIGN)) {
ERROR("read storage failed\n");
continue;
}
crc32_val = crc32(crc32_val, (uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN);
MD5Update(&context, (uint8_t *)dl_scratch_base,
DL_LENGTH_ALIGN);
addr += DL_LENGTH_ALIGN;
}
DBG("crc32_val = 0x%08x\n", crc32_val);
MD5Final(md5_calc, &context);
dl_hexdump(0, (void *)md5_calc, MD5_LEN);
continue;
}
/* md5 calc for ram */
else if (!strcmp(dl_test_arg.argv[0], "md5ram")) {
if (dl_test_arg.argc != 3) {
ERROR("md5ram need 3 arg\n");
continue;
}
addr = (addr_t)strtoull(dl_test_arg.argv[1], &addrsuffix, 16);
length = atoi(dl_test_arg.argv[2]);
printf("ram md5 cmd addr 0x%llx, len %lld\n", addr, length);
MD5Init(&context);
if (addr % DL_ADDR_ALIGN || length % DL_LENGTH_ALIGN) {
ERROR("do not align\n");
continue;
}
total_sec = length / DL_MD5RAM_ALIGN;
for (i = 0; i < total_sec; i++) {
memset((uint8_t *)dl_scratch_base, 0, DL_MD5RAM_ALIGN);
memcpy((uint8_t *)dl_scratch_base, (void *)(uint32_t)addr,
DL_MD5RAM_ALIGN);
crc32_val = crc32(crc32_val, (uint8_t *)dl_scratch_base,
DL_MD5RAM_ALIGN);
MD5Update(&context, (uint8_t *)dl_scratch_base,
DL_MD5RAM_ALIGN);
addr += DL_MD5RAM_ALIGN;
}
DBG("crc32_val = 0x%08x\n", crc32_val);
MD5Final(md5_calc, &context);
dl_hexdump(0, (void *)md5_calc, MD5_LEN);
continue;
}
/* flash command test */
else if (!strcmp(dl_test_arg.argv[0], "flash")) {
if (dl_test_arg.argc != 4) {
ERROR("dl flash need at least 4 arg\n");
continue;
}
addr = (addr_t)strtoull(dl_test_arg.argv[2], &addrsuffix, 16);
length_total = (uint32_t)atoi(dl_test_arg.argv[3]);
DBG("flash cmd = %s, addr 0x%llx, len %lld\n",
(const char *)dl_test_arg.argv[1], addr, length_total);
total_sec = ((uint32_t)length_total) / dl_data_sz;
left_sec = ((uint32_t)length_total) % dl_data_sz;
DBG("total_sec = %d, left_sec = %d \n", total_sec, left_sec);
for (i = 0; i <= total_sec; i++) {
if (i == total_sec) {
length = left_sec;
} else {
length = dl_data_sz;
}
if (0 == (uint32_t)length)
break;
DBG("flash data from addr = %d, length = %d \n", (uint32_t)addr,
(uint32_t)length);
md5((const uint8_t *)(uint32_t)addr, length, md5_received);
if (dl_cmd_flash((const char *)dl_test_arg.argv[1],
(void *)(uint32_t)addr, (uint32_t)length)) {
ERROR("dl_cmd_flash error\n");
continue;
}
addr += length;
}
DBG("md5_received :\n");
dl_hexdump(0, (void *)md5_received, MD5_LEN);
DBG("dl_cmd_flash finish\n");
continue;
}
/* erase command test*/
else if (!strcmp(dl_test_arg.argv[0], "erase")) {
if (dl_test_arg.argc != 2) {
ERROR("dl flash need at least 2 arg\n");
continue;
}
DBG("cmd = %s\n", (const char *)dl_test_arg.argv[1]);
dl_cmd_erase((const char *)dl_test_arg.argv[1], dl_data_base, 0);
continue;
}
}
}
/**
* @brief test app for dloader
* @param argc
* @param argv
* @return int
*/
static int dloader_test(int argc, char *argv[])
{
int i = 0;
static bool dl_test_thread_on = 0;
if (0 == dl_test_thread_on) {
if (!strcmp(argv[0], "init")) {
dl_test_thread_on = 1;
/* test thread */
new_msg_event = xSemaphoreCreateCounting(1, 0);
xTaskCreate(dloader_test_thread, "dloader_test", DL_TEST_STACK_SIZE,
NULL, (tskIDLE_PRIORITY + 2), &dloader_process_thread);
if (!dloader_process_thread) {
ERROR("failed to dloader_test process thread\n");
return CLI_FALSE;
}
DBG("download test init success\n");
return CLI_FALSE;
}
}
if (argc == 0) {
ERROR("need in put arg\n");
return CLI_FALSE;
}
if (argc > DL_TEST_ARGV_NUM) {
ERROR("too many arg\n");
return CLI_FALSE;
}
DBG("dloader argc = %d\n", argc);
dl_test_arg.argc = argc;
for (i = 0; i < dl_test_arg.argc; i++) {
memset(dl_test_arg.argv[i], 0, DL_TEST_ARGV_LEN);
strncpy(dl_test_arg.argv[i], argv[i], DL_TEST_ARGV_LEN - 1);
DBG("dl_test_arg.argc[%d] = %s\n", i, dl_test_arg.argv[i]);
}
DBG("event set!\r\n");
xSemaphoreGive(new_msg_event);
return CLI_FALSE;
}
CLI_CMD("dl", "download test", dloader_test);
#endif

View File

@@ -0,0 +1,449 @@
/**
* @file dloader_usb_fastboot.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: usb fastboot package.
*
* Revision History:
* -----------------
*/
#include <Source/usbd_core.h>
#include <board.h>
#include <part.h>
#include <reg.h>
#include <stdbool.h>
#include <usb_bsp.h>
#include "dloader_usb_fastboot.h"
#include "regs_base.h"
#include "sdrv_fuse.h"
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
#define SD_VENDOR_ID 0x3273
#ifdef CONFIG_E3L
#define SD_PRODUCT_ID 0x0003
#else
#define SD_PRODUCT_ID 0x0002
#endif
#else
#define SD_VENDOR_ID 0x18d1
#define SD_PRODUCT_ID 0x4d00
#endif
#define SD_VERSION_ID 0x0100
#define SD_FB_CFG_MAX_NBR_CMD 20u
#define SD_FB_CFG_MAX_NBR_VAR 20u
#define ANDROID_VENDOR_ID 0x18d1
#define ANDROID_PRODUCT_ID 0x4d00
#define SD_ROM_PATCH0_INDEX 112
#define SD_PID_INDEX 12
#define SD_UID_INDEX 4
#define SD_MINOR_INDEX 6
#define ERROR(format, args...) \
ssdk_printf(SSDK_CRIT, "[ERROR]DLOADER_USB_FB:%s %d " format "", __func__, \
__LINE__, ##args);
#define DBG(format, args...) \
ssdk_printf(SSDK_CRIT, "[DEBUG]DLOADER_USB_FB:%s %d " format "", __func__, \
__LINE__, ##args);
static char usbd_fb_serial[17] = "0000000000000000";
static char usbd_product_str[5] = "0000";
static USBD_DRV_EP_INFO USBD_DrvEP_InfoTbl[] = {
{USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_OUT, 0u, 64u},
{USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_IN, 0u, 64u},
{USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT |
USBD_EP_INFO_DIR_IN,
1u, 512u},
{USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT |
USBD_EP_INFO_DIR_IN,
2u, 512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 3u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 4u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 5u,
512u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 6u,
64u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 7u,
64u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 8u,
64u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 9u,
512u},
{USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 10u,
64u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 11u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 12u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 13u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 14u,
512u},
{USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 15u,
512u},
{DEF_BIT_NONE, 0u, 0u}};
USBD_DEV_CFG FB_USBD_DevCfg = {
SD_VENDOR_ID, /* Vendor ID. */
SD_PRODUCT_ID, /* Product ID. */
SD_VERSION_ID, /* Device release number. */
"Semidrive", /* Manufacturer string. */
usbd_product_str, /* Product string. */
usbd_fb_serial, /* Serial number string. */
USBD_LANG_ID_ENGLISH_US /* String language ID. */
};
static const USBD_DRV_CFG FB_USBD_DrvCfg = {
DEVICE_BASE(USB0D), /* Base addr of device controller hw registers. */
0u, /* Base addr of device controller dedicated mem. */
0u, /* Size of device controller dedicated mem. */
#if (USBD_CFG_HS_EN == DEF_ENABLED)
USBD_DEV_SPD_HIGH, /* Speed of device controller. */
#else
USBD_DEV_SPD_FULL,
#endif
USBD_DrvEP_InfoTbl /* EP Info tbl of device controller. */
};
/* Donnot care about bus events. */
static USBD_BUS_FNCTS FB_USBD_BusFncts;
static fastboot_dev_t fb_dev = {USBD_CLASS_NBR_NONE, USBD_DEV_NBR_NONE};
static USBD_FB_CMD fb_cmd_tbl[SD_FB_CFG_MAX_NBR_CMD] = {
{"getvar:", USBD_FB_CmdGetVar},
{"download:", USBD_FB_CmdDownload},
};
static CPU_INT16U fb_cmd_len = 2;
static USBD_FB_VAR fb_var_tbl[SD_FB_CFG_MAX_NBR_VAR] = {
{"version", "0.5"},
{"name", "fastboot"},
};
static CPU_INT16U fb_var_len = 2;
static void get_product_no(void)
{
uint32_t product_id = 0;
usbd_product_str[4] = 0;
uint8_t *buf = NULL;
uint32_t ret = 0;
buf = (uint8_t *)&product_id;
ret = sdrv_fuse_sense(SD_MINOR_INDEX, &product_id);
if (ret) {
ERROR("fuse_sense error, use product no = 0000\r\n");
return;
}
snprintf(usbd_product_str, sizeof(usbd_product_str), "%02X%02X", buf[1],
buf[0]);
DBG("usbd_product str = %s\r\n", usbd_product_str);
}
static void get_serialno(void)
{
uint32_t serial_fuse[2] = {0};
uint8_t *buf = NULL;
uint32_t ret = 0;
ret = sdrv_fuse_sense(SD_UID_INDEX, &serial_fuse[0]);
ret |= sdrv_fuse_sense(SD_UID_INDEX + 1, &serial_fuse[1]);
usbd_fb_serial[16] = 0;
if (ret) {
ERROR("fuse_sense error, use serialno = 0000000000000000\r\n");
return;
}
buf = (uint8_t *)serial_fuse;
snprintf(usbd_fb_serial, sizeof(usbd_fb_serial),
"%02X%02X%02X%02X%02X%02X%02X%02X", buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
DBG("patched usbd_fb_serial = %s\r\n", usbd_fb_serial);
}
static void get_vid_pid(uint16_t *vid, uint16_t *pid)
{
uint32_t pid_vid_fuse = 0;
uint32_t use_semidrive_pid_vid = 0;
uint32_t ret = 0;
ret = sdrv_fuse_sense(SD_PID_INDEX, &pid_vid_fuse);
ret |= sdrv_fuse_sense(SD_ROM_PATCH0_INDEX, &use_semidrive_pid_vid);
if (ret) {
*pid = ANDROID_PRODUCT_ID;
*vid = ANDROID_VENDOR_ID;
ERROR("fuse_sense error, use pid = 0x%04x , vid = 0x%04x \r\n", *pid,
*vid);
return;
}
*pid = pid_vid_fuse & 0xFFFFU;
*vid = (pid_vid_fuse >> 16) & 0xFFFFU;
use_semidrive_pid_vid = ((use_semidrive_pid_vid >> 14) & 0x1);
DBG("use semidrive pid vid = %d\r\n", use_semidrive_pid_vid);
DBG("origin fuse vid:0x%0x pid:0x%0x\r\n", *vid, *pid);
if (*pid == 0) {
if (use_semidrive_pid_vid)
*pid = SD_PRODUCT_ID;
else
*pid = ANDROID_PRODUCT_ID;
}
if (*vid == 0) {
if (use_semidrive_pid_vid)
*vid = SD_VENDOR_ID;
else
*vid = ANDROID_VENDOR_ID;
}
DBG("final vid:0x%0x pid:0x%0x\r\n", *vid, *pid);
}
bool App_USBD_FB_Init(fastboot_dev_t *fbd, CPU_INT08U cfg_hs, CPU_INT08U cfg_fs)
{
USBD_ERR err;
CPU_INT08U fb_nbr;
bool valid;
DBG(" Initializing MSC class ... \r\n");
USBD_FB_Init(&err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n",
err);
return 0;
}
fb_nbr = USBD_FB_Add(&err);
if (cfg_hs != USBD_CFG_NBR_NONE) {
valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_hs, &err);
if (!valid) {
ERROR(" ... could not add msc instance #%d to HS "
"configuration w/err = %d\r\n\r\n",
fb_nbr, err);
return 0;
}
}
if (cfg_fs != USBD_CFG_NBR_NONE) {
valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_fs, &err);
if (!valid) {
ERROR(" ... could not add msc instance #%d to FS "
"configuration w/err = %d\r\n\r\n",
fb_nbr, err);
return 0;
}
}
fbd->cls_nbr = fb_nbr;
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
USBD_DevSetMS_VendorCode(fbd->dev_nbr, 1u, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not set MS vendor code w/err = %d\r\n\r\n",
err);
}
#endif
return 1;
}
static bool fastboot_common_usb_init(fastboot_dev_t *fbd)
{
CPU_INT08U dev_nbr;
CPU_INT08U cfg_hs_nbr;
CPU_INT08U cfg_fs_nbr;
bool ok;
USBD_ERR err;
uint16_t vid;
uint16_t pid;
DBG("Initializing USB Device...\r\n");
get_vid_pid(&vid, &pid);
FB_USBD_DevCfg.VendorID = vid;
FB_USBD_DevCfg.ProductID = pid;
get_serialno();
get_product_no();
if ((vid != SD_VENDOR_ID) && (vid != ANDROID_VENDOR_ID))
FB_USBD_DevCfg.ManufacturerStrPtr = "MANUFACTER";
USBD_Init(&err);
if (err != USBD_ERR_NONE) {
ERROR("... init failed w/err = %d\r\n\r\n", err);
return 0;
}
DBG(" Adding controller driver ... \r\n");
/* Add USB device instance. */
dev_nbr = USBD_DevAdd((USBD_DEV_CFG *)&FB_USBD_DevCfg, &FB_USBD_BusFncts,
&USBD_DrvAPI_RenesasRZ_DMA, &FB_USBD_DrvCfg,
&USBD_DrvBSP_TAISHAN_USB0, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add controller driver w/err = %d\r\n\r\n",
err);
return 0;
}
/* Device is not self-powered. */
USBD_DevSelfPwrSet(dev_nbr, DEF_NO, &err);
cfg_hs_nbr = USBD_CFG_NBR_NONE;
cfg_fs_nbr = USBD_CFG_NBR_NONE;
#if (USBD_CFG_HS_EN == DEF_ENABLED)
DBG(" Adding HS configuration ... \r\n");
/* Add HS configuration. */
cfg_hs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u,
USBD_DEV_SPD_HIGH, "HS fastboot config", &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add HS configuration w/err = %d\r\n\r\n",
err);
/* Continue if dev is not high-speed. */
if (err != USBD_ERR_DEV_INVALID_SPD) {
return 0;
}
}
#endif
DBG(" Adding FS configuration ... \r\n");
/* Add FS configuration. */
cfg_fs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u,
USBD_DEV_SPD_FULL, "FS fastboot config", &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not add FS configuration w/err = %d\r\n\r\n",
err);
return 0;
}
#if (USBD_CFG_HS_EN == DEF_ENABLED)
if ((cfg_fs_nbr != USBD_CFG_NBR_NONE) &&
(cfg_hs_nbr != USBD_CFG_NBR_NONE)) {
/* Associate both config for other spd desc. */
USBD_CfgOtherSpeed(dev_nbr, cfg_hs_nbr, cfg_fs_nbr, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not associate other speed configuration w/err "
"= %d\r\n\r\n",
err);
return 0;
}
}
#endif
DBG(" Initializing USB classes ... \r\n");
fbd->dev_nbr = dev_nbr;
/* Initialize MSC class. */
ok = App_USBD_FB_Init(fbd, cfg_hs_nbr, cfg_fs_nbr);
if (!ok) {
ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n",
err);
return 0;
}
return 1;
}
void fastboot_register_cmd(const char *prefix, USBD_FB_CMD_HDL handle)
{
if (!prefix || !*prefix || !handle ||
(fb_cmd_len >= SD_FB_CFG_MAX_NBR_CMD)) {
ERROR("Add command fail cmd len=%d\r\n", fb_cmd_len);
return;
}
fb_cmd_tbl[fb_cmd_len].cmd = prefix;
fb_cmd_tbl[fb_cmd_len].handler = handle;
fb_cmd_len++;
}
void fastboot_register_var(const char *name, const char *value)
{
if (!name || !*name || !value || !*value ||
(fb_var_len >= SD_FB_CFG_MAX_NBR_VAR)) {
ERROR("Add variable fail var len=%d\r\n", fb_var_len);
return;
}
fb_var_tbl[fb_var_len].name = name;
fb_var_tbl[fb_var_len].value = value;
fb_var_len++;
}
fastboot_t *fastboot_common_init(void *dl_addr, uint32_t dl_sz)
{
fastboot_dev_t *fbd;
bool ok;
USBD_ERR err;
fbd = &fb_dev;
ok = fastboot_common_usb_init(fbd);
if (!ok)
return NULL;
USBD_FB_SetDL(fbd->cls_nbr, dl_addr, dl_sz, &err);
USBD_FB_SetCmdTbl(fbd->cls_nbr, fb_cmd_tbl, fb_cmd_len, &err);
USBD_FB_SetVarTbl(fbd->cls_nbr, fb_var_tbl, fb_var_len, &err);
USBD_DevStart(fbd->dev_nbr, &err);
if (err != USBD_ERR_NONE) {
ERROR(" ... could not start device stack w/err = %d\r\n\r\n", err);
return NULL;
}
DBG(" .... USB classes initialization done.\r\n");
return &fbd->cls_nbr;
}
void fastboot_common_okay(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Okay(fb, reason);
}
}
void fastboot_common_fail(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Fail(fb, reason);
}
}
void fastboot_common_info(fastboot_t *fb, const char *reason)
{
if (fb) {
USBD_FB_Info(fb, reason);
}
}
void fastboot_common_stop(fastboot_t *fb)
{
USBD_ERR err;
if (fb && (*fb == fb_dev.cls_nbr)) {
USBD_DevStop(fb_dev.dev_nbr, &err);
}
}

View File

@@ -0,0 +1,34 @@
/**
* @file dloader_usb_fastboot.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: fastboot common interface.
*
* Revision History:
* -----------------
*/
#ifndef _DLOADER_USB_FASTBOOT_H
#define _DLOADER_USB_FASTBOOT_H
#include <Class/FastBoot/usbd_fb.h>
typedef unsigned char fastboot_t;
typedef struct fastboot_dev {
fastboot_t cls_nbr;
unsigned char dev_nbr;
} fastboot_dev_t;
void fastboot_register_cmd(const char *prefix, USBD_FB_CMD_HDL handle);
void fastboot_register_var(const char *name, const char *value);
fastboot_t *fastboot_common_init(void *dl_addr, uint32_t dl_sz);
void fastboot_common_okay(fastboot_t *fb, const char *reason);
void fastboot_common_fail(fastboot_t *fb, const char *reason);
void fastboot_common_info(fastboot_t *fb, const char *reason);
void fastboot_common_stop(fastboot_t *fb);
#endif