main: update to version 1.2

- add gpt command to write gpt table
- add ul command, need run db first

Signed-off-by: Liu Yi <liuyi@rock-chips.com>
Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
Tested-by: Kever Yang <kever.yang@rock-chips.com>
This commit is contained in:
Kever Yang 2017-04-11 18:06:10 +08:00
parent 7a9a9fd691
commit c30d921c26
6 changed files with 926 additions and 11 deletions

View File

@ -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<STRUCT_RKDEVICE_DESC> RKDEVICE_DESC_SET;
typedef RKDEVICE_DESC_SET::iterator device_list_iter;
typedef vector<string> STRING_VECTOR;
typedef vector<UINT> UINT_VECTOR;
typedef vector<STRUCT_CONFIG_ITEM> CONFIG_ITEM_VECTOR;
typedef vector<STRUCT_PARAM_ITEM> PARAM_ITEM_VECTOR;
typedef enum{
TESTDEVICE_PROGRESS,
DOWNLOADIMAGE_PROGRESS,

View File

@ -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::

View File

@ -1,6 +1,6 @@
dnl Copyright (C) 2017 Trevor Woerner <twoerner@gmail.com>
AC_INIT([Rockchip rkdeveloptool], 1.0, [Eddie Cai <eddie.cai.linux@gmail.com>], rkdeveloptool)
AC_INIT([Rockchip rkdeveloptool], 1.2, [Eddie Cai <eddie.cai.linux@gmail.com>], rkdeveloptool)
AC_PREREQ([2.68])
AC_CONFIG_SRCDIR(main.cpp)
AC_CONFIG_AUX_DIR(cfg)

123
crc.cpp
View File

@ -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,6 +163,7 @@ UINT ggx1=0;
UINT ggx2=0;
UINT ggx3=0;
UINT ggx4=0;
// get crc32 value
UINT CRC_32(unsigned char* pData, UINT ulSize)
{
@ -103,6 +174,56 @@ UINT CRC_32(unsigned char* pData, UINT ulSize)
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)
{

163
gpt.h Normal file
View File

@ -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 */

545
main.cpp
View File

@ -7,13 +7,14 @@
#include <unistd.h>
#include <dirent.h>
#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 <Loader>\r\n");
printf("UpgradeLoader: UL <Loader>\r\n");
printf("ReadLBA: RL <BeginSec> <SectorLen> <File>\r\n");
printf("WriteLBA: WL <BeginSec> <File>\r\n");
printf("WriteGPT: GPT <parameter>\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)&sector0Info, usFlashDataSec, usFlashBootSec);
MakeSector1((PBYTE)&sector1Info);
if (!MakeSector2((PBYTE)&sector2Info)) {
return -6;
}
if (!MakeSector3((PBYTE)&sector3Info)) {
return -7;
}
sector2Info.usSec0Crc = CRC_16((PBYTE)&sector0Info, SECTOR_SIZE);
sector2Info.usSec1Crc = CRC_16((PBYTE)&sector1Info, SECTOR_SIZE);
sector2Info.usSec3Crc = CRC_16((PBYTE)&sector3Info, SECTOR_SIZE);
memcpy(lpIDBlock, &sector0Info, SECTOR_SIZE);
memcpy(lpIDBlock + SECTOR_SIZE, &sector1Info, SECTOR_SIZE);
memcpy(lpIDBlock + SECTOR_SIZE * 3, &sector3Info, 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, &sector2Info, 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;