mirror of
https://github.com/sharkcz/rkdeveloptool.git
synced 2024-11-22 14:06:47 +01:00
1.add "wlx" command support flash image by name
2.flash sparse image by wlx command Signed-off-by: liuyi <liuyi@rock-chips.com>
This commit is contained in:
parent
c29e5f0fb3
commit
6ae612bebc
@ -74,6 +74,31 @@ typedef enum{
|
||||
} ENUM_RKBOOTENTRY;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct sparse_header_t {
|
||||
UINT magic; /* 0xed26ff3a */
|
||||
USHORT major_version; /* (0x1) - reject images with higher major versions */
|
||||
USHORT minor_version; /* (0x0) - allow images with higer minor versions */
|
||||
USHORT file_hdr_sz; /* 28 bytes for first revision of the file format */
|
||||
USHORT chunk_hdr_sz; /* 12 bytes for first revision of the file format */
|
||||
UINT blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
|
||||
UINT total_blks; /* total blocks in the non-sparse output image */
|
||||
UINT total_chunks; /* total chunks in the sparse input image */
|
||||
UINT 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;
|
||||
#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_t {
|
||||
USHORT chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
|
||||
USHORT reserved1;
|
||||
UINT chunk_sz; /* in blocks in output image */
|
||||
UINT total_sz; /* in bytes of chunk input file including chunk header and data */
|
||||
} chunk_header;
|
||||
|
||||
typedef struct{
|
||||
USHORT usYear;
|
||||
BYTE ucMonth;
|
||||
@ -207,4 +232,4 @@ typedef void (*ProgressPromptCB)(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptI
|
||||
|
||||
bool WideStringToString(wchar_t *pszSrc, char *&pszDest);
|
||||
bool StringToWideString(char *pszSrc, wchar_t *&pszDest);
|
||||
#endif
|
||||
#endif
|
||||
|
332
main.cpp
332
main.cpp
@ -48,6 +48,7 @@ void usage()
|
||||
printf("UpgradeLoader:\t\tul <Loader>\r\n");
|
||||
printf("ReadLBA:\t\trl <BeginSec> <SectorLen> <File>\r\n");
|
||||
printf("WriteLBA:\t\twl <BeginSec> <File>\r\n");
|
||||
printf("WriteLBA:\t\twlx <PartitionName> <File>\r\n");
|
||||
printf("WriteGPT:\t\tgpt <gpt partition table>\r\n");
|
||||
printf("EraseFlash:\t\tef \r\n");
|
||||
printf("TestDevice:\t\ttd\r\n");
|
||||
@ -517,6 +518,32 @@ bool parse_parameter_file(char *pParamFile, PARAM_ITEM_VECTOR &vecItem, CONFIG_I
|
||||
delete []pParamBuf;
|
||||
return bRet;
|
||||
}
|
||||
bool is_sparse_image(char *szImage)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
sparse_header head;
|
||||
u32 uiRead;
|
||||
file = fopen(szImage, "rb");
|
||||
if( !file ) {
|
||||
if (g_pLogObject)
|
||||
g_pLogObject->Record("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, szImage);
|
||||
return false;
|
||||
}
|
||||
uiRead = fread(&head, 1, sizeof(head), file);
|
||||
if (uiRead != sizeof(head)) {
|
||||
if (g_pLogObject)
|
||||
g_pLogObject->Record("%s failed, err=%d, read=%d, total=%d\r\n", __func__, errno, uiRead, sizeof(head));
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
fclose(file);
|
||||
if (head.magic!=SPARSE_HEADER_MAGIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
void gen_rand_uuid(unsigned char *uuid_bin)
|
||||
{
|
||||
efi_guid_t id;
|
||||
@ -550,6 +577,36 @@ void prepare_gpt_backup(u8 *master, u8 *backup)
|
||||
calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size));
|
||||
gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32);
|
||||
}
|
||||
bool get_lba_from_gpt(u8 *master, char *pszName, u64 *lba, u64 *lba_end)
|
||||
{
|
||||
gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
|
||||
gpt_entry *gptEntry = NULL;
|
||||
u32 i,j;
|
||||
u8 zerobuf[GPT_ENTRY_SIZE];
|
||||
bool bFound = false;
|
||||
memset(zerobuf,0,GPT_ENTRY_SIZE);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(gptMasterHead->num_partition_entries); i++) {
|
||||
gptEntry = (gpt_entry *)(master + 2 * SECTOR_SIZE + i * GPT_ENTRY_SIZE);
|
||||
if (memcmp(zerobuf, (u8 *)gptEntry, GPT_ENTRY_SIZE) == 0)
|
||||
break;
|
||||
for (j = 0; j < strlen(pszName); j++)
|
||||
if (gptEntry->partition_name[j] != pszName[j])
|
||||
break;
|
||||
if (gptEntry->partition_name[j] != 0)
|
||||
continue;
|
||||
if (j == strlen(pszName)) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bFound) {
|
||||
*lba = le64_to_cpu(gptEntry->starting_lba);
|
||||
*lba_end = le64_to_cpu(gptEntry->ending_lba);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void update_gpt_disksize(u8 *master, u8 *backup, u32 total_sector)
|
||||
{
|
||||
gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
|
||||
@ -2051,6 +2108,40 @@ bool read_chip_info(STRUCT_RKDEVICE_DESC &dev)
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
bool read_gpt(STRUCT_RKDEVICE_DESC &dev, u8 *pGpt)
|
||||
{
|
||||
if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
|
||||
return false;
|
||||
gpt_header *gptHead = (gpt_header *)(pGpt + SECTOR_SIZE);
|
||||
CRKUsbComm *pComm = NULL;
|
||||
bool bRet, bSuccess = false;
|
||||
int iRet;
|
||||
pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
|
||||
if (bRet) {
|
||||
iRet = pComm->RKU_ReadLBA( 0, 34, pGpt);
|
||||
if(ERR_SUCCESS == iRet) {
|
||||
if (gptHead->signature != le64_to_cpu(GPT_HEADER_SIGNATURE)) {
|
||||
if (g_pLogObject)
|
||||
g_pLogObject->Record("Error: invalid gpt signature");
|
||||
printf("Invalid GPT signature!\r\n");
|
||||
goto Exit_ReadGPT;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (g_pLogObject)
|
||||
g_pLogObject->Record("Error: read gpt failed, err=%d", iRet);
|
||||
printf("Read GPT failed!\r\n");
|
||||
goto Exit_ReadGPT;
|
||||
}
|
||||
bSuccess = true;
|
||||
}
|
||||
Exit_ReadGPT:
|
||||
if (pComm) {
|
||||
delete pComm;
|
||||
pComm = NULL;
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile)
|
||||
{
|
||||
if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
|
||||
@ -2120,6 +2211,230 @@ Exit_ReadLBA:
|
||||
fclose(file);
|
||||
return bSuccess;
|
||||
}
|
||||
bool erase_partition(CRKUsbComm *pComm, UINT uiOffset, UINT uiSize)
|
||||
{
|
||||
UINT uiErase=2048*64;
|
||||
bool bSuccess = true;
|
||||
int iRet;
|
||||
while (uiSize)
|
||||
{
|
||||
if (uiSize>=uiErase)
|
||||
{
|
||||
iRet = pComm->RKU_EraseLBA(uiOffset,uiErase);
|
||||
uiSize -= uiErase;
|
||||
uiOffset += uiErase;
|
||||
}
|
||||
else
|
||||
{
|
||||
iRet = pComm->RKU_EraseLBA(uiOffset,uiSize);
|
||||
uiSize = 0;
|
||||
uiOffset += uiSize;
|
||||
}
|
||||
if (iRet!=ERR_SUCCESS)
|
||||
{
|
||||
if (g_pLogObject)
|
||||
{
|
||||
g_pLogObject->Record("ERROR:erase_partition failed,err=%d",iRet);
|
||||
}
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bSuccess;
|
||||
|
||||
}
|
||||
bool EatSparseChunk(FILE *file, chunk_header &chunk)
|
||||
{
|
||||
UINT uiRead;
|
||||
uiRead = fread(&chunk, 1, sizeof(chunk_header), file);
|
||||
if (uiRead != sizeof(chunk_header)) {
|
||||
if (g_pLogObject)
|
||||
{
|
||||
g_pLogObject->Record("Error:EatSparseChunk failed,err=%d", errno);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool EatSparseData(FILE *file, PBYTE pBuf, DWORD dwSize)
|
||||
{
|
||||
UINT uiRead;
|
||||
uiRead = fread(pBuf, 1, dwSize, file);
|
||||
if (uiRead!=dwSize)
|
||||
{
|
||||
if (g_pLogObject)
|
||||
{
|
||||
g_pLogObject->Record("Error:EatSparseData failed,err=%d",errno);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_sparse_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiSize, char *szFile)
|
||||
{
|
||||
if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
|
||||
return false;
|
||||
CRKUsbComm *pComm = NULL;
|
||||
FILE *file = NULL;
|
||||
bool bRet, bSuccess = false, bFirst = true;
|
||||
int iRet;
|
||||
u64 iTotalWrite = 0, iFileSize = 0;
|
||||
UINT iRead = 0, uiTransferSec, curChunk, i;
|
||||
UINT dwChunkDataSize, dwMaxReadWriteBytes, dwTransferBytes, dwFillByte, dwCrc;
|
||||
BYTE pBuf[SECTOR_SIZE * DEFAULT_RW_LBA];
|
||||
sparse_header header;
|
||||
chunk_header chunk;
|
||||
dwMaxReadWriteBytes = DEFAULT_RW_LBA * SECTOR_SIZE;
|
||||
pComm = new CRKUsbComm(dev, g_pLogObject, bRet);
|
||||
if (bRet) {
|
||||
bRet = erase_partition(pComm, uiBegin, uiSize);
|
||||
if (!bRet) {
|
||||
printf("%s failed, erase partition error\r\n", __func__);
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
file = fopen(szFile, "rb");
|
||||
if( !file ) {
|
||||
printf("%s failed, err=%d, can't open file: %s\r\n", __func__, errno, szFile);
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
fseeko(file, 0, SEEK_SET);
|
||||
iRead = fread(&header, 1, sizeof(header), file);
|
||||
if (iRead != sizeof(sparse_header))
|
||||
{
|
||||
if (g_pLogObject)
|
||||
{
|
||||
g_pLogObject->Record("ERROR:%s-->read sparse header failed,file=%s,err=%d", __func__, szFile, errno);
|
||||
}
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
iFileSize = header.blk_sz * (u64)header.total_blks;
|
||||
iTotalWrite = 0;
|
||||
curChunk = 0;
|
||||
|
||||
while(curChunk < header.total_chunks)
|
||||
{
|
||||
if (!EatSparseChunk(file, chunk)) {
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
curChunk++;
|
||||
switch (chunk.chunk_type) {
|
||||
case CHUNK_TYPE_RAW:
|
||||
dwChunkDataSize = chunk.total_sz - sizeof(chunk_header);
|
||||
while (dwChunkDataSize) {
|
||||
memset(pBuf, 0, dwMaxReadWriteBytes);
|
||||
if (dwChunkDataSize >= dwMaxReadWriteBytes) {
|
||||
dwTransferBytes = dwMaxReadWriteBytes;
|
||||
uiTransferSec = DEFAULT_RW_LBA;
|
||||
} else {
|
||||
dwTransferBytes = dwChunkDataSize;
|
||||
uiTransferSec = ((dwTransferBytes % SECTOR_SIZE == 0) ? (dwTransferBytes / SECTOR_SIZE) : (dwTransferBytes / SECTOR_SIZE + 1));
|
||||
}
|
||||
if (!EatSparseData(file, pBuf, dwTransferBytes)) {
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
iRet = pComm->RKU_WriteLBA(uiBegin, uiTransferSec, pBuf);
|
||||
if( ERR_SUCCESS == iRet ) {
|
||||
dwChunkDataSize -= dwTransferBytes;
|
||||
iTotalWrite += dwTransferBytes;
|
||||
uiBegin += uiTransferSec;
|
||||
} else {
|
||||
if (g_pLogObject) {
|
||||
g_pLogObject->Record("ERROR:%s-->RKU_WriteLBA failed,Written(%d),RetCode(%d)", __func__, iTotalWrite, iRet);
|
||||
}
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
if (bFirst) {
|
||||
if (iTotalWrite >= 1024)
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
else
|
||||
printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
|
||||
bFirst = false;
|
||||
} else {
|
||||
CURSOR_MOVEUP_LINE(1);
|
||||
CURSOR_DEL_LINE;
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHUNK_TYPE_FILL:
|
||||
dwChunkDataSize = chunk.chunk_sz * header.blk_sz;
|
||||
if (!EatSparseData(file, (PBYTE)&dwFillByte, 4)) {
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
while (dwChunkDataSize) {
|
||||
memset(pBuf, 0, dwMaxReadWriteBytes);
|
||||
if (dwChunkDataSize >= dwMaxReadWriteBytes) {
|
||||
dwTransferBytes = dwMaxReadWriteBytes;
|
||||
uiTransferSec = DEFAULT_RW_LBA;
|
||||
} else {
|
||||
dwTransferBytes = dwChunkDataSize;
|
||||
uiTransferSec = ((dwTransferBytes % SECTOR_SIZE == 0) ? (dwTransferBytes / SECTOR_SIZE) : (dwTransferBytes / SECTOR_SIZE + 1));
|
||||
}
|
||||
for (i = 0; i < dwTransferBytes / 4; i++) {
|
||||
*(DWORD *)(pBuf + i * 4) = dwFillByte;
|
||||
}
|
||||
iRet = pComm->RKU_WriteLBA(uiBegin, uiTransferSec, pBuf);
|
||||
if( ERR_SUCCESS == iRet ) {
|
||||
dwChunkDataSize -= dwTransferBytes;
|
||||
iTotalWrite += dwTransferBytes;
|
||||
uiBegin += uiTransferSec;
|
||||
} else {
|
||||
if (g_pLogObject) {
|
||||
g_pLogObject->Record("ERROR:%s-->RKU_WriteLBA failed,Written(%d),RetCode(%d)" ,__func__, iTotalWrite, iRet);
|
||||
}
|
||||
goto Exit_WriteSparseLBA;
|
||||
}
|
||||
if (bFirst) {
|
||||
if (iTotalWrite >= 1024)
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
else
|
||||
printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
|
||||
bFirst = false;
|
||||
} else {
|
||||
CURSOR_MOVEUP_LINE(1);
|
||||
CURSOR_DEL_LINE;
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHUNK_TYPE_DONT_CARE:
|
||||
dwChunkDataSize = chunk.chunk_sz * header.blk_sz;
|
||||
iTotalWrite += dwChunkDataSize;
|
||||
uiTransferSec = ((dwChunkDataSize % SECTOR_SIZE == 0) ? (dwChunkDataSize / SECTOR_SIZE) : (dwChunkDataSize / SECTOR_SIZE + 1));
|
||||
uiBegin += uiTransferSec;
|
||||
if (bFirst) {
|
||||
if (iTotalWrite >= 1024)
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
else
|
||||
printf("Write LBA from file (%lld%%)\r\n", iTotalWrite * 100 / iFileSize);
|
||||
bFirst = false;
|
||||
} else {
|
||||
CURSOR_MOVEUP_LINE(1);
|
||||
CURSOR_DEL_LINE;
|
||||
printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024));
|
||||
}
|
||||
break;
|
||||
case CHUNK_TYPE_CRC32:
|
||||
EatSparseData(file,(PBYTE)&dwCrc,4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bSuccess = true;
|
||||
} else {
|
||||
printf("Write LBA quit, creating comm object failed!\r\n");
|
||||
}
|
||||
Exit_WriteSparseLBA:
|
||||
if (pComm) {
|
||||
delete pComm;
|
||||
pComm = NULL;
|
||||
}
|
||||
if (file)
|
||||
fclose(file);
|
||||
return bSuccess;
|
||||
|
||||
}
|
||||
|
||||
bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile)
|
||||
{
|
||||
if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM))
|
||||
@ -2275,6 +2590,8 @@ bool handle_command(int argc, char* argv[], CRKScan *pScan)
|
||||
char *s;
|
||||
int i, ret;
|
||||
STRUCT_RKDEVICE_DESC dev;
|
||||
u8 master_gpt[34 * SECTOR_SIZE];
|
||||
u64 lba, lba_end;
|
||||
|
||||
transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper);
|
||||
s = (char*)strCmd.c_str();
|
||||
@ -2402,6 +2719,21 @@ bool handle_command(int argc, char* argv[], CRKScan *pScan)
|
||||
bSuccess = write_lba(dev, uiBegin, argv[3]);
|
||||
} else
|
||||
printf("Parameter of [WL] command is invalid, please check help!\r\n");
|
||||
} else if(strcmp(strCmd.c_str(), "WLX") == 0) {
|
||||
if (argc == 4) {
|
||||
bRet = read_gpt(dev, master_gpt);
|
||||
if (bRet) {
|
||||
bRet = get_lba_from_gpt(master_gpt, argv[2], &lba, &lba_end);
|
||||
if (bRet) {
|
||||
if (is_sparse_image(argv[3]))
|
||||
bSuccess = write_sparse_lba(dev, (u32)lba, (u32)(lba_end - lba + 1), argv[3]);
|
||||
else
|
||||
bSuccess = write_lba(dev, (u32)lba, argv[3]);
|
||||
} else
|
||||
printf("No found %s partition\r\n", argv[2]);
|
||||
}
|
||||
} else
|
||||
printf("Parameter of [WLX] command is invalid, please check help!\r\n");
|
||||
} else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA
|
||||
char *pszEnd;
|
||||
UINT uiBegin, uiLen;
|
||||
|
Loading…
Reference in New Issue
Block a user