summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/amlogic/gxb_p200_v1/gxb_p200_v1.c14
-rw-r--r--board/amlogic/gxb_p201_v1/gxb_p201_v1.c12
-rw-r--r--board/amlogic/gxb_skt_v1/gxb_skt_v1.c12
-rw-r--r--common/Makefile2
-rw-r--r--common/cmd_aml_mmc.c623
-rw-r--r--common/cmd_burnup.c359
-rw-r--r--common/store_interface.c1562
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/mmc/aml_sd_emmc.c317
-rw-r--r--drivers/mmc/emmc_partitions.c32
-rw-r--r--drivers/mmc/mmc_write.c13
-rw-r--r--drivers/usb/gadget/v2_burning/Makefile41
-rw-r--r--drivers/usb/gadget/v2_burning/aml_sysrecovery/aml_sysrecovery.c196
-rw-r--r--drivers/usb/gadget/v2_burning/aml_sysrecovery/cmd_detect_sys_recovery_key.c108
-rw-r--r--drivers/usb/gadget/v2_burning/aml_v2_burning.c161
-rw-r--r--drivers/usb/gadget/v2_burning/v2_burning_i.h41
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/amlImage_if.h124
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_buffer_manager.c320
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_download.c1319
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_download.h203
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_download_key.c658
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_fat.c1268
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_img_decoder.c601
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_progress.c142
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.c634
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.h82
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/optimus_simg2img.c436
-rw-r--r--drivers/usb/gadget/v2_burning/v2_common/sparse_format.h50
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini__aml_sdc_burn.c444
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini_parser.c429
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.c155
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.h40
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn.c764
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn_i.h108
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_update.c352
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/optimus_key_burn.c299
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.c239
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.h70
-rw-r--r--drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_keysprovider.c507
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_burn.c80
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_update.c131
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.c739
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.h2079
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.c1286
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.h30
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_core.c65
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_transform.c545
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/platform.c161
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/platform.h155
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/usb_ch9.h676
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.c980
-rw-r--r--drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.h41
-rw-r--r--fs/fat/fat.c2
-rw-r--r--include/amlogic/aml_v2_burning.h31
-rw-r--r--include/amlogic/storage_if.h66
-rw-r--r--include/configs/gxb_p200_v1.h4
-rw-r--r--include/configs/gxb_p201_v1.h4
-rw-r--r--include/configs/gxb_skt_v1.h4
-rw-r--r--include/linux/mtd/nand.h15
-rw-r--r--include/mmc.h3
60 files changed, 18873 insertions, 963 deletions
diff --git a/board/amlogic/gxb_p200_v1/gxb_p200_v1.c b/board/amlogic/gxb_p200_v1/gxb_p200_v1.c
index 1d5d0804e0..75de877e93 100644
--- a/board/amlogic/gxb_p200_v1/gxb_p200_v1.c
+++ b/board/amlogic/gxb_p200_v1/gxb_p200_v1.c
@@ -31,6 +31,9 @@
#ifdef CONFIG_VPU_PRESET
#include <vpu.h>
#endif
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+#include <amlogic/aml_v2_burning.h>
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
DECLARE_GLOBAL_DATA_PTR;
@@ -320,6 +323,12 @@ struct amlogic_usb_config g_usb_config_gx_skt_h={
int board_init(void)
{
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_usb_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
+ /*Power on GPIOAO_2 for VCC_5V*/
+ clrbits_le32(P_AO_GPIO_O_EN_N, ((1<<2)|(1<<18)));
#ifdef CONFIG_USB_DWC_OTG_HCD
board_usb_init(&g_usb_config_gx_skt_a,BOARD_USB_MODE_HOST);
board_usb_init(&g_usb_config_gx_skt_b,BOARD_USB_MODE_HOST);
@@ -335,6 +344,11 @@ int board_init(void)
int board_late_init(void){
/*add board late init function here*/
run_command("setenv fdt_high 0x20000000", 1);
+
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_sdcard_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
return 0;
}
#endif
diff --git a/board/amlogic/gxb_p201_v1/gxb_p201_v1.c b/board/amlogic/gxb_p201_v1/gxb_p201_v1.c
index 12ed3a910e..dc7e6a2d0e 100644
--- a/board/amlogic/gxb_p201_v1/gxb_p201_v1.c
+++ b/board/amlogic/gxb_p201_v1/gxb_p201_v1.c
@@ -31,6 +31,9 @@
#ifdef CONFIG_VPU_PRESET
#include <vpu.h>
#endif
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+#include <amlogic/aml_v2_burning.h>
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
DECLARE_GLOBAL_DATA_PTR;
@@ -320,6 +323,10 @@ struct amlogic_usb_config g_usb_config_gx_skt_h={
int board_init(void)
{
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_usb_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
/*Power on GPIOAO_2 for VCC_5V*/
clrbits_le32(P_AO_GPIO_O_EN_N, ((1<<2)|(1<<18)));
#ifdef CONFIG_USB_DWC_OTG_HCD
@@ -341,6 +348,11 @@ int board_init(void)
int board_late_init(void){
/*add board late init function here*/
run_command("setenv fdt_high 0x20000000", 1);
+
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_sdcard_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
return 0;
}
#endif
diff --git a/board/amlogic/gxb_skt_v1/gxb_skt_v1.c b/board/amlogic/gxb_skt_v1/gxb_skt_v1.c
index 4f1b64da8e..56bc0881ba 100644
--- a/board/amlogic/gxb_skt_v1/gxb_skt_v1.c
+++ b/board/amlogic/gxb_skt_v1/gxb_skt_v1.c
@@ -32,6 +32,9 @@
#ifdef CONFIG_VPU_PRESET
#include <vpu.h>
#endif
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+#include <amlogic/aml_v2_burning.h>
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
DECLARE_GLOBAL_DATA_PTR;
@@ -321,6 +324,10 @@ struct amlogic_usb_config g_usb_config_gx_skt_h={
int board_init(void)
{
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_usb_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
#ifdef CONFIG_USB_DWC_OTG_HCD
//setbits_le32(PREG_PAD_GPIO0_EN_N, 1<<24);
//setbits_le32(PREG_PAD_GPIO0_O, 1<<24);
@@ -338,6 +345,11 @@ int board_init(void)
int board_late_init(void){
/*add board late init function here*/
run_command("setenv fdt_high 0x20000000", 1);
+
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ aml_try_factory_sdcard_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
return 0;
}
#endif
diff --git a/common/Makefile b/common/Makefile
index f52c46fa83..5b8d897eae 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -133,6 +133,8 @@ obj-$(CONFIG_CMD_MII) += cmd_mdio.o
endif
obj-$(CONFIG_CMD_MISC) += cmd_misc.o
obj-$(CONFIG_CMD_MMC) += cmd_mmc.o
+obj-$(CONFIG_CMD_MMC) += cmd_aml_mmc.o
+obj-$(CONFIG_STORE_COMPATIBLE) += store_interface.o cmd_burnup.o
obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
obj-$(CONFIG_MP) += cmd_mp.o
obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
diff --git a/common/cmd_aml_mmc.c b/common/cmd_aml_mmc.c
new file mode 100644
index 0000000000..68db30f6f5
--- /dev/null
+++ b/common/cmd_aml_mmc.c
@@ -0,0 +1,623 @@
+/*
+ * (C) Copyright 2003
+ * Kyle Harris, kharris@nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <mmc.h>
+#include <partition_table.h>
+#include <emmc_partitions.h>
+
+extern int find_dev_num_by_partition_name (char *name);
+bool emmckey_is_protected (struct mmc *mmc)
+{
+ return 0;
+}
+
+unsigned emmc_cur_partition = 0;
+
+static int get_off_size(struct mmc * mmc, char * name, uint64_t offset, uint64_t size, u64 * blk, u64 * cnt, u64 * sz_byte)
+{
+ struct partitions *part_info = NULL;
+ uint64_t off = 0;
+ int blk_shift = 0;
+
+ blk_shift = ffs(mmc->read_bl_len) - 1;
+ // printf("blk_shift:%d , off:0x%llx , size:0x%llx.\n ",blk_shift,off,size );
+ part_info = find_mmc_partition_by_name(name);
+ if (part_info == NULL) {
+ printf("get partition info failed !!\n");
+ return -1;
+ }
+ off = part_info->offset + offset;
+
+ // printf("part_info->offset:0x%llx , off:0x%llx , size:0x%llx.\n",part_info->offset ,off,size);
+
+ *blk = off >> blk_shift ;
+ *cnt = size >> blk_shift ;
+ *sz_byte = size - ((*cnt)<<blk_shift) ;
+
+ // printf("get_partition_off_size : blk:0x%llx , cnt:0x%llx.\n",*blk,*cnt);
+ return 0;
+}
+
+static int get_partition_size(unsigned char* name, uint64_t* addr)
+{
+ struct partitions *part_info = NULL;
+ part_info = find_mmc_partition_by_name((char *)name);
+ if (part_info == NULL) {
+ printf("get partition info failed !!\n");
+ return -1;
+ }
+
+ *addr = part_info->size >> 9; // unit: 512 bytes
+ return 0;
+}
+
+static inline int isstring(char *p)
+{
+ char *endptr = p;
+ while (*endptr != '\0') {
+ if (!(((*endptr >= '0') && (*endptr <= '9'))
+ || ((*endptr >= 'a') && (*endptr <= 'f'))
+ || ((*endptr >= 'A') && (*endptr <= 'F'))
+ || (*endptr == 'x') || (*endptr == 'X')))
+ return 1;
+ endptr++;
+ }
+
+ return 0;
+}
+
+
+int do_amlmmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+ /*printf("%s:%d\n",__func__,__LINE__);*/
+ /*printf("argc = %d\n",argc);*/
+ switch (argc) {
+ case 3:
+ if (strcmp(argv[1], "rescan") == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ if (dev < 0) {
+ printf("Cannot find dev.\n");
+ return 1;
+ }
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (!mmc)
+ return 1;
+
+ return mmc_init(mmc);
+ } else if (strncmp(argv[1], "part", 4) == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ block_dev_desc_t *mmc_dev;
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (!mmc) {
+ puts("no mmc devices available\n");
+ return 1;
+ }
+ mmc_init(mmc);
+ mmc_dev = mmc_get_dev(dev);
+ if (mmc_dev != NULL &&
+ mmc_dev->type != DEV_TYPE_UNKNOWN) {
+ print_part(mmc_dev);
+ return 0;
+ }
+
+ puts("get mmc type error!\n");
+ return 1;
+ } else if (strcmp(argv[1], "erase") == 0) {
+ char *name = NULL;
+ int dev;
+ u32 n=0;
+ bool is_part = false;//is argv[2] partition name
+ bool protect_cache = false;
+ bool non_loader = false;
+ int blk_shift;
+ u64 cnt=0, blk =0,start_blk =0;
+ struct partitions *part_info;
+
+ if (isstring(argv[2])) {
+ if (!strcmp(argv[2], "whole")) {
+ name = "logo";
+ dev = find_dev_num_by_partition_name (name);
+ }else if(!strcmp(argv[2], "non_cache")){
+ name = "logo";
+ dev = find_dev_num_by_partition_name (name);
+ protect_cache = true;
+ }
+ else if(!strcmp(argv[2], "non_loader")){
+ dev = 1;
+ non_loader = true;
+ }
+ else{
+ name = argv[2];
+ dev = find_dev_num_by_partition_name (name);
+ is_part = true;
+ }
+ }else if(isdigit(argv[2][0])){
+ dev = simple_strtoul(argv[2], NULL, 10);
+ }else{
+ printf("Input is invalid, nothing happen.\n");
+ return 1;
+ }
+
+ if (dev < 0) {
+ printf("Cannot find dev.\n");
+ return 1;
+ }
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (!mmc)
+ return 1;
+
+ mmc_init(mmc);
+
+ blk_shift = ffs(mmc->read_bl_len) -1;
+ if (is_part) { // erase only one partition
+ if (emmckey_is_protected(mmc)
+ && (strncmp(name, MMC_RESERVED_NAME, sizeof(MMC_RESERVED_NAME)) == 0x00)) {
+ printf("\"%s-partition\" is been protecting and should no be erased!\n", MMC_RESERVED_NAME);
+ return 1;
+ }
+
+ part_info = find_mmc_partition_by_name(name);
+ if (part_info == NULL) {
+ return 1;
+ }
+
+ blk = part_info->offset>> blk_shift;
+ if (emmc_cur_partition && !strncmp(name, "bootloader", strlen("bootloader"))) {
+
+ cnt = mmc->boot_size>> blk_shift;
+ }
+ else
+ cnt = part_info->size>> blk_shift;
+ n = mmc->block_dev.block_erase(dev, blk, cnt);
+ } else { // erase the whole card if possible
+
+ if (non_loader) {
+ part_info = find_mmc_partition_by_name(MMC_BOOT_NAME);
+ if (part_info == NULL) {
+ start_blk = 0;
+ printf("no uboot partition for eMMC boot, just erase from 0\n");
+ }
+ else{
+ start_blk = (part_info->offset + part_info->size) >> blk_shift;
+ }
+ }
+ else{
+ start_blk = 0;
+ }
+
+ if (emmckey_is_protected(mmc)) {
+ part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
+ if (part_info == NULL) {
+ return 1;
+ }
+
+ blk = part_info->offset;
+ if (blk > 0) { // it means: there should be other partitions before reserve-partition.
+ blk -= PARTITION_RESERVED;
+ }
+ blk >>= blk_shift;
+
+ n=0;
+
+ // (1) erase all the area before reserve-partition
+ if (blk > 0) {
+ n = mmc->block_dev.block_erase(dev, start_blk, blk);
+ // printf("(1) erase blk: 0 --> %llx %s\n", blk, (n == 0) ? "OK" : "ERROR");
+ }
+ if (n == 0) { // not error
+ // (2) erase all the area after reserve-partition
+ if (protect_cache) {
+ part_info = find_mmc_partition_by_name(MMC_CACHE_NAME);
+ if (part_info == NULL) {
+ return 1;
+ }
+ }
+ start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED) >> blk_shift;
+ u64 erase_cnt = (mmc->capacity >> blk_shift) - 1 - start_blk;
+ n = mmc->block_dev.block_erase(dev, start_blk, erase_cnt);
+ // printf("(2) erase blk: %#llx --> %#llx %s\n", start_blk, start_blk+erase_cnt, (n == 0) ? "OK" : "ERROR");
+ }
+
+ } else {
+ n = mmc->block_dev.block_erase(dev, start_blk, 0); // erase the whole card
+ }
+
+ //erase boot partition
+ if (mmc->boot_size && (n == 0) && (non_loader == false)) {
+
+ for (cnt=0;cnt<2;cnt++) {
+ rc = mmc_switch_part(dev, cnt+1);
+ if (rc != 0) {
+ printf("mmc switch %s failed\n", (cnt == 0)?"boot0":"boot1");
+ break;
+ }
+
+ n = mmc->block_dev.block_erase(dev, 0, mmc->boot_size>>blk_shift);
+ if (n != 0) {
+ printf("mmc erase %s failed\n", (cnt == 0)?"boot0":"boot1");
+ break;
+ }
+ }
+
+ rc = mmc_switch_part(dev, 0);
+ if (rc != 0) {
+ printf("mmc switch back to user failed\n");
+ }
+ }
+ }
+
+ // printf("dev # %d, %s, # %#llx blocks erased %s\n",
+ // dev, (is_part == 0) ? "card":(argv[2]) ,
+ // (cnt == 0) ? (int)(mmc->block_dev.lba): cnt ,
+ // (n == 0) ? "OK" : "ERROR");
+ return (n == 0) ? 0 : 1;
+ } else {
+ return cmd_usage(cmdtp);
+ }
+
+ case 0:
+ case 1:
+ case 4:
+ if (strcmp(argv[1], "switch") == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ struct mmc* mmc = find_mmc_device(dev);
+ if (!mmc) {
+ puts("no mmc devices available\n");
+ return 1;
+ }
+ mmc_init(mmc);
+ if (strcmp(argv[3], "boot0") == 0) {
+ rc = mmc_switch_part(dev, 1);
+ if (rc == 0)
+ emmc_cur_partition = 1;
+ }
+ else if(strcmp(argv[3], "boot1")==0){
+ rc = mmc_switch_part(dev, 2);
+ if (rc == 0)
+ emmc_cur_partition = 2;
+ }
+ else if(strcmp(argv[3], "user")==0){
+ rc = mmc_switch_part(dev, 0);
+ if (rc == 0)
+ emmc_cur_partition = 0;
+ }
+ return rc;
+ }
+
+ if (strcmp(argv[1], "size") == 0) {
+ char *name;
+ uint64_t* addr =NULL;
+ name = argv[2];
+ addr = (uint64_t *)simple_strtoul(argv[3], NULL, 16);
+ return get_partition_size((unsigned char *)name, addr);
+ }
+
+ return cmd_usage(cmdtp);
+
+ case 2:
+ if (!strcmp(argv[1], "list")) {
+ print_mmc_devices('\n');
+ return 0;
+ }
+
+ if (strcmp(argv[1], "env") == 0) {
+ printf("herh\n");
+ env_relocate();
+ return 0 ;
+ }
+
+#ifdef CONFIG_SECURITYKEY
+ if (strcmp(argv[1], "key") == 0) {
+ struct mmc* mmc;
+ char *name = "logo";
+ int dev = find_dev_num_by_partition_name (name);
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("device %d is invalid\n",dev);
+ return 1;
+ }
+ mmc->key_protect = 0;
+#ifdef CONFIG_STORE_COMPATIBLE
+ info_disprotect |= DISPROTECT_KEY; //disprotect
+#endif
+ return 0;
+ }
+#endif
+ return cmd_usage(cmdtp);
+
+ default: /* at least 5 args */
+ if (strcmp(argv[1], "read") == 0) {
+ int dev;
+ void *addr =NULL;
+ u32 flag =0;
+ u64 cnt =0,n =0, blk =0, sz_byte =0;
+ char *name=NULL;
+ u64 offset =0,size =0;
+
+ if (argc != 6) {
+ printf("Input is invalid, nothing happen.\n");
+ return 1;
+ }
+
+ if (isstring(argv[2])) {
+ name = argv[2];
+ dev = find_dev_num_by_partition_name (name);
+ addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ size = simple_strtoull(argv[5], NULL, 16);
+ offset = simple_strtoull(argv[4], NULL, 16);
+ /*printf("offset %llx size %llx\n",offset,size);*/
+ flag = 1;
+ if ((strcmp(argv[2], "card") == 0)) {
+ flag = 2;
+ }
+ }else{
+ dev = simple_strtoul(argv[2], NULL, 10);
+ addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ cnt = simple_strtoull(argv[5], NULL, 16);
+ blk = simple_strtoull(argv[4], NULL, 16);
+ }
+ if (dev < 0) {
+ printf("Cannot find dev.\n");
+ return 1;
+ }
+ struct mmc *mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("dev = %d;, no mmc device found",dev);
+ return 1;
+ }
+
+ if (flag == 1) { // emmc or tsd
+ /*printf("offset %#llx size %#llx\n",offset,size);*/
+ get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
+ }
+ else if(flag == 2){ // card
+ int blk_shift = ffs( mmc->read_bl_len) -1;
+ cnt = size >> blk_shift;
+ blk = offset >> blk_shift;
+ sz_byte = size - (cnt<<blk_shift);
+ }
+
+
+ /*printf("MMC read: dev # %d, block # %#llx, count # %#llx ...\n",*/
+ /*dev, blk, cnt);*/
+ mmc_init(mmc);
+
+ n = mmc->block_dev.block_read(dev, blk, cnt, addr);
+ //read sz_byte bytes
+ if ((n == cnt) && (sz_byte != 0)) {
+ /*printf("sz_byte=%#llx bytes\n",sz_byte);*/
+ void *addr_tmp = malloc(mmc->read_bl_len);
+ void *addr_byte = (void *)(addr+cnt*(mmc->read_bl_len));
+ ulong start_blk = blk+cnt;
+
+ if (addr_tmp == NULL) {
+ printf("mmc read: malloc fail\n");
+ return 1;
+ }
+
+ if (mmc->block_dev.block_read(dev, start_blk, 1, addr_tmp) != 1) { // read 1 block
+ free(addr_tmp);
+ printf("mmc read 1 block fail\n");
+ return 1;
+ }
+
+ memcpy(addr_byte, addr_tmp, sz_byte);
+ free(addr_tmp);
+ }
+
+ /* flush cache after read */
+ //flush_cache((ulong)addr, cnt * 512); /* FIXME */
+
+ if (n != cnt) {
+ printf("MMC read: dev # %d, block # %#llx, count # %#llx, byte_size # %#llx ERROR!\n",
+ dev, blk, cnt, sz_byte);
+ printf("%#llx blocks read: %s\n",
+ n, (n==cnt) ? "OK" : "ERROR");
+ }
+ return (n == cnt) ? 0 : 1;
+ } else if (strcmp(argv[1], "write") == 0) {
+ int dev;
+ void *addr =NULL;
+ u32 flag =0;
+ u64 cnt =0,n =0, blk =0,sz_byte =0;
+ char *name=NULL;
+ u64 offset =0,size =0;
+
+ if (argc != 6) {
+ printf("Input is invalid, nothing happen.\n");
+ return 1;
+ }
+
+ if (isstring(argv[2])) {
+ name = argv[2];
+ dev = find_dev_num_by_partition_name (name);
+ addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ offset = simple_strtoull(argv[4], NULL, 16);
+ size = simple_strtoull(argv[5], NULL, 16);
+ flag = 1;
+ if ((strcmp(argv[2], "card") == 0)) {
+ flag = 2;
+ }
+ }else{
+ dev = simple_strtoul(argv[2], NULL, 10);
+ addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ blk = simple_strtoull(argv[4], NULL, 16);
+ cnt = simple_strtoull(argv[5], NULL, 16);
+ }
+ if (dev < 0) {
+ printf("Cannot find dev.\n");
+ return 1;
+ }
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (flag == 1) { // tsd or emmc
+ get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
+ }
+ else if(flag == 2){ // card
+ int blk_shift = ffs( mmc->read_bl_len) -1;
+ cnt = size >> blk_shift;
+ blk = offset >> blk_shift;
+ sz_byte = size - (cnt<<blk_shift);
+ }
+
+ if (!mmc)
+ return 1;
+
+ // printf("MMC write: dev # %d, block # %#llx, count # %#llx ... ",
+ // dev, blk, cnt);
+
+ mmc_init(mmc);
+
+ n = mmc->block_dev.block_write(dev, blk, cnt, addr);
+
+ //write sz_byte bytes
+ if ((n == cnt) && (sz_byte != 0)) {
+ // printf("sz_byte=%#llx bytes\n",sz_byte);
+ void *addr_tmp = malloc(mmc->write_bl_len);
+ void *addr_byte = (void*)(addr+cnt*(mmc->write_bl_len));
+ ulong start_blk = blk+cnt;
+
+ if (addr_tmp == NULL) {
+ printf("mmc write: malloc fail\n");
+ return 1;
+ }
+
+ if (mmc->block_dev.block_read(dev, start_blk, 1, addr_tmp) != 1) { // read 1 block
+ free(addr_tmp);
+ printf("mmc read 1 block fail\n");
+ return 1;
+ }
+
+ memcpy(addr_tmp, addr_byte, sz_byte);
+ if (mmc->block_dev.block_write(dev, start_blk, 1, addr_tmp) != 1) { // write 1 block
+ free(addr_tmp);
+ printf("mmc write 1 block fail\n");
+ return 1;
+ }
+ free(addr_tmp);
+ }
+
+ if (cnt != n) {
+ printf("%#llx blocks , %#llx bytes written: ERROR\n", n, sz_byte);
+ }
+ return (n == cnt) ? 0 : 1;
+ }
+ else if (strcmp(argv[1], "erase") == 0) {
+
+ int dev=0;
+ u32 flag=0;
+ u64 cnt = 0, blk = 0, n = 0, sz_byte =0;
+ char *name=NULL;
+ u64 offset_addr =0, size=0;
+
+ if (argc != 5) {
+ printf("Input is invalid, nothing happen.\n");
+ return 1;
+ }
+
+ if (isstring(argv[2])) {
+ name = argv[2];
+ dev = find_dev_num_by_partition_name (name);
+ offset_addr = simple_strtoull(argv[3], NULL, 16);
+ size = simple_strtoull(argv[4], NULL, 16);
+ flag = 1;
+ if ((strcmp(argv[2], "card") == 0)) {
+ flag = 2;
+ }
+ }else if(isdigit(argv[2][0])){
+ dev = simple_strtoul(argv[2], NULL, 10);
+ blk = simple_strtoull(argv[3], NULL, 16);
+ cnt = simple_strtoull(argv[4], NULL, 16);
+ }
+
+ if (dev < 0) {
+ printf("Cannot find dev.\n");
+ return 1;
+ }
+
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (flag == 1) { // mmc write logo add offset size
+ struct partitions *part_info = find_mmc_partition_by_name(name);
+
+ if (offset_addr >= part_info->size) {
+ printf("Start address out #%s# partition'address region,(addr_byte < 0x%llx)\n",
+ name, part_info->size);
+ return 1;
+ }
+ if ((offset_addr+size) > part_info->size) {
+ printf("End address exceeds #%s# partition,(offset = 0x%llx,size = 0x%llx)\n",
+ name, part_info->offset,part_info->size);
+ return 1;
+ }
+ get_off_size(mmc, name, offset_addr, size, &blk, &cnt, &sz_byte);
+ }
+ else if(flag == 2){
+ int tmp_shift = ffs( mmc->read_bl_len) -1;
+ cnt = size >> tmp_shift;
+ blk = offset_addr >> tmp_shift;
+ sz_byte = size - (cnt<<tmp_shift);
+ }
+
+ if (!mmc)
+ return 1;
+
+ printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx, several blocks # %lld will be erased ...\n ",
+ dev, blk, cnt);
+
+ mmc_init(mmc);
+
+ if (cnt != 0)
+ n = mmc->block_dev.block_erase(dev, blk, cnt);
+
+ printf("dev # %d, %s, several blocks erased %s\n",
+ dev, (flag == 0) ? " ":(argv[2]),(n == cnt) ? "OK" : "ERROR");
+
+ return (n == cnt) ? 0 : 1;
+
+ } else
+ rc = cmd_usage(cmdtp);
+
+ return rc;
+ }
+}
+
+U_BOOT_CMD(
+ amlmmc, 6, 1, do_amlmmcops,
+ "AMLMMC sub system",
+ "amlmmc read <partition name> ram_addr addr_byte# cnt_byte\n"
+ "amlmmc write <partition name> ram_addr addr_byte# cnt_byte\n"
+ "amlmmc erase <partition name> addr_byte# cnt_byte\n"
+ "amlmmc erase <partition name>/<device num>\n"
+ "amlmmc rescan <device num>\n"
+ "amlmmc part <device num> - show partition infomation of mmc\n"
+ "amlmmc list - lists available devices\n"
+ "amlmmc switch <device num> <part name> - part name : boot0, boot1, user");
diff --git a/common/cmd_burnup.c b/common/cmd_burnup.c
new file mode 100644
index 0000000000..c5e39157fe
--- /dev/null
+++ b/common/cmd_burnup.c
@@ -0,0 +1,359 @@
+#include <command.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <common.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <div64.h>
+#include <linux/err.h>
+#include <partition_table.h>
+
+unsigned char *cmd_name = (unsigned char *)("store");
+
+/***
+upgrade_read_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+ ***/
+
+int store_read_ops(unsigned char *partition_name,unsigned char * buf, uint64_t off, uint64_t size)
+{
+ unsigned char *name;
+ uint64_t addr;
+ char str[128];
+ int ret =0;
+
+ if (!buf) {
+ store_msg("upgrade: no buf!!");
+ return -1;
+ }
+
+ name = partition_name;
+ addr = (unsigned long)buf;
+
+ sprintf(str, "%s read %s 0x%llx 0x%llx 0x%llx",cmd_name, name, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s failed ",cmd_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/***
+upgrade_write_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+ ***/
+
+int store_write_ops(unsigned char *partition_name,unsigned char * buf, uint64_t off, uint64_t size)
+{
+ unsigned char *name;
+ uint64_t addr;
+ char str[128];
+ int ret =0;
+
+ if (!buf) {
+ store_msg("upgrade: no buf!!");
+ return -1;
+ }
+
+ name = partition_name;
+ addr = (unsigned long)buf;
+
+ sprintf(str, "%s write %s 0x%llx 0x%llx 0x%llx",cmd_name, name, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s failed ",cmd_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/***
+upgrade_write_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+ ***/
+
+int store_get_partititon_size(unsigned char *partition_name, uint64_t *size)
+{
+ unsigned char *name;
+ char str[128];
+ uint64_t addr;
+ int ret=0;
+ unsigned char * buf = malloc(4*sizeof(uint64_t));
+
+ if (!buf) {
+ store_msg("store_get_partititon_size : malloc failed");
+ return -1;
+ }
+ memset(buf,0x0,4*sizeof(uint64_t));
+ store_dbg("4*sizeof(uint64_t) =%ld",4*sizeof(uint64_t));
+ addr = (unsigned long)size;
+ name = partition_name;
+ sprintf(str, "%s size %s 0x%llx ",cmd_name, name, addr);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s size failed ",cmd_name);
+ return -1;
+ }
+
+
+
+ if (buf) {
+ kfree(buf);
+ }
+ return 0;
+}
+
+
+/***
+upgrade_erase_ops:
+
+partition_name: boot / data
+
+flag = 0; indicate erase partition ;
+flag = 1; indicate scurb whole nand;
+
+ ***/
+int store_erase_ops(unsigned char *par_name, uint64_t off, uint64_t size, unsigned char flag)
+{
+ unsigned char *name;
+ char str[128];
+ int ret=0;
+
+ name = par_name;
+ if (flag == 0) {
+ sprintf(str, "%s erase %s 0x%llx 0x%llx",cmd_name, name, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s erase failed",cmd_name);
+ return -1;
+ }
+
+ }else if(flag == 1){
+
+ sprintf(str, "%s rom_protect off ",cmd_name);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s scrub failed ",cmd_name);
+ return -1;
+ }
+
+ sprintf(str, "%s scrub 0x%llx ",cmd_name, (long long unsigned int)0);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s scrub failed",cmd_name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/***
+bootloader:
+ ***/
+int store_boot_read(unsigned char * buf, uint64_t off, uint64_t size)
+{
+ //unsigned char *name;
+ uint64_t addr;
+ char str[128];
+ int ret =0;
+
+ if (!buf) {
+ store_msg("upgrade: no buf!!");
+ return -1;
+ }
+
+ addr = (unsigned long)buf;
+ store_dbg("store_boot_read: addr 0x%llx\n",addr);
+
+ sprintf(str, "%s rom_read 0x%llx 0x%llx 0x%llx",cmd_name, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s rom_read failed",cmd_name);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int store_boot_write(unsigned char * buf,uint64_t off, uint64_t size)
+{
+ //unsigned char *name;
+ uint64_t addr;
+ char str[128];
+ int ret =0;
+
+ if (!buf) {
+ store_msg("upgrade: no buf!!");
+ return -1;
+ }
+
+ addr = (unsigned long)buf;
+
+ sprintf(str, "%s rom_write 0x%llx 0x%llx 0x%llx",cmd_name, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s rom_write failed",cmd_name);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+int store_init(unsigned flag)
+{
+ //unsigned char *name;
+ //unsigned long addr;
+ char str[128];
+ int ret =0;
+ store_dbg("flag : %d",flag);
+
+ sprintf(str, "%s init %d",cmd_name,flag);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd [%s] init failed ",cmd_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+int store_exit(void)
+{
+ //unsigned char *name;
+ //unsigned long addr;
+ char str[128];
+ int ret =0;
+
+ sprintf(str, "%s exit",cmd_name);
+ printf("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("cmd %s exit failed",cmd_name);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+#if 0
+int do_store_test(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+ int i, init_flag=0,dev, ret = 0;
+ ulong addr;
+ uint64_t off, size;
+ char *cmd, *s, *area;
+ char str[128];
+ unsigned char *buf;
+
+ cmd = argv[1];
+
+ buf = malloc(0x400000);
+ if (!buf) {
+ printf("do_store_test : malloc failed\n");
+ return -1;
+ }
+
+ area ="logo";
+
+ if (strcmp(cmd, "read") == 0) {
+ ret = store_read_ops(area,buf,0x0,0x40000);
+ if (ret < 0) {
+ printf("store read failed\n");
+ return -1;
+ }
+ printf("store read OK\n");
+ }
+
+ if (strcmp(cmd, "boot_read") == 0) {
+ ret = store_boot_read(buf,0x0,0x60000);
+ if (ret < 0) {
+ printf("store boot_read failed\n");
+ return -1;
+ }
+ printf("store boot_read OK\n");
+ }
+
+ if (strcmp(cmd, "init") == 0) {
+ ret = store_init(0x0);
+ if (ret < 0) {
+ printf("store init failed\n");
+ return -1;
+ }
+ printf("store init OK\n");
+ }
+
+ if (strcmp(cmd, "write") == 0) {
+ memset(buf,0xa5,0x400000);
+ ret = store_write_ops(area,buf,0x0,0x40000);
+ if (ret < 0) {
+ printf("store write failed\n");
+ return -1;
+ }
+ printf("store write OK\n");
+ }
+
+ if (strcmp(cmd, "erase") == 0) {
+ area = "data";
+ ret = store_erase_ops(area,0x0,0,0);
+ if (ret < 0) {
+ printf("store write failed\n");
+ return -1;
+ }
+ }
+
+ if (strcmp(cmd, "size") == 0) {
+ uint64_t off=0, size;
+
+ ret = store_get_partititon_size(area,&size);
+ if (ret < 0) {
+ printf("store write failed\n");
+ return -1;
+ }
+ printf("off =%llx size=%llx\n",off,size);
+ }
+
+ if (buf)
+ kfree(buf);
+ return 0;
+
+}
+
+U_BOOT_CMD(store_test, CONFIG_SYS_MAXARGS, 1, do_store_test,
+ "NAND sub-system",
+ "store read name addr off|partition size\n"
+ " read 'size' bytes starting at offset 'off'\n"
+ " to/from memory address 'addr', skipping bad blocks.\n"
+ "store write name addr off|partition size\n"
+ " write 'size' bytes starting at offset 'off'\n"
+ " to/from memory address 'addr', skipping bad blocks.\n"
+ "store erase boot/data: \n"
+ "erase the area which is uboot or datas \n"
+ "store scrub off|partition size\n"
+ "scrub the area from offset and size \n"
+ );
+#endif
+
diff --git a/common/store_interface.c b/common/store_interface.c
index 84e0470fa5..2e8bb6c960 100644
--- a/common/store_interface.c
+++ b/common/store_interface.c
@@ -20,7 +20,7 @@
#define STORE_BOOT_SCRUB_ALL 4
#define _SPI_FLASH_ERASE_SZ (CONFIG_ENV_IN_SPI_OFFSET + CONFIG_ENV_SIZE)
-
+#define CONFIG_ENV_IN_SPI_OFFSET 0
//Ignore mbr since mmc driver already handled
//#define MMC_UBOOT_CLEAR_MBR
#define MMC_BOOT_PARTITION_SUPPORT
@@ -29,9 +29,9 @@
static char _mbrFlag[4] ;
#endif
-extern void get_device_boot_flag(void);
+//extern void get_device_boot_flag(void);
static int _info_disprotect_back_before_mmcinfo1 = 0;//mmcinfo 1 will clear info_disprotect before run_command("mmc erase 1")
-int info_disprotect = 0;
+extern int info_disprotect;
static inline int isstring(char *p)
{
char *endptr = p;
@@ -81,846 +81,850 @@ static inline int str2longlong(char *p, unsigned long long *num)
static int get_off_size(int argc, char *argv[], loff_t *off, loff_t *size)
{
- if (argc >= 1) {
- if (!(str2longlong(argv[0], (unsigned long long*)off))) {
+ if (argc >= 1) {
+ if (!(str2longlong(argv[0], (unsigned long long*)off))) {
store_msg("'%s' is not a number\n", argv[0]);
- return -1;
+ return -1;
+ }
+ } else {
+ *off = 0;
+ *size = 0;
}
- } else {
- *off = 0;
- *size = 0;
- }
- if (argc >= 2) {
- if (!(str2longlong(argv[1], (unsigned long long *)size))) {
- store_msg("'%s' is not a number\n", argv[1]);
- return -1;
+ if (argc >= 2) {
+ if (!(str2longlong(argv[1], (unsigned long long *)size))) {
+ store_msg("'%s' is not a number\n", argv[1]);
+ return -1;
+ }
+ }else{
+ *size = 0;
}
- }else{
- *size = 0;
- }
- store_dbg("offset 0x%llx, size 0x%llx", *off, *size);
+ store_dbg("offset 0x%llx, size 0x%llx", *off, *size);
- return 0;
+ return 0;
}
int do_store(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
- int i, init_flag=0, ret = 0;
- uint64_t addr;
- loff_t off=0, size=0;
- char *cmd, *s, *area;
- char str[128];
- unsigned char *tmp_buf= NULL;
-
- if (argc < 2)
- goto usage;
-
- cmd = argv[1];
-
- if (strcmp(cmd, "erase") == 0) {
-
- area = argv[2];
-
- if (strcmp(area, "boot") == 0) {
- if (device_boot_flag == NAND_BOOT_FLAG) {
- off = simple_strtoul(argv[3], NULL, 16);
- size = simple_strtoul(argv[4], NULL, 16);
- store_dbg("NAND BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
-
- ret = run_command("amlnf deverase boot 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }else if((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
- off = simple_strtoul(argv[3], NULL, 16);
- size = simple_strtoul(argv[4], NULL, 16);
-
- store_dbg("SPI BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
-
- ret = run_command("sf probe 2",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
+ int i, init_flag=0, ret = 0;
+ uint64_t addr;
+ loff_t off=0, size=0;
+ char *cmd, *s, *area;
+ char str[128];
+ //unsigned char *tmp_buf = NULL;
+
+ if (argc < 2)
+ goto usage;
+
+ cmd = argv[1];
+
+ if (strcmp(cmd, "erase") == 0) {
+
+ area = argv[2];
+
+ if (strcmp(area, "boot") == 0) {
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ off = simple_strtoul(argv[3], NULL, 16);
+ size = simple_strtoul(argv[4], NULL, 16);
+ store_dbg("NAND BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
+
+ ret = run_command("amlnf deverase boot 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }else if((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
+ off = simple_strtoul(argv[3], NULL, 16);
+ size = simple_strtoul(argv[4], NULL, 16);
+
+ store_dbg("SPI BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
+
+ ret = run_command("sf probe 2",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
sprintf(str, "sf erase 0 0x%x", CONFIG_ENV_IN_SPI_OFFSET);//store erase boot shoould NOT erase ENV in flash!
ret = run_command(str,0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }else if(device_boot_flag == EMMC_BOOT_FLAG){
- off = simple_strtoul(argv[3], NULL, 16);
- size = simple_strtoul(argv[4], NULL, 16);
-
- store_dbg("MMC BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
-
- sprintf(str, "mmc erase bootloader");
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed",cmd);
- return -1;
- }
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }else if(device_boot_flag == EMMC_BOOT_FLAG){
+ off = simple_strtoul(argv[3], NULL, 16);
+ size = simple_strtoul(argv[4], NULL, 16);
+
+ store_dbg("MMC BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
+
+ sprintf(str, "amlmmc erase bootloader");
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed",cmd);
+ return -1;
+ }
#ifdef MMC_BOOT_PARTITION_SUPPORT
- for (i=0; i<2; i++) {
- //switch to boot partition here
- sprintf(str, "mmc switch 1 boot%d", i);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret == -1) {
- //store_msg("mmc cmd %s failed \n",cmd);
- return 0;
- }
- else if(ret != 0){
- store_msg("mmc cmd %s failed",cmd);
- //return -1;
- goto E_SWITCH_BACK;
- }
-
- //erase boot partition
- sprintf(str, "mmc erase bootloader");
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed",cmd);
- //return -1;
- goto E_SWITCH_BACK;
- }
- }
+ for (i=0; i<2; i++) {
+ //switch to boot partition here
+ sprintf(str, "amlmmc switch 1 boot%d", i);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret == -1) {
+ //store_msg("mmc cmd %s failed \n",cmd);
+ return 0;
+ }
+ else if(ret != 0){
+ store_msg("amlmmc cmd %s failed",cmd);
+ //return -1;
+ goto E_SWITCH_BACK;
+ }
+
+ //erase boot partition
+ sprintf(str, "amlmmc erase bootloader");
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed",cmd);
+ //return -1;
+ goto E_SWITCH_BACK;
+ }
+ }
E_SWITCH_BACK:
- //switch back to urs partition
- sprintf(str, "mmc switch 1 user");
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
+ //switch back to urs partition
+ sprintf(str, "amlmmc switch 1 user");
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
#endif
- return ret;
- }else{
- store_dbg("CARD BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
- return 0;
- }
- }
- else if(strcmp(area, "data") == 0){
-
- if (device_boot_flag == NAND_BOOT_FLAG) {
- store_dbg("NAND BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
-
- ret = run_command("amlnf deverase data 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
-
- ret = run_command("amlnf deverase code 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- ret = run_command("amlnf deverase cache 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_NAND_FLAG){
- store_dbg("spi+nand , %s %d ",__func__,__LINE__);
- ret = run_command("amlnf deverase data 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
-
- ret = run_command("amlnf deverase code 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- ret = run_command("amlnf deverase cache 0",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_EMMC_FLAG){
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- off = size =0;
- ret = run_command("mmc erase 1",0); // whole
- if (ret != 0) {
- store_msg("mmc cmd %s failed ",cmd);
- return -1;
- }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT,erase uboot : %s %d off =%llx ,size=%llx",__func__,__LINE__,off,size);
+ return 0;
+ }
+ }
+ else if(strcmp(area, "data") == 0){
+
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ store_dbg("NAND BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
+
+ ret = run_command("amlnf deverase data 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+
+ ret = run_command("amlnf deverase code 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ ret = run_command("amlnf deverase cache 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_NAND_FLAG){
+ store_dbg("spi+nand , %s %d ",__func__,__LINE__);
+ ret = run_command("amlnf deverase data 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+
+ ret = run_command("amlnf deverase code 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ ret = run_command("amlnf deverase cache 0",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_EMMC_FLAG){
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ off = size =0;
+ ret = run_command("mmc erase 1",0); // whole
+ if (ret != 0) {
+ store_msg("mmc cmd %s failed ",cmd);
+ return -1;
+ }
+
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
+ off = size =0;
+ ret = run_command("amlmmc erase 1",0); //whole
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
+ return 0;
+ }
+ }
+ else {
+ goto usage;
+ }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
- off = size =0;
- ret = run_command("mmc erase 1",0); //whole
- if (ret != 0) {
- store_msg("mmc cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }else{
- store_dbg("CARD BOOT,erase data : %s %d off =%llx ,size=%llx",__func__,__LINE__, off, size);
- return 0;
- }
- }
- else {
- goto usage;
- }
+ }
+ else if(strcmp(cmd, "read") == 0){
+ if (argc < 6)
+ goto usage;
+
+ s = argv[2];
+ addr = (ulong)simple_strtoul(argv[3], NULL, 16);
+ if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0)
+ goto usage;
+
+ store_dbg("addr = %llx off= 0x%llx size=0x%llx",addr,off,size);
+ if ((device_boot_flag == NAND_BOOT_FLAG)) {
+ sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx",s, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_NAND_FLAG){
+ sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_EMMC_FLAG){
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ sprintf(str, "amlmmc read %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG) {
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
+ sprintf(str, "amlmmc read %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
- }
- else if(strcmp(cmd, "read") == 0){
- if (argc < 6)
- goto usage;
-
- s = argv[2];
- addr = (ulong)simple_strtoul(argv[3], NULL, 16);
- if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0)
- goto usage;
-
- store_dbg("addr = %llx off= 0x%llx size=0x%llx",addr,off,size);
- if ((device_boot_flag == NAND_BOOT_FLAG)) {
- sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx",s, addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_NAND_FLAG){
- sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_EMMC_FLAG){
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- sprintf(str, "mmc read %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG) {
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- sprintf(str, "mmc read %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }else{
- store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
+ return 0;
+ }
+ }
+ else if(strcmp(cmd, "write") == 0){
+ if (argc < 6)
+ goto usage;
+ s = argv[2];
+ addr = (ulong)simple_strtoul(argv[3], NULL, 16);
+ if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0)
+ goto usage;
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+
+ sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed ",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_NAND_FLAG){
+ store_dbg("spi+nand , %s %d ",__func__,__LINE__);
+ sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_EMMC_FLAG){
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ sprintf(str, "amlmmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
+ sprintf(str, "amlmmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
+ return 0;
+ }
+ return ret;
+ }
+ else if(strcmp(cmd, "rom_write") == 0){
+ if (argc < 5)
+ goto usage;
+ addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+ if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0)
+ goto usage;
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ sprintf(str, "amlnf rom_write 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if ((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
+ ret = run_command("sf probe 2",0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ sprintf(str, "sf erase 0x%llx 0x%llx ", off, size);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ sprintf(str, "sf write 0x%llx 0x%llx 0x%llx ",addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- return 0;
- }
- }
- else if(strcmp(cmd, "write") == 0){
- if (argc < 6)
- goto usage;
- s = argv[2];
- addr = (ulong)simple_strtoul(argv[3], NULL, 16);
- if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0)
- goto usage;
- if (device_boot_flag == NAND_BOOT_FLAG) {
-
- sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed ",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_NAND_FLAG){
- store_dbg("spi+nand , %s %d ",__func__,__LINE__);
- sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_EMMC_FLAG){
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- sprintf(str, "mmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- sprintf(str, "mmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }else{
- store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
- return 0;
- }
- return ret;
- }
- else if(strcmp(cmd, "rom_write") == 0){
- if (argc < 5)
- goto usage;
- addr = (ulong)simple_strtoul(argv[2], NULL, 16);
- if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0)
- goto usage;
- if (device_boot_flag == NAND_BOOT_FLAG) {
- sprintf(str, "amlnf rom_write 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if ((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
- ret = run_command("sf probe 2",0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- sprintf(str, "sf erase 0x%llx 0x%llx ", off, size);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- sprintf(str, "sf write 0x%llx 0x%llx 0x%llx ",addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- tmp_buf= (unsigned char *)(int)addr;
#ifndef CONFIG_AML_SECU_BOOT_V2
- #ifdef MMC_UBOOT_CLEAR_MBR
- //modify the 55 AA info for emmc uboot
- _mbrFlag[0] = tmp_buf[510];
- _mbrFlag[1] = tmp_buf[511];
- tmp_buf[510]=0;
- tmp_buf[511]=0;
- #endif
+#ifdef MMC_UBOOT_CLEAR_MBR
+ //modify the 55 AA info for emmc uboot
+ unsigned char *tmp_buf= (unsigned char *)addr;
+ _mbrFlag[0] = tmp_buf[510];
+ _mbrFlag[1] = tmp_buf[511];
+ tmp_buf[510]=0;
+ tmp_buf[511]=0;
+#endif
#endif// #if defined(CONFIG_AML_SECU_BOOT_V2)
- sprintf(str, "mmc write bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
+ sprintf(str, "amlmmc write bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
#ifdef MMC_BOOT_PARTITION_SUPPORT
- for (i=0; i<2; i++) {
- //switch to boot partition here
- sprintf(str, "mmc switch 1 boot%d", i);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret == -1) {
- //store_msg("mmc cmd %s failed \n",cmd);
- ret = 0;
- return ret;
- }
- else if(ret != 0){
- store_msg("mmc cmd %s failed",cmd);
- //return -1;
- goto W_SWITCH_BACK;
- }
-
- //write uboot to boot partition
- sprintf(str, "mmc write bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- //return -1;
- goto W_SWITCH_BACK;
- }
- }
+ for (i=0; i<2; i++) {
+ //switch to boot partition here
+ sprintf(str, "amlmmc switch 1 boot%d", i);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret == -1) {
+ //store_msg("mmc cmd %s failed \n",cmd);
+ ret = 0;
+ return ret;
+ }
+ else if(ret != 0){
+ store_msg("amlmmc cmd %s failed",cmd);
+ //return -1;
+ goto W_SWITCH_BACK;
+ }
+
+ //write uboot to boot partition
+ sprintf(str, "amlmmc write bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ //return -1;
+ goto W_SWITCH_BACK;
+ }
+ }
W_SWITCH_BACK:
- //switch back to urs partition
- sprintf(str, "mmc switch 1 user");
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
+ //switch back to urs partition
+ sprintf(str, "amlmmc switch 1 user");
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
#endif
- return ret;
- }else{
- store_dbg("CARD BOOT, %s %d",__func__,__LINE__);
- return 0;
- }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT, %s %d",__func__,__LINE__);
+ return 0;
+ }
- }
- else if(strcmp(cmd, "rom_read") == 0){
- if (argc < 5)
- goto usage;
- addr = (ulong)simple_strtoul(argv[2], NULL, 16);
- if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0)
- goto usage;
- if (device_boot_flag == NAND_BOOT_FLAG) {
- sprintf(str, "amlnf rom_read 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }else if ((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
- ret = run_command("sf probe 2",0);
- if (ret != 0) {
- return -1;
- }
- sprintf(str, "sf read 0x%llx 0x%llx 0x%llx ",addr, off, size);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }else if (device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- sprintf(str, "mmc read bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s\n", str);
- tmp_buf= (unsigned char *)(int)addr;
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
+ }
+ else if(strcmp(cmd, "rom_read") == 0){
+ if (argc < 5)
+ goto usage;
+ addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+ if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0)
+ goto usage;
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ sprintf(str, "amlnf rom_read 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }else if ((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG)){
+ ret = run_command("sf probe 2",0);
+ if (ret != 0) {
+ return -1;
+ }
+ sprintf(str, "sf read 0x%llx 0x%llx 0x%llx ",addr, off, size);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }else if (device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
+ sprintf(str, "amlmmc read bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s\n", str);
+ //tmp_buf= (unsigned char *)addr;
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
#ifdef MMC_BOOT_PARTITION_SUPPORT
- for (i=0; i<2; i++) {
- //switch to boot partition here
- sprintf(str, "mmc switch 1 boot%d", i);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret == -1) {
- //store_msg("mmc cmd %s failed \n",cmd);
- return 0;
- }
- else if(ret != 0){
- store_msg("mmc cmd %s failed",cmd);
- goto R_SWITCH_BACK;
- //return -1;
- }
-
- //write uboot to boot partition
- sprintf(str, "mmc read bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- //return -1;
- goto R_SWITCH_BACK;
- }
- }
+ for (i=0; i<2; i++) {
+ //switch to boot partition here
+ sprintf(str, "amlmmc switch 1 boot%d", i);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret == -1) {
+ //store_msg("mmc cmd %s failed \n",cmd);
+ return 0;
+ }
+ else if(ret != 0){
+ store_msg("amlmmc cmd %s failed",cmd);
+ goto R_SWITCH_BACK;
+ //return -1;
+ }
+
+ //write uboot to boot partition
+ sprintf(str, "amlmmc read bootloader 0x%llx 0x%llx 0x%llx", addr, off, size);
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ //return -1;
+ goto R_SWITCH_BACK;
+ }
+ }
R_SWITCH_BACK:
- //switch back to urs partition
- sprintf(str, "mmc switch 1 user");
- store_dbg("command: %s\n", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
+ //switch back to urs partition
+ sprintf(str, "amlmmc switch 1 user");
+ store_dbg("command: %s\n", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
#endif
#ifndef CONFIG_AML_SECU_BOOT_V2
- #ifdef MMC_UBOOT_CLEAR_MBR
- tmp_buf[510]= _mbrFlag[0];
- tmp_buf[511]= _mbrFlag[1];
- #endif
+#ifdef MMC_UBOOT_CLEAR_MBR
+ unsigned char *tmp_buf= (unsigned char *)addr;
+ tmp_buf[510]= _mbrFlag[0];
+ tmp_buf[511]= _mbrFlag[1];
+#endif
#endif// #ifndef CONFIG_AML_SECU_BOOT_V2
- return ret;
- }else{
- store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
- return 0;
- }
+ return ret;
+ }else{
+ store_dbg("CARD BOOT, %s %d ",__func__,__LINE__);
+ return 0;
+ }
- }
- else if (strcmp(cmd, "rom_protect") == 0){
- if (argc < 3)
- goto usage;
-
- area = argv[2];
- if (device_boot_flag == NAND_BOOT_FLAG) {
- sprintf(str, "amlnf rom_protect %s", area);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- }
- else if (strcmp(cmd, "scrub") == 0){
- off = (ulong)simple_strtoul(argv[2], NULL, 16);
- sprintf(str, "amlnf scrub %d", (int)off);
- if (device_boot_flag == NAND_BOOT_FLAG) {
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- }
- else if(device_boot_flag == SPI_NAND_FLAG){
- store_dbg("spi+nand , %s %d ",__func__,__LINE__);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- ret = run_command("sf probe 2", 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
- ret = run_command(str,0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_EMMC_FLAG){
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- ret = run_command("mmc erase whole",0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- device_boot_flag = EMMC_BOOT_FLAG;
- ret = run_command("mmcinfo 1", 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
- MsgP("mmc key\n");
- run_command("mmc key", 0);
- }
- MsgP("mmc erase 1");
- ret = run_command("mmc erase 1", 0);
}
- return ret;
- }
- else if(strcmp(cmd, "init") == 0){
+ else if (strcmp(cmd, "rom_protect") == 0){
+ if (argc < 3)
+ goto usage;
+
+ area = argv[2];
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ sprintf(str, "amlnf rom_protect %s", area);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ }
+ else if (strcmp(cmd, "scrub") == 0){
+ off = (ulong)simple_strtoul(argv[2], NULL, 16);
+ sprintf(str, "amlnf scrub %d", (int)off);
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ }
+ else if(device_boot_flag == SPI_NAND_FLAG){
+ store_dbg("spi+nand , %s %d ",__func__,__LINE__);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ ret = run_command("sf probe 2", 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
+ ret = run_command(str,0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_EMMC_FLAG){
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ ret = run_command("amlmmc erase whole",0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
+ device_boot_flag = EMMC_BOOT_FLAG;
+ run_command("mmc dev 1", 0);
+ ret = run_command("mmcinfo", 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
+ MsgP("mmc key\n");
+ run_command("mmc key", 0);
+ }
+ MsgP("amlmmc erase 1");
+ ret = run_command("amlmmc erase 1", 0);
+ }
+ return ret;
+ }
+ else if(strcmp(cmd, "init") == 0){
- init_flag = (argc > 2) ? (int)simple_strtoul(argv[2], NULL, 16) : 0;
- store_dbg("init_flag %d",init_flag);
+ init_flag = (argc > 2) ? (int)simple_strtoul(argv[2], NULL, 16) : 0;
+ store_dbg("init_flag %d",init_flag);
- if (device_boot_flag == -1) {
- get_device_boot_flag();
- }
- if (device_boot_flag == NAND_BOOT_FLAG)
- {
- if ((init_flag >=STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <=STORE_BOOT_SCRUB_ALL)) {
- sprintf(str, "amlnf init %d ",init_flag);
- run_command(str, 0);
- }
+ if (device_boot_flag == -1) {
+ //get_device_boot_flag();
+ }
+ if (device_boot_flag == NAND_BOOT_FLAG)
+ {
+ if ((init_flag >=STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <=STORE_BOOT_SCRUB_ALL)) {
+ sprintf(str, "amlnf init %d ",init_flag);
+ run_command(str, 0);
+ }
- sprintf(str, "amlnf init %d ",1);
- printf("command: %s -> %d\n", str, init_flag);
- device_boot_flag = NAND_BOOT_FLAG;
- ret = run_command(str, 0);
- if (ret != 0) {
+ sprintf(str, "amlnf init %d ",1);
+ printf("command: %s -> %d\n", str, init_flag);
+ device_boot_flag = NAND_BOOT_FLAG;
+ ret = run_command(str, 0);
+ if (ret != 0) {
#if 0
- if ((ret == NAND_INIT_FAILED) && (init_flag == STORE_BOOT_ERASE_ALL)) {
- sprintf(str, "amlnf init %d ",4);
- ret = run_command(str, 0);
- }
- if (ret) {
- store_msg("nand cmd %s failed,ret=%d ",cmd,ret);
- return -1;
- }
- return 0;
+ if ((ret == NAND_INIT_FAILED) && (init_flag == STORE_BOOT_ERASE_ALL)) {
+ sprintf(str, "amlnf init %d ",4);
+ ret = run_command(str, 0);
+ }
+ if (ret) {
+ store_msg("nand cmd %s failed,ret=%d ",cmd,ret);
+ return -1;
+ }
+ return 0;
#else
- return -1;
+ return -1;
#endif
- }
- return ret;
- }
- else if((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG))
- {
-/*
- if (device_boot_flag == -1)
- {
- ret = run_command("sf probe 2", 0);
- if (ret) {
- store_msg(" cmd %s failed \n",cmd);
- return -1;
- }
- if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
- sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
- ret = run_command(str,0);
- }
- sprintf(str, "amlnf init %d ",init_flag);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret < 0) //fail to init NAND flash
- {
- store_msg("nand cmd %s failed \n",cmd);
- device_boot_flag = SPI_EMMC_FLAG;
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- ret = run_command("mmcinfo 1", 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -2;
- }
- if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
- store_msg("mmc erase non_cache \n");
- ret = run_command("mmc erase non_cache", 0);
- }else if(init_flag >= STORE_BOOT_ERASE_ALL){ // erase all except reserved area
- if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
- MsgP("mmc key;\n");
- run_command("mmc key", 0);
}
- MsgP("mmc erase 1 \n");
- ret = run_command("mmc erase 1", 0);
- }
- return 0;
- }
- else if((ret == NAND_INIT_FAILED)&&(init_flag == STORE_BOOT_ERASE_ALL)){
- sprintf(str, "amlnf init %d ",4);
- ret = run_command(str, 0);
- }
- device_boot_flag = SPI_NAND_FLAG;
- return 0;
- }
-*/
- if (device_boot_flag == SPI_NAND_FLAG) {
- store_dbg("spi+nand , %s %d ",__func__,__LINE__);
-
- if ((init_flag >=STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <=STORE_BOOT_SCRUB_ALL)) {
- sprintf(str, "amlnf init %d ",init_flag);
- run_command(str, 0);
- }
- sprintf(str, "amlnf init %d ",1);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
+ return ret;
+ }
+ else if((device_boot_flag==SPI_EMMC_FLAG)||(device_boot_flag==SPI_NAND_FLAG))
+ {
+ /*
+ if (device_boot_flag == -1)
+ {
+ ret = run_command("sf probe 2", 0);
+ if (ret) {
+ store_msg(" cmd %s failed \n",cmd);
+ return -1;
+ }
+ if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
+ sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
+ ret = run_command(str,0);
+ }
+ sprintf(str, "amlnf init %d ",init_flag);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret < 0) //fail to init NAND flash
+ {
+ store_msg("nand cmd %s failed \n",cmd);
+ device_boot_flag = SPI_EMMC_FLAG;
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ ret = run_command("mmcinfo 1", 0);
+ if (ret != 0) {
+ store_msg("mmc cmd %s failed \n",cmd);
+ return -2;
+ }
+ if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
+ store_msg("mmc erase non_cache \n");
+ ret = run_command("mmc erase non_cache", 0);
+ }else if(init_flag >= STORE_BOOT_ERASE_ALL){ // erase all except reserved area
+ if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
+ MsgP("mmc key;\n");
+ run_command("mmc key", 0);
+ }
+ MsgP("mmc erase 1 \n");
+ ret = run_command("mmc erase 1", 0);
+ }
+ return 0;
+ }
+ else if((ret == NAND_INIT_FAILED)&&(init_flag == STORE_BOOT_ERASE_ALL)){
+ sprintf(str, "amlnf init %d ",4);
+ ret = run_command(str, 0);
+ }
+ device_boot_flag = SPI_NAND_FLAG;
+ return 0;
+ }
+ */
+ if (device_boot_flag == SPI_NAND_FLAG) {
+ store_dbg("spi+nand , %s %d ",__func__,__LINE__);
+
+ if ((init_flag >=STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <=STORE_BOOT_SCRUB_ALL)) {
+ sprintf(str, "amlnf init %d ",init_flag);
+ run_command(str, 0);
+ }
+ sprintf(str, "amlnf init %d ",1);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
#if 0
- if ((ret == NAND_INIT_FAILED) && (init_flag == STORE_BOOT_ERASE_ALL)) {
- sprintf(str, "amlnf init %d ",4);
- ret = run_command(str, 0);
- }
+ if ((ret == NAND_INIT_FAILED) && (init_flag == STORE_BOOT_ERASE_ALL)) {
+ sprintf(str, "amlnf init %d ",4);
+ ret = run_command(str, 0);
+ }
#else
- if (ret == NAND_INIT_FAILED) {
- return -1;
- }
+ if (ret == NAND_INIT_FAILED) {
+ return -1;
+ }
#endif
- if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
- ret = run_command("sf probe 2", 0);
- sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
- ret = run_command(str,0);
- }
- }
- if (device_boot_flag == SPI_EMMC_FLAG) {
- store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
- ret = run_command("mmcinfo 1", 0);
-
- if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
- store_msg("mmc erase non_cache \n");
- ret = run_command("mmc erase non_cache", 0);
- }else if(init_flag == STORE_BOOT_ERASE_ALL){ // erase all except reserved area
- if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
- run_command("mmc key", 0);
- }
- MsgP("mmc erase 1 \n");
- ret = run_command("mmc erase 1", 0);
- }
- if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
- ret = run_command("sf probe 2", 0);
- sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
- ret = run_command(str,0);
- }
- }
-
- if (ret != 0) {
- store_msg("cmd %s failed \n",cmd);
- return -1;
- }
+ if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
+ ret = run_command("sf probe 2", 0);
+ sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
+ ret = run_command(str,0);
+ }
+ }
+ if (device_boot_flag == SPI_EMMC_FLAG) {
+ store_dbg("spi+mmc , %s %d ",__func__,__LINE__);
+ ret = run_command("mmcinfo 1", 0);
+
+ if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
+ store_msg("amlmmc erase non_cache \n");
+ ret = run_command("amlmmc erase non_cache", 0);
+ }else if(init_flag == STORE_BOOT_ERASE_ALL){ // erase all except reserved area
+ if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
+ run_command("mmc key", 0);
+ }
+ MsgP("amlmmc erase 1 \n");
+ ret = run_command("amlmmc erase 1", 0);
+ }
+ if ((init_flag > STORE_BOOT_ERASE_PROTECT_CACHE) && (init_flag <= STORE_BOOT_SCRUB_ALL)) {
+ ret = run_command("sf probe 2", 0);
+ sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ);
+ ret = run_command(str,0);
+ }
+ }
- return ret;
- }
- else if(device_boot_flag == EMMC_BOOT_FLAG){
- store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
- device_boot_flag = EMMC_BOOT_FLAG;
- ret = run_command("mmcinfo 1", 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed \n",cmd);
- return -1;
- }
- if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
- ret = run_command("mmc erase non_cache", 0);
- }else if(init_flag >= STORE_BOOT_ERASE_ALL){ // erase all except reserved area
- if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
- MsgP("mmc key\n");
- run_command("mmc key", 0);
+ if (ret != 0) {
+ store_msg("cmd %s failed \n",cmd);
+ return -1;
}
- MsgP("mmc erase 1");
- ret = run_command("mmc erase 1", 0);
+
+ return ret;
}
+ else if(device_boot_flag == EMMC_BOOT_FLAG){
+ store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__);
+ device_boot_flag = EMMC_BOOT_FLAG;
+ run_command("mmc dev 1",0);
+ ret = run_command("mmcinfo", 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed \n",cmd);
+ return -1;
+ }
+ if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { // OTA upgrade protect cache
+ ret = run_command("amlmmc erase non_cache", 0);
+ }else if(init_flag >= STORE_BOOT_ERASE_ALL){ // erase all except reserved area
+ if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) {
+ MsgP("amlmmc key\n");
+ run_command("amlmmc key", 0);
+ }
+ MsgP("amlmmc erase 1");
+ ret = run_command("amlmmc erase 1", 0);
+ }
return ret;
- }else{
- store_dbg("CARD BOOT, %s %d",__func__,__LINE__);
+ }else{
+ store_dbg("CARD BOOT, %s %d",__func__,__LINE__);
+ return 0;
+ }
+ }
+ else if(strcmp(cmd, "size") == 0){
+
+ if (argc < 4)
+ goto usage;
+
+ s = argv[2];
+ addr = (ulong)simple_strtoul(argv[3], NULL, 16);
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ sprintf(str, "amlnf size %s %llx",s,addr);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_NAND_FLAG){
+ sprintf(str, "amlnf size %s %llx",s,addr);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag == SPI_EMMC_FLAG){
+ store_dbg("MMC , %s %d ",__func__,__LINE__);
+ sprintf(str, "amlmmc size %s %llx",s,addr);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==EMMC_BOOT_FLAG){
+ store_dbg("MMC , %s %d ",__func__,__LINE__);
+ sprintf(str, "amlmmc size %s %llx",s,addr);
+ store_dbg("command: %s", str);
+ ret = run_command(str, 0);
+ if (ret != 0) {
+ store_msg("amlmmc cmd %s failed",cmd);
+ return -1;
+ }
+ return ret;
+ }
+ else if(device_boot_flag==CARD_BOOT_FLAG){
+ store_dbg("CARD BOOT , %s %d ",__func__,__LINE__);
+ return 0;
+ }
+ }
+ else if(strcmp(cmd, "disprotect") == 0){
+ area = argv[2];
+ if (strcmp(area, "key") == 0) {
+ MsgP("disprotect key\n");
+ info_disprotect |= DISPROTECT_KEY;
+ _info_disprotect_back_before_mmcinfo1 |= DISPROTECT_KEY;
+ }
+ if (strcmp(area, "secure") == 0) {
+ store_msg("disprotect secure");
+ info_disprotect |= DISPROTECT_SECURE;
+ }
+ if (strcmp(area, "fbbt") == 0) {
+ store_msg("disprotect fbbt");
+ info_disprotect |= DISPROTECT_FBBT;
+ }
+ if (strcmp(area, "hynix") == 0) {
+ store_msg("disprotect hynix");
+ info_disprotect |= DISPROTECT_HYNIX;
+ }
return 0;
}
- }
- else if(strcmp(cmd, "size") == 0){
-
- if (argc < 4)
- goto usage;
-
- s = argv[2];
- addr = (ulong)simple_strtoul(argv[3], NULL, 16);
- if (device_boot_flag == NAND_BOOT_FLAG) {
- sprintf(str, "amlnf size %s %llx",s,addr);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_NAND_FLAG){
- sprintf(str, "amlnf size %s %llx",s,addr);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag == SPI_EMMC_FLAG){
- store_dbg("MMC , %s %d ",__func__,__LINE__);
- sprintf(str, "mmc size %s %llx",s,addr);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==EMMC_BOOT_FLAG){
- store_dbg("MMC , %s %d ",__func__,__LINE__);
- sprintf(str, "mmc size %s %llx",s,addr);
- store_dbg("command: %s", str);
- ret = run_command(str, 0);
- if (ret != 0) {
- store_msg("mmc cmd %s failed",cmd);
- return -1;
- }
- return ret;
- }
- else if(device_boot_flag==CARD_BOOT_FLAG){
- store_dbg("CARD BOOT , %s %d ",__func__,__LINE__);
- return 0;
- }
- }
- else if(strcmp(cmd, "disprotect") == 0){
- area = argv[2];
- if (strcmp(area, "key") == 0) {
- MsgP("disprotect key\n");
- info_disprotect |= DISPROTECT_KEY;
- _info_disprotect_back_before_mmcinfo1 |= DISPROTECT_KEY;
- }
- if (strcmp(area, "secure") == 0) {
- store_msg("disprotect secure");
- info_disprotect |= DISPROTECT_SECURE;
- }
- if (strcmp(area, "fbbt") == 0) {
- store_msg("disprotect fbbt");
- info_disprotect |= DISPROTECT_FBBT;
- }
- if (strcmp(area, "hynix") == 0) {
- store_msg("disprotect hynix");
- info_disprotect |= DISPROTECT_HYNIX;
- }
- return 0;
- }
- else if(strcmp(cmd, "exit") == 0){
+ else if(strcmp(cmd, "exit") == 0){
- if (device_boot_flag == NAND_BOOT_FLAG) {
- ret = run_command("amlnf exit", 0);
- if (ret != 0) {
- store_msg("nand cmd %s failed",cmd);
- return -1;
- }
- }
- return 0;
- }
- else{
- goto usage;
- }
+ if (device_boot_flag == NAND_BOOT_FLAG) {
+ ret = run_command("amlnf exit", 0);
+ if (ret != 0) {
+ store_msg("nand cmd %s failed",cmd);
+ return -1;
+ }
+ }
+ return 0;
+ }
+ else{
+ goto usage;
+ }
- return ret;
+ return ret;
usage:
- cmd_usage(cmdtp);
- return 1;
+ cmd_usage(cmdtp);
+ return 1;
}
diff --git a/drivers/Makefile b/drivers/Makefile
index 4e610157f7..def96e58fa 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -25,3 +25,5 @@ obj-y += input/
obj-y += soc/
obj-y += thermal/
obj-$(CONFIG_EFUSE) += efuse/
+obj-$(CONFIG_AML_V2_FACTORY_BURN) += usb/gadget/v2_burning/
+
diff --git a/drivers/mmc/aml_sd_emmc.c b/drivers/mmc/aml_sd_emmc.c
index ebbb6929b4..662ebd161b 100644
--- a/drivers/mmc/aml_sd_emmc.c
+++ b/drivers/mmc/aml_sd_emmc.c
@@ -254,162 +254,173 @@ static int sd_inand_staff_init(struct mmc *mmc)
*/
int aml_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
- int ret = SD_NO_ERROR;
- //u32 vconf;
- u32 buffer = 0;
- u32 resp_buffer;
- u32 vstart = 0;
- u32 status_irq = 0;
-
- struct sd_emmc_status *status_irq_reg = (void *)&status_irq;
- struct sd_emmc_start *desc_start = (struct sd_emmc_start*)&vstart;
- //struct sd_emmc_config* sd_emmc_cfg = (struct sd_emmc_config*)&vconf;
- struct aml_card_sd_info *aml_priv = mmc->priv;
- struct sd_emmc_global_regs *sd_emmc_reg = aml_priv->sd_emmc_reg;
- struct cmd_cfg *des_cmd_cur = NULL;
- struct sd_emmc_desc_info *desc_cur = (struct sd_emmc_desc_info*)aml_priv->desc_buf;
-
- //vconf = sd_emmc_reg->gcfg;
-
- memset(desc_cur, 0, (NEWSD_MAX_DESC_MUN>>2)*sizeof(struct sd_emmc_desc_info));
-
- des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info);
- des_cmd_cur->cmd_index = 0x80 | cmd->cmdidx; //bit:31 owner = 1 bit:24-29 cmdidx
- desc_cur->cmd_arg = cmd->cmdarg;
-
- sd_inand_clear_response(cmd->response);
-
- //check response type
- if (cmd->resp_type & MMC_RSP_PRESENT) {
- resp_buffer = (unsigned long)cmd->response;//dma_map_single((void*)cmd->response,sizeof(uint)*4,DMA_FROM_DEVICE);
- des_cmd_cur->no_resp = 0;
-
- //save Resp into Resp addr, and check response from register for RSP_136
- if (cmd->resp_type & MMC_RSP_136)
- des_cmd_cur->resp_128 = 1;
-
- if (cmd->resp_type & MMC_RSP_BUSY)
- des_cmd_cur->r1b = 1; //check data0 busy after R1 reponse
-
- if (!(cmd->resp_type & MMC_RSP_CRC))
- des_cmd_cur->resp_nocrc = 1;
-
- des_cmd_cur->resp_num = 0;
- desc_cur->resp_addr = resp_buffer;
- }else
- des_cmd_cur->no_resp = 1;
-
- if (data) {
- des_cmd_cur->data_io = 1; // cmd has data read or write
- if (data->flags == MMC_DATA_READ) {
- des_cmd_cur->data_wr = 0; //read data from sd/emmc
- buffer = (unsigned long)data->dest;//dma_map_single((void*)data->dest,data->blocks*data->blocksize,DMA_FROM_DEVICE);
- invalidate_dcache_range((unsigned long)data->dest, (unsigned long)(data->dest+data->blocks*data->blocksize));
- }else{
- des_cmd_cur->data_wr = 1;
- buffer = (unsigned long)data->src;//dma_map_single((void*)data->src,data->blocks*data->blocksize,DMA_TO_DEVICE);//(char *)data->src;
- flush_dcache_range((unsigned long)data->src,(unsigned long)(data->src+data->blocks*data->blocksize));
- }
- if (data->blocks > 1) {
- des_cmd_cur->block_mode = 1;
- des_cmd_cur->length = data->blocks;
- }else{
- des_cmd_cur->block_mode = 0;
- des_cmd_cur->length = data->blocksize;
- }
- des_cmd_cur->data_num = 0;
- desc_cur->data_addr = buffer;
- desc_cur->data_addr &= ~(1<<0); //DDR
-
- }
- if (data) {
- if ((data->blocks*data->blocksize <0x200) && (data->flags == MMC_DATA_READ)) {
- desc_cur->data_addr = (unsigned long)sd_emmc_reg->gping;
- desc_cur->data_addr |= 1<<0;
- }
- }
- /*Prepare desc for config register*/
- des_cmd_cur->owner = 1;
- des_cmd_cur->end_of_chain = 0;
-
- //sd_emmc_reg->gcfg = vconf;
-
- des_cmd_cur->end_of_chain = 1; //the end flag of descriptor chain
-
- sd_emmc_reg->gstatus = NEWSD_IRQ_ALL;
-
- invalidate_dcache_range((unsigned long)aml_priv->desc_buf,
- (unsigned long)(aml_priv->desc_buf+NEWSD_MAX_DESC_MUN*(sizeof(struct sd_emmc_desc_info))));
- //start transfer cmd
- desc_start->init = 0;
- desc_start->busy = 1;
- desc_start->addr = (unsigned long)aml_priv->desc_buf >> 2;
+ int ret = SD_NO_ERROR;
+ //u32 vconf;
+ u32 buffer = 0;
+ u32 resp_buffer;
+ u32 vstart = 0;
+ u32 status_irq = 0;
+ //u32 inalign = 0;
+ u32 *write_buffer = NULL;
+ struct sd_emmc_status *status_irq_reg = (void *)&status_irq;
+ struct sd_emmc_start *desc_start = (struct sd_emmc_start*)&vstart;
+ //struct sd_emmc_config* sd_emmc_cfg = (struct sd_emmc_config*)&vconf;
+ struct aml_card_sd_info *aml_priv = mmc->priv;
+ struct sd_emmc_global_regs *sd_emmc_reg = aml_priv->sd_emmc_reg;
+ struct cmd_cfg *des_cmd_cur = NULL;
+ struct sd_emmc_desc_info *desc_cur = (struct sd_emmc_desc_info*)aml_priv->desc_buf;
+
+ //vconf = sd_emmc_reg->gcfg;
+
+ memset(desc_cur, 0, (NEWSD_MAX_DESC_MUN>>2)*sizeof(struct sd_emmc_desc_info));
+
+ des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info);
+ des_cmd_cur->cmd_index = 0x80 | cmd->cmdidx; //bit:31 owner = 1 bit:24-29 cmdidx
+ desc_cur->cmd_arg = cmd->cmdarg;
+
+ sd_inand_clear_response(cmd->response);
+
+ //check response type
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ resp_buffer = (unsigned long)cmd->response;//dma_map_single((void*)cmd->response,sizeof(uint)*4,DMA_FROM_DEVICE);
+ des_cmd_cur->no_resp = 0;
+
+ //save Resp into Resp addr, and check response from register for RSP_136
+ if (cmd->resp_type & MMC_RSP_136)
+ des_cmd_cur->resp_128 = 1;
+
+ if (cmd->resp_type & MMC_RSP_BUSY)
+ des_cmd_cur->r1b = 1; //check data0 busy after R1 reponse
+
+ if (!(cmd->resp_type & MMC_RSP_CRC))
+ des_cmd_cur->resp_nocrc = 1;
+
+ des_cmd_cur->resp_num = 0;
+ desc_cur->resp_addr = resp_buffer;
+ }else
+ des_cmd_cur->no_resp = 1;
+
+ if (data) {
+ des_cmd_cur->data_io = 1; // cmd has data read or write
+ if (data->flags == MMC_DATA_READ) {
+ des_cmd_cur->data_wr = 0; //read data from sd/emmc
+ buffer = (unsigned long)data->dest;//dma_map_single((void*)data->dest,data->blocks*data->blocksize,DMA_FROM_DEVICE);
+ invalidate_dcache_range((unsigned long)data->dest, (unsigned long)(data->dest+data->blocks*data->blocksize));
+ }else{
+ des_cmd_cur->data_wr = 1;
+ //buffer = (unsigned long)data->src;//dma_map_single((void*)data->src,data->blocks*data->blocksize,DMA_TO_DEVICE);//(char *)data->src;
+ write_buffer = (u32 *)malloc(128*1024);
+ memset(write_buffer, 0 ,128*1024);
+ memcpy(write_buffer, (u32 *)data->src, data->blocks*data->blocksize);
+ flush_dcache_range((unsigned)(long)write_buffer,(unsigned long)(write_buffer+data->blocks*data->blocksize));
+ }
+
+ if (data->blocks > 1) {
+ des_cmd_cur->block_mode = 1;
+ des_cmd_cur->length = data->blocks;
+ }else{
+ des_cmd_cur->block_mode = 0;
+ des_cmd_cur->length = data->blocksize;
+ }
+ des_cmd_cur->data_num = 0;
+ if (des_cmd_cur->data_wr == 1)
+ desc_cur->data_addr = (unsigned long)write_buffer;
+ else
+ desc_cur->data_addr = buffer;
+ desc_cur->data_addr &= ~(1<<0); //DDR
+
+ }
+ if (data) {
+ if ((data->blocks*data->blocksize <0x200) && (data->flags == MMC_DATA_READ)) {
+ desc_cur->data_addr = (unsigned long)sd_emmc_reg->gping;
+ desc_cur->data_addr |= 1<<0;
+ }
+ }
+ /*Prepare desc for config register*/
+ des_cmd_cur->owner = 1;
+ des_cmd_cur->end_of_chain = 0;
+
+ //sd_emmc_reg->gcfg = vconf;
+
+ des_cmd_cur->end_of_chain = 1; //the end flag of descriptor chain
+
+ sd_emmc_reg->gstatus = NEWSD_IRQ_ALL;
+
+ invalidate_dcache_range((unsigned long)aml_priv->desc_buf,
+ (unsigned long)(aml_priv->desc_buf+NEWSD_MAX_DESC_MUN*(sizeof(struct sd_emmc_desc_info))));
+ //start transfer cmd
+ desc_start->init = 0;
+ desc_start->busy = 1;
+ desc_start->addr = (unsigned long)aml_priv->desc_buf >> 2;
#if 0
- sd_emmc_reg->gstart = vstart;
+ sd_emmc_reg->gstart = vstart;
#else
- sd_emmc_reg->gcmd_cfg = desc_cur->cmd_info;
- sd_emmc_reg->gcmd_dat = desc_cur->data_addr;
- sd_emmc_reg->gcmd_arg = desc_cur->cmd_arg;
+ sd_emmc_reg->gcmd_cfg = desc_cur->cmd_info;
+ sd_emmc_reg->gcmd_dat = desc_cur->data_addr;
+ sd_emmc_reg->gcmd_arg = desc_cur->cmd_arg;
#endif
- //waiting end of chain
- while (1) {
- status_irq = sd_emmc_reg->gstatus;
- if (status_irq_reg->end_of_chain)
- break;
- }
-
- if (status_irq_reg->rxd_err)
- ret |= SD_EMMC_RXD_ERROR;
- if (status_irq_reg->txd_err)
- ret |= SD_EMMC_TXD_ERROR;
- if (status_irq_reg->desc_err)
- ret |= SD_EMMC_DESC_ERROR;
- if (status_irq_reg->resp_err)
- ret |= SD_EMMC_RESP_CRC_ERROR;
- if (status_irq_reg->resp_timeout)
- ret |= SD_EMMC_RESP_TIMEOUT_ERROR;
- if (status_irq_reg->desc_timeout)
- ret |= SD_EMMC_DESC_TIMEOUT_ERROR;
- if (data) {
- if ((data->blocks*data->blocksize <0x200) && (data->flags == MMC_DATA_READ)) {
- memcpy(data->dest, (const void *)sd_emmc_reg->gping,data->blocks*data->blocksize);
- }
- }
- /*we get response [0]:bit0~31
- * response [1]:bit32~63
- * response [2]:bit64~95
- * response [3]:bit96~127
- * actually mmc driver definition is:
- * response [0]:bit96~127
- * response [1]:bit64~95
- * response [2]:bit32~63
- * response [3]:bit0~31
- */
-
- if (cmd->resp_type & MMC_RSP_136) {
- cmd->response[0] = sd_emmc_reg->gcmd_rsp3;
- cmd->response[1] = sd_emmc_reg->gcmd_rsp2;
- cmd->response[2] = sd_emmc_reg->gcmd_rsp1;
- cmd->response[3] = sd_emmc_reg->gcmd_rsp0;
- } else {
- cmd->response[0] = sd_emmc_reg->gcmd_rsp0;
- }
-
-
- sd_debug("cmd->cmdidx = %d, cmd->cmdarg=0x%x, ret=0x%x\n",cmd->cmdidx,cmd->cmdarg,ret);
- sd_debug("cmd->response[0]=0x%x;\n",cmd->response[0]);
- sd_debug("cmd->response[1]=0x%x;\n",cmd->response[1]);
- sd_debug("cmd->response[2]=0x%x;\n",cmd->response[2]);
- sd_debug("cmd->response[3]=0x%x;\n",cmd->response[3]);
-
- if (ret) {
- if (status_irq_reg->resp_timeout)
- return TIMEOUT;
- else
- return ret;
- }
-
- return SD_NO_ERROR;
+ //waiting end of chain
+ while (1) {
+ status_irq = sd_emmc_reg->gstatus;
+ if (status_irq_reg->end_of_chain)
+ break;
+ }
+
+ if (status_irq_reg->rxd_err)
+ ret |= SD_EMMC_RXD_ERROR;
+ if (status_irq_reg->txd_err)
+ ret |= SD_EMMC_TXD_ERROR;
+ if (status_irq_reg->desc_err)
+ ret |= SD_EMMC_DESC_ERROR;
+ if (status_irq_reg->resp_err)
+ ret |= SD_EMMC_RESP_CRC_ERROR;
+ if (status_irq_reg->resp_timeout)
+ ret |= SD_EMMC_RESP_TIMEOUT_ERROR;
+ if (status_irq_reg->desc_timeout)
+ ret |= SD_EMMC_DESC_TIMEOUT_ERROR;
+ if (data) {
+ if ((data->blocks*data->blocksize <0x200) && (data->flags == MMC_DATA_READ)) {
+ memcpy(data->dest, (const void *)sd_emmc_reg->gping,data->blocks*data->blocksize);
+ }
+ }
+ /*we get response [0]:bit0~31
+ * response [1]:bit32~63
+ * response [2]:bit64~95
+ * response [3]:bit96~127
+ * actually mmc driver definition is:
+ * response [0]:bit96~127
+ * response [1]:bit64~95
+ * response [2]:bit32~63
+ * response [3]:bit0~31
+ */
+
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[0] = sd_emmc_reg->gcmd_rsp3;
+ cmd->response[1] = sd_emmc_reg->gcmd_rsp2;
+ cmd->response[2] = sd_emmc_reg->gcmd_rsp1;
+ cmd->response[3] = sd_emmc_reg->gcmd_rsp0;
+ } else {
+ cmd->response[0] = sd_emmc_reg->gcmd_rsp0;
+ }
+
+
+ sd_debug("cmd->cmdidx = %d, cmd->cmdarg=0x%x, ret=0x%x\n",cmd->cmdidx,cmd->cmdarg,ret);
+ sd_debug("cmd->response[0]=0x%x;\n",cmd->response[0]);
+ sd_debug("cmd->response[1]=0x%x;\n",cmd->response[1]);
+ sd_debug("cmd->response[2]=0x%x;\n",cmd->response[2]);
+ sd_debug("cmd->response[3]=0x%x;\n",cmd->response[3]);
+ if (des_cmd_cur->data_wr == 1) {
+ free(write_buffer);
+ write_buffer = NULL;
+ }
+ if (ret) {
+ if (status_irq_reg->resp_timeout)
+ return TIMEOUT;
+ else
+ return ret;
+ }
+
+ return SD_NO_ERROR;
}
int aml_sd_init(struct mmc *mmc)
diff --git a/drivers/mmc/emmc_partitions.c b/drivers/mmc/emmc_partitions.c
index 7aa9f55ae2..5da31456c5 100644
--- a/drivers/mmc/emmc_partitions.c
+++ b/drivers/mmc/emmc_partitions.c
@@ -471,30 +471,32 @@ int mmc_device_init (struct mmc *mmc)
return ret;
}
+
int find_dev_num_by_partition_name (char *name)
{
- int port=-1, dev_num;
- struct mmc *mmc;
+ int dev_num=-1;
+ //struct mmc *mmc;
if (!strncmp(name, MMC_CARD_PARTITION_NAME, sizeof(MMC_CARD_PARTITION_NAME))) { // card
- port = SDIO_PORT_B;
+ // port = SDIO_PORT_B;
+ dev_num = 0;
} else { // eMMC OR TSD
if (find_mmc_partition_by_name(name)) { // partition name is valid
- port = SDIO_PORT_C;
+ //port = SDIO_PORT_C;
+ dev_num = 1;
} // else port=-1
}
- if (port > 0) {
- mmc = find_mmc_device_by_port((unsigned)port);
- if (!mmc) { // not found
- dev_num = -1;
- } else {
- dev_num = mmc->block_dev.dev;
- }
- } else { // partition name is invalid
- dev_num = -1;
- }
- // printf("[%s] dev_num = %d\n", __FUNCTION__, dev_num);
+// if (port > 0) {
+// mmc = find_mmc_device_by_port((unsigned)port);
+// if (!mmc) { // not found
+// dev_num = -1;
+// } else {
+// dev_num = mmc->block_dev.dev;
+// }
+// } else { // partition name is invalid
+// dev_num = -1;
+// }
return dev_num;
}
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 3db9669c82..4e8655b43e 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -24,7 +24,7 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
end = (start + blkcnt - 1) * mmc->write_bl_len;
start *= mmc->write_bl_len;
}
-
+ printf("start = %lu,end = %lu\n",start,end);
if (IS_SD(mmc)) {
start_cmd = SD_CMD_ERASE_WR_BLK_START;
end_cmd = SD_CMD_ERASE_WR_BLK_END;
@@ -72,7 +72,10 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
if (!mmc)
return -1;
-
+ if (blkcnt == 0) {
+ blkcnt = mmc->capacity/512 - (mmc->capacity/512)% mmc->erase_grp_size; // erase whole
+ printf("blkcnt = %lu\n",blkcnt);
+ }
if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
printf("\n\nCaution! Your devices Erase group is 0x%x\n"
"The erase range would be change to "
@@ -82,7 +85,7 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
& ~(mmc->erase_grp_size - 1)) - 1);
while (blk < blkcnt) {
- blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
+ blk_r = ((blkcnt - blk) < mmc->erase_grp_size) ?
mmc->erase_grp_size : (blkcnt - blk);
err = mmc_erase_t(mmc, start + blk, blk_r);
if (err)
@@ -92,10 +95,10 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
/* Waiting for the ready status */
if (mmc_send_status(mmc, timeout))
- return 0;
+ return 1;
}
- return blk;
+ return 0;
}
static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
diff --git a/drivers/usb/gadget/v2_burning/Makefile b/drivers/usb/gadget/v2_burning/Makefile
new file mode 100644
index 0000000000..aa61f5a479
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/Makefile
@@ -0,0 +1,41 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+EXTRA_CFLAGS = -I./v2_common -I./v2_usb_tool -I./v2_sdc_burn
+
+obj-$(CONFIG_AML_V2_FACTORY_BURN) += aml_v2_burn.o
+
+aml_v2_burn-y = aml_v2_burning.o
+aml_v2_burn-y += v2_common/optimus_download.o v2_common/optimus_buffer_manager.o v2_common/optimus_simg2img.o
+aml_v2_burn-y += v2_common/optimus_progress.o v2_common/optimus_img_decoder.o v2_common/optimus_fat.o
+aml_v2_burn-y += v2_sdc_burn/optimus_sdc_update.o v2_sdc_burn/optimus_sdc_burn.o v2_sdc_burn/optimus_ini_parser.o
+aml_v2_burn-y += v2_sdc_burn/optimus_ini__aml_sdc_burn.o
+aml_v2_burn-y += v2_usb_tool/optimus_core.o v2_usb_tool/optimus_transform.o
+aml_v2_burn-y += v2_usb_burn/optimus_usb_burn.o v2_usb_burn/optimus_usb_update.o
+aml_v2_burn-$(CONFIG_UNIFY_KEY_MANAGE) += v2_common/optimus_download_key.o
+aml_v2_burn-$(CONFIG_SD_BURNING_SUPPORT_UI) += v2_common/optimus_progress_ui.o
+aml_v2_burn-$(CONFIG_SD_BURNING_SUPPORT_LED) += v2_sdc_burn/optimus_led.o
+aml_v2_burn-y += aml_sysrecovery/aml_sysrecovery.o
+aml_v2_burn-$(CONFIG_DETECT_SYS_RECOVERY_KEY) += aml_sysrecovery/cmd_detect_sys_recovery_key.o
+aml_v2_burn-$(CONFIG_SUPPORT_SDC_KEYBURN) += v2_sdc_burn/sdc_burnkeys/optimus_key_burn.o
+aml_v2_burn-$(CONFIG_SUPPORT_SDC_KEYBURN) += v2_sdc_burn/sdc_burnkeys/sdc_keysprovider.o v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.o
+
diff --git a/drivers/usb/gadget/v2_burning/aml_sysrecovery/aml_sysrecovery.c b/drivers/usb/gadget/v2_burning/aml_sysrecovery/aml_sysrecovery.c
new file mode 100644
index 0000000000..780cadf629
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/aml_sysrecovery/aml_sysrecovery.c
@@ -0,0 +1,196 @@
+/*
+ * \file sysrecovery.c
+ * \brief
+ *
+ * \version 1.0.0
+ * \date Friday,14/11/21
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2014 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+#include "../v2_sdc_burn/optimus_sdc_burn_i.h"
+#include "../v2_sdc_burn/optimus_led.h"
+
+#define CONFIG_AML_SYS_RECOVERY_CLEAR_USR_DATA 1
+
+static int optimus_sysrec_check_whole_img_before_burn(const char* partName)
+{
+ //TODO:
+ return 0;
+}
+
+#if CONFIG_AML_SYS_RECOVERY_CLEAR_USR_DATA
+//clear data parts then the parts will formatted when firtsboot
+//As fill half parttition need so much time, I just clear 2M
+static int optimus_sysrec_clear_usr_data_parts(void)
+{
+ const char* const _usrDataParts[] = {"data",};
+ const int dataPartsNum = sizeof(_usrDataParts)/sizeof(const char*);
+ const unsigned BufSz = 1U<<20;//1MB
+ unsigned char* clearBuf= (unsigned char*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ int partIndex = 0;
+ int ret = 0;
+
+ memset(clearBuf, 0xff, BufSz);
+ for (partIndex = 0; partIndex < dataPartsNum; ++partIndex)
+ {
+ u64 partCap = 0;
+ unsigned char* thePart = (unsigned char*)_usrDataParts[partIndex];
+ int rcode = 0;
+ u64 offset = 0;
+ u64 ClearSz = 2U<<20;
+
+ DWN_MSG("To clear data part[%s]\n", thePart);
+ rcode = store_get_partititon_size(thePart, &partCap);
+ if (rcode) {
+ DWN_ERR("Fail to get partSz for part[%s]\n", thePart);
+ return rcode;
+ }
+ partCap <<= 9;
+ //FIXME: If there is fschk before firstboot, the 2MB to destroy the data if not enough
+ /*ClearSz = partCap>>1;*/
+ DWN_MSG("partCap 0x%llxMB, ClearSz=%llxMb\n", (partCap>>20), (ClearSz>>20));
+
+ for (; offset < ClearSz; offset += BufSz)
+ {
+ rcode = store_write_ops(thePart, clearBuf, offset, BufSz);
+ if (rcode) {
+ DWN_ERR("Failed when clear data part[%s], rcode=%d\n", thePart, rcode);
+ ret += rcode;
+ }
+ }
+ }
+
+ return ret;
+}
+#endif//#if CONFIG_AML_SYS_RECOVERY_CLEAR_USR_DATA
+
+/*
+ *.partName: aml_sysrecovery
+ *.needVerify: 1 then verify partitions that contain verify file; 0 then not to verify for faster burning
+ */
+static int optimus_sysrec_burn_package_from_partition(const char* partName, const unsigned needVerifyWhileBurn,
+ const unsigned verifyPackageBeforeBurn)
+{
+ extern ConfigPara_t g_sdcBurnPara ;
+ ConfigPara_t* pSdcCfgPara = &g_sdcBurnPara;
+ __hdle hUiProgress = NULL;
+ HIMAGE hImg = NULL;
+ int ret = 0;
+
+ ret = optimus_storage_init(0);//Init all partitions for burning
+
+ if (verifyPackageBeforeBurn)
+ {
+ ret = optimus_sysrec_check_whole_img_before_burn(partName);
+ if (ret) {
+ DWN_ERR("Failed in crc check the burning package.\n");
+ return __LINE__;
+ }
+ }
+
+ hImg = image_open("store", "0", AML_SYS_RECOVERY_PART, "");
+ if (!hImg) {
+ DWN_ERR("Fail to open image in part %s\n", AML_SYS_RECOVERY_PART);
+ ret = __LINE__; goto _finish;
+ }
+
+ if (video_res_prepare_for_upgrade(hImg)) {
+ DWN_ERR("Fail when prepare bm res or init video for upgrade\n");
+ ret = __LINE__; goto _finish;
+ }
+ show_logo_to_report_burning();
+
+ hUiProgress = optimus_progress_ui_request_for_sdc_burn();
+ if (!hUiProgress) {
+ DWN_ERR("request progress handle failed!\n");
+ ret = __LINE__; goto _finish;
+ }
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STEPS_AFTER_DISK_INIT_OK);
+
+ int hasBootloader = 0;
+ u64 datapartsSz = optimus_img_decoder_get_data_parts_size(hImg, &hasBootloader);
+ DWN_MSG("datapartsSz=[%8u]MB\n", (unsigned)(datapartsSz >> 20));
+ ret = optimus_progress_ui_set_smart_mode(hUiProgress, datapartsSz,
+ UPGRADE_STEPS_FOR_BURN_DATA_PARTS_IN_PKG(!pSdcCfgPara->burnEx.bitsMap.mediaPath));
+ if (ret) {
+ DWN_ERR("Fail to set smart mode\n");
+ ret = __LINE__; goto _finish;
+ }
+
+ pSdcCfgPara->burnParts.burn_num = 0;
+ ret = optimus_sdc_burn_partitions(pSdcCfgPara, hImg, hUiProgress, needVerifyWhileBurn);
+ if (ret) {
+ DWN_ERR("Fail when burn partitions\n");
+ ret = __LINE__; goto _finish;
+ }
+
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK);
+
+#if CONFIG_AML_SYS_RECOVERY_CLEAR_USR_DATA
+ optimus_sysrec_clear_usr_data_parts();
+#endif// #if CONFIG_AML_SYS_RECOVERY_CLEAR_USR_DATA
+#if 1
+ if (hasBootloader)
+ {//burn bootloader
+ ret = optimus_burn_bootlader(hImg);
+ if (ret) {
+ DWN_ERR("Fail in burn bootloader\n");
+ goto _finish;
+ }
+ ret = optimus_set_burn_complete_flag();
+ if (ret) {
+ DWN_ERR("Fail in set_burn_complete_flag\n");
+ ret = __LINE__; goto _finish;
+ }
+ }
+#endif
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STEPS_AFTER_BURN_BOOTLOADER_OK);
+
+_finish:
+ image_close(hImg);
+ optimus_progress_ui_report_upgrade_stat(hUiProgress, !ret);
+ optimus_report_burn_complete_sta(ret, 1/*pSdcCfgPara->custom.rebootAfterBurn*/);
+ optimus_progress_ui_release(hUiProgress);
+ //optimus_storage_exit();//temporary not exit storage driver when failed as may continue burning after burn
+ return ret;
+}
+
+static int do_aml_sysrecovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ unsigned needVerify = (1 < argc) ? simple_strtoul(argv[1], NULL, 0) : 0;
+ unsigned verifyPackageBeforeBurn = (2 < argc) ? simple_strtoul(argv[2], NULL, 0) : 0;
+
+ if (argc < 2 ) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+
+ show_logo_to_report_burning();//indicate enter flow of burning! when 'run update'
+ if (optimus_led_open(LED_TYPE_PWM)) {
+ DWN_ERR("Fail to open led for burn\n");
+ return __LINE__;
+ }
+ optimus_led_show_in_process_of_burning();
+
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_SYS_RECOVERY);
+ rcode = optimus_sysrec_burn_package_from_partition(AML_SYS_RECOVERY_PART, needVerify, verifyPackageBeforeBurn);
+
+ return rcode;
+}
+
+U_BOOT_CMD(
+ aml_sysrecovery, //command name
+ 3, //maxargs
+ 0, //repeatable
+ do_aml_sysrecovery, //command function
+ "Burning with amlogic format package from partition sysrecovery", //description
+ "argv: needVerify [,checkWholeImgBeforeBurn]\n"//usage
+ " --@needVerify: 0 then skip to verify the partition even have verify file."
+ " --@checkWholeImgBeforeBurn: 1 then crc32 check the burn package in partition sysrecovery before actual burn"
+ " eg:'aml_sysrecovery 0': burn from partition aml_sysrecovery without verify"
+);
+
diff --git a/drivers/usb/gadget/v2_burning/aml_sysrecovery/cmd_detect_sys_recovery_key.c b/drivers/usb/gadget/v2_burning/aml_sysrecovery/cmd_detect_sys_recovery_key.c
new file mode 100644
index 0000000000..0a33f97a24
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/aml_sysrecovery/cmd_detect_sys_recovery_key.c
@@ -0,0 +1,108 @@
+/*
+ * \file cmd_detect_sys_recovery_key.c
+ * \brief Detect whether user want to enter sys_recovery
+ *
+ * \version 1.0.0
+ * \date 14/11/25
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2014 Amlogic. All Rights Reserved.
+ *
+ */
+#include <config.h>
+#include <common.h>
+#include <asm/arch/io.h>
+#include <command.h>
+#include <malloc.h>
+#include <amlogic/gpio.h>
+
+#define debugP(fmt...) //printf("L%d:", __LINE__),printf(fmt)
+#define errorP(fmt...) printf("[ERR]L%d:", __LINE__),printf(fmt)
+#define MsgP(fmt...) printf("[msg]"fmt)
+
+static int store_key_open(const char* keyName, const char* keyType)
+{
+ int pin = -1;
+
+ pin=gpioname_to_pin(keyName);
+ if (pin<0) {
+ errorP("wrong gpio name %s\n",keyName);
+ return -1;
+ }
+ udelay(100);
+
+ return pin;
+}
+
+static int is_sys_recovery_key_pressed(int hKey)
+{
+ int val = -1;
+
+ val=amlogic_get_value(hKey);
+
+ return val != 1;
+}
+
+static int assert_key_is_pressed_in_a_period(unsigned nMillSeconds, const char* keyName, const char* keyType)
+{
+ unsigned start = 0;
+ int hKey = -1;
+
+ hKey = store_key_open(keyName, keyType);
+ if (hKey < 0) {
+ errorP("Fail to init key for aml_sysrecovery, hKey=%d\n", hKey);
+ return __LINE__;
+ }
+
+ if (!is_sys_recovery_key_pressed(hKey)) {
+ return __LINE__;
+ }
+
+ MsgP("pin=%d\n",hKey);
+ start = get_timer(0);
+ while (is_sys_recovery_key_pressed(hKey))
+ {
+ const unsigned pressTime = (unsigned)get_timer(start) ;
+ if (pressTime > nMillSeconds) {
+ MsgP("store key pressed time %d[ms]\n", pressTime);
+ return 0;
+ }
+ }
+ if (!is_sys_recovery_key_pressed(hKey)) {
+ MsgP("key released in time %u[ms]\n", (unsigned)get_timer(start));
+ return __LINE__;
+ }
+
+ return 1;//restore key released in time @nMillSeconds
+}
+
+//test If the recovery_key pressed time >= @nMillSeconds
+int do_sys_rec_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ unsigned nMillSeconds = 0;
+ const char* keyName = NULL;
+ const char* keyType = "gpio";
+
+ if (2 > argc) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+
+ nMillSeconds = simple_strtoul(argv[1], NULL, 0);
+ keyName = argc > 2 ? argv[2] :"GPIOX_16";
+ rcode = assert_key_is_pressed_in_a_period(nMillSeconds, keyName, keyType);
+
+ return rcode;
+}
+
+
+U_BOOT_CMD(
+ get_restore_key, //command name
+ 5, //maxargs
+ 1, //repeatable
+ do_sys_rec_key, //command function
+ "check if user press sys_recovery key", //description
+ "Usage: sys_recovery nMillSeconds [GPIOX_16] [key_type]\n" //usage
+);
+
diff --git a/drivers/usb/gadget/v2_burning/aml_v2_burning.c b/drivers/usb/gadget/v2_burning/aml_v2_burning.c
new file mode 100644
index 0000000000..f8b19c30bc
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/aml_v2_burning.c
@@ -0,0 +1,161 @@
+/*
+ * \file aml_v2_burning.c
+ * \brief common interfaces for version 2 burning
+ *
+ * \version 1.0.0
+ * \date 09/15/2013
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "v2_burning_i.h"
+#include <mmc.h>
+#include <asm/arch/secure_apb.h>
+#include <asm/arch/io.h>
+
+#ifndef BOOT_DEVICE_USB
+#define BOOT_DEVICE_SD 4
+#define BOOT_DEVICE_USB 5
+#endif// #ifndef BOOT_DEVICE_USB
+
+extern int v2_usbburning(unsigned timeout);
+extern int optimus_burn_package_in_sdmmc(const char* sdc_cfg_file);
+extern void close_usb_phy_clock(int cfg);
+
+//check ${sdcburncfg} exist in external mmc and internal flash not burned yet!
+static int aml_check_is_ready_for_sdc_produce(void)
+{
+ char* sdc_cfg_file = NULL;
+ const char* cmd = NULL;
+ int ret = 0;
+
+ //if reboot_mode is MESON_SDC_BURNER_REBOOT, then this booting is skip_booted for sdc_burning
+ if (/*MESON_SDC_BURNER_REBOOT != reboot_mode*/ 0) {
+ /*DWN_MSG("reboot_mode=0x%x\n", (unsigned int)reboot_mode);*/
+ return 1;//not ready
+ }
+
+ cmd = "mmcinfo 0";
+ ret = run_command(cmd, 0);
+ if (ret) {
+ DWN_MSG("mmcinfo failed!\n");
+ return 0;//not ready
+ }
+
+ sdc_cfg_file = getenv("sdcburncfg");
+ if (!sdc_cfg_file) {
+ sdc_cfg_file = "aml_sdc_burn.ini";
+ setenv("sdcburncfg", sdc_cfg_file);
+ }
+
+ cmd = "fatexist mmc 0 ${sdcburncfg}";
+ ret = run_command(cmd, 0);
+ if (ret) {
+ DWN_DBG("%s not exist in external mmc\n", sdc_cfg_file);
+ return 0;
+ }
+
+ return 1;//is ready for sdcard producing
+}
+
+static unsigned _get_romcode_boot_id(void)
+{
+ DWN_DBG("P_AO_SEC_GP_CFG0=0x%p\n", P_AO_SEC_GP_CFG0);
+ const unsigned boot_id = readl(P_AO_SEC_GP_CFG0) & 0xf;
+
+ DWN_DBG("boot_id()=%x\n", boot_id);
+ return boot_id;
+}
+
+//is the uboot loaded from usb otg
+int is_tpl_loaded_from_usb(void)
+{
+ return (BOOT_DEVICE_USB == _get_romcode_boot_id());
+}
+
+//is the uboot loaded from sdcard mmc 0
+//note only sdmmc supported by romcode when external device boot
+int is_tpl_loaded_from_ext_sdmmc(void)
+{
+ return (BOOT_DEVICE_SD == _get_romcode_boot_id());
+}
+
+//Check if uboot loaded from external sdmmc or usb otg
+int aml_burn_check_uboot_loaded_for_burn(int flag)
+{
+ int usb_boot = is_tpl_loaded_from_usb();
+ int sdc_boot = is_tpl_loaded_from_ext_sdmmc();
+
+ return usb_boot || sdc_boot;
+}
+
+//1, is booted from external sdmmc: check if aml_sdc_burn.ini existed
+//2, if loaded from usb, ready for burn
+int aml_burn_check_is_ready_for_burn(int flag, bd_t* bis)
+{
+ if (is_tpl_loaded_from_usb()) {
+ return 1;
+ }
+
+ if (is_tpl_loaded_from_ext_sdmmc())
+ {
+ return aml_check_is_ready_for_sdc_produce();
+ }
+
+ return 0;
+}
+
+//producing mode means boot from raw flash, i.e, uboot is loaded from usb
+int aml_burn_usb_producing(int flag, bd_t* bis)
+{
+ flag = flag; bis = bis;//avoid compile warning
+
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_USB_PRODUCE);
+
+ close_usb_phy_clock(0);//disconect before re-connect to enhance pc compatibility
+ return v2_usbburning(20000);
+}
+
+int aml_burn_sdc_producing(int flag, bd_t* bis)
+{
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_SDC_PRODUCE);
+
+ return optimus_burn_package_in_sdmmc(getenv("sdcburncfg"));
+}
+
+//burning flash from romboot stage
+int aml_burn_factory_producing(int flag, bd_t* bis)
+{
+ if (is_tpl_loaded_from_usb())
+ {
+ return aml_burn_usb_producing(flag, bis);
+ }
+
+ if (is_tpl_loaded_from_ext_sdmmc())
+ {
+ return aml_burn_sdc_producing(flag, bis);
+ }
+
+ DWN_ERR("Shouldnot reach here!\n");
+ return 0;
+}
+
+int aml_try_factory_usb_burning(int flag, bd_t* bis)
+{
+ if (!is_tpl_loaded_from_usb()) return 1;
+
+#ifdef CONFIG_GENERIC_MMC
+ DWN_MSG("MMC init in usb\n");
+ mmc_initialize(bis);
+#endif
+ return aml_burn_usb_producing(flag, bis);
+}
+
+int aml_try_factory_sdcard_burning(int flag, bd_t* bis)
+{
+ if (!is_tpl_loaded_from_ext_sdmmc()) return 1;
+
+ return aml_burn_sdc_producing(flag, bis);
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_burning_i.h b/drivers/usb/gadget/v2_burning/v2_burning_i.h
new file mode 100644
index 0000000000..97eb21e576
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_burning_i.h
@@ -0,0 +1,41 @@
+/*
+ * \file v2_burning_i.h
+ * \brief internal include interfaces
+ *
+ * \version 1.0.0
+ * \date 2013/11/4
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+
+#ifndef __V2_BURNING_I_H__
+#define __V2_BURNING_I_H__
+
+#include <common.h>
+#include <environment.h>
+#include <asm/string.h>
+#include <asm-generic/errno.h>
+#include <asm/byteorder.h>
+#include <malloc.h>
+#include <u-boot/sha1.h>
+
+#ifdef CONFIG_MESON_TRUSTZONE
+#include <asm/arch/trustzone.h>
+#endif//#ifdef CONFIG_MESON_TRUSTZONE
+
+#include <amlogic/aml_v2_burning.h>
+//#include <asm/arch/reboot.h>
+#include <asm/arch/romboot.h>
+//#include <amlogic/aml_lcd.h>
+#include <amlogic/storage_if.h>
+#include "v2_common/sparse_format.h"
+#include "v2_common/optimus_download.h"
+#include "v2_common/amlImage_if.h"
+#include "v2_common/optimus_progress_ui.h"
+
+extern int cli_simple_parse_line(char *line, char *argv[]);
+
+#endif//ifndef __V2_BURNING_I_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/amlImage_if.h b/drivers/usb/gadget/v2_burning/v2_common/amlImage_if.h
new file mode 100644
index 0000000000..15373c139e
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/amlImage_if.h
@@ -0,0 +1,124 @@
+/* * \file amlImage_if.h
+ * \brief Amlogic firmware image interface
+ *
+ * \version 1.0.0
+ * \date 2013/5/21
+ * \author Sam.Wu <yihui.wu@Amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc. All Rights Reserved.
+ *
+ */
+#ifndef __AMLIMAGE_IF_H__
+#define __AMLIMAGE_IF_H__
+
+#define IMAGE_MAGIC 0x27b51956 /* Image Magic Number */
+
+#define AML_FRMWRM_VER_V1 0X01
+#define AML_FRMWRM_VER_V2 0X02
+#define ITEM_NAME_LEN_V1 0X20
+#define ITEM_NAME_LEN_V2 0X100
+
+typedef void* __hdle;
+
+#pragma pack(push,4)
+typedef struct _AmlFirmwareItem_s
+{
+ __u32 itemId;
+ __u32 fileType; //image file type, sparse and normal
+ __u64 curoffsetInItem; //current offset in the item
+ const __u64 offsetInImage; //item offset in the image
+ const __u64 itemSz; //item size in the image
+ char itemMainType[ITEM_NAME_LEN_V1]; //item main type and sub type used to index the item
+ char itemSubType[ITEM_NAME_LEN_V1]; //item main type and sub type used to index the item
+ char reserve[32];//don't care fields
+}ItemInfo_V1;
+#pragma pack(pop)
+
+#pragma pack(push,4)
+typedef struct _AmlFirmwareItem2_s
+{
+ __u32 itemId;
+ __u32 fileType; //image file type, sparse and normal
+ __u64 curoffsetInItem; //current offset in the item
+ const __u64 offsetInImage; //item offset in the image
+ const __u64 itemSz; //item size in the image
+ char itemMainType[ITEM_NAME_LEN_V2]; //item main type and sub type used to index the item
+ char itemSubType[ITEM_NAME_LEN_V2]; //item main type and sub type used to index the item
+ char reserve[32];//don't care fields
+}ItemInfo_V2;
+#pragma pack(pop)
+
+#pragma pack(push,4)
+typedef struct _AmlFirmwareImg_s
+{
+ __u32 crc; //check sum of the image
+ __u32 version; //firmware version
+ __u32 magic; //magic No. to say it is Amlogic firmware image
+ __u64 imageSz; //total size of this image file
+ __u32 itemAlginSize; //align size for each item
+ __u32 itemNum; //item number in the image, each item a file
+ char reserve[36];
+}AmlFirmwareImg_t;
+#pragma pack(pop)
+
+
+typedef void* HIMAGE;
+typedef void* HIMAGEITEM;
+
+#define IMAGE_ITEM_TYPE_NORMAL 0
+#define IMAGE_ITEM_TYPE_SPARSE 0XFE
+
+enum {
+ IMAGE_IF_TYPE_MMC = 0XEE, //read amlogic burning package from 'mmc 0/1'
+ IMAGE_IF_TYPE_USB , //read amlogic burning package from 'usb 0'
+ IMAGE_IF_TYPE_STORE , //read amlogic burning package using store interface
+};
+
+#define IMG_OFFSET_IN_PART 0
+
+//open a Amlogic firmware image
+//return value is a handle
+HIMAGE image_open(const char* interface, const char* device, const char* part, const char* imgPath);
+
+//check the image's crc32
+//return 0 when check ok,otherwise return -1
+int image_check(HIMAGE hImg);
+
+//close a Amlogic firmware image
+int image_close(HIMAGE hImg);
+
+//get item count of specify main type
+int image_get_item_count(HIMAGE hImg, const char* mainType);
+
+//open a item in the image
+//@hImage: image handle;
+//@mainType, @subType: main type and subtype to index the item, such as ["IMAGE", "SYSTEM"]
+HIMAGEITEM image_item_open(HIMAGE hImg, const char* mainType, const char* subType);
+
+//close a item
+int image_item_close(HIMAGEITEM hItem);
+
+__u64 image_item_get_size(HIMAGEITEM hItem);
+
+
+//get image item type, current used type is normal or sparse
+int image_item_get_type(HIMAGEITEM hItem);
+
+//read item data, like standard fread
+int image_item_read(HIMAGE hImg, HIMAGEITEM hItem, void* pBuf, const __u32 wantSz);
+
+//relocate the read pointer to read the item data, like standard fseek
+int image_item_seek(HIMAGE , HIMAGEITEM , __s64 , __u32 );
+
+unsigned image_item_get_first_cluster_size(HIMAGE hImg, HIMAGEITEM hItem);
+unsigned image_get_cluster_size(HIMAGEITEM hImg);//Assert read offset and read size is multiple size of thsi unit
+
+int get_item_name(HIMAGE hImg, int itemId, const char** main_type, const char** sub_type);
+
+int get_total_itemnr(HIMAGE hImg);
+
+u64 optimus_img_decoder_get_data_parts_size(HIMAGE hImg, int* hasBootloader);
+
+
+#endif//ifndef __AMLIMAGE_IF_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_buffer_manager.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_buffer_manager.c
new file mode 100644
index 0000000000..71b533fc59
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_buffer_manager.c
@@ -0,0 +1,320 @@
+/*
+ * \file optimus_buffer_manager.c
+ * \brief buffer manager for download data: A thin layer between receiving partition data and writing flash
+ *
+ * \version 1.0.0
+ * \date 2013/5/2
+ * \author Sam.Wu <yihui.wu@Amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+
+#define OPTIMUS_SLOT_STA_FREE (0)//buffer slot not used yet
+#define OPTIMUS_SLOT_STA_USED (0xee)//buffer slot current used for download
+#define OPTIMUS_SLOT_STA_LEFT (0xdd)//buffer slot not disposed over
+
+#define PKT_TRANSFER_STA_EMPTY 0
+#define PKT_TRANSFER_STA_WORKING 1
+#define PKT_TRANSFER_STA_END 2
+
+typedef struct bufManager{
+ const u8* transferBuf;//transfer buffer address
+ const u32 transferBufSz;//transfer buffer size to
+
+ const u32 transferUnitSz;//64k
+ u32 writeBackUnitSz;//for NAND is transferSz, for sparse is transferUnitSz
+
+ u64 tplcmdTotalSz;//total size of a file-system packet
+
+ u32 totalSlotNum;//total slot number that already tranfferred
+ u32 mediaAlignSz;//nand write align size, 16K/32k
+
+ u32 nextWriteBackSlot;//when reach n* (writeBackUnitSz/transferUnitSz), then write back the recevied data to media
+ u32 leftDataSz;//left data size, Assert that 'leftDataInBackBuf + leftDataSz == transferBuf'
+
+ s16 isUpload;
+ s16 pktTransferSta;
+ u32 destMediaType;
+
+ u32 partBaseOffset;//TODO: change it to memory address when dest media type is memory
+ u32 itemOffsetNotAlignClusterSz_f;//For sdcard burning, item offset of aml_upgrade_package.img is not aligned to bytespercluster of FAT fs(_f means not changed inited)
+
+}BufManager;
+
+//TODO: if want to speed-up such as soft PING-PONG buffer, use multiple BufManager
+static BufManager _bufManager =
+{
+//constant members
+ .transferBuf = (const u8*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR,
+ .transferBufSz = OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ,
+ .transferUnitSz = OPTIMUS_DOWNLOAD_SLOT_SZ,
+
+//different for each command, note a command corresponding to a download file
+//must create/destroy for a command
+ .writeBackUnitSz = OPTIMUS_DOWNLOAD_SLOT_SZ,
+
+ .totalSlotNum = 0,//not slot data recevied yet!
+
+ .leftDataSz = 0,
+ .tplcmdTotalSz = 0,
+ .nextWriteBackSlot = 0,//always 0 when upload??
+
+ .isUpload = 0,
+ .pktTransferSta = PKT_TRANSFER_STA_EMPTY,
+
+ .itemOffsetNotAlignClusterSz_f = 0,
+};
+
+int optimus_buf_manager_init(const unsigned mediaAlignSz)
+{
+ if (OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR != (uint64_t)_bufManager.transferBuf) {
+ DWN_ERR("Fatal fail in init-express, init here instead!\n");
+ return OPT_DOWN_FAIL;
+ }
+ _bufManager.mediaAlignSz = mediaAlignSz;
+
+ DWN_DBG("transfer=0x%p, transferBufSz=0x%x, transferUnitSz=0x%x, writeBackUnitSz=0x%x, totalSlotNum=%d\n", _bufManager.transferBuf,
+ _bufManager.transferBufSz, _bufManager.transferUnitSz, _bufManager.writeBackUnitSz, _bufManager.totalSlotNum);
+
+ return OPT_DOWN_OK;
+}
+
+int optimus_buf_manager_exit(void)
+{
+ return 0;
+}
+
+int optimus_buf_manager_tplcmd_init(const char* mediaType, const char* partName, const u64 partBaseOffset,
+ const char* imgType, const u64 pktTotalSz, const int isUpload,
+ const unsigned itemSizeNotAligned /* if item offset 3 and bytepercluste 4k, then it's 4k -3 */)
+{
+ u32 writeBackUnitSz = OPTIMUS_VFAT_IMG_WRITE_BACK_SZ;
+ const u64 pktSz4BufManager = pktTotalSz - itemSizeNotAligned;
+
+ if (!strcmp("sparse", imgType)
+ || itemSizeNotAligned/* use max memory if item 'itemOffset % bytespercluster != 0'*/)
+ {
+ writeBackUnitSz = OPTIMUS_SIMG_WRITE_BACK_SZ;
+ }
+
+ if (!strcmp("bootloader", partName))
+ {
+ if (pktSz4BufManager > _bufManager.transferBufSz) {
+ DWN_ERR("packet size 0x%x too large, max is 0x%x\n", (u32)pktSz4BufManager, _bufManager.transferBufSz);
+ return OPT_DOWN_FAIL;
+ }
+ /*writeBackUnitSz = OPTIMUS_BOOTLOADER_MAX_SZ;*/
+ writeBackUnitSz = pktSz4BufManager + _bufManager.transferUnitSz - 1;
+ writeBackUnitSz >>= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+ writeBackUnitSz <<= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+ }
+
+ _bufManager.destMediaType = OPTIMUS_MEDIA_TYPE_STORE;
+ if (!strcmp("mem", mediaType))
+ {
+ writeBackUnitSz = pktSz4BufManager + _bufManager.transferUnitSz - 1;
+ writeBackUnitSz >>= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+ writeBackUnitSz <<= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+
+ _bufManager.destMediaType = OPTIMUS_MEDIA_TYPE_MEM;
+
+ if (partBaseOffset>>32) {
+ DWN_ERR("partBaseOffset 0x%llx more than 4G!!\n", partBaseOffset);
+ return OPT_DOWN_FAIL;
+ }
+ _bufManager.partBaseOffset = (u32)partBaseOffset;
+ }
+
+ if (_bufManager.transferBufSz < writeBackUnitSz && strcmp("mem", mediaType)) {
+ DWN_ERR("write back size 0x%x > max size 0x%x\n", writeBackUnitSz, _bufManager.transferBufSz);
+ return OPT_DOWN_FAIL;
+ }
+ if (_bufManager.transferUnitSz > writeBackUnitSz) {
+ DWN_ERR("write back size %d < align size %d\n", writeBackUnitSz, _bufManager.mediaAlignSz);
+ return OPT_DOWN_FAIL;
+ }
+ DWN_DBG("writeBackUnitSz = 0x%x, pktSz4BufManager = %lld\n", writeBackUnitSz, pktSz4BufManager);
+
+ _bufManager.writeBackUnitSz = writeBackUnitSz;
+ _bufManager.totalSlotNum = 0;
+ _bufManager.isUpload = isUpload;
+ _bufManager.pktTransferSta = PKT_TRANSFER_STA_EMPTY;
+
+ if (_bufManager.isUpload)
+ {
+ _bufManager.nextWriteBackSlot = 0;//always 0 if upload
+ }
+ else//has write back if download
+ {
+ if (pktSz4BufManager < writeBackUnitSz)
+ {
+ _bufManager.nextWriteBackSlot = ((u32)pktSz4BufManager + _bufManager.transferUnitSz - 1)/_bufManager.transferUnitSz;//first slot index to write back to media
+ }
+ else
+ {
+ _bufManager.nextWriteBackSlot = writeBackUnitSz/_bufManager.transferUnitSz;//first slot index to write back to media
+ }
+
+ }
+
+ _bufManager.itemOffsetNotAlignClusterSz_f = itemSizeNotAligned;
+ _bufManager.leftDataSz = itemSizeNotAligned;//data size in the buffer that not write back to media yet in previous transfer
+ _bufManager.tplcmdTotalSz = pktSz4BufManager;
+
+ optimus_progress_init((u32)(_bufManager.tplcmdTotalSz>>32), (u32)_bufManager.tplcmdTotalSz, 0, 100);
+ DWN_MSG("totalSlotNum = %d, nextWriteBackSlot %d\n", _bufManager.totalSlotNum, _bufManager.nextWriteBackSlot);
+
+ return OPT_DOWN_OK;
+}
+
+int optimus_buf_manager_get_buf_for_bulk_transfer(char** pBuf, const unsigned wantSz, const unsigned sequenceNo, char* errInfo)
+{
+ const unsigned totalSlotNum = _bufManager.totalSlotNum;
+ const u64 totalTransferSz = ((u64)totalSlotNum) * _bufManager.transferUnitSz;//data size already transferred
+ const u64 leftPktSz = (totalTransferSz > _bufManager.tplcmdTotalSz) ? 0 :(_bufManager.tplcmdTotalSz - totalTransferSz);
+ const int isLastTransfer = (leftPktSz == wantSz);//totalTransferSz + wantSz >= _bufManager.tplcmdTotalSz;
+ const u32 bufSzNotDisposed = ((u32)totalTransferSz)% _bufManager.writeBackUnitSz;//buffer data not disposed, bufSz is always writeBackUnitSz
+ const u8* BufBase = (OPTIMUS_MEDIA_TYPE_MEM != _bufManager.destMediaType) ? _bufManager.transferBuf :
+ (u8*)(u64)_bufManager.partBaseOffset ;
+
+ if (wantSz < _bufManager.transferUnitSz && !isLastTransfer) {
+ DWN_ERR("only last transfer can less 64K, this index %d at size 0x%u illegle\n", totalSlotNum + 1, wantSz);
+ return OPT_DOWN_FAIL;
+ }
+
+ //TODO: totalSlotNum + 1 == sequenceNo
+ if (totalSlotNum + 1 != sequenceNo) {//ASSERT it ??
+
+ }
+
+ *pBuf = (char*)(bufSzNotDisposed + BufBase);
+ DWN_DBG("bufSzNotDisposed 0x%x, _bufManager.transferBuf 0x%p, _bufManager.partBaseOffset 0x%x, *pBuf 0x%p\n",
+ bufSzNotDisposed, _bufManager.transferBuf, _bufManager.partBaseOffset, *pBuf);
+
+ _bufManager.pktTransferSta = PKT_TRANSFER_STA_WORKING;
+
+ //prepare data for upload
+ if (!bufSzNotDisposed && _bufManager.isUpload)
+ {
+ u32 wantSz = (leftPktSz > _bufManager.writeBackUnitSz) ? _bufManager.writeBackUnitSz : ((u32)leftPktSz);
+ DWN_DBG("want size 0x%x\n", wantSz);
+
+ u32 readSz = optimus_dump_storage_data((u8*)BufBase, wantSz, errInfo);
+ if (readSz != wantSz) {
+ DWN_ERR("Want read %u, but %u\n", wantSz, readSz);
+ return OPT_DOWN_FAIL;
+ }
+ }
+
+ return OPT_DOWN_OK;
+}
+
+int optimus_buf_manager_report_transfer_complete(const u32 transferSz, char* errInfo)
+{
+ const unsigned totalSlotNum = _bufManager.totalSlotNum;
+ const u64 totalTransferSz = ((u64)totalSlotNum) * _bufManager.transferUnitSz + transferSz;
+ const u64 leftPktSz = (totalTransferSz > _bufManager.tplcmdTotalSz) ? 0 :(_bufManager.tplcmdTotalSz - totalTransferSz);
+ const u32 thisWriteBackSz = (_bufManager.transferUnitSz == transferSz) ? _bufManager.writeBackUnitSz : ((u32)totalTransferSz % _bufManager.writeBackUnitSz);
+ const u8* BufBase = (OPTIMUS_MEDIA_TYPE_MEM != _bufManager.destMediaType) ? _bufManager.transferBuf :
+ (u8*)(u64)_bufManager.partBaseOffset ;
+
+ DWN_DBG("transferSz=0x%x\n", transferSz);
+ //state fileds to update
+ _bufManager.totalSlotNum += 1;
+ if (_bufManager.totalSlotNum == _bufManager.nextWriteBackSlot)
+ {
+ u32 burnSz = 0;
+ u32 leftSz = _bufManager.leftDataSz;//data size not write to media in previous write back, > 0 only when not normal packet
+ const u32 size = leftSz + thisWriteBackSz;
+ const u8* data = (u8*)BufBase -leftSz;
+ const unsigned reserveNotAlignSz = leftPktSz ? _bufManager.itemOffsetNotAlignClusterSz_f : 0;//reserve
+
+ //call cb function to write to media
+ DWN_DBG("size 0x%x, reserveNotAlignSz 0x%x\n", size, reserveNotAlignSz);
+ burnSz = optimus_download_img_data(data, size - reserveNotAlignSz, errInfo);
+ if (burnSz <= leftSz || !burnSz) {
+ DWN_ERR("this burn size %d <= last left size %d, data 0x%p\n", burnSz, leftSz, data);
+ return OPT_DOWN_FAIL;
+ }
+ if (size - reserveNotAlignSz < burnSz) {
+ DWN_ERR("Exception:siz 0x%x < burnSz 0x%x\n", size - reserveNotAlignSz, burnSz);
+ return OPT_DOWN_FAIL;
+ }
+
+ leftSz = size - burnSz;
+ if (leftSz)
+ {
+ const u8* src = data + burnSz;
+ u8* dest = (u8*)BufBase - leftSz;
+
+ if (totalTransferSz >= _bufManager.tplcmdTotalSz) {
+ DWN_ERR("Exception:packet end but data left 0x%x, totalTransferSz 0x%llx, cmd sz 0x%llx!\n",
+ leftSz, totalTransferSz, _bufManager.tplcmdTotalSz);
+ return OPT_DOWN_FAIL;
+ }
+
+ if (leftSz > OPTIMUS_SPARSE_IMG_LEFT_DATA_MAX_SZ) {
+ DWN_ERR("Exception, left data sz 0x%x > back buf sz 0x%x!\n", leftSz, OPTIMUS_SPARSE_IMG_LEFT_DATA_MAX_SZ);
+ return OPT_DOWN_FAIL;
+ }
+ if (leftSz & 0x03) {
+ DWN_ERR("Exception, copy size not align to 4! May will copy fail!\n");
+ return OPT_DOWN_FAIL;
+ }
+
+ DWN_DBG("MV:left size 0x%08x, src %p, dest %p\n", leftSz, src, dest);
+ memcpy(dest, src, leftSz);
+ }
+
+ //update _bufManager.leftDataSz and _bufManager.nextWriteBackSlot
+ _bufManager.leftDataSz = leftSz;
+ if (leftPktSz >= _bufManager.writeBackUnitSz)
+ {
+ _bufManager.nextWriteBackSlot += _bufManager.writeBackUnitSz/_bufManager.transferUnitSz;
+ }
+ else
+ {
+ _bufManager.nextWriteBackSlot += ((u32)leftPktSz + _bufManager.transferUnitSz - 1)/_bufManager.transferUnitSz;
+ }
+ }
+
+ optimus_update_progress(transferSz);//report burning steps
+ return OPT_DOWN_OK;
+}
+
+int is_largest_data_transferring(void)
+{
+ const unsigned totalSlotNum = _bufManager.totalSlotNum;
+ const u64 totalTransferSz = ((u64)totalSlotNum) * _bufManager.transferUnitSz;//data size already transferred
+
+ return (PKT_TRANSFER_STA_WORKING == _bufManager.pktTransferSta)
+ && (_bufManager.tplcmdTotalSz > totalTransferSz);//as last packet may less than 64k, var totalSlotNum may > _bufManager.tplcmdTotalSz
+}
+
+int set_largest_data_transfer_sta_end(void)
+{
+ _bufManager.pktTransferSta = PKT_TRANSFER_STA_END;
+ return 0;
+}
+
+//command data format: [0-3]reserver, [4-7]dataLen, [8-11]sequence number, [12-15]check sum
+int optimus_buf_manager_get_command_data_for_upload_transfer(u8* cmdDataBuf, const unsigned bufLen)
+{
+ const unsigned totalSlotNum = _bufManager.totalSlotNum;
+ const u64 totalTransferSz = ((u64)totalSlotNum) * _bufManager.transferUnitSz;
+ const u64 leftPktSz = (totalTransferSz > _bufManager.tplcmdTotalSz) ? 0 :(_bufManager.tplcmdTotalSz - totalTransferSz);
+ const unsigned thisTransDataLen = (leftPktSz > _bufManager.transferUnitSz) ? _bufManager.transferUnitSz : ((u32)leftPktSz);
+
+ DWN_DBG("thisTransDataLen 0x%x, left 0x%x, total 0x%x\n", thisTransDataLen, (u32)leftPktSz, (u32)totalTransferSz);
+ DWN_DBG("totalSlotNum %d, totalTransferSz 0x%x\n", totalSlotNum, (u32)totalTransferSz);
+ memset(cmdDataBuf, bufLen, 0);
+ *(unsigned*)(cmdDataBuf + 0) = 0xefe8;
+ *(unsigned*)(cmdDataBuf + 4) = thisTransDataLen;//Fill transfer data length of this bulk transfer
+
+ _bufManager.pktTransferSta = PKT_TRANSFER_STA_WORKING;
+ return 0;
+}
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_download.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_download.c
new file mode 100644
index 0000000000..51555fc01a
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_download.c
@@ -0,0 +1,1319 @@
+/*
+ * \file optimu_download.c
+ * \brief
+ *
+ * \version 1.0.0
+ * \date 2013/4/25
+ * \author Sam.Wu <yihui.wu@amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+#include <libfdt.h>
+
+#if defined(CONFIG_ACS)
+#include <asm/arch/cpu.h>
+#include <asm/arch/acs.h>
+#include <partition_table.h>
+#define MAGIC_ACS "acs_"
+#endif//#if defined(CONFIG_ACS)
+
+extern unsigned int get_multi_dt_entry(unsigned int fdt_addr);
+int is_optimus_storage_inited(void);
+
+#ifndef CONFIG_UNIFY_KEY_MANAGE
+int v2_key_read(const char* keyName, u8* keyVal, const unsigned keyValLen, char* errInfo, unsigned* fmtLen)
+{
+ DWN_ERR("burn key not supported as CONFIG_UNIFY_KEY_MANAGE undef!!");
+ return OPT_DOWN_FAIL;
+}
+
+unsigned v2_key_burn(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo)
+{
+ DWN_ERR("burn key not supported as CONFIG_UNIFY_KEY_MANAGE undef!!");
+ return OPT_DOWN_FAIL;
+}
+#endif//#ifndef CONFIG_UNIFY_KEY_MANAGE
+
+
+#define IMG_VERIFY_ALG_NONE 0 //not need to veryfy
+#define IMG_VERIFY_ALG_SHA1SUM 1
+#define IMG_VERIFY_ALG_CRC32 2
+#define IMG_VERIFY_ALG_ADDSUM 3
+
+#define OPTIMUS_IMG_STA_EMPTY 0
+#define OPTIMUS_IMG_STA_PRE_BURN 1 //has get tplcmd load
+#define OPTIMUS_IMG_STA_BURN_ING 2
+#define OPTIMUS_IMG_STA_BURN_COMPLETE 3
+#define OPTIMUS_IMG_STA_BURN_FAILED 4
+#define OPTIMUS_IMG_STA_VERIFY_ING 5
+#define OPTIMUS_IMG_STA_VERIFY_END 6
+
+#define IMG_TYPE_SPARSE (0xfe)
+#define IMG_TYPE_NORMAL 0
+#define IMG_TYPE_BOOTLOADER (0xfd)
+
+//Image info for burnning and verify
+//FIXME: how to assert that image not larger than the partition
+#define IMG_BURN_INFO_SZ 64
+struct ImgBurnInfo{
+ u8 imgType; //0 normal, 1 sparse
+ u8 verifyAlgorithm;//0--sha1sum, 1--crc32, 2--addsum
+ u8 imgBurnSta;//
+ u8 storageMediaType;//NAND default,
+ u8 resrv4Align[4];
+
+ u64 nextMediaOffset;//image size already received
+ u64 imgPktSz;//total size of the file image
+ u64 imgSzDisposed;//total size alreay disposed
+ u64 partBaseOffset;//start offset of this part
+
+ void* devHdle;
+ char partName[16];//
+
+ u8 burnInfoPrivate[IMG_BURN_INFO_SZ - 16 - sizeof(void*) - sizeof(u64) * 5];//needed private info when verify, for example when we read ext4 to sparse file
+};
+
+static struct ImgBurnInfo OptimusImgBurnInfo = {0};
+
+struct imgBurnInfo_sparse{
+
+};
+
+struct imgBurnInfo_normal{
+};
+
+struct imgBurnInfo_bootloader{
+ u32 transferBufAddr;
+ u32 transferBufSzTotal;
+
+};
+
+COMPILE_TIME_ASSERT(IMG_BURN_INFO_SZ == sizeof(struct ImgBurnInfo));
+
+#if defined(CONFIG_ACS)
+#if 0
+static void _show_partition_table(const struct partitions* pPartsTab)
+{
+ int i=0;
+ const struct partitions* partInfo = pPartsTab;
+
+ for (i=0; i < MAX_PART_NUM; i++, ++partInfo)
+ {
+ if (partInfo->size == -1) {
+ printf("part: %d, name : %10s, size : %-4s\n",i, partInfo->name, "end");
+ break;
+ }
+ printf("part: %d, name : %10s, size : %-4llx\n",i, partInfo->name, partInfo->size);
+ }
+
+ return;
+}
+#endif
+
+static int _check_partition_table_consistency(const unsigned uboot_bin)
+{
+ int rc = 0;
+ unsigned partitionTableSz = 0;
+ const int acsOffsetInSpl = START_ADDR - AHB_SRAM_BASE;
+ const int addrMapFromAhb2Bin = AHB_SRAM_BASE - uboot_bin;
+
+ const struct acs_setting* acsSettingInBin = NULL;
+ unsigned partTabAddrInBin = 0;
+ const struct partitions* partsTabInBin = NULL;
+
+ const struct acs_setting* acsSettingInSram = NULL;
+ const struct partitions* partsTabInSram = NULL;
+
+ DWN_DBG("uboot_bin 0x%p, acsOffsetInSpl 0x%x, addrMapFromAhb2Bin 0x%x\n", uboot_bin, acsOffsetInSpl, addrMapFromAhb2Bin);
+ acsSettingInBin = (struct acs_setting*)(*(unsigned*)(uboot_bin + acsOffsetInSpl) - addrMapFromAhb2Bin);
+
+ if ( (unsigned)acsSettingInBin >= uboot_bin + 64*1024 || (unsigned)acsSettingInBin <= uboot_bin) {//acs not in the spl
+ DWN_MSG("Acs not in the spl of uboot_bin\n");
+ return 0;
+ }
+
+ if (memcmp(MAGIC_ACS, acsSettingInBin->acs_magic, strlen(MAGIC_ACS))
+ || memcmp(TABLE_MAGIC_NAME, acsSettingInBin->partition_table_magic, strlen(TABLE_MAGIC_NAME)))
+ {
+ DWN_MSG("acs magic OR part magic in ubootin not match\n");
+ return 0;//Not to check partTable as acs magic or part magic not match in u-boot.bin, maybe encrypted by AMLETOOL
+ }
+ partTabAddrInBin = acsSettingInBin->partition_table_addr - addrMapFromAhb2Bin;
+ partsTabInBin = (const struct partitions*)partTabAddrInBin;
+
+#ifndef CONFIG_MESON_TRUSTZONE
+ acsSettingInSram = (struct acs_setting*)(*(unsigned*)START_ADDR);
+#else
+ //twice eget value at sram address and copy 1K to memory
+ acsSettingInSram = (struct acs_setting*)meson_trustzone_acs_addr(START_ADDR);
+ DWN_MSG("[Trust]acsSettingInSram=0x%p\n", acsSettingInSram);
+#endif// #ifndef CONFIG_MESON_TRUSTZONE
+ partsTabInSram = (const struct partitions*)acsSettingInSram->partition_table_addr;
+ DWN_MSG("partsTabInSram=0x%p\n", partsTabInSram);
+
+ if (memcmp(MAGIC_ACS, acsSettingInSram->acs_magic, strlen(MAGIC_ACS))
+ || memcmp(TABLE_MAGIC_NAME, acsSettingInSram->partition_table_magic, strlen(TABLE_MAGIC_NAME)))
+ {
+ DWN_MSG("acs magic OR part magic in SPL not match\n");
+ return __LINE__;//Not to check partTable as acs magic or part magic not match in SRAM, assert this!!
+ }
+
+#ifdef CONFIG_MESON_TRUSTZONE
+ partsTabInSram = (const struct partitions*)meson_trustzone_acs_addr((unsigned)&acsSettingInSram->partition_table_addr);
+#endif// #ifndef CONFIG_MESON_TRUSTZONE
+
+ partitionTableSz = acsSettingInBin->partition_table_length;
+ DWN_MSG("acsSettingInBin=0x%x, partTabSz=0x%x\n", (unsigned int)acsSettingInBin, partitionTableSz);
+
+ rc = memcmp(partsTabInSram, partsTabInBin, partitionTableSz);
+ DWN_MSG("Check parts table %s\n", !rc ? "OK." : "FAILED!");
+#if 0//I comment print as str-prefix function (strcmp, strcmp, and .etc) are all not reliable in uboot
+ if (rc)
+ {
+ DWN_MSG("acs_setting 0x%p, 0x%p\n", acsSettingInBin, acsSettingInSram);
+ DWN_MSG("partitions 0x%08x, 0x%p\n", partTabAddrInBin, partsTabInSram);
+ DWN_MSG("partition_table_addr 0x%x, 0x%x\n", acsSettingInSram->partition_table_addr, acsSettingInBin->partition_table_addr);
+
+ DWN_MSG("part in ubootbin:\n");
+ _show_partition_table(partsTabInBin);
+
+ DWN_MSG("part in spl:\n");
+ _show_partition_table(partsTabInSram);
+ return __LINE__;
+ }
+#endif//#if 0
+
+ return rc;
+}
+#else
+#define _check_partition_table_consistency(a) 0
+#endif//#if defined(CONFIG_ACS)
+
+#if 0
+//asset nand logical partition size equals CFG size in storage.c
+//nand often make mistake this size, emmc should always ok
+static int _assert_logic_partition_cap(const char* thePartName, const uint64_t nandPartCap)
+{
+ extern struct partitions * part_table;
+
+ struct partitions * thePart = NULL;
+
+ for (thePart = part_table; NAND_PART_SIZE_FULL != thePart->size; ++thePart)
+ {
+ const uint64_t partSzInBytes = thePart->size;
+ if (strcmp(thePartName, thePart->name)) continue;
+ if (partSzInBytes != nandPartCap) {
+ DWN_ERR("partSz in ACS %llx != flash Sz %llx\n", partSzInBytes, nandPartCap);
+ return __LINE__;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+#else
+#define _assert_logic_partition_cap(...) 0
+#endif
+
+//return value is the actual size it write
+static int optimus_download_bootloader_image(struct ImgBurnInfo* pDownInfo, u32 dataSzReceived, const u8* data)
+{
+ int ret = OPT_DOWN_OK;
+ uint64_t size = dataSzReceived;
+
+ if (dataSzReceived < pDownInfo->imgPktSz) {
+ DWN_ERR("please write back bootloader after all data rx end.0x(%x, %x)\n", dataSzReceived, (u32)pDownInfo->imgPktSz);
+ return 0;
+ }
+
+ ret = _check_partition_table_consistency((unsigned)data);
+ if (ret) {
+ DWN_ERR("Fail in _check_partition_table_consistency\n");
+ return 0;
+ }
+ if (size > (1U<<20)) {
+ DWN_ERR("uboot.bin size 0x%llx > 1M unsupported\n", size);
+ return 0;
+ }
+
+ size = size <= 0x60000 ? 0x60000 : (1U<<20);//384K when non-secure_os, 1M when secure_os
+ ret = store_boot_write((unsigned char*)data, 0, size);
+
+ return ret ? 0 : dataSzReceived;
+}
+
+static int optimus_verify_bootloader(struct ImgBurnInfo* pDownInfo, u8* genSum)
+{
+ int ret = OPT_DOWN_OK;
+ unsigned char* pBuf = (unsigned char*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ uint64_t size = 0;
+
+ /*size = 0x60000;////////////TODO:hardcode len!!*/
+ size=pDownInfo->imgPktSz;
+ ret = store_boot_read(pBuf, (u64)0, size);
+ if (ret) {
+ DWN_ERR("Fail to read bootloader\n");
+ return __LINE__;
+ }
+
+ sha1_csum(pBuf, (u32)pDownInfo->imgPktSz, genSum);
+
+ return ret;
+}
+
+
+u32 optimus_cb_simg_write_media(const unsigned destAddrInSec, const unsigned dataSzInBy, const char* data)
+{
+ int ret = OPT_DOWN_OK;
+ unsigned char* partName = (unsigned char*)OptimusImgBurnInfo.partName;
+
+ if (OPTIMUS_MEDIA_TYPE_STORE < OptimusImgBurnInfo.storageMediaType) {
+ DWN_ERR("storage type %d not supported yet!\n", OptimusImgBurnInfo.storageMediaType);
+ return OPT_DOWN_FAIL;
+ }
+
+ DWN_DBG("1addrOffset=0x%llx, dataSz=0x%x, data = 0x%p\t", (((u64)destAddrInSec)<<9), dataSzInBy, (void*)data);
+ //FIXME:why dirty value if not convert to u64
+ ret = store_write_ops(partName, (u8*)data, (((u64)destAddrInSec)<<9), (u64)dataSzInBy);
+ if (ret) {
+ DWN_ERR("Fail to write to media, ret = %d\n", ret);
+ return 0;
+ }
+
+ return dataSzInBy;
+}
+
+//return value: the data size disposed
+static u32 optimus_download_sparse_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data)
+{
+ u32 unParsedDataLen = 0;
+ int flashOffset = 0;
+ const u64 addrOffset = pDownInfo->nextMediaOffset;
+
+ flashOffset = optimus_simg_to_media((char*)data, dataSz, &unParsedDataLen, ((u32)(addrOffset>>9)));
+ if (flashOffset < 0) {
+ DWN_ERR("Fail in parse simg. src 0x%p, size 0x%x, unParsedDataLen 0x%x, ret %d\n", data, dataSz, unParsedDataLen, flashOffset);
+ return 0;
+ }
+ pDownInfo->nextMediaOffset += ((u64)flashOffset)<<9;
+
+ return dataSz - unParsedDataLen;
+}
+
+//Normal image can write directly to NAND, best aligned to 16K when write
+//FIXME: check it aligned to 16K when called
+//1, write to media 2 -- save the verify info
+static u32 optimus_download_normal_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data)
+{
+ int ret = 0;
+ u64 addrOrOffsetInBy = pDownInfo->nextMediaOffset;
+
+ DWN_DBG("addrOffset=0x%llx, dataSz=0x%x, data = 0x%p\n", addrOrOffsetInBy, dataSz, data);
+
+ ret = store_write_ops((u8*)pDownInfo->partName, (u8*)data, addrOrOffsetInBy, (u64)dataSz);
+ if (ret) {
+ DWN_ERR("Fail to write to media\n");
+ return 0;
+ }
+
+ pDownInfo->nextMediaOffset += dataSz;
+
+ return dataSz;
+}
+
+static int optimus_storage_open(struct ImgBurnInfo* pDownInfo, const u8* data, const u32 dataSz)
+{
+ int ret = OPT_DOWN_OK;
+ const char* partName = (const char*)pDownInfo->partName;
+ const int imgType = pDownInfo->imgType;
+ const int MediaType = pDownInfo->storageMediaType;
+
+ if (!pDownInfo->imgSzDisposed && OPTIMUS_IMG_STA_PRE_BURN == pDownInfo->imgBurnSta)
+ {
+ DWN_MSG("Burn Start...\n");
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_ING;
+ }
+ else if(pDownInfo->imgSzDisposed == pDownInfo->imgPktSz && OPTIMUS_IMG_STA_BURN_COMPLETE == pDownInfo->imgBurnSta)
+ {
+ DWN_MSG("Verify Start...\n");
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_VERIFY_ING;
+ }
+
+ switch (MediaType)
+ {
+ case OPTIMUS_MEDIA_TYPE_NAND:
+ case OPTIMUS_MEDIA_TYPE_SDMMC:
+ case OPTIMUS_MEDIA_TYPE_STORE:
+ {
+ if (IMG_TYPE_BOOTLOADER != pDownInfo->imgType && !pDownInfo->devHdle) //if not bootloader and device not open
+ {
+ /*pDownInfo->devHdle = aml_nftl_get_dev(partName);*/
+ pDownInfo->devHdle = (void*)1;
+ if (!pDownInfo->devHdle) {
+ DWN_ERR("Fail to open nand part %s\n", partName);
+ return OPT_DOWN_FAIL;
+ }
+
+ if (IMG_TYPE_SPARSE == imgType)
+ {
+ ret = optimus_simg_probe(data, dataSz);
+ if (!ret) {
+ DWN_ERR("Fail in sparse format probe,ret=%d\n", ret);
+ return OPT_DOWN_FAIL;
+ }
+ return optimus_simg_parser_init(data);
+ }
+ }
+ else//is bootloader, than do nothing
+ {
+ return OPT_DOWN_OK;
+ }
+ }
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_KEY_UNIFY:
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_MEM:
+ break;
+
+ default:
+ DWN_MSG("Error MediaType %d\n", MediaType);
+ return OPT_DOWN_FAIL;
+ }
+
+ return ret;
+}
+
+static int optimus_storage_close(struct ImgBurnInfo* pDownInfo)
+{
+ if (pDownInfo->imgSzDisposed == pDownInfo->imgPktSz && OPTIMUS_IMG_STA_BURN_ING == pDownInfo->imgBurnSta)
+ {
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_COMPLETE;
+ DWN_MSG("Burn complete\n");
+
+ return OPT_DOWN_OK;
+ }
+
+ if (!pDownInfo->imgSzDisposed && OPTIMUS_IMG_STA_VERIFY_ING == pDownInfo->imgBurnSta)
+ {
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_VERIFY_END;
+ DWN_MSG("Verify End\n");
+ return OPT_DOWN_OK;
+ }
+
+ return OPT_DOWN_OK;
+}
+
+
+//return value is the data size that actual dealed
+static u32 optimus_storage_write(struct ImgBurnInfo* pDownInfo, u64 addrOrOffsetInBy, unsigned dataSz, const u8* data, char* errInfo)
+{
+ u32 burnSz = 0;
+ const u32 imgType = pDownInfo->imgType;
+ const int MediaType = pDownInfo->storageMediaType;
+
+ addrOrOffsetInBy += pDownInfo->partBaseOffset;
+ DWN_DBG("[0x]Data %p, addrOrOffsetInBy %llx, dataSzInBy %x\n", data, addrOrOffsetInBy, dataSz);
+
+ if (OPTIMUS_IMG_STA_BURN_ING != pDownInfo->imgBurnSta) {
+ sprintf(errInfo, "Error burn sta %d\n", pDownInfo->imgBurnSta);
+ DWN_ERR(errInfo);
+ return 0;
+ }
+
+ switch (MediaType)
+ {
+ case OPTIMUS_MEDIA_TYPE_NAND:
+ case OPTIMUS_MEDIA_TYPE_SDMMC:
+ case OPTIMUS_MEDIA_TYPE_STORE:
+ {
+ switch (imgType)
+ {
+ case IMG_TYPE_NORMAL:
+ burnSz = optimus_download_normal_image(pDownInfo, dataSz, data);
+ break;
+
+ case IMG_TYPE_BOOTLOADER:
+ burnSz = optimus_download_bootloader_image(pDownInfo, dataSz, data);
+ break;
+
+ case IMG_TYPE_SPARSE:
+ burnSz = optimus_download_sparse_image(pDownInfo, dataSz, data);
+ break;
+
+ default:
+ DWN_ERR("error image type %d\n", imgType);
+ }
+ }
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_KEY_UNIFY:
+ {
+ burnSz = v2_key_burn(pDownInfo->partName, data, dataSz, errInfo);
+ if (burnSz != dataSz) {//return value is write size
+ DWN_ERR("burn key failed\n");
+ return 0;
+ }
+ }
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_MEM:
+ {
+ u8* buf = (u8*)addrOrOffsetInBy;
+ if (buf != data) {
+ DWN_ERR("buf(%llx) != data(%p)\n", addrOrOffsetInBy, data);
+ return 0;
+ }
+ if (!strcmp("dtb", pDownInfo->partName)) //as memory write back size = min[fileSz, 2G], so reach here if downloaded ok!
+ {
+ int rc = 0;
+ char* dtbLoadAddr = NULL;//(char*)CONFIG_DTB_LOAD_ADDR;
+ const int DtbMaxSz = (2U<<20);
+ unsigned fdtSz = 0;
+ unsigned char* destDtb = (unsigned char*)data;
+
+ //Make sure flash already inited before 'run aml_dt'
+ //old tool will download dtb before 'disk_initial', but new tool will 'disk_initial' first
+ if (is_optimus_storage_inited() ||
+ (OPTIMUS_WORK_MODE_USB_PRODUCE != optimus_work_mode_get()))
+ {
+ /*destDtb = (unsigned char*)(uint64_t)get_multi_dt_entry((unsigned int)data);*/
+ destDtb = NULL;
+ }
+ rc = fdt_check_header(destDtb);
+ if (rc) {
+ sprintf(errInfo, "failed at fdt_check_header\n");
+ DWN_ERR(errInfo);
+ return 0;
+ }
+ fdtSz = fdt_totalsize(destDtb);
+ if (DtbMaxSz <= fdtSz) {
+ sprintf(errInfo, "failed: fdt header ok but sz 0%x > max 0x%x\n", fdtSz, DtbMaxSz);
+ DWN_ERR(errInfo);
+ return 0;
+ }
+
+ DWN_MSG("load dtb to 0x%p\n", dtbLoadAddr);
+ memcpy(dtbLoadAddr, destDtb, fdtSz);
+ }
+
+ burnSz = dataSz;
+ }
+ break;
+
+ default:
+ sprintf(errInfo, "Error MediaType %d\n", MediaType);
+ DWN_ERR(errInfo);
+ }
+
+ return burnSz;
+}
+
+//TODO: to consist with optimus_storage_write, return value should be readSzInBy
+static int optimus_storage_read(struct ImgBurnInfo* pDownInfo, u64 addrOrOffsetInBy,
+ unsigned readSzInBy, unsigned char* buff, char* errInfo)
+{
+ int ret = 0;
+ const int MediaType = pDownInfo->storageMediaType;
+ unsigned char* partName = (unsigned char*)pDownInfo->partName;
+
+ addrOrOffsetInBy += pDownInfo->partBaseOffset;
+
+ switch (MediaType)
+ {
+ case OPTIMUS_MEDIA_TYPE_NAND:
+ case OPTIMUS_MEDIA_TYPE_SDMMC:
+ case OPTIMUS_MEDIA_TYPE_STORE:
+ {
+ if (IMG_TYPE_BOOTLOADER == pDownInfo->imgType)
+ {
+ ret = store_boot_read(buff, addrOrOffsetInBy, (u64)readSzInBy);
+ }
+ else
+ {
+ ret = store_read_ops(partName, buff, addrOrOffsetInBy, (u64)readSzInBy);
+ }
+ if (ret) {
+ if (errInfo) sprintf(errInfo, "Read failed\n") ;
+ DWN_ERR("Read failed\n");
+ return OPT_DOWN_FAIL;
+ }
+
+ }
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_KEY_UNIFY:
+ {
+ unsigned fmtLen = 0;
+ if (addrOrOffsetInBy) {
+ DWN_ERR("OH NO, IS key len > 64K!!? addrOrOffsetInBy is 0x%llx not 0\n", addrOrOffsetInBy);
+ return OPT_DOWN_FAIL;
+ }
+ ret = v2_key_read(pDownInfo->partName, buff, readSzInBy, errInfo, &fmtLen);
+ }
+ break;
+
+ case OPTIMUS_MEDIA_TYPE_MEM:
+ {
+ u8* buf = (u8*)addrOrOffsetInBy;
+ if (addrOrOffsetInBy >> 32) {
+ DWN_ERR("mem addr 0x%llx too large\n", addrOrOffsetInBy);
+ }
+ if (buf != buff) {
+ DWN_ERR("buf(%llx) != buff(%p)\n", addrOrOffsetInBy, buff);
+ }
+ }
+ break;
+
+ default:
+ DWN_MSG("Error MediaType %d\n", MediaType);
+ return OPT_DOWN_FAIL;
+ }
+
+ return ret;
+}
+
+//return value is the size actual write to media
+//Paras: const char* partName, const char* imgType, const char* verifyAlgorithm
+static u32 optimus_func_download_image(struct ImgBurnInfo* pDownInfo, u32 dataSz, const u8* data, char* errInfo)
+{
+ int burnSz = 0;
+ int ret = 0;
+ u64 nextMediaOffset = pDownInfo->nextMediaOffset;
+
+ DWN_DBG("data=0x%p, sz=0x%x, offset=%llx\n", data, dataSz, nextMediaOffset);
+
+ ret = optimus_storage_open(pDownInfo, data, dataSz);
+ if (OPT_DOWN_OK != ret) {
+ sprintf(errInfo, "Fail to open stoarge\n");
+ DWN_ERR(errInfo);
+ return 0;
+ }
+
+ burnSz = optimus_storage_write(pDownInfo, nextMediaOffset, dataSz, data, errInfo);
+ if (!burnSz) {
+ DWN_ERR("Fail in optimus_storage_write, data 0x%p, wantSz 0x%x\n", data, dataSz);
+ goto _err;
+ }
+ pDownInfo->imgSzDisposed += burnSz;
+
+ ret = optimus_storage_close(pDownInfo);
+ if (ret) {
+ DWN_ERR("Fail to close media\n");
+ return 0;
+ }
+
+ return burnSz;
+
+_err:
+ optimus_storage_close(pDownInfo);
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_FAILED;////
+ return 0;
+}
+
+//TODO: add _errInfo as argument to pass more info
+static int _parse_img_download_info(struct ImgBurnInfo* pDownInfo, const char* partName,
+ const u64 imgSz, const char* imgType, const char* mediaType, const u64 partBaseOffset)
+{
+ u64 partCap = 0;
+ int ret = 0;
+
+ memset(pDownInfo, 0, sizeof(struct ImgBurnInfo));//clear burnning info
+
+ //TODO: check format is normal/bootloader if upload!!
+
+ if (!strcmp("sparse", imgType))
+ {
+ pDownInfo->imgType = IMG_TYPE_SPARSE;
+ }
+ else if(!strcmp("bootloader", partName))
+ {
+ pDownInfo->imgType = IMG_TYPE_BOOTLOADER;
+ }
+ else if(!strcmp("normal", imgType))
+ {
+ pDownInfo->imgType = IMG_TYPE_NORMAL;
+ }
+ else{
+ DWN_ERR("err image type %s\n", imgType);
+ return __LINE__;
+ }
+
+ if (!strcmp("store", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_STORE;
+ }
+ else if(!strcmp("nand", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_NAND;
+ }
+ else if(!strcmp("sdmmc", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_SDMMC;
+ }
+ else if(!strcmp("spiflash", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_SPIFLASH;
+ }
+ else if(!strcmp("key", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_KEY_UNIFY;
+
+ if (OPTIMUS_DOWNLOAD_SLOT_SZ <= imgSz) {
+ DWN_ERR("size (0x%llx) for key %s invalid!!\n", imgSz, partName);
+ return __LINE__;
+ }
+ }
+ else if(!strcmp("mem", mediaType))
+ {
+ pDownInfo->storageMediaType = OPTIMUS_MEDIA_TYPE_MEM;
+ }
+ else{
+ DWN_ERR("error mediaType %s\n", mediaType);
+ return __LINE__;
+ }
+
+ pDownInfo->partBaseOffset = partBaseOffset;
+ memcpy(pDownInfo->partName, partName, strlen(partName));
+
+ if (OPTIMUS_MEDIA_TYPE_MEM > pDownInfo->storageMediaType) //if command for burning partition
+ {
+ if (strcmp("bootloader", partName)) //get size if not bootloader
+ {
+ ret = store_get_partititon_size((u8*)partName, &partCap);
+ if (ret) {
+ DWN_ERR("Fail to get size for part %s\n", partName);
+ return __LINE__;
+ }
+ partCap <<= 9;//trans sector to byte
+ DWN_MSG("flash LOGIC partCap 0x%llxB\n", partCap);
+ if (imgSz > partCap) {
+ DWN_ERR("imgSz 0x%llx out of cap 0x%llx\n", imgSz, partCap);
+ return __LINE__;
+ }
+ ret = _assert_logic_partition_cap(partName, partCap);
+ if (ret) {
+ DWN_ERR("Fail in _assert_logic_partition_cap\n");
+ return __LINE__;
+ }
+ }
+ }
+
+ pDownInfo->nextMediaOffset = pDownInfo->imgSzDisposed = 0;
+ pDownInfo->imgPktSz = imgSz;
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_PRE_BURN;
+
+ DWN_MSG("Down(%s) part(%s) sz(0x%llx) fmt(%s)\n", mediaType, partName, pDownInfo->imgPktSz, imgType);
+
+ return 0;
+}
+
+int optimus_download_init(void)
+{
+ memset(&OptimusImgBurnInfo, 0, sizeof(struct ImgBurnInfo));
+ return 0;
+}
+
+int optimus_download_exit(void)
+{
+ return 0;
+}
+
+int optimus_parse_img_download_info(const char* partName, const u64 imgSz, const char* imgType, const char* mediaType, const u64 partBaseOffset)
+{
+ return _parse_img_download_info(&OptimusImgBurnInfo, partName, imgSz, imgType, mediaType, partBaseOffset);
+}
+
+static int _disk_intialed_ok = 0;
+
+int is_optimus_storage_inited(void)
+{
+ return _disk_intialed_ok;
+}
+
+int optimus_storage_init(int toErase)
+{
+ int ret = 0;
+ char* cmd = NULL;
+
+ if (_disk_intialed_ok) {//To assert only actual disk intialed once
+ DWN_MSG("Disk inited again.\n");
+ return 0;
+ }
+
+ if (OPTIMUS_WORK_MODE_USB_PRODUCE != optimus_work_mode_get()) //Already inited in other work mode
+ {
+ DWN_MSG("Exit before re-init\n");
+ store_exit();
+ }
+
+ switch (toErase)
+ {
+ case 0://NO erase
+ ret = store_init(1);
+ break;
+
+ case 3://erase all(with key)
+ {
+ cmd = "store disprotect key";
+ DWN_MSG("run cmd [%s]\n", cmd);
+ ret = run_command(cmd, 0);
+ if (ret) {
+ DWN_ERR("Fail when run cmd[%s], ret %d\n", cmd, ret);
+ break;
+ }
+ }
+ case 1://normal erase, store init 3
+ ret = store_init(3);
+ break;
+
+ case 4://force erase all
+ {
+ cmd = "store disprotect key; store disprotect hynix";
+ DWN_MSG("run cmd [%s]\n", cmd);
+ ret = run_command(cmd, 0);
+ if (ret) {
+ DWN_ERR("Fail when run cmd[%s], ret %d\n", cmd, ret);
+ break;
+ }
+ }
+ case 2:
+ ret = store_init(4);
+ break;
+
+ default:
+ DWN_ERR("Unsupported erase flag %d\n", toErase); ret = -__LINE__;
+ break;
+ }
+
+ if (!ret)
+ {
+ _disk_intialed_ok = 1;
+ _disk_intialed_ok += toErase <<16;
+
+ if (OPTIMUS_WORK_MODE_USB_PRODUCE == optimus_work_mode_get()) //env not relocated in this case
+ {
+ DWN_MSG("usb producing env_relocate\n");
+ env_relocate();
+ }
+ }
+
+ return ret;
+}
+
+int optimus_storage_exit(void)
+{
+ _disk_intialed_ok = 0;
+ DWN_MSG("store_exit yet!!\n");
+ return store_exit();
+}
+
+int is_optimus_on_burn(void)//is now transfering image
+{
+ return (OPTIMUS_IMG_STA_BURN_ING == OptimusImgBurnInfo.imgBurnSta);
+}
+
+int is_optimus_pre_burn(void) //is now has get "download command"
+{
+ return (OPTIMUS_IMG_STA_PRE_BURN == OptimusImgBurnInfo.imgBurnSta);
+}
+
+int is_optimus_to_burn_ready(void)
+{
+ return (OPTIMUS_IMG_STA_PRE_BURN == OptimusImgBurnInfo.imgBurnSta);
+}
+
+int is_optimus_burn_complete(void)
+{
+ int is_burn_completed = 0;
+
+ is_burn_completed = (OPTIMUS_IMG_STA_BURN_COMPLETE == OptimusImgBurnInfo.imgBurnSta);
+ if (!is_burn_completed) {
+ DWN_MSG("imgSzDisposed 0x%llx != imgPktSz 0x%llx\n", OptimusImgBurnInfo.imgSzDisposed, OptimusImgBurnInfo.imgPktSz);
+ }
+
+ return is_burn_completed;
+}
+
+u32 optimus_download_img_data(const u8* data, const u32 size, char* errInfo)
+{
+ return optimus_func_download_image(&OptimusImgBurnInfo, size, data, errInfo);
+}
+
+static int optimus_sha1sum_verify_partition(const char* partName, const u64 verifyLen, const u8 imgType, u8* genSum)
+{
+ int ret = 0;
+ u8* buff = (u8*) OPTIMUS_SHA1SUM_BUFFER_ADDR;
+ const u32 buffSz = OPTIMUS_SHA1SUM_BUFFER_LEN;
+ sha1_context ctx;
+ u64 leftLen = verifyLen;
+
+ if (strcmp(partName, OptimusImgBurnInfo.partName)) {
+ DWN_ERR("partName %s err, must %s\n", partName, OptimusImgBurnInfo.partName);
+ return OPT_DOWN_FAIL;
+ }
+
+ if (!is_optimus_burn_complete()) {
+ return OPT_DOWN_FAIL;
+ }
+
+ memset(buff, 0xde, 1024);//clear 1kb data before verfiy, in case read buffer not overlapped
+ if (IMG_TYPE_BOOTLOADER == imgType)
+ {
+ return optimus_verify_bootloader(&OptimusImgBurnInfo, genSum);
+ }
+ else if(IMG_TYPE_SPARSE == imgType)//sparse image
+ {
+ ret = optimus_sparse_back_info_probe();
+ if (OPT_DOWN_TRUE != ret) {
+ DWN_ERR("Fail to probe back sparse info\n");
+ return OPT_DOWN_FAIL;
+ }
+ }
+
+ ret = optimus_storage_open(&OptimusImgBurnInfo, NULL, 0);
+ if (ret) {
+ DWN_ERR("Fail to open storage for read\n");
+ return OPT_DOWN_FAIL;
+ }
+
+ sha1_starts(&ctx);
+
+ DWN_MSG("To verify part %s in fmt %s\n", partName, (IMG_TYPE_SPARSE == imgType) ? "sparse": "normal");
+ if (IMG_TYPE_SPARSE == imgType) //sparse image
+ {
+ for (; leftLen;)
+ {
+ u32 spHeadSz = 0;
+ u32 chunkDataLen = 0;
+ u64 chunkDataOffset = 0;
+ u8* head = NULL;
+
+ ret = optimus_sparse_get_chunk_data(&head, &spHeadSz, &chunkDataLen, &chunkDataOffset);
+ if (ret) {
+ DWN_ERR("Fail to get chunk data\n");
+ goto _finish;
+ }
+
+ sha1_update(&ctx, head, spHeadSz);
+
+ leftLen -= spHeadSz + chunkDataLen;//update image read info
+
+ for (;chunkDataLen;)
+ {
+ const int thisReadLen = (chunkDataLen > buffSz) ? buffSz : chunkDataLen;
+
+ ret = optimus_storage_read(&OptimusImgBurnInfo, chunkDataOffset, thisReadLen, buff, NULL);
+ if (ret) {
+ DWN_ERR("Fail to read at offset 0x[%x, %8x], len=0x%8x\n", ((u32)(chunkDataOffset>>32)), (u32)chunkDataOffset, thisReadLen);
+ goto _finish;
+ }
+
+ sha1_update(&ctx, buff, thisReadLen);
+
+ chunkDataLen -= thisReadLen;
+ chunkDataOffset += thisReadLen;
+ }
+
+ if (leftLen && !spHeadSz) {
+ DWN_ERR("Fail to read when pkt len left 0x%x\n", (u32)leftLen);
+ break;
+ }
+ }
+ }
+ else//normal image
+ {
+ for (; leftLen;)
+ {
+ int thisReadLen = (leftLen > buffSz) ? buffSz : ((u32)leftLen);
+ u64 addrOffset = verifyLen - leftLen;
+
+ ret = optimus_storage_read(&OptimusImgBurnInfo, addrOffset, thisReadLen, buff, NULL);
+ if (ret) {
+ DWN_ERR("Fail to read at offset 0x[%x, %8x], len=0x%8x\n", ((u32)(addrOffset>>32)), (u32)addrOffset, thisReadLen);
+ goto _finish;
+ }
+
+ sha1_update(&ctx, buff, thisReadLen);
+
+ leftLen -= thisReadLen;
+ }
+
+ }
+
+_finish:
+ OptimusImgBurnInfo.imgSzDisposed = leftLen;
+ sha1_finish(&ctx, genSum);
+ optimus_storage_close(&OptimusImgBurnInfo);
+
+ return ret;
+}
+
+//usage: verify sha1sum nand srcSum part_name size imgType
+int optimus_media_download_verify(const int argc, char * const argv[], char *info)
+{
+ const char* verifyType = argv[1];
+ const char* srcSum = argv[2];
+ static u8 verifyResult[20];
+ static char sha1Result[42];
+ const u8 srcImgType = OptimusImgBurnInfo.imgType;
+ const char* partName = OptimusImgBurnInfo.partName;
+ u64 verifyLen = OptimusImgBurnInfo.imgPktSz;
+ int ret = 0;
+
+ if (argc != 3) {
+ strcpy(info, "failed:need 3 args\n");
+ printf(info);
+ return -1;
+ }
+
+ if (strcmp(verifyType, "sha1sum")) {
+ ret = __LINE__;
+ sprintf(info, "verifyType [%s] err, ret %d!\n", verifyType, ret);
+ DWN_ERR(info);
+ return ret;
+ }
+
+ ret = optimus_sha1sum_verify_partition(partName, verifyLen, srcImgType, verifyResult);
+ if (ret) {
+ DWN_ERR("Fail to gen check sum\n");
+ return __LINE__;
+ }
+
+ ret = optimus_hex_data_2_ascii_str(verifyResult, 20, sha1Result, 42);
+ if (ret) {
+ DWN_ERR("Failed when format sha1 to string\n");
+ return __LINE__;
+ }
+
+ /*DWN_MSG("%s %s\n", verifyType, sha1Result);*/
+ ret = strcmp(sha1Result, srcSum);
+ if (ret) {
+ sprintf(info, "failed:Verify Failed with %s, origin sum \"%s\" != gen sum \"%s\"\n", verifyType, srcSum, sha1Result);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ DWN_MSG("VERIFY OK \n");
+ return ret;
+}
+
+int optimus_key_burn_init(const char* keyType)
+{
+ int ret = 0;
+
+ if (!strcmp("efuse", keyType))
+ {
+ return ret;
+ }
+
+ if (!strcmp("secure", keyType))
+ {
+ return ret;
+ }
+
+ DWN_ERR("unsported key type %s\n", keyType);
+ return OPT_DOWN_FAIL;
+}
+
+//update tplcmd dev0 "download nand part_name imageType imgSz"
+//update tplcmd dev0 "download get_status"
+int optimus_parse_download_cmd(int argc, char* argv[])
+{
+ const int isUpload = !strcmp("upload", argv[0]);
+ const char* mediaType = argv[1];
+ const char* part_name = argv[2];
+ const char* imgType = argv[3];
+ const char* imgSzStr = argv[4];
+ u64 imgSzInBy = 0;
+ u64 partBaseOffset = 0;
+ int ret = 0;
+
+ if (!strcmp("get_status", mediaType))
+ {
+ return !is_optimus_burn_complete();
+ }
+
+ if (!strcmp("is_ready", mediaType))
+ {
+ return !is_optimus_to_burn_ready();
+ }
+
+ if (5 > argc) {
+ printf("argc[%d] too few, use \"download nand part_name imageType imgSz\"\n", argc);
+ return __LINE__;
+ }
+
+ imgSzInBy = simple_strtoull(imgSzStr, NULL, 0);
+
+ if (!strcmp("mem", mediaType))
+ {
+ char* endp = NULL;
+ partBaseOffset = simple_strtoull(part_name, &endp, 0);
+ if (0 != *endp) //not a valid 0-terminated c string
+ {
+ if (!strcmp("dtb", part_name))
+ {
+ partBaseOffset = OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ DWN_MSG("dtb boot down to %llx\n", partBaseOffset);
+ }
+ }
+ }
+
+ ret = optimus_parse_img_download_info(part_name, imgSzInBy, imgType, mediaType, partBaseOffset);
+ if (ret) {
+ DWN_ERR("Fail in init download info\n");
+ return __LINE__;
+ }
+
+ ret = optimus_buf_manager_tplcmd_init(mediaType, part_name, partBaseOffset, imgType, imgSzInBy, isUpload, 0);
+ if (ret) {
+ DWN_ERR("Fail in init download info\n");
+ return __LINE__;
+ }
+
+ return OPT_DOWN_OK;
+}
+
+u32 optimus_dump_storage_data(u8* pBuf, const u32 wantSz, char* errInfo)
+{
+ struct ImgBurnInfo* pDownInfo = &OptimusImgBurnInfo;
+ u64 nextMediaOffset = pDownInfo->nextMediaOffset;
+ int ret = 0;
+
+ DWN_DBG("pBuf=0x%p, wantSz=0x%x, nextMediaOffset=%x\n", pBuf, wantSz, (u32)nextMediaOffset);
+
+ ret = optimus_storage_open(pDownInfo, pBuf, wantSz);
+ if (OPT_DOWN_OK != ret) {
+ sprintf(errInfo, "Fail to open stoarge\n");
+ DWN_ERR(errInfo);
+ return 0;
+ }
+
+ ret = optimus_storage_read(pDownInfo, nextMediaOffset, wantSz, pBuf, errInfo);
+ if (ret) {
+ DWN_ERR("Failed \n");
+ goto _err;
+ }
+ pDownInfo->imgSzDisposed += wantSz;
+ pDownInfo->nextMediaOffset += wantSz;
+
+ ret = optimus_storage_close(pDownInfo);
+ if (ret) {
+ DWN_ERR("Fail to close media\n");
+ return 0;
+ }
+
+ return wantSz;
+
+_err:
+ optimus_storage_close(pDownInfo);
+ pDownInfo->imgBurnSta = OPTIMUS_IMG_STA_BURN_FAILED;////
+ return 0;
+}
+
+static int _optimusWorkMode = OPTIMUS_WORK_MODE_NONE;
+
+int optimus_work_mode_get(void)
+{
+ return _optimusWorkMode;
+}
+
+int optimus_work_mode_set(int workmode)
+{
+ _optimusWorkMode = workmode;
+ return 0;
+}
+
+int is_the_flash_first_burned(void)
+{
+ const char* s = getenv("upgrade_step");
+
+ DWN_MSG("====>upgrade_step=%s<=====\n", s ? s : "<UNDEFINED>");
+
+ return !strcmp(s, "0");//"0" indicate first boot
+}
+
+//FIXME: check whether 'saveenv' failed and exception when usb prodcing mode from code boot mode if without env_relocate
+int optimus_set_burn_complete_flag(void)
+{
+ int rc = 0;
+ const int IsTplLoadedFromBurningPackage = aml_burn_check_uboot_loaded_for_burn(0);
+ const char* const upgrade_step = IsTplLoadedFromBurningPackage ? "2" : "1";
+
+ if (IsTplLoadedFromBurningPackage)
+ {
+ extern int device_boot_flag;
+
+ char str_store[8];
+
+ sprintf(str_store, "%d", device_boot_flag);
+ DWN_MSG("store=%s\n", str_store);
+ /*rc = run_command("defenv", 0);//use new env directly if uboot is new !!!*/
+ set_default_env("## save_setting ##\n");//use new env directly if uboot is new !!!
+ setenv("store", str_store);
+ setenv("firstboot", "1");
+ if (!strstr(getenv("initargs"), "storage") && getenv("initargs") && 0) {
+ rc = run_command("setenv initargs ${initargs} storage=${store}", 0);
+ DWN_MSG("[initargs=%s]\n", getenv("initargs"));
+ }
+ else if(!strstr(getenv("bootargs"), "storage") && getenv("bootargs") && 0){//user not configure storage in 'bootargs' of default env
+ rc = run_command("setenv bootargs ${bootargs} storage=${store}", 0);
+ DWN_MSG("[bootargs=%s]\n", getenv("bootargs"));
+ }
+ }
+
+ DWN_MSG("Set upgrade_step to %s\n", upgrade_step);
+ rc = setenv("upgrade_step", (char*)upgrade_step);
+ if (rc) {
+ DWN_ERR("Fail to set upgraded_step to 1\n");
+ }
+ rc = run_command("saveenv", 0);
+ if (rc) {
+ DWN_ERR("Fail to saveenv to flash\n");
+ }
+ udelay(200);
+
+ return rc;
+}
+
+static int _optimus_set_reboot_mode(const int cfgFlag)
+{
+ switch (cfgFlag)
+ {
+ case OPTIMUS_BURN_COMPLETE__REBOOT_UPDATE:
+ /*reboot_mode = AMLOGIC_UPDATE_REBOOT; */
+ break;
+
+ case OPTIMUS_BURN_COMPLETE__REBOOT_SDC_BURN:
+ /*reboot_mode = MESON_SDC_BURNER_REBOOT; */
+ break;
+
+ case OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL:
+ default:
+ /*reboot_mode = AMLOGIC_NORMAL_BOOT; */
+ break;
+ }
+
+ return 0;
+}
+
+void optimus_reset(const int cfgFlag)
+{
+ unsigned i = 0x100;
+
+ //writel(0, CONFIG_TPL_BOOT_ID_ADDR);//clear boot_id
+
+ //set reboot mode
+ _optimus_set_reboot_mode(cfgFlag);
+
+#if defined(CONFIG_M6) || defined(CONFIG_M6TV)
+ //if not clear, uboot command reset will fail -> blocked
+ *((volatile unsigned long *)P_AO_RTI_STATUS_REG0) = 0;
+#endif//#if defined(CONFIG_M6) || defined(CONFIG_M6TV)
+ printf("Burn Reboot...\n");//Add printf to delay to save env
+ while (--i) ;
+
+ /*disable_interrupts();*/
+ reset_cpu(0);
+
+ while (i++)
+ {
+ unsigned ret = i;
+ unsigned mask = 1U<<20;
+
+ mask -= 1;
+ ret &= mask;
+ if (!ret) {
+ printf("To reseting...\n");
+ }
+ }
+}
+
+void optimus_poweroff(void)
+{
+ //writel(0, CONFIG_TPL_BOOT_ID_ADDR);//clear boot_id
+ /*reboot_mode_clear();*/
+
+#if CONFIG_POWER_KEY_NOT_SUPPORTED_FOR_BURN
+ DWN_MSG("stop here as poweroff and powerkey not supported in platform!\n");
+ DWN_MSG("You can <Ctrl-c> to reboot\n");
+ while (!ctrlc()) continue;
+ optimus_reset(OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL);
+#else
+ printf("To poweroff\n");
+ run_command("poweroff", 0);
+ printf("!!!After run command poweroff!!\n");
+#endif// #if CONFIG_POWER_KEY_NOT_SUPPORTED_FOR_BURN
+
+ return;
+}
+
+//use choice = 0xfu to query is_burn_completed
+int optimus_burn_complete(const int choice)
+{
+ static unsigned _isBurnComplete = 0;
+ int rc = 0;
+
+ switch (choice)
+ {
+ case OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_POWERKEY://wait power key to power off, for sdc_burn
+ {
+#if CONFIG_POWER_KEY_NOT_SUPPORTED_FOR_BURN
+ DWN_MSG("stop here as poweroff and powerkey not supported in platform!\n");
+ DWN_MSG("You can <Ctrl-c> to reboot\n");
+
+ while (!ctrlc()) continue;
+ optimus_reset(OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL);
+#endif// #if CONFIG_POWER_KEY_NOT_SUPPORTED_FOR_BURN
+ DWN_MSG("PLS short-press power key to shut down\n");
+ do
+ {
+ rc = run_command("getkey", 0);
+ }while(rc);
+ }
+ case OPTIMUS_BURN_COMPLETE__POWEROFF_DIRECT:
+ optimus_poweroff();
+ break;
+
+ case OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_DISCONNECT:
+ DWN_MSG("Pls un-plug USB line to poweroff\n");
+ _isBurnComplete = 0xefe;
+ break;
+ case OPTIMUS_BURN_COMPLETE__QUERY:
+ return (0xefe == _isBurnComplete);
+
+ case OPTIMUS_BURN_COMPLETE__REBOOT_UPDATE:
+ case OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL:
+ {
+ optimus_reset(choice);
+ }
+ break;
+
+
+ default:
+ rc = 1;
+ DWN_ERR("Error burn_complete flag %d\n", choice);
+ }
+
+ return rc;
+}
+
+#if ROM_BOOT_SKIP_BOOT_ENABLED
+int optimus_enable_romboot_skip_boot(void)
+{
+#ifdef CONFIG_MESON_TRUSTZONE
+ writel(meson_trustzone_sram_read_reg32(SKIP_BOOT_REG_BACK_ADDR), P_AO_RTI_STATUS_REG0); //disable watchdog
+#else
+ /*writel(readl(SKIP_BOOT_REG_BACK_ADDR), P_AO_RTI_STATUS_REG0); //disable watchdog*/
+#endif// #ifdef CONFIG_MESON_TRUSTZONE
+
+ //enable romboot skip_boot function to jump to usb boot
+ /*DWN_MSG("Skip boot flag[%x]\n", (unsigned int)readl(P_AO_RTI_STATUS_REG0));*/
+ return 0;
+}
+#endif// #if ROM_BOOT_SKIP_BOOT_ENABLED
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_download.h b/drivers/usb/gadget/v2_burning/v2_common/optimus_download.h
new file mode 100644
index 0000000000..fdb285aeea
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_download.h
@@ -0,0 +1,203 @@
+/*
+ * \file optimus_download.h
+ * \brief common included files for optimus_*.c
+ *
+ * \version 1.0.0
+ * \date 2013/5/3
+ * \author Sam.Wu <yihui.wu@Amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+
+#ifndef __OPTIMUS_DOWNLOAD_H__
+#define __OPTIMUS_DOWNLOAD_H__
+
+
+int optimus_buf_manager_init(const unsigned mediaAlignSz);
+int optimus_buf_manager_exit(void);
+int optimus_buf_manager_tplcmd_init(const char* mediaType, const char* partName, u64 partBaseOffset,
+ const char* imgType, const u64 pktTotalSz, const int isUpload,
+ const unsigned itemSizeNotAligned);
+int optimus_buf_manager_get_buf_for_bulk_transfer(char** pBuf, const unsigned wantSz, const unsigned sequenceNo, char* errInfo);
+int optimus_buf_manager_report_transfer_complete(const u32 transferSz, char* errInfo);
+int is_largest_data_transferring(void);
+int optimus_buf_manager_get_command_data_for_upload_transfer(u8* cmdDataBuf, const unsigned bufLen);
+
+int optimus_download_init(void);
+int optimus_download_exit(void);
+int optimus_parse_download_cmd(int argc, char* argv[]);
+int optimus_parse_img_download_info(const char* part_name, const u64 imgSz, const char* imgType, const char* mediaType, const u64 partBaseOffset);
+int is_optimus_to_burn_ready(void);//ready before burn
+u32 optimus_download_img_data(const u8* data, const u32 size, char* errInfo);
+int is_optimus_on_burn(void); //is now transferring image
+int is_optimus_pre_burn(void); //is now has get "download command"
+int optimus_media_download_verify(const int argc, char * const argv[], char *info);
+
+u32 optimus_dump_storage_data(u8* pBuf, const u32 wantSz, char* errInfo);
+
+
+//for key opearations
+//
+int v2_key_command(const int argc, char * const argv[], char *info);
+
+/*
+ *This fucntion called by mread command, mread= bulkcmd "upload key .." + n * upload transfer, for key n==1
+ *Attentions: return 0 if success, else failed
+ *@keyName: key name in null-terminated c style string
+ *@keyVal: the buffer to read back the key value
+ *@keyValLen: keyVal len is strict when read, i.e, user must know the length of key he/she wnat to read!!
+ *@errInfo: start it with success if burned ok, or format error info into it tell pc burned failed
+ */
+int v2_key_read(const char* keyName, u8* keyVal, const unsigned keyValLen, char* errInfo, unsigned* fmtLen);
+
+/*
+ *This fucntion called by mwrite command, mread= bulkcmd "download key .." + n * download transfer, for key n==1
+ *Attentions: return value is the key length if burn sucess
+ *@keyName: key name in null-terminated c style string
+ *@keyVal: key value download from USB, "the value for sepecial keyName" may need de-encrypt by user code
+ *@keyValLen: the key value downloaded from usb transfer!
+ *@errInfo: start it with success if burned ok, or format error info into it tell pc burned failed
+ */
+unsigned v2_key_burn(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo);
+
+#define DDR_MEM_ADDR_START ( CONFIG_SYS_SDRAM_BASE + (16<<20) )
+
+// |<---Back 2M---->|<------------USB transfer Buf 64 ----------->|<--Backed sparse format info for verify-->|
+// Back buf Transfer buf
+//TODO: move memory mapping to comman shared header file
+//FIXME:Make sure [0x818<<20, 0x839<<20] not used by others
+//[Buffer 0] DRAM_START, DRAM_START+2M, This range can't be accessed
+//[Buffer 1] Buffer to Back up partition image data that not write back to flash,
+#define OPTIMUS_SPARSE_IMG_LEFT_DATA_ADDR_LOW (DDR_MEM_ADDR_START + (2U<<20))//Don't access First 1M address
+#define OPTIMUS_SPARSE_IMG_LEFT_DATA_MAX_SZ (0X2<<20) //back up address for sparse image, 2M
+
+//[Buffer 2] This 64M buffer is used to cache image data received from USB download,
+// This Buffer size should be 64M, other size has pending bugs when sparse image is very large.
+#define OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR (OPTIMUS_SPARSE_IMG_LEFT_DATA_ADDR_LOW + OPTIMUS_SPARSE_IMG_LEFT_DATA_MAX_SZ)
+#define OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ (0X40<<20)//64M
+
+#define OPTIMUS_DOWNLOAD_SLOT_SZ (64<<10) //64K
+#define OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS (16) //64K
+#define OPTIMUS_DOWNLOAD_SLOT_NUM (OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ/OPTIMUS_DOWNLOAD_SLOT_SZ)
+
+//[Buffer 3] This buffer is used to Back up sparse chunk headers for verifying sparse image
+#define OPTIMUS_DOWNLOAD_SPARSE_INFO_FOR_VERIFY (OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR + OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ)
+#define OPTIMUS_DOWNLOAD_SPS_VERIFY_BACK_INFO_SZ (0x2U<<20)
+
+//[Buffer 4] This buffer is used for filling filled-value CHUNK_TYPE_FILL type sparse chunk,
+#define OPTIMUS_SPARSE_IMG_FILL_VAL_BUF (OPTIMUS_DOWNLOAD_SPARSE_INFO_FOR_VERIFY + OPTIMUS_DOWNLOAD_SPS_VERIFY_BACK_INFO_SZ)
+#define OPTIMUS_SPARSE_IMG_FILL_BUF_SZ OPTIMUS_DOWNLOAD_SLOT_SZ
+
+//[Buffer 5] This buffer to cache header of burning package when not usb burning
+#define OPTIMUS_BURN_PKG_HEAD_BUF_ADDR (OPTIMUS_SPARSE_IMG_FILL_VAL_BUF + OPTIMUS_SPARSE_IMG_FILL_BUF_SZ)
+#define OPTIMUS_BURN_PKG_HEAD_BUF_SZ (1U<<20)//1M should be enough!
+
+//[Buffer 6] This buffer is used to cache logo resources for upgrading
+////buffer to display logo, 10M used now
+#define OPTIMUS_DOWNLOAD_DISPLAY_BUF (OPTIMUS_BURN_PKG_HEAD_BUF_ADDR + OPTIMUS_BURN_PKG_HEAD_BUF_SZ)
+#define OPTIMUS_DOWNLOAD_BUF_FREE_USE (OPTIMUS_DOWNLOAD_DISPLAY_BUF + (10U<<20))//free buffer not used by downloading, 2 + 64 + 2 + 10
+
+#define OPTIMUS_VFAT_IMG_WRITE_BACK_SZ (OPTIMUS_DOWNLOAD_SLOT_SZ*1)//update complete alogrithm if change it
+#define OPTIMUS_SIMG_WRITE_BACK_SZ OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ
+#define OPTIMUS_MEMORY_WRITE_BACK_SZ (0X2U<<30)//2GBytes
+#define OPTIMUS_BOOTLOADER_MAX_SZ (2U<<20)//max size is 2M ??
+
+#define OPTIMUS_SHA1SUM_BUFFER_ADDR OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR
+#define OPTIMUS_SHA1SUM_BUFFER_LEN (OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ/8) //16M each time
+
+//As key size < 64K, So buffer [OPTIMUS_SPARSE_IMG_LEFT_DATA_ADDR_LOW, OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR) not used when download key
+#define OPTIMUS_KEY_DECRYPT_BUF OPTIMUS_SPARSE_IMG_LEFT_DATA_ADDR_LOW//buffer for decrypt the key
+#define OPTIMUS_KEY_DECRYPT_BUF_SZ OPTIMUS_DOWNLOAD_SLOT_SZ
+
+#define COMPILE_TYPE_CHK(expr, t) typedef char t[(expr) ? 1 : -1]
+#define COMPILE_TIME_ASSERT(expr) typedef char assert_type[(expr) ? 1 : -1]
+
+#define OPT_DOWN_OK 0
+#define OPT_DOWN_FAIL 1
+#define OPT_DOWN_TRUE 1
+#define OPT_DOWN_FALSE 0
+
+#define OPTIMUS_MEDIA_TYPE_NAND 0 //nand is default
+#define OPTIMUS_MEDIA_TYPE_SDMMC 1
+#define OPTIMUS_MEDIA_TYPE_SPIFLASH 2
+#define OPTIMUS_MEDIA_TYPE_STORE 3 //store stands for one of nand/emmc/spi, which smart identified by stoarge driver
+#define OPTIMUS_MEDIA_TYPE_MEM 4 //memory, dram and sram
+#define OPTIMUS_MEDIA_TYPE_KEY_UNIFY 5
+
+//Following for optimus_simg2img.c
+int optimus_simg_probe(const u8* source, const u32 length);
+int optimus_simg_parser_init(const u8* source);
+u32 optimus_cb_simg_write_media(const unsigned destAddrInSec, const unsigned dataSzInBy, const char* data);
+int optimus_simg_to_media(char* simgPktHead, const u32 pktLen, u32* unParsedDataLen, const u32 flashAddrInSec);
+int optimus_sparse_get_chunk_data(u8** head, u32* headSz, u32* dataSz, u64* dataOffset);
+int optimus_sparse_back_info_probe(void);
+
+unsigned add_sum(const void* pBuf, const unsigned size);//Add-sum used for 64K transfer
+
+//outStr will be null-terminater after format
+int optimus_hex_data_2_ascii_str(const unsigned char* hexData, const unsigned nBytes, char* outStr, const unsigned strSz);
+
+//for prompting step info
+int optimus_progress_init(const unsigned itemSzHigh, const unsigned itemSzLow, const u32 startStep, const u32 endStep);
+int optimus_progress_exit(void);
+int optimus_update_progress(const unsigned thisBurnSz);
+
+#define DWN_ERR(fmt ...) printf("ERR(%s)L%d:", __FILE__, __LINE__);printf(fmt)
+#define DWN_MSG(fmt ...) printf("msg:"fmt)
+#define DWN_DBG(...)
+#define DWN_HERE() printf("f(%s)L%d\n", __FILE__, __LINE__)
+
+//for fat fs
+long do_fat_fopen(const char *filename);
+long do_fat_fread(int fd, __u8 *buffer, unsigned long maxsize);
+void do_fat_fclose(int fd);
+s64 do_fat_get_fileSz(const char* imgItemPath);
+int do_fat_fseek(int fd, const __u64 offset, int wherehence);
+unsigned do_fat_get_bytesperclust(int fd);
+int optimus_device_probe(const char* interface, const char* inPart);
+
+//<0 if failed, 0 is normal, 1 is sparse, others reserved
+int do_fat_get_file_format(const char* imgFilePath, unsigned char* pbuf, const unsigned bufSz);
+
+//common internal function
+int optimus_erase_bootloader(char* info);
+void optimus_reset(const int cfgFlag);
+int optimus_storage_init(int toErase);//init dest burning staorge
+int optimus_storage_exit(void);
+int is_optimus_storage_inited(void);
+void optimus_poweroff(void);
+int optimus_burn_complete(const int choice);
+int is_the_flash_first_burned(void);
+int optimus_set_burn_complete_flag(void);//set 'upgrade_step 1' after burnning success
+
+#define OPTIMUS_WORK_MODE_NONE 0
+#define OPTIMUS_WORK_MODE_USB_UPDATE (0xefe5)
+#define OPTIMUS_WORK_MODE_USB_PRODUCE (0xefe6)
+#define OPTIMUS_WORK_MODE_SDC_UPDATE (0xefe7)
+#define OPTIMUS_WORK_MODE_SDC_PRODUCE (0xefe8)
+#define OPTIMUS_WORK_MODE_SYS_RECOVERY (0xefe9)
+int optimus_work_mode_get(void);
+int optimus_work_mode_set(int workmode);
+
+#define OPTIMUS_BURN_COMPLETE__POWEROFF_DIRECT (0X0)
+#define OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL (0x1)
+#define OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_POWERKEY (0x2)
+#define OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_DISCONNECT (0x3)
+#define OPTIMUS_BURN_COMPLETE__REBOOT_SDC_BURN (0xdc)
+#define OPTIMUS_BURN_COMPLETE__REBOOT_UPDATE (0xeb)
+#define OPTIMUS_BURN_COMPLETE__QUERY (0xe1)
+
+#if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8)
+#define ROM_BOOT_SKIP_BOOT_ENABLED 0//skip boot function is supported by romboot
+#else
+#define ROM_BOOT_SKIP_BOOT_ENABLED 0
+#endif// #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8)
+int optimus_enable_romboot_skip_boot(void);
+
+//ENV for auto jump into producing
+#define _ENV_TIME_OUT_TO_AUTO_BURN "identifyWaitTime"
+#define AML_SYS_RECOVERY_PART "aml_sysrecovery"
+
+#endif//ifndef __OPTIMUS_DOWNLOAD_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_download_key.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_download_key.c
new file mode 100644
index 0000000000..e7a8a2f60c
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_download_key.c
@@ -0,0 +1,658 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: v2_download_key.c
+ *
+ * Version: 1.0
+ * Created: 2013/9/4 14:10:07
+ * Compiler: gcc
+ *
+ * Author: Sam Wu (yihui.wu@amlogic.com)
+ * Organization: Amlogic Inc.
+ *
+ * Revision: none
+ * Description: Funcitions and command to burn keys with key_unify driver
+ *
+ * =====================================================================================
+ */
+#include "../v2_burning_i.h"
+#include <amlogic/keyunify.h>
+
+extern ssize_t uboot_key_put(char *device,char *key_name, char *key_data,int key_data_len,int ascii_flag);
+extern ssize_t uboot_key_get(char *device,char *key_name, char *key_data,int key_data_len,int ascii_flag);
+extern ssize_t uboot_key_query(char *device,char *key_name,unsigned int *keystate);
+
+#ifndef CMD_BUFF_SIZE
+#define CMD_BUFF_SIZE (512)
+#endif// #ifndef CMD_BUFF_SIZE
+
+#define HDCP2_RX_LC128_LEN (36)
+#define HDCP2_RX_KEY_LEN (862)
+#pragma pack(push, 1)
+typedef struct _Hdcp2RxKeyFmt{
+ unsigned version;
+ char lc128[HDCP2_RX_LC128_LEN];
+ char keyVal[HDCP2_RX_KEY_LEN];
+}Hdcp2RxKeyFmt_t;
+#pragma pack(pop)
+
+#define HDCP2_RX_KEY_TOTAL_LEN sizeof(Hdcp2RxKeyFmt_t)
+#define HDCP2_RX_KEY_LC128_NAME "hdcp2lc128"
+#define HDCP2_RX_KEY_NAME "hdcp2key"
+#define HDCP2_RX_KEY_VERSION (0x02000000U)
+
+static char generalDataChange(const char input)
+{
+ int i;
+ char result = 0;
+
+ for (i=0; i<8; i++) {
+ if ((input & (1<<i)) != 0)
+ result |= (1<<(7-i));
+ else
+ result &= ~(1<<(7-i));
+ }
+
+ return result;
+}
+
+static void hdcp2DataEncryption(const unsigned len, const char *input, char *out)
+{
+ int i = 0;
+
+ for (i=0; i<len; i++)
+ *out++ = generalDataChange(*input++);
+}
+
+static void hdcp2DataDecryption(const unsigned len, const char *input, char *out)
+{
+ int i = 0;
+
+ for (i=0; i<len; i++)
+ *out++ = generalDataChange(*input++);
+}
+
+static int _hdcp2_rx_key_Encrypt_before_burn(const char* keyName, char* keyVal, const unsigned keyValLen,
+ const u8** keyRealVal, unsigned* keyRealValLen, char* encryptBuf)
+{
+ Hdcp2RxKeyFmt_t* pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)keyVal;
+
+ if (HDCP2_RX_KEY_TOTAL_LEN != keyValLen) {
+ DWN_ERR("hdcp2 rx len unsupported. want %d but get %d\n", HDCP2_RX_KEY_TOTAL_LEN, keyValLen);
+ return __LINE__;
+ }
+ if (HDCP2_RX_KEY_VERSION != pHdcp2RxKey->version) {
+ DWN_ERR("Version value 0x%x is error, should be 0x%x\n", pHdcp2RxKey->version, HDCP2_RX_KEY_VERSION);
+ return __LINE__;
+ }
+
+ hdcp2DataEncryption(keyValLen, keyVal, encryptBuf);
+ DWN_MSG("Ecnrypt hdcp2 END.\n");
+ *keyRealVal = (u8*)encryptBuf;
+ *keyRealValLen = keyValLen;
+
+ return 0;
+}
+
+static int _hdcp2_rx_key_burn(const char* keyName, char* keyVal, const unsigned keyValLen)
+{
+ int err = -EINVAL;
+ const char* keyDevice = NULL;
+ int ascii_flag = 0;
+ Hdcp2RxKeyFmt_t* pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)keyVal;
+ int flashKeyLen = 0;
+ char* flashKeyVal = NULL;
+ char* flashKeyName = NULL;
+
+ keyDevice = key_unify_query_key_device((char*)keyName);
+ if (strcmp(keyDevice, "nandkey")) {
+ DWN_ERR("hdcp2 rx only support nandkey yet!\n");
+ return __LINE__;
+ }
+#if 0//key value already ecnrypted!! in func '_hdcp2_rx_key_Encrypt_before_burn'
+ if (HDCP2_RX_KEY_TOTAL_LEN != keyValLen) {
+ DWN_ERR("hdcp2 rx len unsupported. want %d but get %d\n", HDCP2_RX_KEY_TOTAL_LEN, keyValLen);
+ return __LINE__;
+ }
+ if (HDCP2_RX_KEY_VERSION != pHdcp2RxKey->version) {
+ DWN_ERR("Version value 0x%x is error, should be 0x%x\n", pHdcp2RxKey->version, HDCP2_RX_KEY_VERSION);
+ return __LINE__;
+ }
+#endif//
+
+ ascii_flag = strcmp("hexascii", key_unify_query_key_format((char*)keyName)) ? 0 : 1 ;
+
+ DWN_MSG("To Burn hdcp2 to flash\n");
+ flashKeyLen = HDCP2_RX_LC128_LEN;
+ flashKeyVal = (char*)&pHdcp2RxKey->lc128;
+ flashKeyName = (char*)HDCP2_RX_KEY_LC128_NAME;
+ err = uboot_key_put("auto", flashKeyName, flashKeyVal, flashKeyLen, ascii_flag);
+ if (err < 0) {
+ DWN_ERR("Fail to burn \"%s\" to flash\n", flashKeyName);
+ return __LINE__;
+ }
+ DWN_MSG("Burn \"%s\" to flash OK.\n", flashKeyName);
+
+ flashKeyLen = HDCP2_RX_KEY_LEN;
+ flashKeyVal = (char*)&pHdcp2RxKey->keyVal;
+ flashKeyName = (char*)HDCP2_RX_KEY_NAME;
+ /*hdcp2DataEncryption(flashKeyLen, flashKeyVal, encryptBuf);*/
+ err = uboot_key_put("auto", flashKeyName, flashKeyVal, flashKeyLen, ascii_flag);
+ if (err < 0) {
+ DWN_ERR("Fail to burn \"%s\" to flash\n", flashKeyName);
+ return __LINE__;
+ }
+ DWN_MSG("Burn \"%s\" to flash OK.\n", flashKeyName);
+
+ err = key_unify_write((char*)keyName, (u8*)&pHdcp2RxKey->version, 4);
+ DWN_MSG("%s, ret 0x%x\n", __func__, err);
+ err = err >=0 ? 0 : __LINE__;
+ DWN_MSG("Write HDCP2 version end\n");
+
+ return err;
+}
+
+static int _hdcp2_rx_key_read(char* keyName, char* keyValBuf, const unsigned keyValBufCap, unsigned* pKeyLen)
+{
+ int err = -EINVAL;
+ const char* keyDevice = NULL;
+ int ascii_flag = 0;
+ Hdcp2RxKeyFmt_t* pHdcp2RxKey = (Hdcp2RxKeyFmt_t*)keyValBuf;
+ unsigned flashKeyLen = 0;
+ char* flashKeyVal = NULL;
+ const char* flashKeyName = NULL;
+
+ DWN_MSG("To read hdcp2.\n");
+ keyDevice = key_unify_query_key_device(keyName);
+ if (strcmp(keyDevice, "nandkey")) {
+ DWN_ERR("hdcp2 rx only support nandkey yet!\n");
+ return __LINE__;
+ }
+ if (HDCP2_RX_KEY_TOTAL_LEN > keyValBufCap) {
+ DWN_ERR("BufSz for hdcp2 rx len %d < least len %d\n", keyValBufCap, HDCP2_RX_KEY_TOTAL_LEN);
+ return __LINE__;
+ }
+ ascii_flag = strcmp("hexascii", key_unify_query_key_format(keyName)) ? 0 : 1 ;
+
+ flashKeyLen = HDCP2_RX_LC128_LEN;
+ flashKeyName = HDCP2_RX_KEY_LC128_NAME;
+ flashKeyVal = (char*)&pHdcp2RxKey->lc128;
+ err = uboot_key_get("auto", (char*)flashKeyName, flashKeyVal, flashKeyLen, ascii_flag);
+ if (err < 0) {
+ DWN_ERR("Fail to read \"%s\" from flash\n", flashKeyName);
+ return __LINE__;
+ }
+ *pKeyLen = flashKeyLen;
+
+ flashKeyLen = HDCP2_RX_KEY_LEN;
+ flashKeyName = HDCP2_RX_KEY_NAME;
+ flashKeyVal = (char*)&pHdcp2RxKey->keyVal;
+ err = uboot_key_get("auto", (char*)flashKeyName, flashKeyVal, flashKeyLen, ascii_flag);
+ if (err < 0) {
+ DWN_ERR("Fail to read \"%s\" from flash\n", flashKeyName);
+ return __LINE__;
+ }
+ *pKeyLen += flashKeyLen;
+
+ err = key_unify_read(keyName, (u8*)&pHdcp2RxKey->version, 4, &flashKeyLen);
+ if (err < 0) {
+ DWN_ERR("Fail to read \"%s\" from flash\n", keyName);
+ return __LINE__;
+ }
+ *pKeyLen += 4;
+
+ return 0;
+}
+
+int decrypt_hdcp_license_to_raw_value(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo,
+ const u8** keyRealVal, unsigned* keyRealValLen,
+ char* decryptBuf, const unsigned decryptBufSz)
+{
+ int ret = 0;
+ decryptBuf = decryptBuf;//avoid compiler warning as not used
+
+ DWN_MSG("hdcp down in len %d\n", keyValLen);
+ if (288 == keyValLen) //288 means license data is raw, not including the 20Bytes sha value
+ {
+ return 0;//ok, it's raw data if size is 288
+ }
+ else if(308 == keyValLen)
+ {
+ const unsigned shaSumLen = 20;
+ const unsigned licLen = keyValLen - shaSumLen;
+ const u8* orgSum = keyVal + licLen;
+ u8 genSum[shaSumLen];
+
+ sha1_csum((u8*)keyVal, licLen, genSum);
+
+ ret = memcmp(orgSum, genSum, shaSumLen);
+ if (ret) {
+ const unsigned fmtStrLen = shaSumLen * 2 + 2;
+ char org_sha1Str[fmtStrLen];
+ char gen_sha1Str[fmtStrLen];
+
+ optimus_hex_data_2_ascii_str(orgSum, shaSumLen, org_sha1Str, fmtStrLen);
+ optimus_hex_data_2_ascii_str(genSum, shaSumLen, gen_sha1Str, fmtStrLen);
+ sprintf(errInfo, "failed:hdcp, orgSum[%s] != genSum[%s]\n", org_sha1Str, gen_sha1Str);
+ DWN_ERR(errInfo);
+
+ return EINVAL;
+ }
+ DWN_MSG("Verify hdcp key with sha1sum OK\n");
+
+ *keyRealValLen = licLen;
+ return 0;
+ }
+ else
+ {
+ sprintf(errInfo, "failed:hdcp len %d is invalid\n", keyValLen);
+ DWN_ERR(errInfo);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int decrypt_mac_str_fmt_4_media(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo,
+ const u8** keyRealVal, unsigned* keyRealValLen,
+ char* decryptBuf, const unsigned decryptBufSz)
+{
+ int index = 0;
+ const char* keyDevice = NULL;
+
+ if (17 != keyValLen) //288 means license data is raw, not including the 20Bytes sha value
+ {
+ sprintf(errInfo, "failed:mac len %d is invalid, must be 17\n", keyValLen);
+ DWN_ERR(errInfo);
+ return -EINVAL;
+ }
+
+ for (index = 2; index < 17; index += 3) {
+ const char c = keyVal[index];
+ if (':' != c) {
+ sprintf(errInfo, "failed:L%d:mac str(%s) fmt err at index[%d]\n", __LINE__, keyVal, index);
+ DWN_ERR(errInfo);
+ return -EINVAL;
+ }
+ }
+
+ for (index = 0; index < 17; index += 3) {
+ int k = 0;
+ for (k = 0; k < 2; ++k) {
+ const char c = keyVal[index + k];
+ if (!( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )) {
+ sprintf(errInfo, "failed:L%d:mac str(%s) fmt err at index[%d]\n", __LINE__, keyVal, index);
+ DWN_ERR(errInfo);
+ return -EINVAL;
+ }
+ }
+ }
+
+ keyDevice = key_unify_query_key_device((char*)keyName);
+ DWN_MSG("write %s as %s\n", keyName, keyDevice);
+ if (strcmp("efusekey", keyDevice)) //not efusekey, not need to decrypt
+ {
+ return 0;
+ }
+
+ *keyRealVal = (u8*)decryptBuf;//change the keyRealVal to decryptBuf
+ *keyRealValLen = 6;
+
+ for (index = 0; index < 17; index += 3) {
+ const char *theByteStr = (const char*)keyVal + index;
+ int k = 0;
+ unsigned byteSum = 0;
+
+ for (k = 0; k < 2; ++k) {
+ const char c = *theByteStr++;
+
+ if (c >= '0' && c <= '9') {
+ byteSum += c - '0' + 0x0;
+ }
+ else if (c >= 'a' && c <= 'f'){
+ byteSum += c - 'a' + 0xa;
+ }
+ else if (c >= 'A' && c <= 'F'){
+ byteSum += c - 'A' + 0XA;
+ }
+ else{
+ sprintf(errInfo, "failed:Exception when burn key for efuse, c=%x\n", c);
+ return -EINVAL;
+ }
+ byteSum <<= 4 * (1 - k);
+ }
+ DWN_DBG("byteSum=0x%x\n", byteSum);
+ *decryptBuf++ = byteSum;
+ }
+
+ return 0;
+}
+
+/*
+ * Check or Decrypt the key from usb to real key value before burn to device
+ *Only depending the keyName to decide whether the key value needed special disposed !!
+ * */
+int check_or_decrypt_raw_usb_key_value(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo,
+ const u8** keyRealVal, unsigned* keyRealValLen)
+{
+ int ret = 0;
+ char* keyDecryptBuf = (char*)OPTIMUS_KEY_DECRYPT_BUF;
+ const unsigned keyDecryptBufSz = OPTIMUS_KEY_DECRYPT_BUF_SZ;
+
+ *keyRealVal = keyVal;
+ *keyRealValLen = keyValLen;
+
+ //do with the special key value
+ if (!strcmp("hdcp", keyName))
+ {
+ ret = decrypt_hdcp_license_to_raw_value(keyName, keyVal, keyValLen, errInfo,
+ keyRealVal, keyRealValLen, keyDecryptBuf, keyDecryptBufSz);
+ }
+ else if (!strcmp("mac", keyName) || !strcmp("mac_bt", keyName) || !strcmp("mac_wifi", keyName))
+ {
+ ret = decrypt_mac_str_fmt_4_media(keyName, keyVal, keyValLen, errInfo,
+ keyRealVal, keyRealValLen, keyDecryptBuf, keyDecryptBufSz);
+ }
+ else if(!strcmp("hdcp2", keyName))
+ {
+ ret = _hdcp2_rx_key_Encrypt_before_burn(keyName, (char*)keyVal, keyValLen, keyRealVal, keyRealValLen, keyDecryptBuf);
+ }
+ else if(!strcmp("your_key_name", keyName))
+ {
+ //TODO:Add your key decrypt or check code here
+ }
+
+ return ret;
+}
+
+/*
+ *This fucntion called by mwrite command, mread= bulkcmd "download key .." + n * download transfer, for key n==1
+ *Attentions: "return value is the key length" if burn sucess
+
+ *@keyName: key name in null-terminated c style string
+ *@keyVal: key value download from USB, "the value for sepecial keyName" may need de-encrypt by user code
+ *@keyValLen: the key value downloaded from usb transfer!
+ *@errInfo: start it with success if burned ok, or format error info into it tell pc burned failed
+ */
+unsigned v2_key_burn(const char* keyName, const u8* keyVal, const unsigned keyValLen, char* errInfo)
+{
+ int ret = 0;
+ unsigned writtenLen = 0;
+ const u8* keyRealVal = NULL;//the real value to burn to flash/efuse
+ unsigned keyRealValLen = 0;
+
+ ret = check_or_decrypt_raw_usb_key_value(keyName, keyVal, keyValLen, errInfo,
+ &keyRealVal, &keyRealValLen);
+ if (ret) {
+ DWN_ERR("Fail to check_or_decrypt_raw_usb_key_value, writtenLen=0x%x\n", writtenLen);
+ return 0;
+ }
+
+ if (!strcmp("hdcp2", keyName))
+ {
+ ret = _hdcp2_rx_key_burn(keyName, (char*)keyRealVal, keyValLen);
+ }
+ else{//not hdcp2
+ ret = key_unify_write((char*)keyName, (unsigned char*)keyRealVal, keyRealValLen);
+ }
+ DWN_MSG("%s, ret 0x%x\n", __func__, ret);
+ writtenLen = ret >=0 ? keyValLen : 0;
+
+ return writtenLen;
+}
+
+//Trnasform data format after read, To make data read back equal to write
+static int _key_read_fmt_transform_4_usr(const char* keyName,
+ const unsigned keyValBufCap, u8* keyVal, const unsigned keyLenInDevice, unsigned* fmtLen)
+{
+ int rc = 0;
+ char* decryptBuf = (char*)OPTIMUS_KEY_DECRYPT_BUF;
+
+ if (keyValBufCap < keyLenInDevice) {
+ DWN_ERR("bufsz %d < real sz %d\n", keyValBufCap, keyLenInDevice);
+ return __LINE__;
+ }
+ //keyValBufCap > keyLenInDevice
+ if (!strcmp("mac", keyName) || !strcmp("mac_bt", keyName) || !strcmp("mac_wifi", keyName))
+ {
+ if (6 == keyLenInDevice)
+ {
+ int i = 0;
+
+ rc = optimus_hex_data_2_ascii_str(keyVal, keyLenInDevice, decryptBuf, keyValBufCap);
+ if (rc) {
+ DWN_ERR("Fail to format mac hex data to str, rc=%d\n", rc);
+ return __LINE__;
+ }
+ for (i = 0; i < keyLenInDevice; ++i) {
+ *keyVal++ = decryptBuf[i * 2];
+ *keyVal++ = decryptBuf[i * 2 + 1];
+ *keyVal++ = ':';
+ }
+ *--keyVal = 0;
+ *fmtLen = keyLenInDevice * 3 - 1;
+
+ return 0;
+ }
+ else if(17 != keyLenInDevice){
+ DWN_ERR("mac/bt/wifi len in device must be 17 or 6, but %d\n", keyLenInDevice);
+ return __LINE__;
+ }
+ }
+ else if(!strcmp("hdcp2", keyName))
+ {
+ //Decrypt hdcp2_rx key for miracast
+ hdcp2DataDecryption(keyLenInDevice, (char*)keyVal, decryptBuf);
+ memcpy(keyVal, decryptBuf, keyLenInDevice);
+ }
+ else{
+
+ }
+
+ return rc;
+}
+
+/*
+ *This fucntion called by mread command, mread= bulkcmd "upload key .." + n * upload transfer, for key n==1
+ *Attentions: return 0 if success, else failed
+ *@keyName: key name in null-terminated c style string
+ *@keyVal: the buffer to read back the key value
+ *@keyValLen: keyVal len is strict when read, i.e, user must know the length of key he/she wnat to read!!
+ *@errInfo: start it with success if burned ok, or format error info into it tell pc burned failed
+ */
+int v2_key_read(const char* keyName, u8* keyVal, const unsigned keyValLen, char* errInfo, unsigned* fmtLen)
+{
+ unsigned reallen = 0;
+ unsigned keyIsBurned = -1;
+ unsigned keypermit = -1;
+ int rc = 0;
+
+ rc = key_unify_query((char*)keyName, &keyIsBurned, &keypermit);
+ if (rc < 0 || 1 != keyIsBurned) {
+ sprintf(errInfo, "failed to query key state, rc %d, keyIsBurned=%d\n", rc, keyIsBurned);
+ DWN_ERR(errInfo);
+ return __LINE__;
+ }
+
+ if (!strcmp("hdcp2", keyName))
+ {
+ rc = _hdcp2_rx_key_read((char*)keyName, (char*)keyVal, keyValLen, &reallen);
+ if (rc) {
+ sprintf(errInfo, "failed:key_read rc %d\n", rc);
+ DWN_ERR(errInfo);
+ return __LINE__;
+ }
+ }
+ else
+ {
+ rc = key_unify_read((char*)keyName, keyVal, keyValLen, &reallen);
+ if (rc < 0 || !reallen) {
+ sprintf(errInfo, "failed:key_read rc %d, reallen(%d), want len(%d)\n", rc, reallen, keyValLen);
+ DWN_ERR(errInfo);
+ return __LINE__;
+ }
+ }
+
+ *fmtLen = reallen;
+ rc = _key_read_fmt_transform_4_usr(keyName, keyValLen, keyVal, reallen, fmtLen);
+
+ return rc;
+}
+
+//key command: 1, key init seed_in_str; 2, key uninit
+//argv[0] can be 'key' from usb tool, or 'aml_key_burn/misc' from sdc_burn
+int v2_key_command(const int argc, char * const argv[], char *info)
+{
+ const char* keyCmd = argv[1];
+ int rcode = 0;
+ int subCmd_argc = argc - 1;
+ char* const * subCmd_argv = argv + 1;
+
+ DWN_DBG("argc=%d, argv[%s, %s, %s, %s]\n", argc, argv[0], argv[1], argv[2], argv[3]);
+ if (argc < 2) {
+ sprintf(info, "argc < 2, need key subcmd\n");
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ if (!strcmp("init", keyCmd))
+ {
+ if (argc < 3) {
+ sprintf(info, "failed:cmd [key init] must take argument (seedNum)\n");
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ u64 seedNum = simple_strtoull(subCmd_argv[1], NULL, 16);
+ if (!seedNum) {
+ sprintf(info, "failed:seedNum %s illegal\n", argv[2]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ rcode = key_unify_init((char*)&seedNum, sizeof(seedNum));
+
+ DWN_MSG("seedNum is 0x%llx, rcode %d\n", seedNum, rcode);
+ }
+ else if(!strcmp("uninit", keyCmd))
+ {
+ rcode = key_unify_uninit();
+ }
+ else if(!strcmp("is_burned", keyCmd))
+ {
+ if (subCmd_argc < 2) {
+ sprintf(info, "failed: %s %s need a keyName\n", argv[0], argv[1]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ const char* queryKey = subCmd_argv[1];
+ unsigned keyIsBurned = -1;
+ unsigned keypermit = -1;
+ rcode = key_unify_query((char*)queryKey, &keyIsBurned, &keypermit);
+ if (rcode < 0) {
+ sprintf(info, "failed to query key state, rcode %d\n", rcode);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ rcode = (1 == keyIsBurned) ? 0 : __LINE__;
+ sprintf(info, "%s:key[%s] was %s burned yet(keystate %d, keypermit 0x%x)\n",
+ rcode ? "failed" : "success", queryKey, rcode ? "NOT" : "DO", keyIsBurned, keypermit);
+ }
+ else if(!strcmp("can_write", keyCmd) || !strcmp("can_read", keyCmd))
+ {
+ if (subCmd_argc < 2) {
+ sprintf(info, "failed: %s %s need a keyName\n", argv[0], argv[1]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ const char* queryKey = subCmd_argv[1];
+ unsigned keyIsBurned = -1;
+ unsigned keypermit = -1;
+ rcode = key_unify_query((char*)queryKey, &keyIsBurned, &keypermit);
+ if (rcode < 0) {
+ sprintf(info, "failed to query key state, rcode %d\n", rcode);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ int writeCmd = !strcmp("can_write", keyCmd);
+ unsigned canWrite = ( 0xa == ( (keypermit>>4) & 0xfu ) );
+ unsigned canRead = ( 0xa == ( keypermit & 0xfu ) );
+ rcode = writeCmd ? !canWrite : !canRead;
+ sprintf(info, "%s:key[%s] %s %s (keystate %d, keypermit 0x%x)\n",
+ rcode ? "failed" : "success", queryKey, rcode ? "NOT" : "DO", keyCmd, keyIsBurned, keypermit);
+ }
+ else if(!strcmp("write", keyCmd))
+ {
+ /*
+ *
+ *key write [keyName keyValueInStr]
+ *write direct, not support to deencrypt or verify, debug pipe, don't use to in PC tools
+ *Attentions it support at most 512-6 Bytes!
+ */
+
+ const char* keyName = subCmd_argv[1];
+ const char* keyValInStr = subCmd_argv[2];
+
+ if (subCmd_argc < 3) {
+ sprintf(info, "failed: %s %s need a keyName and keyValInStr\n", argv[0], argv[1]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ rcode = v2_key_burn(keyName, (u8*)keyValInStr, strlen(keyValInStr), info);
+ rcode = (strlen(keyValInStr) == rcode) ? 0 : __LINE__;
+ }
+ else if(!strcmp("read", keyCmd) || !strcmp("get_len", keyCmd))
+ {
+ /*
+ *key read [keyName], read directly to info buffer
+ *debug pipe, support at most 512-6 bytes, and PLS DON'T use in PC tools
+ *
+ *
+ */
+ unsigned actualLen = 0;
+ const int cswBufLen = CMD_BUFF_SIZE - sizeof("success") + 1;
+ const char* keyName = subCmd_argv[1];
+ unsigned char* keyValBuf = (unsigned char*)info + CMD_BUFF_SIZE - cswBufLen;
+ unsigned ReadBufLen = cswBufLen;
+
+ if (subCmd_argc < 2) {
+ sprintf(info, "failed: %s %s need a keyName\n", argv[0], argv[1]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ const int is_query = !strcmp("get_len", keyCmd) ;
+ if (is_query) {
+ keyValBuf = (u8*)OPTIMUS_KEY_DECRYPT_BUF;
+ ReadBufLen = OPTIMUS_KEY_DECRYPT_BUF_SZ;
+ }
+
+ rcode = v2_key_read((char*)keyName, keyValBuf, ReadBufLen, info, &actualLen);
+ if (is_query)
+ {
+ if (!rcode)
+ sprintf(info, "success%u", actualLen);
+ else
+ sprintf(info, "failed:at get_len rc %d\n", rcode);
+ }
+ DWN_MSG("key[%s] len(%d), rc(%d)\n", keyName, actualLen, rcode);
+
+ rcode = rcode >=0 ? 0 : rcode;
+ }
+ else if(!strcmp("get_fmt", keyCmd))
+ {
+ const char* fmt = NULL;
+ fmt = key_unify_query_key_format((char*)subCmd_argv[1]);
+ sprintf(info, "success:%s\n", fmt);
+ }
+ else{
+ sprintf(info, "failed:Error keyCmd[%s]\n", keyCmd);
+ DWN_ERR(info);
+ rcode = __LINE__;
+ }
+
+ DWN_DBG("rcode 0x%x\n", rcode);
+ return rcode;
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_fat.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_fat.c
new file mode 100644
index 0000000000..3d4b6dd013
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_fat.c
@@ -0,0 +1,1268 @@
+/*
+ * fat.c
+ *
+ * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
+ *
+ * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
+ * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "../v2_burning_i.h"
+#include <part.h>
+#include <fat.h>
+#include <partition_table.h>
+#include <mmc.h>
+
+#undef FAT_ERROR
+#define FAT_ERROR(fmt...) printf("[FAT_ERR]L%d,", __LINE__),printf(fmt)
+#ifndef FAT_DPRINT
+#define FAT_DPRINT FAT_ERROR
+#endif
+
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE 512
+#endif
+#ifndef FS_BLOCK_SIZE
+#define FS_BLOCK_SIZE SECTOR_SIZE
+#endif
+
+#define FAT_MSG(fmt...) printf("fat:"fmt)
+
+extern int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr);
+
+int optimus_sdc_burn_switch_to_extmmc(void)
+{
+ static struct mmc *mmc = NULL;
+
+ //Attention: So far the work flow of sdc_burn or sdc_update after store_init(0), so device_boot_flag is setup yet!
+ if (SPI_EMMC_FLAG != device_boot_flag && EMMC_BOOT_FLAG != device_boot_flag) {
+ return 0;
+ }
+
+ if (!mmc)
+ {
+ mmc = find_mmc_device(0);
+ if (!mmc) {
+ FAT_ERROR("Fail to find mmc 0 device");
+ return __LINE__;
+ }
+ }
+ if (mmc_init(mmc)) {
+ FAT_ERROR("Fail to init mmc 0 device");
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+static int v2_ext_mmc_read(__u32 startblock, __u32 nBlk, __u8 * bufptr)
+{
+ int ret = 0;
+ char* usb_update = getenv("usb_update");
+ if (strcmp(usb_update,"1"))
+ {
+ ret = optimus_sdc_burn_switch_to_extmmc();
+ if (ret) {
+ FAT_ERROR("failed in switch to extmmc.\n");
+ return __LINE__;
+ }
+ }
+
+ ret = disk_read(startblock, nBlk, bufptr);
+
+ return ret;
+}
+
+/*
+ * Convert a string to lowercase.
+ */
+static void
+downcase(char *str)
+{
+ const int dist = 'a' - 'A';
+ for (;*str != '\0'; ++str) {
+ char c = *str;
+ if ('A' <= c && c <= 'Z')
+ c += dist, *str = c;
+ }
+}
+
+/*
+ * Get the first occurence of a directory delimiter ('/' or '\') in a string.
+ * Return index into string if found, -1 otherwise.
+ */
+static int
+dirdelim(char *str)
+{
+ char *start = str;
+
+ while (*str != '\0') {
+ if (ISDIRDELIM(*str)) return str - start;
+ str++;
+ }
+ return -1;
+}
+
+
+/*
+ * Match volume_info fs_type strings.
+ * Return 0 on match, -1 otherwise.
+ */
+static int
+compare_sign(char *str1, char *str2)
+{
+ char *end = str1+SIGNLEN;
+
+ while (str1 != end) {
+ if (*str1 != *str2) {
+ return -1;
+ }
+ str1++;
+ str2++;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Extract zero terminated short name from a directory entry.
+ */
+static void get_name (dir_entry *dirent, char *s_name)
+{
+ char *ptr;
+
+ memcpy (s_name, dirent->name, 8);
+ s_name[8] = '\0';
+ ptr = s_name;
+ while (*ptr && *ptr != ' ')
+ ptr++;
+ if (dirent->ext[0] && dirent->ext[0] != ' ') {
+ *ptr = '.';
+ ptr++;
+ memcpy (ptr, dirent->ext, 3);
+ ptr[3] = '\0';
+ while (*ptr && *ptr != ' ')
+ ptr++;
+ }
+ *ptr = '\0';
+ if (*s_name == DELETED_FLAG)
+ *s_name = '\0';
+ else if (*s_name == aRING)
+ *s_name = DELETED_FLAG;
+ downcase (s_name);
+}
+
+/*
+ * Get the cluster entry at index 'entry' in a FAT (12/16/32) table.
+ * On failure 0x00 is returned.
+ */
+static __u32 get_fatent(fsdata *mydata, __u32 entry/*cluster index*/)
+{
+ __u32 bufnum;
+ __u32 offset;
+ __u32 ret = 0x00;//On failure 0x00 is returned.
+
+ switch (mydata->fatsize) {
+ case 32:
+ bufnum = entry / FAT32BUFSIZE;
+ offset = entry - bufnum * FAT32BUFSIZE;
+ break;
+ case 16:
+ bufnum = entry / FAT16BUFSIZE;
+ offset = entry - bufnum * FAT16BUFSIZE;
+ break;
+ case 12:
+ bufnum = entry / FAT12BUFSIZE;
+ offset = entry - bufnum * FAT12BUFSIZE;
+ break;
+
+ default:
+ /* Unsupported FAT size */
+ return ret;
+ }
+
+ /* Read a new block of FAT entries into the cache. */
+ /* this block of FAT entries is not cached */
+ if (bufnum != mydata->fatbufnum) {
+ int getsize = FATBUFSIZE/FS_BLOCK_SIZE;//==6
+ __u8 *bufptr = mydata->fatbuf;
+ __u32 fatlength = mydata->fatlength;
+ __u32 startblock = bufnum * FATBUFBLOCKS;
+
+ fatlength *= SECTOR_SIZE; /* We want it in bytes now */
+ startblock += mydata->fat_sect; /* Offset from start of disk */
+
+ if (getsize > fatlength) getsize = fatlength;
+ if (v2_ext_mmc_read(startblock, getsize, bufptr) < 0) {
+ FAT_DPRINT("Error reading FAT blocks\n");
+ return ret;
+ }
+ mydata->fatbufnum = bufnum;
+ }
+
+ /* Get the actual entry from the table */
+ switch (mydata->fatsize) {
+ case 32:
+ ret = FAT2CPU32(((__u32*)mydata->fatbuf)[offset]);
+ break;
+ case 16:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[offset]);
+ break;
+ case 12: {
+ __u32 off16 = (offset*3)/4;
+ __u16 val1, val2;
+
+ switch (offset & 0x3) {
+ case 0:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ ret &= 0xfff;
+ break;
+ case 1:
+ val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ val1 &= 0xf000;
+ val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
+ val2 &= 0x00ff;
+ ret = (val2 << 4) | (val1 >> 12);
+ break;
+ case 2:
+ val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ val1 &= 0xff00;
+ val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
+ val2 &= 0x000f;
+ ret = (val2 << 8) | (val1 >> 8);
+ break;
+ case 3:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);;
+ ret = (ret & 0xfff0) >> 4;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ FAT_DPRINT("ret: %d, offset: %d\n", ret, offset);
+
+ return ret;
+}
+
+
+/*
+ * Read at most 'size' bytes from the specified cluster into 'buffer'.
+ * Return 0 on success, -1 otherwise.
+ */
+static int
+get_cluster(fsdata *mydata, const __u32 clustnum, __u8 *buffer, const unsigned long size)
+{
+ int idx = 0;
+ __u32 startsect;
+
+ if (clustnum > 0) {
+ startsect = mydata->data_begin + clustnum*mydata->clust_size;
+ } else {
+ startsect = mydata->rootdir_sect;
+ }
+
+ FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
+ if (v2_ext_mmc_read(startsect, size/FS_BLOCK_SIZE , buffer) < 0) {
+ FAT_DPRINT("Error reading data\n");
+ return -1;
+ }
+ if (size % FS_BLOCK_SIZE) {
+ __u8 tmpbuf[FS_BLOCK_SIZE];
+ idx= size/FS_BLOCK_SIZE;
+ if (v2_ext_mmc_read(startsect + idx, 1, tmpbuf) < 0) {
+ FAT_ERROR("Error reading data\n");
+ return -1;
+ }
+ buffer += idx*FS_BLOCK_SIZE;
+
+ memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE);
+ return 0;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SUPPORT_VFAT
+/*
+ * Extract the file name information from 'slotptr' into 'l_name',
+ * starting at l_name[*idx].
+ * Return 1 if terminator (zero byte) is found, 0 otherwise.
+ */
+static int
+slot2str(dir_slot *slotptr, char *l_name, int *idx)
+{
+ int j;
+
+ for (j = 0; j <= 8; j += 2) {
+ l_name[*idx] = slotptr->name0_4[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+ for (j = 0; j <= 10; j += 2) {
+ l_name[*idx] = slotptr->name5_10[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+ for (j = 0; j <= 2; j += 2) {
+ l_name[*idx] = slotptr->name11_12[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Extract the full long filename starting at 'retdent' (which is really
+ * a slot) into 'l_name'. If successful also copy the real directory entry
+ * into 'retdent'
+ * Return 0 on success, -1 otherwise.
+ */
+__attribute__ ((__aligned__(__alignof__(dir_entry))))
+__u8 get_vfatname_block[MAX_CLUSTSIZE];
+static int
+get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
+ dir_entry *retdent, char *l_name)
+{
+ dir_entry *realdent;
+ dir_slot *slotptr = (dir_slot*) retdent;
+ __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+ __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
+ int idx = 0;
+
+ while ((__u8*)slotptr < nextclust) {
+ if (counter == 0) break;
+ if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
+ return -1;
+ slotptr++;
+ counter--;
+ }
+
+ if ((__u8*)slotptr >= nextclust) {
+ dir_slot *slotptr2;
+
+ slotptr--;
+ curclust = get_fatent(mydata, curclust);
+ if (CHECK_CLUST(curclust, mydata->fatsize)) {
+ FAT_ERROR("curclust: 0x%x\n", curclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ return -1;
+ }
+ if (get_cluster(mydata, curclust, get_vfatname_block,
+ mydata->clust_size * SECTOR_SIZE) != 0) {
+ FAT_ERROR("Error: reading directory block\n");
+ return -1;
+ }
+ slotptr2 = (dir_slot*) get_vfatname_block;
+ while (slotptr2->id > 0x01) {
+ slotptr2++;
+ }
+ /* Save the real directory entry */
+ realdent = (dir_entry*)slotptr2 + 1;
+ while ((__u8*)slotptr2 >= get_vfatname_block) {
+ slot2str(slotptr2, l_name, &idx);
+ slotptr2--;
+ }
+ } else {
+ /* Save the real directory entry */
+ realdent = (dir_entry*)slotptr;
+ }
+
+ do {
+ slotptr--;
+ if (slot2str(slotptr, l_name, &idx)) break;
+ } while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
+
+ l_name[idx] = '\0';
+ if (*l_name == DELETED_FLAG) *l_name = '\0';
+ else if (*l_name == aRING) *l_name = DELETED_FLAG;
+ downcase(l_name);
+
+ /* Return the real directory entry */
+ memcpy(retdent, realdent, sizeof(dir_entry));
+
+ return 0;
+}
+
+
+/* Calculate short name checksum */
+static __u8
+mkcksum(const char *str)
+{
+ int i;
+ __u8 ret = 0;
+
+ for (i = 0; i < 11; i++) {
+ ret = (((ret&1)<<7)|((ret&0xfe)>>1)) + str[i];
+ }
+
+ return ret;
+}
+#endif
+
+
+/*
+ * Get the directory entry associated with 'filename' from the directory
+ * starting at 'startsect'
+ */
+__attribute__ ((__aligned__(__alignof__(dir_entry))))
+static __u8 get_dentfromdir_block[MAX_CLUSTSIZE];
+static dir_entry *get_dentfromdir (fsdata * mydata, int startsect,
+ char *filename, dir_entry * retdent,
+ int dols)
+{
+ __u16 prevcksum = 0xffff;
+ __u32 curclust = START (retdent);
+ int files = 0, dirs = 0;
+
+ FAT_DPRINT ("get_dentfromdir: %s\n", filename);
+ while (1) {
+ dir_entry *dentptr;
+ int i;
+
+ if (get_cluster (mydata, curclust, get_dentfromdir_block,
+ mydata->clust_size * SECTOR_SIZE) != 0) {
+ FAT_DPRINT ("Error: reading directory block\n");
+ return NULL;
+ }
+ dentptr = (dir_entry *) get_dentfromdir_block;
+ for (i = 0; i < DIRENTSPERCLUST; i++) {
+ char s_name[14], l_name[256];
+
+ l_name[0] = '\0';
+ if (dentptr->name[0] == DELETED_FLAG) {
+ dentptr++;
+ continue;
+ }
+ if ((dentptr->attr & ATTR_VOLUME)) {
+#ifdef CONFIG_SUPPORT_VFAT
+ if ((dentptr->attr & ATTR_VFAT) &&
+ (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
+ prevcksum = ((dir_slot *) dentptr)
+ ->alias_checksum;
+ get_vfatname (mydata, curclust, get_dentfromdir_block,
+ dentptr, l_name);
+ if (dols) {
+ int isdir = (dentptr->attr & ATTR_DIR);
+ char dirc;
+ int doit = 0;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ doit = 1;
+ } else {
+ dirc = ' ';
+ if (l_name[0] != 0) {
+ files++;
+ doit = 1;
+ }
+ }
+ if (doit) {
+ if (dirc == ' ') {
+ printf (" %8ld %s%c\n",
+ (long) FAT2CPU32 (dentptr->size),
+ l_name, dirc);
+ } else {
+ printf (" %s%c\n", l_name, dirc);
+ }
+ }
+ dentptr++;
+ continue;
+ }
+ FAT_DPRINT ("vfatname: |%s|\n", l_name);
+ } else
+#endif
+ {
+ /* Volume label or VFAT entry */
+ dentptr++;
+ continue;
+ }
+ }
+ if (dentptr->name[0] == 0) {
+ if (dols) {
+ printf ("\n%d file(s), %d dir(s)\n\n", files, dirs);
+ }
+ FAT_DPRINT ("Dentname == NULL - %d\n", i);
+ return NULL;
+ }
+#ifdef CONFIG_SUPPORT_VFAT
+ if (dols && mkcksum (dentptr->name) == prevcksum) {
+ dentptr++;
+ continue;
+ }
+#endif
+ get_name (dentptr, s_name);
+ if (dols) {
+ int isdir = (dentptr->attr & ATTR_DIR);
+ char dirc;
+ int doit = 0;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ doit = 1;
+ } else {
+ dirc = ' ';
+ if (s_name[0] != 0) {
+ files++;
+ doit = 1;
+ }
+ }
+ if (doit) {
+ if (dirc == ' ') {
+ printf (" %8ld %s%c\n",
+ (long) FAT2CPU32 (dentptr->size), s_name,
+ dirc);
+ } else {
+ printf (" %s%c\n", s_name, dirc);
+ }
+ }
+ dentptr++;
+ continue;
+ }
+ if (strcmp (filename, s_name) && strcmp (filename, l_name)) {
+ FAT_DPRINT ("Mismatch: |%s|%s|\n", s_name, l_name);
+ dentptr++;
+ continue;
+ }
+ memcpy (retdent, dentptr, sizeof (dir_entry));
+
+ FAT_DPRINT ("DentName: %s", s_name);
+ FAT_DPRINT (", start: 0x%x", START (dentptr));
+ FAT_DPRINT (", size: 0x%x %s\n",
+ FAT2CPU32 (dentptr->size),
+ (dentptr->attr & ATTR_DIR) ? "(DIR)" : "");
+
+ return retdent;
+ }
+ curclust = get_fatent (mydata, curclust);
+ if (CHECK_CLUST(curclust, mydata->fatsize)) {
+ FAT_DPRINT ("curclust: 0x%x\n", curclust);
+ FAT_ERROR ("Invalid FAT entry\n");
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Read boot sector and volume info from a FAT filesystem
+ */
+static int
+read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
+{
+ __u8 block[FS_BLOCK_SIZE];
+ volume_info *vistart;
+ char *fstype;
+
+ if (disk_read(0, 1, block) < 0) {
+ FAT_ERROR("Error: reading block\n");
+ return -1;
+ }
+
+ memcpy(bs, block, sizeof(boot_sector));
+ bs->reserved = FAT2CPU16(bs->reserved);
+ bs->fat_length = FAT2CPU16(bs->fat_length);
+ bs->secs_track = FAT2CPU16(bs->secs_track);
+ bs->heads = FAT2CPU16(bs->heads);
+#if 0 /* UNUSED */
+ bs->hidden = FAT2CPU32(bs->hidden);
+#endif
+ bs->total_sect = FAT2CPU32(bs->total_sect);
+
+ /* FAT32 entries */
+ if (bs->fat_length == 0) {
+ /* Assume FAT32 */
+ bs->fat32_length = FAT2CPU32(bs->fat32_length);
+ bs->flags = FAT2CPU16(bs->flags);
+ bs->root_cluster = FAT2CPU32(bs->root_cluster);
+ bs->info_sector = FAT2CPU16(bs->info_sector);
+ bs->backup_boot = FAT2CPU16(bs->backup_boot);
+ vistart = (volume_info*) (block + sizeof(boot_sector));
+ *fatsize = 32;
+ } else {
+ vistart = (volume_info*) &(bs->fat32_length);
+ *fatsize = 0;
+ }
+ memcpy(volinfo, vistart, sizeof(volume_info));
+
+ /*
+ * Terminate fs_type string. Writing past the end of vistart
+ * is ok - it's just the buffer.
+ */
+ fstype = vistart->fs_type;
+ fstype[8] = '\0';
+
+ if (*fatsize == 32) {
+ if (compare_sign(FAT32_SIGN, vistart->fs_type) == 0) {
+ return 0;
+ }
+ } else {
+ if (compare_sign(FAT12_SIGN, vistart->fs_type) == 0) {
+ *fatsize = 12;
+ return 0;
+ }
+ if (compare_sign(FAT16_SIGN, vistart->fs_type) == 0) {
+ *fatsize = 16;
+ return 0;
+ }
+ }
+
+ FAT_ERROR("Error: broken fs_type sign\n");
+ return -1;
+}
+
+__attribute__ ((__aligned__(__alignof__(dir_entry))))
+__u8 do_fat_read_block[MAX_CLUSTSIZE];
+
+//////////////////////////////////////////////////////////////////////
+
+__attribute__ ((__aligned__(__alignof__(dir_entry))))
+__u8 _do_fat_read_block[MAX_CLUSTSIZE];
+
+
+#define FILE_MAX 2
+struct _fs_info
+{
+ fsdata datablock;
+ volume_info volinfo;
+ boot_sector bs;
+
+ char *fat_buf;
+ unsigned fat_buf_cluster_index;//remember the index that which cluster was cached
+};
+
+struct file
+{
+ dir_entry dent;
+ unsigned long offset;
+ unsigned long filesize;
+ __u32 curclust;//next cluster to read
+ __u32 headclust;
+
+};
+
+static struct file files[FILE_MAX];
+static struct _fs_info fs_info[FILE_MAX];
+static int _fd[FILE_MAX] = {0};
+#define OPTIMUS_FD_MAGIC (0XEFE80025)
+#define OPTIMUS_INVAL_FD (-1)
+
+static int get_fd(void)
+{
+ int index = 0;
+
+ for (; index < FILE_MAX; ++index) {
+ if (OPTIMUS_FD_MAGIC != _fd[index]) {//fd not used
+ _fd[index] = OPTIMUS_FD_MAGIC;
+ return index;
+ }
+ }
+
+ return OPTIMUS_INVAL_FD;
+}
+
+static void put_fd(int fd_index)
+{
+ if (fd_index >= 0)
+ _fd[fd_index] = 0;
+ return;
+}
+
+/* wherehence: 0 to seek from start of file; 1 to seek from current position from file */
+int do_fat_fseek(int fd, const __u64 offset, int wherehence)
+{
+ unsigned long curoffset;
+ unsigned long offset_in_clust;
+ unsigned long seeked;
+ const unsigned int bytesperclust = fs_info[fd].datablock.clust_size * SECTOR_SIZE;
+ const unsigned long filesize = files[fd].filesize;
+ __u32 curclust;
+
+ if (fd<0) {
+ FAT_ERROR("invalid fd %d\n", fd);
+ return -1;
+ }
+
+ curclust = files[fd].curclust;
+ curoffset = files[fd].offset;
+
+ if (wherehence == 0)
+ {
+ const unsigned long curClusterOffset = curoffset - (curoffset & (bytesperclust - 1));
+
+ if (offset > filesize) {
+ FAT_ERROR("offset %llx > filesize %lx\n", offset, filesize);
+ return -1;
+ }
+
+ if (offset < curoffset) //seek from head if want to seek backwards
+ {
+ curclust = files[fd].headclust;
+ seeked=0;
+ }
+ else if(curClusterOffset + bytesperclust > offset)//Not need to actual seek as just in the right cluster
+ {
+ files[fd].offset = offset;
+ return 0;
+ }
+ else//seek from the current cluster
+ {
+ seeked = curoffset - (curoffset & (bytesperclust - 1));//curclust not need to change
+ FAT_MSG("Seek 0x%llx from 0x%lx\n", offset, curoffset);
+ }
+
+ /* seek to offset */
+ while (1)
+ {
+
+ if (seeked + bytesperclust > offset)
+ {
+ fsdata* mydata = &fs_info[fd].datablock;
+ __u8* clusterCache = (__u8*)fs_info[fd].fat_buf;
+
+ files[fd].curclust = curclust;
+ files[fd].offset = offset;
+
+ if ((offset & (bytesperclust - 1)) && curclust != fs_info[fd].fat_buf_cluster_index)
+ {//cache the cluster if want to read from the offset where not align in cluster, and not cached yet
+ if (get_cluster(mydata, curclust, clusterCache, (int)bytesperclust) != 0) {
+ FAT_ERROR("Error reading cluster\n");
+ return -1;
+ }
+ fs_info[fd].fat_buf_cluster_index = curclust;
+ }
+
+ break;
+ }
+
+ curclust = get_fatent(&fs_info[fd].datablock, curclust);
+
+ seeked += bytesperclust;
+ }
+ }
+ else if(wherehence == 1)//this branch not used and not checked!
+ {
+ if (offset + curoffset > filesize) {
+ DWN_ERR("offset 0x%llx + curoffset 0x%lx > filesize 0x%lx\n", offset, curoffset, filesize);
+ return __LINE__;
+ }
+ if (offset == 0)
+ return 0;
+
+ curclust = files[fd].curclust;
+
+ seeked=0;
+ /* seek to offset */
+
+ offset_in_clust = curoffset % bytesperclust;
+
+ if (offset_in_clust + offset <= bytesperclust)
+ {
+ files[fd].offset += offset;
+ return 0;
+ }
+ else
+ {
+ //round down to cluster boundry.
+ const __u64 aimOffset = offset + offset_in_clust;
+ /*offset += offset_in_clust;*/
+
+ while (1) {
+
+ if (seeked + bytesperclust > aimOffset)
+ {
+ files[fd].curclust = curclust;
+ files[fd].offset = aimOffset;
+ break;
+ }
+
+ curclust = get_fatent(&fs_info[fd].datablock, curclust);
+
+ seeked += bytesperclust;
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+long do_fat_fopen(const char *filename)
+{
+#if CONFIG_NIOS /* NIOS CPU cannot access big automatic arrays */
+ static
+#endif
+ unsigned int bytesperclust;
+ char fnamecopy[2048];
+ fsdata *mydata;
+ int fd;
+ dir_entry *dentptr;
+ char *subname = "";
+ int rootdir_size, cursect;
+ int idx, isdir = 0;
+ /*int firsttime;*/
+
+ if ((fd = get_fd()) < 0) {
+ FAT_ERROR("get_fd failed\n");
+ return -1;
+ }
+
+ mydata = &fs_info[fd].datablock;
+
+ if (read_bootsectandvi (&fs_info[fd].bs, &fs_info[fd].volinfo, &mydata->fatsize)) {
+ FAT_ERROR ("Error: reading boot sector\n");
+ put_fd(fd);
+ return -1;
+ }
+ if (mydata->fatsize == 32) {
+ mydata->fatlength = fs_info[fd].bs.fat32_length;
+ } else {
+ mydata->fatlength = fs_info[fd].bs.fat_length;
+ }
+ mydata->fat_sect = fs_info[fd].bs.reserved;
+ cursect = mydata->rootdir_sect
+ = mydata->fat_sect + mydata->fatlength * fs_info[fd].bs.fats;
+ mydata->clust_size = fs_info[fd].bs.cluster_size;
+ if (mydata->fatsize == 32) {
+ rootdir_size = mydata->clust_size;
+ mydata->data_begin = mydata->rootdir_sect /* + rootdir_size */
+ - (mydata->clust_size * 2);
+ } else {
+ rootdir_size = ((fs_info[fd].bs.dir_entries[1] * (int) 256 + fs_info[fd].bs.dir_entries[0])
+ * sizeof (dir_entry)) / SECTOR_SIZE;
+ mydata->data_begin = mydata->rootdir_sect + rootdir_size
+ - (mydata->clust_size * 2);
+ }
+ mydata->fatbufnum = -1;
+
+ FAT_DPRINT ("FAT%d, fatlength: %d\n", mydata->fatsize,
+ mydata->fatlength);
+ FAT_DPRINT ("Rootdir begins at sector: %d, offset: %x, size: %d\n"
+ "Data begins at: %d\n",
+ mydata->rootdir_sect, mydata->rootdir_sect * SECTOR_SIZE,
+ rootdir_size, mydata->data_begin);
+ FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);
+
+ /* "cwd" is always the root... */
+ while (ISDIRDELIM (*filename))
+ filename++;
+ /* Make a copy of the filename and convert it to lowercase */
+ strcpy (fnamecopy, filename);
+ downcase (fnamecopy);
+ if (*fnamecopy == '\0') {
+ put_fd(fd);
+ return -1;
+ } else if ((idx = dirdelim (fnamecopy)) >= 0) {
+ isdir = 1;
+ fnamecopy[idx] = '\0';
+ subname = fnamecopy + idx + 1;
+ /* Handle multiple delimiters */
+ while (ISDIRDELIM (*subname))
+ subname++;
+ }
+
+ while (1) {
+ int i;
+
+ if (v2_ext_mmc_read(cursect, mydata->clust_size, _do_fat_read_block) < 0) {
+ FAT_ERROR ("Error: reading rootdir block\n");
+ put_fd(fd);
+ return -1;
+ }
+ dentptr = (dir_entry *) _do_fat_read_block;
+ for (i = 0; i < DIRENTSPERBLOCK; i++) {
+ char s_name[14], l_name[256];
+
+ l_name[0] = '\0';
+ if ((dentptr->attr & ATTR_VOLUME)) {
+#ifdef CONFIG_SUPPORT_VFAT
+ if (((dentptr->attr & ATTR_VFAT) == ATTR_VFAT) &&
+ (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
+ get_vfatname (mydata, 0, _do_fat_read_block, dentptr, l_name);
+ } else
+#endif
+ {
+ /* Volume label or VFAT entry */
+ dentptr++;
+ continue;
+ }
+ } else if (dentptr->name[0] == 0) {
+ FAT_DPRINT ("RootDentname == NULL - %d\n", i);
+ put_fd(fd);
+ return -1;
+ }
+
+ get_name (dentptr, s_name);
+
+ if (strcmp (fnamecopy, s_name) && strcmp (fnamecopy, l_name)) {
+ FAT_DPRINT ("RootMismatch: |%s|%s|\n", s_name, l_name);
+ dentptr++;
+ continue;
+ }
+ if (isdir && !(dentptr->attr & ATTR_DIR))
+ {
+ put_fd(fd);
+ return -1;
+ }
+ FAT_DPRINT ("RootName: %s", s_name);
+ FAT_DPRINT (", start: 0x%x", START (dentptr));
+ FAT_DPRINT (", size: 0x%x %s\n",
+ FAT2CPU32 (dentptr->size), isdir ? "(DIR)" : "");
+
+ goto rootdir_done; /* We got a match */
+ }
+ cursect++;
+ }
+ rootdir_done:
+
+ /*firsttime = 1;*/
+ while (isdir) {
+ int startsect = mydata->data_begin
+ + START (dentptr) * mydata->clust_size;
+ dir_entry dent;
+ char *nextname = NULL;
+
+ dent = *dentptr;
+ dentptr = &dent;
+
+ idx = dirdelim (subname);
+ if (idx >= 0) {
+ subname[idx] = '\0';
+ nextname = subname + idx + 1;
+ /* Handle multiple delimiters */
+ while (ISDIRDELIM (*nextname))
+ nextname++;
+ } else {
+ isdir = 0;
+ }
+
+ if (get_dentfromdir (mydata, startsect, subname, dentptr, 0) == NULL) {
+ put_fd(fd);
+ return -1;
+ }
+
+ if (idx >= 0) {
+ if (!(dentptr->attr & ATTR_DIR))
+ {
+ put_fd(fd);
+ return -1;
+ }
+ subname = nextname;
+ }
+ }
+
+ files[fd].dent = *dentptr;
+ files[fd].offset = 0;
+ files[fd].curclust = files[fd].headclust = START(dentptr);
+ files[fd].filesize = FAT2CPU32(dentptr->size);
+ FAT_MSG("Filesize is 0x%lxB[%luM]\n", files[fd].filesize, (files[fd].filesize>>20));
+
+ bytesperclust = fs_info[fd].datablock.clust_size * SECTOR_SIZE;
+ fs_info[fd].fat_buf_cluster_index = 0;//0 is invalid
+ fs_info[fd].fat_buf = malloc(bytesperclust);
+ if (!fs_info[fd].fat_buf)
+ {
+ if (fd >= 0)
+ {
+ memset(&files[fd], 0, sizeof(struct file));
+ memset(&fs_info[fd], 0, sizeof(struct _fs_info));
+ }
+ put_fd(fd);
+ return -1;
+ }
+ return fd;
+}
+
+unsigned do_fat_get_bytesperclust(int fd)
+{
+ const unsigned bytesperclust = fs_info[fd].datablock.clust_size * SECTOR_SIZE;
+
+ if (fd < 0) {
+ FAT_ERROR("Invalid fd %d\n", fd);
+ return -1;
+ }
+
+ return bytesperclust;
+}
+
+long do_fat_fread(int fd, __u8 *buffer, unsigned long maxsize)
+{
+ __u32 gotsize = 0;
+ __u32 curclust;
+ unsigned long actsize;
+ unsigned long offset;
+ unsigned long offset_in_clust;
+ struct _fs_info* theFsInfo = fs_info + fd;
+ const unsigned bytesperclust = theFsInfo->datablock.clust_size * SECTOR_SIZE;
+ fsdata* mydata = &fs_info[fd].datablock;
+
+ if (fd < 0) {
+ FAT_ERROR("Invalid fd %d\n", fd);
+ return -1;
+ }
+
+ offset = files[fd].offset;
+
+
+
+#if 0
+ seeked=0;
+
+ /* seek to offset */
+ while (1) {
+
+ if (seeked + bytesperclust > offset)
+ {
+ printf("Seeked to %d, target offset %d, clust %d\n", seeked, offset, curclust);
+ break;
+ }
+
+ curclust = get_fatent(&fs_info[fd].datablock, curclust);
+
+ if (CHECK_CLUST(curclust, mydata->fatsize)) {
+ FAT_DPRINT("curclust: 0x%x\n", curclust);
+ FAT_DPRINT("Invalid FAT entry\n");
+ return 0;
+ }
+
+ seeked += bytesperclust;
+ }
+#else
+
+ curclust = files[fd].curclust;
+
+#endif
+
+ /* calc actual size to read */
+ if (offset + maxsize > files[fd].filesize)
+ {
+ actsize = files[fd].filesize - offset;
+ }
+ else
+ {
+ actsize = maxsize;
+ }
+
+ /* Deal with partial data at the first cluster */
+
+ /* Data occupation in cluster 1
+ Case 1:
+
+ cluster1 : |####____|
+
+ Case 2:
+ cluster1 : |########|
+
+ Case 3:
+ cluster1 : |__####__|
+
+ Case 4:
+ cluster1 : |__######|
+ */
+
+ offset_in_clust = (offset % bytesperclust);
+ if (offset_in_clust != 0)
+ {
+ if (curclust != theFsInfo->fat_buf_cluster_index)
+ {//should seldom reach here if the image item consecutive
+ FAT_MSG("offset_in_clust 0x%lx\n", offset_in_clust);
+ /* Use vfat_buf as intermedia buffer to deal with the situation that size of _buf_ is smaller than a cluster */
+ //FIXME:check if the fat_buf cache the data user wanted, and copy directly if wanted!!
+ if (get_cluster(mydata, curclust, (__u8*)fs_info[fd].fat_buf, (int)bytesperclust) != 0) {
+ FAT_ERROR("Error reading cluster\n");
+ return -1;
+ }
+ fs_info[fd].fat_buf_cluster_index = curclust;
+ }
+
+ if (actsize < (bytesperclust - offset_in_clust))
+ {/* Case 3: the end of the cluster is not reached */
+ memcpy(buffer, fs_info[fd].fat_buf+ offset_in_clust, actsize);
+ offset += actsize;
+ gotsize = actsize;
+ goto exit;
+ }
+ else
+ {/* Case 4 */
+ memcpy(buffer, fs_info[fd].fat_buf+ offset_in_clust, bytesperclust - offset_in_clust);
+ actsize -= (bytesperclust - offset_in_clust);
+ gotsize = (bytesperclust - offset_in_clust);
+ offset += (bytesperclust - offset_in_clust);
+ buffer += gotsize;
+
+ //update cluster index if seeked to next cluster
+ curclust = get_fatent(mydata, curclust);//get next cluster index
+ if (CHECK_CLUST(curclust, mydata->fatsize)) {
+ FAT_ERROR("curclust: 0x%x\n", curclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ goto exit;
+ }
+ }
+ }
+
+ //Following disposing data which 'offset % bytesperclust == 0', that is start from align offset
+ while (actsize) //left data length
+ {
+ __u32 endclust; //last cluster index of this consecutive clusters
+ __u32 newclust = 0; //new cluster index of next consecutive clusters
+ unsigned thisConsecutiveLen = 0;
+
+ endclust = curclust;
+ /* search for consecutive clusters until get enghou size*/
+ while (actsize >= bytesperclust)
+ {
+ newclust = get_fatent(mydata, endclust);//get next cluster index
+ if (CHECK_CLUST(newclust, mydata->fatsize)) {
+ FAT_ERROR("curclust: 0x%x\n", newclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ goto exit;
+ }
+ thisConsecutiveLen+= bytesperclust;
+ actsize -= bytesperclust;
+
+ //clusters not consecutive
+ if ((newclust -1)!= endclust) break;
+ endclust =newclust;//update curclust for next read
+ }
+ if (thisConsecutiveLen)
+ {
+ if (get_cluster(mydata, curclust, buffer, thisConsecutiveLen) != 0) {
+ FAT_ERROR("Error reading cluster\n");
+ return -1;
+ }
+ buffer += thisConsecutiveLen;
+ gotsize += thisConsecutiveLen;
+ offset += thisConsecutiveLen;
+ curclust = newclust;
+ /*DWN_DBG("thisConsecutiveLen 0x%x\n", thisConsecutiveLen);*/
+ }
+ //data not enough
+ if (actsize < bytesperclust && actsize) //Left data in the 'next' cluster < bytesperclust
+ {
+ __u8* clusterCache = (__u8*)theFsInfo->fat_buf;
+
+ if (get_cluster(mydata, curclust, clusterCache, bytesperclust) != 0) {
+ FAT_ERROR("Error reading cluster\n");
+ return -1;
+ }
+ theFsInfo->fat_buf_cluster_index = curclust;
+ memcpy(buffer, clusterCache, actsize);
+
+ gotsize += actsize;
+ offset += actsize;
+
+ //If this message printed when burning, we saied the bootloader is above data parts in image.cfg, or
+ //sdc_burn not burn data partitions in the order in image
+ FAT_MSG("sz 0x%x gz 0x%x, bps 0x%x\n", (unsigned)actsize, gotsize, bytesperclust);//bpc:bytesperclust
+ actsize = 0;///end the loop
+ }
+ }
+
+exit:
+
+ files[fd].offset = offset;
+ files[fd].curclust = curclust;
+ return gotsize;
+}
+
+void
+do_fat_fclose(int fd)
+{
+
+ if (fd >= 0)
+ {
+ memset(&files[fd], 0, sizeof(struct file));
+ memset(&fs_info[fd], 0, sizeof(struct _fs_info));
+ }
+
+ if (fs_info[fd].fat_buf)
+ {
+ free(fs_info[fd].fat_buf);
+ fs_info[fd].fat_buf=0;
+ }
+
+ put_fd(fd);
+}
+
+// added by scy
+//if image not exist, return 0
+s64 do_fat_get_fileSz(const char* imgItemPath)
+{
+ char cmdBuf[256] = "";
+ int rcode = 0;
+ const char* envFileSz = NULL;
+ const char* usb_update = getenv("usb_update");
+
+ if (!strcmp(usb_update,"1"))
+ {
+ //fatexist usb host 0 imgItemPath
+ sprintf(cmdBuf, "fatexist usb 0 %s", imgItemPath);
+ }
+ else
+ {
+ optimus_sdc_burn_switch_to_extmmc();
+ sprintf(cmdBuf, "fatexist mmc 0 %s", imgItemPath);
+ }
+ /*SDC_DBG("to run cmd [%s]\n", cmdBuf);*/
+ rcode = run_command(cmdBuf, 0);
+ if (rcode) {
+ printf("fail in cmd [%s], rcode %d\n", cmdBuf, rcode);
+ return 0;//item size is 0
+ }
+ envFileSz = getenv("filesize");
+ /*SDC_DBG("size of item %s is 0x%s\n", imgItemPath, envFileSz);*/
+
+ return simple_strtoull(envFileSz, NULL, 16);
+}
+
+//<0 if failed, 0 is normal, 1 is sparse, others reserved
+int do_fat_get_file_format(const char* imgFilePath, unsigned char* pbuf, const unsigned bufSz)
+{
+ int readSz = 0;
+
+ int hFile = do_fat_fopen(imgFilePath);
+ if (hFile < 0) {
+ printf("Fail to open file (%s)\n", imgFilePath);
+ return -1;
+ }
+
+ readSz = do_fat_fread(hFile, pbuf, bufSz);
+ if (readSz <= 0) {
+ printf("Fail to read file(%s), readSz=%d\n", imgFilePath, readSz);
+ do_fat_fclose(hFile);
+ return -1;
+ }
+
+ readSz = optimus_simg_probe(pbuf, readSz);
+
+ do_fat_fclose(hFile);
+
+ return readSz;
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_img_decoder.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_img_decoder.c
new file mode 100644
index 0000000000..f70664766b
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_img_decoder.c
@@ -0,0 +1,601 @@
+/*
+ * \file optimus_img_decoder.c
+ * \brief
+ *
+ * \version 1.0.0
+ * \date 2013-7-8
+ * \author Sam.Wu <yihui.wu@amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+
+//FIMXE:
+COMPILE_TYPE_CHK(128 == sizeof(ItemInfo_V1), _op_a);
+COMPILE_TYPE_CHK(576 == sizeof(ItemInfo_V2), __op_a2);
+COMPILE_TYPE_CHK(64 == sizeof(AmlFirmwareImg_t), __op_b);
+
+typedef struct _ImgSrcIf{
+ unsigned devIf; //mmc/usb/store
+ unsigned devNo; //0/1/2
+ unsigned devAlignSz; //64K for store
+ unsigned reserv2Align64;
+ uint64_t itemCurSeekOffsetInImg;//fread will auto seek the @readSz, but for STORE we must do it
+
+ char partName[28]; //partIndex <= 28 (+4 if partIndex not used)
+ unsigned partIndex; //partIndex and part
+ unsigned char resrv[512 - 32 - 24];
+}ImgSrcIf_t;
+
+COMPILE_TYPE_CHK(512 == sizeof(ImgSrcIf_t), bb);
+#define MAX_ITEM_NUM 48
+
+typedef struct _ImgInfo_s
+{
+ ImgSrcIf_t imgSrcIf;
+ AmlFirmwareImg_t imgHead;//Must begin align 512, or store read wiill exception
+ union ItemInfo_u{
+ ItemInfo_V1 v1[MAX_ITEM_NUM];
+ ItemInfo_V2 v2[MAX_ITEM_NUM];
+ }itemInfo;
+
+}ImgInfo_t;
+
+typedef struct _AmlFirmwareItem0_s
+{
+ __u32 itemId;
+ __u32 fileType; //image file type, sparse and normal
+ __u64 curoffsetInItem; //current offset in the item
+ __u64 offsetInImage; //item offset in the image
+ __u64 itemSz; //item size in the image
+ const char* itemMainType;
+ const char* itemSubType;
+}ItemInfo;
+
+static int _hFile = -1;
+
+//open a Amlogic firmware image
+//return value is a handle
+HIMAGE image_open(const char* interface, const char* device, const char* part, const char* imgPath)
+{
+ const int HeadSz = sizeof(ImgInfo_t) - sizeof(ImgSrcIf_t);
+ ImgInfo_t* hImg = (ImgInfo_t*)OPTIMUS_BURN_PKG_HEAD_BUF_ADDR;
+ int ret = 0;
+ ImgSrcIf_t* pImgSrcIf = NULL;
+ unsigned imgVer = 0;
+
+ pImgSrcIf = &hImg->imgSrcIf;
+ memset(pImgSrcIf, 0, sizeof(ImgSrcIf_t));
+
+ if (!strcmp("store", interface))
+ {
+ DWN_DBG("imgHead=0x%x, hImg=%p\n", (unsigned)&hImg->imgHead, hImg);
+ ret = store_read_ops((u8*)part, (u8*)&hImg->imgHead, IMG_OFFSET_IN_PART, HeadSz);
+ if (ret) {
+ DWN_ERR("Fail to read image header.\n");
+ ret = __LINE__; goto _err;
+ }
+
+ pImgSrcIf->devIf = IMAGE_IF_TYPE_STORE;
+ pImgSrcIf->devAlignSz = 4*1024;//512;//OPTIMUS_DOWNLOAD_SLOT_SZ;
+ strcpy(pImgSrcIf->partName, part);
+ }
+ else
+ {
+ int pFile = do_fat_fopen(imgPath);
+ if (pFile < 0) {
+ DWN_ERR("Fail to open file %s\n", imgPath);
+ goto _err;
+ }
+ _hFile = pFile;
+
+ ret = do_fat_fread(pFile, (u8*)&hImg->imgHead, HeadSz);
+ if (ret != HeadSz) {
+ DWN_ERR("want to read %d, but %d\n", HeadSz, ret);
+ goto _err;
+ }
+
+ pImgSrcIf->devAlignSz = do_fat_get_bytesperclust(pFile);
+ }
+
+ if (IMAGE_MAGIC != hImg->imgHead.magic) {
+ DWN_ERR("error magic 0x%x\n", hImg->imgHead.magic);
+ goto _err;
+ }
+ imgVer = hImg->imgHead.version;
+ if (AML_FRMWRM_VER_V1 != imgVer && AML_FRMWRM_VER_V2 != imgVer) {
+ DWN_ERR("error verison 0x%x\n", hImg->imgHead.version);
+ goto _err;
+ }
+ DWN_MSG("image version [0x%8x]\n", imgVer);
+ if (MAX_ITEM_NUM < hImg->imgHead.itemNum) {
+ DWN_ERR("max itemNum(%d)<actual itemNum (%d)\n", MAX_ITEM_NUM, hImg->imgHead.itemNum);
+ goto _err;
+ }
+
+ return hImg;
+_err:
+ return NULL;
+}
+
+
+//close a Amlogic firmware image
+int image_close(HIMAGE hImg)
+{
+ DWN_MSG("to close image\n");
+
+ if (_hFile >= 0)do_fat_fclose(_hFile) , _hFile = -1;
+
+ if (hImg) {
+ hImg = NULL;
+ }
+ return 0;
+}
+
+static const ItemInfo* image_item_get_item_info_byid(HIMAGE hImg, const int itemIndex)
+{
+ ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ const unsigned imgVer = imgInfo->imgHead.version;
+ static ItemInfo theItem;
+
+ switch (imgVer)
+ {
+ case AML_FRMWRM_VER_V2:
+ {
+ ItemInfo_V2* pItem = &imgInfo->itemInfo.v2[itemIndex];
+ theItem.itemMainType = pItem->itemMainType;
+ theItem.itemSubType = pItem->itemSubType;
+ theItem.itemSz = pItem->itemSz;
+ theItem.offsetInImage = pItem->offsetInImage;
+ theItem.curoffsetInItem = pItem->curoffsetInItem;
+ theItem.fileType = pItem->fileType;
+ theItem.itemId = pItem->itemId;
+ }
+ break;
+
+ case AML_FRMWRM_VER_V1:
+ {
+ ItemInfo_V1* pItem = &imgInfo->itemInfo.v1[itemIndex];
+ theItem.itemMainType = pItem->itemMainType;
+ theItem.itemSubType = pItem->itemSubType;
+ theItem.itemSz = pItem->itemSz;
+ theItem.offsetInImage = pItem->offsetInImage;
+ theItem.curoffsetInItem = pItem->curoffsetInItem;
+ theItem.fileType = pItem->fileType;
+ theItem.itemId = pItem->itemId;
+ }
+ break;
+
+ default:
+ DWN_ERR("Exception, imgVer=0x%x\n", imgVer);
+ return NULL;
+ }
+
+ return &theItem;
+}
+
+//open a item in the image
+//@hImage: image handle;
+//@mainType, @subType: main type and subtype to index the item, such as ["IMAGE", "SYSTEM"]
+HIMAGEITEM image_item_open(HIMAGE hImg, const char* mainType, const char* subType)
+{
+ ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ const int itemNr = imgInfo->imgHead.itemNum;
+ const ItemInfo* pItem = NULL;
+ int i = 0;
+
+ for (; i < itemNr ;i++)
+ {
+ pItem = image_item_get_item_info_byid(hImg, i);
+ if (!pItem) {
+ DWN_ERR("Fail to get item at index %d\n", i);
+ return NULL;
+ }
+
+ if (!strcmp(mainType, pItem->itemMainType) && !strcmp(subType, pItem->itemSubType))
+ {
+ break;
+ }
+ }
+ if (i >= itemNr) {
+ DWN_ERR("Can't find item [%s, %s]\n", mainType, subType);
+ return NULL;
+ }
+
+ if (i != pItem->itemId) {
+ DWN_ERR("itemid %d err, should %d\n", pItem->itemId, i);
+ return NULL;
+ }
+
+ if (IMAGE_IF_TYPE_STORE != imgInfo->imgSrcIf.devIf)
+ {
+ DWN_DBG("Item offset 0x%llx\n", pItem->offsetInImage);
+ i = do_fat_fseek(_hFile, pItem->offsetInImage, 0);
+ if (i) {
+ DWN_ERR("fail to seek, offset is 0x%x\n", (u32)pItem->offsetInImage);
+ return NULL;
+ }
+ }
+ imgInfo->imgSrcIf.itemCurSeekOffsetInImg = pItem->offsetInImage;
+
+ return (HIMAGEITEM)pItem;
+}
+
+//Need this if item offset in the image file is not aligned to bytesPerCluster of FAT
+unsigned image_item_get_first_cluster_size(HIMAGE hImg, HIMAGEITEM hItem)
+{
+ const ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ ItemInfo* pItem = (ItemInfo*)hItem;
+ unsigned itemSizeNotAligned = 0;
+ const unsigned fat_bytesPerCluste = imgInfo->imgSrcIf.devAlignSz;
+
+ itemSizeNotAligned = pItem->offsetInImage & (fat_bytesPerCluste - 1);
+ itemSizeNotAligned = fat_bytesPerCluste - itemSizeNotAligned;
+
+ DWN_MSG("itemSizeNotAligned 0x%x\n", itemSizeNotAligned);
+ return itemSizeNotAligned;
+}
+
+unsigned image_get_cluster_size(HIMAGEITEM hImg)
+{
+ const ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ const unsigned fat_bytesPerCluste = imgInfo->imgSrcIf.devAlignSz;
+
+ return fat_bytesPerCluste;
+}
+
+//close a item
+int image_item_close(HIMAGEITEM hItem)
+{
+ return 0;
+}
+
+__u64 image_item_get_size(HIMAGEITEM hItem)
+{
+ ItemInfo* pItem = (ItemInfo*)hItem;
+
+ return pItem->itemSz;
+}
+
+
+//get image item type, current used type is normal or sparse
+int image_item_get_type(HIMAGEITEM hItem)
+{
+ ItemInfo* pItem = (ItemInfo*)hItem;
+
+ return pItem->fileType;
+}
+
+//read item data, like standard fread
+int image_item_read(HIMAGE hImg, HIMAGEITEM hItem, void* pBuf, const __u32 wantSz)
+{
+ ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ unsigned readSz = 0;
+
+ if (IMAGE_IF_TYPE_STORE == imgInfo->imgSrcIf.devIf)
+ {
+ unsigned char* part = (unsigned char*)imgInfo->imgSrcIf.partName;
+ const uint64_t offsetInPart = imgInfo->imgSrcIf.itemCurSeekOffsetInImg + IMG_OFFSET_IN_PART;
+ int rc = 0;
+ const unsigned storeBlkSz = imgInfo->imgSrcIf.devAlignSz;
+ const unsigned offsetNotAlign = offsetInPart & (storeBlkSz - 1);
+ const unsigned sizeNotAlignInFirstBlk = storeBlkSz - offsetNotAlign;//in the the first block and its offset not aligned
+
+ //Attention: deal with the align issue in "optimus_burn_one_partition", then not need to modify "do_fat_fread"
+ if (offsetNotAlign)
+ {
+ unsigned char* bufInABlk = NULL;
+ const uint64_t readOffset = offsetInPart - offsetNotAlign;
+ const unsigned bufLen = sizeNotAlignInFirstBlk < wantSz ? sizeNotAlignInFirstBlk : (wantSz);
+ unsigned thisTotalReadSz = wantSz;
+
+ DWN_MSG("offsetInPart %llx, wantSz=%x\n", offsetInPart, wantSz);
+ bufInABlk = (u8*)malloc(storeBlkSz);
+ rc = store_read_ops(part, bufInABlk, readOffset, storeBlkSz);
+ if (rc) {
+ DWN_ERR("Fail to read: readOffset=%llx, storeBlkSz=%x\n", readOffset, storeBlkSz);
+ free(bufInABlk);
+ return __LINE__;
+ }
+ memcpy(pBuf, bufInABlk + offsetNotAlign, bufLen);
+ thisTotalReadSz -= bufLen;
+ pBuf += bufLen/sizeof(void);
+ free(bufInABlk);
+
+ if (sizeNotAlignInFirstBlk < wantSz && offsetNotAlign)
+ {
+ rc = store_read_ops(part, (u8*)pBuf, (offsetInPart + sizeNotAlignInFirstBlk), thisTotalReadSz);
+ if (rc) {
+ DWN_ERR("Fail in store_read_ops to read %u at offset %llx.\n", wantSz,
+ offsetInPart + sizeNotAlignInFirstBlk);
+ return __LINE__;
+ }
+ }
+ }
+ else
+ {
+ rc = store_read_ops(part, (u8*)pBuf, offsetInPart, wantSz);
+ if (rc) {
+ DWN_ERR("Fail in store_read_ops to read %u at offset %llx.\n", wantSz, offsetInPart);
+ return __LINE__;
+ }
+ }
+
+ imgInfo->imgSrcIf.itemCurSeekOffsetInImg += wantSz;
+ }
+ else
+ {
+ readSz = do_fat_fread(_hFile, pBuf, wantSz);
+ if (readSz != wantSz) {
+ DWN_ERR("want to read 0x%x, but 0x%x\n", wantSz, readSz);
+ return __LINE__;
+ }
+ }
+
+ return 0;
+}
+
+int get_total_itemnr(HIMAGE hImg)
+{
+ ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+
+ return imgInfo->imgHead.itemNum;
+}
+
+HIMAGEITEM get_item(HIMAGE hImg, int itemId)
+{
+ int ret = 0;
+ ImgInfo_t* imgInfo = (ImgInfo_t*)hImg;
+ const ItemInfo* pItem = NULL;
+
+ pItem = image_item_get_item_info_byid(hImg, itemId);
+ if (!pItem) {
+ DWN_ERR("Fail to get item at index %d\n", itemId);
+ return NULL;
+ }
+ if (itemId != pItem->itemId) {
+ DWN_ERR("itemid %d err, should %d\n", pItem->itemId, itemId);
+ return NULL;
+ }
+ DWN_MSG("get item [%s, %s] at %d\n", pItem->itemMainType, pItem->itemSubType, itemId);
+
+ if (IMAGE_IF_TYPE_STORE != imgInfo->imgSrcIf.devIf)
+ {
+ ret = do_fat_fseek(_hFile, pItem->offsetInImage, 0);
+ if (ret) {
+ DWN_ERR("fail to seek, offset is 0x%x, ret=%d\n", (u32)pItem->offsetInImage, ret);
+ return NULL;
+ }
+ }
+ imgInfo->imgSrcIf.itemCurSeekOffsetInImg = pItem->offsetInImage;
+
+ return (HIMAGEITEM)pItem;
+}
+
+int get_item_name(HIMAGE hImg, int itemId, const char** main_type, const char** sub_type)
+{
+ const ItemInfo* pItem = NULL;
+
+ pItem = image_item_get_item_info_byid(hImg, itemId);
+ if (!pItem) {
+ DWN_ERR("Fail to get item at index %d\n", itemId);
+ return __LINE__;
+ }
+ if (itemId != pItem->itemId) {
+ DWN_ERR("itemid %d err, should %d\n", pItem->itemId, itemId);
+ return __LINE__;
+ }
+ DWN_DBG("get item [%s, %s] at %d\n", pItem->itemMainType, pItem->itemSubType, itemId);
+
+ *main_type = pItem->itemMainType;
+ *sub_type = pItem->itemSubType;
+
+ return OPT_DOWN_OK;
+}
+
+__u64 image_get_item_size_by_index(HIMAGE hImg, const int itemId)
+{
+ const ItemInfo* pItem = NULL;
+
+ pItem = image_item_get_item_info_byid(hImg, itemId);
+ if (!pItem) {
+ DWN_ERR("Fail to get item at index %d\n", itemId);
+ return 0;
+ }
+ if (itemId != pItem->itemId) {
+ DWN_ERR("itemid %d err, should %d\n", pItem->itemId, itemId);
+ return __LINE__;
+ }
+ DWN_DBG("get item [%s, %s] at %d\n", pItem->itemMainType, pItem->itemSubType, itemId);
+
+ return pItem->itemSz;
+}
+
+u64 optimus_img_decoder_get_data_parts_size(HIMAGE hImg, int* hasBootloader)
+{
+ int i = 0;
+ int ret = 0;
+ u64 dataPartsSz = 0;
+ const int totalItemNum = get_total_itemnr(hImg);
+
+ *hasBootloader = 0;
+ for (i = 0; i < totalItemNum; i++)
+ {
+ const char* main_type = NULL;
+ const char* sub_type = NULL;
+
+ ret = get_item_name(hImg, i, &main_type, &sub_type);
+ if (ret) {
+ DWN_ERR("Exception:fail to get item name!\n");
+ return __LINE__;
+ }
+
+ if (strcmp("PARTITION", main_type)) { continue; }
+ if (!strcmp("bootloader", sub_type)) {
+ *hasBootloader = 1;
+ continue;
+ }
+ if (!strcmp(AML_SYS_RECOVERY_PART, sub_type))
+ {
+ if (OPTIMUS_WORK_MODE_SYS_RECOVERY == optimus_work_mode_get()) continue;
+ }
+
+ dataPartsSz += image_get_item_size_by_index(hImg, i);
+ }
+
+ return dataPartsSz;
+}
+
+#define MYDBG 0
+#if MYDBG
+static int test_item(HIMAGE hImg, const char* main_type, const char* sub_type, char* pBuf, const int sz)
+{
+ HIMAGEITEM hItem = NULL;
+ int ret = 0;
+
+ hItem = image_item_open(hImg, main_type, sub_type);
+ if (!hItem) {
+ DWN_ERR("fail to open %s, %s\n", main_type, sub_type);
+ return __LINE__;
+ }
+
+ ret = image_item_read(hImg, hItem, pBuf, sz);
+ if (ret) {
+ DWN_ERR("fail to read\n");
+ goto _err;
+ }
+ if (64 >= sz)DWN_MSG("%s\n", pBuf) ;
+
+_err:
+ image_item_close(hItem);
+ return ret;
+}
+
+static int test_pack(const char* interface, const char* device, const char* part, const char* imgPath)
+{
+ const int ImagBufLen = OPTIMUS_DOWNLOAD_SLOT_SZ;
+ char* pBuf = (char*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR + ImagBufLen;
+ int ret = 0;
+ int i = 0;
+ HIMAGEITEM hItem = NULL;
+
+ if (!strcmp("store", interface))
+ {
+ ret = run_command("store init 1", 0);
+ if (ret) {
+ DWN_ERR("Fail in init mmc, Does sdcard not plugged in?\n");
+ return __LINE__;
+ }
+ }
+ else
+ {
+ s64 fileSz = 0;
+
+ ret = run_command("mmcinfo", 0);
+ if (ret) {
+ DWN_ERR("Fail in init mmc, Does sdcard not plugged in?\n");
+ return __LINE__;
+ }
+
+ fileSz = do_fat_get_fileSz(imgPath);
+ if (!fileSz) {
+ DWN_ERR("file %s not exist\n", imgPath);
+ return __LINE__;
+ }
+ }
+
+ HIMAGE hImg = image_open(interface, device, part, imgPath);
+ if (!hImg) {
+ DWN_ERR("Fail to open image\n");
+ return __LINE__;
+ }
+
+ const int itemNr = get_total_itemnr(hImg);
+ for (i = 0; i < itemNr ; i++)
+ {
+ __u64 itemSz = 0;
+ int fileType = 0;
+
+ hItem = get_item(hImg, i);
+ if (!hItem) {
+ DWN_ERR("Fail to open item at id %d\n", i);
+ break;
+ }
+
+ itemSz = image_item_get_size(hItem);
+ DWN_MSG("Item Sz is 0x%llx\n", itemSz);
+
+ unsigned wantSz = ImagBufLen > itemSz ? (unsigned)itemSz : ImagBufLen;
+ unsigned itemSizeNotAligned = 0;
+ char* readBuf = pBuf;
+ unsigned readSz = wantSz;
+
+ itemSizeNotAligned = image_item_get_first_cluster_size(hImg, hItem);
+ if (itemSizeNotAligned)
+ {
+ ret = image_item_read(hImg, hItem, readBuf, itemSizeNotAligned);
+ readSz = (wantSz > itemSizeNotAligned) ? (wantSz - itemSizeNotAligned) : 0;
+ }
+
+ if (readSz)
+ {
+ ret = image_item_read(hImg, hItem, readBuf + itemSizeNotAligned, readSz);
+ if (ret) {
+ DWN_ERR("fail to read item data\n");
+ break;
+ }
+ }
+
+ fileType = image_item_get_type(hItem);
+ if (IMAGE_ITEM_TYPE_SPARSE == fileType)
+ {
+ DWN_MSG("sparse packet\n");
+ ret = optimus_simg_probe((const u8*)pBuf, wantSz);
+ if (!ret) {
+ DWN_ERR("item data error, should sparse, but no\n");
+ break;
+ }
+ }
+ }
+
+#if 1
+ test_item(hImg, "PARTITION", "logo", pBuf, ImagBufLen);
+ test_item(hImg, "VERIFY", "logo", pBuf, 50);
+#endif
+
+ image_close(hImg);
+ return 0;
+}
+
+static int do_unpack(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ const char* imgPath = "a";
+
+#if 1
+ if (2 > argc) imgPath = "dt.img";
+#else
+ if (2 > argc) {
+ cmd_usage(cmdtp);
+ return -1;
+ }
+#endif//#if MYDBG
+ DWN_MSG("argc %d, %s, %s\n", argc, argv[0], argv[1]);
+
+ rcode = test_pack("mmc", "0", "aml_sysrecovery", imgPath);
+
+ DWN_MSG("rcode %d\n", rcode);
+ return rcode;
+}
+
+U_BOOT_CMD(
+ unpack, //command name
+ 5, //maxargs
+ 1, //repeatable
+ do_unpack, //command function
+ "unpack the image in sdmmc ", //description
+ "Usage: unpack imagPath\n" //usage
+);
+#endif//#if MYDBG
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_progress.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress.c
new file mode 100644
index 0000000000..3080fc3dbf
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress.c
@@ -0,0 +1,142 @@
+/*
+ * \file optimus_report_progress.c
+ * \brief display and print progress info when burning a partition
+ *
+ * \version 1.0.0
+ * \date 2013/6/23
+ * \author Sam.Wu <wuehui@allwinnertech.com>
+ *
+ * Copyright (c) 2013 Allwinner Technology. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+
+#define OPTIMUS_PROMPT_SIZE_MIN (4U<<20)//mininal size to prompt burning progress step
+
+struct ProgressInfo{
+ u32 itemSzLow;
+ u32 itemSzHigh;
+
+ u8 startStep;
+ u8 endStep;
+ u8 totalStepNum;
+ u8 currentStep;
+
+ u32 bytesToIncOneStep;
+ u32 unReportSzInByte;
+
+ u32 bytesToUpdateStep;
+ u32 reserv;
+
+};
+static struct ProgressInfo _progressInfo = {0};
+
+int optimus_progress_init(const unsigned itemSzHigh, const unsigned itemSzLow, const u32 startStep, const u32 endStep)
+{
+ _progressInfo.itemSzLow = itemSzLow;
+ _progressInfo.itemSzHigh = itemSzHigh;
+
+ _progressInfo.startStep = startStep;
+ _progressInfo.endStep = endStep;
+ _progressInfo.currentStep = startStep;
+ _progressInfo.totalStepNum = endStep - startStep;
+
+ _progressInfo.unReportSzInByte = 0;//clear it
+
+ //ATTENTION: as divisor / is lossy, _progressInfo.bytesToIncOneStep * _progressInfo.totalStepNum <= item size, so 100% is sometimes not exactly Burn Completed!!
+ _progressInfo.bytesToIncOneStep = ((((u64)itemSzHigh)<<32) + itemSzLow) / _progressInfo.totalStepNum;
+ _progressInfo.bytesToUpdateStep = (OPTIMUS_PROMPT_SIZE_MIN > _progressInfo.bytesToIncOneStep) ? OPTIMUS_PROMPT_SIZE_MIN : _progressInfo.bytesToIncOneStep;
+
+
+ DWN_DBG("item size 0x[%x, %x], currentStep %d, totalStepNum %d, bytesToIncOneStep 0x%x\n",
+ itemSzHigh, itemSzLow, _progressInfo.currentStep, _progressInfo.totalStepNum, _progressInfo.bytesToIncOneStep);
+ return 0;
+}
+
+int optimus_progress_exit(void)
+{
+ return 0;
+}
+
+int optimus_update_progress(const unsigned thisBurnSz)
+{
+ _progressInfo.unReportSzInByte += thisBurnSz;
+
+ if (_progressInfo.bytesToUpdateStep > _progressInfo.unReportSzInByte) {
+ return 0;
+ }
+
+ //if it is first time to prompt UI progress steps
+ if (_progressInfo.unReportSzInByte == thisBurnSz && _progressInfo.startStep + 1 == _progressInfo.currentStep)
+ {
+ printf("\n");
+ }
+
+ _progressInfo.currentStep += _progressInfo.unReportSzInByte / _progressInfo.bytesToIncOneStep;
+ _progressInfo.unReportSzInByte %= _progressInfo.bytesToIncOneStep;
+
+ printf("Downloading %%%d\r", _progressInfo.currentStep);
+ if (_progressInfo.currentStep == _progressInfo.endStep) {
+ printf("\n");
+ }
+
+ return 0;
+}
+
+//outStr will be null-terminater after format
+int optimus_hex_data_2_ascii_str(const unsigned char* hexData, const unsigned nBytes, char* outStr, const unsigned strSz)
+{
+ int i = 1;
+ if (strSz < 2 * nBytes + 1) {
+ DWN_ERR("strSz(%d) > 2 * nBytes(%d)\n", strSz, nBytes);
+ return __LINE__;
+ }
+
+ sprintf(outStr, "%02x", hexData[0]);
+ for (; i < nBytes; ++i)
+ {
+ sprintf(outStr, "%s%02x", outStr, hexData[i]);
+ }
+
+ return 0;
+}
+
+unsigned add_sum(const void* pBuf, const unsigned size)
+{
+ unsigned sum = 0;
+ const unsigned* data = (const unsigned*)pBuf;
+ unsigned wordLen = size>>2;
+ unsigned rest = size & 3;
+
+ for (; wordLen/4; wordLen -= 4)
+ {
+ sum += *data++;
+ sum += *data++;
+ sum += *data++;
+ sum += *data++;
+ }
+ while (wordLen--)
+ {
+ sum += *data++;
+ }
+
+ if (rest == 0)
+ {
+ ;
+ }
+ else if(rest == 1)
+ {
+ sum += (*data) & 0xff;
+ }
+ else if(rest == 2)
+ {
+ sum += (*data) & 0xffff;
+ }
+ else if(rest == 3)
+ {
+ sum += (*data) & 0xffffff;
+ }
+
+ return sum;
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.c
new file mode 100644
index 0000000000..c23bff1fb2
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.c
@@ -0,0 +1,634 @@
+/*
+ * \file optimus_progress_ui.c
+ * \brief Show progress info to UI
+ *
+ * \version 1.0.0
+ * \date 2013/10/13
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+#include <bmp_layout.h>
+#include <lcd.h>
+#include <video_font.h>
+
+#ifdef CONFIG_VIDEO_AMLLCD
+extern int lcd_drawchars (ushort x, ushort y, uchar *str, int count);
+#else
+#define lcd_drawchars(x, y, str, count)
+#define lcd_printf(fmt...)
+#endif// #ifdef CONFIG_VIDEO_AMLLCD
+
+#ifdef CONFIG_VIDEO_AMLTVOUT
+#define _VIDEO_DEV_OPEN "video dev open ${outputmode};"
+#else
+#define _VIDEO_DEV_OPEN "video dev bl_on;"
+#endif// #ifdef CONFIG_VIDEO_AMLTVOUT
+
+//if env upgrade_logo_offset exist, use bmp resources existed in memory
+int video_res_prepare_for_upgrade(HIMAGE hImg)
+{
+ const char* env_name = NULL;
+ int ret = 0;
+ const char* UpgradeLogoAddr = (const char*)OPTIMUS_DOWNLOAD_DISPLAY_BUF;
+ char env_buf[32];
+
+ //imgread res logo ${loadaddr_misc};
+ sprintf(env_buf, "imgread res logo 0x%p", UpgradeLogoAddr);
+ ret = run_command(env_buf, 0);
+
+ if (!ret) {
+ sprintf(env_buf, "unpackimg 0x%p", UpgradeLogoAddr);
+ ret = run_command(env_buf, 0);
+ }
+ if (ret)
+ {//Failed to load logo resources from memory, then Load it from package
+ unsigned imgItemSz = 0;
+ HIMAGEITEM hItem = NULL;
+
+ DWN_MSG("Use upgrade res in pkg\n");
+ hItem = image_item_open(hImg, "PARTITION", "logo");
+ if (!hItem) {
+ DWN_ERR("Fail to get logo.PARTITION for display logo\n");
+ return __LINE__;
+ }
+
+ imgItemSz = (unsigned)image_item_get_size(hItem);
+ ret = image_item_read(hImg, hItem, (void*)UpgradeLogoAddr, imgItemSz);
+ if (ret) {
+ DWN_ERR("Fail to read item logo\n");
+ image_item_close(hItem); return __LINE__;
+ }
+ image_item_close(hItem);
+
+ ret = run_command(env_buf, 0);
+ if (ret) {
+ DWN_ERR("Exception: Fail to unpack image in the package.\n");
+ return __LINE__;
+ }
+ }
+
+ //video prepare to show upgrade bmp
+
+#ifdef CONFIG_VIDEO_AMLLCD
+ if (OPTIMUS_WORK_MODE_SDC_PRODUCE == optimus_work_mode_get())
+ {
+ DWN_MSG("LCD Initialize for upgrade:\n");
+ aml_lcd_init();
+ }
+#endif// #ifdef CONFIG_VIDEO_AMLLCD
+
+ DWN_MSG("echo video prepare for upgrade\n");
+#ifdef CONFIG_CMD_LOGO
+ DWN_MSG("outputmode=%s\n", getenv("outputmode"));
+ env_name = "logo size ${outputmode}";
+ ret = run_command(env_name, 0);
+ if (ret) goto _fail;
+#endif// #ifdef CONFIG_CMD_LOGO
+ env_name = "video open; video clear;";
+ ret = run_command(env_name, 0);
+ if (ret) goto _fail;
+
+ env_name = _VIDEO_DEV_OPEN;
+ ret = run_command(env_name, 0);
+ if (ret) goto _fail;
+
+ ret = run_command("video clear", 0);//twice clear it
+
+ return 0;
+
+_fail:
+ DWN_ERR("Fail in run_command[%s]\n", env_name);
+ return ret;
+}
+
+static int _show_burn_logo(const char* bmpOffsetName) //Display logo to report burning result is failed
+{
+ int ret = 0;
+ char bmpCmd[64] = "bmp display %s";
+ char* bmpAddrEnv = getenv((char*)bmpOffsetName);
+
+ if (!bmpAddrEnv) {
+ const char* UpgradeLogoAddr = (const char*)OPTIMUS_DOWNLOAD_DISPLAY_BUF;
+ char env_buf[32];
+ sprintf(env_buf, "unpackimg 0x%p", UpgradeLogoAddr);
+
+ ret = run_command(env_buf, 0);//need re-unpack after 'defenv'
+ if (ret) {
+ DWN_ERR("Fail in re-unpack res img\n");
+ return __LINE__;
+ }
+ bmpAddrEnv = getenv((char*)bmpOffsetName);
+ }
+ sprintf(bmpCmd, "bmp display %s ", bmpAddrEnv);
+
+ ret = run_command(bmpCmd, 0);
+ if (ret) {
+ DWN_ERR("Fail in run[%s], bmpOffsetName=%s\n", bmpCmd, bmpOffsetName);
+ return __LINE__;
+ }
+#ifdef CONFIG_OSD_SCALE_ENABLE
+ run_command("bmp scale", 0);
+#endif// #ifdef CONFIG_OSD_SCALE_ENABLE
+
+ return 0;
+}
+
+//Display logo to report platform is in burning state
+int show_logo_to_report_burning(void)
+{
+ return _show_burn_logo("upgrade_upgrading_offset");
+}
+
+int show_logo_to_report_burn_success(void)
+{
+ int ret = 0;
+
+ ret = _show_burn_logo("upgrade_success_offset");
+ if (ret) {
+ DWN_ERR("Fail in display logo upgrade_success_offset\n");
+ return __LINE__;
+ }
+ lcd_printf("PLS short-press the power key to shut down\n");
+
+ return 0;
+}
+
+static int show_logo_report_burn_ui_error(void)
+{
+ int ret = 0;
+
+ ret = _show_burn_logo("upgrade_error_offset");
+ if (ret) {
+ DWN_ERR("Fail in display logo upgrade_error\n");
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+//Horizontal progress bar
+//_f means not changed after initialized
+typedef struct _uiProgress{
+ //For smart mode
+ u64 smartModeTotalBytes_f;//fixed
+ u64 smartModeLeftBytes;
+
+ unsigned nDownBytesOnePercent_f;//update 1% if .nDownBytesOnePercent, (==.totalDownloadBytes/totalPercents)
+
+//For total
+ int totalPercents_f; //Total width for display the progress bar, should < 'display_width'
+
+ int curPercent;//curent percent of the progress
+ int endPercent_f;//.endPercent + 1 - .startPerCent = .totalPercents, this field is fixed
+
+ int progressBarWidth_f;//pixel width of the progress bar bmp
+ int progressBarHeight_f;//pixel height of the progress bar bmp
+
+ unsigned totalProgressBarWidth_f;//total pixel width of the progress bar, use 'display_width'/100*100 ?
+ unsigned nProgressBarOnePercent_f;//times to display bar.if .totalProgressBarWidth=2000, .progressBarWidth=2, .totalPercents=100, then .nProgressBarOnePercent=10
+
+ int nextProgressBarX;
+ int progressBarY_f;//As this is a horizon progress bar, y coordinate is fixed.
+
+ int upgradeStepX_f;
+ int upgradeStepY_f;
+
+ unsigned bmpAddr_f;
+ unsigned reservToAlign64;
+}UiProgress_t;
+
+
+__hdle optimus_progress_ui_request(int totalPercents_f, int startPercent, unsigned bmpBarAddr,
+ int display_width, int progressBarY_f )
+{
+ UiProgress_t* pUiProgress = NULL;
+ bmp_header_t* bmpHeadInfo = (bmp_header_t*)bmpBarAddr;
+ const unsigned commonMultiple = totalPercents_f * bmpHeadInfo->width;
+
+ if (display_width < commonMultiple) {
+ DWN_ERR("pic width too large!! width(%d) * totalPercents_f(%d) >= display_width(%d)\n",
+ bmpHeadInfo->width, totalPercents_f, display_width);
+ show_logo_report_burn_ui_error(); return NULL;
+ }
+ pUiProgress = (UiProgress_t*)malloc(sizeof(UiProgress_t));
+ if (!pUiProgress) {
+ DWN_ERR("Fail when malloc for UiProgress_t\n");
+ show_logo_report_burn_ui_error(); return NULL;
+ }
+
+ pUiProgress->totalPercents_f = totalPercents_f;
+ pUiProgress->curPercent = startPercent;
+ pUiProgress->endPercent_f = startPercent + totalPercents_f;
+
+
+ pUiProgress->bmpAddr_f = bmpBarAddr;
+ pUiProgress->progressBarWidth_f = bmpHeadInfo->width;
+ pUiProgress->progressBarHeight_f = bmpHeadInfo->height;
+ DWN_MSG("w,h[%u,%u]\n", pUiProgress->progressBarWidth_f, pUiProgress->progressBarHeight_f);
+
+ pUiProgress->totalProgressBarWidth_f = /* common multiple of totalPercents_f and progress bar width */
+ (display_width / commonMultiple) * commonMultiple;
+ pUiProgress->nProgressBarOnePercent_f = pUiProgress->totalProgressBarWidth_f / totalPercents_f;
+
+ pUiProgress->nextProgressBarX = display_width - pUiProgress->totalProgressBarWidth_f;
+ pUiProgress->nextProgressBarX /= 2;
+
+ pUiProgress->progressBarY_f = progressBarY_f;
+ DWN_DBG("barYCor %d\n", progressBarY_f);
+
+ pUiProgress->upgradeStepX_f = pUiProgress->nextProgressBarX;
+ pUiProgress->upgradeStepY_f = progressBarY_f - VIDEO_FONT_HEIGHT;
+ DWN_DBG("upgradeStepX_f %d, upgradeStepY_f %d\n", pUiProgress->upgradeStepX_f, pUiProgress->upgradeStepY_f);
+
+ DWN_DBG("totalProgressBarWidth_f %d, nProgressBarOnePercent_f %d, nextProgressBarX %d\n",
+ pUiProgress->totalProgressBarWidth_f, pUiProgress->nProgressBarOnePercent_f, pUiProgress->nextProgressBarX);
+
+ return (__hdle)pUiProgress;
+}
+
+int optimus_progress_ui_set_smart_mode(__hdle hUiProgress, const u64 smartModeTotalBytes_f, const unsigned smartModePercents)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiProgress;
+
+ if (!smartModeTotalBytes_f || !smartModePercents) {
+ DWN_ERR("arg error!, smartModeTotalBytes_f %lld, smartModePercents %u\n", smartModeTotalBytes_f, smartModePercents);
+ show_logo_report_burn_ui_error();
+ return __LINE__;
+ }
+ pUiProgress->smartModeTotalBytes_f = smartModeTotalBytes_f;
+ pUiProgress->nDownBytesOnePercent_f = smartModeTotalBytes_f/smartModePercents;
+ DWN_DBG("nDownBytesOnePercent_f %d\n", pUiProgress->nDownBytesOnePercent_f);
+ pUiProgress->smartModeLeftBytes = 0;
+
+ return 0;
+}
+
+int optimus_progress_ui_set_unfocus_bkg(__hdle hUiProgress, unsigned unfocusBmpAddr)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiProgress;
+ bmp_header_t* bkgBmpHead = (bmp_header_t*)unfocusBmpAddr;
+ const unsigned barHeight = pUiProgress->progressBarHeight_f;
+ const unsigned bkgHeight = bkgBmpHead->height;
+ const unsigned bkgWidth = bkgBmpHead->width;
+ const int nProgressBar = pUiProgress->totalPercents_f
+ * pUiProgress->nProgressBarOnePercent_f / bkgWidth;
+ int progressBarX = pUiProgress->nextProgressBarX;
+ const int progressBarY = pUiProgress->progressBarY_f;
+
+ int i = 0;
+
+ //allow width not equal, but height must equal!
+ if (barHeight != bkgHeight) {
+ DWN_ERR("barHeight %d != bkgHeight %d\n", barHeight, bkgHeight);
+ show_logo_report_burn_ui_error();
+ return __LINE__;
+ }
+
+ //show the progress bar to update progress to video device
+ for (i=0; i < nProgressBar; ++i)
+ {
+ char cmd[64];
+
+ sprintf(cmd, "bmp display 0x%x %d %d 1", unfocusBmpAddr, progressBarX, progressBarY);
+ if (run_command(cmd, 0)) {
+ DWN_ERR("Fail to in cmd[%s]\n", cmd);
+ show_logo_report_burn_ui_error();
+ return __LINE__;
+ }
+
+ progressBarX += bkgWidth;
+ }
+
+#ifdef CONFIG_OSD_SCALE_ENABLE
+ run_command("bmp scale", 0);
+#endif// #ifdef CONFIG_OSD_SCALE_ENABLE
+
+ return 0;
+}
+
+static int optimus_progress_ui_set_steps(__hdle hUiProgress, int steps)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiProgress;
+ const int curPercent = pUiProgress->curPercent;
+ char strStep[16];
+
+ sprintf(strStep, "%d%%", steps);
+ lcd_drawchars((ushort)pUiProgress->upgradeStepX_f, (ushort)pUiProgress->upgradeStepY_f, (uchar*)strStep, strlen(strStep));
+
+ if (UPGRADE_STEPS_AFTER_IMAGE_OPEN_OK == curPercent)
+ {
+ lcd_printf("[OK]Open image\n");
+ }
+ if (UPGRADE_STEPS_AFTER_DISK_INIT_OK == curPercent)
+ {
+ lcd_printf("[OK]Disk initial\n");
+ }
+ else if(UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK == curPercent)
+ {
+ lcd_printf("[OK]Burn Data Partitons\n");
+ }
+ else if(UPGRADE_STEPS_AFTER_BURN_BOOTLOADER_OK == curPercent)
+ {
+ lcd_printf("[OK]Burn bootloader\n");
+ }
+
+ return 0;
+}
+
+int optimus_progress_ui_direct_update_progress(__hdle hUiProgress, const int percents)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiProgress;
+ const int nPercents = percents - pUiProgress->curPercent;
+ const int nProgressBar= nPercents * pUiProgress->nProgressBarOnePercent_f / pUiProgress->progressBarWidth_f;
+ int i = 0;
+
+ //if already up to this user percents, not need to update yet!
+ if (percents > pUiProgress->endPercent_f) {
+ DWN_ERR("user percents(%d) beyond max (%d)\n", percents, pUiProgress->endPercent_f);
+ show_logo_report_burn_ui_error();
+ return __LINE__;
+ }
+ if (nPercents <= 0) {
+ DWN_MSG("curPercent(%d) >= percents(%d)\n", pUiProgress->curPercent, percents);
+ show_logo_report_burn_ui_error();
+ return 0;
+ }
+
+ DWN_DBG("curPercent %d, percents %d, nPercents %d\n", pUiProgress->curPercent, percents, nPercents);
+ DWN_DBG("nProgressBar %d, %d\n", nProgressBar, pUiProgress->progressBarWidth_f);
+
+ //show the progress bar to update progress to video device
+ for (i=0; i < nProgressBar; ++i)
+ {
+ const int progressBarX = pUiProgress->nextProgressBarX;
+ const int progressBarY = pUiProgress->progressBarY_f;
+ const unsigned bmpAddr = pUiProgress->bmpAddr_f;
+ char cmd[64];
+
+ sprintf(cmd, "bmp display %x %d %d 1", bmpAddr, progressBarX, progressBarY);
+ if (run_command(cmd, 0)) {
+ DWN_ERR("Fail to in cmd[%s]\n", cmd);
+ show_logo_report_burn_ui_error();
+ return __LINE__;
+ }
+
+ pUiProgress->nextProgressBarX += pUiProgress->progressBarWidth_f;
+ }
+#ifdef CONFIG_OSD_SCALE_ENABLE
+ run_command("bmp scale", 0);
+#endif// #ifdef CONFIG_OSD_SCALE_ENABLE
+
+ pUiProgress->curPercent = percents;
+
+ optimus_progress_ui_set_steps(hUiProgress, percents);
+
+ return 0;
+}
+
+//intelligent mode, update progress by download bytes
+int optimus_progress_ui_update_by_bytes(__hdle hUiPrgress, const unsigned nBytes)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiPrgress;
+ const unsigned nDownBytesOnePercent_f = pUiProgress->nDownBytesOnePercent_f;
+ const unsigned bytesNotReport = nBytes + pUiProgress->smartModeLeftBytes;
+ int percentsIncreased = 0;
+ unsigned leftBytes = 0;
+ int ret = 0;
+ int percentsToReport = 0;
+
+ //bytes not enghout to update one percent
+ if (bytesNotReport < nDownBytesOnePercent_f)
+ {
+ pUiProgress->smartModeLeftBytes = bytesNotReport;
+ return 0;
+ }
+ percentsIncreased = bytesNotReport / nDownBytesOnePercent_f;
+ leftBytes = bytesNotReport - percentsIncreased * nDownBytesOnePercent_f;
+
+ percentsToReport = percentsIncreased + pUiProgress->curPercent;
+ DWN_DBG("update ui to [%d%%]\n", percentsToReport);
+ ret = optimus_progress_ui_direct_update_progress(hUiPrgress, percentsToReport);
+ pUiProgress->smartModeLeftBytes = leftBytes;
+
+ return ret;
+}
+
+int optimus_progress_ui_release(__hdle hUiPrgress)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiPrgress;
+
+ DWN_MSG("Release prgress bar res\n");
+ if (pUiProgress)
+ {
+ free(pUiProgress), pUiProgress = NULL;
+ }
+
+ return 0;
+}
+
+__hdle optimus_progress_ui_request_for_sdc_burn(void)
+{
+ __hdle hUiProgress = NULL;
+ unsigned barAddr = simple_strtoul(getenv("upgrade_bar_offset"), NULL, 0);
+ unsigned display_width = simple_strtoul(getenv("display_width"), NULL, 0);
+ unsigned display_height = simple_strtoul(getenv("display_height"), NULL, 0);
+ bmp_header_t* upgrading = (bmp_header_t*)simple_strtoul(getenv("upgrade_upgrading_offset"), NULL, 0);
+ const unsigned loadingHeight = upgrading->height;
+ const unsigned barYCor =
+ (3* display_height + loadingHeight)/4;//display_height - (display_height/2 - loadingHeight/2)/2;
+ unsigned unfocusBmpAddr = simple_strtoul(getenv("upgrade_unfocus_offset"), NULL, 0);
+
+ if (!barAddr) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_bar_offset", getenv("upgrade_bar_offset"));
+ show_logo_report_burn_ui_error();
+ return NULL;
+ }
+ if (!display_width) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "display_width", getenv("display_width"));
+ show_logo_report_burn_ui_error(); return NULL;
+ }
+ if (!display_height) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "display_height", getenv("display_height")); return NULL;
+ }
+ if (!upgrading) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_upgrading_offset", getenv("upgrade_upgrading_offset"));
+ show_logo_report_burn_ui_error(); return NULL;
+ }
+ if (!unfocusBmpAddr) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_unfocus_offset", getenv("upgrade_unfocus_offset"));
+ show_logo_report_burn_ui_error(); return NULL;
+ }
+ DWN_DBG("upgrade_unfocus_offset=%s\n", getenv("upgrade_unfocus_offset"));
+
+ DWN_MSG("dw,dh[%u, %u]\n", display_width, display_height);
+ hUiProgress = optimus_progress_ui_request(100, 0,barAddr, display_width, barYCor);
+ if (!hUiProgress) {
+ DWN_ERR("Fail to request progress bar\n");
+ return NULL;
+ }
+
+ if (optimus_progress_ui_set_unfocus_bkg(hUiProgress, unfocusBmpAddr)) {
+ DWN_ERR("Fail to set bkg\n");
+ return NULL;;
+ }
+
+ return hUiProgress;
+}
+
+int optimus_progress_ui_report_upgrade_stat(__hdle hUiProgress, const int isSuccess)
+{
+ UiProgress_t* pUiProgress = (UiProgress_t*)hUiProgress;
+ const int curPercent = pUiProgress->curPercent;
+
+ if (isSuccess)
+ {
+ optimus_progress_ui_direct_update_progress(hUiProgress, 100);
+ _show_burn_logo("upgrade_success_offset");
+ lcd_printf("Burning Success^^\nPLS SHORT-PRESS the power key to shut down\n");
+ return 0;
+ }
+
+ _show_burn_logo("upgrade_fail_offset");
+ lcd_printf("[Failed] at ");
+ //Followings failure
+ if (UPGRADE_STEPS_AFTER_IMAGE_OPEN_OK == curPercent)
+ {
+ lcd_printf("Disk initial!!\n");
+ }
+ else if(UPGRADE_STEPS_AFTER_DISK_INIT_OK < curPercent && UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK > curPercent)
+ {
+ lcd_printf("Burning Data Partitons[%d%%]\n", curPercent);
+ }
+ else if(UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK == curPercent)
+ {
+ lcd_printf("Burning bootloader\n");
+ }
+ else if(UPGRADE_STEPS_AFTER_BURN_BOOTLOADER_OK == curPercent)
+ {
+ lcd_printf("Burn complete\n");
+ }
+ lcd_printf("PLS LONG-PRESS the power key to shut down\n");
+
+ return 0;
+}
+
+int optimus_progress_ui_printf(const char* fmt, ...)
+{
+ va_list args;
+ char buf[CONFIG_SYS_PBSIZE];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+
+ lcd_printf(buf);
+ return 0;
+}
+
+#define PROGRESS_BAR_TEST 0
+#if PROGRESS_BAR_TEST
+static int do_progress_bar_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ //bmp display $upgrade_bar_offset x,y,width
+ static __hdle hProgressBar = NULL;
+ int percents = 0;
+
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+
+ if (!strcmp("rel", argv[1])) {
+ optimus_progress_ui_release(hProgressBar);
+ hProgressBar = NULL;
+ return 0;
+ }
+
+ if (!hProgressBar)
+ {
+ unsigned barAddr = simple_strtoul(getenv("upgrade_bar_offset"), NULL, 0);
+ unsigned display_width = simple_strtoul(getenv("display_width"), NULL, 0);
+ unsigned display_height = simple_strtoul(getenv("display_height"), NULL, 0);
+ bmp_header_t* upgrading = (bmp_header_t*)simple_strtoul(getenv("upgrade_upgrading_offset"), NULL, 0);
+ const unsigned loadingHeight = upgrading->height;
+ const unsigned barYCor =
+ (3* display_height + loadingHeight)/4;//display_height - (display_height/2 - loadingHeight/2)/2;
+ unsigned unfocusBmpAddr = simple_strtoul(getenv("upgrade_unfocus_offset"), NULL, 0);
+
+ if (!barAddr) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_bar_offset", getenv("upgrade_bar_offset")); return __LINE__;
+ }
+ if (!display_width) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "display_width", getenv("display_width")); return __LINE__;
+ }
+ if (!display_height) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "display_height", getenv("display_height")); return __LINE__;
+ }
+ if (!upgrading) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_upgrading_offset", getenv("upgrade_upgrading_offset")); return __LINE__;
+ }
+ if (!unfocusBmpAddr) {
+ DWN_ERR("Fail to getenv[%s=%s]\n",
+ "upgrade_unfocus_offset", getenv("upgrade_unfocus_offset")); return __LINE__;
+ }
+
+ hProgressBar = optimus_progress_ui_request(100, 0, barAddr, display_width, barYCor);
+ if (!hProgressBar) {
+ DWN_ERR("Fail to request progress bar\n");
+ return __LINE__;
+ }
+
+ if (optimus_progress_ui_set_unfocus_bkg(hProgressBar, unfocusBmpAddr)) {
+ DWN_ERR("Fail to set bkg\n");
+ return __LINE__;
+ }
+ lcd_printf("-----25%%");
+ }
+
+ if (!strcmp("dir", argv[1]))
+ {
+ percents = simple_strtoul(argv[2], NULL, 10);
+ optimus_progress_ui_direct_update_progress(hProgressBar, percents);
+ }
+ else if(!strcmp("nb", argv[1]))
+ {
+ static u64 dataBytes = 0;
+ unsigned nBytes = simple_strtoul(argv[2], NULL, 10);
+
+ if (!dataBytes) {
+ dataBytes = 2u*1024*1024*1024;
+ if (optimus_progress_ui_set_smart_mode(hProgressBar, dataBytes, 90)) {
+ DWN_ERR("Fail to set smart mode\n");
+ return __LINE__;
+ }
+ }
+ optimus_progress_ui_update_by_bytes(hProgressBar, nBytes);
+ }
+
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ bar, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_progress_bar_test, //command function
+ "Test dynamic upgrade progress bar", //description
+ "argv: [percents]\n"//usage
+ " -10 means 10%\n"
+);
+#endif//#if PROGRESS_BAR_TEST
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.h b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.h
new file mode 100644
index 0000000000..3c5b176dd0
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_progress_ui.h
@@ -0,0 +1,82 @@
+/*
+ * \file optimus_progress_ui.h
+ * \brief interfaces of optimus_progress_ui.c
+ *
+ * \version 1.0.0
+ * \date 2013/10/13
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+#ifndef __OPTIMUS_PROGRESS_UI__
+#define __OPTIMUS_PROGRESS_UI__
+
+//after erase_bootloader, before store_init
+#define UPGRADE_STEPS_AFTER_IMAGE_OPEN_OK 2//disk_initialed failed if hang up here
+#define UPGRADE_STEPS_AFTER_DISK_INIT_OK 5//burn data parts failed if hang up in [6, 95]
+#define UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK 95
+#define UPGRADE_STEPS_AFTER_BURN_BOOTLOADER_OK 98
+
+#define UPGRADE_STEPS_FOR_BURN_DATA_PARTS_IN_PKG(allInPkg) \
+ ((allInPkg) ? (UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK - UPGRADE_STEPS_AFTER_DISK_INIT_OK - 1) : (UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK - UPGRADE_STEPS_AFTER_DISK_INIT_OK - 10))
+
+#if CONFIG_SD_BURNING_SUPPORT_UI
+int show_logo_to_report_burning(void);//show bmp 'upgrade_upgrading'
+
+int show_logo_to_report_burn_failed(void); //Display logo to report burning result is failed
+
+int show_logo_to_report_burn_success(void);
+
+__hdle optimus_progress_ui_request(const int totalPercents_f, int startPercent,
+ unsigned bmpBarAddr, int display_width, int progressBarY_f );
+__hdle optimus_progress_ui_request_for_sdc_burn(void);
+
+int optimus_progress_ui_release(__hdle hUiPrgress);
+
+int optimus_progress_ui_set_unfocus_bkg(__hdle hUiProgress, unsigned unfocusBmpAddr);
+
+int optimus_progress_ui_direct_update_progress(__hdle hUiProgress, const int percents);
+
+int optimus_progress_ui_report_upgrade_stat(__hdle hUiProgress, const int isSuccess);
+
+//smart mode with bytes
+int optimus_progress_ui_set_smart_mode(__hdle hUiProgress, const u64 smartModeTotalBytes_f, const unsigned smartModePercents);
+int optimus_progress_ui_update_by_bytes(__hdle hUiPrgress, const unsigned nBytes);
+
+int optimus_progress_ui_printf(const char* fmt, ...);
+
+int video_res_prepare_for_upgrade(HIMAGE hImg);
+
+#else
+
+#define video_res_prepare_for_upgrade(hImg) 0
+
+#define show_logo_to_report_burning()
+
+#define show_logo_to_report_burn_failed() 0
+
+#define show_logo_to_report_burn_success() 0
+
+#define optimus_progress_ui_request(totalPercents_f,startPercent, bmpBarAddr,display_width,progressBarY_f ) 1
+
+#define optimus_progress_ui_request_for_sdc_burn() (void*)1
+
+#define optimus_progress_ui_release(hUiPrgress) do{}while(0)
+
+#define optimus_progress_ui_set_unfocus_bkg(hUiProgress, unfocusBmpAddr) 0
+
+#define optimus_progress_ui_direct_update_progress(a ...) do{}while(0)
+
+//smart mode with bytes
+#define optimus_progress_ui_set_smart_mode(a ...) 0
+#define optimus_progress_ui_update_by_bytes(hUiPrgress, nBytes) do{}while(0)
+
+#define optimus_progress_ui_report_upgrade_stat(a ...) do{}while(0)
+
+#define optimus_progress_ui_printf(a ...) do{}while(0)
+
+#endif//#if CONFIG_SD_BURNING_SUPPORT_UI
+
+#endif//ifndef __OPTIMUS_PROGRESS_UI__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/optimus_simg2img.c b/drivers/usb/gadget/v2_burning/v2_common/optimus_simg2img.c
new file mode 100644
index 0000000000..7f9e8636e3
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/optimus_simg2img.c
@@ -0,0 +1,436 @@
+/*
+ * \file optimus_simg2img.c
+ * \brief sparse image to ext4 image in optimus system
+ * a sparse image consit of "file_header + chunk_num * (chunk_header + [chunk_data]),
+ * chunk data can be empty when chunk type is CHUNK_TYPE_DONT_CARE"
+ *
+ * \version 1.0.0
+ * \date 2013/5/6
+ * \author Sam.Wu <yihui.wu@Amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+#include <partition_table.h>
+
+#define sperr DWN_ERR
+#define spmsg(fmt ...) //printf("spmsg:"fmt)
+#define spdbg(fmt ...) //printf("SP:"), printf(__VA_ARGS__)
+
+#define SPARSE_HEADER_MAJOR_VER 1
+#define CHUNK_HEAD_SIZE sizeof(chunk_header_t)
+#define FILE_HEAD_SIZE sizeof(sparse_header_t)
+
+//states for a sparse packet, initialized when sparse packet probed
+static struct
+{
+ unsigned leftChunkNum;//chunks that not parsed yet
+ unsigned chunksBufLen;//>=OPTIMUS_DOWNLOAD_SPARSE_TRANSFER_SZ
+
+ unsigned sparseBlkSz;//block size of sparse format packet
+ unsigned parsedPacketCrc;//crc value for packet that already parsed
+
+ int pktHeadLen;
+ u32 reservetoAlign64;
+
+ //If long chunk data sz > write back size(e.g. 64M), write it at next write back time, This can't reduce copy and use less buffer
+ u32 notWrBackSz4LongChunk;
+ u32 nextFlashAddr4LastLongChunk; //flash start Addr not write back chunk data , in sector
+
+ //back up infomation for verify
+ u32 chunkInfoBackAddr;//file header and chunk info back address
+ u32 backChunkNum; //chunk number backed
+ u64 chunkOffset;
+
+}_spPacketStates;
+
+//0 is not sparse packet header, else is sparse packet_header
+int optimus_simg_probe(const u8* source, const u32 length)
+{
+ sparse_header_t *header = (sparse_header_t*) source;
+
+ if (length < sizeof(sparse_header_t)) {
+ sperr("length %d < sparse_header_t len %d\n", length, (int)FILE_HEAD_SIZE);
+ return 0;
+ }
+ if (header->magic != SPARSE_HEADER_MAGIC) {
+ sperr("sparse bad magic, expect 0x%x but 0x%x\n", SPARSE_HEADER_MAGIC, header->magic);
+ return 0;
+ }
+
+ if(!(SPARSE_HEADER_MAJOR_VER == header->major_version
+ && FILE_HEAD_SIZE == header->file_hdr_sz
+ && CHUNK_HEAD_SIZE == header->chunk_hdr_sz))
+ {
+ sperr("want 0x [%x, %x, %x], but [%x, %x, %x]\n",
+ SPARSE_HEADER_MAJOR_VER, (unsigned)FILE_HEAD_SIZE, (unsigned)CHUNK_HEAD_SIZE,
+ header->major_version, header->file_hdr_sz, header->chunk_hdr_sz);
+ return 0;
+ }
+
+
+ return 1;
+}
+
+int optimus_simg_parser_init(const u8* source)
+{
+ sparse_header_t *header = (sparse_header_t*) source;
+
+ memset(&_spPacketStates, 0, sizeof(_spPacketStates));
+ _spPacketStates.leftChunkNum = header->total_chunks;
+ _spPacketStates.parsedPacketCrc = 0;
+ _spPacketStates.pktHeadLen = header->file_hdr_sz;
+ _spPacketStates.sparseBlkSz = header->blk_sz;//often 4k
+ spmsg("totalChunkNum %d, fileHeadSz 0x%x, chunkHeadSz 0x%x\n", _spPacketStates.leftChunkNum, _spPacketStates.pktHeadLen, CHUNK_HEAD_SIZE);
+
+ //for verify
+ _spPacketStates.chunkInfoBackAddr = OPTIMUS_DOWNLOAD_SPARSE_INFO_FOR_VERIFY;
+ _spPacketStates.backChunkNum = 0;
+ memcpy((void*)(u64)_spPacketStates.chunkInfoBackAddr, header, sizeof(sparse_header_t));
+ spmsg("back header addr 0x%x\n", _spPacketStates.chunkInfoBackAddr);
+
+ return OPT_DOWN_OK;
+}
+
+//return value: flash address offset in sector in this time dispose
+//call this method to parse sparse format data and write it to media
+//@flashAddrInSec: flash write address of first chunk
+//@simgPktHead : buffered sparse image
+//@pktLen : buffered sparse data len
+//@unParsedDataLen: data length need write at next write back time
+// Take care the size to align 64K for flash and and addres to align sector!!!!
+int optimus_simg_to_media(char* simgPktHead, const u32 pktLen, u32* unParsedDataLen, const u32 flashAddrInSec)
+{
+ const unsigned notWrBackSz4LongChunk = _spPacketStates.notWrBackSz4LongChunk;
+ unsigned unParsedBufLen = pktLen - _spPacketStates.pktHeadLen;
+ u32 flashAddrStart = flashAddrInSec;
+ chunk_header_t* pChunk = (chunk_header_t*)(simgPktHead + _spPacketStates.pktHeadLen);
+ chunk_header_t* backChunkHead = (chunk_header_t*)(_spPacketStates.chunkInfoBackAddr + FILE_HEAD_SIZE) + _spPacketStates.backChunkNum;
+
+ if (notWrBackSz4LongChunk && !_spPacketStates.pktHeadLen/*0 if head*/)
+ {
+ //const chunk_header_t* pLastLongChunk = backChunkHead - 1;////
+ //const unsigned leftLongChunk_dataLen = pLastLongChunk->total_sz;
+ const unsigned leftLongChunk_flashAddr = _spPacketStates.nextFlashAddr4LastLongChunk;
+ unsigned writeLen = 0;
+ unsigned thisWriteLen = 0;
+
+ thisWriteLen = notWrBackSz4LongChunk >= pktLen ? pktLen : notWrBackSz4LongChunk;
+ if (notWrBackSz4LongChunk > thisWriteLen) {
+ //Align write size to 64K for flash write until last flash write
+ //At least make sure align to sector as flashAddress in sector here!!!
+ thisWriteLen >>= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS; thisWriteLen <<= OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+ spmsg("pktLen(0x%08x) < long chunk leftLen 0x%x08\n", pktLen, notWrBackSz4LongChunk);
+ }
+ spmsg("notWrBackSz4LongChunk 0x%08x, thisWriteLen 0x%08x, flashAddr 0x%08xSec\n", notWrBackSz4LongChunk, thisWriteLen, leftLongChunk_flashAddr);
+
+ writeLen = optimus_cb_simg_write_media(leftLongChunk_flashAddr, thisWriteLen, simgPktHead);
+ if (thisWriteLen != writeLen) {
+ sperr("Want to write left chunk sz 0x%x, but only 0x%x\n", thisWriteLen, writeLen);
+ return -__LINE__;
+ }
+
+ unParsedBufLen -= thisWriteLen;
+ _spPacketStates.notWrBackSz4LongChunk -= thisWriteLen;
+
+ if (notWrBackSz4LongChunk >= pktLen) //packet data ended
+ {
+ _spPacketStates.nextFlashAddr4LastLongChunk += thisWriteLen>>9;//address needed next write time
+ *unParsedDataLen = unParsedBufLen;
+ return 0;//the long chunk not disposed all yet!
+ }
+
+ pChunk = (chunk_header_t*)(simgPktHead + notWrBackSz4LongChunk + _spPacketStates.pktHeadLen);
+ }
+
+
+ spdbg("headLen=0x%x, leftNum=%d, backNum %d\n", _spPacketStates.pktHeadLen, _spPacketStates.leftChunkNum, _spPacketStates.backChunkNum);
+ for (;_spPacketStates.leftChunkNum && !_spPacketStates.notWrBackSz4LongChunk; _spPacketStates.leftChunkNum--)
+ {
+ //chunk data for ext4, but maybe empty in sparse, that is why called sparse format
+ const unsigned chunkDataLen = pChunk->chunk_sz * _spPacketStates.sparseBlkSz;
+ unsigned thisWriteLen = 0;
+
+ if (CHUNK_HEAD_SIZE > unParsedBufLen) {//total size not enough for CHUNK_HEAD_SIZE yet!!
+ spmsg("unParsedBufLen 0x%x < head sz 0x%x\n", unParsedBufLen, CHUNK_HEAD_SIZE);
+ break;
+ }
+
+ switch (pChunk->chunk_type)
+ {
+ case CHUNK_TYPE_RAW:
+ {
+ unsigned wantWrLen = chunkDataLen;
+
+ if (CHUNK_HEAD_SIZE + chunkDataLen != pChunk->total_sz) {
+ sperr("sparse: bad chunk size: head 0x%x + data 0x%x != total 0x%x\n",
+ (unsigned)CHUNK_HEAD_SIZE, chunkDataLen, pChunk->total_sz);
+ return -__LINE__;
+ }
+
+ if (pChunk->total_sz > unParsedBufLen)//left data not enough for this chunk (chunk header + chunk data)
+ {
+ const unsigned unParseChunkDataLen = unParsedBufLen - CHUNK_HEAD_SIZE;
+
+ wantWrLen = (unParseChunkDataLen >> OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS) << OPTIMUS_DOWNLOAD_SLOT_SZ_SHIFT_BITS;
+ _spPacketStates.notWrBackSz4LongChunk = chunkDataLen - wantWrLen;
+ _spPacketStates.nextFlashAddr4LastLongChunk = flashAddrStart + (wantWrLen>>9);
+ spmsg("Not enough one chunk: unParseChunkDataLen 0x%x ,chunk data len 0x%x, wantWrLen 0x%x, left 0x%08x\n",
+ unParseChunkDataLen, chunkDataLen, wantWrLen, _spPacketStates.notWrBackSz4LongChunk);
+ }
+
+ if (wantWrLen)
+ {
+ thisWriteLen = optimus_cb_simg_write_media(flashAddrStart, wantWrLen, (char*)pChunk + CHUNK_HEAD_SIZE);
+ if (thisWriteLen != wantWrLen) {
+ sperr("Fail to write to flash, want to write %dB, but %dB\n", wantWrLen, thisWriteLen);
+ return -__LINE__;
+ }
+ }
+ }
+ break;
+
+ case CHUNK_TYPE_DONT_CARE:
+ {
+ DWN_DBG("don't care chunk\n");
+ if (CHUNK_HEAD_SIZE != pChunk->total_sz) {
+ sperr("bogus DONT CARE chunk\n");
+ return -__LINE__;
+ }
+
+ }
+ break;
+
+ case CHUNK_TYPE_FILL:
+ {
+ const unsigned fillVal = *(unsigned*)(pChunk + 1);
+ unsigned LeftDataLen = chunkDataLen;
+ unsigned temp_flashAddrStart = flashAddrStart;
+ unsigned* pFillValBuf = (unsigned*)OPTIMUS_SPARSE_IMG_FILL_VAL_BUF;
+ const unsigned FillBufSz = OPTIMUS_SPARSE_IMG_FILL_BUF_SZ;
+ static unsigned _filledBufValidLen = 0;
+ const unsigned thisChunkFilledLen = min(chunkDataLen, FillBufSz);
+ int _NeedFillAsNotErasedYet = 0;
+
+ spdbg("CHUNK_TYPE_FILL,fillVal=0x%8x, chunkDataLen=0x%8x, thisChunkFilledLen=0x%x\n",
+ fillVal, chunkDataLen, thisChunkFilledLen);
+ if (CHUNK_HEAD_SIZE + 4 != pChunk->total_sz) {
+ sperr("error FILL chunk\n");
+ return -__LINE__;
+ }
+ switch (device_boot_flag) {
+ case EMMC_BOOT_FLAG:
+ case SPI_EMMC_FLAG:
+ _NeedFillAsNotErasedYet = (fillVal != 0);
+ break;
+
+ case NAND_BOOT_FLAG:
+ case SPI_NAND_FLAG:
+ _NeedFillAsNotErasedYet = (fillVal != 0XFFFFFFFFU);
+ break;
+ default:
+ _NeedFillAsNotErasedYet = 1;
+ break;
+ }
+ //for, emmc, if fillVal is 0, then _NeedFillAsNotErasedYet = false if "disk_inital > 0"
+ if (!_NeedFillAsNotErasedYet)_NeedFillAsNotErasedYet = (is_optimus_storage_inited()>>16) == 0;// == 0 means 'disk_inital 0'
+
+ if (_NeedFillAsNotErasedYet)
+ {
+ if (!_filledBufValidLen) {
+ DWN_MSG("CHUNK_TYPE_FILL\n");
+ }
+ if (fillVal != *pFillValBuf && _filledBufValidLen) {
+ _filledBufValidLen = 0;
+ }
+ if (_filledBufValidLen < thisChunkFilledLen) {
+ int i = _filledBufValidLen>>2;
+ unsigned* temBuf = pFillValBuf + i;
+
+ while (i++ < (thisChunkFilledLen>>2)) *temBuf++ = fillVal;
+ _filledBufValidLen = thisChunkFilledLen;
+ }
+
+ do {
+ unsigned actualWrLen = 0;
+
+ thisWriteLen = min(LeftDataLen, thisChunkFilledLen);
+
+ actualWrLen = optimus_cb_simg_write_media(temp_flashAddrStart, thisWriteLen, (char*)pFillValBuf);
+ if (actualWrLen != thisWriteLen) {
+ sperr("FILL_CHUNK:Want write 0x%x Bytes, but 0x%x\n", thisWriteLen, actualWrLen);
+ break;
+ }
+
+ temp_flashAddrStart += thisWriteLen >> 9;
+ LeftDataLen -= thisWriteLen;
+ }while(LeftDataLen);
+ }
+ thisWriteLen = 4;///////////
+ }
+ break;
+ case CHUNK_TYPE_CRC32:
+ sperr("CHUNK_TYPE_CRC32 unsupported yet!\n");
+ return -__LINE__;
+ default:
+ sperr("unknown chunk ID 0x%x at %p\n", pChunk->chunk_type, pChunk);
+ return -__LINE__;
+ }
+
+ /////update for next chunk
+ unParsedBufLen -= CHUNK_HEAD_SIZE + thisWriteLen;
+ flashAddrStart += chunkDataLen>>9;
+ memcpy(backChunkHead, pChunk, CHUNK_HEAD_SIZE);//back up verify chunk info
+ spdbg("index %d ,tp 0x%x\n", _spPacketStates.backChunkNum, backChunkHead->chunk_type);
+ ++_spPacketStates.backChunkNum;
+ ++backChunkHead;
+
+ pChunk = (chunk_header_t*)((u64)pChunk + pChunk->total_sz);
+ }
+
+ spmsg("leftChunkNum %d, bak num %d\n", _spPacketStates.leftChunkNum, _spPacketStates.backChunkNum);
+
+ _spPacketStates.pktHeadLen = 0;//>0 only when first time
+
+ *unParsedDataLen = unParsedBufLen;
+ return (flashAddrStart - flashAddrInSec);
+}
+
+int optimus_sparse_back_info_probe(void)
+{
+ int ret = 0;
+
+ if (_spPacketStates.leftChunkNum)
+ {
+ DWN_ERR("%d chunk left, image not burn completed!!\n", _spPacketStates.leftChunkNum);
+ return OPT_DOWN_FALSE;
+ }
+
+ ret = optimus_simg_probe((u8*)(u64)_spPacketStates.chunkInfoBackAddr, FILE_HEAD_SIZE);
+ DWN_DBG("back h addr 0x%x\n", _spPacketStates.chunkInfoBackAddr);
+
+ return ret;
+}
+
+//get next chunk data to read from ext4 partition
+int optimus_sparse_get_chunk_data(u8** head, u32* headSz, u32* dataSz, u64* dataOffset)
+{
+ chunk_header_t* pChunk = (chunk_header_t*)(_spPacketStates.chunkInfoBackAddr + FILE_HEAD_SIZE) + _spPacketStates.leftChunkNum;//chunk header
+
+ *headSz = *dataOffset = *dataSz = 0;
+ DWN_DBG("leftNum %d\n", _spPacketStates.backChunkNum);
+
+ if (!_spPacketStates.leftChunkNum) //file header
+ {
+ *headSz = FILE_HEAD_SIZE;
+ *head = (u8*)(u64)_spPacketStates.chunkInfoBackAddr;
+ }
+ else
+ {
+ *head = (u8*)pChunk;
+ }
+
+ //parse until RAW chunk or no chunk left
+ for (;_spPacketStates.leftChunkNum < _spPacketStates.backChunkNum;)
+ {
+ const unsigned chunkDataLen = pChunk->chunk_sz * _spPacketStates.sparseBlkSz;
+
+ switch (pChunk->chunk_type)
+ {
+ case CHUNK_TYPE_RAW:
+ {
+ if (CHUNK_HEAD_SIZE + chunkDataLen != pChunk->total_sz) {
+ sperr("sparse: bad chunk size!\n");
+ return OPT_DOWN_FAIL;
+ }
+
+ *dataSz = chunkDataLen;
+ }
+ break;
+
+ case CHUNK_TYPE_DONT_CARE:
+ {
+ spdbg("don't care chunk\n");
+ if (CHUNK_HEAD_SIZE != pChunk->total_sz) {
+ sperr("bogus DONT CARE chunk\n");
+ return OPT_DOWN_FAIL;
+ }
+ }
+ break;
+
+ case CHUNK_TYPE_FILL:
+ {
+ spdbg("CHUNK_TYPE_FILL\n");
+ if (CHUNK_HEAD_SIZE + 4 != pChunk->total_sz) {
+ sperr("bogus DONT CARE chunk\n");
+ return OPT_DOWN_FAIL;
+ }
+ *dataSz = 4;///////
+ }
+ break;
+
+
+ default:
+ sperr("unknown chunk ID 0x%x, parsed %d, total %d\n", pChunk->chunk_type, _spPacketStates.leftChunkNum, _spPacketStates.backChunkNum);
+ return OPT_DOWN_FAIL;
+ }
+
+ //update backed chunk info
+ *dataOffset = _spPacketStates.chunkOffset;//attention that offset < totalDataLen
+
+ _spPacketStates.chunkOffset += chunkDataLen;;
+ *headSz += CHUNK_HEAD_SIZE;
+ ++pChunk;
+ ++_spPacketStates.leftChunkNum;
+
+ if (*dataSz) break;
+ }
+
+ spdbg("left %d, total %d\n", _spPacketStates.leftChunkNum, _spPacketStates.backChunkNum);
+ return OPT_DOWN_OK;
+}
+
+
+#if 0
+int do_timestamp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+/*const char* optimus_time_stamp(void)*/
+{
+ const char* _formatStr = "[%5d.%03d]";
+ static char TimeStr[32] ;
+ int timeMSec = 0;
+ ulong curTimeInUSec = 0;
+static ulong timeInUSec = 0;
+
+ if (!timeInUSec)
+ {
+ timeInUSec = get_timer(timeInUSec);
+ return 0;
+ }
+ timeInUSec = curTimeInUSec = get_timer(timeInUSec);//timer unit is in uS
+
+ /*printf("time %x, %x\n", (u32)(timeInUSec>>32), (u32)timeInUSec);*/
+ /*if(!timeInUSec) return "";//As eFG_printf and uart_printf use while(*str) to determin whether to print, here make use it to not to print*/
+
+ /*curTimeInUSec /= 1000;//time to mSec*/
+ timeMSec = curTimeInUSec % 1000;
+ curTimeInUSec /= 1000;//time to Second
+
+ sprintf(TimeStr, _formatStr, (u32)curTimeInUSec, timeMSec);
+ printf(TimeStr);
+ printf("\n");
+
+ /*return TimeStr;*/
+ return 0;
+}
+
+U_BOOT_CMD(
+ timestamp, //command name
+ 5, //maxargs
+ 1, //repeatable
+ do_timestamp, //command function
+ "Burning a partition from sdmmc ", //description
+ "Usage: sdc_update partiton image_file_path fileFmt(sparse or normal)\n" //usage
+);
+#endif//#if 0
+
diff --git a/drivers/usb/gadget/v2_burning/v2_common/sparse_format.h b/drivers/usb/gadget/v2_burning/v2_common/sparse_format.h
new file mode 100644
index 0000000000..6c62c34c75
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_common/sparse_format.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+typedef struct sparse_header {
+ __le32 magic; /* 0xed26ff3a */
+ __le16 major_version; /* (0x1) - reject images with higher major versions */
+ __le16 minor_version; /* (0x0) - allow images with higer minor versions */
+ __le16 file_hdr_sz; /* 28 bytes for first revision of the file format */
+ __le16 chunk_hdr_sz; /* 12 bytes for first revision of the file format */
+ __le32 blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
+ __le32 total_blks; /* total blocks in the non-sparse output image */
+ __le32 total_chunks; /* total chunks in the sparse input image */
+ __le32 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;
+
+#define SPARSE_HEADER_MAGIC 0xed26ff3a
+
+#define CHUNK_TYPE_RAW 0xCAC1
+#define CHUNK_TYPE_FILL 0xCAC2
+#define CHUNK_TYPE_DONT_CARE 0xCAC3
+#define CHUNK_TYPE_CRC32 0xCAC4
+
+typedef struct chunk_header {
+ __le16 chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
+ __le16 reserved1;
+ __le32 chunk_sz; /* in blocks in output image */
+ __le32 total_sz; /* in bytes of chunk input file including chunk header and data */
+} chunk_header_t;
+
+/* Following a Raw or Fill or CRC32 chunk is data.
+ * For a Raw chunk, it's the data in chunk_sz * blk_sz.
+ * For a Fill chunk, it's 4 bytes of the fill data.
+ * For a CRC32 chunk, it's 4 bytes of CRC32
+ */
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini__aml_sdc_burn.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini__aml_sdc_burn.c
new file mode 100644
index 0000000000..267138b501
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini__aml_sdc_burn.c
@@ -0,0 +1,444 @@
+/*
+ * \file optimus_ini__aml_sdc_burn.c
+ * \brief parse the aml_sdc_burn.ini
+ *
+ * \version 1.0.0
+ * \date 2015/2/3
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2015 Amlogic. All Rights Reserved.
+ *
+ */
+#include "optimus_sdc_burn_i.h"
+
+#define dbg(fmt ...) //printf(fmt)
+#define msg DWN_MSG
+#define err DWN_ERR
+
+#define SET_BURN_PARTS "burn_parts"
+#define SET_CUSTOM_PARA "common"
+#define SET_BURN_PARA_EX "burn_ex"
+
+static const char* _iniSets[] = {
+ SET_BURN_PARTS ,
+ SET_CUSTOM_PARA ,
+ SET_BURN_PARA_EX ,
+};
+
+#define TOTAL_SET_NUM ( sizeof(_iniSets)/sizeof(const char*) )
+
+ConfigPara_t g_sdcBurnPara = {
+ .setsBitMap.burnParts = 0,
+ .setsBitMap.custom = 0,
+ .setsBitMap.burnEx = 0,
+
+ .burnParts = {
+ .burn_num = 0,
+ .bitsMap4BurnParts = 0,
+ },
+
+ .custom = {
+ .eraseBootloader = 1,//default to erase bootloader!
+ .eraseFlash = 0,
+ .bitsMap.eraseBootloader = 0,
+ .bitsMap.eraseFlash = 0,
+ },
+
+ .burnEx = {
+ .bitsMap.pkgPath = 0,
+ .bitsMap.mediaPath = 0,
+ },
+};
+
+static int init_config_para(ConfigPara_t* pCfgPara)
+{
+ memset(pCfgPara, 0, sizeof(ConfigPara_t));
+
+ pCfgPara->setsBitMap.burnParts = 0;
+ pCfgPara->setsBitMap.custom = 0;
+ pCfgPara->setsBitMap.burnEx = 0;
+
+ pCfgPara->burnParts.burn_num = 0;
+ pCfgPara->burnParts.bitsMap4BurnParts = 0;
+
+ pCfgPara->custom.eraseBootloader = 1;//default to erase bootloader!
+ pCfgPara->custom.eraseFlash = 0;
+ pCfgPara->custom.bitsMap.eraseBootloader = 0;
+ pCfgPara->custom.bitsMap.eraseFlash = 0;
+
+ pCfgPara->burnEx.bitsMap.pkgPath = 0;
+ pCfgPara->burnEx.bitsMap.mediaPath = 0;
+
+ return 0;
+}
+
+int print_burn_parts_para(const BurnParts_t* pBurnParts)
+{
+ int partIndex = 0;
+
+ printf("[%s]\n", SET_BURN_PARTS);
+ printf("burn_num = %d\n", pBurnParts->burn_num);
+
+ for (; partIndex < pBurnParts->burn_num; ++partIndex)
+ {
+ printf("burn_part%d = %s\n", partIndex, pBurnParts->burnParts[partIndex]);
+ }
+ printf("\n");
+
+ return 0;
+}
+
+static int print_sdc_burn_para(const ConfigPara_t* pCfgPara)
+{
+ printf("\n=========sdc_burn_paras=====>>>\n");
+
+ {
+ const CustomPara_t* pCustom = &pCfgPara->custom;
+
+ printf("[%s]\n", SET_CUSTOM_PARA);
+ printf("erase_bootloader = %d\n", pCustom->eraseBootloader);
+ printf("erase_flash = %d\n", pCustom->eraseFlash);
+ printf("reboot = 0x%x\n", pCustom->rebootAfterBurn);
+ printf("key_overwrite = 0x%x\n", pCustom->keyOverwrite);
+ printf("\n");
+ }
+
+ {
+ const BurnEx_t* pBurnEx = &pCfgPara->burnEx;
+
+ printf("[%s]\n", SET_BURN_PARA_EX);
+ printf("package = %s\n", pBurnEx->pkgPath);
+ printf("media = %s\n", pBurnEx->mediaPath);
+ printf("\n");
+ }
+
+ print_burn_parts_para(&pCfgPara->burnParts);
+
+ printf("<<<<=====sdc_burn_paras======\n\n");
+
+ return 0;
+}
+
+static int parse_set_burnEx(const char* key, const char* strVal)
+{
+ BurnEx_t* pBurnEx = &g_sdcBurnPara.burnEx;
+
+ if (!strcmp("package", key))
+ {
+ if (pBurnEx->bitsMap.pkgPath) {
+ err("key package in burn_ex is duplicated!\n");
+ return __LINE__;
+ }
+ if (!strVal) {
+ err("value for package in set burn_ex can't be empty!\n");
+ return __LINE__;
+ }
+
+ strcpy(pBurnEx->pkgPath, strVal);
+ pBurnEx->bitsMap.pkgPath = 1;
+
+ return 0;
+ }
+
+ if (!strcmp("media", key))
+ {
+ if (pBurnEx->bitsMap.mediaPath) {
+ err("key media in burn_ex is duplicated!\n");
+ return __LINE__;
+ }
+ if (strVal)
+ {
+ strcpy(pBurnEx->mediaPath, strVal);
+ pBurnEx->bitsMap.mediaPath = 1;
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static int parse_set_custom_para(const char* key, const char* strVal)
+{
+ CustomPara_t* pCustome = &g_sdcBurnPara.custom;
+ const unsigned cfgVal = strVal ? simple_strtoul(strVal, NULL, 0) : 0;
+
+ if (!strcmp(key, "erase_bootloader"))
+ {
+ if (pCustome->bitsMap.eraseBootloader) {
+ goto _key_dup;
+ }
+
+ if (strVal)
+ {
+ pCustome->eraseBootloader = cfgVal;
+ pCustome->bitsMap.eraseBootloader = 1;
+ }
+
+ }
+
+ if (!strcmp(key, "erase_flash"))
+ {
+ if (pCustome->bitsMap.eraseFlash) {
+ goto _key_dup;
+ }
+
+ if (strVal)
+ {
+ pCustome->eraseFlash = cfgVal;
+ pCustome->bitsMap.eraseFlash = 1;
+ }
+
+ }
+
+ if (!strcmp(key, "reboot"))
+ {
+ if (pCustome->bitsMap.rebootAfterBurn) {
+ goto _key_dup;
+ }
+
+ if (strVal)
+ {
+ pCustome->rebootAfterBurn = cfgVal;
+ pCustome->bitsMap.rebootAfterBurn = 1;
+ }
+
+ }
+
+ if (!strcmp(key, "key_overwrite"))
+ {
+ if (pCustome->bitsMap.keyOverwrite) {
+ goto _key_dup;
+ }
+
+ if (strVal)
+ {
+ pCustome->keyOverwrite = cfgVal;
+ pCustome->bitsMap.keyOverwrite = 1;
+ }
+
+ }
+
+ return 0;
+
+_key_dup:
+ err("key %s is duplicated!\n", key);
+ return -1;
+}
+
+#if 0
+int check_custom_para(const CustomPara_t* pCustome)
+{
+ //TODO: not completed!!
+ return 0;
+}
+#endif
+
+static int parse_burn_parts(const char* key, const char* strVal)
+{
+ BurnParts_t* pBurnParts = &g_sdcBurnPara.burnParts;
+
+ if ( !strcmp("burn_num", key) )
+ {
+ if (!strVal) {
+ err("burn_num in burn_parts can't be empty!!");
+ return __LINE__;
+ }
+
+ pBurnParts->burn_num = simple_strtoul(strVal, NULL, 0);
+ if (pBurnParts->burn_num < 1) {
+ err("value for burn_num in burn_parts in invalid\n");
+ return __LINE__;
+ }
+
+ return 0;
+ }
+
+ if (pBurnParts->burn_num < 1) {
+ err("burn_num is not config or 0 ??\n");
+ return __LINE__;
+ }
+
+ {
+ const char burn_partx[] = "burn_partx";
+ const int validKeyLen = sizeof(burn_partx) - 2;
+ const int totalBurnNum = pBurnParts->burn_num;
+ int burnIndex = 0;
+ char* partName = NULL;
+
+ if (strncmp(burn_partx, key, validKeyLen))
+ {
+ err("error burn part name [%s]\n", key);
+ return __LINE__;
+ }
+
+ burnIndex = key[validKeyLen] - '0';
+ if (!(burnIndex >= 0 && burnIndex < totalBurnNum))
+ {
+ err("Error \"%s\", only burn_part[0~%d] is valid as burn_num is %d\n",
+ key, totalBurnNum - 1, totalBurnNum);
+ return __LINE__;
+ }
+
+ if (pBurnParts->bitsMap4BurnParts & (1U<<burnIndex)) {
+ err("key %s is duplicated in burn_parts\n", key);
+ return __LINE__;
+ }
+ pBurnParts->bitsMap4BurnParts |= 1U<<burnIndex;
+
+ partName = (char*)pBurnParts->burnParts[burnIndex];
+ if (!strVal) {
+ err("value of %s can't empty\n", key);
+ return __LINE__;
+ }
+
+ if (!strcmp("bootloader", strVal)) {
+ err("bootloader not need to configure at burn_parts\n");
+ return __LINE__;
+ }
+
+ strcpy(partName, strVal);
+ }
+
+ return 0;
+}
+
+int check_cfg_burn_parts(const ConfigPara_t* burnPara)
+{
+ const BurnParts_t* pBurnParts = &burnPara->burnParts;
+ const int cfgBurnNum = pBurnParts->burn_num;
+ const unsigned bitsMap = pBurnParts->bitsMap4BurnParts;
+ int mediaPathHasCfg = burnPara->burnEx.bitsMap.mediaPath;
+ int i = 0;
+
+
+ for (i = 0; i < cfgBurnNum; i++)
+ {
+ int b = bitsMap & (1U<<i);
+
+ if (!b) {
+ err("Please cfg burn_part%d\n", i);
+ return __LINE__;
+ }
+
+ if (mediaPathHasCfg)
+ {
+ if (!strcmp(pBurnParts->burnParts[i], "media")) {
+ DWN_ERR("media can't cfg in both media_path and burn_parts\n");
+ return __LINE__;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int optimus_aml_sdc_ini_check_set_valid(const char* setName)
+{
+ const char* pName = NULL;
+ int i = 0;
+ int isValid = 0;
+
+ for (; i < TOTAL_SET_NUM && !isValid; ++i)
+ {
+ pName = _iniSets[i];
+ isValid = !strcmp(setName, pName);
+ }
+
+
+ return isValid;
+}
+
+static int optimus_aml_sdc_burn_ini_parse_usr_cfg(const char* setName, const char* keyName, const char* usrKeyVal)
+{
+ int ret = 0;
+
+ if (!strcmp(SET_BURN_PARTS, setName))
+ {
+ return parse_burn_parts(keyName, usrKeyVal);
+ }
+ if (!strcmp(SET_CUSTOM_PARA, setName))
+ {
+ return parse_set_custom_para(keyName, usrKeyVal);
+ }
+ if (!strcmp(SET_BURN_PARA_EX, setName))
+ {
+ return parse_set_burnEx(keyName, usrKeyVal);
+ }
+
+ return ret;
+}
+
+int parse_ini_cfg_file(const char* filePath)
+{
+ const int MaxFileSz = OPTIMUS_DOWNLOAD_SLOT_SZ;
+ char* CfgFileLoadAddr = (char*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ int rcode = 0;
+ const int MaxLines = 1024;//
+ char* lines[MaxLines];
+ int validLineNum = 0;
+
+ init_config_para(&g_sdcBurnPara);
+
+ validLineNum = parse_ini_file_2_valid_lines(filePath, CfgFileLoadAddr, MaxFileSz, lines);
+ if (!validLineNum) {
+ err("error in parse ini file\n");
+ return __LINE__;
+ }
+
+ rcode = optimus_ini_trans_lines_2_usr_params((const char* *)lines, validLineNum,
+ optimus_aml_sdc_ini_check_set_valid,
+ optimus_aml_sdc_burn_ini_parse_usr_cfg);
+ if (rcode) {
+ err("Fail in get cfg from %s\n", filePath);
+ return __LINE__;
+ }
+
+ rcode = check_cfg_burn_parts(&g_sdcBurnPara);
+ if (rcode) {
+ err("Fail in check burn parts.\n");
+ return __LINE__;
+ }
+
+ print_sdc_burn_para(&g_sdcBurnPara);
+
+ return 0;
+}
+
+#define MYDBG 0
+#if MYDBG
+int do_ini_parser(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ const char* filePath = "dos_dc_burn.ini";
+
+ //mmc info to ensure sdcard inserted and inited, mmcinfo outer as there U-disk later
+ rcode = run_command("mmcinfo", 0);
+ if (rcode) {
+ err("Fail in init mmc, Does sdcard not plugged in?\n");
+ return __LINE__;
+ }
+
+ if (2 <= argc) {
+ filePath = argv[1];
+ }
+
+ rcode = parse_ini_cfg_file(filePath);
+ if (rcode) {
+ err("error in parse ini file\n");
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ ini_parser, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_ini_parser, //command function
+ "Burning a partition from sdmmc ", //description
+ "Usage: sdc_update partiton image_file_path fileFmt(android sparse, other normal) [,verify_file]\n" //usage
+);
+#endif//#if MYDBG
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini_parser.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini_parser.c
new file mode 100644
index 0000000000..c02b377107
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_ini_parser.c
@@ -0,0 +1,429 @@
+/*
+ * \file optimus_ini_parser.c
+ * \brief ini parsing utilities for sdc burnning
+ *
+ * \version 1.0.0
+ * \date 2013-7-11
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "optimus_sdc_burn_i.h"
+
+#define dbg(fmt ...) //printf(fmt)
+#define msg DWN_MSG
+#define err DWN_ERR
+
+#define MAX_ARGS 4
+#define is_space_char(c) ('\t' == c || ' ' == c)
+#define is_delimeter(c) ('[' == c || ']' == c || '=' == c)
+
+#define is_valid_char(c) ( ('0' <= c && '9' >= c) || ('_' == c)\
+ || ('a' <= c && 'z' >= c) || ('A' <= c && 'Z' >= c) ) \
+ || ('.' == c) || ('\\' == c) || ('/' == c) || ('-' == c) \
+ || (':' == c)
+
+static int line_is_valid(const char* line)
+{
+ char c = 0;
+
+ while (c = *line++, c)
+ {
+ int ret = is_delimeter(c) || is_valid_char(c) || is_space_char(c);
+
+ if (!ret) {
+ err("invalid chars! ascii val(0x%x)\n", c);
+ return 0;
+ }
+ }
+
+ return 1;//line is valid
+}
+
+//valid lines type: set or key/value pair
+enum _INI_LINE_TYPE{
+ INI_LINE_TYPE_ERR = 0,
+ INI_LINE_TYPE_SET ,
+ INI_LINE_TYPE_KE_VALUE ,
+};
+
+//this func is used after line_is_valid
+static int line_2_words(char* line, char* argv[], const int maxWords)
+{
+ int nargs = 0;
+ char cur = 0;
+
+ for (cur = *line; is_space_char(cur); cur = *++line) {}
+
+ argv[nargs++] = line;
+ for (;cur = *line, cur; ++line)
+ {
+ if (!is_space_char(cur)) continue;
+ //following do with space character
+
+ *line = 0;
+ for (cur = *++line; is_space_char(cur) && cur; cur = *++line) {}//ignore all space between words
+
+ if (!cur) break;//line ended
+
+ argv[nargs++] = line;
+ if (maxWords <= nargs) {
+ err("too many words num %d, max is %d\n", nargs, maxWords);
+ return 0;
+ }
+ }
+
+ return nargs;
+}
+
+//step1:first loop to seprate buffer to lines
+int _optimus_parse_buf_2_lines(char* pTextBuf, const unsigned textSz,
+ const char* lines[], unsigned* totalLineNum, const unsigned MaxLines)
+{
+ const char* curLine = pTextBuf;
+ char* pTemp = pTextBuf;
+ unsigned i = 0;
+ unsigned lineNum = 0;
+
+ pTextBuf[textSz] = '\0';
+ //loop to seprate buffer to lines
+ for (i = 0; i < textSz ; i++, ++pTemp)
+ {
+ char c = *pTemp;
+ int isFileEnd = i + 1 >= textSz;
+
+ if (MaxLines <= lineNum) {
+ DWN_ERR("total line number %d too many, at most %d lines!\n", lineNum, MaxLines);
+ break;
+ }
+
+ if ('\r' != c && '\n' != c) {
+ continue;
+ }
+ *pTemp = 0;///
+
+ if (isFileEnd)
+ {
+ lines[lineNum++] = curLine;
+ break;//End to read file if file ended
+ }
+
+ DWN_DBG("%3d: %s\n", lineNum, curLine);
+ if ('\r' == c) //for DOS \r\n mode
+ {
+ if ('\n' == pTemp[1])
+ {
+ lines[lineNum++] = curLine;
+
+ ++pTemp;
+ curLine = pTemp + 1;
+ ++i;//skip '\n' which follows '\r'
+ }
+ else
+ {
+ DWN_ERR("Syntax error at line %d, DOS end \\r\\n, but \\r%x\n", lineNum + 1, pTemp[1]);
+ return __LINE__;
+ }
+ }
+ else if('\n' == c)//for UNIX '\n' mode
+ {
+ lines[lineNum++] = curLine;
+ curLine = pTemp + 1;
+ }
+ }
+
+ *totalLineNum = lineNum;
+ return 0;
+}
+
+//abandon comments lines and space lines,
+//but not decrease thie line numbers
+int _optimus_abandon_ini_comment_lines(char* lines[], const unsigned lineNum)
+{
+ unsigned lineIndex = 0;
+ for (lineIndex = 0; lineIndex < lineNum ; lineIndex++)
+ {
+ int isSpaceLine = 1;
+ char c = 0;
+ char* thisLine = lines[lineIndex];
+
+ while (c = *thisLine++, c)
+ {
+ //escape space and tab
+ if (is_space_char(c))
+ {
+ continue;
+ }
+
+ isSpaceLine = 0;//no space line
+ //test if frist char is comment delimeter
+ if (';' == c)
+ {
+ lines[lineIndex] = NULL;//invalid comment lines
+ }
+ }
+
+ //if all character is space or tab, also invlalid it
+ if (isSpaceLine)
+ {
+ lines[lineIndex] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+//Return value is the valid line numbers
+//1, Read the whole file content to buffer
+//2, parse file content to lines
+//3, parse each valid line
+int parse_ini_file_2_valid_lines(const char* filePath, char* iniBuf, const unsigned bufSz, char* lines[])
+{
+ const int MaxLines = 1024;//
+ int ret = 0;
+ unsigned fileSz = bufSz;
+ unsigned lineNum = 0;
+ int hFile = -1;
+ unsigned readLen = 0;
+
+ fileSz = (unsigned)do_fat_get_fileSz(filePath);
+ if (!fileSz) {
+ err("File %s not exist in sdcard??\n", filePath);
+ return __LINE__;
+ }
+ if (fileSz >= bufSz) {
+ err("file size 0x%x illegal, > bufSz 0x%x\n", fileSz, bufSz);
+ return __LINE__;
+ }
+ DWN_MSG("ini sz 0x%xB\n", fileSz);
+
+ hFile = do_fat_fopen(filePath);
+ if (hFile < 0) {
+ err("Fail to open file %s\n", filePath);
+ return 0;
+ }
+
+ readLen = do_fat_fread(hFile, (u8*)iniBuf, fileSz);
+ if (readLen != fileSz) {
+ err("failed to load cfg file, want size 0x%x, but 0x%x\n", fileSz, readLen);
+ do_fat_fclose(hFile);
+ return 0;
+ }
+ iniBuf[fileSz] = 0;
+
+ do_fat_fclose(hFile);
+
+ dbg("\\r is 0x%x\t, \\n is 0x%x\n", '\r', '\n');
+
+ //step1:first loop to seprate buffer to lines
+ ret = _optimus_parse_buf_2_lines(iniBuf, fileSz, (const char**)lines, &lineNum, MaxLines);
+ if (ret) {
+ err("Fail to parse buf to lines.ret=%d\n", ret);
+ return 0;
+ }
+
+ //step 2: abandon comment or space lines
+ ret = _optimus_abandon_ini_comment_lines(lines, lineNum);
+
+ return lineNum;
+}
+
+int optimus_ini_trans_lines_2_usr_params(const char* const lines[], const unsigned lineNum,
+ int (*pCheckSetUseFul)(const char* setName),
+ int (*pParseCfgVal)(const char* setName, const char* keyName, const char* keyVal))
+{
+ const int MaxWordsALine = 32;
+ char* wordsALine[MaxWordsALine];
+ int ret = 0;
+ int nwords = 0;
+ unsigned i = 0;
+ unsigned lineIndex = 0;
+ const int MaxUsefulSets = 8;
+ const char* cacheSetNames[MaxUsefulSets];
+ const char* CurrentSetName = NULL;
+
+ while (i < MaxUsefulSets) cacheSetNames[i++] = NULL;
+
+ dbg("\nvalid lines:\n");
+ for (lineIndex = 0; lineIndex < lineNum ; lineIndex++)
+ {
+ int lineType = INI_LINE_TYPE_ERR;
+ const char* iniKey = NULL;
+ const char* iniVal = NULL;
+ const char* iniSet = NULL;
+
+ const char* const curLine = lines[lineIndex];
+
+ if (!curLine) continue;//comment or space lines
+
+ if (!line_is_valid(curLine)) //only comment lines can contain non-ASCII letters
+ {
+ err("line %d contain invalid chars\n", lineIndex + 1);
+ ret = __LINE__;
+ break;
+ }
+ dbg("%3d: %s\n",lineIndex, curLine);
+
+ nwords = line_2_words((char*)curLine, wordsALine, MaxWordsALine);
+ if (nwords <= 0) {
+ ret = __LINE__;
+ break;
+ }
+ if (nwords > 3) {
+ err("line %d error: ini support at most 3 words, but %d\n", lineIndex + 1, nwords);
+ ret = __LINE__;
+ break;
+ }
+
+ switch (nwords)
+ {
+ case 3:
+ {
+ if (!strcmp("=", wordsALine[1]))//k/v pair
+ {
+ lineType = INI_LINE_TYPE_KE_VALUE;
+ iniKey = wordsALine[0]; iniVal = wordsALine[2];
+ break;
+ }
+ else if(!strcmp("[" , wordsALine[0]) && !strcmp("]" , wordsALine[2]))//set line
+ {
+ lineType = INI_LINE_TYPE_SET;
+ iniSet = wordsALine[1];
+ break;
+ }
+ else
+ {
+ lineType = INI_LINE_TYPE_ERR;
+ err("Ini syntax error when parse line %d\n", lineIndex + 1);
+ ret = __LINE__; break;
+ }
+ }
+ break;
+
+ case 2:
+ {
+ if ('[' == wordsALine[0][0]) //set like "[set ]" or "[ set]"
+ {
+ if (!strcmp("]", wordsALine[1]))
+ {
+ lineType = INI_LINE_TYPE_SET;
+ iniSet = wordsALine[0] + 1;
+ break;
+ }
+ else if (']' == wordsALine[1][strlen(wordsALine[1]) - 1] && !strcmp("[", wordsALine[0]))
+ {
+ lineType = INI_LINE_TYPE_SET;
+ iniSet = wordsALine[1];
+ wordsALine[1][strlen(wordsALine[1]) - 1] = 0;
+ break;
+ }
+ }
+ else if(!strcmp("=", wordsALine[1]))//k/v pair like "key = "
+ {
+ lineType = INI_LINE_TYPE_KE_VALUE;
+ iniKey = wordsALine[0];
+ break;
+ }
+ else if('=' == wordsALine[1][0])//k/v pair like "key =v" or "key= v"
+ {
+ lineType = INI_LINE_TYPE_KE_VALUE;
+ iniKey = wordsALine[0];
+ iniVal = wordsALine[1] + 1;
+ break;
+ }
+ else if ('=' == wordsALine[0][strlen(wordsALine[0]) - 1])//k/v pair like "key= v"
+ {
+ wordsALine[0][strlen(wordsALine[0]) - 1] = 0;
+ lineType = INI_LINE_TYPE_KE_VALUE;
+ iniKey = wordsALine[0];
+ iniVal = wordsALine[1];
+ }
+ }
+ break;
+
+ case 1:
+ {
+ char* word = wordsALine[0];
+ char firstChar = word[0];
+ char lastChar = word[strlen(word) - 1];
+
+ if ('[' == firstChar && ']' == lastChar)
+ {
+ lineType = INI_LINE_TYPE_SET;
+ iniSet = word + 1;
+ word[strlen(word) - 1] = 0;
+ break;
+ }
+ else
+ {
+ char c = 0;
+
+ iniKey = word;
+ while (c = *word++, c)
+ {
+ if ('=' == c)//TODO: not assert only delimeter in a line yet
+ {
+ lineType = INI_LINE_TYPE_KE_VALUE;
+ *--word = 0;
+ iniVal = ++word;
+ iniVal = *iniVal ? iniVal : NULL;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (INI_LINE_TYPE_SET == lineType)
+ {
+ int setIndex = 0;
+
+ dbg("set line, set is %s\n", iniSet);
+ CurrentSetName = NULL;
+ ret = pCheckSetUseFul(iniSet);
+ if (!ret) {//the set don't care
+ continue;
+ }
+
+ //Check the useful set name is not duplicated!
+ for (setIndex = 0; setIndex < MaxUsefulSets; ++setIndex) {
+ const char* pset = cacheSetNames[setIndex];
+ if (!pset) {
+ CurrentSetName = cacheSetNames[setIndex] = iniSet;
+ break;
+ }
+ ret = strcmp(pset, iniSet);
+ if (!ret) {
+ ret = __LINE__;
+ goto _set_duplicated;
+ }
+ }
+ }
+ else if(INI_LINE_TYPE_KE_VALUE == lineType && CurrentSetName)
+ {
+ dbg("k/v line, key (%s), val (%s)\n", iniKey, iniVal);
+
+ ret = pParseCfgVal(CurrentSetName, iniKey, iniVal);
+ if (ret) {
+ goto _line_err;
+ }
+ }
+ }
+
+ return ret;
+
+_line_err:
+ err("Fail to parse line %d\n", lineIndex + 1);
+ return ret;
+
+_set_duplicated:
+ err("line %d err:set is duplicated!!\n", lineIndex + 1);
+ return ret;
+}
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.c
new file mode 100644
index 0000000000..8c8623598c
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.c
@@ -0,0 +1,155 @@
+/*
+ * \file optimus_led.c
+ * \brief use led to indicate burning states
+ *
+ * \version 1.0.0
+ * \date 2013/11/9
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+#include "../v2_burning_i.h"
+#include "optimus_led.h"
+
+#define OPTIMUS_LED_SRC_IS_PWM 1//pwm type led
+
+typedef enum{
+ OPTIMUS_LED_STATE_INVALID = 0XF0 ,
+ OPTIMUS_LED_STATE_RED ,//Burning failed if stay on this state
+ OPTIMUS_LED_STATE_GREEN ,
+ OPTIMUS_LED_STATE_SLOW_FLICKERING ,
+ OPTIMUS_LED_STATE_FAST_FLICKERING ,//fast flickering to catch the eye that it's burning successful
+
+}OptimusLedStates_e;
+
+#if OPTIMUS_LED_SRC_IS_PWM
+#define PWM_CHANNEL_INDEX 5
+
+static int optimus_pwm_led_show_state(OptimusLedStates_e ledState)
+{
+ int rc = 0;
+ int PwmHighLevelPeriod = 0;
+ int PwmLowLevelPeriod = 0;
+ char cmdStr[64];
+
+ switch (ledState)
+ {
+ case OPTIMUS_LED_STATE_SLOW_FLICKERING:
+ {
+ PwmHighLevelPeriod = 0xfffe;
+ PwmLowLevelPeriod = PwmHighLevelPeriod;
+
+ sprintf(cmdStr, "pwm config %d %d %d", PWM_CHANNEL_INDEX, PwmHighLevelPeriod, PwmLowLevelPeriod);
+ }
+ break;
+
+ case OPTIMUS_LED_STATE_FAST_FLICKERING:
+ {
+ PwmHighLevelPeriod = 0x2000;
+ PwmLowLevelPeriod = PwmHighLevelPeriod;
+
+ sprintf(cmdStr, "pwm config %d %d %d", PWM_CHANNEL_INDEX, PwmHighLevelPeriod, PwmLowLevelPeriod);
+ }
+ break;
+
+ case OPTIMUS_LED_STATE_GREEN:
+ {
+ PwmHighLevelPeriod = 0;
+ PwmLowLevelPeriod = 0xffffu;//always low level
+
+ sprintf(cmdStr, "pwm config %d %d %d", PWM_CHANNEL_INDEX, PwmHighLevelPeriod, PwmLowLevelPeriod);
+ }
+ break;
+
+ case OPTIMUS_LED_STATE_RED:
+ {
+ PwmHighLevelPeriod = 0xffffu;//always high level
+ PwmLowLevelPeriod = 0;
+
+ sprintf(cmdStr, "pwm config %d %d %d", PWM_CHANNEL_INDEX, PwmHighLevelPeriod, PwmLowLevelPeriod);
+ }
+ break;
+ default:
+ DWN_ERR("invlaid pwm state %d\n", ledState);
+ return __LINE__;
+ }
+
+ rc = run_command(cmdStr, 0);
+ if (rc) {
+ DWN_ERR("Fail in run_cmd[%s], ret=%d\n", cmdStr, rc);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+int optimus_led_open(int ledType)
+{
+ const int clkSel = 0;
+ const int clkDiv = 0x7f;
+ const int pinIndex = 0;
+ char cmdStr[64];
+ int rc = 0;
+
+ sprintf(cmdStr, "pwm enable %d %d %d %d", PWM_CHANNEL_INDEX, pinIndex, clkSel, clkDiv);
+ rc = run_command(cmdStr, 0);
+ if (rc) {
+ DWN_ERR("Fail in run_cmd[%s], ret=%d\n", cmdStr, rc);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+int optimus_led_close(void)
+{
+ int rc = 0;
+ char cmdStr[64];
+
+ sprintf(cmdStr, "pwm disable %d", PWM_CHANNEL_INDEX);
+ rc = run_command(cmdStr, 0);
+
+ return rc;
+}
+
+int optimus_led_show_in_process_of_burning(void)
+{
+ return optimus_pwm_led_show_state(OPTIMUS_LED_STATE_SLOW_FLICKERING);
+}
+
+int optimus_led_show_burning_success(void)
+{
+ optimus_pwm_led_show_state(OPTIMUS_LED_STATE_FAST_FLICKERING);
+
+ return 0;
+}
+
+int optimus_led_show_burning_failure(void)
+{
+ return optimus_pwm_led_show_state(OPTIMUS_LED_STATE_RED);
+}
+
+#else
+int optimus_led_open(int ledType)
+{
+ return 0;
+}
+
+int optimus_led_close(void)
+{
+ return 0;
+}
+
+int optimus_led_show_in_process_of_burning(void)
+{
+ return 0;
+}
+
+int optimus_led_show_burning_success(void)
+{
+ return 0;
+}
+#endif// #if OPTIMUS_LED_SRC_IS_PWM
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.h b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.h
new file mode 100644
index 0000000000..40ae2c38ff
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_led.h
@@ -0,0 +1,40 @@
+/*
+ * \file optimus_led.h
+ * \brief show burning states by LED
+ * current supported LED source is PWM, other type not supported yet!
+ *
+ * \version 1.0.0
+ * \date 2013/11/9
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic Inc.. All Rights Reserved.
+ *
+ */
+#ifndef __OPTIMUS_LED_H__
+#define __OPTIMUS_LED_H__
+
+#define LED_TYPE_PWM 0xabcd
+
+#if CONFIG_SD_BURNING_SUPPORT_LED
+
+int optimus_led_open(int ledType);//open the led for show burning states
+
+int optimus_led_close(void);
+
+int optimus_led_show_in_process_of_burning(void);
+
+int optimus_led_show_burning_success(void);
+
+int optimus_led_show_burning_failure(void);
+
+#else
+#define optimus_led_open(ledType) 0
+#define optimus_led_close() 0
+#define optimus_led_show_in_process_of_burning() do{}while(0)
+#define optimus_led_show_burning_success() do{}while(0)
+#define optimus_led_show_burning_failure() do{}while(0)
+
+#endif// #if CONFIG_SD_BURNING_SUPPORT_LED
+
+#endif//ifndef __OPTIMUS_LED_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn.c
new file mode 100644
index 0000000000..919fc3f803
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn.c
@@ -0,0 +1,764 @@
+/*
+ * \file optimus_sdc_burn.c
+ * \brief burning itself from Pheripheral tf/sdmmc card
+ *
+ * \version 1.0.0
+ * \date 2013-7-11
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "optimus_sdc_burn_i.h"
+#include "optimus_led.h"
+
+static int is_bootloader_old(void)
+{
+ int sdc_boot = is_tpl_loaded_from_ext_sdmmc();
+
+ return !sdc_boot;
+}
+
+int get_burn_parts_from_img(HIMAGE hImg, ConfigPara_t* pcfgPara)
+{
+ BurnParts_t* pburnPartsCfg = &pcfgPara->burnParts;
+ int i = 0;
+ int ret = 0;
+ int burnNum = 0;
+ const int totalItemNum = get_total_itemnr(hImg);
+
+ for (i = 0; i < totalItemNum; i++)
+ {
+ const char* main_type = NULL;
+ const char* sub_type = NULL;
+
+ ret = get_item_name(hImg, i, &main_type, &sub_type);
+ if (ret) {
+ DWN_ERR("Exception:fail to get item name!\n");
+ return __LINE__;
+ }
+
+ if (!strcmp("PARTITION", main_type))
+ {
+ char* partName = pburnPartsCfg->burnParts[burnNum];
+
+ if (!strcmp("bootloader", sub_type)) continue;
+ if (!strcmp(AML_SYS_RECOVERY_PART, sub_type))
+ {
+ if (OPTIMUS_WORK_MODE_SYS_RECOVERY == optimus_work_mode_get()) continue;
+ }
+
+ strcpy(partName, sub_type);
+ pburnPartsCfg->bitsMap4BurnParts |= 1U<<burnNum;
+ burnNum += 1;
+ }
+ }
+
+ if (burnNum)
+ {
+ pburnPartsCfg->burn_num = burnNum;
+
+ ret = check_cfg_burn_parts(pcfgPara);
+ if (ret) {
+ DWN_ERR("Fail in check burn parts\n");
+ return __LINE__;
+ }
+ print_burn_parts_para(pburnPartsCfg);
+ }
+
+ return OPT_DOWN_OK;
+}
+
+#define ITEM_NOT_EXIST 0x55
+
+int optimus_verify_partition(const char* partName, HIMAGE hImg, char* _errInfo)
+{
+#define MaxSz (64 - 7) //verify file to at most 64B to corresponding to USB burn, strlen("verify ") == 7
+
+ char* argv[4];
+ int ret = 0;
+ HIMAGEITEM hImgItem = NULL;
+ int imgItemSz = 0;
+ char CmdVerify[MaxSz + 7] = {0};
+
+ hImgItem = image_item_open(hImg, "VERIFY", partName);
+ if (!hImgItem) {
+ DWN_ERR("Fail to open verify file for part (%s)\n", partName);
+ return ITEM_NOT_EXIST;
+ }
+
+ imgItemSz = (int)image_item_get_size(hImgItem);
+ if (imgItemSz > MaxSz || !imgItemSz) {
+ DWN_ERR("verify file size %d for part %s invalid, max is %d\n", imgItemSz, partName, MaxSz);
+ ret = __LINE__; goto _finish;
+ }
+ DWN_DBG("item sz %u\n", imgItemSz);
+
+ ret = image_item_read(hImg, hImgItem, CmdVerify, imgItemSz);
+ if (ret) {
+ DWN_ERR("Fail to read verify item for part %s\n", partName);
+ goto _finish;
+ }
+ CmdVerify[imgItemSz] = 0;
+ DWN_DBG("verify[%s]\n", CmdVerify);
+
+ argv[0] = "verify";
+ ret = cli_simple_parse_line(CmdVerify, argv + 1);
+ if (ret != 2) {
+ DWN_ERR("verify cmd argc must be 2, but %d\n", ret);
+ return __LINE__;
+ }
+
+ ret = optimus_media_download_verify(3, argv, _errInfo);
+ if (ret) {
+ DWN_ERR("Fail when verify\n");
+ return __LINE__;
+ }
+
+_finish:
+ image_item_close(hImgItem);
+ return ret;
+}
+
+//.NeedVerify: Try to get verify file if .NeedVerify == 1
+static int optimus_burn_one_partition(const char* partName, HIMAGE hImg, __hdle hUiProgress, int NeedVerify)
+{
+ int rcode = 0;
+ s64 imgItemSz = 0;
+ s64 leftItemSz = 0;
+ u32 thisReadLen = 0;
+ __hdle hImgItem = NULL;
+ char* downTransBuf = NULL;//get buffer from optimus_buffer_manager
+ const unsigned ItemReadBufSz = OPTIMUS_DOWNLOAD_SLOT_SZ;//read this size from image item each time
+ unsigned sequenceNo = 0;
+ const char* fileFmt = NULL;
+ /*static */char _errInfo[512];
+ unsigned itemSizeNotAligned = 0;
+
+ printf("\n");
+ DWN_MSG("=====>To burn part [%s]\n", partName);
+ optimus_progress_ui_printf("Burning part[%s]\n", partName);
+ hImgItem = image_item_open(hImg, "PARTITION", partName);
+ if (!hImgItem) {
+ DWN_ERR("Fail to open item for part (%s)\n", partName);
+ return __LINE__;
+ }
+
+ imgItemSz = leftItemSz = image_item_get_size(hImgItem);
+ if (!imgItemSz) {
+ DWN_ERR("image size is 0 , image of part (%s) not exist ?\n", partName);
+ return __LINE__;
+ }
+
+ fileFmt = (IMAGE_ITEM_TYPE_SPARSE == image_item_get_type(hImgItem)) ? "sparse" : "normal";
+
+ itemSizeNotAligned = image_item_get_first_cluster_size(hImg, hImgItem);
+ leftItemSz -= itemSizeNotAligned;
+ rcode = sdc_burn_buf_manager_init(partName, imgItemSz, fileFmt, itemSizeNotAligned);
+ if (rcode) {
+ DWN_ERR("fail in sdc_burn_buf_manager_init, rcode %d\n", rcode);
+ return __LINE__;
+ }
+
+ //for each loop:
+ //1, get buffer from buffer_manager,
+ //2, read item data to buffer,
+ //3, report data ready to buffer_manager
+ for (; leftItemSz > 0; leftItemSz -= thisReadLen, sequenceNo++)
+ {
+ thisReadLen = leftItemSz > ItemReadBufSz ? ItemReadBufSz: (u32)leftItemSz;
+
+ rcode = optimus_buf_manager_get_buf_for_bulk_transfer(&downTransBuf, thisReadLen, sequenceNo, _errInfo);
+ if (rcode) {
+ DWN_ERR("fail in get buf, msg[%s]\n", _errInfo);
+ goto _finish;
+ }
+
+ //If the item head is not alinged to FAT cluster, Read it firstly to speed up mmc read
+ if (itemSizeNotAligned && !sequenceNo)
+ {
+ DWN_MSG("itemSizeNotAligned 0x%x\n", itemSizeNotAligned);
+ rcode = image_item_read(hImg, hImgItem, downTransBuf - itemSizeNotAligned, itemSizeNotAligned);
+ if (rcode) {
+ DWN_ERR("fail in read data from item,rcode %d, len 0x%x, sequenceNo %d\n", rcode, itemSizeNotAligned, sequenceNo);
+ goto _finish;
+ }
+ }
+
+ rcode = image_item_read(hImg, hImgItem, downTransBuf, thisReadLen);
+ if (rcode) {
+ DWN_ERR("fail in read data from item,rcode %d\n", rcode);
+ goto _finish;
+ }
+
+ rcode = optimus_buf_manager_report_transfer_complete(thisReadLen, _errInfo);
+ if (rcode) {
+ DWN_ERR("fail in report data ready, rcode %d\n", rcode);
+ goto _finish;
+ }
+ if (hUiProgress)optimus_progress_ui_update_by_bytes(hUiProgress, thisReadLen) ;
+ }
+
+ DWN_DBG("BURN part %s %s!\n", partName, leftItemSz ? "FAILED" : "SUCCESS");
+
+_finish:
+ image_item_close(hImgItem);
+
+ if (rcode) {
+ DWN_ERR("Fail to burn part(%s) with in format (%s) before verify\n", partName, fileFmt);
+ optimus_progress_ui_printf("Failed at burn part[%s] befor VERIFY\n", partName);
+ return rcode;
+ }
+
+#if 1
+ if (!NeedVerify) {
+ return rcode;
+ }
+ rcode = optimus_verify_partition(partName, hImg, _errInfo);
+ if (ITEM_NOT_EXIST == rcode)
+ {
+ printf("WRN:part(%s) NOT verified\n", partName);
+ return 0;
+ }
+ if (rcode) {
+ printf("Fail in verify part(%s)\n", partName);
+ optimus_progress_ui_printf("Failed at VERIFY part[%s]\n", partName);
+ return __LINE__;
+ }
+#endif//#fi 0
+
+ return rcode;
+}
+
+int optimus_sdc_burn_partitions(ConfigPara_t* pCfgPara, HIMAGE hImg, __hdle hUiProgress, int NeedVerify)
+{
+ BurnParts_t* cfgParts = &pCfgPara->burnParts;
+ int burnNum = cfgParts->burn_num;
+ int i = 0;
+ int rcode = 0;
+
+ //update burn_parts para if burnNum is 0, i.e, not configured
+ if (!burnNum)
+ {
+ rcode = get_burn_parts_from_img(hImg, pCfgPara);
+ if (rcode) {
+ DWN_ERR("Fail to get burn parts from image\n");
+ return __LINE__;
+ }
+ burnNum = cfgParts->burn_num;
+ DWN_DBG("Data part num %d\n", burnNum);
+ }
+ if (!burnNum) {
+ DWN_ERR("Data part num is 0!!\n");
+ return __LINE__;
+ }
+
+ for (i = 0; i < burnNum; i++)
+ {
+ const char* partName = cfgParts->burnParts[i];
+
+ rcode = optimus_burn_one_partition(partName, hImg, hUiProgress, NeedVerify);
+ if (rcode) {
+ DWN_ERR("Fail in burn part %s\n", partName);
+ return __LINE__;
+ }
+ }
+
+ return rcode;
+}
+
+//not need to verify as not config ??
+int optimus_sdc_burn_media_partition(const char* mediaImgPath, const char* verifyFile)
+{
+ //TODO:change configure to 'partName = image' and work it using cmd 'sdc_update'
+ return optimus_burn_partition_image("media", mediaImgPath, "normal", verifyFile, 0);
+}
+
+int optimus_burn_bootlader(HIMAGE hImg)
+{
+ int rcode = 0;
+ int NeedVerify = 1;
+
+ rcode = optimus_burn_one_partition("bootloader", hImg, NULL, NeedVerify);
+ if (rcode) {
+ DWN_ERR("Fail when burn bootloader\n");
+ return __LINE__;
+ }
+
+ return rcode;
+}
+
+//flag, 0 is burn completed, else burn failed
+int optimus_report_burn_complete_sta(int isFailed, int rebootAfterBurn)
+{
+ if (isFailed)
+ {
+ DWN_MSG("======sdc burn Failed!!!!!\n");
+ DWN_MSG("PLS long-press power key to shut down\n");
+ optimus_led_show_burning_failure();
+ while (1) {
+ /*if(ctrlc())*/
+ }
+
+ return __LINE__;
+ }
+
+ DWN_MSG("======sdc burn SUCCESS.\n");
+ optimus_led_show_burning_success();
+ optimus_burn_complete(rebootAfterBurn ? rebootAfterBurn : OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_POWERKEY);//set complete flag and poweroff if burn successful
+ return 0;
+}
+
+static int sdc_burn_dtb_load(HIMAGE hImg)
+{
+ s64 itemSz = 0;
+ HIMAGEITEM hImgItem = NULL;
+ int rc = 0;
+ const char* partName = "dtb";
+ const u64 partBaseOffset = OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ unsigned char* dtbTransferBuf = (unsigned char*)partBaseOffset;
+
+ hImgItem = image_item_open(hImg, partName, "meson");
+ if (!hImgItem) {
+ DWN_ERR("Fail to open verify file for part (%s)\n", partName);
+ return ITEM_NOT_EXIST;
+ }
+
+ itemSz = image_item_get_size(hImgItem);
+ if (!itemSz) {
+ DWN_ERR("Item size 0\n");
+ image_item_close(hImgItem); return __LINE__;
+ }
+
+ rc = image_item_read(hImg, hImgItem, dtbTransferBuf, (unsigned)itemSz);
+ if (rc) {
+ DWN_ERR("Failed at item read, rc = %d\n", rc);
+ image_item_close(hImgItem); return __LINE__;
+ }
+ image_item_close(hImgItem);
+
+ rc = optimus_parse_img_download_info(partName, itemSz, "normal", "mem", partBaseOffset);
+ if (rc) {
+ DWN_ERR("Failed in init down info\n"); return __LINE__;
+ }
+
+ {
+ unsigned wrLen = 0;
+ char errInfo[512];
+
+ wrLen = optimus_download_img_data(dtbTransferBuf, (unsigned)itemSz, errInfo);
+ rc = (wrLen == itemSz) ? 0 : wrLen;
+ }
+
+ return rc;
+}
+
+#if CONFIG_SUPPORT_SDC_KEYBURN
+//fetch the keys names which need be burned from item[conf, keys]
+static int sdc_burn_get_user_key_names(HIMAGE hImg, const char* **pKeysName, unsigned* keysNum)
+{
+ int rc = 0;
+ HIMAGEITEM hImgItem = NULL;
+ unsigned itemSz = 0;
+ unsigned char* thisReadBuf = (unsigned char*)OPTIMUS_SPARSE_IMG_FILL_VAL_BUF;//This buf is not used and not need reuse when burning keys
+ const unsigned thisReadBufSz = (OPTIMUS_SPARSE_IMG_FILL_BUF_SZ >> 1);
+ const char* *keysName = (const char**)(thisReadBuf + thisReadBufSz);
+
+ hImgItem = image_item_open(hImg, "conf", "keys");
+ if (!hImgItem) {
+ DWN_ERR("Fail to open keys.conf\n");
+ return ITEM_NOT_EXIST;
+ }
+
+ itemSz = (unsigned)image_item_get_size(hImgItem);
+ if (!itemSz) {
+ DWN_ERR("Item size 0\n");
+ image_item_close(hImgItem); return __LINE__;
+ }
+
+ rc = image_item_read(hImg, hImgItem, thisReadBuf, itemSz);
+ if (rc) {
+ DWN_ERR("Failed at item read, rc = %d\n", rc);
+ image_item_close(hImgItem); return __LINE__;
+ }
+ image_item_close(hImgItem);
+
+ if (itemSz >= thisReadBufSz) {
+ DWN_ERR("itemSz(0x%x) of keys.conf too large, > max 0x%x.\n", itemSz, thisReadBufSz);
+ return __LINE__;
+ }
+
+ rc = _optimus_parse_buf_2_lines((char*)thisReadBuf, itemSz, keysName, keysNum, 16);
+ if (rc) {
+ DWN_ERR("Fail in parse buf_2_lines\n");
+ return __LINE__;
+ }
+
+ rc = _optimus_abandon_ini_comment_lines((char**)keysName, *keysNum);
+
+ *pKeysName = keysName;
+ return rc;
+}
+
+//check key is burned yet --> need keyOverWrite -->can_write
+static int sdc_check_key_need_to_burn(const char* keyName, const int keyOverWrite)
+{
+ int rc = 0;
+ char _cmd[96];
+
+ sprintf(_cmd, "aml_key_burn misc is_burned %s", keyName);
+ rc = run_command(_cmd, 0);
+ if (rc < 0) {
+ DWN_ERR("Fail in check key is_burned\n");
+ return -__LINE__;
+ }
+ DWN_MSG("key[%s] is %s burned\n", keyName, rc ? "NOT" : "DO");
+ if (rc) {//not success
+ return 1;//need burn as not burned yet.
+ }
+ if (!keyOverWrite) {
+ DWN_MSG("User choose not to overwrite the key\n");
+ return 0;
+ }
+
+ sprintf(_cmd, "aml_key_burn misc can_write %s", keyName);
+ rc = run_command(_cmd, 0);
+ if (rc) {
+ DWN_ERR("Fail in check key[%s] is_burned\n", keyName);
+ return -__LINE__;
+ }
+ DWN_MSG("key[%s] is %s can_write\n", keyName, rc ? "NOT" : "DO");
+ return !rc;
+}
+
+//burn the amlogic keys like USB_Burning_Tool
+static int sdc_burn_aml_keys(HIMAGE hImg, const int keyOverWrite)
+{
+ int rc = 0;
+ const char* *keysName = NULL;
+ unsigned keysNum = 0;
+ const char** pCurKeysName = NULL;
+ unsigned index = 0;
+
+ rc = run_command("aml_key_burn probe vfat sdc", 0);
+ if (rc) {
+ DWN_ERR("Fail in probe for aml_key_burn\n");
+ return __LINE__;
+ }
+
+ {
+ unsigned random32 = 0;
+ unsigned seed = 0;
+ char cmd[96];
+
+ random32 = seed = get_utimer(0) + 12345;//make it random
+ /*random32 = random_u32(seed);*/
+ DWN_MSG("random value is 0x%x\n", random32);
+ sprintf(cmd, "aml_key_burn init 0x%x", random32);
+
+ rc = run_command(cmd, 0);
+ if (rc) {
+ DWN_ERR("Fail in cmd[%s]\n", cmd);
+ return __LINE__;
+ }
+ }
+
+ rc = sdc_burn_get_user_key_names(hImg, &keysName, &keysNum);
+ if (ITEM_NOT_EXIST != rc && rc) {
+ DWN_ERR("Fail to parse keys.conf, rc =%d\n", rc);
+ return __LINE__;
+ }
+ DWN_MSG("keys.conf:\n");
+ for (index = 0; index < keysNum; ++index)printf("\tkey[%d]\t%s\n", index, keysName[index]) ;
+
+ rc = optimus_sdc_keysprovider_init();
+ if (rc) {
+ DWN_ERR("Fail in optimus_sdc_keysprovider_init\n");
+ return __LINE__;
+ }
+
+ pCurKeysName = keysName;
+ for (index = 0; index < keysNum; ++index)
+ {
+ const char* const keyName = *pCurKeysName++;
+
+ if (!keyName) continue;
+ DWN_MSG("\n");
+ DWN_MSG("Now to burn key <---- [%s] ----> %d \n", keyName, index);
+ rc = sdc_check_key_need_to_burn(keyName, keyOverWrite);
+ if (rc < 0) {
+ DWN_ERR("Fail when when check stauts for key(%s)\n", keyName);
+ return __LINE__;
+ }
+ if (!rc) continue;//not need to burn this key
+
+ //0, init the key license parser
+ const void* pHdle = NULL;
+ rc = optimus_sdc_keysprovider_open(keyName, &pHdle);
+ if (rc) {
+ DWN_ERR("Fail in init license for key[%s]\n", keyName);
+ return __LINE__;
+ }
+
+ //1,using cmd_keysprovider to read a key to memory
+ u8* keyValue = (u8*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ unsigned keySz = OPTIMUS_DOWNLOAD_SLOT_SZ;//buffer size
+ rc = optimus_sdc_keysprovider_get_keyval(pHdle, keyValue, &keySz);
+ if (rc) {
+ DWN_ERR("Fail to get value for key[%s]\n", keyName);
+ return __LINE__;
+ }
+
+ //3, burn the key
+ rc = optimus_keysburn_onekey(keyName, (u8*)keyValue, keySz);
+ if (rc) {
+ DWN_ERR("Fail in burn the key[%s] at addr=%p, sz=%d\n", keyName, keyValue, keySz);
+ return __LINE__;
+ }
+
+ //3,report burn result to cmd_keysprovider
+ rc = optimus_sdc_keysprovider_update_license(pHdle);
+ if (rc) {
+ DWN_ERR("Fail in update license for key[%s]\n", keyName);
+ return __LINE__;
+ }
+ }
+
+ rc = optimus_sdc_keysprovider_exit();
+ if (rc) {
+ DWN_ERR("Fail in optimus_sdc_keysprovider_exit\n");
+ return __LINE__;
+ }
+
+ rc = run_command("aml_key_burn uninit", 0);
+ if (rc) {
+ DWN_ERR("Fail in uninit for aml_key_burn\n");
+ return __LINE__;
+ }
+
+ return 0;
+}
+#else
+#define sdc_burn_aml_keys(fmt...) 0
+#endif// #if CONFIG_SUPPORT_SDC_KEYBURN
+
+int optimus_burn_with_cfg_file(const char* cfgFile)
+{
+ extern ConfigPara_t g_sdcBurnPara ;
+
+ int ret = 0;
+ HIMAGE hImg = NULL;
+ ConfigPara_t* pSdcCfgPara = &g_sdcBurnPara;
+ const char* pkgPath = pSdcCfgPara->burnEx.pkgPath;
+ __hdle hUiProgress = NULL;
+
+ ret = parse_ini_cfg_file(cfgFile);
+ if (ret) {
+ DWN_ERR("Fail to parse file %s\n", cfgFile);
+ ret = __LINE__; goto _finish;
+ }
+
+ if (pSdcCfgPara->custom.eraseBootloader)
+ {
+ if (is_bootloader_old())
+ {
+ DWN_MSG("To erase OLD bootloader !\n");
+ ret = optimus_erase_bootloader(NULL);
+ if (ret) {
+ DWN_ERR("Fail to erase bootloader\n");
+ ret = __LINE__; goto _finish;
+ }
+
+#if defined(CONFIG_VIDEO_AMLLCD)
+ //axp to low power off LCD, no-charging
+ DWN_MSG("To close LCD\n");
+ ret = run_command("video dev disable", 0);
+ if (ret) {
+ printf("Fail to close back light\n");
+ /*return __LINE__;*/
+ }
+#endif// #if defined(CONFIG_VIDEO_AMLLCD)
+
+ DWN_MSG("Reset to load NEW uboot from ext-mmc!\n");
+ optimus_reset(OPTIMUS_BURN_COMPLETE__REBOOT_SDC_BURN);
+ return __LINE__;//should never reach here!!
+ }
+ }
+
+ if (OPTIMUS_WORK_MODE_SDC_PRODUCE == optimus_work_mode_get()) //led not depend on image res, can init early
+ {
+ if (optimus_led_open(LED_TYPE_PWM)) {
+ DWN_ERR("Fail to open led for sdc_produce\n");
+ return __LINE__;
+ }
+ optimus_led_show_in_process_of_burning();
+ }
+
+ hImg = image_open("mmc", "0", "1", pkgPath);
+ if (!hImg) {
+ DWN_ERR("Fail to open image %s\n", pkgPath);
+ ret = __LINE__; goto _finish;
+ }
+
+ //update dtb for burning drivers
+ ret = sdc_burn_dtb_load(hImg);
+ if (ret) {
+ DWN_ERR("Fail in load dtb for sdc_burn\n");
+ ret = __LINE__; goto _finish;
+ }
+
+ if (video_res_prepare_for_upgrade(hImg)) {
+ DWN_ERR("Fail when prepare bm res or init video for upgrade\n");
+ ret = __LINE__; goto _finish;
+ }
+ show_logo_to_report_burning();
+
+ hUiProgress = optimus_progress_ui_request_for_sdc_burn();
+ if (!hUiProgress) {
+ DWN_ERR("request progress handle failed!\n");
+ ret = __LINE__; goto _finish;
+ }
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STEPS_AFTER_IMAGE_OPEN_OK);
+
+ int hasBootloader = 0;
+ u64 datapartsSz = optimus_img_decoder_get_data_parts_size(hImg, &hasBootloader);
+
+ int eraseFlag = pSdcCfgPara->custom.eraseFlash;
+ if (!datapartsSz) {
+ eraseFlag = 0;
+ DWN_MSG("Disable erase as data parts size is 0\n");
+ }
+ ret = optimus_storage_init(eraseFlag);
+ if (ret) {
+ DWN_ERR("Fail to init stoarge for sdc burn\n");
+ return __LINE__;
+ }
+
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STEPS_AFTER_DISK_INIT_OK);
+
+ if (datapartsSz)
+ {
+ ret = optimus_progress_ui_set_smart_mode(hUiProgress, datapartsSz,
+ UPGRADE_STEPS_FOR_BURN_DATA_PARTS_IN_PKG(!pSdcCfgPara->burnEx.bitsMap.mediaPath));
+ if (ret) {
+ DWN_ERR("Fail to set smart mode\n");
+ ret = __LINE__; goto _finish;
+ }
+
+ ret = optimus_sdc_burn_partitions(pSdcCfgPara, hImg, hUiProgress, 1);
+ if (ret) {
+ DWN_ERR("Fail when burn partitions\n");
+ ret = __LINE__; goto _finish;
+ }
+ }
+
+ if (pSdcCfgPara->burnEx.bitsMap.mediaPath) //burn media image
+ {
+ const char* mediaPath = pSdcCfgPara->burnEx.mediaPath;
+
+ ret = optimus_sdc_burn_media_partition(mediaPath, NULL);//no progress bar info if have partition image not in package
+ if (ret) {
+ DWN_ERR("Fail to burn media partition with image %s\n", mediaPath);
+ optimus_storage_exit();
+ ret = __LINE__;goto _finish;
+ }
+ }
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STPES_AFTER_BURN_DATA_PARTS_OK);
+
+ //TO burn nandkey/securekey/efusekey
+ ret = sdc_burn_aml_keys(hImg, pSdcCfgPara->custom.keyOverwrite);
+ if (ret) {
+ DWN_ERR("Fail in sdc_burn_aml_keys\n");
+ ret = __LINE__;goto _finish;
+ }
+
+#if 1
+ if (hasBootloader)
+ {//burn bootloader
+ ret = optimus_burn_bootlader(hImg);
+ if (ret) {
+ DWN_ERR("Fail in burn bootloader\n");
+ goto _finish;
+ }
+ else
+ {//update bootloader ENV only when bootloader image is burned
+ ret = optimus_set_burn_complete_flag();
+ if (ret) {
+ DWN_ERR("Fail in set_burn_complete_flag\n");
+ ret = __LINE__; goto _finish;
+ }
+ }
+ }
+#endif
+ optimus_progress_ui_direct_update_progress(hUiProgress, UPGRADE_STEPS_AFTER_BURN_BOOTLOADER_OK);
+
+_finish:
+ image_close(hImg);
+ optimus_progress_ui_report_upgrade_stat(hUiProgress, !ret);
+ optimus_report_burn_complete_sta(ret, pSdcCfgPara->custom.rebootAfterBurn);
+ optimus_progress_ui_release(hUiProgress);
+ //optimus_storage_exit();//temporary not exit storage driver when failed as may continue burning after burn
+ return ret;
+}
+
+int optimus_burn_package_in_sdmmc(const char* sdc_cfg_file)
+{
+ int rcode = 0;
+
+#if (MESON_CPU_TYPE_MESON8 <= MESON_CPU_TYPE)
+ //AML_WATCH_DOG_DISABLE(); //disable watchdog
+#endif// #if (MESON_CPU_TYPE_MESON8 <= MESON_CPU_TYPE)
+
+ DWN_MSG("mmcinfo\n");
+ rcode = run_command("mmcinfo", 0);
+ if (rcode) {
+ DWN_ERR("Fail in init mmc, Does sdcard not plugged in?\n");
+ return __LINE__;
+ }
+
+#if 0//this asserted by 'run update' and 'aml_check_is_ready_for_sdc_produce'
+ rcode = do_fat_get_fileSz(sdc_cfg_file);
+ if (!rcode) {
+ printf("The [%s] not exist in bootable mmc card\n", sdc_cfg_file);
+ return __LINE__;
+ }
+#endif//#if 0
+
+ rcode = optimus_burn_with_cfg_file(sdc_cfg_file);
+
+ return rcode;
+}
+
+int do_sdc_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ const char* sdc_cfg_file = argv[1];
+
+ if (argc < 2 ) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_SDC_UPDATE);
+ show_logo_to_report_burning();//indicate enter flow of burning! when 'run update'
+ if (optimus_led_open(LED_TYPE_PWM)) {
+ DWN_ERR("Fail to open led for burn\n");
+ return __LINE__;
+ }
+ optimus_led_show_in_process_of_burning();
+
+ rcode = optimus_burn_package_in_sdmmc(sdc_cfg_file);
+
+ return rcode;
+}
+
+U_BOOT_CMD(
+ sdc_burn, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_sdc_burn, //command function
+ "Burning with amlogic format package in sdmmc ", //description
+ "argv: [sdc_burn_cfg_file]\n"//usage
+ " -aml_sdc_burn.ini is usually used configure file\n"
+);
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn_i.h b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn_i.h
new file mode 100644
index 0000000000..2ad2203233
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_burn_i.h
@@ -0,0 +1,108 @@
+/*
+ * \file optimus_sdc_burn_i.h
+ * \brief internal struct types and interfaces for sdc burn
+ *
+ * \version 1.0.0
+ * \date 2013-7-12
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#ifndef __OPTIMUS_SDC_BURN_I_H__
+#define __OPTIMUS_SDC_BURN_I_H__
+
+#include "../v2_burning_i.h"
+#include <fat.h>
+#include <part.h>
+
+typedef struct _burnEx{
+ char pkgPath[128];
+ char mediaPath[128];
+ struct {
+ unsigned pkgPath : 1;
+ unsigned mediaPath : 1;
+ unsigned reserv : 32 - 2;
+ }bitsMap;
+}BurnEx_t;
+
+typedef struct _customPara{
+ int eraseBootloader;
+ int eraseFlash;
+ int rebootAfterBurn;
+ int keyOverwrite;
+ struct{
+ unsigned eraseBootloader : 1;
+ unsigned eraseFlash : 1;
+ unsigned rebootAfterBurn : 1;
+ unsigned keyOverwrite : 1;
+ unsigned resev : 32 - 4;
+ }bitsMap;
+}CustomPara_t;
+
+#define MAX_BURN_PARTS (32)
+#define PART_NAME_LEN_MAX (32)
+
+typedef struct _burnParts{
+ int burn_num;
+ char burnParts[MAX_BURN_PARTS][PART_NAME_LEN_MAX];
+ unsigned bitsMap4BurnParts;
+}BurnParts_t;
+
+typedef struct _ConfigPara{
+ BurnParts_t burnParts;
+ CustomPara_t custom;
+ BurnEx_t burnEx;
+ struct {
+ unsigned burnParts : 1;
+ unsigned custom : 1;
+ unsigned burnEx : 1;
+ unsigned reserv : 32 - 3;
+ }setsBitMap;
+}ConfigPara_t;
+
+//ini parser
+int _optimus_parse_buf_2_lines(char* pTextBuf, const unsigned textSz, const char* lines[],
+ unsigned* totalLineNum, const unsigned MaxLines);//parse text context to linces delimitted by (\r)\n
+int parse_ini_file_2_valid_lines(const char* filePath, char* iniBuf, const unsigned bufSz, char* lines[]);
+int _optimus_abandon_ini_comment_lines(char* lines[], const unsigned lineNum);
+int optimus_ini_trans_lines_2_usr_params(const char* const lines[], const unsigned lineNum,
+ int (*pCheckSetUseFul)(const char* setName),
+ int (*pParseCfgVal)(const char* setName, const char* keyName, const char* keyVal));
+
+int parse_ini_cfg_file(const char* filePath);
+
+int check_cfg_burn_parts(const ConfigPara_t* burnPara);
+int print_burn_parts_para(const BurnParts_t* pBurnParts);
+
+int sdc_burn_verify(const char* verifyFile);
+
+//burn a partition with a image file
+int optimus_burn_partition_image(const char* partName, const char* imgItemPath, const char* fileFmt, const char* verifyFile, const unsigned itemSizeNotAligned);
+
+int sdc_burn_buf_manager_init(const char* partName, s64 imgItemSz, const char* fileFmt,
+ const unsigned itemSizeNotAligned /* if item offset 3 and bytepercluste 4k, then it's 4k -3 */);
+
+int get_burn_parts_from_img(HIMAGE hImg, ConfigPara_t* pcfg);
+
+//declare for aml_sysrecovery
+int optimus_sdc_burn_partitions(ConfigPara_t* pCfgPara, HIMAGE hImg, __hdle hUiProgress, int needVerify);
+
+int optimus_burn_bootlader(HIMAGE hImg);
+
+int optimus_report_burn_complete_sta(int isFailed, int rebootAfterBurn);
+
+
+int optimus_sdc_burn_switch_to_extmmc(void);
+
+//Followings are For burn keys only
+int optimus_sdc_keysprovider_init(void);
+int optimus_sdc_keysprovider_exit(void);
+int optimus_sdc_keysprovider_open(const char* keyName, const void** pHdle);
+int optimus_sdc_keysprovider_get_keyval(const void* pHdle, u8* pBuf, unsigned* keySz);
+int optimus_sdc_keysprovider_update_license(const void* pHdle);
+
+int optimus_keysburn_onekey(const char* keyName, u8* keyVal, unsigned keyValLen);
+
+#endif//#ifndef __OPTIMUS_SDC_BURN_I_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_update.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_update.c
new file mode 100644
index 0000000000..73000865f9
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/optimus_sdc_update.c
@@ -0,0 +1,352 @@
+/*
+ * \file optimus_sdc_update.c
+ * \brief sdc_update command to burn a parition image from mmc
+ * this update based on the burner is latest: (uboot for burnner can run from peripherals such as sdmmc/usb)
+ *
+ * \version 1.0.0
+ * \date 2014-9-15
+ * \author Sam.Wu <yihui.wu@amlogic.com>
+ * Chunyu.Song <chunyu.song@amlogic.com>
+ * Copyright (c) 2014 Amlogic. All Rights Reserved.
+ *
+ */
+#include "optimus_sdc_burn_i.h"
+
+typedef int __hFileHdl;
+
+#define BURN_DBG 0
+#if BURN_DBG
+#define SDC_DBG(fmt...) printf(fmt)
+#else
+#define SDC_DBG(fmt...)
+#endif//if BURN_DBG
+
+#define SDC_MSG DWN_MSG
+#define SDC_ERR DWN_ERR
+
+static char _errInfo[512] = "";
+
+//default is mmc 0:1, i.e, part 1 of first registered mmc device
+int optimus_device_probe(const char* interface, const char* inPart)
+{
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ dev = (int)simple_strtoul(inPart, &ep, 16);
+ dev_desc = get_dev((char*)interface,dev);
+ if (dev_desc == NULL) {
+ puts("\n** Invalid boot device **\n");
+ return 1;
+ }
+ if (*ep) {
+ if (*ep != ':') {
+ puts("\n** Invalid boot device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+ if (fat_register_device(dev_desc,part) != 0) {
+ printf("\n** Unable to use %s %d:%d for device probe **\n",
+ interface, dev, part);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+__hFileHdl opt_file_open(const char* imgItemPath)
+{
+ __hFileHdl hFile = 0;
+
+#if 0
+ //FIXME: Check this probe needed!!!
+ if (device_probe("mmc", "0")) {
+ SDC_ERR("Fail to probe mmc 0");
+ return -1;
+ }
+#endif//#if 0
+
+ hFile = do_fat_fopen(imgItemPath);
+
+ return hFile;
+}
+
+int opt_file_read(__hFileHdl hFile, u8* buffer, const unsigned size)
+{
+ unsigned readSz = do_fat_fread(hFile, buffer, size);
+ if (readSz != size) {
+ SDC_ERR("Want to read 0x%x, but 0x%x\n", size, readSz);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+int opt_file_close(__hFileHdl hFile)
+{
+ do_fat_fclose(hFile);
+
+ return 0;
+}
+
+//part size 0 if failed
+s64 storage_get_partition_size_in_byte(const char* partName)
+{
+ int ret = 0;
+ u64 size = 0;
+
+#if 1
+ ret = store_get_partititon_size((u8*)partName, &size);
+ if (ret) {
+ SDC_ERR("Fail to get size for part %s\n", partName);
+ return 0;
+ }
+ size <<= 9;//trans sector to byte
+#endif
+
+ return size;
+}
+
+//0 is OK, others failed
+int sdc_burn_buf_manager_init(const char* partName, s64 imgItemSz, const char* fileFmt,
+ const unsigned itemSizeNotAligned /* if item offset 3 and bytepercluste 4k, then it's 4k -3 */)
+{
+ int rcode = 0;
+ s64 partCapInByte = 0;
+ const char* destMediaType = "store";
+ const u64 partBaseOffset = 0;
+
+ if (strcmp("bootloader", partName)) //TODO:bootloader size can't get yet!
+ {
+ partCapInByte = storage_get_partition_size_in_byte(partName);
+ if (partCapInByte < imgItemSz || !partCapInByte) {
+ SDC_ERR("partCapInByte 0x[%x, %x] < imgItemSz 0x[%x, %x]\n",
+ (u32)(partCapInByte>>32), (u32)partCapInByte, (u32)(imgItemSz>>32), (u32)imgItemSz);
+ return __LINE__;
+ }
+ }
+
+ rcode = optimus_parse_img_download_info(partName, imgItemSz, fileFmt, destMediaType, partBaseOffset);
+ if (rcode) {
+ SDC_ERR("fail in init down info, rcode %d\n", rcode);
+ return __LINE__;
+ }
+ rcode = optimus_buf_manager_tplcmd_init(destMediaType, partName, 0, fileFmt, imgItemSz, 0, itemSizeNotAligned);
+ if (rcode) {
+ SDC_ERR("Fail in buf manager init\n");
+ return __LINE__;
+ }
+
+ return rcode;
+}
+
+int sdc_burn_verify(const char* verifyFile)
+{
+ int rcode = 0;
+ char* argv[8];
+ char verifyCmd[64] = "";
+ char cmdBuf[64];
+ char *usb_update = getenv("usb_update");
+
+ if (!strcmp(usb_update,"1")) {
+ sprintf(cmdBuf, "%s 0x%p %s", "fatload usb 0 ", verifyCmd, verifyFile);
+ }
+ else{
+ sprintf(cmdBuf, "%s 0x%p %s", "fatload mmc 0 ", verifyCmd, verifyFile);
+ }
+ SDC_DBG("To run cmd [%s]\n", cmdBuf);
+ rcode = run_command(cmdBuf, 0);
+ if (rcode < 0) {
+ SDC_ERR("Fail in cmd fatload\n");
+ return __LINE__;
+ }
+ SDC_MSG("cmd verify[%s]\n", verifyCmd);
+
+ rcode = cli_simple_parse_line(verifyCmd, argv + 1);
+ if (rcode != 2) {
+ SDC_ERR("verify cmd argc must be 2, but %d\n", rcode);
+ return __LINE__;
+ }
+ argv[0] = "verify";
+
+ rcode = optimus_media_download_verify(3, argv, _errInfo);
+ if (rcode) {
+ SDC_ERR("Fail to verify\n");
+ return __LINE__;
+ }
+ return 0;
+}
+
+int optimus_burn_partition_image(const char* partName, const char* imgItemPath, const char* fileFmt, const char* verifyFile, const unsigned itemSizeNotAligned)
+{
+ int rcode = 0;
+ s64 imgItemSz = 0;
+ s64 leftItemSz = 0;
+ u32 thisReadLen = 0;
+ __hFileHdl hImgItem = 0;
+ char* downTransBuf = NULL;//get buffer from optimus_buffer_manager
+ const unsigned ItemReadBufSz = OPTIMUS_DOWNLOAD_SLOT_SZ;//read this size from image item each time
+ unsigned sequenceNo = 0;
+
+ imgItemSz = leftItemSz = do_fat_get_fileSz(imgItemPath);
+ if (!imgItemSz) {
+ SDC_ERR("Fail to get image %s from mmc\n", imgItemPath);
+ return __LINE__;
+ }
+
+ rcode = sdc_burn_buf_manager_init(partName, imgItemSz, fileFmt, itemSizeNotAligned);
+ if (rcode) {
+ SDC_ERR("fail in sdc_burn_buf_manager_init, rcode %d\n", rcode);
+ return __LINE__;
+ }
+
+ hImgItem = opt_file_open(imgItemPath);
+ if (hImgItem < 0) {
+ SDC_ERR("Fail to open the item %s\n", imgItemPath);
+ return __LINE__;
+ }
+
+ /*optimus_progress_init((u32)(imgItemSz>>32), (u32)imgItemSz, 0, 100);*/
+
+ //for each loop:
+ //1, get buffer from buffer_manager,
+ //2, read item data to buffer,
+ //3, report data ready to buffer_manager
+ for (; leftItemSz > 0; leftItemSz -= thisReadLen, sequenceNo++)
+ {
+ thisReadLen = leftItemSz > ItemReadBufSz ? ItemReadBufSz: (u32)leftItemSz;
+
+ rcode = optimus_buf_manager_get_buf_for_bulk_transfer(&downTransBuf, thisReadLen, sequenceNo, _errInfo);
+ if (rcode) {
+ SDC_ERR("fail in get buf, msg[%s]\n", _errInfo);
+ goto _finish;
+ }
+
+ rcode = opt_file_read(hImgItem, (u8*)downTransBuf, thisReadLen);
+ if (rcode) {
+ SDC_ERR("fail in read data from item,rcode %d\n", rcode);
+ goto _finish;
+ }
+
+ rcode = optimus_buf_manager_report_transfer_complete(thisReadLen, _errInfo);
+ if (rcode) {
+ SDC_ERR("fail in report data ready, rcode %d\n", rcode);
+ goto _finish;
+ }
+
+ /*optimus_update_progress(thisReadLen);//report burning steps*/
+ }
+
+ if (leftItemSz <= 0) {
+ printf("BURN %s to part %s OK!\n", imgItemPath, partName);
+ }
+
+_finish:
+ opt_file_close(hImgItem);
+
+ if (!rcode && verifyFile)
+ {
+ rcode = sdc_burn_verify(verifyFile);
+ }
+
+ printf("=====>Burn part %s in fmt %s %s<======\n\n", partName, fileFmt, rcode ? "FAILED!!": "OK");
+ return rcode;
+}
+
+//step 1: get script file size, and get script file contents
+//step 2: read image file
+//"Usage: sdc_update partiton image_file_path [imgFmt, verifyFile]\n" //usage
+int do_sdc_update(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+ const char* partName = argv[1];
+ const char* imgItemPath = argv[2];
+ const char* fileFmt = argc > 3 ? argv[3] : NULL;
+ const char* verifyFile = argc > 4 ? argv[4] : NULL;
+
+ setenv("usb_update",0);
+#if BURN_DBG
+ printf("argc %d, %s, %s\n", argc, argv[0], argv[1]);
+ if (argc < 3)
+ {
+ partName = "system";
+ imgItemPath = "rec.img";
+ fileFmt = "normal";
+ verifyFile = "recovery.verify";
+ }
+#else
+ if (argc < 3) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+#endif//#if BURN_DBG
+
+ //mmc info to ensure sdcard inserted and inited
+ rcode = run_command("mmcinfo", 0);
+ if (rcode) {
+ SDC_ERR("Fail in init mmc, Does sdcard not plugged in?\n");
+ return __LINE__;
+ }
+
+#if 0
+ if (!do_fat_get_fileSz(imgItemPath)) {
+ SDC_ERR("file (%s) not existed\n", imgItemPath);
+ return __LINE__;
+ }
+#else
+ rcode = optimus_device_probe("mmc", "0");
+ if (rcode) {
+ SDC_ERR("Fail to detect device mmc 0\n");
+ return __LINE__;
+ }
+#endif//#if 0
+
+ if (!fileFmt)
+ {
+ rcode = do_fat_get_file_format(imgItemPath, (u8*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR, (8*1024));
+ if (rcode < 0) {
+ SDC_ERR("Fail when parse file format\n");
+ return __LINE__;
+ }
+ fileFmt = rcode ? "sparse" : "normal";
+ }
+
+#if 0
+ if (!getenv("disk_initial")) //if disk_initial command not executed for burning
+ {
+ rcode = optimus_storage_init(0);//can't erase as not full updating
+ if (rcode) {
+ SDC_ERR("Fail in init storage, rcode %d\n", rcode);
+ return rcode;
+ }
+ setenv("disk_initial", "0");
+ }
+#endif//#if 0
+
+ rcode = optimus_burn_partition_image(partName, imgItemPath, fileFmt, verifyFile, 0);
+ if (rcode) {
+ SDC_ERR("Fail to burn partition (%s) with image file (%s) in format (%s)\n", partName, imgItemPath, fileFmt);
+ }
+
+ return rcode;
+}
+
+U_BOOT_CMD(
+ sdc_update, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_sdc_update, //command function
+ "Burning a partition with image file in sdmmc card", //description
+ " argv: <part_name> <image_file_path> <[,fileFmt]> <[,verify_file]> \n" //usage
+ " - <fileFmt> parameter is optional, if you know it you can specify it.\n"
+ " for Android, system.img and data.img is \"sparse\" format, other is \"normal\"\n" //usage
+ " - <verify_file> parameter is optional, if you have it you can specify it.\n"
+ " - e.g. \n"
+ " to burn partition boot with boot.img of mmc 0 : \"sdc_update boot boot.img\"\n" //usage
+ " to burn partition system with system.img of mmc 0 : \"sdc_update system system.img\"\n" //usage
+);
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/optimus_key_burn.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/optimus_key_burn.c
new file mode 100644
index 0000000000..cf16043cb1
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/optimus_key_burn.c
@@ -0,0 +1,299 @@
+/*
+ * \file optimus_key_burn.c
+ * \brief burning keys from sdcard like update.exe
+ *
+ * \version 1.0.0
+ * \date 2014/12/25
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2014 Amlogic. All Rights Reserved.
+ *
+ */
+
+/*
+ *
+ * This cmd [aml_key_burn] aim to burn keys like 'update.exe', and mainly used for myself.
+ * like update.exe, the key in here is single and not need to sperate
+ * e.g, for comparison, here to burn a hdcp key using aml_key_burn and update.exe
+ * 0. update.exe identify . <-----> aml_key_burn probe vfat sdc
+ * 1. update.exe mwrite meson.dtb mem dtb normal . <-----> aml_key_burn meson_dtb meson.dtb
+ * 2, update.exe bulkcmd "key init 0x1234" <-----> aml_key_burn init 0x1234
+ * 3, update.exe mwrite key hdcp normal hdcp308.val <-----> aml_key_burn burn hdcp hdcp308.val
+ * other keys
+ * 4, update.exe bulkcmd "key uninit" <-----> aml_key_burn uninit
+ *
+ */
+#include "../optimus_sdc_burn_i.h"
+#include <amlogic/keyunify.h>
+
+#define _AML_KEY_ERR(fmt...) sprintf(_errInfo, fmt), DWN_ERR(_errInfo)
+
+static char _errInfo[512] = "";
+
+
+typedef enum{
+ DEV_FILE_FMT_VFAT = 0xee,
+ DEV_FILE_FMT_EXT2
+}DevFileFmt_e;
+
+typedef enum{
+ DEV_INTF_EXT_SDMMC = 0xdd,
+ DEV_INTF_EXT_UDISK ,
+}DevIntf_e;
+
+static struct optKeyInfo_s{
+ DevFileFmt_e fileFmt;
+ DevIntf_e intf;//interface
+} _optKeyInfo;
+/*
+ * <aml_key_burn probe> device_format interface
+ */
+static int do_opt_keysburn_probe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+ const char* device_format = argv[2];//vfat
+ const char* device_interf = argv[3];//sdc/udisk
+
+ if (4 > argc) {
+ _AML_KEY_ERR("failed:argc: %d < 4\n", argc);
+ return __LINE__;
+ }
+ if (!strcmp(device_format, "vfat")) {
+ _optKeyInfo.fileFmt = DEV_FILE_FMT_VFAT;
+ }
+ else{
+ _AML_KEY_ERR("failed:device_format %s unsupported yet\n", device_format);
+ return __LINE__;
+ }
+
+ if (!strcmp("sdc", device_interf))
+ {
+ static int _mmcprobe = 0;
+
+ if (!_mmcprobe)
+ {
+ rc = run_command("mmcinfo 0", 0);
+ if (rc) {
+ _AML_KEY_ERR("failed: in mmcinfo\n");
+ return __LINE__;
+ }
+ rc = optimus_device_probe("mmc", "0");
+ if (rc) {
+ _AML_KEY_ERR("Fail to detect device mmc 0\n");
+ return __LINE__;
+ }
+ _mmcprobe = 1;
+ }
+ _optKeyInfo.intf = DEV_INTF_EXT_SDMMC;
+ }
+ else if(!strcmp("udisk", device_interf))
+ {
+ static int _udiskProbe = 0;
+
+ if (!_udiskProbe)
+ {
+ rc = run_command("usb start 0", 0);
+ if (rc) {
+ _AML_KEY_ERR("Fail in mmcinfo\n");
+ return __LINE__;
+ }
+ rc = optimus_device_probe("usb", "0");
+ if (rc) {
+ _AML_KEY_ERR("Fail to detect device mmc 0\n");
+ return __LINE__;
+ }
+ _udiskProbe = 1;
+ }
+ _optKeyInfo.intf = DEV_INTF_EXT_UDISK;
+ }
+ else{
+ _AML_KEY_ERR("device_interf %s unsupported\n", device_interf);
+ return -__LINE__;
+ }
+
+ return rc;
+}
+
+static int do_opt_keysburn_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+
+ if (3 > argc)
+ {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+ rc = v2_key_command(argc, argv, _errInfo);
+ if (rc) {
+ DWN_ERR("Fail to init key driver.\n");
+ return -__LINE__;
+ }
+
+ return rc;
+}
+
+static int do_opt_keysburn_uninit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+
+ rc = v2_key_command(argc, argv, _errInfo);
+ if (rc) {
+ DWN_ERR("Fail to init key driver.\n");
+ return -__LINE__;
+ }
+ return rc;
+}
+
+static int do_opt_keysburn_misc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+
+ --argc, ++argv;//skip the misc subcmd
+ rc = v2_key_command(argc, argv, _errInfo);
+ if (rc < 0) {
+ return -__LINE__;
+ }
+
+ return rc;
+}
+
+static int optimus_read_keyfile_2_mem(const char* filePath, u8* buf, unsigned* keyValLen)
+{
+ int rc = 0;
+ unsigned keySz = 0;
+
+ if (DEV_FILE_FMT_VFAT == _optKeyInfo.fileFmt)
+ {
+ long hFile = -1;
+ unsigned readSz = 0;
+
+#if 1//FIXME: remove this mmcinfo
+ /*rc = run_command("mmcinfo 0", 0);*/
+ rc = optimus_sdc_burn_switch_to_extmmc();
+ if (rc) {
+ DWN_ERR("Fail in mmcinfo\n");
+ return __LINE__;
+ }
+#endif//
+ keySz = (unsigned)do_fat_get_fileSz(filePath);//can support both sdc and udisk
+ if (!keySz) {
+ DWN_ERR("size is 0 of file [%s]\n", filePath);
+ return __LINE__;
+ }
+
+ hFile = do_fat_fopen(filePath);
+ if (hFile < 0) {
+ DWN_ERR("Fail to open file[%s]\n", filePath);
+ return __LINE__;
+ }
+
+ readSz = do_fat_fread(hFile, buf, keySz);
+ if (readSz != keySz) {
+ DWN_ERR("Want read %d bytes, but %d\n", keySz, readSz);
+ return __LINE__;
+ }
+
+ do_fat_fclose(hFile);
+ }
+
+ *keyValLen = keySz;
+ return rc;
+}
+
+int optimus_keysburn_onekey(const char* keyName, u8* keyVal, unsigned keyValLen)
+{
+ int rc = 0;
+ unsigned wrLen = 0;
+
+ DWN_MSG("keyName[%s], keyValAddr=%p,len=%d\n", keyName, keyVal, keyValLen);
+ wrLen = v2_key_burn(keyName, keyVal, keyValLen, _errInfo);
+ DWN_MSG("writeLen=====%d\n", wrLen);
+ rc = wrLen != keyValLen;
+ _AML_KEY_ERR("%s in burn key[%s]\n", rc ? "failed" : "success", keyName);
+
+ return rc;
+}
+
+static int do_opt_keysburn_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+ const char* keyName = argv[2];
+ u8* keyVal = (u8*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR;
+ unsigned keyValLen = 0;
+
+ if (4 > argc) {
+ _AML_KEY_ERR("argc=%d < 4\n", argc);
+ return __LINE__;
+ }
+ if (argc > 4)
+ {
+ keyVal = (u8*)simple_strtoul(argv[3], NULL, 16);
+ keyValLen = simple_strtoul(argv[4], NULL, 0);
+ }
+ else//The key is file in the specified device
+ {
+ const char* filePath = argv[3];
+
+ rc = optimus_read_keyfile_2_mem(filePath, keyVal, &keyValLen);
+ if (rc) {
+ _AML_KEY_ERR("Fail to read file[%s]\n", filePath);
+ return __LINE__;
+ }
+ }
+ rc = optimus_keysburn_onekey(keyName, keyVal, keyValLen);
+
+ return rc;
+}
+
+
+static cmd_tbl_t cmd_opt_key_burn[] = {
+ U_BOOT_CMD_MKENT(probe, 4, 0, do_opt_keysburn_probe, "", ""),
+ U_BOOT_CMD_MKENT(init, 3, 0, do_opt_keysburn_init, "", ""),
+ U_BOOT_CMD_MKENT(uninit, 2, 0, do_opt_keysburn_uninit, "", ""),
+ U_BOOT_CMD_MKENT(burn, 5, 0, do_opt_keysburn_burn, "", ""),
+ U_BOOT_CMD_MKENT(misc, 6, 0, do_opt_keysburn_misc, "", ""),
+};
+
+static int do_aml_key_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+ cmd_tbl_t *c;
+
+ sprintf(_errInfo, "success");
+ c = find_cmd_tbl(argv[1], cmd_opt_key_burn, ARRAY_SIZE(cmd_opt_key_burn));
+
+ if (!c) {
+ DWN_ERR("Can't find subcmd[%s]\n", argv[1]);
+ return 1;
+ }
+
+ rc = c->cmd(cmdtp, flag, argc, argv);
+ DWN_MSG("[key]%s\n", _errInfo);
+ if (rc < 0) {
+ DWN_ERR("Fail in cmd[%s %s].ret=%d\n", argv[1], argv[2], rc);
+ return -__LINE__;
+ }
+ rc = strncmp("success", _errInfo, 7);
+
+ return rc;
+}
+
+U_BOOT_CMD(
+ aml_key_burn, //command name
+ 6, //maxargs
+ 0, //repeatable
+ do_aml_key_burn, //command function
+ "Burning keys from external device(sdmmc/udisk/memory) other than usb device", //description
+ "argv: aml_key_burn ...\n"//usage
+ "<probe> file_system interface --- init external device/interface\n"//usage
+ " - e.g.1, for fat sdcard : <aml_key_burn probe> vfat sdc\n"
+ " - e.g.2, for fat udisk : <aml_key_burn probe> vfat udisk\n"
+ "\n"
+ "<init/uninit> random_value --- init nandkey/efusekey driver\n"//usage
+ "\n"
+ "<burn> keyName keyFilePath(keyBufAddr keySize) --- init external device/interface\n"//usage
+ " - e.g.1, write hdcp key with hdcp308.key from sdcard: <aml_key_burn burn> hdcp hdcp308.key\n"
+ " - e.g.2, write hdcp key in addr 0x200000 : <aml_key_burn burn> hdcp 0x200000 308\n"
+ "\n"
+);
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.c
new file mode 100644
index 0000000000..46c7fef071
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.c
@@ -0,0 +1,239 @@
+/*
+ * \file sdc_bootPart_license.c
+ * \brief
+ *
+ * \version 1.0.0
+ * \date 2015/3/10
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2015 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../optimus_sdc_burn_i.h"
+#include "sdc_bootPart_license.h"
+#include <crc.h>
+
+COMPILE_TYPE_CHK(AML_BOOT_PART_KEY_HEAD_SZ == sizeof(BootPartKeyInf_head_t), _aa1);
+COMPILE_TYPE_CHK(AML_BOOT_PART_KEY_ITEM_SZ == sizeof(BootPartKeyInf_Item_t), _aa2);
+
+#define _OPT_BOOT_PART_LIC_INFO_LOADADDR (OPTIMUS_DOWNLOAD_SPARSE_INFO_FOR_VERIFY)
+#define _pOptBootPartLicHeadInf (BootPartKeyInf_head_t*)(_OPT_BOOT_PART_LIC_INFO_LOADADDR)
+
+//Load boot part license info from external emmc to memory
+//As "mmc read" is slow, I load it from external mmc only once
+int optimus_sdc_bootPart_lic_download(void)
+{
+ const unsigned maxLen = 2U<<20;//
+ const unsigned firstReadLen = 2U<<10;//2K
+ const char* _cmdStr = "mmc read 1 0x%x, 0x%x 0x%x";
+ BootPartKeyInf_head_t* pBootPartKeyInfHead = _pOptBootPartLicHeadInf;
+ char _cmdBuf[96];
+ int rc = 0;
+
+//1, Read from _OPT_BOOT_PART_LIC_INFO_LOADADDR
+ rc = run_command("mmcinfo 0", 0);
+ if (rc) {
+ DWN_ERR("Fail to init external sdcard\n");
+ return __LINE__;
+ }
+
+ memset(pBootPartKeyInfHead, 0, AML_BOOT_PART_KEY_HEAD_SZ + AML_BOOT_PART_KEY_ITEM_SZ * 64);
+ sprintf(_cmdBuf, _cmdStr, _OPT_BOOT_PART_LIC_INFO_LOADADDR, AML_BOOT_PART_KEY_HEAD_OFFSET, firstReadLen);
+ DWN_MSG("cmd[%s]\n", _cmdBuf);
+ rc = run_command(_cmdBuf, 0);
+ if (rc) {
+ DWN_ERR("Fail in cmd[%s]\n", _cmdBuf);
+ return __LINE__;
+ }
+
+ rc = (AML_BOOT_PART_KEY_HEAD_VERSION == pBootPartKeyInfHead->version)
+ && (AML_BOOT_PART_KEY_HEAD_MAGIC == pBootPartKeyInfHead->magic);
+ if (!rc)
+ {
+ DWN_MSG("Ver[0x%x] or magic[0x%8x] error\n",
+ pBootPartKeyInfHead->version, pBootPartKeyInfHead->magic);
+ //Create the image header
+ pBootPartKeyInfHead->magic = AML_BOOT_PART_KEY_HEAD_MAGIC;
+ pBootPartKeyInfHead->version = AML_BOOT_PART_KEY_HEAD_VERSION;
+ pBootPartKeyInfHead->alignSz = AML_BOOT_PART_ALIGN_SZ;
+ pBootPartKeyInfHead->imgSz = sizeof(BootPartKeyInf_head_t);
+ pBootPartKeyInfHead->imgItemNum = 0;
+
+ return 0;
+ }
+ const unsigned totalLen = pBootPartKeyInfHead->imgSz;
+ if (totalLen > maxLen) {
+ DWN_ERR("totalLen=0x%x > max=0x%x\n", totalLen, maxLen);
+ return __LINE__;
+ }
+
+ DWN_MSG("totalLen=0x%x\n", totalLen);
+ const unsigned genCrc = crc32(0, (u8*)&pBootPartKeyInfHead->magic,
+ totalLen - sizeof(unsigned int));
+ if (genCrc != pBootPartKeyInfHead->hcrc) {
+ DWN_ERR("genCrc(0x%x) != savedCrc(0x%x), pls clear the card using tool\n",
+ genCrc, pBootPartKeyInfHead->hcrc);
+ return __LINE__;
+ }
+ DWN_MSG("genCrc=0x%x\n", genCrc);
+
+ if (totalLen > firstReadLen)
+ {
+ const unsigned leftLen = totalLen - firstReadLen;
+ sprintf(_cmdBuf, _cmdStr, _OPT_BOOT_PART_LIC_INFO_LOADADDR,
+ AML_BOOT_PART_KEY_HEAD_OFFSET + firstReadLen, leftLen);
+ DWN_MSG("cmd[%s]\n", _cmdBuf);
+ rc = run_command(_cmdBuf, 0);
+ if (rc) {
+ DWN_ERR("Fail in cmd[%s]\n", _cmdBuf);
+ return __LINE__;
+ }
+ }
+
+ return 0;
+}
+
+int optimus_sdc_bootPart_lic_upload(void)
+{
+ const char* _cmdStr = "mmc write 1 0x%x, 0x%x 0x%x";
+ BootPartKeyInf_head_t* pBootPartKeyInfHead = _pOptBootPartLicHeadInf;
+ char _cmdBuf[96];
+ int rc = 0;
+
+ rc = (AML_BOOT_PART_KEY_HEAD_VERSION == pBootPartKeyInfHead->version)
+ && (AML_BOOT_PART_KEY_HEAD_MAGIC == pBootPartKeyInfHead->magic);
+ if (!rc) {
+ DWN_MSG("Ver[0x%x] or magic[0x%8x] error\n",
+ pBootPartKeyInfHead->version, pBootPartKeyInfHead->magic);
+ return __LINE__;
+ }
+
+ rc = run_command("mmcinfo 0", 0);
+ if (rc) {
+ DWN_ERR("Fail to init external sdcard\n");
+ return __LINE__;
+ }
+ DWN_MSG("imgSz=0x%x\n", pBootPartKeyInfHead->imgSz);
+ //Update crc32 in image header
+ const unsigned genCrc = crc32(0, (u8*)&pBootPartKeyInfHead->magic,
+ pBootPartKeyInfHead->imgSz - sizeof(unsigned int));
+ pBootPartKeyInfHead->hcrc = genCrc;
+ DWN_MSG("genCrc=0x%x\n", genCrc);
+
+ const unsigned totalLen = pBootPartKeyInfHead->imgSz;
+ sprintf(_cmdBuf, _cmdStr, _OPT_BOOT_PART_LIC_INFO_LOADADDR, AML_BOOT_PART_KEY_HEAD_OFFSET, totalLen);
+ rc = run_command(_cmdBuf, 0);
+ if (rc) {
+ DWN_ERR("Fail in cmd[%s]\n", _cmdBuf);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+//* keyInfAddr is sizeof the key info
+//
+//*/
+int optimus_sdc_bootPart_lic_get_key_infdata(const char* keyName, void** keyInfAddr)
+{
+ BootPartKeyInf_head_t* pBootPartKeyInfHead = _pOptBootPartLicHeadInf;
+ BootPartKeyInf_Item_t* pBootPartKeyItemInf = (BootPartKeyInf_Item_t*)(pBootPartKeyInfHead + 1);
+ const unsigned itemCnt = pBootPartKeyInfHead->imgItemNum;
+ int rc = 0;
+ int itemIndex = 0;
+
+ *keyInfAddr = NULL;
+
+ DWN_MSG("Get lic info for key[%s]\n", keyName);
+ //2, check _pOptBootPartLicHeadInf
+ rc = (AML_BOOT_PART_KEY_HEAD_VERSION == pBootPartKeyInfHead->version)
+ && (AML_BOOT_PART_KEY_HEAD_MAGIC == pBootPartKeyInfHead->magic);
+ if (!rc) {
+ DWN_MSG("Ver[0x%x] or magic[0x%8x]\n",
+ pBootPartKeyInfHead->version, pBootPartKeyInfHead->magic);
+ return 0;
+ }
+
+ //3, find the item and return the count, return 0 if not found
+ for(itemIndex = 0; itemIndex < itemCnt; ++itemIndex,
+ pBootPartKeyItemInf = (BootPartKeyInf_Item_t*)(pBootPartKeyItemInf->nextItemInfOffset + _OPT_BOOT_PART_LIC_INFO_LOADADDR))
+ {
+ const unsigned char* theKeyName = pBootPartKeyItemInf->keyName;
+
+ rc = memcmp(keyName, theKeyName, strlen(keyName));
+ if (rc) continue;
+ *keyInfAddr = ++pBootPartKeyItemInf;
+ return 0;
+ }
+
+ return 0;
+}
+
+//add an key info item if any, or update it
+int optimus_sdc_bootPart_lic_update_key_inf(const char* keyName, unsigned char* keyVal, unsigned int keyLen)
+{
+ BootPartKeyInf_head_t* pBootPartKeyInfHead = _pOptBootPartLicHeadInf;
+ BootPartKeyInf_Item_t* pBootPartKeyItemInf = (BootPartKeyInf_Item_t*)(pBootPartKeyInfHead + 1);
+ const unsigned itemCnt = pBootPartKeyInfHead->imgItemNum;
+ int rc = 0;
+ int itemIndex = 0;
+
+ DWN_MSG("update lic info for key[%s]\n", keyName);
+ //2, check _pOptBootPartLicHeadInf
+ rc = (AML_BOOT_PART_KEY_HEAD_VERSION == pBootPartKeyInfHead->version)
+ && (AML_BOOT_PART_KEY_HEAD_MAGIC == pBootPartKeyInfHead->magic);
+ if (!rc) {
+ DWN_MSG("Ver[0x%x] or magic[0x%8x]\n",
+ pBootPartKeyInfHead->version, pBootPartKeyInfHead->magic);
+ return __LINE__;
+ }
+
+ BootPartKeyInf_Item_t* prevItemInf = NULL;
+ //3, find the item and return the count, return 0 if not found
+ for(itemIndex = 0; itemIndex < itemCnt; ++itemIndex,
+ prevItemInf = pBootPartKeyItemInf,
+ pBootPartKeyItemInf = (BootPartKeyInf_Item_t*)(pBootPartKeyItemInf->itemSz + (unsigned)pBootPartKeyItemInf))
+ {
+ const unsigned char* theKeyName = pBootPartKeyItemInf->keyName;
+
+ rc = memcmp(keyName, theKeyName, strlen(keyName));
+ if (rc) continue;
+
+ if (AML_BOOT_PART_KEY_ITEM_MAGIC != pBootPartKeyItemInf->magic) {
+ DWN_ERR("Excp: item magic 0x%x eror, must be 0x%x\n",
+ pBootPartKeyItemInf->magic, AML_BOOT_PART_KEY_ITEM_MAGIC);
+ return __LINE__;
+ }
+ //write key founded, update the total data
+ DWN_MSG("Find item at index %d\n", itemIndex);
+ if (pBootPartKeyItemInf->itemSz != keyLen + sizeof(BootPartKeyInf_Item_t)) {
+ DWN_ERR("Excp: oldlen %d != newlen %d\n", pBootPartKeyItemInf->itemSz, keyLen);
+ return __LINE__;
+ }
+ return 0;//To simple it just return
+ }
+ if (prevItemInf)
+ {
+ prevItemInf->nextItemInfOffset = (unsigned)pBootPartKeyItemInf - _OPT_BOOT_PART_LIC_INFO_LOADADDR;
+ }
+
+ if (itemIndex != itemCnt) {
+ DWN_ERR("Exp:itemIndex[%d] != itemCnt[%d]\n", itemIndex, itemCnt);
+ return __LINE__;
+ }
+ memcpy(pBootPartKeyItemInf + 1, keyVal, keyLen);
+ //update item info
+ pBootPartKeyItemInf->itemIndex = itemIndex;
+ pBootPartKeyItemInf->itemSz = keyLen + sizeof(BootPartKeyInf_Item_t);
+ memcpy(pBootPartKeyItemInf->keyName, keyName, strlen(keyName));
+ pBootPartKeyItemInf->version = AML_BOOT_PART_KEY_ITEM_VERSION;
+ pBootPartKeyItemInf->magic = AML_BOOT_PART_KEY_ITEM_MAGIC;
+ //
+ //Update head info
+ pBootPartKeyInfHead->imgSz += keyLen;
+ ++pBootPartKeyInfHead->imgItemNum;
+
+ return 0;
+
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.h b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.h
new file mode 100644
index 0000000000..37503ad806
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_bootPart_license.h
@@ -0,0 +1,70 @@
+/*
+ * \file sdc_bootPart_license.h
+ * \brief Interfaces to read/update license in boot part
+ *
+ * \version 1.0.0
+ * \date 2015/3/10
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2015 Amlogic. All Rights Reserved.
+ *
+ */
+#ifndef __V2_SDC_BURN_SDC_BOOTPART_LICENSE_H__
+#define __V2_SDC_BURN_SDC_BOOTPART_LICENSE_H__
+
+#define AML_BOOT_PART_KEY_HEAD_OFFSET (0x4U<<20)
+#define AML_BOOT_PART_KEY_HEAD_MAGIC 0X2143494C //"LIC!"
+#define AML_BOOT_PART_KEY_HEAD_VERSION 0x01
+#define AML_BOOT_PART_KEY_HEAD_SZ (128)
+#define AML_BOOT_PART_ALIGN_SZ (16)
+
+#define AML_BOOT_PART_KEY_ITEM_MAGIC 0X4D455449 //"ITEM!"
+#define AML_BOOT_PART_KEY_ITEM_VERSION 0x01
+#define AML_BOOT_PART_KEY_ITEM_SZ (128)
+#define AML_BOOT_PART_KEY_ITEM_NAME_LEN 16
+
+#pragma pack(push, 4)
+typedef struct _bootPartKeyInf_head{
+ unsigned int hcrc;
+ unsigned int magic;
+
+ unsigned int version;
+ unsigned int alignSz;
+
+ unsigned int imgSz;
+ unsigned int imgItemNum;
+
+ unsigned char reserv[AML_BOOT_PART_KEY_HEAD_SZ - sizeof(unsigned int) * 6];
+}BootPartKeyInf_head_t;
+#pragma pack(pop)
+
+#pragma pack(push, 4)
+typedef struct _bootPartKeyInf_Item{
+ unsigned int magic;
+ unsigned int version;
+
+ unsigned int itemIndex;
+ unsigned int itemSz;//including this inf head
+
+ unsigned int nextItemInfOffset;
+ unsigned int reserv;
+
+ unsigned char keyName[AML_BOOT_PART_KEY_ITEM_NAME_LEN];
+
+ unsigned char resv1[AML_BOOT_PART_KEY_ITEM_SZ - sizeof(unsigned) * 6 - AML_BOOT_PART_KEY_ITEM_NAME_LEN];
+}BootPartKeyInf_Item_t;
+#pragma pack(pop)
+
+//Read license inf from external emmc boot part
+int optimus_sdc_bootPart_lic_download(void);
+
+//update the license inf to external mmc boot part
+int optimus_sdc_bootPart_lic_upload(void);
+
+int optimus_sdc_bootPart_lic_get_key_infdata(const char* keyName, void** keyInfAddr);
+
+//add an key info item if any, or update it
+int optimus_sdc_bootPart_lic_update_key_inf(const char* keyName, unsigned char* keyVal, unsigned int keyLen);
+
+#endif//ifndef __V2_SDC_BURN_SDC_BOOTPART_LICENSE_H__
+
diff --git a/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_keysprovider.c b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_keysprovider.c
new file mode 100644
index 0000000000..e40ba0e23c
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_sdc_burn/sdc_burnkeys/sdc_keysprovider.c
@@ -0,0 +1,507 @@
+/*
+ * \file sdc_keysprovider.c
+ * \brief Parse users' nankey/efusekey like PC's keysprovider.dll in sdcard burning mode
+ *
+ * \version 1.0.0
+ * \date 2014/12/25
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2014 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../optimus_sdc_burn_i.h"
+#include "sdc_bootPart_license.h"
+
+#define _KEYS_PRV_DBG(fmt...) //DWN_MSG(fmt)
+#define _KEYS_PRV_ITEM_INF_ADDR_4_CONSIST (OPTIMUS_DOWNLOAD_DISPLAY_BUF + 48 * 1024)
+#define _KEYS_PRV_ITEM_INF_ADDR_MISC (OPTIMUS_DOWNLOAD_DISPLAY_BUF + 52 * 1024)
+
+#define _KEY_VAL_TMP_BUF (OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR - OPTIMUS_DOWNLOAD_SLOT_SZ)
+static struct {
+ char* keyBuf;
+ unsigned keySize;
+}_currentKey = {0};
+
+//Note: keys which read only is not need to update license, and so not need stored in boot partition
+//Typedef for keys structs in sdcard boot partition
+#if 1
+#define AML_BOOT_PART_KEY_IMG_OFFSET (0X2U<<20)
+#define AML_BOOT_PART_KEY_IMG_MAGIC_LEN 8
+#define AML_BOOT_PART_KEY_IMG_MAGIC_V1 "AML_KEY!"
+#define AML_BOOT_PART_KEY_IMG_ALIGN_SZ 512
+#define AML_BOOT_PART_KEY_IMG_HEAD_SZ (64)
+
+#define AML_BOOT_PART_KEY_ITEM_INF_LEN (64)
+#define AML_BOOT_PART_KEY_ITEM_NAME_LEN_MAX (16)
+
+//struct for the keys head which stored in boot partition
+#pragma pack(push, 4)
+typedef struct {
+ __u32 crc;
+ __s32 version;
+
+ __u8 magic[AML_BOOT_PART_KEY_IMG_MAGIC_LEN];
+
+ __u32 imgSz;
+ __u32 imgItemNum;
+
+ __u32 alignSz;//512
+ __u8 resrv[AML_BOOT_PART_KEY_IMG_HEAD_SZ - 8 * 3 - 4];
+
+}AmlBootPartKeysHead_t;
+#pragma pack(pop)
+
+#pragma pack(push, 4)
+typedef struct {
+ __u8 keyName[AML_BOOT_PART_KEY_ITEM_NAME_LEN_MAX];
+
+ __u32 itemIndex;
+ __u32 itemSz; //equl to sizeof of each key
+
+ __u32 itemBodyOffset;
+ __u32 itemHasConf;//this item name is configured in keys.conf
+
+ __u8 resrv[32];
+
+}KeyInfo_t;
+#pragma pack(pop)
+
+#define MAX_KEY_INF_NUM 5 //the max key numbers supported at the same time
+
+typedef struct {
+ AmlBootPartKeysHead_t bootPartKeyHead;
+ KeyInfo_t keysInf[MAX_KEY_INF_NUM];
+}BootPartKeyInf_t;
+
+#endif//image for keys END #if 1
+
+#define debugP(fmt...) //printf("L%d:", __LINE__),printf(fmt)
+#define errorP(fmt...) printf("Err[keyspr]L%d:", __LINE__),printf(fmt)
+#define wrnP(fmt...) printf("Wrn[keyspr]L%d:", __LINE__),printf(fmt)
+#define MsgP(fmt...) printf("Msg[keyspr]L%d:", __LINE__),printf(fmt)
+
+#define KEY_MAP_MAGIC 0xeeffaa00
+
+enum {
+ KEY_FMT__MAC = 0XBB, //string format like 00:01:02:03:04:05
+ KEY_FMT__ONLEYONE , //only one format means read the total license file as key value
+ KEY_FMT__HDCP ,
+ KEY_FMT__HDCP2 ,
+};
+
+//Different keyNames can have the same key format
+typedef int (*pFunc_getKeyValByLic)(const char* licensePath, u8* keyVal, unsigned* keyValLen, const char* keyName);
+typedef int (*pFunc_updateLic)(const char* keyName, const char* licensePath);//update the licnese file when burn succeed
+
+typedef struct _keyFmtMapping{
+ unsigned magic;
+ const char* const keyName;
+ const char* const licenseFile;
+ const unsigned keyFmt;
+ pFunc_getKeyValByLic get_key_val;
+ pFunc_updateLic update_license;
+}KeyFmtMap_t;
+
+static int get_key_val_for_fmt_mac(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName);
+static int get_key_val_for_fmt_hdcp(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName);
+static int get_key_val_for_fmt_hdcp2rx(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName);
+static int get_key_val_for_fmt_onlyone(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName);
+
+static int update_lic_for_fmt_mac(const char* keyName, const char* licenseName);
+static int update_lic_for_fmt_hdcp(const char* keyName, const char* licenseName);
+static int update_lic_for_fmt_hdcp2rx(const char* keyName, const char* licenseName);
+
+static const KeyFmtMap_t _keysFmtMapping[] = {
+ /* magic, keyname license file name keyFmt*/
+ [0] = {KEY_MAP_MAGIC, "mac", "license/mac_ether.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac },
+ [1] = {KEY_MAP_MAGIC, "mac_bt", "license/mac_bt.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac },
+ [2] = {KEY_MAP_MAGIC, "mac_wifi", "license/mac_wifi.ini" , KEY_FMT__MAC , get_key_val_for_fmt_mac , update_lic_for_fmt_mac },
+ [3] = {KEY_MAP_MAGIC, "hdcp", "license/HDCP_LIENCE" , KEY_FMT__HDCP , get_key_val_for_fmt_hdcp , update_lic_for_fmt_hdcp },
+ [4] = {KEY_MAP_MAGIC, "hdcp2", "license/HDCP2_LIENCE" , KEY_FMT__HDCP2 , get_key_val_for_fmt_hdcp2rx, update_lic_for_fmt_hdcp2rx},
+ [5] = {KEY_MAP_MAGIC, "secure_boot_set", "license/SECURE_BOOT_SET", KEY_FMT__ONLEYONE, get_key_val_for_fmt_onlyone, NULL},
+};
+#define _SupportKeysNum (sizeof(_keysFmtMapping)/sizeof(KeyFmtMap_t))
+
+#if 1 //mac begin
+static int optimus_sdc_burn_check_mac_ini_set_is_valid(const char* setName)
+{
+ const char* macSets[] = {"Group1", "Group2", "Group3"};
+ const int nSet = sizeof(macSets)/sizeof(char*);
+ int index = 0;
+ int rc = 0;
+
+ for (; index < nSet && !rc; ++index)
+ {
+ rc = !strcmp(setName, macSets[index]);
+ }
+
+ return rc;
+}
+
+typedef struct {
+ char startMac[17 + 3]; //+2 to align 4
+ char endMac[17 + 3]; //+2 to align 4
+ unsigned total;
+ unsigned used;
+}MacGroup_t;
+
+typedef struct {
+ unsigned actualGroup;
+ MacGroup_t groups[3];//max group is 3
+}KeyInf_mac_t;
+
+typedef struct {
+ const char* start;
+ const char* end;
+ unsigned used;
+ unsigned total;//total = end + 1 - start
+}MacCfg_t;
+
+/*static KeyInf_mac_t _bootPart_keyInf_Mac;//Mac key info stored in boot partition*/
+
+static int optimus_update_mac_str_current_val(char* startVal, unsigned used)
+{
+ int i = 0;
+
+ if (17 != strlen(startVal)) {
+ DWN_ERR("start(%s) fmt error.\n", startVal);
+ return __LINE__;
+ }
+
+ MsgP("start[%s], used=%d\n", startVal, used);
+ for (i = 5; i >= 0 && used; --i, (used >>= 8))
+ {
+ char* grp2 = startVal + i * 3;
+ unsigned grp2Val = simple_strtoul(grp2, NULL, 16);
+
+ DWN_DBG("gpp2(%s)grep2=%d, used=%d\n", grp2, grp2Val, used);
+ grp2Val += used & 0xff;
+ if (grp2Val > 0xff)
+ {
+ used += 0x100;
+ grp2Val &= 0xff;
+ }
+ sprintf(grp2, "%02x", grp2Val);
+ DWN_DBG("grp[%d]%s\n", i, grp2);
+ }
+ DWN_MSG("Update mac [%s]\n", startVal);
+
+ return 0;
+}
+
+static int _optimus_get_mac_diff(MacCfg_t* macCfg)
+{
+ const char* start = macCfg->start;
+ const char* end = macCfg->end;
+ __u64 startVal = 0;
+ __u64 endVal = 0;
+ int i = 0;
+
+ for (i = 0; i < 6; ++i, start += 3, end += 3)
+ {
+ startVal += simple_strtoul(start, NULL, 16);
+ endVal += simple_strtoul(end, NULL, 16);
+
+ startVal <<= 8;
+ endVal <<= 8;
+ }
+ startVal >>= 8;
+ endVal >>= 8;
+ DWN_MSG("mac range[%04x%08x, %04x%08x]\n",
+ (unsigned)(startVal>>32), (unsigned)(startVal),
+ (unsigned)(endVal>>32), (unsigned)endVal );
+ macCfg->total = (unsigned)(endVal + 1 - startVal);
+ return 0;
+}
+
+//update the mac value extracted from mac.ini
+//To simplest the case, currently one group is supported
+static int optimus_sdc_burn_parse_mac_ini_key_value(const char* setName, const char* keyName, const char* usrKeyVal)
+{
+ int rc = 0;
+ int grpN = 0;
+ MacCfg_t* currentMacCfg = (MacCfg_t*)_KEYS_PRV_ITEM_INF_ADDR_MISC;
+ char* keyBuf = (char*)_KEY_VAL_TMP_BUF;
+ KeyInf_mac_t* pKeyInf4Consist = (KeyInf_mac_t*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST;
+
+ rc = strncmp("Group", setName, 5) || ( 6 != strlen(setName) );
+ if (rc) {//mac.ini only care Groupn
+ return 0;
+ }
+ grpN = setName[5] - '1'; //'1' not '0'
+ if (grpN > 3) {
+ DWN_ERR("Can only support grp1 ~ grp3 now!, grp[%s] not ok\n", setName);
+ return __LINE__;
+ }
+ pKeyInf4Consist->actualGroup = grpN + 1;
+ MacGroup_t* pKeyConsist = pKeyInf4Consist->groups + grpN;
+
+ _KEYS_PRV_DBG("grp[%d]key=[%s], val=[%s]\n", grpN, keyName, usrKeyVal);
+ //the mac cfg must be in the order: start + end (+used)
+ if (!strcmp("start", keyName))
+ {
+ currentMacCfg->start = usrKeyVal;//value in memory
+ _currentKey.keySize = strlen(usrKeyVal);
+ strcpy(keyBuf, currentMacCfg->start);
+ keyBuf[_currentKey.keySize] = 0;
+ _currentKey.keyBuf = keyBuf;
+ DWN_DBG("keybuf[%s]\n", keyBuf);
+ memcpy(pKeyConsist->startMac, usrKeyVal, strlen(usrKeyVal));
+ }
+ else if (!strcmp("end", keyName))
+ {
+ currentMacCfg->end = usrKeyVal;
+ _currentKey.keySize = strlen(usrKeyVal);
+ _optimus_get_mac_diff(currentMacCfg);
+ memcpy(pKeyConsist->endMac, usrKeyVal, strlen(usrKeyVal));
+ pKeyConsist->total = currentMacCfg->total;
+ }
+ else if(!strcmp("used", keyName))
+ {
+ currentMacCfg->used = simple_strtoul(usrKeyVal, NULL, 0);
+ if (currentMacCfg->used >= currentMacCfg->total) {
+ DWN_ERR("mac used(%d) >= total(%d)\n", currentMacCfg->used , currentMacCfg->total);
+ return __LINE__;
+ }
+ pKeyConsist->used = currentMacCfg->used;
+ }
+
+ if (17 != _currentKey.keySize) {
+ errorP("key size %d of mac(%s) is error, must be 17\n", _currentKey.keySize, usrKeyVal);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
+static int _update_mac_with_cfg_and_bootpart(KeyInf_mac_t* pKeyInf4Consist, KeyInf_mac_t* pKeyInfInBootPart,
+ u8* keyVal, unsigned* keyValLen)
+{
+ const int grpNum = pKeyInf4Consist->actualGroup;
+ MacGroup_t* theMacGrpCfg = NULL;
+ MacGroup_t* theMacGrpInBootPart = NULL;
+ unsigned currentUsed = 0;
+ int i = 0;
+
+ theMacGrpCfg = pKeyInf4Consist->groups;
+ currentUsed = theMacGrpCfg->used;
+ for (; i < grpNum; ++i, ++theMacGrpCfg)
+ {
+ const unsigned leftInCfg = theMacGrpCfg->total - theMacGrpCfg->used;
+ unsigned leftCnt = leftInCfg;
+ if (pKeyInfInBootPart)
+ {
+ theMacGrpInBootPart = pKeyInfInBootPart->groups + i;
+ const unsigned leftInBoot = theMacGrpInBootPart->total - theMacGrpInBootPart->used;
+ DWN_MSG("leftInCfg=%u, leftInBoot=%u, used=%u\n", leftCnt, leftInBoot, theMacGrpInBootPart->used);
+ if (leftCnt < leftInBoot) {
+ DWN_ERR("Excp:leftInCfg[%u] < leftInBoot[%u]\n", leftCnt, leftInBoot);
+ return __LINE__;
+ }
+ if (theMacGrpInBootPart->total != theMacGrpCfg->total) {
+ DWN_ERR("Excp:cfg total[%u] != boot total[%u]\n",
+ theMacGrpCfg->total, theMacGrpInBootPart->total);
+ return __LINE__;
+ }
+ currentUsed = ++theMacGrpInBootPart->used;//used is saved by prev burned
+ }
+ if (currentUsed < theMacGrpCfg->total) {//Find it
+ DWN_MSG("Found available at grp[%d], total=%u, used=%u\n",
+ i, theMacGrpCfg->total, currentUsed);
+ break;
+ }
+ }
+
+ if (i == grpNum) {
+ DWN_ERR("Can't find available grp,i=%d\n", i);
+ return __LINE__;
+ }
+
+ *keyValLen = strlen(theMacGrpCfg->startMac);
+ memcpy(keyVal, theMacGrpCfg->startMac, *keyValLen);
+ i = optimus_update_mac_str_current_val((char*)keyVal, currentUsed);
+ return i;
+}
+
+//step 1: parsing license/mac.ini to get 'start' and 'used'
+//step 2: search the key info in the boot key, if not existed , then append the keyinfo and update total count
+//step 3: check the 'start' and 'used' is same as which in the boot partition if existed
+//step 3: get the count recorded in the uboot partition
+static int get_key_val_for_fmt_mac(const char* licPath, u8* keyVal, unsigned* keyValLen, const char* keyName)
+{
+ const int MaxLines = 256;//
+ char* lines[MaxLines];
+ int rc = __LINE__;
+ int validLineNum = 0;
+ KeyInf_mac_t* pKeyInfInBootPart = NULL;
+ KeyInf_mac_t* pKeyInf4Consist = (KeyInf_mac_t*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST;
+
+ memset(pKeyInf4Consist, 0, sizeof(KeyInf_mac_t));
+ validLineNum = parse_ini_file_2_valid_lines(licPath, (char*)keyVal, *keyValLen, lines);
+ if (!validLineNum) {
+ DWN_ERR("error in parse ini file\n");
+ return __LINE__;
+ }
+
+ rc = optimus_ini_trans_lines_2_usr_params((const char* *)lines, validLineNum,
+ optimus_sdc_burn_check_mac_ini_set_is_valid,
+ optimus_sdc_burn_parse_mac_ini_key_value);
+ if (rc) {
+ DWN_ERR("Fail in get cfg from %s\n", licPath);
+ return __LINE__;
+ }
+ *keyValLen = _currentKey.keySize;
+ memcpy(keyVal, _currentKey.keyBuf, _currentKey.keySize);
+ keyVal[_currentKey.keySize] = 0;
+
+#if 1
+ rc = optimus_sdc_bootPart_lic_get_key_infdata(keyName, (void**)&pKeyInfInBootPart);
+ if (rc) {
+ DWN_ERR("Fail in get key inf from boot part\n");
+ return __LINE__;
+ }
+#endif
+ rc = _update_mac_with_cfg_and_bootpart(pKeyInf4Consist, pKeyInfInBootPart, keyVal, keyValLen);
+
+ return rc;
+}
+
+static int update_lic_for_fmt_mac(const char* keyName, const char* licenseName)
+{
+ int rc = 0;
+
+ rc = optimus_sdc_bootPart_lic_update_key_inf(keyName, (u8*)_KEYS_PRV_ITEM_INF_ADDR_4_CONSIST, sizeof(KeyInf_mac_t));
+
+ return rc;
+}
+#endif//MAC
+
+
+static int get_key_val_for_fmt_hdcp(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName)
+{
+ int rc = __LINE__;
+
+
+ return rc;
+}
+
+static int get_key_val_for_fmt_hdcp2rx(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName)
+{
+ int rc = __LINE__;
+
+
+ return rc;
+}
+
+static int get_key_val_for_fmt_onlyone(const char* licenseName, u8* keyVal, unsigned* keyValLen, const char* keyName)
+{
+ int rc = 0;
+ char _cmd[96];
+
+ optimus_sdc_burn_switch_to_extmmc();
+ sprintf(_cmd, "fatexist mmc 0:1 %s", licenseName);
+ rc = run_command(_cmd, 0);
+ if (rc) {
+ errorP("file[%s] is not existed\n", licenseName);
+ return __LINE__;
+ }
+
+ sprintf(_cmd, "fatload mmc 0:1 0x%p %s", keyVal, licenseName);
+ rc = run_command(_cmd, 0);
+ if (rc) {
+ errorP("failed in cmd[%s]\n", _cmd);
+ return __LINE__;
+ }
+
+ *keyValLen = simple_strtoul(getenv("filesize"), NULL, 16);
+
+ return rc;
+}
+
+static int update_lic_for_fmt_hdcp(const char* keyName, const char* licenseName)
+{
+ int rc = 0;
+
+
+ return rc;
+}
+
+static int update_lic_for_fmt_hdcp2rx(const char* keyName, const char* licenseName)
+{
+ int rc = 0;
+
+
+ return rc;
+}
+
+int optimus_sdc_keysprovider_init(void)
+{
+ return optimus_sdc_bootPart_lic_download();
+}
+
+int optimus_sdc_keysprovider_exit(void)
+{
+
+ return optimus_sdc_bootPart_lic_upload();
+}
+
+//check whether the key license is existed and supported
+//keyName is getted from keys.conf in package like PC burning tool
+int optimus_sdc_keysprovider_open(const char* keyName, const void** pHdle)
+{
+ int i = 0;
+ int rc = __LINE__;
+
+ const KeyFmtMap_t* pMappedKey = &_keysFmtMapping[0];
+ for (i=0; i < _SupportKeysNum; ++i, ++pMappedKey) {
+ rc = strcmp(keyName, pMappedKey->keyName);
+ if (rc) continue;//keyName not mapped
+ *pHdle = pMappedKey;
+ return 0;
+ }
+
+ return rc;
+}
+
+int optimus_sdc_keysprovider_get_keyval(const void* pHdle, u8* pBuf, unsigned* keySz)
+{
+ const KeyFmtMap_t* pMappedKey = (const KeyFmtMap_t*)pHdle;
+ const char* const keyName = pMappedKey->keyName;
+ const char* licPath = pMappedKey->licenseFile;
+ int rc = 0;
+
+ if (KEY_MAP_MAGIC != pMappedKey->magic) {
+ errorP("magic should be %x, but %x\n", KEY_MAP_MAGIC, pMappedKey->magic);
+ return __LINE__;
+ }
+ rc = pMappedKey->get_key_val(licPath, pBuf, keySz, keyName);
+ if (rc) {
+ errorP("Fail in getKeyVal for key[%s] at lic path[%s]\n", keyName, licPath);
+ return __LINE__;
+ }
+
+ return rc;
+}
+
+int optimus_sdc_keysprovider_update_license(const void* pHdle)
+{
+ const KeyFmtMap_t* pMappedKey = (const KeyFmtMap_t*)pHdle;
+ const char* const keyName = pMappedKey->keyName;
+ const char* licPath = pMappedKey->licenseFile;
+ int rc = 0;
+
+ if (KEY_MAP_MAGIC != pMappedKey->magic) {
+ errorP("magic should be %x, but %x\n", KEY_MAP_MAGIC, pMappedKey->magic);
+ return __LINE__;
+ }
+ if (!pMappedKey->update_license) return 0;
+
+ rc = pMappedKey->update_license(keyName, licPath);
+ if (rc) {
+ errorP("Fail in getKeyVal for key[%s] at lic path[%s]\n", keyName, licPath);
+ return __LINE__;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_burn.c b/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_burn.c
new file mode 100644
index 0000000000..77ca54e50c
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_burn.c
@@ -0,0 +1,80 @@
+/*
+ * \file optimus_usb_burn.c
+ * \brief burning itself from Pheripheral usb host
+ *
+ * \version 1.0.0
+ * \date 2014-9-15
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ * Chunyu.Song <chunyu.song@amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../v2_sdc_burn/optimus_sdc_burn_i.h"
+#include "../v2_sdc_burn/optimus_led.h"
+
+extern int optimus_burn_with_cfg_file(const char* cfgFile);
+
+// added by scy
+int optimus_burn_package_in_usb(const char* sdc_cfg_file)
+{
+ int rcode = 0;
+
+ DWN_MSG("usb start\n");
+ rcode = run_command("usb start", 0);
+ if (rcode) {
+ DWN_ERR("Fail in init usb host, Does usb host not plugged in?\n");
+ return __LINE__;
+ }
+
+#if 0//this asserted by 'run update' and 'aml_check_is_ready_for_sdc_produce'
+ rcode = do_fat_get_fileSz(sdc_cfg_file);
+ if (!rcode) {
+ printf("The [%s] not exist in bootable mmc card\n", sdc_cfg_file);
+ return __LINE__;
+ }
+#endif//#if 0
+
+ rcode = optimus_burn_with_cfg_file(sdc_cfg_file);
+
+ return rcode;
+}
+
+
+// added by scy
+int do_usb_burn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+
+ int rcode = 0;
+ const char* sdc_cfg_file = argv[1];
+
+ setenv("usb_update","1");
+
+ if (argc < 2 ) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_SDC_UPDATE);
+ show_logo_to_report_burning();//indicate enter flow of burning! when 'run update'
+ if (optimus_led_open(LED_TYPE_PWM)) {
+ DWN_ERR("Fail to open led for burn\n");
+ return __LINE__;
+ }
+ optimus_led_show_in_process_of_burning();
+
+ rcode = optimus_burn_package_in_usb(sdc_cfg_file);
+
+ return rcode;
+}
+
+// added by scy
+U_BOOT_CMD(
+ usb_burn, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_usb_burn, //command function
+ "Burning with amlogic format package in usb ", //description
+ "argv: [sdc_burn_cfg_file]\n"//usage
+ " -aml_sdc_burn.ini is usually used configure file\n"
+);
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_update.c b/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_update.c
new file mode 100644
index 0000000000..d31f51bd22
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_burn/optimus_usb_update.c
@@ -0,0 +1,131 @@
+/*
+ * \file optimus_usb_update.c
+ * \brief usb_update command to burn a parition image from usb host
+ * this update based on the burner is latest: (uboot for burnner can run from peripherals such as sdmmc/usb)
+ *
+ * \version 1.0.0
+ * \date 2014-9-15
+ * \author Chunyu.Song<chunyu.song@amlogic.com>
+ * Sam.Wu <yihui.wu@amlogic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#include "../v2_sdc_burn/optimus_sdc_burn_i.h"
+
+typedef int __hFileHdl;
+
+#define BURN_DBG 0
+#if BURN_DBG
+#define SDC_DBG(fmt...) printf(fmt)
+#else
+#define SDC_DBG(fmt...)
+#endif//if BURN_DBG
+
+#define SDC_MSG DWN_MSG
+#define SDC_ERR DWN_ERR
+
+//static char _errInfo[512] = "";
+// count usb start,to reduce the time-consuming of excuting usb start
+int usb_start_count = 0;
+
+//step 1: get script file size, and get script file contents
+//step 2: read image file
+//"Usage: usb_update partiton image_file_path [imgFmt, verifyFile]\n" //usage
+int do_usb_update(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rcode = 0;
+
+ const char* partName = argv[1];
+ const char* imgItemPath = argv[2];
+ const char* fileFmt = argc > 3 ? argv[3] : NULL;
+ const char* verifyFile = argc > 4 ? argv[4] : NULL;
+
+ setenv("usb_update", "1");
+ printf("usb_start_count %d\n", usb_start_count);
+#if BURN_DBG
+ printf("argc %d, %s, %s\n", argc, argv[0], argv[1]);
+ if (argc < 3)
+ {
+ partName = "system";
+ imgItemPath = "rec.img";
+ fileFmt = "normal";
+ verifyFile = "recovery.verify";
+ }
+#else
+ if (argc < 3) {
+ cmd_usage(cmdtp);
+ return __LINE__;
+ }
+#endif//#if BURN_DBG
+
+if (usb_start_count == 0)
+{
+ //usb start to ensure usb host inserted and inited
+ rcode = run_command("usb start", 0);
+ usb_start_count++;
+ if (rcode) {
+ SDC_ERR("Fail in init usb, Does usb host not plugged in?\n");
+ return __LINE__;
+ }
+}
+
+#if 0
+ if (!do_fat_get_fileSz(imgItemPath)) {
+ SDC_ERR("file (%s) not existed\n", imgItemPath);
+ return __LINE__;
+ }
+#else
+ rcode = optimus_device_probe("usb", "0");
+/*
+ if (rcode) {
+ SDC_ERR("Fail to detect device usb 0\n");
+ return __LINE__;
+ }
+ */
+#endif//#if 0
+
+ if (!fileFmt)
+ {
+ rcode = do_fat_get_file_format(imgItemPath, (u8*)OPTIMUS_DOWNLOAD_TRANSFER_BUF_ADDR, (8*1024));
+ if (rcode < 0) {
+ SDC_ERR("Fail when parse file format\n");
+ return __LINE__;
+ }
+ fileFmt = rcode ? "sparse" : "normal";
+ }
+
+#if 0
+ if (!getenv("disk_initial")) //if disk_initial command not executed for burning
+ {
+ rcode = optimus_storage_init(0);//can't erase as not full updating
+ if (rcode) {
+ SDC_ERR("Fail in init storage, rcode %d\n", rcode);
+ return rcode;
+ }
+ setenv("disk_initial", "0");
+ }
+#endif//#if 0
+
+ rcode = optimus_burn_partition_image(partName, imgItemPath, fileFmt, verifyFile, 0);
+ if (rcode) {
+ SDC_ERR("Fail to burn partition (%s) with image file (%s) in format (%s)\n", partName, imgItemPath, fileFmt);
+ }
+
+ return rcode;
+}
+
+U_BOOT_CMD(
+ usb_update, //command name
+ 5, //maxargs
+ 0, //repeatable
+ do_usb_update, //command function
+ "Burning a partition with image file in usb host", //description
+ " argv: <part_name> <image_file_path> <[,fileFmt]> <[,verify_file]> \n" //usage
+ " - <fileFmt> parameter is optional, if you know it you can specify it.\n"
+ " for Android, system.img and data.img is \"sparse\" format, other is \"normal\"\n" //usage
+ " - <verify_file> parameter is optional, if you have it you can specify it.\n"
+ " - e.g. \n"
+ " to burn partition boot with boot.img of usb 0 : \"usb_update boot boot.img\"\n" //usage
+ " to burn partition system with system.img of usb 0 : \"usb_update system system.img\"\n" //usage
+);
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.c
new file mode 100644
index 0000000000..f1a8e31bab
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.c
@@ -0,0 +1,739 @@
+/* dwc controller pcd drivers */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ *
+ */
+#include "../v2_burning_i.h"
+#include "platform.h"
+#include "usb_ch9.h"
+#include "dwc_pcd.h"
+#include "dwc_pcd_irq.h"
+
+pcd_struct_t this_pcd ;//FIXME:This PCD should point to different or cause bug!!
+
+dwc_ep_t g_dwc_eps[NUM_EP];
+
+int dwc_core_init(void)
+{
+ gotgctl_data_t gctrldata;
+ int32_t snpsid;
+
+ memset(&this_pcd, 0, sizeof(this_pcd));
+
+ DBG("DWC_REG_GSNPSID 0x%x\n", DWC_REG_GSNPSID+DWC_REG_BASE);
+ snpsid = dwc_read_reg32(DWC_REG_GSNPSID);
+
+ if ( !( 0x4F542000 == (snpsid & 0xFFFFF000) || 0x4F543000 == (snpsid & 0xFFFFF000) ) ) {
+ printf("%s,Bad value for SNPSID: 0x%08x\n", __func__, snpsid);
+ return -1;
+ }
+
+#if 1
+ /*GOTGCTL*/
+ gctrldata.d32 = dwc_read_reg32(DWC_REG_GOTGCTL);//Can this GOTGCTL read before dwc_otg_core_init() ??
+ if (!gctrldata.b.asesvld || !gctrldata.b.bsesvld) {
+ printf("GOTGCTL=0x%08x, asesvld=%x, bsesvld=%x\n",
+ gctrldata.d32, gctrldata.b.asesvld, gctrldata.b.bsesvld);
+ return __LINE__;
+
+ }
+#endif//
+
+ DBG("dwc core init is ok!\n");// show printf is ok.
+ /*
+ * Disable the global interrupt until all the interrupt
+ * handlers are installed.
+ */
+ gahbcfg_data_t ahbcfg = {.d32 = 0 };
+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts bit */
+ dwc_modify_reg32(DWC_REG_GAHBCFG, ahbcfg.d32, 0);
+ /*
+ * Initialize the DWC_otg core.
+ */
+ dwc_otg_core_init();
+
+ dwc_modify_reg32(DWC_REG_DCTL,0,2);// Disconnect data line
+ dwc_otg_pcd_init();
+ dwc_modify_reg32(DWC_REG_DCTL,2,0);// Connect data line
+
+ /*
+ * Enable the global interrupt after all the interrupt
+ * handlers are installed.
+ */
+ dwc_otg_enable_global_interrupts();
+
+ return 0;
+}
+
+int dwc_otg_irq(void)
+{
+ int ret1,ret2;
+
+ ret1 = dwc_common_irq();
+ ret2 = dwc_pcd_irq();
+ return (ret1+ret2);
+}
+
+void dwc_otg_pullup(int is_on)
+{
+ if (is_on)
+ dwc_modify_reg32(DWC_REG_DCTL,2,0);// connect data line
+ else dwc_modify_reg32(DWC_REG_DCTL,0,2);// disconnect data line
+}
+static void dwc_otg_core_init() //Elvis Fool, add 'static'
+{
+ gahbcfg_data_t ahbcfg = {.d32 = 0 };
+ gusbcfg_data_t usbcfg = {.d32 = 0 };
+ // gi2cctl_data_t i2cctl = {.d32 = 0 };
+// hcfg_data_t hcfg;
+#ifndef USE_FULL_SPEED
+ usbcfg.d32 = dwc_read_reg32(DWC_REG_GUSBCFG);
+
+ usbcfg.b.ulpi_ext_vbus_drv = 0;
+ usbcfg.b.term_sel_dl_pulse = 0;
+ dwc_write_reg32(DWC_REG_GUSBCFG,usbcfg.d32);
+#endif
+ /*
+ * Reset the Controller
+ */
+ dwc_otg_core_reset();
+
+ usbcfg.d32 = dwc_read_reg32(DWC_REG_GUSBCFG);
+ usbcfg.b.srpcap = 0;
+ usbcfg.b.hnpcap = 0;
+#ifdef USE_FULL_SPEED
+ dcfg_data_t dcfg;
+ printf("Full Speed\n");
+ usbcfg.b.physel = 1; // Work at full speed
+ dwc_write_reg32(DWC_REG_GUSBCFG, usbcfg.d32);
+
+ dwc_otg_core_reset();
+/* for HOST
+ hcfg.d32 = dwc_read_reg32(DWC_REG_ hcfg);
+ hcfg.b.fslspclksel = val;
+ dwc_write_reg32(&_core_if->host_if->host_global_regs->hcfg, hcfg.d32);
+*/
+// for Device
+ dcfg.d32 = dwc_read_reg32(DWC_REG_DCFG);
+ dcfg.b.devspd = 1;//Hi speed phy run at Full speed
+ dwc_write_reg32(DWC_REG_DCFG, dcfg.d32);
+#else
+ DBG("High Speed\n");
+ usbcfg.b.ulpi_utmi_sel = 1;
+ usbcfg.b.phyif = 0; // 16 bit
+ usbcfg.b.ddrsel = 0;
+ dwc_write_reg32(DWC_REG_GUSBCFG, usbcfg.d32);
+
+ dwc_otg_core_reset();
+#endif
+ ahbcfg.b.dmaenable = 0;
+ dwc_write_reg32(DWC_REG_GAHBCFG, ahbcfg.d32);
+
+
+ /*
+ * Enable common interrupts
+ */
+ dwc_otg_enable_common_interrupts();
+
+ /*
+ * Do device or host intialization based on mode during PCD and HCD
+ * initialization
+ */
+ if (dwc_read_reg32(DWC_REG_GINTSTS) & 0x1) {
+ DBG("Host Mode\n");
+ return ;
+ } else {
+ DBG("Device Mode\n");
+ dwc_otg_core_dev_init();
+ }
+
+}
+
+/**
+ * This function initialized the PCD portion of the driver.
+ *
+ */
+static int dwc_otg_pcd_init()
+{
+ return 0;
+}
+
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+static void dwc_otg_core_reset(void) //Elvis Fool, add 'static'
+{
+ grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ /*
+ * Wait for AHB master IDLE state.
+ */
+ do {
+ udelay(10);
+ greset.d32 = dwc_read_reg32(DWC_REG_GRSTCTL);
+ if (++count > 100000) {
+ //DBG("%s() HANG! AHB Idle GRSTCTL=%0x\n", dwc_otg_core_reset, greset.d32);
+ return;
+ }
+ }
+ while (greset.b.ahbidle == 0);
+
+ /*
+ * Core Soft Reset
+ */
+ count = 0;
+ greset.b.csftrst = 1;
+ dwc_write_reg32(DWC_REG_GRSTCTL, greset.d32);
+ do {
+ greset.d32 = dwc_read_reg32(DWC_REG_GRSTCTL);
+ if (++count > 1000000) {
+ //DBG("%s() HANG! Soft Reset GRSTCTL=%0x\n", dwc_otg_core_reset, greset.d32);
+ break;
+ }
+ }
+ while (greset.b.csftrst == 1);
+
+ /*
+ * Wait for 3 PHY Clocks
+ */
+ wait_ms(10);
+}
+
+static void dwc_otg_enable_common_interrupts()
+{
+ gintmsk_data_t intr_mask = { 0};
+ /* Clear any pending OTG Interrupts */
+ dwc_write_reg32(DWC_REG_GOTGINT, 0xFFFFFFFF);
+ /* Clear any pending interrupts */
+ dwc_write_reg32(DWC_REG_GINTSTS, 0xFFFFFFFF);
+ /*
+ * Enable the interrupts in the GINTMSK.
+ */
+ intr_mask.b.modemismatch = 1;
+ intr_mask.b.otgintr = 1;
+ intr_mask.b.rxstsqlvl = 1;
+ intr_mask.b.conidstschng = 1;
+ intr_mask.b.wkupintr = 1;
+ intr_mask.b.disconnect = 1;
+ intr_mask.b.usbsuspend = 1;
+ intr_mask.b.sessreqintr = 1;
+ dwc_write_reg32(DWC_REG_GINTMSK, intr_mask.d32);
+}
+
+/**
+ * This function enables the Device mode interrupts.
+ *
+ * @param _core_if Programming view of DWC_otg controller
+ */
+static void dwc_otg_enable_device_interrupts()
+{
+ gintmsk_data_t intr_mask = { 0};
+
+ /* Disable all interrupts. */
+ dwc_write_reg32( DWC_REG_GINTMSK, 0);
+
+ /* Clear any pending interrupts */
+ dwc_write_reg32( DWC_REG_GINTSTS, 0xFFFFFFFF);
+
+ /* Enable the common interrupts */
+ dwc_otg_enable_common_interrupts( );
+
+ /* Enable interrupts */
+ intr_mask.b.usbreset = 1;
+ intr_mask.b.enumdone = 1;
+ intr_mask.b.epmismatch = 1;
+ intr_mask.b.inepintr = 1;
+ intr_mask.b.outepintr = 1;
+ intr_mask.b.erlysuspend = 1;
+
+ dwc_modify_reg32( DWC_REG_GINTMSK, intr_mask.d32, intr_mask.d32);
+
+}
+/**
+ * This function enables the controller's Global Interrupt in the AHB Config
+ * register.
+ *
+ * @param[in] _core_if Programming view of DWC_otg controller.
+ */
+static void dwc_otg_enable_global_interrupts( )
+{
+ gahbcfg_data_t ahbcfg = { 0};
+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
+ dwc_modify_reg32(DWC_REG_GAHBCFG, 0, ahbcfg.d32);
+}
+
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ *
+ * @param _core_if Programming view of DWC_otg controller
+ *
+ */
+static void dwc_otg_core_dev_init(void)
+{
+ dcfg_data_t dcfg = { 0};
+ grstctl_t resetctl = { 0 };
+ int i;
+ fifosize_data_t nptxfifosize;
+
+ /* Restart the Phy Clock */
+ dwc_write_reg32(DWC_REG_PCGCCTL, 0);
+
+ /* Device configuration register */
+ dcfg.d32 = dwc_read_reg32(DWC_REG_DCFG);
+#ifdef USE_FULL_SPEED
+ dcfg.b.devspd = 1;//Hi speed phy run at Full speed
+#else
+ dcfg.b.devspd = 0;
+#endif
+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+ dwc_write_reg32(DWC_REG_DCFG, dcfg.d32);
+
+ /* Configure data FIFO sizes */
+
+ /* Rx FIFO */
+ dwc_write_reg32(DWC_REG_GRXFSIZ, 256 );
+ //DBG("new grxfsiz=%08x\n",dwc_read_reg32(DWC_REG_GRXFSIZ));
+
+ /* Non-periodic Tx FIFO */
+ nptxfifosize.b.depth = 256;
+ nptxfifosize.b.startaddr = 256;
+ dwc_write_reg32(DWC_REG_GNPTXFSIZ, nptxfifosize.d32 );
+ //DBG("new gnptxfsiz=%08x\n",dwc_read_reg32(DWC_REG_GNPTXFSIZ));
+
+ /* Flush the FIFOs */
+ dwc_otg_flush_tx_fifo( 0x10); /* all Tx FIFOs */
+ dwc_otg_flush_rx_fifo();
+
+ /* Flush the Learning Queue. */
+ resetctl.b.intknqflsh = 1;
+ dwc_write_reg32( DWC_REG_GRSTCTL, resetctl.d32);
+
+ /* Clear all pending Device Interrupts */
+ dwc_write_reg32( DWC_REG_DIEPMSK, 0 );
+ dwc_write_reg32( DWC_REG_DOEPMSK, 0 );
+ dwc_write_reg32( DWC_REG_DAINT, 0xFFFFFFFF );
+ dwc_write_reg32( DWC_REG_DAINTMSK, 0 );
+
+ for (i=0; i < NUM_EP; i++) {
+ depctl_data_t depctl;
+ depctl.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(i));
+ if (depctl.b.epena) {
+ depctl.d32 = 0;
+ depctl.b.epdis = 1;
+ depctl.b.snak = 1;
+ } else {
+ depctl.d32 = 0;
+ }
+ dwc_write_reg32( DWC_REG_IN_EP_REG(i),depctl.d32);
+
+ depctl.d32 = dwc_read_reg32(DWC_REG_OUT_EP_REG(i));
+ if (depctl.b.epena) {
+ depctl.d32 = 0;
+ depctl.b.epdis = 1;
+ depctl.b.snak = 1;
+ } else {
+ depctl.d32 = 0;
+ }
+ dwc_write_reg32( DWC_REG_OUT_EP_REG(i), depctl.d32);
+
+ /* Device IN/OUT Endpoint Transfer Size */
+ dwc_write_reg32(DWC_REG_IN_EP_TSIZE(i), 0);
+ dwc_write_reg32(DWC_REG_OUT_EP_TSIZE(i), 0);
+ /* Device IN/OUT Endpoint DMA Address Register */
+ dwc_write_reg32( DWC_REG_IN_EP_DMA(i), 0);
+ dwc_write_reg32( DWC_REG_OUT_EP_DMA(i), 0);
+ /* Device IN/OUT Endpoint Interrupt Register */
+ //dwc_write_reg32( DWC_REG_IN_EP_DMA(i), 0xFF);
+ //dwc_write_reg32( DWC_REG_OUT_EP_INTR(i), 0xFF);
+ }
+
+ //d wc_otg_set_vbus_power(_core_if, 0); //Power off VBus
+
+ dwc_otg_enable_device_interrupts();
+
+ DBG("init gintmsk: 0x%x\n",dwc_read_reg32(DWC_REG_GINTMSK));
+}
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param _core_if Programming view of DWC_otg controller.
+ * @param _num Tx FIFO to flush.
+ */
+static void dwc_otg_flush_tx_fifo( const int _num ) //Elvis Fool, add 'static'
+{
+ grstctl_t greset = { 0};
+ int count = 0;
+
+
+ DBG("dwc_otg_flush_tx_fifo: %d\n",_num);
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = _num;
+ dwc_write_reg32(DWC_REG_GRSTCTL, greset.d32 );
+
+ do {
+ greset.d32 = dwc_read_reg32( DWC_REG_GRSTCTL);
+ if (++count > 10000) {
+ // ERR("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
+ // "dwc_otg_flush_tx_fifo", greset.d32,
+ // dwc_read_reg32( DWC_REG_GNPTXSTS));
+ break;
+ }
+
+ } while (greset.b.txfflsh == 1);
+ /* Wait for 3 PHY Clocks*/
+ udelay(1);
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param _core_if Programming view of DWC_otg controller.
+ */
+static void dwc_otg_flush_rx_fifo( )
+{
+ grstctl_t greset = { 0};
+ int count = 0;
+
+ DBG("dwc_otg_flush_rx_fifo\n");
+ greset.b.rxfflsh = 1;
+ dwc_write_reg32( DWC_REG_GRSTCTL, greset.d32 );
+
+ do {
+ greset.d32 = dwc_read_reg32( DWC_REG_GRSTCTL);
+ if (++count > 10000) {
+ //ERR("%s() HANG! GRSTCTL=%0x\n", "dwc_otg_flush_rx_fifo",
+ // greset.d32);
+ break;
+ }
+ } while (greset.b.rxfflsh == 1);
+ /* Wait for 3 PHY Clocks*/
+ udelay(1);
+}
+/**
+ * This function does the setup for a data transfer for EP0 and starts
+ * the transfer. For an IN transfer, the packets will be loaded into
+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
+ * unloaded from the Rx FIFO in the ISR.
+ *
+ * @param _core_if Programming view of DWC_otg controller.
+ * @param _ep The EP0 data.
+ */
+ #if 0
+void dwc_otg_ep0_start_transfer(dwc_ep_t *_ep)
+{
+ depctl_data_t depctl;
+ deptsiz0_data_t deptsiz;
+ gintmsk_data_t intr_mask = { 0};
+
+ _ep->total_len = _ep->xfer_len;
+
+ //DBG("dwc_otg_ep0_start_transfer: xfer_len:%d\n",_ep->xfer_len);
+ /* IN endpoint */
+ if (_ep->is_in == 1) {
+ gnptxsts_data_t tx_status = { 0};
+
+ tx_status.d32 = dwc_read_reg32(DWC_REG_GNPTXSTS);
+ if (tx_status.b.nptxqspcavail == 0) {
+ return;
+ }
+
+ depctl.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(0));
+ deptsiz.d32 = dwc_read_reg32(DWC_REG_IN_EP_TSIZE(0));
+
+ /* Zero Length Packet? */
+ if (_ep->xfer_len == 0) {
+ deptsiz.b.xfersize = 0;
+ deptsiz.b.pktcnt = 1;
+ } else {
+ /* Program the transfer size and packet count
+ * as follows: xfersize = N * maxpacket +
+ * short_packet pktcnt = N + (short_packet
+ * exist ? 1 : 0)
+ */
+ if (_ep->xfer_len > _ep->maxpacket) {
+ _ep->xfer_len = _ep->maxpacket;
+ deptsiz.b.xfersize = _ep->maxpacket;
+ }
+ else {
+ deptsiz.b.xfersize = _ep->xfer_len;
+ }
+ deptsiz.b.pktcnt = 1;
+
+ }
+ dwc_write_reg32(DWC_REG_IN_EP_TSIZE(0), deptsiz.d32);
+ //DBG( "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
+ // _ep->xfer_len,deptsiz.b.xfersize, deptsiz.b.pktcnt, deptsiz.d32);
+
+
+ flush_cpu_cache();
+
+ /* EP enable, IN data in FIFO */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ dwc_write_reg32(DWC_REG_IN_EP_REG(0), depctl.d32);
+
+ /**
+ * Enable the Non-Periodic Tx FIFO empty interrupt, the
+ * data will be written into the fifo by the ISR.
+ */
+
+ /* First clear it from GINTSTS */
+ intr_mask.b.nptxfempty = 1;
+ dwc_modify_reg32( DWC_REG_GINTSTS,intr_mask.d32, 0);
+ dwc_modify_reg32( DWC_REG_GINTMSK,intr_mask.d32, intr_mask.d32);
+
+
+ } else { /* OUT endpoint */
+
+ depctl.d32 = dwc_read_reg32(DWC_REG_OUT_EP_REG(0));
+ deptsiz.d32 = dwc_read_reg32(DWC_REG_OUT_EP_TSIZE(0));
+
+ /* Program the transfer size and packet count as follows:
+ * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
+ * pktcnt = N */
+#if 0
+ if (_ep->xfer_len == 0) {
+ /* Zero Length Packet */
+ deptsiz.b.xfersize = _ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ } else {
+ deptsiz.b.pktcnt =
+ (_ep->xfer_len + (_ep->maxpacket - 1)) /_ep->maxpacket;
+ deptsiz.b.xfersize = deptsiz.b.pktcnt * _ep->maxpacket;
+ }
+#else // ep0 pktcnt is 1 bit
+
+ deptsiz.b.xfersize = _ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ udelay(1); // This is needed, don't know reason.
+#endif
+
+
+ dwc_write_reg32(DWC_REG_OUT_EP_TSIZE(0), deptsiz.d32);
+ //DBG( "OUT len=%d xfersize=%d pktcnt=%d\n",
+ // _ep->xfer_len,deptsiz.b.xfersize, deptsiz.b.pktcnt);
+
+
+ /* EP enable */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ dwc_write_reg32 (DWC_REG_OUT_EP_REG(0), depctl.d32);
+ }
+
+ flush_cpu_cache();
+}
+ #endif
+
+void dwc_otg_ep_start_transfer(dwc_ep_t *_ep)
+{
+ depctl_data_t depctl;
+ deptsiz_data_t deptsiz;
+ int epctl_reg,epctltsize_reg;
+ int ep_num = _ep->num;
+ int is_in = _ep->is_in;
+ int ep_mps = _ep->maxpacket;
+
+ //DBG("dwc_otg_ep_start_transfer: xfer_len:%d\n",_ep->xfer_len);
+
+ _ep->total_len = _ep->xfer_len;
+
+ if (is_in) {
+ epctl_reg = DWC_REG_IN_EP_REG(ep_num);
+ epctltsize_reg = DWC_REG_IN_EP_TSIZE(ep_num);
+ }else{
+ epctl_reg = DWC_REG_OUT_EP_REG(ep_num);
+ epctltsize_reg = DWC_REG_OUT_EP_TSIZE(ep_num);
+ }
+
+ depctl.d32 = dwc_read_reg32(epctl_reg);
+ deptsiz.d32 = dwc_read_reg32(epctltsize_reg);
+
+ /* Zero Length Packet? */
+ if (_ep->xfer_len == 0) {
+ deptsiz.b.xfersize = is_in?0:ep_mps;
+ deptsiz.b.pktcnt = 1;
+ }
+ else {
+ deptsiz.b.pktcnt = (_ep->xfer_len + (ep_mps - 1)) /ep_mps;
+ if (is_in && _ep->xfer_len < ep_mps)
+ deptsiz.b.xfersize = _ep->xfer_len;
+ else
+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep_mps;
+ /*deptsiz.b.xfersize = _ep->xfer_len - _ep->xfer_count;////////victor fixed*/
+ }
+
+ /* Fill size and count */
+ dwc_write_reg32(epctltsize_reg,deptsiz.d32);
+
+ /* EP enable */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ dwc_write_reg32 (epctl_reg, depctl.d32);
+
+ /* IN endpoint */
+ if (is_in) {
+ gintmsk_data_t intr_mask = {0};
+ //gnptxsts_data_t tx_status = { 0};
+
+ //tx_status.d32 = dwc_read_reg32(DWC_REG_GNPTXSTS);
+ //if (tx_status.b.nptxqspcavail == 0){
+ // return;
+ //}
+
+ /**
+ * Enable the Non-Periodic Tx FIFO empty interrupt, the
+ * data will be written into the fifo by the ISR.
+ */
+
+ /* First clear it from GINTSTS */
+ intr_mask.b.nptxfempty = 1;
+ dwc_modify_reg32( DWC_REG_GINTSTS,intr_mask.d32, 0);
+ dwc_modify_reg32( DWC_REG_GINTMSK,intr_mask.d32, intr_mask.d32);
+
+ }
+
+}
+
+int dwc_otg_ep_req_start(pcd_struct_t *pcd,int ep_num)
+{
+ dwc_ep_t *ep = &g_dwc_eps[ep_num];
+
+ ep->num = ep_num;
+ //DBG("dwc_otg_ep_req_start: ep%d\n",ep_num);
+ /* EP0 Transfer? */
+ if (ep_num == 0)
+ {
+ //DBG("EP0 State: %d\n",pcd->ep0state);
+ switch (pcd->ep0state)
+ {
+ case EP0_IN_DATA_PHASE:
+ break;
+
+ case EP0_OUT_DATA_PHASE:
+ if (pcd->request_config) {
+ /* Work around for SetConfig cmd */
+ /* Complete STATUS PHASE */
+ ep->is_in = 1;
+ pcd->ep0state = EP0_STATUS;
+ }
+ else if(pcd->length == 0)
+ {
+ /* Work around for MSC Reset cmd */
+ /* Complete STATUS PHASE */
+ ep->is_in = 1;
+ pcd->ep0state = EP0_STATUS;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ ep->start_xfer_buff = (uint8_t*)pcd->buf;
+ ep->xfer_buff = (uint8_t*)pcd->buf;
+ ep->xfer_len = pcd->length;
+ ep->xfer_count = 0;
+ ep->sent_zlp = 0;
+ ep->total_len = ep->xfer_len;
+ ep->maxpacket = 64;
+ dwc_otg_ep_start_transfer( ep );
+
+ }
+ else {
+ /* Setup and start the Transfer for Bulk */
+ ep->start_xfer_buff = (uint8_t*)pcd->bulk_buf + pcd->bulk_xfer_len;
+ ep->xfer_buff = (uint8_t*)pcd->bulk_buf + pcd->bulk_xfer_len;
+ ep->xfer_len = pcd->bulk_len;
+ /*ep->xfer_len = MIN(pcd->bulk_data_len , pcd->bulk_len);////Victor fixed!!*/
+ ep->xfer_count = 0;
+ ep->sent_zlp = 0;
+ ep->total_len = ep->xfer_len;
+ ep->maxpacket = BULK_EP_MPS;
+ ep->is_in = (ep_num == BULK_IN_EP_NUM);
+ //tranfer failed here after printf here
+
+ dwc_otg_bulk_ep_activate( ep );
+ /*printf("start_xfer_buf=0x%x, xfer_buf=0x%x, xfer_len 0x%x\n", ep->start_xfer_buff, ep->xfer_buff, ep->xfer_len);*/
+ dwc_otg_ep_start_transfer( ep );
+ }
+
+ return 0;
+
+}
+
+static void dwc_otg_bulk_ep_activate(dwc_ep_t *ep)
+{
+ depctl_data_t depctl = {0};
+ daint_data_t daintmsk = {0};
+ int epctl;
+ int ep_num = ep->num;
+
+ if (ep->is_in) {
+ epctl = DWC_REG_IN_EP_REG(ep_num);
+ daintmsk.ep.in = 1<<BULK_IN_EP_NUM; //ep1:BULK_IN
+ }
+ else{
+ epctl = DWC_REG_OUT_EP_REG(ep_num);
+ daintmsk.ep.out = 1<<BULK_OUT_EP_NUM;//ep2:BULK_OUT
+ }
+
+ depctl.d32 = dwc_read_reg32(epctl);
+ if (!depctl.b.usbactep) {
+ depctl.b.mps = BULK_EP_MPS;
+ depctl.b.eptype = 2;//BULK_STYLE
+ depctl.b.setd0pid = 1;
+ depctl.b.txfnum = 0; //Non-Periodic TxFIFO
+ depctl.b.usbactep = 1;
+
+ dwc_write_reg32(epctl, depctl.d32);
+ }
+
+ dwc_modify_reg32(DWC_REG_DAINTMSK, 0, daintmsk.d32);
+
+ return;
+}
+
+int dwc_otg_bulk_ep_enable(int is_in)
+{
+ depctl_data_t depctl = {0};
+ daint_data_t daintmsk = {0};
+ int epctl;
+ const int ep_num = is_in ? BULK_IN_EP_NUM : BULK_OUT_EP_NUM;
+
+ if (is_in) {
+ epctl = DWC_REG_IN_EP_REG(ep_num);
+ daintmsk.ep.in = 1<<BULK_IN_EP_NUM; //ep1:BULK_IN
+ }
+ else{
+ epctl = DWC_REG_OUT_EP_REG(ep_num);
+ daintmsk.ep.out = 1<<BULK_OUT_EP_NUM;//ep2:BULK_OUT
+ }
+
+ depctl.d32 = dwc_read_reg32(epctl);
+ if (!depctl.b.usbactep) {
+ depctl.b.mps = BULK_EP_MPS;
+ depctl.b.eptype = 2;//BULK_STYLE
+ depctl.b.setd0pid = 1;
+ depctl.b.txfnum = 0; //Non-Periodic TxFIFO
+ depctl.b.usbactep = 1;
+
+ dwc_write_reg32(epctl, depctl.d32);
+ }
+
+ dwc_modify_reg32(DWC_REG_DAINTMSK, 0, daintmsk.d32);
+
+ return 0;
+}
+
+void dwc_otg_power_off_phy(void)
+{
+ dwc_write_reg32(DWC_REG_PCGCCTL, 0xF);
+}
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.h b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.h
new file mode 100644
index 0000000000..5b7a69eca5
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd.h
@@ -0,0 +1,2079 @@
+/* dwc controller pcd drivers header */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ * From synopsys head file
+ */
+
+#ifndef __DWC_PCD_H__
+#define __DWC_PCD_H__
+
+//#define USE_FULL_SPEED
+
+#define NUM_EP 4
+
+#define BULK_IN_EP_NUM 1
+#define BULK_OUT_EP_NUM 2
+
+#ifdef USE_FULL_SPEED
+#define BULK_EP_MPS (64) //only for full speed
+#else
+#define BULK_EP_MPS (512)
+#endif
+
+#define DWC_REG_GOTGCTL 0x000 /** OTG Control and Status Register. <i>Offset: 000h</i> */
+#define DWC_REG_GOTGINT 0x004 /** OTG Interrupt Register. <i>Offset: 004h</i> */
+#define DWC_REG_GAHBCFG 0x008 /**Core AHB Configuration Register. <i>Offset: 008h</i> */
+#define DWC_REG_GUSBCFG 0x00C /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
+#define DWC_REG_GRSTCTL 0x010 /**Core Reset Register. <i>Offset: 010h</i> */
+#define DWC_REG_GINTSTS 0x014 /**Core Interrupt Register. <i>Offset: 014h</i> */
+#define DWC_REG_GINTMSK 0x018 /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
+#define DWC_REG_GRXSTSR 0x01C /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
+#define DWC_REG_GRXSTSP 0x020 /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
+#define DWC_REG_GRXFSIZ 0x024 /**Receive FIFO Size Register. <i>Offset: 024h</i> */
+#define DWC_REG_GNPTXFSIZ 0x028 /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
+#define DWC_REG_GNPTXSTS 0x02C /**Non Periodic Transmit FIFO/Queue Status Register (Read * Only). <i>Offset: 02Ch</i> */
+#define DWC_REG_GI2CCTL 0x030 /**I2C Access Register. <i>Offset: 030h</i> */
+#define DWC_REG_GPVNDCTL 0x034 /**PHY Vendor Control Register. <i>Offset: 034h</i> */
+#define DWC_REG_GGPIO 0x038 /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
+#define DWC_REG_GUID 0x03C /**User ID Register. <i>Offset: 03Ch</i> */
+#define DWC_REG_GSNPSID 0x040 /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
+#define DWC_REG_GHWCFG1 0x044 /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
+#define DWC_REG_GHWCFG2 0x048 /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
+#define DWC_REG_GHWCFG3 0x04C /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
+#define DWC_REG_GHWCFG4 0x050 /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
+#define DWC_REG_HPTXFSIZ 0x100 /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
+
+/** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
+ otherwise Device Transmit FIFO#n Register.
+ * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
+#define DWC_REG_DPTXFSIZ_DIEPTXF 0x104
+
+#define DWC_REG_DCFG 0x800 /** Device Configuration Register. <i>Offset 800h</i> */
+#define DWC_REG_DCTL 0x804 /** Device Control Register. <i>Offset: 804h</i> */
+#define DWC_REG_DSTS 0x808 /** Device Status Register (Read Only). <i>Offset: 808h</i> */
+#define DWC_REG_DIEPMSK 0x810 /** Device IN Endpoint Common Interrupt Mask Register. <i>Offset: 810h</i> */
+#define DWC_REG_DOEPMSK 0x814 /** Device OUT Endpoint Common Interrupt Mask Register. <i>Offset: 814h</i> */
+#define DWC_REG_DAINT 0x818 /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
+#define DWC_REG_DAINTMSK 0x81C /** Device All Endpoints Interrupt Mask Register. <i>Offset: 81Ch</i> */
+#define DWC_REG_DTKNQR1 0x820 /** Device IN Token Queue Read Register-1 (Read Only). <i>Offset: 820h</i> */
+#define DWC_REG_DTKNQR2 0x824 /** Device IN Token Queue Read Register-2 (Read Only). <i>Offset: 824h</i> */
+#define DWC_REG_DVBUGDIS 0x828 /** Device VBUS discharge Register. <i>Offset: 828h</i> */
+#define DWC_REG_DVBUSPULSE 0x82C /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
+#define DWC_REG_DTKNQR3 0x830
+ /** Device IN Token Queue Read Register-3 (Read Only). /
+ * Device Thresholding control register (Read/Write)
+ * <i>Offset: 830h</i> */
+#define DWC_REG_DTKNQR4 0x834
+ /** Device IN Token Queue Read Register-4 (Read Only). /
+ * Device IN EPs empty Inr. Mask Register (Read/Write)
+ * <i>Offset: 834h</i> */
+#define DWC_REG_PCGCCTL 0xE00 /** Power and Clock Gating Control Register */
+
+#define DWC_EP_REGS_OFFSET 0x00
+#define DWC_EP_INTR_OFFSET 0x08
+#define DWC_EP_TSIZE_OFFSET 0x10
+#define DWC_EP_DMA_OFFSET 0x14
+
+#define DWC_IN_EP_REG_START 0x900
+#define DWC_OUT_EP_REG_START 0xB00
+
+#define DWC_REG_IN_EP_REG(x) (DWC_IN_EP_REG_START + x*0x20 + DWC_EP_REGS_OFFSET)
+#define DWC_REG_IN_EP_INTR(x) (DWC_IN_EP_REG_START + x*0x20 + DWC_EP_INTR_OFFSET)
+#define DWC_REG_IN_EP_TSIZE(x) (DWC_IN_EP_REG_START + x*0x20 + DWC_EP_TSIZE_OFFSET)
+#define DWC_REG_IN_EP_DMA(x) (DWC_IN_EP_REG_START + x*0x20 + DWC_EP_DMA_OFFSET)
+
+#define DWC_REG_OUT_EP_REG(x) (DWC_OUT_EP_REG_START + x*0x20 + DWC_EP_REGS_OFFSET)
+#define DWC_REG_OUT_EP_INTR(x) (DWC_OUT_EP_REG_START + x*0x20 + DWC_EP_INTR_OFFSET)
+#define DWC_REG_OUT_EP_TSIZE(x) (DWC_OUT_EP_REG_START + x*0x20 + DWC_EP_TSIZE_OFFSET)
+#define DWC_REG_OUT_EP_DMA(x) (DWC_OUT_EP_REG_START + x*0x20 + DWC_EP_DMA_OFFSET)
+
+
+#define DWC_REG_DATA_FIFO_START 0x1000
+#define DWC_REG_DATA_FIFO(ep) (DWC_REG_DATA_FIFO_START + ep * 0x1000)
+
+/**
+ * The <code>dwc_ep</code> structure represents the state of a single
+ * endpoint when acting in device mode. It contains the data items
+ * needed for an endpoint to be activated and transfer packets.
+ */
+typedef struct dwc_ep {
+ /** EP number used for register address lookup */
+ uint8_t num;
+ /** EP direction 0 = OUT */
+ unsigned is_in : 1;
+ /** EP active. */
+ unsigned active : 1;
+
+ unsigned stopped : 1;
+ unsigned disabling : 1;
+
+ /** Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO */
+ unsigned tx_fifo_num : 4;
+ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */
+ unsigned type : 2;
+#define DWC_OTG_EP_TYPE_CONTROL 0
+#define DWC_OTG_EP_TYPE_ISOC 1
+#define DWC_OTG_EP_TYPE_BULK 2
+#define DWC_OTG_EP_TYPE_INTR 3
+
+ /** DATA start PID for INTR and BULK EP */
+ unsigned data_pid_start : 1;
+ /** Frame (even/odd) for ISOC EP */
+ unsigned even_odd_frame : 1;
+ /** Max Packet bytes */
+ unsigned maxpacket : 11;
+
+ /** @name Transfer state */
+ /** @{ */
+
+ /**
+ * Pointer to the beginning of the transfer buffer -- do not modify
+ * during transfer.
+ */
+
+ uint32_t dma_addr;
+
+ uint8_t *start_xfer_buff;
+ /** pointer to the transfer buffer */
+ uint8_t *xfer_buff;
+ /** Number of bytes to transfer */
+ unsigned xfer_len : 19;
+ /** Number of bytes transferred. */
+ unsigned xfer_count : 19;
+ /** Sent ZLP */
+ unsigned sent_zlp : 1;
+ /** Total len for control transfer */
+ unsigned total_len : 19;
+
+ /** @} */
+} dwc_ep_t;
+
+typedef struct pcd_struct_s{
+ /** SETUP packet for EP0
+ * This structure is allocated as a DMA buffer on PCD initialization
+ * with enough space for up to 3 setup packets.
+ */
+ union {
+ struct usb_ctrlrequest req;
+ uint32_t d32[2];
+ }setup_pkt;
+ int ep0state;
+
+ /* for USB_REQ_GET_STATUS */
+ unsigned status;
+
+ struct {
+ u8 type;//1-->setup+out+in, others: reseved
+ u8 setup_complete;
+ u8 out_complete;
+ u8 in_complete;
+ }cmdtype;
+
+ /* request */
+ volatile char * buf;
+
+ int length;
+
+ /* bulk req */
+ char * bulk_buf;
+ int bulk_len; // one bulk transfer length
+ int bulk_num; // number of bulk transfer
+ int bulk_data_len;// data len of all data
+ int xfer_len;
+ char bulk_out; // flag
+ char bulk_lock; // bulk transfering
+ //short bulk_seq;
+
+ short isPktResended;//is this 64K transfer is re-send
+ int bulk_xfer_len;//data len already transferred //added by Sam.Wu
+ unsigned origiSum;//data checksum in every 64K transfer //added by Sam.Wu
+ unsigned sequenceNo;
+ int xferNeedReply;
+
+ unsigned request_config : 1;
+ unsigned request_enable : 1;
+ unsigned request_reserv : 30;
+
+}pcd_struct_t;
+
+extern pcd_struct_t this_pcd;
+extern dwc_ep_t g_dwc_eps[NUM_EP];
+
+/**
+ * @file
+ *
+ * This file contains the data structures for accessing the DWC_otg core registers.
+ *
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/****************************************************************************/
+/** DWC_otg Core registers .
+ * The dwc_otg_core_global_regs structure defines the size
+ * and relative field offsets for the Core Global registers.
+ */
+typedef struct dwc_otg_core_global_regs
+{
+ /** OTG Control and Status Register. <i>Offset: 000h</i> */
+ volatile uint32_t gotgctl;
+ /** OTG Interrupt Register. <i>Offset: 004h</i> */
+ volatile uint32_t gotgint;
+ /**Core AHB Configuration Register. <i>Offset: 008h</i> */
+ volatile uint32_t gahbcfg;
+
+#define DWC_GLBINTRMASK 0x0001
+#define DWC_DMAENABLE 0x0020
+#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
+#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
+#define DWC_PTXEMPTYLVL_EMPTY 0x0100
+#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
+
+ /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
+ volatile uint32_t gusbcfg;
+ /**Core Reset Register. <i>Offset: 010h</i> */
+ volatile uint32_t grstctl;
+ /**Core Interrupt Register. <i>Offset: 014h</i> */
+ volatile uint32_t gintsts;
+ /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
+ volatile uint32_t gintmsk;
+ /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
+ volatile uint32_t grxstsr;
+ /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
+ volatile uint32_t grxstsp;
+ /**Receive FIFO Size Register. <i>Offset: 024h</i> */
+ volatile uint32_t grxfsiz;
+ /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
+ volatile uint32_t gnptxfsiz;
+ /**Non Periodic Transmit FIFO/Queue Status Register (Read
+ * Only). <i>Offset: 02Ch</i> */
+ volatile uint32_t gnptxsts;
+ /**I2C Access Register. <i>Offset: 030h</i> */
+ volatile uint32_t gi2cctl;
+ /**PHY Vendor Control Register. <i>Offset: 034h</i> */
+ volatile uint32_t gpvndctl;
+ /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
+ volatile uint32_t ggpio;
+ /**User ID Register. <i>Offset: 03Ch</i> */
+ volatile uint32_t guid;
+ /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
+ volatile uint32_t gsnpsid;
+ /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
+ volatile uint32_t ghwcfg1;
+ /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
+ volatile uint32_t ghwcfg2;
+#define DWC_SLAVE_ONLY_ARCH 0
+#define DWC_EXT_DMA_ARCH 1
+#define DWC_INT_DMA_ARCH 2
+
+#define DWC_MODE_HNP_SRP_CAPABLE 0
+#define DWC_MODE_SRP_ONLY_CAPABLE 1
+#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
+#define DWC_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_MODE_SRP_CAPABLE_HOST 5
+#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
+
+ /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
+ volatile uint32_t ghwcfg3;
+ /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
+ volatile uint32_t ghwcfg4;
+ /** Core LPM Configuration register <i>Offset: 054h</i>*/
+ volatile uint32_t glpmcfg;
+ /** Global PowerDn Register <i>Offset: 058h</i> */
+ volatile uint32_t gpwrdn;
+ /** Global DFIFO SW Config Register <i>Offset: 05Ch</i> */
+ volatile uint32_t gdfifocfg;
+ /** ADP Control Register <i>Offset: 060h</i> */
+ volatile uint32_t adpctl;
+ /** Reserved <i>Offset: 064h-0FFh</i> */
+ volatile uint32_t reserved39[39];
+ /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
+ volatile uint32_t hptxfsiz;
+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
+ otherwise Device Transmit FIFO#n Register.
+ * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
+ volatile uint32_t dptxfsiz_dieptxf[15];
+} dwc_otg_core_global_regs_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Control
+ * and Status Register (GOTGCTL). Set the bits using the bit
+ * fields then write the <i>d32</i> value to the register.
+ */
+typedef union gotgctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned sesreqscs : 1;
+ unsigned sesreq : 1;
+ unsigned reserved2_7 : 6;
+ unsigned hstnegscs : 1;
+ unsigned hnpreq : 1;
+ unsigned hstsethnpen : 1;
+ unsigned devhnpen : 1;
+ unsigned reserved12_15 : 4;
+ unsigned conidsts : 1;
+ unsigned reserved17 : 1;
+ unsigned asesvld : 1;
+ unsigned bsesvld : 1;
+ unsigned currmod : 1;
+ unsigned reserved21_31 : 11;
+ } b;
+} gotgctl_data_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Interrupt Register
+ * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i>
+ * value to the register.
+ */
+typedef union gotgint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Current Mode */
+ unsigned reserved0_1 : 2;
+
+ /** Session End Detected */
+ unsigned sesenddet : 1;
+
+ unsigned reserved3_7 : 5;
+
+ /** Session Request Success Status Change */
+ unsigned sesreqsucstschng : 1;
+ /** Host Negotiation Success Status Change */
+ unsigned hstnegsucstschng : 1;
+
+ unsigned reserver10_16 : 7;
+
+ /** Host Negotiation Detected */
+ unsigned hstnegdet : 1;
+ /** A-Device Timeout Change */
+ unsigned adevtoutchng : 1;
+ /** Debounce Done */
+ unsigned debdone : 1;
+
+ unsigned reserved31_20 : 12;
+
+ } b;
+} gotgint_data_t;
+
+
+/**
+ * This union represents the bit fields of the Core AHB Configuration
+ * Register (GAHBCFG). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gahbcfg_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned glblintrmsk : 1;
+#define DWC_GAHBCFG_GLBINT_ENABLE 1
+
+ unsigned hburstlen : 4;
+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
+
+ unsigned dmaenable : 1;
+#define DWC_GAHBCFG_DMAENABLE 1
+ unsigned reserved : 1;
+ unsigned nptxfemplvl_txfemplvl : 1;
+ unsigned ptxfemplvl : 1;
+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
+ unsigned reserved9_31 : 23;
+ } b;
+} gahbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core USB Configuration
+ * Register (GUSBCFG). Set the bits using the bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union gusbcfg_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned toutcal : 3;
+ unsigned phyif : 1;
+ unsigned ulpi_utmi_sel : 1;
+ unsigned fsintf : 1;
+ unsigned physel : 1;
+ unsigned ddrsel : 1;
+ unsigned srpcap : 1;
+ unsigned hnpcap : 1;
+ unsigned usbtrdtim : 4;
+ unsigned nptxfrwnden : 1;
+ unsigned phylpwrclksel : 1;
+ unsigned otgutmifssel : 1;
+ unsigned ulpi_fsls : 1;
+ unsigned ulpi_auto_res : 1;
+ unsigned ulpi_clk_sus_m : 1;
+ unsigned ulpi_ext_vbus_drv : 1;
+ unsigned ulpi_int_vbus_indicator : 1;
+ unsigned term_sel_dl_pulse : 1;
+ unsigned reserved : 9;
+ } b;
+} gusbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core Reset Register
+ * (GRSTCTL). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union grstctl_data
+{
+ /** raw register data */
+ unsigned int d32;
+ /** register bits */
+ struct
+ {
+ /** Core Soft Reset (CSftRst) (Device and Host)
+ *
+ * The application can flush the control logic in the
+ * entire core using this bit. This bit resets the
+ * pipelines in the AHB Clock domain as well as the
+ * PHY Clock domain.
+ *
+ * The state machines are reset to an IDLE state, the
+ * control bits in the CSRs are cleared, all the
+ * transmit FIFOs and the receive FIFO are flushed.
+ *
+ * The status mask bits that control the generation of
+ * the interrupt, are cleared, to clear the
+ * interrupt. The interrupt status bits are not
+ * cleared, so the application can get the status of
+ * any events that occurred in the core after it has
+ * set this bit.
+ *
+ * Any transactions on the AHB are terminated as soon
+ * as possible following the protocol. Any
+ * transactions on the USB are terminated immediately.
+ *
+ * The configuration settings in the CSRs are
+ * unchanged, so the software doesn't have to
+ * reprogram these registers (Device
+ * Configuration/Host Configuration/Core System
+ * Configuration/Core PHY Configuration).
+ *
+ * The application can write to this bit, any time it
+ * wants to reset the core. This is a self clearing
+ * bit and the core clears this bit after all the
+ * necessary logic is reset in the core, which may
+ * take several clocks, depending on the current state
+ * of the core.
+ */
+ unsigned csftrst : 1;
+ /** Hclk Soft Reset
+ *
+ * The application uses this bit to reset the control logic in
+ * the AHB clock domain. Only AHB clock domain pipelines are
+ * reset.
+ */
+ unsigned hsftrst : 1;
+ /** Host Frame Counter Reset (Host Only)<br>
+ *
+ * The application can reset the (micro)frame number
+ * counter inside the core, using this bit. When the
+ * (micro)frame counter is reset, the subsequent SOF
+ * sent out by the core, will have a (micro)frame
+ * number of 0.
+ */
+ unsigned hstfrm : 1;
+ /** In Token Sequence Learning Queue Flush
+ * (INTknQFlsh) (Device Only)
+ */
+ unsigned intknqflsh : 1;
+ /** RxFIFO Flush (RxFFlsh) (Device and Host)
+ *
+ * The application can flush the entire Receive FIFO
+ * using this bit. <p>The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is reading from the RxFIFO nor the MAC
+ * is writing the data in to the FIFO. <p>The
+ * application should wait until the bit is cleared
+ * before performing any other operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned rxfflsh : 1;
+ /** TxFIFO Flush (TxFFlsh) (Device and Host).
+ *
+ * This bit is used to selectively flush a single or
+ * all transmit FIFOs. The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is writing into the TxFIFO nor the MAC
+ * is reading the data out of the FIFO. <p>The
+ * application should wait until the core clears this
+ * bit, before performing any operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned txfflsh : 1;
+
+ /** TxFIFO Number (TxFNum) (Device and Host).
+ *
+ * This is the FIFO number which needs to be flushed,
+ * using the TxFIFO Flush bit. This field should not
+ * be changed until the TxFIFO Flush bit is cleared by
+ * the core.
+ * - 0x0 : Non Periodic TxFIFO Flush
+ * - 0x1 : Periodic TxFIFO #1 Flush in device mode
+ * or Periodic TxFIFO in host mode
+ * - 0x2 : Periodic TxFIFO #2 Flush in device mode.
+ * - ...
+ * - 0xF : Periodic TxFIFO #15 Flush in device mode
+ * - 0x10: Flush all the Transmit NonPeriodic and
+ * Transmit Periodic FIFOs in the core
+ */
+ unsigned txfnum : 5;
+ /** Reserved */
+ unsigned reserved11_29 : 19;
+ /** DMA Request Signal. Indicated DMA request is in
+ * probress. Used for debug purpose. */
+ unsigned dmareq : 1;
+ /** AHB Master Idle. Indicates the AHB Master State
+ * Machine is in IDLE condition. */
+ unsigned ahbidle : 1;
+ } b;
+} grstctl_t;
+
+
+/**
+ * This union represents the bit fields of the Core Interrupt Mask
+ * Register (GINTMSK). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gintmsk_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned reserved0 : 1;
+ unsigned modemismatch : 1;
+ unsigned otgintr : 1;
+ unsigned sofintr : 1;
+ unsigned rxstsqlvl : 1;
+ unsigned nptxfempty : 1;
+ unsigned ginnakeff : 1;
+ unsigned goutnakeff : 1;
+ unsigned reserved8 : 1;
+ unsigned i2cintr : 1;
+ unsigned erlysuspend : 1;
+ unsigned usbsuspend : 1;
+ unsigned usbreset : 1;
+ unsigned enumdone : 1;
+ unsigned isooutdrop : 1;
+ unsigned eopframe : 1;
+ unsigned reserved16 : 1;
+ unsigned epmismatch : 1;
+ unsigned inepintr : 1;
+ unsigned outepintr : 1;
+ unsigned incomplisoin : 1;
+ unsigned incomplisoout : 1;
+ unsigned reserved22_23 : 2;
+ unsigned portintr : 1;
+ unsigned hcintr : 1;
+ unsigned ptxfempty : 1;
+ unsigned reserved27 : 1;
+ unsigned conidstschng : 1;
+ unsigned disconnect : 1;
+ unsigned sessreqintr : 1;
+ unsigned wkupintr : 1;
+ } b;
+} gintmsk_data_t;
+/**
+ * This union represents the bit fields of the Core Interrupt Register
+ * (GINTSTS). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union gintsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+#define DWC_SOF_INTR_MASK 0x0008
+ /** register bits */
+ struct
+ {
+#define DWC_HOST_MODE 1
+ unsigned curmode : 1;
+ unsigned modemismatch : 1;
+ unsigned otgintr : 1;
+ unsigned sofintr : 1;
+ unsigned rxstsqlvl : 1;
+ unsigned nptxfempty : 1;
+ unsigned ginnakeff : 1;
+ unsigned goutnakeff : 1;
+ unsigned reserved8 : 1;
+ unsigned i2cintr : 1;
+ unsigned erlysuspend : 1;
+ unsigned usbsuspend : 1;
+ unsigned usbreset : 1;
+ unsigned enumdone : 1;
+ unsigned isooutdrop : 1;
+ unsigned eopframe : 1;
+ unsigned intokenrx : 1;
+ unsigned epmismatch : 1;
+ unsigned inepint: 1;
+ unsigned outepintr : 1;
+ unsigned incomplisoin : 1;
+ unsigned incomplisoout : 1;
+ unsigned reserved22_23 : 2;
+ unsigned portintr : 1;
+ unsigned hcintr : 1;
+ unsigned ptxfempty : 1;
+ unsigned reserved27 : 1;
+ unsigned conidstschng : 1;
+ unsigned disconnect : 1;
+ unsigned sessreqintr : 1;
+ unsigned wkupintr : 1;
+ } b;
+} gintsts_data_t;
+
+
+/**
+ * This union represents the bit fields in the Device Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union device_grxsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned epnum : 4;
+ unsigned bcnt : 11;
+ unsigned dpid : 2;
+
+#define DWC_STS_DATA_UPDT 0x2 // OUT Data Packet
+#define DWC_STS_XFER_COMP 0x3 // OUT Data Transfer Complete
+
+#define DWC_DSTS_GOUT_NAK 0x1 // Global OUT NAK
+#define DWC_DSTS_SETUP_COMP 0x4 // Setup Phase Complete
+#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet
+ unsigned pktsts : 4;
+ unsigned fn : 4;
+ unsigned reserved : 7;
+ } b;
+} device_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union host_grxsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned chnum : 4;
+ unsigned bcnt : 11;
+ unsigned dpid : 2;
+
+ unsigned pktsts : 4;
+#define DWC_GRXSTS_PKTSTS_IN 0x2
+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
+#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
+
+ unsigned reserved : 11;
+ } b;
+} host_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element then
+ * read out the bits using the <i>b</i>it elements.
+ */
+typedef union fifosize_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned startaddr : 16;
+ unsigned depth : 16;
+ } b;
+} fifosize_data_t;
+
+/**
+ * This union represents the bit fields in the Non-Periodic Transmit
+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union gnptxsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned nptxfspcavail : 16;
+ unsigned nptxqspcavail : 8;
+ /** Top of the Non-Periodic Transmit Request Queue
+ * - bit 24 - Terminate (Last entry for the selected
+ * channel/EP)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - IN/OUT
+ * - 2'b01 - Zero Length OUT
+ * - 2'b10 - PING/Complete Split
+ * - 2'b11 - Channel Halt
+ * - bits 30:27 - Channel/EP Number
+ */
+ unsigned nptxqtop_terminate : 1;
+ unsigned nptxqtop_token : 2;
+ unsigned nptxqtop_chnep : 4;
+ unsigned reserved : 1;
+ } b;
+} gnptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Transmit
+ * FIFO Status Register (DTXFSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union dtxfsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned txfspcavail : 16;
+ unsigned reserved : 16;
+ } b;
+} dtxfsts_data_t;
+
+/**
+ * This union represents the bit fields in the I2C Control Register
+ * (I2CCTL). Read the register into the <i>d32</i> element then read out the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union gi2cctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned rwdata : 8;
+ unsigned regaddr : 8;
+ unsigned addr : 7;
+ unsigned i2cen : 1;
+ unsigned ack : 1;
+ unsigned i2csuspctl : 1;
+ unsigned i2cdevaddr : 2;
+ unsigned reserved : 2;
+ unsigned rw : 1;
+ unsigned bsydne : 1;
+ } b;
+} gi2cctl_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config1
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg1_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned ep_dir0 : 2;
+ unsigned ep_dir1 : 2;
+ unsigned ep_dir2 : 2;
+ unsigned ep_dir3 : 2;
+ unsigned ep_dir4 : 2;
+ unsigned ep_dir5 : 2;
+ unsigned ep_dir6 : 2;
+ unsigned ep_dir7 : 2;
+ unsigned ep_dir8 : 2;
+ unsigned ep_dir9 : 2;
+ unsigned ep_dir10 : 2;
+ unsigned ep_dir11 : 2;
+ unsigned ep_dir12 : 2;
+ unsigned ep_dir13 : 2;
+ unsigned ep_dir14 : 2;
+ unsigned ep_dir15 : 2;
+ } b;
+} hwcfg1_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config2
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg2_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /* GHWCFG2 */
+ unsigned op_mode : 3;
+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+
+ unsigned architecture : 2;
+ unsigned point2point : 1;
+ unsigned hs_phy_type : 2;
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+
+ unsigned fs_phy_type : 2;
+ unsigned num_dev_ep : 4;
+ unsigned num_host_chan : 4;
+ unsigned perio_ep_supported : 1;
+ unsigned dynamic_fifo : 1;
+ unsigned rx_status_q_depth : 2;
+ unsigned nonperio_tx_q_depth : 2;
+ unsigned host_perio_tx_q_depth : 2;
+ unsigned dev_token_q_depth : 5;
+ unsigned reserved31 : 1;
+ } b;
+} hwcfg2_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config3
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg3_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /* GHWCFG3 */
+ unsigned xfer_size_cntr_width : 4;
+ unsigned packet_size_cntr_width : 3;
+ unsigned otg_func : 1;
+ unsigned i2c : 1;
+ unsigned vendor_ctrl_if : 1;
+ unsigned optional_features : 1;
+ unsigned synch_reset_type : 1;
+ unsigned ahb_phy_clock_synch : 1;
+ unsigned reserved15_13 : 3;
+ unsigned dfifo_depth : 16;
+ } b;
+} hwcfg3_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config4
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg4_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned num_dev_perio_in_ep : 4;
+ unsigned power_optimiz : 1;
+ unsigned min_ahb_freq : 9;
+ unsigned utmi_phy_data_width : 2;
+ unsigned num_dev_mode_ctrl_ep : 4;
+ unsigned iddig_filt_en : 1;
+ unsigned vbus_valid_filt_en : 1;
+ unsigned a_valid_filt_en : 1;
+ unsigned b_valid_filt_en : 1;
+ unsigned session_end_filt_en : 1;
+ unsigned ded_fifo_en : 1;
+ unsigned num_in_eps : 4;
+ unsigned reserved31_30 : 2;
+ } b;
+} hwcfg4_data_t;
+
+////////////////////////////////////////////
+// Device Registers
+/**
+ * Device Global Registers. <i>Offsets 800h-BFFh</i>
+ *
+ * The following structures define the size and relative field offsets
+ * for the Device Mode Registers.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_global_regs
+{
+ /** Device Configuration Register. <i>Offset 800h</i> */
+ volatile uint32_t dcfg;
+ /** Device Control Register. <i>Offset: 804h</i> */
+ volatile uint32_t dctl;
+ /** Device Status Register (Read Only). <i>Offset: 808h</i> */
+ volatile uint32_t dsts;
+ /** Reserved. <i>Offset: 80Ch</i> */
+ uint32_t unused;
+ /** Device IN Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 810h</i> */
+ volatile uint32_t diepmsk;
+ /** Device OUT Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 814h</i> */
+ volatile uint32_t doepmsk;
+ /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
+ volatile uint32_t daint;
+ /** Device All Endpoints Interrupt Mask Register. <i>Offset:
+ * 81Ch</i> */
+ volatile uint32_t daintmsk;
+ /** Device IN Token Queue Read Register-1 (Read Only).
+ * <i>Offset: 820h</i> */
+ volatile uint32_t dtknqr1;
+ /** Device IN Token Queue Read Register-2 (Read Only).
+ * <i>Offset: 824h</i> */
+ volatile uint32_t dtknqr2;
+ /** Device VBUS discharge Register. <i>Offset: 828h</i> */
+ volatile uint32_t dvbusdis;
+ /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
+ volatile uint32_t dvbuspulse;
+ /** Device IN Token Queue Read Register-3 (Read Only). /
+ * Device Thresholding control register (Read/Write)
+ * <i>Offset: 830h</i> */
+ volatile uint32_t dtknqr3_dthrctl;
+ /** Device IN Token Queue Read Register-4 (Read Only). /
+ * Device IN EPs empty Inr. Mask Register (Read/Write)
+ * <i>Offset: 834h</i> */
+ volatile uint32_t dtknqr4_fifoemptymsk;
+} dwc_otg_device_global_regs_t;
+
+/**
+ * This union represents the bit fields in the Device Configuration
+ * Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements. Write the
+ * <i>d32</i> member to the dcfg register.
+ */
+typedef union dcfg_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Device Speed */
+ unsigned devspd : 2;
+ /** Non Zero Length Status OUT Handshake */
+ unsigned nzstsouthshk : 1;
+#define DWC_DCFG_SEND_STALL 1
+
+ unsigned reserved3 : 1;
+ /** Device Addresses */
+ unsigned devaddr : 7;
+ /** Periodic Frame Interval */
+ unsigned perfrint : 2;
+#define DWC_DCFG_FRAME_INTERVAL_80 0
+#define DWC_DCFG_FRAME_INTERVAL_85 1
+#define DWC_DCFG_FRAME_INTERVAL_90 2
+#define DWC_DCFG_FRAME_INTERVAL_95 3
+
+ unsigned reserved13_17 : 5;
+ /** In Endpoint Mis-match count */
+ unsigned epmscnt : 4;
+ } b;
+} dcfg_data_t;
+
+/**
+ * This union represents the bit fields in the Device Control
+ * Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union dctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Remote Wakeup */
+ unsigned rmtwkupsig : 1;
+ /** Soft Disconnect */
+ unsigned sftdiscon : 1;
+ /** Global Non-Periodic IN NAK Status */
+ unsigned gnpinnaksts : 1;
+ /** Global OUT NAK Status */
+ unsigned goutnaksts : 1;
+ /** Test Control */
+ unsigned tstctl : 3;
+ /** Set Global Non-Periodic IN NAK */
+ unsigned sgnpinnak : 1;
+ /** Clear Global Non-Periodic IN NAK */
+ unsigned cgnpinnak : 1;
+ /** Set Global OUT NAK */
+ unsigned sgoutnak : 1;
+ /** Clear Global OUT NAK */
+ unsigned cgoutnak : 1;
+
+ unsigned reserved : 21;
+ } b;
+} dctl_data_t;
+
+/**
+ * This union represents the bit fields in the Device Status
+ * Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union dsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Suspend Status */
+ unsigned suspsts : 1;
+ /** Enumerated Speed */
+ unsigned enumspd : 2;
+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2
+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3
+ /** Erratic Error */
+ unsigned errticerr : 1;
+ unsigned reserved4_7: 4;
+ /** Frame or Microframe Number of the received SOF */
+ unsigned soffn : 14;
+ unsigned reserved22_31 : 10;
+ } b;
+} dsts_data_t;
+
+
+/**
+ * This union represents the bit fields in the Device IN EP Interrupt
+ * Register and the Device IN EP Common Mask Register.
+ *
+ * - Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union diepint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Transfer complete mask */
+ unsigned xfercompl : 1;
+ /** Endpoint disable mask */
+ unsigned epdisabled : 1;
+ /** AHB Error mask */
+ unsigned ahberr : 1;
+ /** TimeOUT Handshake mask (non-ISOC EPs) */
+ unsigned timeout : 1;
+ /** IN Token received with TxF Empty mask */
+ unsigned intktxfemp : 1;
+ /** IN Token Received with EP mismatch mask */
+ unsigned intknepmis : 1;
+ /** IN Endpoint HAK Effective mask */
+ unsigned inepnakeff : 1;
+ /** IN Endpoint HAK Effective mask */
+ unsigned emptyintr : 1;
+
+ unsigned txfifoundrn : 1;
+
+ unsigned reserved08_31 : 23;
+ } b;
+} diepint_data_t;
+/**
+ * This union represents the bit fields in the Device IN EP Common
+ * Interrupt Mask Register.
+ */
+typedef union diepint_data diepmsk_data_t;
+
+/**
+ * This union represents the bit fields in the Device OUT EP Interrupt
+ * Registerand Device OUT EP Common Interrupt Mask Register.
+ *
+ * - Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union doepint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Transfer complete */
+ unsigned xfercompl : 1;
+ /** Endpoint disable */
+ unsigned epdisabled : 1;
+ /** AHB Error */
+ unsigned ahberr : 1;
+ /** Setup Phase Done (contorl EPs) */
+ unsigned setup : 1;
+ unsigned reserved04_31 : 28;
+ } b;
+} doepint_data_t;
+/**
+ * This union represents the bit fields in the Device OUT EP Common
+ * Interrupt Mask Register.
+ */
+typedef union doepint_data doepmsk_data_t;
+
+
+/**
+ * This union represents the bit fields in the Device All EP Interrupt
+ * and Mask Registers.
+ * - Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union daint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** IN Endpoint bits */
+ unsigned in : 16;
+ /** OUT Endpoint bits */
+ unsigned out : 16;
+ } ep;
+ struct
+ {
+ /** IN Endpoint bits */
+ unsigned inep0 : 1;
+ unsigned inep1 : 1;
+ unsigned inep2 : 1;
+ unsigned inep3 : 1;
+ unsigned inep4 : 1;
+ unsigned inep5 : 1;
+ unsigned inep6 : 1;
+ unsigned inep7 : 1;
+ unsigned inep8 : 1;
+ unsigned inep9 : 1;
+ unsigned inep10 : 1;
+ unsigned inep11 : 1;
+ unsigned inep12 : 1;
+ unsigned inep13 : 1;
+ unsigned inep14 : 1;
+ unsigned inep15 : 1;
+ /** OUT Endpoint bits */
+ unsigned outep0 : 1;
+ unsigned outep1 : 1;
+ unsigned outep2 : 1;
+ unsigned outep3 : 1;
+ unsigned outep4 : 1;
+ unsigned outep5 : 1;
+ unsigned outep6 : 1;
+ unsigned outep7 : 1;
+ unsigned outep8 : 1;
+ unsigned outep9 : 1;
+ unsigned outep10 : 1;
+ unsigned outep11 : 1;
+ unsigned outep12 : 1;
+ unsigned outep13 : 1;
+ unsigned outep14 : 1;
+ unsigned outep15 : 1;
+ } b;
+} daint_data_t;
+
+/**
+ * This union represents the bit fields in the Device IN Token Queue
+ * Read Registers.
+ * - Read the register into the <i>d32</i> member.
+ * - READ-ONLY Register
+ */
+typedef union dtknq1_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** In Token Queue Write Pointer */
+ unsigned intknwptr : 5;
+ /** Reserved */
+ unsigned reserved05_06 : 2;
+ /** write pointer has wrapped. */
+ unsigned wrap_bit : 1;
+ /** EP Numbers of IN Tokens 0 ... 4 */
+ unsigned epnums0_5 : 24;
+ }b;
+} dtknq1_data_t;
+
+/**
+ * This union represents Threshold control Register
+ * - Read and write the register into the <i>d32</i> member.
+ * - READ-WRITABLE Register
+ */
+typedef union dthrctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** non ISO Tx Thr. Enable */
+ unsigned non_iso_thr_en : 1;
+ /** ISO Tx Thr. Enable */
+ unsigned iso_thr_en : 1;
+ /** Tx Thr. Length */
+ unsigned tx_thr_len : 9;
+ /** Reserved */
+ unsigned reserved11_15 : 5;
+ /** Rx Thr. Enable */
+ unsigned rx_thr_en : 1;
+ /** Rx Thr. Length */
+ unsigned rx_thr_len : 9;
+ /** Reserved */
+ unsigned reserved26_31 : 6;
+ }b;
+} dthrctl_data_t;
+
+
+/**
+ * Device Logical IN Endpoint-Specific Registers. <i>Offsets
+ * 900h-AFCh</i>
+ *
+ * There will be one set of endpoint registers per logical endpoint
+ * implemented.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_in_ep_regs
+{
+ /** Device IN Endpoint Control Register. <i>Offset:900h +
+ * (ep_num * 20h) + 00h</i> */
+ volatile uint32_t diepctl;
+ /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
+ uint32_t reserved04;
+ /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
+ * (ep_num * 20h) + 08h</i> */
+ volatile uint32_t diepint;
+ /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
+ uint32_t reserved0C;
+ /** Device IN Endpoint Transfer Size
+ * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
+ volatile uint32_t dieptsiz;
+ /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
+ * (ep_num * 20h) + 14h</i> */
+ volatile uint32_t diepdma;
+ /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
+ * (ep_num * 20h) + 18h</i> */
+ volatile uint32_t dtxfsts;
+ /** Reserved. <i>Offset:900h + (ep_num * 20h) + 1Ch - 900h +
+ * (ep_num * 20h) + 1Ch</i>*/
+ uint32_t reserved18;
+} dwc_otg_dev_in_ep_regs_t;
+
+/**
+ * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
+ * B00h-CFCh</i>
+ *
+ * There will be one set of endpoint registers per logical endpoint
+ * implemented.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_out_ep_regs
+{
+ /** Device OUT Endpoint Control Register. <i>Offset:B00h +
+ * (ep_num * 20h) + 00h</i> */
+ volatile uint32_t doepctl;
+ /** Device OUT Endpoint Frame number Register. <i>Offset:
+ * B00h + (ep_num * 20h) + 04h</i> */
+ volatile uint32_t doepfn;
+ /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
+ * (ep_num * 20h) + 08h</i> */
+ volatile uint32_t doepint;
+ /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
+ uint32_t reserved0C;
+ /** Device OUT Endpoint Transfer Size Register. <i>Offset:
+ * B00h + (ep_num * 20h) + 10h</i> */
+ volatile uint32_t doeptsiz;
+ /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
+ * + (ep_num * 20h) + 14h</i> */
+ volatile uint32_t doepdma;
+ /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 18h - B00h +
+ * (ep_num * 20h) + 1Ch</i> */
+ uint32_t unused[2];
+} dwc_otg_dev_out_ep_regs_t;
+
+/**
+ * This union represents the bit fields in the Device EP Control
+ * Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union depctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Maximum Packet Size
+ * IN/OUT EPn
+ * IN/OUT EP0 - 2 bits
+ * 2'b00: 64 Bytes
+ * 2'b01: 32
+ * 2'b10: 16
+ * 2'b11: 8 */
+ unsigned mps : 11;
+#define DWC_DEP0CTL_MPS_64 0
+#define DWC_DEP0CTL_MPS_32 1
+#define DWC_DEP0CTL_MPS_16 2
+#define DWC_DEP0CTL_MPS_8 3
+
+ /** Next Endpoint
+ * IN EPn/IN EP0
+ * OUT EPn/OUT EP0 - reserved */
+ unsigned nextep : 4;
+
+ /** USB Active Endpoint */
+ unsigned usbactep : 1;
+
+ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
+ * This field contains the PID of the packet going to
+ * be received or transmitted on this endpoint. The
+ * application should program the PID of the first
+ * packet going to be received or transmitted on this
+ * endpoint , after the endpoint is
+ * activated. Application use the SetD1PID and
+ * SetD0PID fields of this register to program either
+ * D0 or D1 PID.
+ *
+ * The encoding for this field is
+ * - 0: D0
+ * - 1: D1
+ */
+ unsigned dpid : 1;
+
+ /** NAK Status */
+ unsigned naksts : 1;
+
+ /** Endpoint Type
+ * 2'b00: Control
+ * 2'b01: Isochronous
+ * 2'b10: Bulk
+ * 2'b11: Interrupt */
+ unsigned eptype : 2;
+
+ /** Snoop Mode
+ * OUT EPn/OUT EP0
+ * IN EPn/IN EP0 - reserved */
+ unsigned snp : 1;
+
+ /** Stall Handshake */
+ unsigned stall : 1;
+
+ /** Tx Fifo Number
+ * IN EPn/IN EP0
+ * OUT EPn/OUT EP0 - reserved */
+ unsigned txfnum : 4;
+
+ /** Clear NAK */
+ unsigned cnak : 1;
+ /** Set NAK */
+ unsigned snak : 1;
+ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
+ * Writing to this field sets the Endpoint DPID (DPID)
+ * field in this register to DATA0. Set Even
+ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
+ * Writing to this field sets the Even/Odd
+ * (micro)frame (EO_FrNum) field to even (micro)
+ * frame.
+ */
+ unsigned setd0pid : 1;
+ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
+ * Writing to this field sets the Endpoint DPID (DPID)
+ * field in this register to DATA1 Set Odd
+ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
+ * Writing to this field sets the Even/Odd
+ * (micro)frame (EO_FrNum) field to odd (micro) frame.
+ */
+ unsigned setd1pid : 1;
+
+ /** Endpoint Disable */
+ unsigned epdis : 1;
+ /** Endpoint Enable */
+ unsigned epena : 1;
+ } b;
+} depctl_data_t;
+
+/**
+ * This union represents the bit fields in the Device EP Transfer
+ * Size Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union deptsiz_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Transfer size */
+ unsigned xfersize : 19;
+ /** Packet Count */
+ unsigned pktcnt : 10;
+ /** Multi Count - Periodic IN endpoints */
+ unsigned mc : 2;
+ unsigned reserved : 1;
+ } b;
+} deptsiz_data_t;
+
+/**
+ * This union represents the bit fields in the Device EP 0 Transfer
+ * Size Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union deptsiz0_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Transfer size */
+ unsigned xfersize : 7;
+ /** Reserved */
+ unsigned reserved7_18 : 12;
+ /** Packet Count */
+ unsigned pktcnt : 1;
+ /** Reserved */
+ unsigned reserved20_28 : 9;
+ /**Setup Packet Count (DOEPTSIZ0 Only) */
+ unsigned supcnt : 2;
+ unsigned reserved31;
+ } b;
+} deptsiz0_data_t;
+
+
+/** Maximum number of Periodic FIFOs */
+#define MAX_PERIO_FIFOS 15
+/** Maximum number of Periodic FIFOs */
+#define MAX_TX_FIFOS 15
+
+/** Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS 16
+
+/**
+ * The dwc_otg_dev_if structure contains information needed to manage
+ * the DWC_otg controller acting in device mode. It represents the
+ * programming view of the device-specific aspects of the controller.
+ */
+typedef struct dwc_otg_dev_if
+{
+ /** Pointer to device Global registers.
+ * Device Global Registers starting at offset 800h
+ */
+ dwc_otg_device_global_regs_t *dev_global_regs;
+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
+
+ /**
+ * Device Logical IN Endpoint-Specific Registers 900h-AFCh
+ */
+ dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_IN_EP_REG_OFFSET 0x900
+#define DWC_EP_REG_OFFSET 0x20
+
+ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
+ dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
+
+ /* Device configuration information*/
+ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */
+ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */
+ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/
+
+ /** Size of periodic FIFOs (Bytes) */
+ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
+
+ /** Size of Tx FIFOs (Bytes) */
+ uint16_t tx_fifo_size[MAX_TX_FIFOS];
+
+ /** Thresholding enable flags and length varaiables **/
+ uint16_t rx_thr_en;
+ uint16_t iso_tx_thr_en;
+ uint16_t non_iso_tx_thr_en;
+
+ uint16_t rx_thr_length;
+ uint16_t tx_thr_length;
+
+} dwc_otg_dev_if_t;
+
+
+
+
+/////////////////////////////////////////////////
+// Host Mode Register Structures
+//
+/**
+ * The Host Global Registers structure defines the size and relative
+ * field offsets for the Host Mode Global Registers. Host Global
+ * Registers offsets 400h-7FFh.
+*/
+typedef struct dwc_otg_host_global_regs
+{
+ /** Host Configuration Register. <i>Offset: 400h</i> */
+ volatile uint32_t hcfg;
+ /** Host Frame Interval Register. <i>Offset: 404h</i> */
+ volatile uint32_t hfir;
+ /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
+ volatile uint32_t hfnum;
+ /** Reserved. <i>Offset: 40Ch</i> */
+ uint32_t reserved40C;
+ /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
+ volatile uint32_t hptxsts;
+ /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
+ volatile uint32_t haint;
+ /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
+ volatile uint32_t haintmsk;
+} dwc_otg_host_global_regs_t;
+
+/**
+ * This union represents the bit fields in the Host Configuration Register.
+ * Read the register into the <i>d32</i> member then set/clear the bits using
+ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
+ */
+typedef union hcfg_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ /** FS/LS Phy Clock Select */
+ unsigned fslspclksel : 2;
+#define DWC_HCFG_30_60_MHZ 0
+#define DWC_HCFG_48_MHZ 1
+#define DWC_HCFG_6_MHZ 2
+
+ /** FS/LS Only Support */
+ unsigned fslssupp : 1;
+ } b;
+} hcfg_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfir_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ unsigned frint : 16;
+ unsigned reserved : 16;
+ } b;
+} hfir_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfnum_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ unsigned frnum : 16;
+#define DWC_HFNUM_MAX_FRNUM 0x3FFF
+ unsigned frrem : 16;
+ } b;
+} hfnum_data_t;
+
+typedef union hptxsts_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ unsigned ptxfspcavail : 16;
+ unsigned ptxqspcavail : 8;
+ /** Top of the Periodic Transmit Request Queue
+ * - bit 24 - Terminate (last entry for the selected channel)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - Zero length
+ * - 2'b01 - Ping
+ * - 2'b10 - Disable
+ * - bits 30:27 - Channel Number
+ * - bit 31 - Odd/even microframe
+ */
+ unsigned ptxqtop_terminate : 1;
+ unsigned ptxqtop_token : 2;
+ unsigned ptxqtop_chnum : 4;
+ unsigned ptxqtop_odd : 1;
+ } b;
+} hptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Port Control and Status
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hprt0 register.
+ */
+typedef union hprt0_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned prtconnsts : 1;
+ unsigned prtconndet : 1;
+ unsigned prtena : 1;
+ unsigned prtenchng : 1;
+ unsigned prtovrcurract : 1;
+ unsigned prtovrcurrchng : 1;
+ unsigned prtres : 1;
+ unsigned prtsusp : 1;
+ unsigned prtrst : 1;
+ unsigned reserved9 : 1;
+ unsigned prtlnsts : 2;
+ unsigned prtpwr : 1;
+ unsigned prttstctl : 4;
+ unsigned prtspd : 2;
+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
+#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
+ unsigned reserved19_31 : 13;
+ } b;
+} hprt0_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned ch0 : 1;
+ unsigned ch1 : 1;
+ unsigned ch2 : 1;
+ unsigned ch3 : 1;
+ unsigned ch4 : 1;
+ unsigned ch5 : 1;
+ unsigned ch6 : 1;
+ unsigned ch7 : 1;
+ unsigned ch8 : 1;
+ unsigned ch9 : 1;
+ unsigned ch10 : 1;
+ unsigned ch11 : 1;
+ unsigned ch12 : 1;
+ unsigned ch13 : 1;
+ unsigned ch14 : 1;
+ unsigned ch15 : 1;
+ unsigned reserved : 16;
+ } b;
+
+ struct
+ {
+ unsigned chint : 16;
+ unsigned reserved : 16;
+ } b2;
+} haint_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haintmsk_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ unsigned ch0 : 1;
+ unsigned ch1 : 1;
+ unsigned ch2 : 1;
+ unsigned ch3 : 1;
+ unsigned ch4 : 1;
+ unsigned ch5 : 1;
+ unsigned ch6 : 1;
+ unsigned ch7 : 1;
+ unsigned ch8 : 1;
+ unsigned ch9 : 1;
+ unsigned ch10 : 1;
+ unsigned ch11 : 1;
+ unsigned ch12 : 1;
+ unsigned ch13 : 1;
+ unsigned ch14 : 1;
+ unsigned ch15 : 1;
+ unsigned reserved : 16;
+ } b;
+
+ struct
+ {
+ unsigned chint : 16;
+ unsigned reserved : 16;
+ } b2;
+} haintmsk_data_t;
+
+/**
+ * Host Channel Specific Registers. <i>500h-5FCh</i>
+ */
+typedef struct dwc_otg_hc_regs
+{
+ /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
+ volatile uint32_t hcchar;
+ /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
+ volatile uint32_t hcsplt;
+ /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
+ volatile uint32_t hcint;
+ /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
+ volatile uint32_t hcintmsk;
+ /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
+ volatile uint32_t hctsiz;
+ /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
+ volatile uint32_t hcdma;
+ /** Reserved. <i>Offset: 500h + (chan_num * 20h) + 18h - 500h + (chan_num * 20h) + 1Ch</i> */
+ uint32_t reserved[2];
+} dwc_otg_hc_regs_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Characteristics
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+typedef union hcchar_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ /** Maximum packet size in bytes */
+ unsigned mps : 11;
+
+ /** Endpoint number */
+ unsigned epnum : 4;
+
+ /** 0: OUT, 1: IN */
+ unsigned epdir : 1;
+
+ unsigned reserved : 1;
+
+ /** 0: Full/high speed device, 1: Low speed device */
+ unsigned lspddev : 1;
+
+ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
+ unsigned eptype : 2;
+
+ /** Packets per frame for periodic transfers. 0 is reserved. */
+ unsigned multicnt : 2;
+
+ /** Device address */
+ unsigned devaddr : 7;
+
+ /**
+ * Frame to transmit periodic transaction.
+ * 0: even, 1: odd
+ */
+ unsigned oddfrm : 1;
+
+ /** Channel disable */
+ unsigned chdis : 1;
+
+ /** Channel enable */
+ unsigned chen : 1;
+ } b;
+} hcchar_data_t;
+
+typedef union hcsplt_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ /** Port Address */
+ unsigned prtaddr : 7;
+
+ /** Hub Address */
+ unsigned hubaddr : 7;
+
+ /** Transaction Position */
+ unsigned xactpos : 2;
+#define DWC_HCSPLIT_XACTPOS_MID 0
+#define DWC_HCSPLIT_XACTPOS_END 1
+#define DWC_HCSPLIT_XACTPOS_BEGIN 2
+#define DWC_HCSPLIT_XACTPOS_ALL 3
+
+ /** Do Complete Split */
+ unsigned compsplt : 1;
+
+ /** Reserved */
+ unsigned reserved : 14;
+
+ /** Split Enble */
+ unsigned spltena : 1;
+ } b;
+} hcsplt_data_t;
+
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union hcint_data
+{
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct
+ {
+ /** Transfer Complete */
+ unsigned xfercomp : 1;
+ /** Channel Halted */
+ unsigned chhltd : 1;
+ /** AHB Error */
+ unsigned ahberr : 1;
+ /** STALL Response Received */
+ unsigned stall : 1;
+ /** NAK Response Received */
+ unsigned nak : 1;
+ /** ACK Response Received */
+ unsigned ack : 1;
+ /** NYET Response Received */
+ unsigned nyet : 1;
+ /** Transaction Err */
+ unsigned xacterr : 1;
+ /** Babble Error */
+ unsigned bblerr : 1;
+ /** Frame Overrun */
+ unsigned frmovrun : 1;
+ /** Data Toggle Error */
+ unsigned datatglerr : 1;
+ /** Reserved */
+ unsigned reserved : 21;
+ } b;
+} hcint_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Transfer Size
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+typedef union hctsiz_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ /** Total transfer size in bytes */
+ unsigned xfersize : 19;
+
+ /** Data packets to transfer */
+ unsigned pktcnt : 10;
+
+ /**
+ * Packet ID for next data packet
+ * 0: DATA0
+ * 1: DATA2
+ * 2: DATA1
+ * 3: MDATA (non-Control), SETUP (Control)
+ */
+ unsigned pid : 2;
+#define DWC_HCTSIZ_DATA0 0
+#define DWC_HCTSIZ_DATA1 2
+#define DWC_HCTSIZ_DATA2 1
+#define DWC_HCTSIZ_MDATA 3
+#define DWC_HCTSIZ_SETUP 3
+
+ /** Do PING protocol when 1 */
+ unsigned dopng : 1;
+ } b;
+} hctsiz_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Interrupt Mask
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcintmsk register.
+ */
+typedef union hcintmsk_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ unsigned xfercompl : 1;
+ unsigned chhltd : 1;
+ unsigned ahberr : 1;
+ unsigned stall : 1;
+ unsigned nak : 1;
+ unsigned ack : 1;
+ unsigned nyet : 1;
+ unsigned xacterr : 1;
+ unsigned bblerr : 1;
+ unsigned frmovrun : 1;
+ unsigned datatglerr : 1;
+ unsigned reserved : 21;
+ } b;
+} hcintmsk_data_t;
+
+/** OTG Host Interface Structure.
+ *
+ * The OTG Host Interface Structure structure contains information
+ * needed to manage the DWC_otg controller acting in host mode. It
+ * represents the programming view of the host-specific aspects of the
+ * controller.
+ */
+typedef struct dwc_otg_host_if
+{
+ /** Host Global Registers starting at offset 400h.*/
+ dwc_otg_host_global_regs_t *host_global_regs;
+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
+
+ /** Host Port 0 Control and Status Register */
+ volatile uint32_t *hprt0;
+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
+
+
+ /** Host Channel Specific Registers at offsets 500h-5FCh. */
+ dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
+#define DWC_OTG_CHAN_REGS_OFFSET 0x20
+
+
+ /* Host configuration information */
+ /** Number of Host Channels (range: 1-16) */
+ uint8_t num_host_channels;
+ /** Periodic EPs supported (0: no, 1: yes) */
+ uint8_t perio_eps_supported;
+ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
+ uint16_t perio_tx_fifo_size;
+
+} dwc_otg_host_if_t;
+
+
+/**
+ * This union represents the bit fields in the Power and Clock Gating Control
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union pcgcctl_data
+{
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct
+ {
+ /** Stop Pclk */
+ unsigned stoppclk : 1;
+ /** Gate Hclk */
+ unsigned gatehclk : 1;
+ /** Power Clamp */
+ unsigned pwrclmp : 1;
+ /** Reset Power Down Modules */
+ unsigned rstpdwnmodule : 1;
+ /** PHY Suspended */
+ unsigned physuspended : 1;
+
+ unsigned reserved : 27;
+ } b;
+} pcgcctl_data_t;
+
+#define DWC_OTG_EP_TYPE_CONTROL 0
+#define DWC_OTG_EP_TYPE_ISOC 1
+#define DWC_OTG_EP_TYPE_BULK 2
+#define DWC_OTG_EP_TYPE_INTR 3
+
+
+int dwc_core_init(void);
+
+static void dwc_otg_core_init(void);
+static int dwc_otg_pcd_init(void);
+static void dwc_otg_core_reset(void);
+static void dwc_otg_enable_common_interrupts(void);
+static void dwc_otg_enable_device_interrupts(void);
+static void dwc_otg_enable_global_interrupts(void);
+static void dwc_otg_core_dev_init(void);
+static void dwc_otg_flush_tx_fifo( const int _num ) ;
+static void dwc_otg_flush_rx_fifo(void) ;
+int dwc_otg_ep_req_start(pcd_struct_t * _pcd,int ep_num);
+void dwc_otg_ep_start_transfer(dwc_ep_t *_ep);
+static void dwc_otg_bulk_ep_activate(dwc_ep_t *ep);
+void dwc_otg_power_off_phy(void);
+void dwc_otg_pullup(int is_on);
+int dwc_otg_bulk_ep_enable(int is_in);//Added by Sam
+
+#endif
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.c
new file mode 100644
index 0000000000..da5d371280
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.c
@@ -0,0 +1,1286 @@
+/* dwc controller pcd interrupt drivers */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-30 @ Shanghai
+ *
+ */
+#include "platform.h"
+#include "usb_ch9.h"
+#include "dwc_pcd.h"
+#include "dwc_pcd_irq.h"
+//#define flush_cpu_cache()
+extern void do_gadget_setup( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl);
+extern void do_vendor_request( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl);
+extern void do_vendor_out_complete( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl);
+extern void do_bulk_complete( pcd_struct_t *_pcd);
+extern void do_modify_memory(u16 opcode,char * inbuff);
+
+static void ep0_out_start(void);
+static int32_t ep0_complete_request( pcd_struct_t * pcd);
+/**
+ * This function starts the Zero-Length Packet for the IN status phase
+ * of a 2 stage control transfer.
+ */
+static void do_setup_in_status_phase( pcd_struct_t *_pcd)
+{
+ dwc_ep_t *ep0 = &g_dwc_eps[0];
+ if (_pcd->ep0state == EP0_STALL) {
+ return;
+ }
+
+ _pcd->ep0state = EP0_STATUS;
+
+ DBG( "EP0 IN ZLP\n");
+ ep0->xfer_len = 0;
+ ep0->xfer_count = 0;
+ ep0->is_in = 1;
+
+ dwc_otg_ep_start_transfer( ep0 );
+
+ /* Prepare for more SETUP Packets */
+ ep0_out_start();
+
+}
+/**
+ * This function starts the Zero-Length Packet for the OUT status phase
+ * of a 2 stage control transfer.
+ */
+static void do_setup_out_status_phase( pcd_struct_t *_pcd)
+{
+ dwc_ep_t *ep0 = &g_dwc_eps[0];
+ if (_pcd->ep0state == EP0_STALL) {
+ return;
+ }
+ _pcd->ep0state = EP0_STATUS;
+
+ /* Prepare for more SETUP Packets */
+ //ep0_out_start( GET_CORE_IF(_pcd), _pcd );
+
+ DBG( "EP0 OUT ZLP\n");
+ ep0->xfer_len = 0;
+ ep0->xfer_count = 0;
+ ep0->is_in = 0;
+ dwc_otg_ep_start_transfer( ep0 );
+
+ /* Prepare for more SETUP Packets */
+ ep0_out_start( );
+
+}
+
+static void pcd_out_completed(pcd_struct_t *_pcd)
+{
+ if (_pcd->cmdtype.out_complete && _pcd->cmdtype.in_complete)
+ {
+ _pcd->cmdtype.setup_complete = _pcd->cmdtype.out_complete = _pcd->cmdtype.in_complete = 0;
+ do_vendor_out_complete(_pcd,(struct usb_ctrlrequest*)&_pcd->setup_pkt);
+ }
+}
+
+static void pcd_in_completed(pcd_struct_t *_pcd)
+{
+ do_vendor_in_complete(_pcd,(struct usb_ctrlrequest*)&_pcd->setup_pkt);
+}
+
+
+static void pcd_setup( pcd_struct_t *_pcd )
+{
+
+ struct usb_ctrlrequest ctrl = _pcd->setup_pkt.req;
+ dwc_ep_t *ep0 = &g_dwc_eps[0];
+ /*deptsiz0_data_t doeptsize0 = { 0};*/
+
+ if (_pcd->request_enable == 0)
+ return;
+
+ // _pcd->setup_pkt.d32[0] = 0;
+ // _pcd->setup_pkt.d32[1] = 0;
+ _pcd->status = 0;
+ _pcd->request_enable = 0;
+
+ /*doeptsize0.d32 = dwc_read_reg32( DWC_REG_OUT_EP_TSIZE(0));*/
+
+ if (ctrl.bRequestType & USB_DIR_IN) {
+ ep0->is_in = 1;
+ _pcd->ep0state = EP0_IN_DATA_PHASE;
+ } else {
+ ep0->is_in = 0;
+ _pcd->ep0state = EP0_OUT_DATA_PHASE;
+ }
+
+
+ if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+ {
+ /* handle non-standard (class/vendor) requests in the gadget driver */
+ //do_gadget_setup(_pcd, &ctrl );
+ DBG("Vendor requset\n");
+ do_vendor_request(_pcd, &ctrl );
+ dwc_otg_ep_req_start(_pcd,0);
+ return;
+ }
+
+ /** @todo NGS: Handle bad setup packet? */
+
+ switch (ctrl.bRequest)
+ {
+ case USB_REQ_GET_STATUS:
+
+ _pcd->status = 0;
+ switch (ctrl.bRequestType & USB_RECIP_MASK) {
+
+ case USB_RECIP_DEVICE:
+ _pcd->status = 0; /* Default Bus Powered, no Remote wakeup */
+ //_pcd->status |= 0x1; /* Self powered */
+ //_pcd->status |= 0x2;//_pcd->remote_wakeup_enable << 1;
+ break;
+
+ case USB_RECIP_INTERFACE:
+ _pcd->status = 0;
+ break;
+ }
+ _pcd->buf = (char *)&_pcd->status;
+ _pcd->length = 2;
+ dwc_otg_ep_req_start(_pcd,0);
+ break;
+#if 0
+ case USB_RECIP_INTERFACE:
+ *status = 0;
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ ep = get_ep_by_addr(_pcd, ctrl.wIndex);
+ if ( ep == 0 || ctrl.wLength > 2) {
+ ep0_do_stall(_pcd, -EOPNOTSUPP);
+ return;
+ }
+ /** @todo check for EP stall */
+ *status = ep->stopped;
+ break;
+ _pcd->ep0_pending = 1;
+
+ ep0->dwc_ep.start_xfer_buff = (uint8_t *)status;
+ ep0->dwc_ep.xfer_buff = (uint8_t *)status;
+ ep0->dwc_ep.dma_addr = _pcd->status_buf_dma_handle;
+ ep0->dwc_ep.xfer_len = 2;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+ dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep );
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ do_clear_feature( _pcd );
+ break;
+
+ case USB_REQ_SET_FEATURE:
+ do_set_feature( _pcd );
+ break;
+#endif
+ case USB_REQ_SET_ADDRESS:
+ if (ctrl.bRequestType == USB_RECIP_DEVICE)
+ {
+ dcfg_data_t dcfg = { 0 };
+
+ printf("Set Addr %d\n",ctrl.wValue);
+ dcfg.b.devaddr = ctrl.wValue;
+ dwc_modify_reg32(DWC_REG_DCFG,0, dcfg.d32);
+ do_setup_in_status_phase( _pcd );
+ return;
+ }
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ case USB_REQ_SET_CONFIGURATION:
+ _pcd->request_config = 1; /* Configuration changed */
+ do_gadget_setup(_pcd, &ctrl );
+ dwc_otg_ep_req_start(_pcd,0);
+ break;
+
+ default:
+ /* Call the Gadget Driver's setup functions */
+ do_gadget_setup(_pcd, &ctrl );
+ dwc_otg_ep_req_start(_pcd,0);
+ break;
+ }
+}
+
+/**
+ * This function handles EP0 Control transfers.
+ *
+ * The state of the control tranfers are tracked in
+ * <code>ep0state</code>.
+ * is_in : 1 -- IN Trans
+ * is_in : 0 -- OUT/SETUP Trans
+ */
+static void handle_ep0( int is_in )
+{
+ pcd_struct_t * _pcd = &this_pcd;//Oh, this_pcd
+ dwc_ep_t * ep0 = &g_dwc_eps[0];
+
+ switch (_pcd->ep0state)
+ {
+ case EP0_DISCONNECT:
+ DBG("EP0 DISCONNECT\n");
+ break;
+
+ case EP0_IDLE:
+ _pcd->request_config = 0;
+ DBG("Enter PCD Setup()\n");
+ pcd_setup( _pcd );
+ break;
+
+ case EP0_IN_DATA_PHASE:
+
+ if (ep0->xfer_count < ep0->total_len) {
+ DBG("FIX ME!! dwc_otg_ep0_continue_transfer!\n");
+ //dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep );
+ }
+ else {
+ ep0_complete_request( _pcd );
+ pcd_in_completed(_pcd);/////////////
+ }
+ break;
+
+ case EP0_OUT_DATA_PHASE:
+ ep0_complete_request(_pcd );
+ _pcd->cmdtype.in_complete = 1;
+ pcd_out_completed(_pcd);
+ break;
+
+
+ case EP0_STATUS:
+
+ ep0_complete_request( _pcd );
+ _pcd->ep0state = EP0_IDLE;
+ ep0->stopped = 1;
+ ep0->is_in = 0; /* OUT for next SETUP */
+
+ break;
+
+ case EP0_STALL:
+ ERR("EP0 STALLed, should not get here pcd_setup()\n");
+ break;
+ }
+
+ return ;
+}
+
+/**
+ * This function completes the request for the EP. If there are
+ * additional requests for the EP in the queue they will be started.
+ */
+static void complete_ep( int ep_num,int is_in )
+{
+ deptsiz_data_t deptsiz;
+ pcd_struct_t *pcd = &this_pcd;
+ dwc_ep_t *ep = &g_dwc_eps[ep_num];
+
+ if (is_in)
+ {
+ pcd->xfer_len = ep->xfer_count;////////////////
+
+ deptsiz.d32 = dwc_read_reg32(DWC_REG_IN_EP_TSIZE(ep_num));
+ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 &&
+ ep->xfer_count == ep->xfer_len)
+ {
+
+ ep->start_xfer_buff = 0;
+ ep->xfer_buff = 0;
+ ep->xfer_len = 0;
+ }
+ }
+ else
+ {/* OUT Transfer */
+
+ deptsiz.d32 = dwc_read_reg32(DWC_REG_OUT_EP_TSIZE(ep_num));
+
+ pcd->xfer_len = ep->xfer_count;
+
+ ep->start_xfer_buff = 0;
+ ep->xfer_buff = 0;
+ ep->xfer_len = 0;
+ }
+
+ do_bulk_complete(pcd);
+}
+/**
+ * This function completes the ep0 control transfer.
+ */
+static int32_t ep0_complete_request( pcd_struct_t * pcd)
+{
+
+ deptsiz0_data_t deptsiz;
+ int is_last = 0;
+ dwc_ep_t* ep = &g_dwc_eps[0];
+
+ DBG("ep0_complete_request()\n");
+ if (pcd->ep0state == EP0_STATUS)
+ {
+ is_last = 1;
+ }
+ else if (ep->xfer_len == 0)
+ {
+ ep->xfer_len = 0;
+ ep->xfer_count = 0;
+ ep->sent_zlp = 1;
+ dwc_otg_ep_start_transfer( ep );
+ return 1;
+ }
+ else if (ep->is_in)
+ {
+ deptsiz.d32 = dwc_read_reg32(DWC_REG_IN_EP_TSIZE(0) );
+ if (deptsiz.b.xfersize == 0) {
+ /* Is a Zero Len Packet needed? */
+ do_setup_out_status_phase(pcd);
+ }
+ }
+ else {
+ /* ep0-OUT */
+ do_setup_in_status_phase(pcd);
+ }
+
+ /* Complete the request */
+ if (is_last) {
+ ep->start_xfer_buff = 0;
+ ep->xfer_buff = 0;
+ ep->xfer_len = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * This function reads a packet from the Rx FIFO into the destination
+ * buffer. To read SETUP data use dwc_otg_read_setup_packet.
+ *
+ * @param _dest Destination buffer for the packet.
+ * @param _bytes Number of bytes to copy to the destination.
+ */
+static void dwc_otg_read_packet(uint8_t *_dest, uint16_t _bytes) //Elvis Fool, add 'static'
+{
+ int i;
+ /*const char* str = (char*)_dest;*/
+ uint32_t* pu32 = (uint32_t*)_dest;
+ const unsigned lenIn32 = (_bytes>>2);
+ const unsigned rest = (_bytes & 3);
+
+ /**
+ * @todo Account for the case where _dest is not dword aligned. This
+ * requires reading data from the FIFO into a uint32_t temp buffer,
+ * then moving it into the data buffer.
+ */
+ //DBG("dwc_otg_read_packet() dest: %p, len: %d\n",_dest,_bytes);
+ for (i = 0; i < lenIn32; ++i)
+ {
+ *pu32++ = dwc_read_reg32(DWC_REG_DATA_FIFO_START);
+ }
+ if (rest)
+ {
+ const unsigned fifoVal = dwc_read_reg32(DWC_REG_DATA_FIFO_START);
+ uint8_t* pBufDst8 = (uint8_t*)pu32;
+ const uint8_t* pBufSrc8 = (const uint8_t*)&fifoVal;
+ for (i = 0; i < rest; ++i)
+ {
+ *pBufDst8++ = *pBufSrc8++;
+ }
+ }
+
+ /*
+ *if(!strcmp("power", str))
+ * printf("%d>", _bytes),printf(str),printf("\n");
+ */
+
+ return;
+}
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the
+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For
+ * periodic EPs the periodic Tx FIFO associated with the EP is written
+ * with all packets for the next micro-frame.
+ *
+ * @param _core_if Programming view of DWC_otg controller.
+ * @param _ep The EP to write packet for.
+ * @param _dma Indicates if DMA is being used.
+ */
+void dwc_otg_ep_write_packet( dwc_ep_t *_ep)
+{
+ /**
+ * The buffer is padded to DWORD on a per packet basis in
+ * slave/dma mode if the MPS is not DWORD aligned. The last
+ * packet, if short, is also padded to a multiple of DWORD.
+ *
+ * ep->xfer_buff always starts DWORD aligned in memory and is a
+ * multiple of DWORD in length
+ *
+ * ep->xfer_len can be any number of bytes
+ *
+ * ep->xfer_count is a multiple of ep->maxpacket until the last
+ * packet
+ *
+ * FIFO access is DWORD */
+
+ uint32_t i;
+ uint32_t byte_count;
+ uint32_t dword_count;
+ uint32_t fifo;
+ uint8_t *data_buff = _ep->xfer_buff;
+ uint32_t temp_data ;
+
+ //DBG("dwc_otg_ep_write_packet() : %d\n",_ep->xfer_len);
+ if (_ep->xfer_count >= _ep->xfer_len) {
+ //DWC_WARN("%s() No data for EP%d!!!\n", "dwc_otg_ep_write_packet", _ep->num);
+ return;
+ }
+
+ /* Find the byte length of the packet either short packet or MPS */
+ if ((_ep->xfer_len - _ep->xfer_count) < _ep->maxpacket) {
+ byte_count = _ep->xfer_len - _ep->xfer_count;
+ }
+ else {
+ byte_count = _ep->maxpacket;
+ }
+
+ /* Find the DWORD length, padded by extra bytes as neccessary if MPS
+ * is not a multiple of DWORD */
+ dword_count = (byte_count + 3) / 4;
+
+
+ //fifo = _core_if->data_fifo[_ep->num];
+ fifo = DWC_REG_DATA_FIFO(_ep->num);
+
+
+ for (i=0; i<dword_count; i++) {
+ temp_data =get_unaligned(data_buff);
+ dwc_write_reg32( fifo, temp_data );
+ data_buff += 4;
+ }
+
+
+ _ep->xfer_count += byte_count;
+ _ep->xfer_buff += byte_count;
+
+ flush_cpu_cache();
+
+}
+/**
+ * This function reads a setup packet from the Rx FIFO into the destination
+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
+ * Interrupt routine when a SETUP packet has been received in Slave mode.
+ *
+ * @param _core_if Programming view of DWC_otg controller.
+ * @param _dest Destination buffer for packet data.
+ */
+void dwc_otg_read_setup_packet(uint32_t *_dest)
+{
+ /* Get the 8 bytes of a setup transaction data */
+
+ DBG("dwc_otg_read_setup_packet()\n");
+ /* Pop 2 DWORDS off the receive data FIFO into memory */
+ _dest[0] = dwc_read_reg32(DWC_REG_DATA_FIFO_START);
+ _dest[1] = dwc_read_reg32(DWC_REG_DATA_FIFO_START);
+}
+
+
+
+/**
+ * handle the IN EP disable interrupt.
+ */
+static void handle_in_ep_disable_intr(uint32_t _epnum)
+{
+#if 0
+ deptsiz_data_t dieptsiz = { 0 };
+ dctl_data_t dctl = { 0 };
+ depctl_data_t diepctl = { 0 };
+ dwc_ep_t *ep = &g_dwc_eps[_epnum];
+
+ if (ep->stopped) {
+ /* Flush the Tx FIFO */
+ /** @todo NGS: This is not the correct FIFO */
+ dwc_otg_flush_tx_fifo( core_if, 0 );
+ /* Clear the Global IN NP NAK */
+ dctl.d32 = 0;
+ dctl.b.cgnpinnak = 1;
+ dwc_modify_reg32(&dev_if->in_ep_regs[_epnum]->diepctl,
+ diepctl.d32, diepctl.d32);
+ /* Restart the transaction */
+ if (dieptsiz.b.pktcnt != 0 ||
+ dieptsiz.b.xfersize != 0) {
+ restart_transfer( _pcd, _epnum );
+ }
+ }
+#endif
+}
+
+/**
+ * Handler for the IN EP timeout handshake interrupt.
+ */
+static void handle_in_ep_timeout_intr(uint32_t _epnum)
+{
+
+ dctl_data_t dctl = { 0 };
+ dwc_ep_t *ep = &g_dwc_eps[_epnum];
+
+ gintmsk_data_t intr_mask = {0};
+
+
+ /* Disable the NP Tx Fifo Empty Interrrupt */
+
+ intr_mask.b.nptxfempty = 1;
+ dwc_modify_reg32( DWC_REG_GINTMSK, intr_mask.d32, 0);
+ /** @todo NGS Check EP type.
+ * Implement for Periodic EPs */
+ /*
+ * Non-periodic EP
+ */
+ /* Enable the Global IN NAK Effective Interrupt */
+ intr_mask.b.ginnakeff = 1;
+ dwc_modify_reg32( DWC_REG_GINTMSK, 0, intr_mask.d32);
+
+ /* Set Global IN NAK */
+ dctl.b.sgnpinnak = 1;
+ dwc_modify_reg32( DWC_REG_DCTL,dctl.d32, dctl.d32);
+
+ ep->stopped = 1;
+
+}
+
+///////////////////////////////////////////////////////////////////////
+/**
+ * This function handles the Rx Status Queue Level Interrupt, which
+ * indicates that there is a least one packet in the Rx FIFO. The
+ * packets are moved from the FIFO to memory, where they will be
+ * processed when the Endpoint Interrupt Register indicates Transfer
+ * Complete or SETUP Phase Done.
+ *
+ * Repeat the following until the Rx Status Queue is empty:
+ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
+ * info
+ * -# If Receive FIFO is empty then skip to step Clear the interrupt
+ * and exit
+ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
+ * SETUP data to the buffer
+ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
+ * to the destination buffer
+ */
+int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(void)
+{
+ gintmsk_data_t gintmask = { 0 };
+ device_grxsts_data_t status;
+ gintsts_data_t gintsts;
+ dwc_ep_t *ep;
+
+
+ DBG("dwc_otg_pcd_handle_rx_status_q_level_intr()\n");
+ /* Disable the Rx Status Queue Level interrupt */
+ gintmask.b.rxstsqlvl= 1;
+ dwc_modify_reg32( DWC_REG_GINTMSK, gintmask.d32, 0);
+
+ /* Get the Status from the top of the FIFO */
+ status.d32 = dwc_read_reg32( DWC_REG_GRXSTSP);
+
+ //DBG("rx status: ep%d, pktsts: %d\n",status.b.epnum,status.b.pktsts);
+
+ /* Get pointer to EP structure */
+ ep = &g_dwc_eps[status.b.epnum];
+
+ switch (status.b.pktsts)
+ {
+ case DWC_DSTS_GOUT_NAK:
+ DBG( "Global OUT NAK\n");
+ break;
+
+ case DWC_STS_DATA_UPDT:
+ DBG( "OUT Data Packet\n");
+ {
+ if (status.b.bcnt && ep->xfer_buff)
+ {
+ /** @todo NGS Check for buffer overflow? */
+ dwc_otg_read_packet( ep->xfer_buff,status.b.bcnt);
+ ep->xfer_count += status.b.bcnt;
+ ep->xfer_buff += status.b.bcnt;
+
+ if (!status.b.epnum)
+ {
+ /*const char* p = ep->xfer_buff - status.b.bcnt;*/
+ this_pcd.cmdtype.out_complete = 1;
+ /*
+ *if(!strcmp("power", p) || !strcmp("low_power", p)){
+ * printf("%s, bcnt %d, cnt %d, %d\n", p, status.b.bcnt, ep->xfer_count, this_pcd.cmdtype.in_complete);
+ *}
+ */
+ }
+ }
+ }
+ break;
+
+ case DWC_STS_XFER_COMP:
+ DBG("OUT Complete\n");
+ break;
+
+ case DWC_DSTS_SETUP_COMP:
+ DBG("SETUP Complete\n");
+ break;
+
+ case DWC_DSTS_SETUP_UPDT:
+ DBG("SETUP update\n");
+ {
+ static int _is_first_setup_out_in_cmd = 1;
+
+ dwc_otg_read_setup_packet( this_pcd.setup_pkt.d32);
+ this_pcd.request_enable = 1;
+ ep->xfer_count += status.b.bcnt;
+
+ DBG("set %d, %d\n", status.b.bcnt, ep->xfer_count);
+ if (_is_first_setup_out_in_cmd) //first tplcmd/bulkcmd that in sequence 'setup + out + in'
+ {
+ struct usb_ctrlrequest request = this_pcd.setup_pkt.req;
+ if ( USB_TYPE_VENDOR == (request.bRequestType & USB_TYPE_MASK) )
+ {
+ unsigned bRequest = request.bRequest;
+
+ if ((AM_REQ_WR_LARGE_MEM == bRequest) || (AM_REQ_RD_LARGE_MEM == bRequest)
+ ||(AM_REQ_TPL_CMD == bRequest) || (AM_REQ_TPL_STAT == bRequest)
+ || (AM_REQ_DOWNLOAD == bRequest) || (AM_REQ_BULKCMD == bRequest))
+ {
+ __udelay(20);//delay for first command that consisted of consecutive 'ep0 out', i.e. 'setup + out + in'
+ _is_first_setup_out_in_cmd = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ //DBG( "Invalid Packet Status (0x%0x)\n", status.b.pktsts);
+ break;
+
+ }
+
+ /* Enable the Rx Status Queue Level interrupt */
+ dwc_modify_reg32( DWC_REG_GINTMSK, 0, gintmask.d32);
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.rxstsqlvl = 1;
+ dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32);
+
+ return 1;
+}
+
+
+/**
+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
+ * The active request is checked for the next packet to be loaded into
+ * the non-periodic Tx FIFO.
+ */
+int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(void)
+{
+ gnptxsts_data_t txstatus = {0};
+ gintsts_data_t gintsts;
+
+ int epnum = 0;
+ dwc_ep_t *ep = 0;
+ uint32_t len = 0;
+ int dwords;
+ depctl_data_t depctl;
+
+ DBG("dwc_otg_pcd_handle_np_tx_fifo_empty_intr()\n");
+ /* Get the epnum from the IN Token Learning Queue. */
+ for (epnum=0; epnum < NUM_EP; epnum++)
+ {
+
+ ep = &g_dwc_eps[epnum];
+
+
+ /* IN endpoint ? */
+ if (epnum && !ep->is_in ) {
+ continue;
+ }
+ depctl.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(epnum));
+ if (depctl.b.epena != 1)
+ continue;
+
+ if (ep->type == DWC_OTG_EP_TYPE_INTR && ep->xfer_len == 0)
+ continue;
+
+ flush_cpu_cache();
+
+ len = ep->xfer_len - ep->xfer_count;
+ if (len > ep->maxpacket) {
+ len = ep->maxpacket;
+ }
+ dwords = (len + 3)/4;
+
+ //DBG("nptx: write data to fifo, ep%d , size %d\n",epnum,len);
+ /* While there is space in the queue and space in the FIFO and
+ * More data to tranfer, Write packets to the Tx FIFO */
+ txstatus.d32 = dwc_read_reg32( DWC_REG_GNPTXSTS );
+ while (txstatus.b.nptxqspcavail > 0 &&
+ txstatus.b.nptxfspcavail > dwords &&
+ ep->xfer_count < ep->xfer_len) {
+
+ flush_cpu_cache();
+
+ /* Write the FIFO */
+ dwc_otg_ep_write_packet( ep );
+
+ len = ep->xfer_len - ep->xfer_count;
+ if (len > ep->maxpacket) {
+ len = ep->maxpacket;
+ }
+ dwords = (len + 3)/4;
+ flush_cpu_cache();
+ //txstatus.d32 = dwc_read_reg32(DWC_REG_GNPTXSTS);
+#if 1
+ /*
+ TODO: Remove these code.
+ Because, if code break from "while"(Line427), an incomplete-in-trans will occour.
+ Then the tansfer will break.
+ */
+ int retry = 50000; //retry times
+ while (retry--)
+ {
+ txstatus.d32 = dwc_read_reg32(DWC_REG_GNPTXSTS);
+ if(txstatus.b.nptxqspcavail > 0 || //txstatus.b.nptxfspcavail <= dwords ||
+ ep->xfer_count >= ep->xfer_len)
+ break;
+ else
+ {
+ flush_cpu_cache();
+ }
+
+ }
+ if (retry <= 0)
+ {
+ //DWC_ERROR("TxFIFO FULL: Can't trans data to HOST !\n");
+ }
+
+ /* END todo */
+#endif
+ }
+
+ }
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.nptxfempty = 1;
+ dwc_write_reg32 (DWC_REG_GINTSTS, gintsts.d32);
+
+ return 1;
+}
+/**
+ * Read the device status register and set the device speed in the
+ * data structure.
+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
+ */
+int32_t dwc_otg_pcd_handle_enum_done_intr(void)
+{
+ gintsts_data_t gintsts;
+ gusbcfg_data_t gusbcfg;
+ /*dsts_data_t dsts;*/
+ depctl_data_t diepctl;
+ depctl_data_t doepctl;
+ dctl_data_t dctl ={0};
+
+ DBG("SPEED ENUM\n");
+
+ /* Read the Device Status and Endpoint 0 Control registers */
+ /*dsts.d32 = dwc_read_reg32(DWC_REG_DSTS);*/
+ diepctl.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(0) );
+ doepctl.d32 = dwc_read_reg32(DWC_REG_OUT_EP_REG(0));
+
+ /* Set the MPS of the IN EP based on the enumeration speed */
+ diepctl.b.mps = DWC_DEP0CTL_MPS_64;
+ dwc_write_reg32(DWC_REG_IN_EP_REG(0) , diepctl.d32);
+
+ /* Enable OUT EP for receive */
+ doepctl.b.epena = 1;
+ dwc_write_reg32(DWC_REG_OUT_EP_REG(0), doepctl.d32);
+
+ dctl.b.cgnpinnak = 1;
+ dwc_modify_reg32(DWC_REG_DCTL, dctl.d32, dctl.d32);
+
+ if (this_pcd.ep0state == EP0_DISCONNECT) {
+ this_pcd.ep0state = EP0_IDLE;
+ } else if (this_pcd.ep0state == EP0_STALL) {
+ this_pcd.ep0state = EP0_IDLE;
+ }
+
+ this_pcd.ep0state = EP0_IDLE;
+
+
+ /* Set USB turnaround time based on device speed and PHY interface. */
+ gusbcfg.d32 = dwc_read_reg32(DWC_REG_GUSBCFG);
+#if 0
+ if (_pcd->gadget.speed == USB_SPEED_HIGH) {
+ if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
+ /* ULPI interface */
+ gusbcfg.b.usbtrdtim = 9;
+ }
+ if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
+ /* UTMI+ interface */
+ if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) {
+ gusbcfg.b.usbtrdtim = 5;
+ } else {
+ gusbcfg.b.usbtrdtim = 9;
+ }
+ }
+ if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
+ /* UTMI+ OR ULPI interface */
+ if (gusbcfg.b.ulpi_utmi_sel == 1) {
+ /* ULPI interface */
+ gusbcfg.b.usbtrdtim = 9;
+ } else {
+ /* UTMI+ interface */
+ if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) {
+ gusbcfg.b.usbtrdtim = 5;
+ } else {
+ gusbcfg.b.usbtrdtim = 9;
+ }
+ }
+ }
+ } else {
+ /* Full or low speed */
+ gusbcfg.b.usbtrdtim = 9;
+ }
+#else
+ /* Full or low speed */
+ gusbcfg.b.usbtrdtim = 5;
+#endif
+ dwc_write_reg32(DWC_REG_GUSBCFG, gusbcfg.d32);
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.enumdone = 1;
+ dwc_write_reg32(DWC_REG_GINTSTS,gintsts.d32 );
+ return 1;
+}
+///////////////////////////////////////////////////////////////////
+/**
+ * This interrupt indicates that an OUT EP has a pending Interrupt.
+ * The sequence for handling the OUT EP interrupt is shown below:
+ * -# Read the Device All Endpoint Interrupt register
+ * -# Repeat the following for each OUT EP interrupt bit set (from
+ * LSB to MSB).
+ * -# Read the Device Endpoint Interrupt (DOEPINTn) register
+ * -# If "Transfer Complete" call the request complete function
+ * -# If "Endpoint Disabled" complete the EP disable procedure.
+ * -# If "AHB Error Interrupt" log error
+ * -# If "Setup Phase Done" process Setup Packet (See Standard USB
+ * Command Processing)
+ */
+static int32_t dwc_otg_pcd_handle_out_ep_intr(void)
+{
+#define CLEAR_OUT_EP_INTR(__epnum,__intr) \
+do { \
+ doepint_data_t doepint = { 0 }; \
+ doepint.b.__intr = 1; \
+ dwc_write_reg32(DWC_REG_OUT_EP_INTR(__epnum), \
+ doepint.d32); \
+} while (0)
+
+ uint32_t ep_intr;
+ doepint_data_t doepint = { 0 };
+ uint32_t epnum = 0;
+// uint32_t epnum_trans = 0;
+ gintsts_data_t gintsts;
+
+ DBG( "dwc_otg_pcd_handle_out_ep_intr()\n" );
+
+ /* Read in the device interrupt bits */
+ ep_intr = (dwc_read_reg32(DWC_REG_DAINT) &
+ dwc_read_reg32( DWC_REG_DAINTMSK));
+ ep_intr =( (ep_intr & 0xffff0000) >> 16);
+
+ /* Clear the OUTEPINT in GINTSTS */
+ gintsts.d32 = 0;
+ gintsts.b.outepintr = 1;
+ dwc_write_reg32 (DWC_REG_GINTSTS, gintsts.d32);
+ dwc_write_reg32(DWC_REG_DAINT, 0xFFFF0000 );
+
+ while ( ep_intr ) {
+ if (ep_intr&0x1) {
+ doepint.d32 = (dwc_read_reg32( DWC_REG_OUT_EP_INTR(epnum)) &
+ dwc_read_reg32(DWC_REG_DOEPMSK));
+
+ /* Transfer complete */
+ if ( doepint.b.xfercompl ) {
+ DBG("EP%d OUT Xfer Complete\n", epnum);
+
+ /* Clear the bit in DOEPINTn for this interrupt */
+ CLEAR_OUT_EP_INTR(epnum,xfercompl);
+
+ if (epnum == 0) {
+ handle_ep0( 0 );
+ } else {
+ complete_ep( epnum,0 );
+ }
+ }
+ /* Endpoint disable */
+ if ( doepint.b.epdisabled ) {
+ DBG("EP%d OUT disabled\n", epnum);
+ /* Clear the bit in DOEPINTn for this interrupt */
+ CLEAR_OUT_EP_INTR(epnum,epdisabled);
+ }
+ /* AHB Error */
+ if ( doepint.b.ahberr ) {
+ DBG("EP%d OUT AHB Error\n", epnum);
+ CLEAR_OUT_EP_INTR(epnum,ahberr);
+ }
+ /* Setup Phase Done (contorl EPs) */
+ if ( doepint.b.setup ) {
+ handle_ep0( 0 );
+ CLEAR_OUT_EP_INTR(epnum,setup);
+ }
+ }
+ epnum++;
+ ep_intr >>=1;
+ }
+
+ return 1;
+
+#undef CLEAR_OUT_EP_INTR
+}
+/**
+ * This interrupt indicates that an IN EP has a pending Interrupt.
+ * The sequence for handling the IN EP interrupt is shown below:
+ * -# Read the Device All Endpoint Interrupt register
+ * -# Repeat the following for each IN EP interrupt bit set (from
+ * LSB to MSB).
+ * -# Read the Device Endpoint Interrupt (DIEPINTn) register
+ * -# If "Transfer Complete" call the request complete function
+ * -# If "Endpoint Disabled" complete the EP disable procedure.
+ * -# If "AHB Error Interrupt" log error
+ * -# If "Time-out Handshake" log error
+ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
+ * FIFO.
+ * -# If "IN Token EP Mismatch" (disable, this is handled by EP
+ * Mismatch Interrupt)
+ */
+static int32_t dwc_otg_pcd_handle_in_ep_intr(void)
+{
+#define CLEAR_IN_EP_INTR(__epnum,__intr) \
+do { \
+ diepint_data_t diepint = { 0 }; \
+ diepint.b.__intr = 1; \
+ dwc_write_reg32(DWC_REG_IN_EP_INTR(__epnum), \
+ diepint.d32); \
+} while (0)
+
+ diepint_data_t diepint = { 0 };
+// depctl_data_t diepctl = { 0 };
+ uint32_t ep_intr;
+ uint32_t epnum = 0;
+ gintmsk_data_t intr_mask = {0};
+ gintsts_data_t gintsts;
+
+ DBG( "dwc_otg_pcd_handle_in_ep_intr()\n" );
+
+ /* Read in the device interrupt bits */
+ ep_intr = (dwc_read_reg32(DWC_REG_DAINT) &
+ dwc_read_reg32( DWC_REG_DAINTMSK));
+ ep_intr =( (ep_intr & 0xffff) );
+
+
+ /* Clear the INEPINT in GINTSTS */
+ /* Clear all the interrupt bits for all IN endpoints in DAINT */
+ gintsts.d32 = 0;
+ gintsts.b.inepint = 1;
+ dwc_write_reg32 (DWC_REG_GINTSTS, gintsts.d32);
+ dwc_write_reg32(DWC_REG_DAINT, 0xFFFF );
+ flush_cpu_cache();
+
+ /* Service the Device IN interrupts for each endpoint */
+ while ( ep_intr ) {
+ if (ep_intr&0x1) {
+
+ diepint.d32 = (dwc_read_reg32( DWC_REG_IN_EP_INTR(epnum)) &
+ dwc_read_reg32(DWC_REG_DAINTMSK));
+ /* Transfer complete */
+ if ( diepint.b.xfercompl ) {
+
+
+ /* Disable the NP Tx FIFO Empty
+ * Interrrupt */
+ intr_mask.b.nptxfempty = 1;
+ dwc_modify_reg32( DWC_REG_GINTMSK, intr_mask.d32, 0);
+
+ /* Clear the bit in DIEPINTn for this interrupt */
+ CLEAR_IN_EP_INTR(epnum,xfercompl);
+
+ /* Complete the transfer */
+ if (epnum == 0) {
+ handle_ep0( 0 );
+ } else {
+ complete_ep( epnum,1 );
+ }
+ }
+ /* Endpoint disable */
+ if ( diepint.b.epdisabled ) {
+ handle_in_ep_disable_intr( epnum );
+
+ /* Clear the bit in DIEPINTn for this interrupt */
+ CLEAR_IN_EP_INTR(epnum,epdisabled);
+ }
+ /* AHB Error */
+ if ( diepint.b.ahberr ) {
+ /* Clear the bit in DIEPINTn for this interrupt */
+ CLEAR_IN_EP_INTR(epnum,ahberr);
+ }
+ /* TimeOUT Handshake (non-ISOC IN EPs) */
+ if ( diepint.b.timeout ) {
+ handle_in_ep_timeout_intr( epnum );
+
+ CLEAR_IN_EP_INTR(epnum,timeout);
+ }
+ /** IN Token received with TxF Empty */
+ if (diepint.b.intktxfemp) {
+#if 0
+ if (!ep->stopped && epnum != 0) {
+ diepmsk_data_t diepmsk = { 0};
+ diepmsk.b.intktxfemp = 1;
+ dwc_modify_reg32( &dev_if->dev_global_regs->diepmsk, diepmsk.d32, 0 );
+ start_next_request(ep);
+ }
+#endif
+ CLEAR_IN_EP_INTR(epnum,intktxfemp);
+ }
+ /** IN Token Received with EP mismatch */
+ if (diepint.b.intknepmis) {
+ CLEAR_IN_EP_INTR(epnum,intknepmis);
+ }
+ /** IN Endpoint NAK Effective */
+ if (diepint.b.inepnakeff) {
+ CLEAR_IN_EP_INTR(epnum,inepnakeff);
+ }
+ }
+ epnum++;
+ ep_intr >>=1;
+ }
+
+ return 1;
+
+#undef CLEAR_IN_EP_INTR
+}
+/**
+ * This function configures EP0 to receive SETUP packets.
+ *
+ * @todo NGS: Update the comments from the HW FS.
+ *
+ * -# Program the following fields in the endpoint specific registers
+ * for Control OUT EP 0, in order to receive a setup packet
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
+ * setup packets)
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
+ * to back setup packets)
+ * - In DMA mode, DOEPDMA0 Register with a memory address to
+ * store any setup packets received
+ *
+ */
+static void ep0_out_start(void)
+{
+ deptsiz0_data_t doeptsize0 = { 0};
+ depctl_data_t doepctl = { 0 };
+
+ doeptsize0.b.supcnt = 3;
+ doeptsize0.b.pktcnt = 1;
+ doeptsize0.b.xfersize = 8*3;
+
+ DBG("ep0_out_start()\n");
+ dwc_write_reg32( DWC_REG_OUT_EP_TSIZE(0),doeptsize0.d32 );
+
+
+ // EP enable
+ doepctl.d32 = dwc_read_reg32(DWC_REG_OUT_EP_REG(0));
+ doepctl.b.epena = 1;
+
+ doepctl.d32 = 0x80008000;
+ dwc_write_reg32(DWC_REG_OUT_EP_REG(0),doepctl.d32);
+
+ flush_cpu_cache();
+}
+/**
+ * This interrupt occurs when a USB Reset is detected. When the USB
+ * Reset Interrupt occurs the device state is set to DEFAULT and the
+ * EP0 state is set to IDLE.
+ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
+ * -# Unmask the following interrupt bits
+ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
+ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
+ * - DOEPMSK.SETUP = 1
+ * - DOEPMSK.XferCompl = 1
+ * - DIEPMSK.XferCompl = 1
+ * - DIEPMSK.TimeOut = 1
+ * -# Program the following fields in the endpoint specific registers
+ * for Control OUT EP 0, in order to receive a setup packet
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
+ * setup packets)
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
+ * to back setup packets)
+ * - In DMA mode, DOEPDMA0 Register with a memory address to
+ * store any setup packets received
+ * At this point, all the required initialization, except for enabling
+ * the control 0 OUT endpoint is done, for receiving SETUP packets.
+ */
+int32_t dwc_otg_pcd_handle_usb_reset_intr(void)
+{
+
+ depctl_data_t doepctl = { 0};
+ daint_data_t daintmsk = { 0};
+ doepmsk_data_t doepmsk = { 0};
+ diepmsk_data_t diepmsk = { 0};
+ dcfg_data_t dcfg = { 0 };
+ depctl_data_t diepctl = { 0};
+ depctl_data_t diepctl_rd = { 0};
+ grstctl_t resetctl = { 0 };
+ dctl_data_t dctl = { 0 };
+ int i = 0;
+ gintsts_data_t gintsts;
+
+
+ DBG("\nUSB RESET\n");
+
+
+ /* Clear the Remote Wakeup Signalling */
+ dctl.b.rmtwkupsig = 1;
+ dwc_modify_reg32( DWC_REG_DCTL,dctl.d32, 0 );
+
+ /* Disable all active IN EPs */
+ diepctl.b.epdis = 1;
+ diepctl.b.snak = 1;
+ for (i=0; i < NUM_EP; i++) {
+ diepctl_rd.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(i));
+ if (diepctl_rd.b.epena) {
+ dwc_write_reg32(DWC_REG_IN_EP_REG(i),diepctl.d32 );
+ }
+ }
+
+ /* Set NAK for all OUT EPs */
+ doepctl.b.snak = 1;
+ for (i=0; i < NUM_EP; i++) {
+ dwc_write_reg32(DWC_REG_OUT_EP_REG(i), doepctl.d32 );
+ }
+
+ /* Flush the NP Tx FIFO */
+ dwc_otg_flush_tx_fifo( 0 );
+ /* Flush the Learning Queue */
+ resetctl.b.intknqflsh = 1;
+ dwc_write_reg32( DWC_REG_GRSTCTL, resetctl.d32);
+
+ daintmsk.b.inep0 = 1;
+ daintmsk.b.outep0 = 1;
+ dwc_write_reg32( DWC_REG_DAINTMSK, daintmsk.d32 );
+
+ doepmsk.b.setup = 1;
+ doepmsk.b.xfercompl = 1;
+ doepmsk.b.ahberr = 1;
+ doepmsk.b.epdisabled = 1;
+ dwc_write_reg32( DWC_REG_DOEPMSK, doepmsk.d32 );
+
+ diepmsk.b.xfercompl = 1;
+ diepmsk.b.timeout = 1;
+ diepmsk.b.epdisabled = 1;
+ diepmsk.b.ahberr = 1;
+ dwc_write_reg32( DWC_REG_DIEPMSK, diepmsk.d32 );
+ /* Reset Device Address */
+ dcfg.d32 = dwc_read_reg32( DWC_REG_DCFG);
+ dcfg.b.devaddr = 0;
+ dwc_write_reg32( DWC_REG_DCFG, dcfg.d32);
+
+ /* setup EP0 to receive SETUP packets */
+ ep0_out_start();
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.usbreset = 1;
+ dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32);
+
+ flush_cpu_cache();
+ return 1;
+}
+
+
+///////////////////////////////////////////////////////////////////
+int dwc_common_irq(void)
+{
+ int ret = 0;
+ gotgint_data_t gotgint;
+
+ gotgint.d32 = dwc_read_reg32(DWC_REG_GOTGINT);
+ if (gotgint.d32 == 0)
+ return 0;
+ if (gotgint.b.sesreqsucstschng) {
+ ERR("Session Request Success Status Change\n");
+ }
+ if (gotgint.b.sesenddet) {
+ ERR("Session End Detected, Line Disconected\n");
+ cb_4_dis_connect_intr();
+ }
+
+ dwc_write_reg32(DWC_REG_GOTGINT,gotgint.d32); // clear intr
+
+ return ret;
+}
+
+int dwc_pcd_irq(void)
+{
+ gintsts_data_t gintr_status;
+ gintsts_data_t gintr_msk;
+
+ gintr_msk.d32 = dwc_read_reg32(DWC_REG_GINTMSK);
+ gintr_status.d32 = dwc_read_reg32(DWC_REG_GINTSTS);
+
+ if ((gintr_status.d32 & gintr_msk.d32)== 0)
+ return 0;
+
+ DBG("irq gintmsk: 0x%08x\n",gintr_msk.d32);
+ DBG("irq gintrsts: 0x%08x\n",gintr_status.d32);
+
+ gintr_status.d32 = gintr_status.d32 & gintr_msk.d32;
+ DBG("irq gintmsk & gintrsts = 0x%08x\n",gintr_status.d32);
+
+ if (gintr_status.b.rxstsqlvl) {
+ dwc_otg_pcd_handle_rx_status_q_level_intr();
+ pcd_out_completed(&this_pcd);
+ }
+ if (gintr_status.b.nptxfempty) {
+ dwc_otg_pcd_handle_np_tx_fifo_empty_intr( );
+ }
+
+ if (gintr_status.b.usbreset) {
+ dwc_otg_pcd_handle_usb_reset_intr( );
+ }
+ if (gintr_status.b.enumdone) {
+ dwc_otg_pcd_handle_enum_done_intr();
+ }
+ if (gintr_status.b.epmismatch) {
+ //dwc_otg_pcd_handle_ep_mismatch_intr( core_if );
+ }
+ if (gintr_status.b.inepint) {
+ dwc_otg_pcd_handle_in_ep_intr();
+ }
+ if (gintr_status.b.outepintr) {
+ dwc_otg_pcd_handle_out_ep_intr( );
+ }
+
+#if 0
+ if (gintr_status.b.otgintr)
+ {
+ gotgint_data_t gotgint;
+
+ gotgint.d32 = dwc_read_reg32(DWC_REG_GOTGINT);
+ if (gotgint.b.sesenddet)
+ {
+ printf("dis-connect-intr\n");
+ cb_4_dis_connect_intr();
+ }
+ }
+#endif//#if 0
+
+ dwc_write_reg32(DWC_REG_GINTSTS,gintr_status.d32);
+ flush_cpu_cache();
+ return 0;
+}
+
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.h b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.h
new file mode 100644
index 0000000000..48cc165eac
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/dwc_pcd_irq.h
@@ -0,0 +1,30 @@
+/* dwc driver irq header */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-30 @ Shanghai
+ *
+ */
+#ifndef __DWC_PCD_IRQ_H__
+#define __DWC_PCD_IRQ_H__
+
+int dwc_pcd_irq(void);
+int dwc_otg_irq(void);
+
+/**
+ * States of EP0.
+ */
+typedef enum ep0_state {
+ EP0_DISCONNECT, /* no host */
+ EP0_IDLE,
+ EP0_IN_DATA_PHASE,
+ EP0_OUT_DATA_PHASE,
+ EP0_STATUS,
+ EP0_STALL,
+} ep0state_e;
+
+extern int dwc_common_irq(void);
+
+extern int cb_4_dis_connect_intr(void);
+#endif
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_core.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_core.c
new file mode 100644
index 0000000000..0f90ef18a4
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_core.c
@@ -0,0 +1,65 @@
+#include <common.h>
+#include "platform.h"
+#include "usb_pcd.h"
+
+#include "usb_pcd.c"
+#include "platform.c"
+#include "dwc_pcd.c"
+#include "dwc_pcd_irq.c"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int v2_usbburning(unsigned timeout)
+{
+ int cfg = EXT_CLOCK;
+
+#if defined(CONFIG_SILENT_CONSOLE)
+ gd->flags &= ~GD_FLG_SILENT;
+#endif
+
+ printf("Enter USB burn\n");
+ set_usb_phy_config(cfg);
+
+ usb_parameter_init(timeout);
+
+ if (usb_pcd_init()) {
+ printf("Fail in usb_pcd_init\n");
+ return __LINE__;
+ }
+
+#if (MESON_CPU_TYPE_MESON8 <= MESON_CPU_TYPE)
+ //AML_WATCH_DOG_DISABLE(); //disable watchdog
+#endif// #if (MESON_CPU_TYPE_MESON8 <= MESON_CPU_TYPE)
+
+ while (1)
+ {
+ //watchdog_clear(); //Elvis Fool
+ if (usb_pcd_irq())
+ break;
+ }
+ return 0;
+}
+
+int do_v2_usbtool (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int rc = 0;
+ unsigned timeout = (2 <= argc) ? simple_strtoul(argv[1], NULL, 0) : 0;
+ //if get burning tool identify command in pcToolWaitTime, then auto jump into burning mode
+ unsigned pcToolWaitTime = (3 <= argc) ? simple_strtoul(argv[2], NULL, 0) : 0;
+
+ optimus_work_mode_set(OPTIMUS_WORK_MODE_USB_UPDATE);
+ setenv(_ENV_TIME_OUT_TO_AUTO_BURN, pcToolWaitTime ? argv[2] : "");
+
+ rc = v2_usbburning(timeout);
+ /*close_usb_phy_clock(0);*/
+
+ return rc;
+}
+
+
+U_BOOT_CMD(
+ update, 3, 0, do_v2_usbtool,
+ "Enter v2 usbburning mode",
+ "usbburning timeout"
+);
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_transform.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_transform.c
new file mode 100644
index 0000000000..eba0668d50
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/optimus_transform.c
@@ -0,0 +1,545 @@
+#include "../v2_burning_i.h"
+#include "usb_pcd.h"
+#include "platform.h"
+#include <partition_table.h>
+
+#define MYDBG(fmt ...) printf("OPT]"fmt)
+
+#ifdef CONFIG_CMD_AML
+#define USB_BURN_POWER_CONTROL 1
+#endif// #ifdef CONFIG_CMD_AML
+
+#ifndef CONFIG_UNIFY_KEY_MANAGE
+int v2_key_command(const int argc, char * const argv[], char *info)
+{
+
+ DWN_ERR("burn key not supported as CONFIG_UNIFY_KEY_MANAGE undef!!\n");
+ return OPT_DOWN_FAIL;
+}
+#endif//#ifndef CONFIG_UNIFY_KEY_MANAGE
+
+static inline int str2long(const char *p, unsigned long *num)
+{
+ char *endptr;
+ *num = simple_strtoul(p, &endptr, 0);
+ return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+}
+
+static inline int str2longlong(char *p, unsigned long long *num)
+{
+ char *endptr;
+
+ *num = simple_strtoull(p, &endptr, 16);
+ if (*endptr != '\0')
+ {
+ switch (*endptr)
+ {
+ case 'g':
+ case 'G':
+ *num<<=10;
+ case 'm':
+ case 'M':
+ *num<<=10;
+ case 'k':
+ case 'K':
+ *num<<=10;
+ endptr++;
+ break;
+ }
+ }
+
+ return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+}
+
+static int opimus_func_write_bootloader(unsigned long addr)
+{
+ int ret = 0;
+ loff_t size = 0;
+
+ size = 0x60000;//FIXME: 256K at most ??
+
+ ret = store_boot_write((u8*)addr, (loff_t)0, size);
+
+ return ret;
+}
+
+//[0]write_raw_img [1]part_name [2]address, [3]offset, [4]size
+int opimus_func_write_raw_img(int argc, char *argv[], char *info)
+{
+ int ret = 0;
+ u64 addr;
+ u64 off, size;
+ const char* partName = argv[1];
+
+ if (strcmp(partName, "bootloader") == 0)
+ {
+ addr = simple_strtoul(argv[2], NULL, 0);
+ return opimus_func_write_bootloader(addr);
+ }
+
+ addr = simple_strtoull(argv[2], NULL, 0);
+ off = simple_strtoull(argv[3], NULL, 0);
+ size = simple_strtoul(argv[4], NULL, 0);
+
+ printf("write_raw_img part %s offset 0x%x, size 0x%x, addr 0x%llx\n", argv[1], (u32)off, (u32)size, addr);
+ ret = store_write_ops((u8*)partName, (u8*)addr, off, size);
+
+ return ret;
+}
+
+
+//read_raw_img partName memAddr partOffset readSzInBytes
+int opimus_func_read_raw_img(int argc, char *argv[], char *info)
+{
+ int ret = 0;
+ unsigned long addr;
+ u64 off, size;
+ unsigned char* partName = (unsigned char*)argv[1];
+
+ MYDBG("%s, %s, %s, %s\n", __func__, argv[0], argv[1], argv[2]);
+
+ if (!(str2long(argv[2], &addr)))
+ {
+ sprintf(info, "failed:'%s' is not a number\n", argv[2]);
+ return -1;
+ }
+ if (!(str2longlong(argv[3], &off)))
+ {
+ sprintf(info, "failed:'%s' is not a number\n", argv[3]);
+ return -1;
+ }
+ if (!(str2longlong(argv[4], &size)))
+ {
+ sprintf(info, "failed:'%s' is not a number\n", argv[4]);
+ return -1;
+ }
+
+ ret = store_read_ops(partName, (u8*)addr, off, size);
+
+ return ret;
+}
+
+int optimus_simg2part (int argc, char * const argv[], char *info)
+{
+ int ret = -1;
+ const char* partition_name = argv[1];
+ u8* simg_addr = (u8*)simple_strtoul(argv[2], NULL, 16);
+ u32 pktSz = simple_strtoul(argv[3], NULL, 0);
+ const unsigned memAddrTop = OPTIMUS_DOWNLOAD_SPARSE_INFO_FOR_VERIFY;//this address backup the chunk info, don't overwrite it!
+
+ if (argc < 4) {
+ sprintf(info, "failed: used [%s partName memAddr, pktSz]\n", argv[0]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ if (!pktSz || !simg_addr) {
+ sprintf(info, "simg_addr(%s) or pktSz(%s)error\n", argv[2], argv[3]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+ if ((unsigned long)simg_addr + pktSz > memAddrTop) {
+ sprintf(info, "failed:simg_addr(0x%p) + pktSz(0x%x) > memAddrTop(0x%x)\n", simg_addr, pktSz, memAddrTop);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+
+#if 0
+ ret = simg_write_to_partition(partition_name, simg_addr);
+#else /* ----- not 0 ----- */
+#if 0
+ ret = optimus_simg_probe(simg_addr, pktSz);
+ if (!ret) {
+ sprintf(info, "failed:format error, not a sparse image at addr %s\n", argv[2]);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+#endif /* ----- 0 ----- */
+ ret = optimus_parse_img_download_info(partition_name, pktSz, "sparse", "store", 0);
+ if (ret) {
+ sprintf(info, "failed:init download info for part(%s)\n", partition_name);
+ DWN_ERR(info);
+ return __LINE__;
+ }
+ unsigned writeLen = optimus_download_img_data(simg_addr, pktSz, info);
+ if (writeLen != pktSz) {
+ DWN_ERR("failed when burn simg!, want(0x%x), write(0x%x)\n", pktSz, writeLen);
+ return __LINE__;
+ }
+#endif /* ----- not 0 ----- */
+
+ return ret;
+}
+
+int optimus_sha1sum (int argc, char * const argv[], char *info)
+{
+ unsigned buffermax = 64<<20;
+ unsigned char* sha1_addr = (u8*)0x81000000;
+ int ret = -1;
+ char *partition_name;
+ unsigned long long Bits_need_read = 0,partition_offset = 0;
+ unsigned long long verify_len = 0;
+ u8 output[20];
+ char *sha1_verify = NULL;
+ char sha1_value[41];
+ int i = 1;
+
+ memset(sha1_value, 0, sizeof(sha1_value));
+
+ if (3 == argc) //test to sha1sum memory: sha1sum memAddr, length
+ {
+ unsigned verify_len = 0;
+ unsigned char* pBuf = NULL;
+
+ pBuf = (unsigned char*)simple_strtoul(argv[1], NULL, 0);
+ verify_len = simple_strtoul(argv[2], NULL, 0);
+
+ printf("Gen sha1sum: addr 0x%p, len 0x%x\n", pBuf, verify_len);
+ sha1_csum(pBuf, verify_len, output);
+
+ sprintf(sha1_value, "%02x", output[0]);
+ for (i = 1; i < 20; ++i)
+ {
+ sprintf(sha1_value, "%02x", output[0]);
+ for (; i < 20; ++i)
+ {
+ sprintf(sha1_value, "%s%02x", sha1_value, output[i]);
+ }
+ /*sprintf(sha1_value, "%s%02x", sha1_value, output[i]);*/
+ }
+ printf("gen sha1sum %s\n", sha1_value);
+ return 0;
+ }
+
+ if (argc != 4)//argv:cmd,partition_name,verify_len,sha1_verify
+ {
+ printf("bad args---sha1sum cmd need 3 args\n");
+ strcpy(info, "failed:need 3 args");
+ return -1;
+ }
+
+ partition_name = argv[1];
+
+ verify_len = simple_strtoull (argv[2], NULL, 10);
+ sha1_verify = argv[3];
+
+ //circularly verify 128M datas readed in memory 0x81000000
+ sha1_context ctx;
+ sha1_starts (&ctx);
+
+ Bits_need_read = verify_len;
+ partition_offset = 0;
+ while (Bits_need_read > buffermax)
+ {
+ ret = store_read_ops((unsigned char*)partition_name, (unsigned char *) sha1_addr, partition_offset, buffermax);
+ if (ret) {
+ DWN_ERR("Fail to read data from %s at offset %llx size %x\n", partition_name, partition_offset, buffermax);
+ return __LINE__;
+ }
+ sha1_update (&ctx, (unsigned char *) sha1_addr, buffermax);
+ Bits_need_read = Bits_need_read - buffermax;
+ partition_offset += buffermax;
+ printf("current Bits_need_read is 0x%llx, buffermax is : 0x%x\n",Bits_need_read,buffermax);
+ for (i = 0; i < 5; i++)sprintf(sha1_value,"%s%08x", sha1_value, (unsigned)ctx.state[i]) ;//5*8=40
+ printf("current sha1_value is %s\n", sha1_value);
+ }
+
+ ret = store_read_ops((unsigned char*)partition_name, (unsigned char *) sha1_addr, partition_offset, Bits_need_read);
+ if (ret) {
+ DWN_ERR("Fail to read data from %s at offset %llx size %x\n", partition_name, partition_offset, buffermax);
+ return __LINE__;
+ }
+
+ sha1_update (&ctx, (unsigned char *) sha1_addr, Bits_need_read);
+ sha1_finish (&ctx, output);
+ //?????????????
+ printf("SHA1 for %s %p,verify_len:0x%llx ==>",partition_name, sha1_addr,verify_len);
+
+ for (i = 0; i < 20; i++)
+ {
+ printf("%02x", output[i]);
+ //sha1_value[i] = output[i];
+ sprintf(sha1_value,"%s%02x", sha1_value, output[i]);
+ }
+ //sha1_value[21] = '\0';
+ printf("\n");
+
+ printf("sha1_verify= %s\n", sha1_verify);
+ printf("sha1_value = %s\n", sha1_value);
+ if (strncmp(sha1_verify, sha1_value, 40) == 0)
+ {
+ ret = 0;
+ strcpy(info, "success");
+ }
+ else
+ {
+ ret = -1;
+ strcpy(info, "failed");
+ }
+
+ return ret;
+}
+
+
+int optimus_mem_md (int argc, char * const argv[], char *info)
+{
+ ulong addr, length = 0x100;
+ int size;
+ int rc = 0;
+
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ /* Address is specified since argc > 1
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ /* If another parameter, it is the length to display.
+ * Length is the number of objects, not number of bytes.
+ */
+ if (argc > 2)
+ length = simple_strtoul(argv[2], NULL, 16);
+
+ /* Print the lines. */
+ print_buffer(addr, (void*)addr, size, length, 16/size);
+ strcpy(info, "success");
+ return rc;
+}
+
+int set_low_power_for_usb_burn(int arg, char* buff)
+{
+ if (OPTIMUS_WORK_MODE_USB_PRODUCE == optimus_work_mode_get()) {
+ return 0;//just return ok as usb producing mode as LCD not initialized yet!
+ }
+
+#if defined(CONFIG_VIDEO_AMLLCD)
+ int ret1=0;
+ //axp to low power off LCD, no-charging
+ MYDBG("To close LCD\n");
+ ret1 = run_command("video dev disable", 0);
+ if (ret1) {
+ if (buff) sprintf(buff, "Fail to close back light") ;
+ printf("Fail to close back light\n");
+ /*return __LINE__;*/
+ }
+#endif// #if defined(CONFIG_VIDEO_AMLLCD)
+
+#if USB_BURN_POWER_CONTROL
+ int ret2=0;
+ //limit vbus curretn to 500mA, i.e, if hub is 4A, 8 devices at most, arg3 to not set_env as it's not inited yet!!
+ MYDBG("set_usbcur_limit 500 0\n");
+ ret2 = run_command("set_usbcur_limit 500 0", 0);
+ if (ret2) {
+ if (buff) sprintf(buff, "Fail to set_usb_cur_limit") ;
+ printf("Fail to set_usb_cur_limit\n");
+ return __LINE__;
+ }
+#endif//#if USB_BURN_POWER_CONTROL
+
+ return 0;
+}
+
+//I assume that store_inited yet when "bootloader_is_old"!!!!
+int optimus_erase_bootloader(char* info)
+{
+ int ret = 0;
+
+#if ROM_BOOT_SKIP_BOOT_ENABLED
+ optimus_enable_romboot_skip_boot();
+#else
+ if (SPI_EMMC_FLAG == device_boot_flag || SPI_NAND_FLAG == device_boot_flag) {
+ run_command("sf probe 2", 0);
+ }
+ ret = store_erase_ops((u8*)"boot", 0, 0, 0);
+#endif// #if ROM_BOOT_SKIP_BOOT_ENABLED
+
+ return ret;
+}
+
+int cb_4_dis_connect_intr(void)
+{
+ if (optimus_burn_complete(OPTIMUS_BURN_COMPLETE__QUERY))
+ {
+ close_usb_phy_clock(0);//disconnect to avoid k200 platfrom which can't relally poweroff
+ DWN_MSG("User Want poweroff after disconnect\n");
+ optimus_poweroff();
+ }
+
+ return 0;
+}
+
+static int _cpu_temp_in_valid_range(int argc, char* argv[], char* errInfo)
+{
+ int ret = 0;
+ int minTemp = 0;
+ int maxTemp = 0;
+ int cpu_temp = 0;
+ char* env_cpu_temp = NULL;
+
+ if (3 > argc) {
+ sprintf(errInfo, "argc %d < 3 is invalid\n", argc);
+ return __LINE__;
+ }
+ minTemp = simple_strtol(argv[1], NULL, 0);
+ maxTemp = simple_strtol(argv[2], NULL, 0);
+ if (minTemp <=0 || maxTemp <= 0 || minTemp >= maxTemp) {
+ sprintf(errInfo, "Invalid:minTemp=%s, maxTemp=%s\n", argv[1], argv[2]);
+ return __LINE__;
+ }
+ ret = run_command("cpu_temp -p", 0);
+ if (ret < 0) {
+ sprintf(errInfo, "cmd[cpu_temp] failed\n");
+ return __LINE__;
+ }
+ env_cpu_temp = getenv("tempa");
+ if (!env_cpu_temp) {
+ sprintf(errInfo, "Can't get cpu_temp, cpu is not calibrated.\n");
+ return __LINE__;
+ }
+ cpu_temp = simple_strtol(env_cpu_temp, NULL, 0);
+ ret = (cpu_temp >= minTemp && cpu_temp <= maxTemp) ? 0 : __LINE__;
+ if (!ret) {
+ sprintf(errInfo, "%s", env_cpu_temp);
+ }
+ else{
+ sprintf(errInfo, "%s is out of temp range[%d, %d], errInfo[%s]\n", env_cpu_temp, minTemp, maxTemp, getenv("err_info_tempa"));
+ }
+
+ return ret;
+}
+
+int optimus_working (const char *cmd, char* buff)
+{
+ static char cmdBuf[CMD_BUFF_SIZE] = {0};
+ int ret = 0;
+ int argc = 33;
+ char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
+ /*printf("reboot_mode [%8x, %8x]\n", P_AO_RTI_STATUS_REG1);*/
+ const char* optCmd = NULL;
+
+ memset(buff, 0, CMD_BUFF_SIZE);
+ memcpy(cmdBuf, cmd, CMD_BUFF_SIZE);
+ if ((argc = cli_simple_parse_line(cmdBuf, argv)) == 0)
+ {
+ strcpy(buff, "failed:no command at all");
+ printf("no command at all\n");
+ return -1; /* no command at all */
+ }
+ optCmd = argv[0];
+
+ if (!strcmp("low_power", optCmd))
+ {
+ ret = set_low_power_for_usb_burn(1, buff);
+ }
+ else if(strcmp(optCmd, "disk_initial") == 0)
+ {
+ unsigned erase = argc > 1 ? simple_strtoul(argv[1], NULL, 0) : 0;
+
+ ret = optimus_storage_init(erase);
+ }
+ else if(!strcmp(optCmd, "bootloader_is_old"))
+ {
+ ret = is_tpl_loaded_from_usb();
+ if (ret)sprintf(buff, "Failed, bootloader is new\n") ;
+ }
+ else if(!strcmp(optCmd, "erase_bootloader"))
+ {
+ ret = optimus_erase_bootloader(buff);
+
+ if (ret)sprintf(buff, "Failed to erase bootloader\n") ;
+ }
+ else if(strcmp(optCmd, "write_raw_img") == 0)
+ {
+ ret = opimus_func_write_raw_img(argc, argv, buff);
+ }
+ else if(strcmp(optCmd, "read_raw_img") == 0)
+ {
+ ret = opimus_func_read_raw_img(argc, argv, buff);
+ }
+ else if(strcmp(optCmd, "simg2part") == 0)
+ {
+ ret = optimus_simg2part(argc, argv, buff);
+ }
+ else if(strcmp(optCmd, "reset") == 0)
+ {
+ close_usb_phy_clock(0);
+ optimus_reset(OPTIMUS_BURN_COMPLETE__REBOOT_NORMAL);
+ }
+ else if(strcmp(optCmd, "poweroff") == 0)
+ {
+ optimus_poweroff();
+ }
+ else if(strncmp(optCmd, "md", 2) == 0)
+ {
+ ret = optimus_mem_md(argc, argv, buff);
+ }
+ else if(!strcmp(optCmd, "download") || !strcmp("upload", optCmd))
+ {
+ ret = optimus_parse_download_cmd(argc, argv);
+ }
+ else if(!strcmp("key", optCmd))
+ {
+ ret = v2_key_command(argc, argv, buff);
+ }
+ else if(!strcmp("verify", optCmd))
+ {
+ ret = optimus_media_download_verify(argc, argv, buff);
+ }
+ else if(!strcmp("save_setting", optCmd))
+ {
+ ret = optimus_set_burn_complete_flag();
+ }
+ else if(!strcmp("burn_complete", optCmd))
+ {
+ unsigned choice = simple_strtoul(argv[1], NULL, 0);//0 is poweroff, 1 is reset system
+
+ if (OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_DISCONNECT != choice) {//disconnect except OPTIMUS_BURN_COMPLETE__POWEROFF_AFTER_DISCONNECT
+ close_usb_phy_clock(0);//some platform can't poweroff but dis-connect needed by pc
+ }
+ ret = optimus_burn_complete(choice);
+ }
+ else if(strncmp(cmd,"sha1sum",(sizeof("sha1sum")-1)) == 0)
+ {
+ ret = optimus_sha1sum(argc, argv, buff);
+ }
+ else if(!strcmp(optCmd, "support_tempcontrol"))
+ {
+#ifndef CONFIG_CMD_CPU_TEMP
+ ret = __LINE__;
+#else
+ ret = run_command("cpu_temp -p", 0);
+ if (ret <= 0) {
+ DWN_MSG("Fail in cmd[cpu_temp]\n");
+ ret = __LINE__;
+ }
+ else{
+ ret = 0;
+ }
+#endif// #ifdef CONFIG_CMD_CPU_TEMP
+ sprintf(buff + 7, "cpu temp control cmd %s supported.\n", ret ? "NOT" : "DO");//7 == strlen("failed")
+ }
+ else if(!strcmp(optCmd, "tempcontrol"))
+ {
+ ret = _cpu_temp_in_valid_range(argc, argv, buff + 7);
+ }
+ else
+ {
+ int flag = 0;
+ ret = run_command(cmd, flag);
+ DWN_MSG("ret = %d\n", ret);
+ ret = ret < 0 ? ret : 0;
+ }
+
+ if (ret)
+ {
+ memcpy(buff, "failed:", strlen("failed:"));//use memcpy but not strcpy to not overwrite storage/key info
+ }
+ else
+ {
+ memcpy(buff, "success", strlen("success"));//use memcpy but not strcpy to not overwrite storage/key info
+ }
+
+ printf("[info]%s\n",buff);
+ return ret;
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.c
new file mode 100644
index 0000000000..8c4fc4b74c
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.c
@@ -0,0 +1,161 @@
+/* platform dirver header */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ *
+ */
+ #include "platform.h"
+
+/*CONFIG_AML_MESON_8 include m8, m8baby, m8m2, etc... defined in cpu.h*/
+#if !( defined(CONFIG_AML_MESON_GX) )
+#error "platform is not GX !!"
+#endif//#if
+
+/*
+ cfg = 0 : EXT clock
+ cfg = 1 : INT clock
+ */
+
+#if 1
+#define PREI_USB_PHY_A_REG_BASE 0xC0000000 //0x2100
+#define PREI_USB_PHY_B_REG_BASE 0xC1108420 //0X2108
+#else
+#define PREI_USB_PHY_A_REG_BASE P_USB_ADDR0
+#define PREI_USB_PHY_B_REG_BASE P_USB_ADDR1
+#endif//#if 0
+
+#ifdef __USE_PORT_B
+#define PREI_USB_PHY_REG_BASE PREI_USB_PHY_B_REG_BASE
+#else
+#define PREI_USB_PHY_REG_BASE PREI_USB_PHY_A_REG_BASE
+#endif
+//#define P_RESET1_REGISTER (volatile unsigned long *)0xc1104408
+#define P_RESET1_REGISTER_USB (volatile unsigned long *)0xc1104408
+
+#define USB_CLK_SEL_XTAL 0
+#define USB_CLK_SEL_XTAL_DIV_2 1
+#define USB_CLK_SEL_DDR_PLL 2
+#define USB_CLK_SEL_MPLL_OUT0 3
+#define USB_CLK_SEL_MPLL_OUT1 4
+#define USB_CLK_SEL_MPLL_OUT2 5
+#define USB_CLK_SEL_FCLK_DIV2 6
+#define USB_CLK_SEL_FCLK_DIV3 7
+
+typedef struct usb_aml_regs {
+ volatile uint32_t config;
+ volatile uint32_t ctrl;
+ volatile uint32_t endp_intr;
+ volatile uint32_t adp_bc;
+ volatile uint32_t dbg_uart;
+ volatile uint32_t test;
+ volatile uint32_t tune;
+} usb_aml_regs_t;
+
+typedef union usb_config_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned clk_en :1;
+ unsigned clk_sel :3;
+ unsigned clk_div :7;
+ unsigned reserved0 :1;
+ unsigned clk_32k_alt_sel:1;
+ unsigned reserved1 :15;
+ unsigned test_trig :1;
+ } b;
+} usb_config_data_t;
+
+typedef union usb_ctrl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned soft_prst:1;
+ unsigned soft_hreset:1;
+ unsigned ss_scaledown_mode:2;
+ unsigned clk_det_rst:1;
+ unsigned intr_sel:1;
+ unsigned reserved:2;
+ unsigned clk_detected:1;
+ unsigned sof_sent_rcvd_tgl:1;
+ unsigned sof_toggle_out:1;
+ unsigned not_used:4;
+ unsigned por:1;
+ unsigned sleepm:1;
+ unsigned txbitstuffennh:1;
+ unsigned txbitstuffenn:1;
+ unsigned commononn:1;
+ unsigned refclksel:2;
+ unsigned fsel:3;
+ unsigned portreset:1;
+ unsigned thread_id:6;
+ } b;
+} usb_ctrl_data_t;
+
+void set_usb_phy_config(int cfg)
+{
+
+ const int time_dly = 5000;
+ usb_aml_regs_t * usb_aml_regs = (usb_aml_regs_t * )PREI_USB_PHY_REG_BASE;
+ usb_config_data_t config;
+ usb_ctrl_data_t control;
+
+ /*CLK_GATE_ON(USB0);*/
+ //if(!IS_CLK_GATE_ON(USB0)){
+ // SET_CBUS_REG_MASK(GCLK_REG_USB0, GCLK_MASK_USB0);
+ //}
+ /*printf("%s %d\n", __func__, __LINE__);*/
+ cfg = cfg;//avoid compiler warning
+ /**P_RESET1_REGISTER = (1<<2);//usb reset*/
+ *P_RESET1_REGISTER_USB = (1<<2);//usb reset
+ udelay(time_dly);//by Sam: delay after reset
+
+ config.d32 = usb_aml_regs->config;
+
+// config.b.clk_sel = 0;
+// config.b.clk_div = 1;
+// config.b.clk_32k_alt_sel = 1;
+ usb_aml_regs->config = config.d32;
+
+ control.d32 = usb_aml_regs->ctrl;
+ control.b.fsel = 5;
+ control.b.por = 1;
+ usb_aml_regs->ctrl = control.d32;
+ udelay(time_dly);
+
+ control.b.por = 0;
+ usb_aml_regs->ctrl = control.d32;
+ udelay(time_dly);//by Sam: delay 0.5s to wait usb clam down
+
+ control.d32 = usb_aml_regs->ctrl;
+ if (!control.b.clk_detected) {
+ printf("Error, usb phy clock not detected!\n");
+ }
+
+ return;
+}
+
+#if 0
+int chip_watchdog(void)
+{
+ watchdog_clear();
+ return 0;
+};
+#endif
+
+void close_usb_phy_clock(int cfg)
+{
+ cfg = cfg;//avoid compiler warning
+
+ dwc_otg_pullup(0);//disconnect
+ __udelay(20);
+ /*dwc_otg_power_off_phy();*///Don't call this as it may cause pull-down failed!!!!
+ run_command("sleep 1", 0);//sleep sometime to improve pc compatibility!!
+
+ return;
+}
+
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.h b/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.h
new file mode 100644
index 0000000000..b8c9227075
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/platform.h
@@ -0,0 +1,155 @@
+/* platform header */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ *
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#include <asm/arch/register.h>
+
+//#include "romboot.h"
+//Elvis Fool
+//#pragma Offwarn(88) /* disable "Expression has no side-effects" print debug info*/
+
+/* A3,CS2,M3 chip, PORT_A is OTG, work as ROM Boot port */
+#ifdef __USE_PORT_B
+#define PORT_REG_OFFSET 0x80000
+#else
+#define PORT_REG_OFFSET 0
+#endif
+
+
+#define DWC_REG_BASE (0xC9000000 + PORT_REG_OFFSET)
+
+#define PERI_BASE_ADDR 0xc1100000
+#define ISABASE 0x01000000
+
+#define PREI_USB_PHY_REG 0xc0000000 //0xC1108400
+
+#define PREI_USB_PHY_A_REG3 0xc0000000
+#define PREI_USB_PHY_B_REG4 0xc0000020
+
+#define PREI_USB_PHY_A_POR (1 << 0)
+#define PREI_USB_PHY_B_POR (1 << 1)
+#define PREI_USB_PHY_CLK_SEL (7 << 5) // changed from A1H
+#define PREI_USB_PHY_CLK_GATE (1 << 8)
+#define PREI_USB_PHY_B_AHB_RSET (1 << 11)
+#define PREI_USB_PHY_B_CLK_RSET (1 << 12)
+#define PREI_USB_PHY_B_PLL_RSET (1 << 13)
+#define PREI_USB_PHY_A_AHB_RSET (1 << 17)
+#define PREI_USB_PHY_A_CLK_RSET (1 << 18)
+#define PREI_USB_PHY_A_PLL_RSET (1 << 19)
+#define PREI_USB_PHY_A_DRV_VBUS (1 << 20)
+#define PREI_USB_PHY_B_DRV_VBUS (1 << 21)
+#define PREI_USB_PHY_B_CLK_DETECT (1 << 22)
+#define PREI_USB_PHY_CLK_DIV (0x7f << 24)
+#define PREI_USB_PHY_A_CLK_DETECT (1 << 31)
+
+#define PREI_USB_PHY_A_REG3_IDDIG_OVR (1 << 23)
+#define PREI_USB_PHY_A_REG3_IDDIG_VAL (1 << 24)
+
+#define PREI_USB_PHY_B_REG4_IDDIG_OVR (1 << 23)
+#define PREI_USB_PHY_B_REG4_IDDIG_VAL (1 << 24)
+
+
+
+/***********************************************/
+#define WRITE_PERI_REG(reg, val) *(volatile unsigned *)(PERI_BASE_ADDR + ((reg)<<2)) = (val)
+#define READ_PERI_REG(reg) (*(volatile unsigned *)(PERI_BASE_ADDR + ((reg)<<2)))
+
+#define CLEAR_PERIPHS_REG_BITS(reg, mask) WRITE_PERI_REG(reg, (READ_PERI_REG(reg)&(~(mask))))
+#define SET_PERIPHS_REG_BITS(reg, mask) WRITE_PERI_REG(reg, (READ_PERI_REG(reg)|(mask)))
+
+#define WRITE_ISA_REG(reg, val) *(volatile unsigned *)(ISABASE + (reg)) = (val)
+#define READ_ISA_REG(reg) (*(volatile unsigned *)(ISABASE + (reg)))
+
+#define CLEAR_ISA_REG_MASK(reg, mask) WRITE_ISA_REG(reg, (READ_ISA_REG(reg)&(~mask)))
+#define SET_ISA_REG_MASK(reg, mask) WRITE_ISA_REG(reg, (READ_ISA_REG(reg)|(mask)))
+/***********************************************/
+
+
+
+
+
+#define IREG_TIMER_E_COUNT 0x2655
+
+
+#define flush_cpu_cache()
+
+
+#define dwc_write_reg32(x, v) (*(volatile uint32_t *)(unsigned long)(x + DWC_REG_BASE))=v
+#define dwc_read_reg32(x) (*(volatile uint32_t*)(unsigned long)(x + DWC_REG_BASE))
+// void dwc_modify_reg32( volatile uint32_t *_reg, const uint32_t _clear_mask, const uint32_t _set_mask)
+#define dwc_modify_reg32(x, c, s) (*(volatile uint32_t *)(x + DWC_REG_BASE))=( ((dwc_read_reg32(x)) & (~c)) | (s))
+
+#define get_unaligned(ptr) (((__u8 *)ptr)[0] | (((__u8 *)ptr)[1]<<8) | (((__u8 *)ptr)[2]<<16) | (((__u8 *)ptr)[3]<<24))
+#define get_unaligned_16(ptr) (((__u8 *)ptr)[0] | (((__u8 *)ptr)[1]<<8))
+#define get_unaligned_32(ptr) (((__u8 *)ptr)[0] | (((__u8 *)ptr)[1]<<8) | (((__u8 *)ptr)[2]<<16) | (((__u8 *)ptr)[3]<<24))
+
+#if 0
+#define __constant_cpu_to_le16(x) (x)
+#define __constant_cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_le32(x) (x)
+#define le16_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+
+#ifndef max
+#define max(a, b) (((a) > (b))? (a): (b))
+#endif
+#ifndef min
+#define min(a, b) (((a) < (b))? (a): (b))
+#endif
+
+#endif//#if 0
+
+#define EXT_CLOCK 0
+#define INT_CLOCK 1
+
+
+// 32 bit TimerE, 1us
+#define USB_ROM_CONN_TIMEOUT 5*1000*1000 //us (5s timeout,)
+
+
+/* Meet with spec */
+#define USB_ROM_VER_MAJOR 0
+#define USB_ROM_STAGE_MAJOR 0
+#define USB_ROM_STAGE_MINOR 16 // IPL = 0, SPL = 8, TPL = 16
+
+#ifdef CONFIG_M6
+#define USB_ROM_VER_MINOR 8 // SPEC Version
+#else
+#define USB_ROM_VER_MINOR 7 // SPEC Version
+#endif
+
+#if 1
+#define PRINTF(x...) do{}while(0)
+#else
+#define PRINTF(x...) printf(x)
+#endif
+
+#define ERR(x...) printf(x)
+#define DBG(x...) PRINTF(x)
+#define USB_ERR(x...) printf("USBErr:%d", __LINE__),printf(x)
+#define USB_DBG(x...) PRINTF(x)
+
+
+void set_usb_phy_config(int cfg);
+void close_usb_phy_clock(int cfg);
+void usb_parameter_init(int timeout);
+int chip_utimer_set(int val);
+int chip_watchdog(void);
+#define udelay __udelay
+#define wait_ms(a) udelay(a*1000);
+int update_utime(void);
+int get_utime(void);
+//int chip_watchdog(void);
+//#define usb_memcpy(dst,src,len) rom_memcpy((unsigned)src,(unsigned)dst,(unsigned)len)
+//#define usb_memcpy_32bits(dst,src,len) rom_memcpy((unsigned)src,(unsigned)dst,(unsigned)len)
+
+#endif
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_ch9.h b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_ch9.h
new file mode 100644
index 0000000000..9b52b67352
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_ch9.h
@@ -0,0 +1,676 @@
+#ifndef __LINUX_USB_CH9_H
+#define __LINUX_USB_CH9_H
+
+/**
+ * @file usb_ch9.h
+ * @brief This file holds USB constants and structures that are needed for USB
+ * device APIs. These are used by the USB device model, which is defined
+ * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
+ * that need these:
+ *
+ * - the master/host side Linux-USB kernel driver API;
+ * - the "usbfs" user space API; and
+ * - the Linux "gadget" slave/device/peripheral side driver API.
+ *
+ * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
+ * act either as a USB master/host or as a USB slave/device. That means
+ * the master and slave side APIs benefit from working well together.
+ *
+ * There's also "Wireless USB", using low power short range radios for
+ * peripheral interconnection but otherwise building on the USB framework.
+ *
+ * @addtogroup usb_core
+ */
+/*@{*/
+
+#include <linux/types.h>
+
+/*******************************************************
+* CONTROL REQUEST SUPPORT
+********************************************************/
+
+/// USB directions, to device
+/// This bit flag is used in endpoint descriptors' bEndpointAddress field.
+/// It's also one of three fields in control requests bRequestType.
+#define USB_DIR_OUT 0
+/// USB directions, to host
+/// This bit flag is used in endpoint descriptors' bEndpointAddress field.
+/// It's also one of three fields in control requests bRequestType.
+#define USB_DIR_IN 0x80
+
+/// USB types, the second of three bRequestType fields
+#define USB_TYPE_MASK (0x03 << 5)
+/// USB types, the second of three bRequestType fields
+#define USB_TYPE_STANDARD (0x00 << 5)
+/// USB types, the second of three bRequestType fields
+#define USB_TYPE_CLASS (0x01 << 5)
+/// USB types, the second of three bRequestType fields
+#define USB_TYPE_VENDOR (0x02 << 5)
+/// USB types, the second of three bRequestType fields
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+/// USB recipients, the third of three bRequestType fields
+#define USB_RECIP_MASK 0x1f
+/// USB recipients, the third of three bRequestType fields
+#define USB_RECIP_DEVICE 0x00
+/// USB recipients, the third of three bRequestType fields
+#define USB_RECIP_INTERFACE 0x01
+/// USB recipients, the third of three bRequestType fields
+#define USB_RECIP_ENDPOINT 0x02
+/// USB recipients, the third of three bRequestType fields
+#define USB_RECIP_OTHER 0x03
+
+/*
+ * Standard requests, for the bRequest field of a SETUP packet.
+ *
+ * These are qualified by the bRequestType field, so that for example
+ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
+ * by a GET_STATUS request.
+ */
+#define USB_REQ_GET_STATUS 0x00
+#define USB_REQ_CLEAR_FEATURE 0x01
+#define USB_REQ_SET_FEATURE 0x03
+#define USB_REQ_SET_ADDRESS 0x05
+#define USB_REQ_GET_DESCRIPTOR 0x06
+#define USB_REQ_SET_DESCRIPTOR 0x07
+#define USB_REQ_GET_CONFIGURATION 0x08
+#define USB_REQ_SET_CONFIGURATION 0x09
+#define USB_REQ_GET_INTERFACE 0x0A
+#define USB_REQ_SET_INTERFACE 0x0B
+#define USB_REQ_SYNCH_FRAME 0x0C
+
+/// Wireless USB
+#define USB_REQ_SET_ENCRYPTION 0x0D/
+
+#define USB_REQ_GET_ENCRYPTION 0x0E
+#define USB_REQ_SET_HANDSHAKE 0x0F
+#define USB_REQ_GET_HANDSHAKE 0x10
+#define USB_REQ_SET_CONNECTION 0x11
+#define USB_REQ_SET_SECURITY_DATA 0x12
+#define USB_REQ_GET_SECURITY_DATA 0x13
+#define USB_REQ_SET_WUSB_DATA 0x14
+#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
+#define USB_REQ_LOOPBACK_DATA_READ 0x16
+#define USB_REQ_SET_INTERFACE_DS 0x17
+
+/*
+ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are read as a bit array returned by USB_REQ_GET_STATUS. (So there
+ * are at most sixteen features of each type.)
+ */
+/// (read only)
+#define USB_DEVICE_SELF_POWERED 0
+
+/// dev may initiate wakeup
+#define USB_DEVICE_REMOTE_WAKEUP 1
+
+/// (wired high speed only)
+#define USB_DEVICE_TEST_MODE 2
+
+/// (wireless)
+#define USB_DEVICE_BATTERY 2
+
+/// (otg) dev may initiate HNP
+#define USB_DEVICE_B_HNP_ENABLE 3
+
+/// (wireless
+#define USB_DEVICE_WUSB_DEVICE 3
+
+/// (otg) RH port supports HNP
+#define USB_DEVICE_A_HNP_SUPPORT 4
+
+/// (otg) other RH port does
+#define USB_DEVICE_A_ALT_HNP_SUPPORT 5
+
+/// (special devices only)
+#define USB_DEVICE_DEBUG_MODE 6
+
+
+
+
+
+
+/// IN/OUT will STALL
+#define USB_ENDPOINT_HALT 0
+
+
+#define USB_SETUP_PACKET_SIZE 8
+
+/**
+ * SETUP data for a USB device control request
+ *
+ * This structure is used to send control requests to a USB device. It matches
+ * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
+ * USB spec for a fuller description of the different fields, and what they are
+ * used for.
+ *
+ * Note that the driver for any interface can issue control requests.
+ * For most devices, interfaces don't coordinate with each other, so
+ * such requests may be made at any time.
+ */
+struct usb_ctrlrequest {
+ /// matches the USB bmRequestType field
+ __u8 bRequestType;
+
+ /// matches the USB bRequest field
+ __u8 bRequest;
+
+ /// matches the USB wValue field (le16 byte order)
+ __u16 wValue;
+
+ /// matches the USB wIndex field (le16 byte order)
+ __u16 wIndex;
+
+ /// matches the USB wLength field (le16 byte order)
+ __u16 wLength;
+} __attribute__ ((packed));
+typedef struct usb_ctrlrequest usb_ctrlrequest_t;
+
+
+/*
+ * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
+ * (rarely) accepted by SET_DESCRIPTOR.
+ *
+ * Note that all multi-byte values here are encoded in little endian
+ * byte order "on the wire". But when exposed through Linux-USB APIs,
+ * they've been converted to cpu byte order.
+ */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+#define USB_DT_DEVICE_QUALIFIER 0x06
+#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_INTERFACE_POWER 0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG 0x09
+#define USB_DT_DEBUG 0x0a
+#define USB_DT_INTERFACE_ASSOCIATION 0x0b
+/* these are from the Wireless USB spec */
+#define USB_DT_SECURITY 0x0c
+#define USB_DT_KEY 0x0d
+#define USB_DT_ENCRYPTION_TYPE 0x0e
+#define USB_DT_BOS 0x0f
+#define USB_DT_DEVICE_CAPABILITY 0x10
+#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
+
+/// conventional codes for class-specific descriptors
+#define USB_DT_CS_DEVICE 0x21
+/// conventional codes for class-specific descriptors
+#define USB_DT_CS_CONFIG 0x22
+/// conventional codes for class-specific descriptors
+#define USB_DT_CS_STRING 0x23
+/// conventional codes for class-specific descriptors
+#define USB_DT_CS_INTERFACE 0x24
+/// conventional codes for class-specific descriptors
+#define USB_DT_CS_ENDPOINT 0x25
+
+/** All standard descriptors have these 2 fields at the beginning */
+struct usb_descriptor_header {
+ __u8 bLength;
+ __u8 bDescriptorType;
+} __attribute__ ((packed));
+typedef struct usb_descriptor_header usb_descriptor_header_t;
+
+
+
+/** USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 bcdUSB;
+ __u8 bDeviceClass;
+ __u8 bDeviceSubClass;
+ __u8 bDeviceProtocol;
+ __u8 bMaxPacketSize0;
+ __u16 idVendor;
+ __u16 idProduct;
+ __u16 bcdDevice;
+ __u8 iManufacturer;
+ __u8 iProduct;
+ __u8 iSerialNumber;
+ __u8 bNumConfigurations;
+} __attribute__ ((packed));
+typedef struct usb_device_descriptor usb_device_descriptor_t;
+
+#define USB_DT_DEVICE_SIZE 18
+
+
+/*
+ * Device and/or Interface Class codes
+ * as found in bDeviceClass or bInterfaceClass
+ * and defined by www.usb.org documents
+ */
+/// for DeviceClass
+#define USB_CLASS_PER_INTERFACE 0
+
+#define USB_CLASS_AUDIO 1
+#define USB_CLASS_COMM 2
+#define USB_CLASS_HID 3
+#define USB_CLASS_PHYSICAL 5
+#define USB_CLASS_STILL_IMAGE 6
+#define USB_CLASS_PRINTER 7
+#define USB_CLASS_MASS_STORAGE 8
+#define USB_CLASS_HUB 9
+#define USB_CLASS_CDC_DATA 0x0a
+
+/// chip+ smart card
+#define USB_CLASS_CSCID 0x0b
+
+/// content security
+#define USB_CLASS_CONTENT_SEC 0x0d
+
+#define USB_CLASS_VIDEO 0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
+#define USB_CLASS_MISC 0xef
+#define USB_CLASS_APP_SPEC 0xfe
+#define USB_CLASS_VENDOR_SPEC 0xff
+
+
+/**
+ * USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different. Highspeed-capable devices can look
+ * different depending on what speed they're currently running. Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
+ * descriptors.
+ */
+struct usb_config_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 wTotalLength;
+ __u8 bNumInterfaces;
+ __u8 bConfigurationValue;
+ __u8 iConfiguration;
+ __u8 bmAttributes;
+ __u8 bMaxPower;
+
+} __attribute__ ((packed));
+//typedef struct usb_config_descriptor usb_config_descriptor_t;
+
+#define USB_DT_CONFIG_SIZE 9
+
+/* from config descriptor bmAttributes */
+/// from config descriptor bmAttributes: must be set
+#define USB_CONFIG_ATT_ONE (1 << 7)
+
+/// from config descriptor bmAttributes: self powered
+#define USB_CONFIG_ATT_SELFPOWER (1 << 6)
+
+/// from config descriptor bmAttributes: can wakeup
+#define USB_CONFIG_ATT_WAKEUP (1 << 5)
+
+/// from config descriptor bmAttributes: battery powered
+#define USB_CONFIG_ATT_BATTERY (1 << 4)
+
+
+/** USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ /// UTF-16LE encoded
+ __u16 wData[1];
+} __attribute__ ((packed));
+typedef struct usb_string_descriptor usb_string_descriptor_t;
+
+/*
+ * note that "string" zero is special, it holds language codes that
+ * the device supports, not Unicode characters.
+ */
+
+
+/** USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bInterfaceNumber;
+ __u8 bAlternateSetting;
+ __u8 bNumEndpoints;
+ __u8 bInterfaceClass;
+ __u8 bInterfaceSubClass;
+ __u8 bInterfaceProtocol;
+ __u8 iInterface;
+
+ struct usb_endpoint_descriptor *endpoint;
+
+ /// Extra descriptors
+ unsigned char *extra;
+
+ int extralen;
+} __attribute__ ((packed));
+typedef struct usb_interface_descriptor usb_interface_descriptor_t;
+
+#if 0
+typedef struct usb_interface {
+ struct usb_interface_descriptor *altsetting;
+
+ int act_altsetting; /* active alternate setting */
+ int num_altsetting; /* number of alternate settings */
+ int max_altsetting; /* total memory allocated */
+
+ void *private_data;
+} usb_interface_t;
+#endif
+
+#define USB_DT_INTERFACE_SIZE 9
+
+
+/** USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bEndpointAddress;
+ __u8 bmAttributes;
+ __u16 wMaxPacketSize;
+ __u8 bInterval;
+
+ /// NOTE: these two are _only_ in audio endpoints.
+ /// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
+ __u8 bRefresh;
+ __u8 bSynchAddress;
+
+ /// Extra descriptors
+
+ unsigned char *extra;
+ int extralen;
+} __attribute__ ((packed));
+typedef struct usb_endpoint_descriptor usb_endpoint_descriptor_t;
+
+#define USB_DT_ENDPOINT_SIZE 7
+
+/// Audio extension
+#define USB_DT_ENDPOINT_AUDIO_SIZE 9
+
+
+/*
+ * Endpoints Macro
+ */
+/// in bEndpointAddress
+#define USB_ENDPOINT_NUMBER_MASK 0x0f
+
+#define USB_ENDPOINT_DIR_MASK 0x80
+
+/// in bmAttributes
+#define USB_ENDPOINT_XFERTYPE_MASK 0x03
+
+#define USB_ENDPOINT_XFER_CONTROL 0
+#define USB_ENDPOINT_XFER_ISOC 1
+#define USB_ENDPOINT_XFER_BULK 2
+#define USB_ENDPOINT_XFER_INT 3
+#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+
+
+
+/** USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __le16 bcdUSB;
+ __u8 bDeviceClass;
+ __u8 bDeviceSubClass;
+ __u8 bDeviceProtocol;
+ __u8 bMaxPacketSize0;
+ __u8 bNumConfigurations;
+ __u8 bRESERVED;
+} __attribute__ ((packed));
+
+
+
+/** USB_DT_OTG (from OTG 1.0a supplement) */
+struct usb_otg_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ /// support for HNP, SRP, etc
+ __u8 bmAttributes;
+} __attribute__ ((packed));
+
+/// from usb_otg_descriptor.bmAttributes
+#define USB_OTG_SRP (1 << 0)
+/// swap host/device roles
+#define USB_OTG_HNP (1 << 1)
+
+
+/** USB_DT_DEBUG: for special highspeed devices, replacing serial console */
+struct usb_debug_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ /// bulk endpoints with 8 byte maxpacket
+ __u8 bDebugInEndpoint;
+ __u8 bDebugOutEndpoint;
+};
+
+
+/** USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bFirstInterface;
+ __u8 bInterfaceCount;
+ __u8 bFunctionClass;
+ __u8 bFunctionSubClass;
+ __u8 bFunctionProtocol;
+ __u8 iFunction;
+};
+
+
+
+/**
+ * USB_DT_SECURITY: group of wireless security descriptors, including
+ * encryption types available for setting up a CC/association.
+ */
+struct usb_security_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __le16 wTotalLength;
+ __u8 bNumEncryptionTypes;
+};
+
+
+/**
+ * USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys
+ * may be retrieved.
+ */
+struct usb_key_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 tTKID[3];
+ __u8 bReserved;
+ __u8 bKeyData[0];
+};
+
+
+/** USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */
+struct usb_encryption_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bEncryptionType;
+#define USB_ENC_TYPE_UNSECURE 0
+
+/// non-wireless mode
+#define USB_ENC_TYPE_WIRED 1
+
+/// aes128/cbc session
+#define USB_ENC_TYPE_CCM_1 2
+
+/// rsa3072/sha1 auth
+#define USB_ENC_TYPE_RSA_1 3
+
+ /// use in SET_ENCRYPTION
+ __u8 bEncryptionValue;
+
+ __u8 bAuthKeyIndex;
+};
+
+
+
+/** USB_DT_BOS: group of wireless capabilities */
+struct usb_bos_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __le16 wTotalLength;
+ __u8 bNumDeviceCaps;
+};
+
+
+/** USB_DT_DEVICE_CAPABILITY: grouped with BOS */
+struct usb_dev_cap_header {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+};
+
+#define USB_CAP_TYPE_WIRELESS_USB 1
+
+/** Ultra Wide Band */
+struct usb_wireless_cap_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+
+ __u8 bmAttributes;
+#define USB_WIRELESS_P2P_DRD (1 << 1)
+#define USB_WIRELESS_BEACON_MASK (3 << 2)
+#define USB_WIRELESS_BEACON_SELF (1 << 2)
+#define USB_WIRELESS_BEACON_DIRECTED (2 << 2)
+#define USB_WIRELESS_BEACON_NONE (3 << 2)
+
+ /// bit rates, Mbps
+ __le16 wPHYRates;
+
+/// always set
+#define USB_WIRELESS_PHY_53 (1 << 0)
+
+#define USB_WIRELESS_PHY_80 (1 << 1)
+
+/// always set
+#define USB_WIRELESS_PHY_107 (1 << 2)
+
+#define USB_WIRELESS_PHY_160 (1 << 3)
+
+/// always set
+#define USB_WIRELESS_PHY_200 (1 << 4)
+
+#define USB_WIRELESS_PHY_320 (1 << 5)
+#define USB_WIRELESS_PHY_400 (1 << 6)
+#define USB_WIRELESS_PHY_480 (1 << 7)
+
+ /// TFI power levels
+ __u8 bmTFITXPowerInfo;
+
+ /// FFI power levels
+ __u8 bmFFITXPowerInfo;
+
+ __le16 bmBandGroup;
+ __u8 bReserved;
+};
+
+
+/**
+ * USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
+ * each endpoint descriptor for a wireless device
+ */
+struct usb_wireless_ep_comp_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bMaxBurst;
+ __u8 bMaxSequence;
+ __le16 wMaxStreamDelay;
+ __le16 wOverTheAirPacketSize;
+ __u8 bOverTheAirInterval;
+ __u8 bmCompAttributes;
+
+/// in bmCompAttributes
+#define USB_ENDPOINT_SWITCH_MASK 0x03
+
+#define USB_ENDPOINT_SWITCH_NO 0
+#define USB_ENDPOINT_SWITCH_SWITCH 1
+#define USB_ENDPOINT_SWITCH_SCALE 2
+};
+
+
+/**
+ * USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
+ * host and a device for connection set up, mutual authentication, and
+ * exchanging short lived session keys. The handshake depends on a CC.
+ */
+struct usb_handshake {
+ __u8 bMessageNumber;
+ __u8 bStatus;
+ __u8 tTKID[3];
+ __u8 bReserved;
+ __u8 CDID[16];
+ __u8 nonce[16];
+ __u8 MIC[8];
+};
+
+
+/**
+ * USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
+ * A CC may also be set up using non-wireless secure channels (including
+ * wired USB!), and some devices may support CCs with multiple hosts.
+ */
+struct usb_connection_context {
+ /// persistent host id
+ __u8 CHID[16];
+
+ /// device id (unique w/in host context)
+ __u8 CDID[16];
+
+ /// connection key
+ __u8 CK[16];
+};
+
+
+
+/** USB 2.0 defines three speeds, here's how Linux identifies them */
+
+enum usb_device_speed {
+ USB_SPEED_UNKNOWN = 0, /** enumerating */
+ USB_SPEED_LOW, USB_SPEED_FULL, /** usb 1.1 */
+ USB_SPEED_HIGH, /** usb 2.0 */
+ USB_SPEED_VARIABLE, /** wireless (usb 2.5) */
+};
+
+/**
+ * USB device state
+ */
+enum usb_device_state {
+ /** NOTATTACHED isn't in the USB spec, and this state acts
+ * the same as ATTACHED ... but it's clearer this way.
+ */
+ USB_STATE_NOTATTACHED = 0,
+
+ /** the chapter 9 device states */
+ USB_STATE_ATTACHED,
+ USB_STATE_POWERED,
+ USB_STATE_DEFAULT, /** limited function */
+ USB_STATE_ADDRESS,
+ USB_STATE_CONFIGURED, /** most functions */
+
+ USB_STATE_SUSPENDED /** Note: there are actually four different SUSPENDED
+ states, returning to POWERED, DEFAULT, ADDRESS, or
+ CONFIGURED respectively when SOF tokens flow again.
+ */
+};
+
+
+/*@}*/
+#endif /* __LINUX_USB_CH9_H */
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.c b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.c
new file mode 100644
index 0000000000..abb21aefc2
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.c
@@ -0,0 +1,980 @@
+/* usb pcd driver */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ *
+ */
+#include "../v2_burning_i.h"
+#include "platform.h"
+#include "usb_ch9.h"
+#include "dwc_pcd.h"
+#include "dwc_pcd_irq.h"
+#include "usb_pcd.h"
+
+#define COMPILE_TYPE_CHK(expr, t) typedef char t[(expr) ? 1 : -1]
+
+static int do_bulk_cmd(char* cmd);
+
+#define DWC_BLK_MAX_LEN 0X1000
+#define DWC_BLK_LEN(leftSz) ((leftSz) >= DWC_BLK_MAX_LEN ? DWC_BLK_MAX_LEN : (leftSz >= BULK_EP_MPS ? BULK_EP_MPS : leftSz))//FIXME:block length 4K, can be 64K ???
+#define DWC_BLK_NUM(totalTransLen) ( (totalTransLen/DWC_BLK_MAX_LEN) + ( (totalTransLen & (DWC_BLK_MAX_LEN - 1)) + (BULK_EP_MPS - 1) )/BULK_EP_MPS )
+
+#define DRIVER_VENDOR_ID 0x1B8E //Amlogic's VerdorID
+#define DRIVER_PRODUCT_ID 0xC003
+#define DRIVER_VERSION 0x0100
+
+
+#define STRING_MANUFACTURER 1
+#define STRING_PRODUCT 2
+#define STRING_SERIAL 3
+#define STRING_CONFIG 4
+#define STRING_INTERFACE 5
+static const struct usb_device_descriptor
+device_desc = {
+ sizeof device_desc, //__u8 bLength;
+ USB_DT_DEVICE, //__u8 bDescriptorType;
+#ifdef USE_FULL_SPEED
+ __constant_cpu_to_le16(0x0110), //__u16 bcdUSB;
+#else
+ __constant_cpu_to_le16(0x0200), //__u16 bcdUSB;
+#endif
+ USB_CLASS_PER_INTERFACE, //__u8 bDeviceClass;
+ 0, //__u8 bDeviceSubClass;
+ 0, //__u8 bDeviceProtocol;
+ 64, //__u8 bMaxPacketSize0;
+ __constant_cpu_to_le16(DRIVER_VENDOR_ID), //__u16 idVendor;
+ __constant_cpu_to_le16(DRIVER_PRODUCT_ID), //__u16 idProduct;
+ __constant_cpu_to_le16(0x0007), //__u16 bcdDevice;
+ 0/*STRING_MANUFACTURER*/, //__u8 iManufacturer;
+ 0/*STRING_PRODUCT*/, //__u8 iProduct;
+ 0/*STRING_SERIAL*/, //__u8 iSerialNumber;
+ 1 //__u8 bNumConfigurations;
+};
+
+#define INTF_CONFIG_DESC_LEN 23
+#define TOTAL_CONFIG_DESC_LEN (INTF_CONFIG_DESC_LEN + USB_DT_CONFIG_SIZE)
+
+#pragma pack(push, 1)
+struct _ConfigDesTotal_s{
+ struct usb_config_descriptor configDesc;
+ char intfDesc[INTF_CONFIG_DESC_LEN] ;
+};
+#pragma pack(pop)
+COMPILE_TYPE_CHK(TOTAL_CONFIG_DESC_LEN == sizeof(struct _ConfigDesTotal_s), a);
+
+static const struct _ConfigDesTotal_s _configDescTotal = {
+ .configDesc =
+ {
+ USB_DT_CONFIG_SIZE, //__u8 bLength;
+ USB_DT_CONFIG, //__u8 bDescriptorType;
+ TOTAL_CONFIG_DESC_LEN, //__u16 wTotalLength;
+ 1, //__u8 bNumInterfaces;
+ 1, //__u8 bConfigurationValue;
+ 0,//STRING_CONFIG, //__u8 iConfiguration;
+ USB_CONFIG_ATT_ONE |
+ USB_CONFIG_ATT_SELFPOWER, //__u8 bmAttributes;
+ 1 //__u8 MaxPower;
+ },
+
+ .intfDesc =
+ {
+ 0x09,// length
+ 0x04,//USB_DT_INTERFACE
+ 0x00,//bInterfaceNumber
+ 0x00,//bAlternateSetting
+ 0x02,//bNumEndpoints
+ 0xFF,//bInterfaceClass, 0xFF = USB_CLASS_VENDOR_SPEC
+ 0x00,//bInterfaceSubClass
+ 0x00,//bInterfaceProtocol
+ 0x00,//iInterface
+
+ 0x07,//Length
+ 0x05,//USB_DT_ENDPOINT
+ 0x80 | BULK_IN_EP_NUM,// 1 -- IN
+ 0x02,// Bulk
+#ifndef USE_FULL_SPEED
+ 0x00,//
+ 0x02,// 64 bytes MPS
+#else
+ 0x40,//
+ 0x00,// 64 bytes MPS
+#endif
+ 0x00,
+
+ 0x07,//Length
+ 0x05,//USB_DT_ENDPOINT
+ 0x00 | BULK_OUT_EP_NUM,// 2 -- OUT
+ 0x02,// Bulk
+#ifndef USE_FULL_SPEED
+ 0x00,//
+ 0x02,// 64 bytes MPS
+#else
+ 0x40,//
+ 0x00,// 64 bytes MPS
+#endif
+ 0x00
+ }
+};
+
+/*static const struct usb_config_descriptor* config_desc = &_configDescTotal.configDesc;*/
+/*static const unsigned char* intf_desc = &_configDescTotal.intfDesc;*/
+
+#define DT_STRING_ID_LEN 4
+static const char dt_string_id[DT_STRING_ID_LEN]={
+ DT_STRING_ID_LEN,
+ USB_DT_STRING,
+ 0x09,
+ 0x04,
+};
+#define DT_STRING_VID_LEN 16
+static const char dt_string_vid[DT_STRING_VID_LEN]=
+{
+ DT_STRING_VID_LEN,
+ USB_DT_STRING,
+ 'A',
+ 0,
+ 'm',
+ 0,
+ 'l',
+ 0,
+ 'o',
+ 0,
+ 'g',
+ 0,
+ 'i',
+ 0,
+ 'c',
+ 0
+};
+
+#define _PLATFORM_CHIP_INDEX '8'
+
+#define DT_STRING_PID_LEN 16
+static const char dt_string_pid[DT_STRING_PID_LEN]=
+{
+ DT_STRING_PID_LEN,
+ USB_DT_STRING,
+ 'M',
+ 0,
+ _PLATFORM_CHIP_INDEX,
+ 0,
+ '-',
+ 0,
+ 'C',
+ 0,
+ 'H',
+ 0,
+ 'I',
+ 0,
+ 'P',
+ 0
+};
+
+#define DT_STRING_SERIAL_LEN 18
+static const char dt_string_serial[DT_STRING_SERIAL_LEN]=
+{
+ DT_STRING_SERIAL_LEN,
+ USB_DT_STRING,
+ '2',
+ 0,
+ '0',
+ 0,
+ '1',
+ 0,
+ '1',
+ 0,
+ '0',
+ 0,
+ '4',
+ 0,
+ '0',
+ 0,
+ '6',
+ 0
+};
+
+static char _resultInfo[AM_BULK_REPLY_LEN] = {0};
+/*static char _bulkCmdBuf[AM_BULK_REPLY_LEN] = {0};*/
+/*#define buff ((char*)PCD_BUFF)*/
+static volatile char _pcd_buff[512] ;
+#define buff _pcd_buff
+
+int usb_pcd_init(void)
+{
+ flush_cache((unsigned long)buff, 512);
+ return dwc_core_init();
+}
+
+static unsigned int need_check_timeout;
+static unsigned int time_out_val;
+static unsigned int _auto_burn_time_out_base = 0;
+
+void usb_parameter_init(int time_out)
+{
+ need_check_timeout = 0;
+ /* clear utimer */
+ need_check_timeout=get_timer(need_check_timeout)?get_timer(need_check_timeout):1;
+ if (time_out)
+ {
+ time_out_val = time_out; // wait PC GetDescriptor command for 1us changed by Elvis
+
+ }
+ else
+ {
+ time_out_val = USB_ROM_CONN_TIMEOUT; // wait PC GetDescriptor command
+ }
+ //printf("need_check_timeout %d, time_out_val %d, time_out %d\n", need_check_timeout, time_out_val, time_out);
+
+ //Added by Sam Wu
+ optimus_buf_manager_init(16*1024);
+ optimus_download_init();
+ return;
+}
+
+int usb_pcd_irq(void)
+{
+ if (need_check_timeout)
+ {
+ unsigned curTime = get_timer(need_check_timeout);
+ if (curTime > time_out_val) {
+ dwc_otg_power_off_phy();
+ ERR("Try connect time out %u, %u, %u\n", curTime, time_out_val, need_check_timeout);
+ return 2;// return to other device boot
+ }
+ }
+ if (_auto_burn_time_out_base) {
+ unsigned waitIdentifyTime = get_timer(_auto_burn_time_out_base);
+ unsigned timeout = simple_strtoul(getenv(_ENV_TIME_OUT_TO_AUTO_BURN), NULL, 0);
+ if (waitIdentifyTime > timeout) {
+ ERR("waitIdentifyTime(%u) > timeout(%u)\n", waitIdentifyTime, timeout);
+ _auto_burn_time_out_base = 0;//clear it to allow enter burning next time
+ return __LINE__;
+ }
+ }
+
+ return dwc_otg_irq();
+}
+
+void start_bulk_transfer(pcd_struct_t *_pcd)
+{
+ _pcd->bulk_lock = 1; // TODO : add lock code.
+ dwc_otg_ep_req_start(_pcd,_pcd->bulk_out?BULK_OUT_EP_NUM:BULK_IN_EP_NUM);
+}
+/**
+ * This functions delegates the setup command to the gadget driver.
+ */
+void do_gadget_setup( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl)
+{
+ int value;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
+
+ /* usually this just stores reply data in the pre-allocated ep0 buffer,
+ * but config change events will also reconfigure hardware. */
+ switch (ctrl->bRequest)
+ {
+ case USB_REQ_GET_DESCRIPTOR:
+ {
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+ break;
+ //time_out_val = USB_ROM_DRIVER_TIMEOUT;// Wait SetConfig (PC install driver OK)
+ /*need_check_timeout = 0;*/
+ switch (w_value >> 8)
+ {
+ case USB_DT_DEVICE:
+ DBG("get dev desc\n");
+ value = min(w_length, (u16) sizeof device_desc);
+ /*usb_memcpy(buff, (char*)&device_desc, value);*/
+ /*
+ *memcpy((void*)buff, &device_desc, value);
+ *_pcd->buf = buff;
+ */
+ _pcd->buf = (volatile char*)&device_desc;
+ _pcd->length = value;
+ break;
+ case USB_DT_DEVICE_QUALIFIER:
+ DBG("get dev qual\n");
+ break;
+ case USB_DT_OTHER_SPEED_CONFIG:
+ DBG("--get other speed configuration descriptor\n");
+ DBG("--other speed configuration descriptor length :%d\n", value);
+ break;
+ case USB_DT_CONFIG:
+ {
+ USB_DBG("--get configuration descriptor: size %d\n",w_length);
+ if (w_length > USB_DT_CONFIG_SIZE) {//request USB_DT_CONFIG_SIZE only
+ value = TOTAL_CONFIG_DESC_LEN;
+ }
+ else{
+ value = w_length;
+ }
+ _pcd->buf = (volatile char*)&_configDescTotal;
+ _pcd->length = value;
+ /*printf("--get configuration descriptor: size %d, ret length :%d\n\n", w_length, value); */
+ printf("Get DT cfg\n");
+
+ }
+ break;
+
+ case USB_DT_STRING:
+ {
+ const char* str = NULL;
+
+ /*DBG("--get string Desc: id %d\n", w_value & 0xff);*/
+ printf("Get str %x\n", w_value);
+ switch (w_value & 0xff)
+ {
+ case 0: // IDs
+ /*usb_memcpy(buff,(void*)dt_string_id,DT_STRING_ID_LEN);*/
+ str = dt_string_id;
+ break;
+
+ case 1: // STRING_MANUFACTURER
+ /*usb_memcpy(buff,(void*)dt_string_vid,DT_STRING_VID_LEN);*/
+ str = dt_string_vid;
+ break;
+
+ case 2://STRING_PRODUCT
+ /*usb_memcpy(buff,(void*)dt_string_pid,DT_STRING_PID_LEN);*/
+ str = dt_string_pid;
+ break;
+
+ case 3://STRING_SERIAL
+ /*usb_memcpy(buff,(void*)dt_string_serial,DT_STRING_SERIAL_LEN);*/
+ str = dt_string_serial;
+ break;
+
+ default:
+ USB_ERR("Error string id!\n");
+ /*buff[0] = 0;*/
+ str = NULL;
+ break;
+ }
+ _pcd->buf = (char*)str;
+ _pcd->length = str[0];
+ /*printf("--get str DESC: id %d ,return length %d\n", (w_value & 0xff), _pcd->length);*/
+ }
+ break;
+
+ }
+
+ }
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ {
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
+ USB_RECIP_DEVICE))
+ break;
+ printf("set CFG\n");
+ _pcd->buf = 0;
+ _pcd->length = 0;
+ _pcd->request_config = 1; /* Configuration changed */
+ need_check_timeout = 0;
+ if (OPTIMUS_WORK_MODE_USB_UPDATE == optimus_work_mode_get()) {//not booting from usb
+ if (getenv(_ENV_TIME_OUT_TO_AUTO_BURN))_auto_burn_time_out_base = get_timer(0) ;
+ }
+ }
+ break;
+
+ case USB_REQ_GET_CONFIGURATION:
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+ break;
+ printf("get CFG\n");
+ buff[0] = 1;
+ _pcd->buf = buff;
+ _pcd->length = 1;
+ break;
+
+ default:
+ USB_ERR("--unknown control req %02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ w_index = 0; //remove compile warning
+ return ;
+}
+
+/**
+ * This functions delegates vendor ctrl request.
+ */
+void do_vendor_request( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl)
+{
+ unsigned long value =0;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
+
+ switch (ctrl->bRequest)
+ {
+ case AM_REQ_WRITE_MEM:
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ USB_DBG("--am req write memory\n");
+ value = (w_value << 16) + w_index;
+ USB_DBG("addr = 0x%08X, size = %d\n\n",value,w_length);
+ _pcd->buf = (char *)value; // copy to dst memory directly
+ _pcd->length = w_length;
+ break;
+
+ case AM_REQ_READ_MEM:
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ value = (w_value << 16) + w_index;
+
+ /*usb_memcpy((char *)buff,(char*)value,w_length);*/
+ memcpy((void*)buff,(void*)value,w_length);
+
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ break;
+
+ case AM_REQ_READ_AUX:
+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ /*unsigned int data = 0;*/
+ value = (w_value << 16) + w_index;
+
+ //data = _lr(value);
+ /**(unsigned int *)(unsigned)buff = data;*/
+ memset((char*)buff, 0, sizeof(unsigned));
+
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ break;
+
+ case AM_REQ_FILL_MEM:
+ case AM_REQ_WRITE_AUX:
+ case AM_REQ_MODIFY_MEM:
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ break;
+
+ case AM_REQ_RUN_IN_ADDR:
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ value = (w_value << 16) + w_index;
+ USB_DBG("--am req run in addr %p\n\n",value);
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ break;
+
+ case AM_REQ_WR_LARGE_MEM:
+ value = 1;
+ case AM_REQ_RD_LARGE_MEM:
+ USB_DBG("--am req large %s mem \n\n",value?"write":"read");
+
+ _pcd->bulk_len = w_value; // block length
+ _pcd->bulk_num = w_index; // number of block
+ _pcd->buf = buff; //EP0 command data buffer
+ _pcd->length = w_length; //EP0 command data length
+ /*FIXME: cann't delay when writelargeMem, or it will fail??*/
+ /*
+ *printf("f(%s)L%d: bulk_len=0x%x, bulk_num=%d, bufAddr=0x%x, len=0x%x\n",
+ * __func__, __LINE__, _pcd->bulk_len, _pcd->bulk_num, _pcd->buf, _pcd->length);
+ */
+ break;
+
+ case AM_REQ_DOWNLOAD:
+ {
+ value = 1;//is out
+ _pcd->bulk_len = w_value;//block length
+ _pcd->bulk_num = w_index;//how many times to transfer
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ }
+ break;
+
+ case AM_REQ_UPLOAD:
+ {
+ _pcd->buf = _resultInfo;
+ _pcd->length = w_length;//assert that lenght == 16 ????
+
+ optimus_buf_manager_get_command_data_for_upload_transfer((u8*)_resultInfo, w_length);
+ }
+ break;
+
+
+ case AM_REQ_IDENTIFY_HOST:
+ {
+ static const char id[4] =
+ {
+ [0] = USB_ROM_VER_MAJOR,
+ [1] = USB_ROM_VER_MINOR,
+ [2] = USB_ROM_STAGE_MAJOR,
+ [3] = USB_ROM_STAGE_MINOR,
+ };
+
+ _pcd->buf = (char*)id;
+ _pcd->length = w_length;//FIXME:asset w_length == 4 ??
+ _auto_burn_time_out_base = 0;//get burning tool identify command, so clear the timeout flag
+ printf("\nID[%d]\n", _pcd->buf[3]);
+ }
+ break;
+
+ case AM_REQ_BULKCMD://Added by Sam
+ {
+ _pcd->bulk_len = w_value; // block length
+ _pcd->bulk_num = w_index; // number of block
+ _pcd->buf = buff; //EP0 command data buffer, out buffer after set_up command
+ _pcd->length = w_length; //EP0 command data length
+ /*printf("blkc:len %d\n", _pcd->length);*/
+ _pcd->cmdtype.setup_complete = 1;
+ }
+ break;
+
+ case AM_REQ_TPL_CMD:
+ {
+ _pcd->buf = buff;
+ _pcd->length = w_length;
+ }
+ break;
+
+ case AM_REQ_TPL_STAT:
+ {
+ _pcd->buf = _resultInfo;
+ _pcd->length = w_length;
+ }
+ break;
+
+ default:
+ USB_ERR("--unknown vendor req %02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ break;
+ }
+
+ return;
+}
+
+/*
+ * This function will be called after a whole SETUP-OUT-IN transfer.
+ */
+void do_vendor_out_complete( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl)
+{
+ unsigned long value = 0;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
+ void (*fp)(void);
+ volatile char * buf;
+
+ //USB_DBG("do_vendor_out_complete(0x%x)\n", ctrl->bRequest);
+ switch (ctrl->bRequest)
+ {
+ case AM_REQ_WRITE_MEM:
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ USB_DBG("--am req write memory completed\n\n");
+ break;
+
+ case AM_REQ_FILL_MEM:
+ buf = (char*)_pcd->buf;
+ unsigned long addr,i;
+ for (i = 0; i < _pcd->length; i+=8) {
+ addr = *((unsigned int *)&buf[i]) ;
+ value = *((unsigned int *)&buf[i+4]) ;
+ *(unsigned int*)addr = value;
+ }
+ break;
+
+ case AM_REQ_WRITE_AUX:
+ buf = _pcd->buf;
+ unsigned int data =0;
+
+ data = *((unsigned int *)&buf[0]) ; //reg value
+ value = (w_value << 16) + w_index; //aux reg
+
+ dwc_write_reg32(value, data);
+ break;
+
+ case AM_REQ_MODIFY_MEM:
+ do_modify_memory(w_value,(char*)_pcd->buf);
+ break;
+
+ case AM_REQ_RUN_IN_ADDR:
+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE))
+ break;
+ value = (w_value << 16) + w_index;
+ USB_DBG("run addr = 0x%08X\n",value);
+ fp = (void(*)(void))value;
+ dwc_otg_power_off_phy();
+ fp();
+ break;
+
+ case AM_REQ_WR_LARGE_MEM:
+ value = 1; // is_out = 1
+ case AM_REQ_RD_LARGE_MEM:
+ {
+ const unsigned* intBuf = (unsigned*)buff;
+ _pcd->bulk_out = (char)value; // read or write
+ _pcd->bulk_buf = (char*)(u64)intBuf[0];
+ _pcd->bulk_data_len = intBuf[1]; // data length
+
+ //added by Sam.Wu
+ _pcd->bulk_xfer_len = 0;
+ _pcd->xferNeedReply = 0;
+
+ _pcd->bulk_len = DWC_BLK_LEN(_pcd->bulk_data_len);
+ _pcd->bulk_num = DWC_BLK_NUM(_pcd->bulk_data_len);
+ start_bulk_transfer(_pcd);
+ }
+ break;
+
+ case AM_REQ_DOWNLOAD:
+ value = 2;//2 to differ from write_large_mem
+ {
+ const unsigned* intBuf = (unsigned*)buff;
+ unsigned isPktResended = intBuf[0];
+ unsigned sequenceNo = intBuf[2];
+ _pcd->bulk_out = value;
+ _pcd->bulk_data_len = intBuf[1];
+ _pcd->bulk_xfer_len = 0;
+ _pcd->origiSum = intBuf[3];
+ _pcd->isPktResended = isPktResended;
+
+ if (!isPktResended) //request next buffer slot only if transfer packet not re-sended packet
+ {
+ int ret = optimus_buf_manager_get_buf_for_bulk_transfer(&_pcd->bulk_buf, _pcd->bulk_data_len, sequenceNo, NULL);
+ if (ret) _pcd->bulk_data_len = _pcd->bulk_len = _pcd->bulk_num = 0;
+ }
+
+ _pcd->sequenceNo = sequenceNo;
+
+ _pcd->bulk_len = DWC_BLK_LEN(_pcd->bulk_data_len);
+ _pcd->bulk_num = DWC_BLK_NUM(_pcd->bulk_data_len);
+ _pcd->xferNeedReply= 1;///////
+ start_bulk_transfer(_pcd);
+ }
+ break;
+
+ case AM_REQ_UPLOAD:
+ {
+ //command foramt: [4-7]dataLen, other don't care now
+ const u8* cmdData = (const u8*)_resultInfo;
+ const u32 sequenceNo = *(unsigned*)(cmdData + 8);
+ const u32 leftDataLen = *(unsigned*)(cmdData + 4);
+ int ret = 0;
+
+ _pcd->bulk_out = 0;
+ _pcd->bulk_xfer_len = 0;
+ _pcd->bulk_data_len = leftDataLen;
+
+ _pcd->bulk_len = DWC_BLK_LEN(leftDataLen);
+ _pcd->bulk_num = DWC_BLK_NUM(leftDataLen);
+
+ ret = optimus_buf_manager_get_buf_for_bulk_transfer(&_pcd->bulk_buf, _pcd->bulk_data_len, sequenceNo, _resultInfo);
+ if (ret) _pcd->bulk_data_len = _pcd->bulk_len = _pcd->bulk_num = 0;//respond 0 byte data to stop transfer
+
+ DWN_DBG("up 0x:len %x, buf %p, bulk_num %d\n", _pcd->bulk_data_len, _pcd->bulk_buf, _pcd->bulk_num);
+ _pcd->xferNeedReply= 1;///////
+ start_bulk_transfer(_pcd);
+ }
+ break;
+
+
+ case AM_REQ_TPL_CMD:
+ /* this is an example for any command */
+ if (!w_index) {/* assume subcode is 0 */
+/* ???????????????????????????
+ char dev[16] = {0};
+ u64 offset = 0;
+ u64 tmp = 0;
+ u32 mem_addr = (*(unsigned int*)buff);
+ offset |= (*(unsigned int*)&buff[16]);
+ tmp = (*(unsigned int*)&buff[20]);
+ offset |= (tmp << 32);
+
+ u32 size = (*(unsigned int*)&buff[12]);
+ usb_memcpy(dev,&buff[32],16);
+ burn_board(dev, mem_addr, offset, size);
+*/
+ }
+ else if(w_index == 1){
+ char cmd[CMD_BUFF_SIZE];
+ memcpy(cmd, (void*)buff, CMD_BUFF_SIZE);
+ if (strncmp(cmd,"bootm",(sizeof("bootm")-1)) == 0) {
+ dwc_otg_pullup(0);//disconnect
+ }
+ printf("tplcmd[%s]\n", cmd);
+ optimus_working(cmd, _resultInfo);
+ }
+ break;
+
+ case AM_REQ_BULKCMD:
+ {
+ do_bulk_cmd((char*)buff);
+ }
+ break;
+
+ default:
+ USB_ERR("--unknown vendor req comp %02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+ w_length = 0;//remove compile warning
+ return;
+}
+
+/*
+ * This function will be called after a whole SETUP-IN-OUT transfer.
+ */
+void do_vendor_in_complete( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl)
+{
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
+
+ //USB_DBG("do_vendor_out_complete(0x%x)\n", ctrl->bRequest);
+ switch (ctrl->bRequest)
+ {
+ case AM_REQ_IDENTIFY_HOST:
+ case AM_REQ_TPL_STAT:
+ break;
+
+ case USB_REQ_GET_DESCRIPTOR:
+ break;
+
+ case AM_REQ_UPLOAD:
+ {
+ //command foramt: [4-7]dataLen, other don't care now
+ const u8* cmdData = (const u8*)_resultInfo;
+ const u32 sequenceNo = *(unsigned*)(cmdData + 8);
+ const u32 leftDataLen = *(unsigned*)(cmdData + 4);
+ int ret = 0;
+
+ _pcd->bulk_out = 0;
+ _pcd->bulk_xfer_len = 0;
+ _pcd->bulk_data_len = leftDataLen;
+
+ _pcd->bulk_len = DWC_BLK_LEN(leftDataLen);
+ _pcd->bulk_num = DWC_BLK_NUM(leftDataLen);
+
+ ret = optimus_buf_manager_get_buf_for_bulk_transfer(&_pcd->bulk_buf, _pcd->bulk_data_len, sequenceNo, _resultInfo);
+ if (ret) _pcd->bulk_data_len = _pcd->bulk_len = _pcd->bulk_num = 0;//respond 0 byte data to stop transfer
+
+ DWN_DBG("up 0x:len %x, buf %p, bulk_num %d\n", _pcd->bulk_data_len, _pcd->bulk_buf, _pcd->bulk_num);
+ _pcd->xferNeedReply= 1;///////
+ start_bulk_transfer(_pcd);
+ }
+ break;
+
+ default:
+ USB_ERR("--unknown vendor req comp %02x.%02x v%04x i%04x l%u\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+ w_length = 0;//remove compile warning
+ return;
+}
+
+
+int bulk_transfer_reply(const pcd_struct_t* _pcd)
+{
+ static int _mediaErr = 0;
+ static pcd_struct_t pcd;
+ char* replyBuf = _resultInfo;
+ const void* data = _pcd->bulk_buf;
+ const unsigned len = _pcd->bulk_xfer_len;
+ const unsigned sequenceNo = _pcd->sequenceNo;
+ int isOut = !_pcd->bulk_out;//handshake direction is opposite
+ const u32 origiSum = _pcd->origiSum;
+ unsigned genSum = 0;
+ int ret = 0;
+ const int isPktResended = _pcd->isPktResended;
+
+ dwc_otg_bulk_ep_enable(!isOut);//enable the bulk in ep first before optimus_working!!
+
+ if(0 == _pcd->sequenceNo
+ && !isPktResended)//media error can't resolved by reseneded, only memory(dram) error can
+ {
+ _mediaErr = 0;//set error none if download a new file
+ }
+
+ if (_mediaErr) {
+ sprintf(replyBuf, "media error %d at seq %d, resend %d\n", _mediaErr, sequenceNo, isPktResended);
+ DWN_ERR(replyBuf);
+ ret = __LINE__;
+ }
+ else
+ {
+ genSum = add_sum(data, len);
+
+ if (origiSum != genSum)
+ {
+ sprintf(replyBuf, "0x: genSum %x != org %x at seq %x, len %x, resend %d\n", genSum, origiSum, sequenceNo, len, isPktResended);
+ DWN_ERR(replyBuf);
+ ret = __LINE__;
+ }
+ }
+
+ if (!ret) //add-sum checked ok and no media error
+ {
+ _mediaErr = optimus_buf_manager_report_transfer_complete(_pcd->bulk_xfer_len, replyBuf);
+ if (_mediaErr) {
+ sprintf(replyBuf, "media error %d at seq %d\n", _mediaErr, sequenceNo);
+ DWN_ERR(replyBuf);
+ ret = __LINE__;
+ }
+ }
+
+ if (!ret)
+ {
+ memcpy(replyBuf, "OK!!", 4);
+ }
+
+ //PCD fields needed for reply
+ //see implementation of dwc_otg_ep_req_start
+ pcd.bulk_data_len = AM_BULK_REPLY_LEN;//total length <= 4k
+ pcd.bulk_len = DWC_BLK_LEN(pcd.bulk_data_len);//total length <= 4k
+ pcd.bulk_num = DWC_BLK_NUM(pcd.bulk_data_len);
+ pcd.bulk_buf = replyBuf;
+ pcd.bulk_xfer_len = 0;
+
+ DWN_DBG("replyBuf %s\n", replyBuf);
+ dwc_otg_ep_req_start(&pcd, isOut?BULK_OUT_EP_NUM:BULK_IN_EP_NUM);
+
+ return ret;
+}
+
+/*
+ * This function will be called after a whole bulk out transfer.
+ * Attention That All bulk transfer will reach here after completed!!
+ */
+void do_bulk_complete( pcd_struct_t *_pcd)
+{
+ _pcd->bulk_lock = 0;
+ _pcd->bulk_num--;
+ /*_pcd->bulk_data_len -= _pcd->xfer_len;*/
+ _pcd->bulk_xfer_len += _pcd->xfer_len;
+
+ //open this debug info if see if _pcd->bulk_num is 0 has been reponsed! i.e, all data transfrred ended
+ //if not bulk in tranferred, open in printf will let down the csw of mwrite(csw will be invalid transfer)
+ DWN_DBG("left blk %d, this len 0x%x, bulk_xfer_len 0x%x\n", _pcd->bulk_num, _pcd->xfer_len, _pcd->bulk_xfer_len);
+
+ if(_pcd->bulk_num > 0
+ && _pcd->bulk_len)//if earlier packet length is 0, no next xfer here!!
+ {
+ const u32 leftDataLen = _pcd->bulk_data_len - _pcd->bulk_xfer_len;
+
+ _pcd->bulk_len = DWC_BLK_LEN(leftDataLen);
+
+ /*_pcd->bulk_buf += _pcd->bulk_len;*/
+ start_bulk_transfer(_pcd);
+
+ return;/////////////////
+ }
+
+ if (this_pcd.xferNeedReply) //get download command and is out
+ {
+ this_pcd.xferNeedReply = 0;////
+
+ if (2 == _pcd->bulk_out) //2 means download command 0x32, only this command need handshake??!!!!!
+ {
+ bulk_transfer_reply(_pcd);
+ return;////////
+ }
+
+ if (!_pcd->bulk_out)
+ {
+ optimus_buf_manager_report_transfer_complete(_pcd->bulk_xfer_len, NULL);
+ }
+ }
+}
+
+static int bulk_cmd_reply(const char* replyBuf)
+{
+ static pcd_struct_t pcd;
+
+ //PCD fields needed for reply
+ //see implementation of dwc_otg_ep_req_start
+ pcd.bulk_len = AM_BULK_REPLY_LEN;
+ pcd.bulk_buf = (char*)replyBuf;
+ pcd.bulk_xfer_len = 0;
+
+ this_pcd.bulk_out = 0;//////////////////////////////OH NO!!!! I don't like the common pcd, FIXME to use various PCD !!
+ this_pcd.xferNeedReply = 0;
+ dwc_otg_ep_req_start(&pcd, BULK_IN_EP_NUM);//bulk in to reply result, it is ALWAYS IN
+
+ return 0;
+}
+
+static int do_bulk_cmd(char* cmd)
+{
+ int ret = 0;
+ const int is_in = 1;
+
+ ret = dwc_otg_bulk_ep_enable(is_in);//enable the bulk in ep first before optimus_working!!
+
+ printf("BULKcmd[%s]\n", cmd);
+ ret = optimus_working(cmd, _resultInfo);
+
+ ret = bulk_cmd_reply(_resultInfo);
+
+ return ret;
+}
+
+void do_modify_memory(u16 opcode, char *inbuff)
+{
+ unsigned int *mem,*mem2;
+ unsigned int data,mask;
+
+ mem = *(unsigned int**)&inbuff[0];
+ data = *(unsigned int*)&inbuff[4];
+ mask = *(unsigned int*)&inbuff[8];
+ mem2= *(unsigned int**)&inbuff[12];
+
+ switch (opcode) {
+ case 0: //*mem = data
+ *mem = data;
+ break;
+
+ case 1:// *mem = (data & mask)
+ *mem = data & mask;
+ break;
+
+ case 2:// *mem =(*mem | mask)
+ *mem = *mem | mask;
+ break;
+
+ case 3:// *mem = (data & (~mask))
+ *mem = (data & (~mask));
+ break;
+
+ case 4:// *mem = (data & mask) |(*mem & ~mask)
+ *mem = (data & mask) |(*mem & ~mask);
+ break;
+
+ case 5:// *mem = *mem2
+ *mem = *mem2;
+ break;
+
+ case 6:// *mem = (*mem2 & mask)
+ *mem = (*mem2 & mask);
+ break;
+
+ case 7:// while(data--) {*mem++ = *mem2++}
+ while (data--) {
+ *mem++ = *mem2++;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
+
diff --git a/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.h b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.h
new file mode 100644
index 0000000000..d4f9827171
--- /dev/null
+++ b/drivers/usb/gadget/v2_burning/v2_usb_tool/usb_pcd.h
@@ -0,0 +1,41 @@
+/* usb pcd driver header */
+/*
+ * (C) Copyright 2010 Amlogic, Inc
+ *
+ * Victor Wan, victor.wan@amlogic.com,
+ * 2010-03-24 @ Shanghai
+ *
+ */
+#ifndef __USB_PCD_H__
+#define __USB_PCD_H__
+#include <asm/types.h>
+
+#define CMD_BUFF_SIZE 512
+
+int usb_pcd_init(void);
+int usb_pcd_irq(void);
+extern int optimus_working (const char *cmd, char* buff);
+
+// Vendor request defines
+#define AM_REQ_WRITE_MEM 0x01
+#define AM_REQ_READ_MEM 0x02
+#define AM_REQ_FILL_MEM 0x03
+#define AM_REQ_MODIFY_MEM 0x04
+#define AM_REQ_RUN_IN_ADDR 0x05
+#define AM_REQ_WRITE_AUX 0x06
+#define AM_REQ_READ_AUX 0x07
+
+#define AM_REQ_WR_LARGE_MEM 0x11
+#define AM_REQ_RD_LARGE_MEM 0x12
+#define AM_REQ_IDENTIFY_HOST 0x20
+
+#define AM_REQ_TPL_CMD 0x30
+#define AM_REQ_TPL_STAT 0x31
+void do_modify_memory(u16 opcode, char *inbuff);
+
+#define AM_REQ_DOWNLOAD 0X32
+#define AM_REQ_UPLOAD 0X33
+#define AM_REQ_BULKCMD 0X34
+#define AM_BULK_REPLY_LEN CMD_BUFF_SIZE
+
+#endif
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index bccc3e3ed8..57af24941a 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -43,7 +43,7 @@ static disk_partition_t cur_part_info;
#define DOS_FS_TYPE_OFFSET 0x36
#define DOS_FS32_TYPE_OFFSET 0x52
-static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
+int disk_read(__u32 block, __u32 nr_blocks, void *buf)
{
if (!cur_dev || !cur_dev->block_read)
return -1;
diff --git a/include/amlogic/aml_v2_burning.h b/include/amlogic/aml_v2_burning.h
new file mode 100644
index 0000000000..1ecdad65b0
--- /dev/null
+++ b/include/amlogic/aml_v2_burning.h
@@ -0,0 +1,31 @@
+/*
+ * \file aml_v2_burning.h
+ * \brief common interfaces for version burning
+ *
+ * \version 1.0.0
+ * \date 09/15/2013
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+
+//is the uboot loaded from usb otg
+int is_tpl_loaded_from_usb(void);
+
+//is the uboot loaded from sdcard mmc 0
+//note only sdmmc supported by romcode when external device boot
+int is_tpl_loaded_from_ext_sdmmc(void);
+
+//Check if uboot loaded from external sdmmc or usb otg
+int aml_burn_check_uboot_loaded_for_burn(int flag);
+
+int aml_burn_factory_producing(int flag, bd_t* bis);
+
+//usb producing mode, if tpl loaded from usb pc tool and auto enter producing mode
+int aml_try_factory_usb_burning(int flag, bd_t* bis);
+
+//Auto enter sdcard burning if booted from sdcard and aml_sdc_burn.ini existed
+int aml_try_factory_sdcard_burning(int flag, bd_t* bis);
+
+
diff --git a/include/amlogic/storage_if.h b/include/amlogic/storage_if.h
new file mode 100644
index 0000000000..725c238559
--- /dev/null
+++ b/include/amlogic/storage_if.h
@@ -0,0 +1,66 @@
+/*
+ * \file storage_if.h
+ * \brief interfaces declarations for storage operations
+ *
+ * \version 1.0.0
+ * \date 2013-7-16
+ * \author Sam.Wu <yihui.wu@amlgic.com>
+ *
+ * Copyright (c) 2013 Amlogic. All Rights Reserved.
+ *
+ */
+#ifndef __STOARGE_IF_H__
+#define __STOARGE_IF_H__
+
+
+/***
+upgrade_read_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+***/
+int store_read_ops(unsigned char *partition_name,unsigned char * buf, uint64_t off, uint64_t size);
+
+
+/***
+upgrade_write_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+***/
+int store_write_ops(unsigned char *partition_name,unsigned char * buf,uint64_t off, uint64_t size);
+
+
+/***
+upgrade_write_ops:
+
+partition_name: env / logo / recovery /boot / system /cache /media
+
+***/
+int store_get_partititon_size(unsigned char *partition_name, uint64_t *size);
+
+
+/***
+upgrade_erase_ops:
+
+partition_name: boot / data
+
+flag = 0; indicate erase partition ;
+flag = 1; indicate scurb whole nand;
+
+***/
+int store_erase_ops(unsigned char *par_name, uint64_t off, uint64_t size, unsigned char flag);
+
+/***
+bootloader:
+***/
+int store_boot_read(unsigned char * buf, uint64_t off, uint64_t size);
+
+int store_boot_write(unsigned char * buf,uint64_t off, uint64_t size);
+
+int store_init(unsigned flag);
+
+int store_exit(void);
+
+#endif//ifndef __STOARGE_IF_H__
+
diff --git a/include/configs/gxb_p200_v1.h b/include/configs/gxb_p200_v1.h
index 5451128513..559c4da71b 100644
--- a/include/configs/gxb_p200_v1.h
+++ b/include/configs/gxb_p200_v1.h
@@ -104,7 +104,8 @@
#define CONFIG_USB_DWC_OTG_HCD 1
#define CONFIG_USB_DWC_OTG_294 1
#endif //#if defined(CONFIG_CMD_USB)
-#define CONFIG_AML_TINY_USBTOOL 1
+//#define CONFIG_AML_TINY_USBTOOL 1
+#define CONFIG_AML_V2_FACTORY_BURN 1
/* net */
#define CONFIG_CMD_NET 1
@@ -156,6 +157,7 @@
#define CONFIG_NEED_BL301 1
#define CONFIG_BOOTDELAY 1 //delay 1s
#define CONFIG_SYS_LONGHELP 1
+#define CONFIG_CMD_MISC 1
#endif
diff --git a/include/configs/gxb_p201_v1.h b/include/configs/gxb_p201_v1.h
index 8dc107f8f2..335d96bbfa 100644
--- a/include/configs/gxb_p201_v1.h
+++ b/include/configs/gxb_p201_v1.h
@@ -103,7 +103,8 @@
#define CONFIG_USB_DWC_OTG_HCD 1
#define CONFIG_USB_DWC_OTG_294 1
#endif //#if defined(CONFIG_CMD_USB)
-#define CONFIG_AML_TINY_USBTOOL 1
+//#define CONFIG_AML_TINY_USBTOOL 1
+#define CONFIG_AML_V2_FACTORY_BURN 1
/* net */
#define CONFIG_CMD_NET 1
@@ -155,6 +156,7 @@
#define CONFIG_NEED_BL301 1
#define CONFIG_BOOTDELAY 1 //delay 1s
#define CONFIG_SYS_LONGHELP 1
+#define CONFIG_CMD_MISC 1
#endif
diff --git a/include/configs/gxb_skt_v1.h b/include/configs/gxb_skt_v1.h
index 434d867799..20d6d47895 100644
--- a/include/configs/gxb_skt_v1.h
+++ b/include/configs/gxb_skt_v1.h
@@ -134,7 +134,8 @@
#define CONFIG_USB_DWC_OTG_HCD 1
#define CONFIG_USB_DWC_OTG_294 1
#endif //#if defined(CONFIG_CMD_USB)
-#define CONFIG_AML_TINY_USBTOOL 1
+//#define CONFIG_AML_TINY_USBTOOL 1
+#define CONFIG_AML_V2_FACTORY_BURN 1
/* net */
#define CONFIG_CMD_NET 1
@@ -186,6 +187,7 @@
#define CONFIG_NEED_BL301 1
#define CONFIG_BOOTDELAY 1
#define CONFIG_SYS_LONGHELP 1
+#define CONFIG_CMD_MISC 1
//support secure boot
//#define CONFIG_AML_SECURE_UBOOT 1
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8438490fe4..b717292132 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -65,7 +65,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
* adjust this accordingly.
*/
#define NAND_MAX_OOBSIZE 744
-#define NAND_MAX_PAGESIZE 8192
+//#define NAND_MAX_PAGESIZE 8192
#endif
/*
@@ -561,10 +561,10 @@ struct nand_buffers {
uint8_t *ecccalc;
uint8_t *ecccode;
uint8_t *databuf;
-#else
- uint8_t ecccalc[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
- uint8_t ecccode[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
- uint8_t databuf[ALIGN(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE,
+//#else
+// uint8_t ecccalc[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
+// uint8_t ecccode[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
+// uint8_t databuf[ALIGN(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE,
ARCH_DMA_MINALIGN)];
#endif
};
@@ -1009,8 +1009,9 @@ static inline int nand_opcode_8bits(unsigned int command)
/* return the supported JEDEC features. */
static inline int jedec_feature(struct nand_chip *chip)
{
- return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features)
- : 0;
+ //return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features)
+ // : 0;
+ return 0;
}
#ifdef __UBOOT__
diff --git a/include/mmc.h b/include/mmc.h
index 7ec255d882..a5c0bcbef1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -313,6 +313,7 @@ struct mmc {
u64 capacity_boot;
u64 capacity_rpmb;
u64 capacity_gp[4];
+ u64 boot_size;
block_dev_desc_t block_dev;
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
char init_in_progress; /* 1 if we have done mmc_start_init() */
@@ -354,6 +355,8 @@ int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
unsigned short cnt, unsigned char *key);
int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
unsigned short cnt, unsigned char *key);
+
+int mmc_switch_partition(struct mmc* mmc, unsigned int part);
/**
* Start device initialization and return immediately; it does not block on
* polling OCR (operation condition register) status. Then you should call