?? 復件 update.c
字號:
/**
* RETR reply after transfer should be "226"
*/
if (FtpRecvReply(ctrl_fd) < 0 || ftp_reply[0] != '2')
{
fprintf(stderr, "error while transfer\n");
/* 釋放內存 */
ClearUpdateBlock(update_block.next);
return UPDATE_CONN_ERROR;
}
else
{
#ifdef __UPDATE_DEBUG__
printf("%.3s: transfer completed\n", ftp_reply);
printf("file %s %d bytes got\n", filename, count);
#endif
}
close(data_fd);
FtpQuitServer(ctrl_fd);
close(ctrl_fd);
printf("now begin to update flashRom!\n");
/* 寫入Flash */
result = UpdateFlashRom(update_block.next, count, fileType);
ClearUpdateBlock(update_block.next);
#ifdef __UPDATE_DEBUG__
if (result == UPDATE_OK)
{
printf("Update OK.\n");
}
#endif
return result;
}
static int FtpQuitServer(int ctrl_fd)
{
/**
* Command QUIT
*/
if (FtpCommand(ctrl_fd, ftp_quit_cmd, NULL) < 0)
{
fprintf(stderr, "QUIT error\n");
return UPDATE_CONN_ERROR;
}
/**
* QUIT reply should be "221"
*/
if (FtpRecvReply(ctrl_fd) < 0 || ftp_reply[0] != '2')
{
fprintf(stderr, "error recv QUIT\n");
return UPDATE_CONN_ERROR;
}
else
{
#ifdef __UPDATE_DEBUG__
printf("%.3s: quit from server\n", ftp_reply);
#endif
}
return UPDATE_OK;
}
static int FtpCommand(int sockfd, char * cmd, const char * param)
{
int len;
memset(ftp_request, 0, FTP_REQ_LENGTH);
len = sprintf(ftp_request, "%s %s\r\n", cmd, (param == NULL)? "" : param);
#ifdef __FTP_DEBUG
printf("%s %s\r\n", cmd, (param == NULL)? "" : param);
#endif
return send(sockfd, ftp_request, len, 0);
}
static int FtpRecvReply(int sockfd)
{
int ret;
fd_set rset;
struct timeval tv;
int len = -1;
char data = 0;
if ((len = recv(sockfd, ftp_reply, 3, 0)) <= 0)
{
memset(ftp_reply, 0, sizeof(ftp_reply));
return -1;
}
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tv.tv_sec = 0.5;
tv.tv_usec = 0;
while (data != '\n')
{
if ((len = recv(sockfd, &data, 1, 0)) <= 0)
{
memset(ftp_reply, 0, sizeof(ftp_reply));
return -1;
}
}
#if 0
while ((len = recv(sockfd, &data, 1, 0)) > 0)
{
/*memset(ftp_reply, 0, sizeof(ftp_reply));
return -1;*/
}
#endif
#if 0
while(ret = select(sockfd + 1, &rset, NULL, NULL, &tv)>0)
len = recv(sockfd,&data,1,0);
if (len == -1)
memset(ftp_reply, 0, sizeof(ftp_reply));
#endif
return len;
}
/*************************************************************************************
* Part TFTP_Update
*************************************************************************************/
static int TftpUpdate()
{
int sockfd, ret;
#ifdef __UPDATE_DEBUG__
printf("Begin tftp update...\n");
#endif
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
perror("tftp socket");
return UPDATE_CONN_ERROR;
}
memset(&tftp_server_addr, 0, addr_len);
tftp_server_addr.sin_len = addr_len;
tftp_server_addr.sin_family = AF_INET;
tftp_server_addr.sin_port = htons(TFTP_SERVER_PORT);
tftp_server_addr.sin_addr.s_addr = htonl(phoneconfig.conf_ftp.server);
tftp_tid = 0;
tftp_index = 1;
if (TftpSendRRQ(sockfd, phoneconfig.conf_ftp.filename) < 0)
{
perror("send RRQ");
close(sockfd);
return UPDATE_CONN_ERROR;
}
ret = TftpGetUpdate(sockfd);
close(sockfd);
return ret;
}
/*******************************************************
* 向服務器發送RRQ請求
* RRQ的報文格式
*
* 2 string 1 string 1
* -----------------------------------------------
* RRQ | 01 | Filename | 0 | Mode | 0 |
* -----------------------------------------------
*
*******************************************************/
static int TftpSendRRQ(int sockfd, char * filename)
{
int offset = 0;
memset(tftp_lastdata.data, 0, TFTP_TMP_LENGTH);
tftp_lastdata.data[1] = TFTP_OP_RRQ;
offset += 2;
offset += sprintf(& tftp_lastdata.data[offset], "%s", filename);
offset++;
offset += sprintf(& tftp_lastdata.data[offset], "%s", tftp_filemode);
offset++;
tftp_lastdata.length = offset;
#ifdef __UPDATE_DEBUG__
printf("send RRQ...get file %s\n", filename);
#endif
return sendto(sockfd, (void *) tftp_lastdata.data, offset, 0, (struct sockaddr *) &tftp_server_addr, addr_len);
}
/*******************************************************
* 向服務器發送ACK
* ACK的報文格式
*
* 2 2 bytes
* -------------------
* ACK | 04 | Block # |
* --------------------
*
*******************************************************/
static int TftpSendAck(int sockfd, unsigned short index)
{
tftp_lastdata.data[0] = 0;
tftp_lastdata.data[1] = TFTP_OP_ACK;
memcpy(&tftp_lastdata.data[2], &index, 2);
tftp_lastdata.length = 4;
return sendto(sockfd, (void *) tftp_lastdata.data, 4, 0, (struct sockaddr *) &tftp_server_addr, addr_len);
}
static int TftpGetResponse(int sockfd, int * p_len)
{
int len, flen;
int retry = 3;
flen = addr_len;
while (retry > 0)
{
#ifdef __UPDATE_DEBUG__
printf("server port %u\n", tftp_tid);
#endif
if (readable_timeo(sockfd, TFTP_TIMEOUT) <= 0)
{
if (--retry <= 0)
{
fprintf(stderr, "No answer from TFTP server after 3 try, Quit.\n");
return UPDATE_CONN_ERROR;
}
/**
* 重新發送上次的報文
*/
#ifdef __UPDATE_DEBUG__
printf("ReSend last data\n", retry);
#endif
if (sendto(sockfd, (void *) tftp_lastdata.data, tftp_lastdata.length, 0,
(struct sockaddr *) &tftp_server_addr, addr_len) < 0)
{
perror("ReSend last data while timeout");
return UPDATE_CONN_ERROR;
}
continue;
}
/**
* 收到服務器端的應答
*/
if ((len = recvfrom(sockfd, (void *) &tftp_fileblock, sizeof(s_tftp_data), 0,
(struct sockaddr *) &tftp_server_addr, &flen)) < 0)
{
perror("recv DATA");
return UPDATE_CONN_ERROR;
}
/**
* 收到其他端口發送的報文 丟棄該報文
*/
if (tftp_tid != 0 && tftp_tid != ntohs(tftp_server_addr.sin_port))
{
tftp_server_addr.sin_port = htons(tftp_tid);
fprintf(stderr, "Got packet from other TID!\n");
continue;
}
/**
* 收到ERROR報文 返回錯誤
*/
if (ntohs(tftp_fileblock.op) == TFTP_OP_ERROR)
{
fprintf(stderr, "file not exist!\n");
return UPDATE_FILE_NOTEXIST;
}
/**
* 收到其它無法識別的報文類型 丟棄
*/
else if (ntohs(tftp_fileblock.op) != TFTP_OP_DATA)
{
fprintf(stderr, "OP error!\n");
continue;
}
/**
* 若為RRQ的應答 記錄服務器的端口
*/
tftp_tid = (tftp_tid == 0) ? ntohs(tftp_server_addr.sin_port) : tftp_tid;
/**
* 收到數據報文 比較數據塊的編號 回送確認
*/
if (tftp_index - 1 == ntohs(tftp_fileblock.index))
{
/* 服務器沒有收到上次的ACK 重發 */
if (TftpSendAck(sockfd, tftp_fileblock.index) < 0)
{
perror("RESend data ACK");
return UPDATE_CONN_ERROR;
}
continue;
}
else if (tftp_index == ntohs(tftp_fileblock.index))
{
if (TftpSendAck(sockfd, tftp_fileblock.index) < 0)
{
perror("send data ACK");
return UPDATE_CONN_ERROR;
}
*p_len = len;
break;
}
else
{
return UPDATE_ERROR_UNKNOWN;
}
}
if (retry <= 0)
{
return UPDATE_CONN_ERROR;
}
else
{
return UPDATE_OK;
}
}
/*******************************************************
* 獲得升級文件 進行升級操作
*******************************************************/
static int TftpGetUpdate(int sockfd)
{
int len, flen;
int offset = 0;
int count = 0;
int fileType;
unsigned char done = 0;
unsigned short index = 0;
int result = UPDATE_OK;
s_updateblock update_block;
s_updateblock * p;
update_block.next = NULL;
fileType = 0;
p = & update_block;
while (!done)
{
if ((result = TftpGetResponse(sockfd, &len)) != UPDATE_OK)
{
break;
}
if ((count + len - 4) > COMPRESSED_IMAGE_ADDR)
{
fprintf(stderr, "file too long\n");
result = UPDATE_NO_SPACE;
break;
}
if (count == 0)
{
if (len > 4)
{
if ( memcmp(tftp_fileblock.fileblock, phoneconfig.bootFileHead, 4) == 0 )
fileType = 1;
if ( memcmp(tftp_fileblock.fileblock, phoneconfig.appFileHead, 4) == 0 )
fileType = 2;
}
if (fileType != 1 && fileType != 2)
{
printf("file type error!\n\n");
return UPDATE_INVALID_FILE;
}
}
count += len - 4;
if (tftp_index % 2 != 0)
{
if ((p -> next = ConstructBlockNode()) == NULL)
{
fprintf(stderr, "file too long\n");
result = UPDATE_NO_SPACE;
break;
}
p = p -> next;
memcpy(p -> fileblock, tftp_fileblock.fileblock, len - 4);
p -> length = len - 4;
}
else
{
memcpy(p -> fileblock + p -> length, tftp_fileblock.fileblock, len - 4);
p -> length += len - 4;
}
if (len < TFTP_BLOCK_SIZE + 4)
{
done = 1;
}
tftp_index++;
}
if (done)
{
#ifdef __UPDATE_DEBUG__
printf("file %s %d bytes got\n", phoneconfig.conf_ftp.filename, count);
#endif
if (count == 0)
{
printf("file size is 0!!!\n\n");
return UPDATE_INVALID_FILE;
}
/* 寫入Flash */
result = UpdateFlashRom(update_block.next, count, fileType);
/*
Program_Version_Flash_Mem((unsigned short *) ptr_file, (p - ptr_file));
*/
}
#ifdef __UPDATE_DEBUG__
if (result == UPDATE_OK)
{
printf("Update OK.\n");
}
#endif
ClearUpdateBlock(update_block.next);
return result;
}
/*******************************************************
* Part UPDATE_COMMON
*******************************************************/
static s_updateblock * ConstructBlockNode(void)
{
s_updateblock * ptr_block;
if ((ptr_block = (s_updateblock *) malloc(sizeof(s_updateblock))) == NULL)
{
return NULL;
}
if ((ptr_block -> fileblock = (unsigned char *) malloc(UPDATE_BUFFER)) == NULL)
{
free(ptr_block);
return NULL;
}
memset(ptr_block -> fileblock, 0, UPDATE_BUFFER);
ptr_block -> length = 0;
ptr_block -> next = NULL;
return ptr_block;
}
void ClearUpdateBlock(s_updateblock * ptr_updatefile)
{
s_updateblock * p, * q;
#ifdef __UPDATE_DEBUG__
printf("Clear Update Node...\n");
#endif
if (ptr_updatefile == NULL)
{
return;
}
for (p = ptr_updatefile; p != NULL; p = q)
{
free(p -> fileblock);
q = p -> next;
free(p);
}
return;
}
int UpdateFlashRom(s_updateblock * ptr_updatefile, int count, int fileT)
{
s_updateblock * p;
unsigned short * pAddr = (unsigned short *) COMPRESSED_IMAGE_ADDR;
unsigned short * pBootAddr = (unsigned short *)ROM_BASE_ADRS;
unsigned char * ptr;
int offset = 0;
#ifdef __UPDATE_DEBUG__
CheckUpdateBlock(ptr_updatefile);
#endif
if (fileT == 1)
{
if (count > BOORROMSIZE)
{
printf("file too long!\n\n");
return UPDATE_TOO_LONG;
}
/*if (1)
{
printf("demo update OK!");
return UPDATE_OK;
}*/
/** remove by chenguoyin
if ((ptr = (unsigned char *) malloc(300 * 1024)) == NULL)
{
fprintf(stderr, "error malloc boot\n");
return -1;
}
for (p = ptr_updatefile; p != NULL; p = p -> next)
{
memcpy(ptr + offset, p -> fileblock, p -> length);
offset += p -> length;
}
Program_Boot_Flash_Mem((unsigned short *) ptr, offset);
free(ptr);
**/
if ( gFlashType == SST )
{
if ( count> ( COMPRESSED_IMAGE_ADDR - ROM_BASE_ADRS - 4 - SST_BLOCK_SIZE_UINT16 * 2 * 2 ) )
{
printf("The Version is to Large!\n");
return UPDATE_TOO_LONG;
}
}
else
{
if (count > ( COMPRESSED_IMAGE_ADDR - ROM_BASE_ADRS - 4 - FLASH_SECTOR_SIZE * 2) )
{
printf("The Version is to Large!\n");
return UPDATE_TOO_LONG;
}
}
if ( Erase_Boot_Flash_Mem () != OK )
return UPDATE_WRITE_ERROR;
for (p = ptr_updatefile; p != NULL && count > 0; p = p -> next)
{
if (Program_Version_Flash_Mem((unsigned short *) p -> fileblock, pBootAddr, p -> length) != OK)
{
fprintf(stderr, "Write Flash ROM ERROR!\n");
return UPDATE_WRITE_ERROR;
}
pBootAddr += p -> length / 2;
count -= p -> length / 2;
}
}
else if (fileT == 2)
{
if (count > APPSIZE)
{
printf("file too long!\n\n");
return UPDATE_TOO_LONG;
}
/*if (1)
{
printf("demo update OK!");
return UPDATE_OK;
}*/
if (count > COMPRESSED_IMAGE_SIZE)
{
fprintf(stderr, "The Version is too Large!\n");
return UPDATE_NO_SPACE;
}
SetVersionUpdateFlag ( 0xff );/*2004-7-12 fujiangdong update begin*/
if (Erase_Version_Flash_Mem () != OK)
{
fprintf(stderr, "Erase Flash ROM ERROR!\n");
return UPDATE_WRITE_ERROR;
}
for (p = ptr_updatefile; p != NULL && count > 0; p = p -> next)
{
if (Program_Version_Flash_Mem((unsigned short *) p -> fileblock, pAddr, p -> length) != OK)
{
fprintf(stderr, "Write Flash ROM ERROR!\n");
return UPDATE_WRITE_ERROR;
}
pAddr += p -> length / 2;
count -= p -> length / 2;
}
SetVersionUpdateFlag ( 0x32 );/*2004-7-12 fujiangdong update begin*/
}
#ifdef __UPDATE_DEBUG__
printf("Write Flash OK.\n");
#endif
return UPDATE_OK;
}
#ifdef __UPDATE_DEBUG__
static void CheckUpdateBlock(s_updateblock * ptr)
{
s_updateblock * p;
int i;
for (p = ptr, i = 0; p != NULL; p = p -> next, i++)
{
/* none */
}
printf("There are %d blocks in the Update file\n", i);
return;
}
#endif
#ifdef __cplusplus
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -