diff --git a/DefineHeader.h b/DefineHeader.h index a8caa33..ac9d898 100644 --- a/DefineHeader.h +++ b/DefineHeader.h @@ -28,7 +28,17 @@ typedef unsigned short WCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned int DWORD; - +#define ALIGN(x, a) __ALIGN_MASK((x), (a) - 1) +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define RK28_SEC2_RESERVED_LEN 473 +#define CHIPINFO_LEN 16 +#define RK28_SEC3_RESERVED_LEN 382 +#define RKDEVICE_SN_LEN 60 +#define RKDEVICE_UID_LEN 30 +#define RKDEVICE_MAC_LEN 6 +#define RKDEVICE_WIFI_LEN 6 +#define RKDEVICE_BT_LEN 6 +#define RKDEVICE_IMEI_LEN 15 typedef enum{ RKNONE_DEVICE = 0, RK27_DEVICE = 0x10, @@ -77,6 +87,12 @@ typedef struct{ char szItemName[20]; char szItemValue[256]; } STRUCT_CONFIG_ITEM, *PSTRUCT_CONFIG_ITEM; +typedef struct +{ + char szItemName[64]; + UINT uiItemOffset; + UINT uiItemSize; +}STRUCT_PARAM_ITEM,*PSTRUCT_PARAM_ITEM; typedef struct _STRUCT_RKDEVICE_DESC{ USHORT usVid; USHORT usPid; @@ -86,12 +102,89 @@ typedef struct _STRUCT_RKDEVICE_DESC{ ENUM_RKDEVICE_TYPE emDeviceType; void *pUsbHandle; } STRUCT_RKDEVICE_DESC, *PSTRUCT_RKDEVICE_DESC; +typedef struct { + DWORD dwTag; + BYTE reserved[4]; + UINT uiRc4Flag; + USHORT usBootCode1Offset; + USHORT usBootCode2Offset; + BYTE reserved1[490]; + USHORT usBootDataSize; + USHORT usBootCodeSize; + USHORT usCrc; +} RK28_IDB_SEC0, *PRK28_IDB_SEC0; + +typedef struct { + USHORT usSysReservedBlock; + USHORT usDisk0Size; + USHORT usDisk1Size; + USHORT usDisk2Size; + USHORT usDisk3Size; + UINT uiChipTag; + UINT uiMachineId; + USHORT usLoaderYear; + USHORT usLoaderDate; + USHORT usLoaderVer; + USHORT usLastLoaderVer; + USHORT usReadWriteTimes; + DWORD dwFwVer; + USHORT usMachineInfoLen; + UCHAR ucMachineInfo[30]; + USHORT usManufactoryInfoLen; + UCHAR ucManufactoryInfo[30]; + USHORT usFlashInfoOffset; + USHORT usFlashInfoLen; + UCHAR reserved[384]; + UINT uiFlashSize; + BYTE reserved1; + BYTE bAccessTime; + USHORT usBlockSize; + BYTE bPageSize; + BYTE bECCBits; + BYTE reserved2[8]; + USHORT usIdBlock0; + USHORT usIdBlock1; + USHORT usIdBlock2; + USHORT usIdBlock3; + USHORT usIdBlock4; +} RK28_IDB_SEC1, *PRK28_IDB_SEC1; + +typedef struct { + USHORT usInfoSize; + BYTE bChipInfo[CHIPINFO_LEN]; + BYTE reserved[RK28_SEC2_RESERVED_LEN]; + char szVcTag[3]; + USHORT usSec0Crc; + USHORT usSec1Crc; + UINT uiBootCodeCrc; + USHORT usSec3CustomDataOffset; + USHORT usSec3CustomDataSize; + char szCrcTag[4]; + USHORT usSec3Crc; +} RK28_IDB_SEC2, *PRK28_IDB_SEC2; + +typedef struct { + USHORT usSNSize; + BYTE sn[RKDEVICE_SN_LEN]; + BYTE reserved[RK28_SEC3_RESERVED_LEN]; + BYTE wifiSize; + BYTE wifiAddr[RKDEVICE_WIFI_LEN]; + BYTE imeiSize; + BYTE imei[RKDEVICE_IMEI_LEN]; + BYTE uidSize; + BYTE uid[RKDEVICE_UID_LEN]; + BYTE blueToothSize; + BYTE blueToothAddr[RKDEVICE_BT_LEN]; + BYTE macSize; + BYTE macAddr[RKDEVICE_MAC_LEN]; +} RK28_IDB_SEC3, *PRK28_IDB_SEC3; #pragma pack() typedef list RKDEVICE_DESC_SET; typedef RKDEVICE_DESC_SET::iterator device_list_iter; typedef vector STRING_VECTOR; typedef vector UINT_VECTOR; typedef vector CONFIG_ITEM_VECTOR; +typedef vector PARAM_ITEM_VECTOR; typedef enum{ TESTDEVICE_PROGRESS, DOWNLOADIMAGE_PROGRESS, diff --git a/Makefile.am b/Makefile.am index 47787c1..05cb453 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,7 +13,8 @@ rkdeveloptool_SOURCES = main.cpp \ RKDevice.cpp RKDevice.h \ RKImage.cpp RKImage.h \ RKLog.cpp RKLog.h \ - RKScan.cpp RKScan.h + RKScan.cpp RKScan.h \ + gpt.h rkdeveloptool_LDADD = $(LIBUSB1_LIBS) clean-local:: diff --git a/configure.ac b/configure.ac index 44f4c1f..03d3007 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Copyright (C) 2017 Trevor Woerner -AC_INIT([Rockchip rkdeveloptool], 1.0, [Eddie Cai ], rkdeveloptool) +AC_INIT([Rockchip rkdeveloptool], 1.2, [Eddie Cai ], rkdeveloptool) AC_PREREQ([2.68]) AC_CONFIG_SRCDIR(main.cpp) AC_CONFIG_AUX_DIR(cfg) diff --git a/crc.cpp b/crc.cpp index 73de7c2..8bd2647 100644 --- a/crc.cpp +++ b/crc.cpp @@ -6,7 +6,7 @@ */ #include "DefineHeader.h" UINT gTable_Crc32[256] = -{//crfc32 factor 0x04C10DB7 +{//crc32 factor 0x04C10DB7 0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005, 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61, @@ -72,6 +72,76 @@ UINT gTable_Crc32[256] = 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668, 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4, }; +#define tole(x) (x) +/*factor is 0xedb88320*/ +unsigned int crc32table_le[] = { +tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL), +tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L), +tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L), +tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L), +tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL), +tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L), +tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL), +tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L), +tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L), +tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL), +tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L), +tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L), +tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L), +tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL), +tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L), +tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL), +tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL), +tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L), +tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L), +tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L), +tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL), +tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L), +tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL), +tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L), +tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L), +tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL), +tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L), +tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L), +tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L), +tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL), +tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L), +tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL), +tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL), +tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L), +tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L), +tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L), +tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL), +tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L), +tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL), +tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L), +tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L), +tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL), +tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L), +tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L), +tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L), +tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL), +tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L), +tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL), +tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL), +tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L), +tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L), +tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L), +tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL), +tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L), +tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL), +tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L), +tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L), +tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL), +tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L), +tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L), +tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L), +tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL), +tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L), +tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL) +}; + + #define rr_max 104 /* Number of parity checks, rr = deg[g(x)] */ #define parallel 8 //bit count #define mm 13//limit count @@ -93,16 +163,67 @@ UINT ggx1=0; UINT ggx2=0; UINT ggx3=0; UINT ggx4=0; + // get crc32 value UINT CRC_32(unsigned char* pData, UINT ulSize) { UINT i; UINT nAccum = 0; - for ( i=0; i>24)^(*pData++)]; + for ( i = 0; i < ulSize; i++) + nAccum = (nAccum << 8) ^ gTable_Crc32[(nAccum >> 24) ^ (*pData++)]; return nAccum; } +#define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) + +unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len) +{ +/* + UINT i; + UINT nAccum = crc; + + for ( i = 0; i < len; i++) { + nAccum = (nAccum >> 8) ^ crc32table_le[(nAccum ^ (*p)) & 0xFF]; + p++; + } + return nAccum; +*/ + unsigned int *b =(unsigned int *)p; + unsigned int *tab = crc32table_le; + crc = crc ^ 0xFFFFFFFF; + if((((long)b)&3 && len)){ + do { + unsigned char *p = (unsigned char *)b; + DO_CRC(*p++); + b = (unsigned int *)p; + } while ((--len) && ((long)b)&3 ); + } + if((len >= 4)){ + unsigned int save_len = len & 3; + len = len >> 2; + --b; + do { + crc ^= *++b; + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + } while (--len); + b++; + len = save_len; + } + if(len){ + do { + unsigned char *p = (unsigned char *)b; + DO_CRC(*p++); + b = (unsigned int *)p; + } while (--len); + } + crc = crc ^ 0xFFFFFFFF; + return crc; + +} + #define CRC16_CCITT 0x1021 //CRC operator void CRCBuildTable16(unsigned short aPoly , unsigned short *crcTable) { @@ -359,4 +480,4 @@ void generate_gf() index_of[alpha_to[i]] = i ; } index_of[0] = -1 ; -} \ No newline at end of file +} diff --git a/gpt.h b/gpt.h new file mode 100644 index 0000000..14f5d1c --- /dev/null +++ b/gpt.h @@ -0,0 +1,163 @@ +#ifndef _GPT_H +#define _GPT_H + +#define MSDOS_MBR_SIGNATURE 0xAA55 +#define EFI_PMBR_OSTYPE_EFI 0xEF +#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE + +#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL +#define GPT_HEADER_REVISION_V1 0x00010000 +#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL +#define GPT_ENTRY_NAME "gpt" +#define GPT_ENTRY_NUMBERS 128 +#define GPT_ENTRY_SIZE 128 +#define PART_PROPERTY_BOOTABLE (1 << 2) + +#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ + ((efi_guid_t) \ + {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +#define PARTITION_IDBLOCK_GUID \ + EFI_GUID(0xDA2BB095, 0x390E, 0x48ca, \ + 0x90, 0x47, 0x05, 0xE8, 0x18, 0xB2, 0x97, 0xCE) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#define uswap_16(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) +#define uswap_32(x) \ + ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) +#define _uswap_64(x, sfx) \ + ((((x) & 0xff00000000000000##sfx) >> 56) | \ + (((x) & 0x00ff000000000000##sfx) >> 40) | \ + (((x) & 0x0000ff0000000000##sfx) >> 24) | \ + (((x) & 0x000000ff00000000##sfx) >> 8) | \ + (((x) & 0x00000000ff000000##sfx) << 8) | \ + (((x) & 0x0000000000ff0000##sfx) << 24) | \ + (((x) & 0x000000000000ff00##sfx) << 40) | \ + (((x) & 0x00000000000000ff##sfx) << 56)) +#if defined(__GNUC__) +# define uswap_64(x) _uswap_64(x, ull) +#else +# define uswap_64(x) _uswap_64(x, ) +#endif +#define __LITTLE_ENDIAN__ 1 +#ifdef __LITTLE_ENDIAN__ +# define cpu_to_le16(x) (x) +# define cpu_to_le32(x) (x) +# define cpu_to_le64(x) (x) +# define le16_to_cpu(x) (x) +# define le32_to_cpu(x) (x) +# define le64_to_cpu(x) (x) +# define cpu_to_be16(x) uswap_16(x) +# define cpu_to_be32(x) uswap_32(x) +# define cpu_to_be64(x) uswap_64(x) +# define be16_to_cpu(x) uswap_16(x) +# define be32_to_cpu(x) uswap_32(x) +# define be64_to_cpu(x) uswap_64(x) +#else +# define cpu_to_le16(x) uswap_16(x) +# define cpu_to_le32(x) uswap_32(x) +# define cpu_to_le64(x) uswap_64(x) +# define le16_to_cpu(x) uswap_16(x) +# define le32_to_cpu(x) uswap_32(x) +# define le64_to_cpu(x) uswap_64(x) +# define cpu_to_be16(x) (x) +# define cpu_to_be32(x) (x) +# define cpu_to_be64(x) (x) +# define be16_to_cpu(x) (x) +# define be32_to_cpu(x) (x) +# define be64_to_cpu(x) (x) +#endif + + +typedef union { + struct { + unsigned int time_low; + unsigned short time_mid; + unsigned short time_hi_and_version; + unsigned char clock_seq_hi_and_reserved; + unsigned char clock_seq_low; + unsigned char node[6]; + } uuid; + u8 raw[16]; +} efi_guid_t; +#pragma pack(1) +typedef struct { + u16 usTag;/*0xEEEE*/ + u16 usBackupGpt;/*0:no backup,1:has backup*/ + u16 usEntryCount; + u64 entryDataSize[32]; +} gpt_compact_info; +/* based on linux/include/genhd.h */ +typedef struct { + u8 boot_ind; /* 0x80 - active */ + u8 head; /* starting head */ + u8 sector; /* starting sector */ + u8 cyl; /* starting cylinder */ + u8 sys_ind; /* What partition type */ + u8 end_head; /* end head */ + u8 end_sector; /* end sector */ + u8 end_cyl; /* end cylinder */ + u32 start_sect; /* starting sector counting from 0 */ + u32 nr_sects; /* nr of sectors in partition */ +} mbr_partition ; + +/* based on linux/fs/partitions/efi.h */ +typedef struct _gpt_header { + u64 signature; + u32 revision; + u32 header_size; + u32 header_crc32; + u32 reserved1; + u64 my_lba; + u64 alternate_lba; + u64 first_usable_lba; + u64 last_usable_lba; + efi_guid_t disk_guid; + u64 partition_entry_lba; + u32 num_partition_entries; + u32 sizeof_partition_entry; + u32 partition_entry_array_crc32; +} gpt_header; + +typedef union _gpt_entry_attributes { + struct { + u64 required_to_function:1; + u64 no_block_io_protocol:1; + u64 legacy_bios_bootable:1; + u64 reserved:45; + u64 type_guid_specific:16; + } fields; + unsigned long long raw; +} gpt_entry_attributes; + +#define PARTNAME_SZ 72 +typedef struct _gpt_entry { + efi_guid_t partition_type_guid; + efi_guid_t unique_partition_guid; + u64 starting_lba; + u64 ending_lba; + gpt_entry_attributes attributes; + u16 partition_name[PARTNAME_SZ / sizeof(u16)]; +} gpt_entry; + +typedef struct _legacy_mbr { + u8 boot_code[440]; + u32 unique_mbr_signature; + u16 unknown; + mbr_partition partition_record[4]; + u16 signature; +} legacy_mbr; +#pragma pack() +#endif /* _GPT_H */ diff --git a/main.cpp b/main.cpp index 0b04ef8..733a973 100644 --- a/main.cpp +++ b/main.cpp @@ -7,13 +7,14 @@ #include #include +#include "config.h" #include "DefineHeader.h" +#include "gpt.h" #include "RKLog.h" #include "RKScan.h" #include "RKComm.h" #include "RKDevice.h" #include "RKImage.h" -#include "config.h" extern const char *szManufName[]; CRKLog *g_pLogObject=NULL; CONFIG_ITEM_VECTOR g_ConfigItemVec; @@ -24,14 +25,30 @@ CONFIG_ITEM_VECTOR g_ConfigItemVec; #define CURSOR_CLEAR_SCREEN printf("%c[2J", 0x1B) #define ERROR_COLOR_ATTR printf("%c[30;41m", 0x1B); #define NORMAL_COLOR_ATTR printf("%c[37;40m", 0x1B); +extern UINT CRC_32(unsigned char* pData, UINT ulSize); +extern unsigned short CRC_16(unsigned char* aData, UINT aSize); +extern void P_RC4(unsigned char* buf, unsigned short len); +extern unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len); +/* +u8 test_gpt_head[] = { + 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDE, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x49, 0x94, 0xEC, 0x23, 0xE8, 0x58, 0x4B, + 0xAE, 0xB7, 0xA9, 0x46, 0x51, 0xD0, 0x08, 0xF8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x51, 0xEA, 0xFE, 0x08}; +*/ + void usage() { printf("\r\n---------------------Tool Usage ---------------------\r\n"); printf("Help: -H\r\n"); printf("Version: -V\r\n"); printf("DownloadBoot: DB \r\n"); + printf("UpgradeLoader: UL \r\n"); printf("ReadLBA: RL \r\n"); printf("WriteLBA: WL \r\n"); + printf("WriteGPT: GPT \r\n"); printf("EraseFlash: EF \r\n"); printf("TestDevice: TD\r\n"); printf("ResetDevice: RD [subcode]\r\n"); @@ -220,6 +237,12 @@ bool parse_config(char *pConfig, CONFIG_ITEM_VECTOR &vecItem) if (strLine[line_size-1] == '\r'){ strLine = strLine.substr(0, line_size-1); } + strLine.erase(0, strLine.find_first_not_of(" ")); + strLine.erase(strLine.find_last_not_of(" ") + 1); + if (strLine.size()==0 ) + continue; + if (strLine[0] == '#') + continue; pos = strLine.find("="); if (pos == string::npos){ continue; @@ -274,6 +297,306 @@ bool parse_config_file(const char *pConfigFile, CONFIG_ITEM_VECTOR &vecItem) delete []pConfigBuf; return bRet; } +bool ParsePartitionInfo(string &strPartInfo, string &strName, UINT &uiOffset, UINT &uiLen) +{ + string::size_type pos,prevPos; + string strOffset,strLen; + int iCount; + prevPos = pos = 0; + if (strPartInfo.size() <= 0) { + return false; + } + pos = strPartInfo.find('@'); + if (pos == string::npos) { + return false; + } + strLen = strPartInfo.substr(prevPos, pos - prevPos); + strLen.erase(0, strLen.find_first_not_of(" ")); + strLen.erase(strLen.find_last_not_of(" ") + 1); + if (strchr(strLen.c_str(), '-')) { + uiLen = 0xFFFFFFFF; + } else { + iCount = sscanf(strLen.c_str(), "0x%x", &uiLen); + if (iCount != 1) { + return false; + } + } + + prevPos = pos + 1; + pos = strPartInfo.find('(',prevPos); + if (pos == string::npos) { + return false; + } + strOffset = strPartInfo.substr(prevPos, pos - prevPos); + strOffset.erase(0, strOffset.find_first_not_of(" ")); + strOffset.erase(strOffset.find_last_not_of(" ") + 1); + iCount = sscanf(strOffset.c_str(), "0x%x", &uiOffset); + if (iCount != 1) { + return false; + } + prevPos = pos + 1; + pos = strPartInfo.find(')', prevPos); + if (pos == string::npos) { + return false; + } + strName = strPartInfo.substr(prevPos, pos - prevPos); + strName.erase(0, strName.find_first_not_of(" ")); + strName.erase(strName.find_last_not_of(" ") + 1); + + return true; +} + +bool parse_parameter(char *pParameter, PARAM_ITEM_VECTOR &vecItem) +{ + stringstream paramStream(pParameter); + bool bRet,bFind = false; + string strLine, strPartition, strPartInfo, strPartName; + string::size_type line_size, pos, posColon, posComma; + UINT uiPartOffset, uiPartSize; + STRUCT_PARAM_ITEM item; + vecItem.clear(); + while (!paramStream.eof()) { + getline(paramStream,strLine); + line_size = strLine.size(); + if (line_size == 0) + continue; + if (strLine[line_size - 1] == '\r'){ + strLine = strLine.substr(0, line_size - 1); + } + strLine.erase(0, strLine.find_first_not_of(" ")); + strLine.erase(strLine.find_last_not_of(" ") + 1); + if (strLine.size()==0 ) + continue; + if (strLine[0] == '#') + continue; + pos = strLine.find("mtdparts"); + if (pos == string::npos) { + continue; + } + bFind = true; + posColon = strLine.find(':', pos); + if (posColon == string::npos) { + continue; + } + strPartition = strLine.substr(posColon + 1); + pos = 0; + posComma = strPartition.find(',', pos); + while (posComma != string::npos) { + strPartInfo = strPartition.substr(pos, posComma - pos); + bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize); + if (bRet) { + strcpy(item.szItemName, strPartName.c_str()); + item.uiItemOffset = uiPartOffset; + item.uiItemSize = uiPartSize; + vecItem.push_back(item); + } + pos = posComma + 1; + posComma = strPartition.find(',', pos); + } + strPartInfo = strPartition.substr(pos); + if (strPartInfo.size() > 0) { + bRet = ParsePartitionInfo(strPartInfo, strPartName, uiPartOffset, uiPartSize); + if (bRet) { + strcpy(item.szItemName, strPartName.c_str()); + item.uiItemOffset = uiPartOffset; + item.uiItemSize = uiPartSize; + vecItem.push_back(item); + } + } + break; + } + return bFind; + +} +bool parse_parameter_file(char *pParamFile, PARAM_ITEM_VECTOR &vecItem) +{ + FILE *file = NULL; + file = fopen(pParamFile, "rb"); + if( !file ) { + if (g_pLogObject) + g_pLogObject->Record("parse_parameter_file failed, err=%d, can't open file: %s\r\n", errno, pParamFile); + return false; + } + int iFileSize; + fseek(file, 0, SEEK_END); + iFileSize = ftell(file); + fseek(file, 0, SEEK_SET); + char *pParamBuf = NULL; + pParamBuf = new char[iFileSize]; + if (!pParamBuf) { + fclose(file); + return false; + } + int iRead; + iRead = fread(pParamBuf, 1, iFileSize, file); + if (iRead != iFileSize) { + if (g_pLogObject) + g_pLogObject->Record("parse_parameter_file failed, err=%d, read=%d, total=%d\r\n", errno,iRead,iFileSize); + fclose(file); + delete []pParamBuf; + return false; + } + fclose(file); + bool bRet; + bRet = parse_parameter(pParamBuf, vecItem); + delete []pParamBuf; + return bRet; +} +void gen_rand_uuid(unsigned char *uuid_bin) +{ + efi_guid_t id; + unsigned int *ptr = (unsigned int *)&id; + unsigned int i; + + /* Set all fields randomly */ + for (i = 0; i < sizeof(id) / sizeof(*ptr); i++) + *(ptr + i) = cpu_to_be32(rand()); + + id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000; + id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80; + + memcpy(uuid_bin, id.raw, sizeof(id)); +} + +void create_gpt_buffer(u8 *gpt, PARAM_ITEM_VECTOR &vecParts, u64 diskSectors) +{ + legacy_mbr *mbr = (legacy_mbr *)gpt; + gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE); + gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE); + u32 i,j; + string strPartName; + string::size_type colonPos; + /*1.protective mbr*/ + memset(gpt, 0, SECTOR_SIZE); + mbr->signature = MSDOS_MBR_SIGNATURE; + mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT; + mbr->partition_record[0].start_sect = 1; + mbr->partition_record[0].nr_sects = (u32)-1; + /*2.gpt header*/ + memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE); + gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); + gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1); + gptHead->header_size = cpu_to_le32(sizeof(gpt_header)); + gptHead->my_lba = cpu_to_le64(1); + gptHead->alternate_lba = cpu_to_le64(diskSectors - 1); + gptHead->first_usable_lba = cpu_to_le64(34); + gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34); + gptHead->partition_entry_lba = cpu_to_le64(2); + gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS); + gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE); + gptHead->header_crc32 = 0; + gptHead->partition_entry_array_crc32 = 0; + gen_rand_uuid(gptHead->disk_guid.raw); + + /*3.gpt partition entry*/ + memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE); + for (i = 0; i < vecParts.size(); i++) { + gen_rand_uuid(gptEntry->partition_type_guid.raw); + gen_rand_uuid(gptEntry->unique_partition_guid.raw); + gptEntry->starting_lba = cpu_to_le64(vecParts[i].uiItemOffset); + gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + vecParts[i].uiItemSize - 1); + gptEntry->attributes.raw = 0; + strPartName = vecParts[i].szItemName; + colonPos = strPartName.find_first_of(':'); + if (colonPos != string::npos) { + if (strPartName.find("bootable") != string::npos) + gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE; + strPartName = strPartName.substr(0, colonPos); + vecParts[i].szItemName[strPartName.size()] = 0; + } + for (j = 0; j < strlen(vecParts[i].szItemName); j++) + gptEntry->partition_name[j] = vecParts[i].szItemName[j]; + gptEntry++; + } + + gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS)); + gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header))); + +} +bool MakeSector0(PBYTE pSector, USHORT usFlashDataSec, USHORT usFlashBootSec) +{ + PRK28_IDB_SEC0 pSec0; + memset(pSector, 0, SECTOR_SIZE); + pSec0 = (PRK28_IDB_SEC0)pSector; + + pSec0->dwTag = 0x0FF0AA55; + pSec0->uiRc4Flag = 1; + pSec0->usBootCode1Offset = 0x4; + pSec0->usBootCode2Offset = 0x4; + pSec0->usBootDataSize = usFlashDataSec; + pSec0->usBootCodeSize = usFlashDataSec + usFlashBootSec; + return true; +} + + +bool MakeSector1(PBYTE pSector) +{ + PRK28_IDB_SEC1 pSec1; + memset(pSector, 0, SECTOR_SIZE); + pSec1 = (PRK28_IDB_SEC1)pSector; + + pSec1->usSysReservedBlock = 0xC; + pSec1->usDisk0Size = 0xFFFF; + pSec1->uiChipTag = 0x38324B52; + return true; +} + +bool MakeSector2(PBYTE pSector) +{ + PRK28_IDB_SEC2 pSec2; + memset(pSector, 0, SECTOR_SIZE); + pSec2 = (PRK28_IDB_SEC2)pSector; + + strcpy(pSec2->szVcTag, "VC"); + strcpy(pSec2->szCrcTag, "CRC"); + return true; +} + +bool MakeSector3(PBYTE pSector) +{ + memset(pSector,0,SECTOR_SIZE); + return true; +} + +int MakeIDBlockData(PBYTE pDDR, PBYTE pLoader, PBYTE lpIDBlock, USHORT usFlashDataSec, USHORT usFlashBootSec, DWORD dwLoaderDataSize, DWORD dwLoaderSize) +{ + RK28_IDB_SEC0 sector0Info; + RK28_IDB_SEC1 sector1Info; + RK28_IDB_SEC2 sector2Info; + RK28_IDB_SEC3 sector3Info; + UINT i; + + MakeSector0((PBYTE)§or0Info, usFlashDataSec, usFlashBootSec); + MakeSector1((PBYTE)§or1Info); + if (!MakeSector2((PBYTE)§or2Info)) { + return -6; + } + if (!MakeSector3((PBYTE)§or3Info)) { + return -7; + } + sector2Info.usSec0Crc = CRC_16((PBYTE)§or0Info, SECTOR_SIZE); + sector2Info.usSec1Crc = CRC_16((PBYTE)§or1Info, SECTOR_SIZE); + sector2Info.usSec3Crc = CRC_16((PBYTE)§or3Info, SECTOR_SIZE); + + memcpy(lpIDBlock, §or0Info, SECTOR_SIZE); + memcpy(lpIDBlock + SECTOR_SIZE, §or1Info, SECTOR_SIZE); + memcpy(lpIDBlock + SECTOR_SIZE * 3, §or3Info, SECTOR_SIZE); + memcpy(lpIDBlock + SECTOR_SIZE * 4, pDDR, dwLoaderDataSize); + memcpy(lpIDBlock + SECTOR_SIZE * (4 + usFlashDataSec), pLoader, dwLoaderSize); + + sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE); + memcpy(lpIDBlock + SECTOR_SIZE * 2, §or2Info, SECTOR_SIZE); + for(i = 0; i < 4; i++) { + if(i == 1) { + continue; + } else { + P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE); + } + } + return 0; +} + + bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType) { @@ -288,6 +611,73 @@ bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType) return false; } } +bool write_gpt(STRUCT_RKDEVICE_DESC &dev, char *szParameter) +{ + u8 flash_info[SECTOR_SIZE], master_gpt[34 * SECTOR_SIZE], backup_gpt[33 * SECTOR_SIZE]; + u32 total_size_sector; + CRKComm *pComm = NULL; + PARAM_ITEM_VECTOR vecItems; + int iRet; + bool bRet, bSuccess = false; + if (!check_device_type(dev, RKUSB_MASKROM)) + return false; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (!bRet) { + ERROR_COLOR_ATTR; + printf("Creating Comm Object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + printf("Write gpt...\r\n"); + //1.get flash info + iRet = pComm->RKU_ReadFlashInfo(flash_info); + if (iRet != ERR_SUCCESS) { + ERROR_COLOR_ATTR; + printf("Reading Flash Info failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + total_size_sector = *(u32 *)flash_info; + //2.get partition from parameter + bRet = parse_parameter_file(szParameter, vecItems); + if (!bRet) { + ERROR_COLOR_ATTR; + printf("Parsing parameter failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + vecItems[vecItems.size()-1].uiItemSize = total_size_sector - 34; + //3.generate gpt info + create_gpt_buffer(master_gpt, vecItems, total_size_sector); + memcpy(backup_gpt, master_gpt + 2* SECTOR_SIZE, 32 * SECTOR_SIZE); + memcpy(backup_gpt + 32 * SECTOR_SIZE, master_gpt + SECTOR_SIZE, SECTOR_SIZE); + //4. write gpt + iRet = pComm->RKU_WriteLBA(0, 34, master_gpt); + if (iRet != ERR_SUCCESS) { + ERROR_COLOR_ATTR; + printf("Writing master gpt failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + iRet = pComm->RKU_WriteLBA(total_size_sector - 34, 33, backup_gpt); + if (iRet != ERR_SUCCESS) { + ERROR_COLOR_ATTR; + printf("Writing backup gpt failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + bSuccess = true; + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + printf("Write gpt ok.\r\n"); + return bSuccess; +} bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader) { @@ -363,6 +753,139 @@ bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader) } return bSuccess; } +bool upgrade_loader(STRUCT_RKDEVICE_DESC &dev, char *szLoader) +{ + if (!check_device_type(dev, RKUSB_MASKROM)) + return false; + CRKImage *pImage = NULL; + CRKBoot *pBoot = NULL; + CRKComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + char index; + USHORT usFlashDataSec, usFlashBootSec; + DWORD dwLoaderSize, dwLoaderDataSize, dwDelay, dwSectorNum; + char loaderCodeName[] = "FlashBoot"; + char loaderDataName[] = "FlashData"; + PBYTE loaderCodeBuffer = NULL; + PBYTE loaderDataBuffer = NULL; + PBYTE pIDBData = NULL; + pImage = new CRKImage(szLoader, bRet); + if (!bRet){ + ERROR_COLOR_ATTR; + printf("Open loader failed,exit upgrade loader!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + goto Exit_UpgradeLoader; + } else { + pBoot = (CRKBoot *)pImage->m_bootObject; + dev.emDeviceType = pBoot->SupportDevice; + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (!bRet) { + ERROR_COLOR_ATTR; + printf("Creating Comm Object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + goto Exit_UpgradeLoader; + } + + printf("Upgrade loader...\r\n"); + index = pBoot->GetIndexByName(ENTRYLOADER, loaderCodeName); + if (index == -1) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry failed"); + } + goto Exit_UpgradeLoader; + } + bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderSize, dwDelay); + if (!bRet) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Entry Size failed"); + } + goto Exit_UpgradeLoader; + } + + loaderCodeBuffer = new BYTE[dwLoaderSize]; + memset(loaderCodeBuffer, 0, dwLoaderSize); + if (!pBoot->GetEntryData(ENTRYLOADER, index, loaderCodeBuffer)) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderCode Data failed"); + } + goto Exit_UpgradeLoader; + } + + index = pBoot->GetIndexByName(ENTRYLOADER, loaderDataName); + if (index == -1) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry failed"); + } + delete []loaderCodeBuffer; + return -4; + } + + bRet = pBoot->GetEntryProperty(ENTRYLOADER, index, dwLoaderDataSize, dwDelay); + if (!bRet) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Entry Size failed"); + } + goto Exit_UpgradeLoader; + } + + loaderDataBuffer = new BYTE[dwLoaderDataSize]; + memset(loaderDataBuffer, 0, dwLoaderDataSize); + if (!pBoot->GetEntryData(ENTRYLOADER,index,loaderDataBuffer)) { + if (g_pLogObject) { + g_pLogObject->Record("ERROR:upgrade_loader-->Get LoaderData Data failed"); + } + goto Exit_UpgradeLoader; + } + + usFlashDataSec = (ALIGN(dwLoaderDataSize, 2048)) / SECTOR_SIZE; + usFlashBootSec = (ALIGN(dwLoaderSize, 2048)) / SECTOR_SIZE; + dwSectorNum = 4 + usFlashDataSec + usFlashBootSec; + pIDBData = new BYTE[dwSectorNum*SECTOR_SIZE]; + if (!pIDBData) { + ERROR_COLOR_ATTR; + printf("New memory failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + goto Exit_UpgradeLoader; + } + memset(pIDBData, 0, dwSectorNum * SECTOR_SIZE); + iRet = MakeIDBlockData(loaderDataBuffer, loaderCodeBuffer, pIDBData, usFlashDataSec, usFlashBootSec, dwLoaderDataSize, dwLoaderSize); + if (iRet != 0) { + ERROR_COLOR_ATTR; + printf("Make idblock failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + goto Exit_UpgradeLoader; + } + iRet = pComm->RKU_WriteLBA(64, dwSectorNum, pIDBData); + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + if (iRet == ERR_SUCCESS) { + pComm->Reset_Usb_Device(); + bSuccess = true; + printf("Upgrade loader ok.\r\n"); + } else { + printf("Upgrade loader failed!\r\n"); + goto Exit_UpgradeLoader; + } + } +Exit_UpgradeLoader: + if (pImage) + delete pImage; + if (pComm) + delete pComm; + if (loaderCodeBuffer) + delete []loaderCodeBuffer; + if (loaderDataBuffer) + delete []loaderDataBuffer; + if (pIDBData) + delete []pIDBData; + return bSuccess; +} + bool erase_flash(STRUCT_RKDEVICE_DESC &dev) { if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) @@ -745,6 +1268,7 @@ void split_item(STRING_VECTOR &vecItems, char *pszItems) vecItems.push_back(strItem); } } + bool handle_command(int argc, char* argv[], CRKScan *pScan) { string strCmd; @@ -759,7 +1283,7 @@ bool handle_command(int argc, char* argv[], CRKScan *pScan) usage(); return true; } else if(strcmp(strCmd.c_str(), "-V") == 0) { - printf("rkDevelopTool ver %s\r\n", PACKAGE_VERSION); + printf("rkdeveloptool ver %s\r\n", PACKAGE_VERSION); return true; } cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER); @@ -827,6 +1351,20 @@ bool handle_command(int argc, char* argv[], CRKScan *pScan) bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue); } else printf("Parameter of [DB] command is invalid,please check help!\r\n"); + } else if(strcmp(strCmd.c_str(), "GPT") == 0) { + if (argc > 2) { + string strParameter; + strParameter = argv[2]; + bSuccess = write_gpt(dev, (char *)strParameter.c_str()); + } else + printf("Parameter of [GPT] command is invalid,please check help!\r\n"); + } else if(strcmp(strCmd.c_str(), "UL") == 0) { + if (argc > 2) { + string strLoader; + strLoader = argv[2]; + bSuccess = upgrade_loader(dev, (char *)strLoader.c_str()); + } else + printf("Parameter of [UL] command is invalid,please check help!\r\n"); } else if(strcmp(strCmd.c_str(), "EF") == 0) { if (argc == 2) { bSuccess = erase_flash(dev); @@ -862,13 +1400,12 @@ bool handle_command(int argc, char* argv[], CRKScan *pScan) } } } else { - printf("command is invalid,please press upgrade_tool -h to check usage!\r\n"); + printf("command is invalid,please press rkDevelopTool -h to check usage!\r\n"); } return bSuccess; } - int main(int argc, char* argv[]) { CRKScan *pScan = NULL;