450 lines
13 KiB
C
450 lines
13 KiB
C
/**
|
|
* @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);
|
|
}
|
|
}
|