第一次提交
This commit is contained in:
4590
middleware/dloader/dloader.c
Normal file
4590
middleware/dloader/dloader.c
Normal file
File diff suppressed because it is too large
Load Diff
238
middleware/dloader/dloader.h
Normal file
238
middleware/dloader/dloader.h
Normal 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
|
||||
139
middleware/dloader/dloader_disk_io.c
Normal file
139
middleware/dloader/dloader_disk_io.c
Normal 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
|
||||
}
|
||||
70
middleware/dloader/dloader_fuse_bin.c
Normal file
70
middleware/dloader/dloader_fuse_bin.c
Normal 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, "");
|
||||
}
|
||||
4
middleware/dloader/dloader_fuse_bin.h
Normal file
4
middleware/dloader/dloader_fuse_bin.h
Normal 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);
|
||||
566
middleware/dloader/dloader_test.c
Normal file
566
middleware/dloader/dloader_test.c
Normal 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
|
||||
449
middleware/dloader/dloader_usb_fastboot.c
Normal file
449
middleware/dloader/dloader_usb_fastboot.c
Normal 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);
|
||||
}
|
||||
}
|
||||
34
middleware/dloader/dloader_usb_fastboot.h
Normal file
34
middleware/dloader/dloader_usb_fastboot.h
Normal 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
|
||||
Reference in New Issue
Block a user