You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
5.2 KiB
C

#include <stdio.h>
#include <stdint.h>
#ifndef WIN32
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <strings.h>
#include <termios.h>
#include <unistd.h>
#include <arpa/inet.h>
#else
#include <windows.h>
#include "getopt.h"
#include "printf.h"
#include "buildno.h"
#endif
#include "hdlcio.h"
#include "ptable.h"
#include "flasher.h"
#include "util.h"
#define true 1
#define false 0
//***************************************************
//* Error code
//***************************************************
int errcode;
//***************************************************
//* Error code output command
//***************************************************
void printerr() {
if (errcode == -1) printf(" - Timeout\n");
else printf(" - Error Code %02x\n",errcode);
}
//***************************************************
// Send partition start command
//
// code - 32-bit partition code
// size - full size of the writable partition
//
//* result:
// false - error
// true - command was accepted by the modem
//***************************************************
int dload_start(uint32_t code,uint32_t size) {
uint32_t iolen;
uint8_t replybuf[4096];
#ifndef WIN32
static struct __attribute__ ((__packed__)) {
#else
#pragma pack(push,1)
static struct {
#endif
uint8_t cmd;
uint32_t code;
uint32_t size;
uint8_t pool[3];
} cmd_dload_init = {0x41,0,0,{0,0,0}};
#ifdef WIN32
#pragma pack(pop)
#endif
cmd_dload_init.code=htonl(code);
cmd_dload_init.size=htonl(size);
iolen=send_cmd((uint8_t*)&cmd_dload_init,sizeof(cmd_dload_init),replybuf);
errcode=replybuf[3];
if ((iolen == 0) || (replybuf[1] != 2)) {
if (iolen == 0) errcode=-1;
return false;
}
else return true;
}
//***************************************************
// Sending a partition block
//
// blk - # of block
// pimage - address of the partition image start in memory
//
//* result:
// false - error
// true - command was accepted by the modem
//***************************************************
int dload_block(uint32_t part, uint32_t blk, uint8_t* pimage) {
uint32_t res,blksize,iolen;
uint8_t replybuf[4096];
#ifndef WIN32
static struct __attribute__ ((__packed__)) {
#else
#pragma pack(push,1)
static struct {
#endif
uint8_t cmd;
uint32_t blk;
uint16_t bsize;
uint8_t data[fblock];
} cmd_dload_block;
#ifdef WIN32
#pragma pack(pop)
#endif
blksize=fblock; // initial block size value
res=ptable[part].hd.psize-blk*fblock; // size of the remaining chunk to the end of the file
if (res<fblock) blksize=res; // correct the size of the last block
// command code
cmd_dload_block.cmd=0x42;
// block number
cmd_dload_block.blk=htonl(blk+1);
// block size
cmd_dload_block.bsize=htons(blksize);
// portion of data from the partition image
memcpy(cmd_dload_block.data,pimage+blk*fblock,blksize);
// send block to the modem
iolen=send_cmd((uint8_t*)&cmd_dload_block,sizeof(cmd_dload_block)-fblock+blksize,replybuf); // send command
errcode=replybuf[3];
if ((iolen == 0) || (replybuf[1] != 2)) {
if (iolen == 0) errcode=-1;
return false;
}
return true;
}
//***************************************************
// End partition recording
//
// code - partition code
// size - size of partition
//
//* result:
// false - error
// true - command was accepted by modem
//***************************************************
int dload_end(uint32_t code, uint32_t size) {
uint32_t iolen;
uint8_t replybuf[4096];
#ifndef WIN32
static struct __attribute__ ((__packed__)) {
#else
#pragma pack(push,1)
static struct {
#endif
uint8_t cmd;
uint32_t size;
uint8_t garbage[3];
uint32_t code;
uint8_t garbage1[11];
} cmd_dload_end;
#ifdef WIN32
#pragma pack(pop)
#endif
cmd_dload_end.cmd=0x43;
cmd_dload_end.code=htonl(code);
cmd_dload_end.size=htonl(size);
iolen=send_cmd((uint8_t*)&cmd_dload_end,sizeof(cmd_dload_end),replybuf);
errcode=replybuf[3];
if ((iolen == 0) || (replybuf[1] != 2)) {
if (iolen == 0) errcode=-1;
return false;
}
return true;
}
//***************************************************
//* Writing all partitions from table to the modem
//***************************************************
void flash_all() {
int32_t part;
uint32_t blk,maxblock;
printf("\n## ---- Partition name ---- Progress");
// main partition recording loop
for(part=0;part<npart;part++) {
printf("\n");
// printf("\n02i %s)",part,ptable[part].pname);
// command to start partitioning
if (!dload_start(ptable[part].hd.code,ptable[part].hd.psize)) {
printf("\r! Rejected partition %i (%s)",part,ptable[part].pname);
printerr();
exit(-2);
}
maxblock=(ptable[part].hd.psize+(fblock-1))/fblock; // number of blocks in the partition
// block cycle of partition image transfer
for(blk=0;blk<maxblock;blk++) {
// output written percentage
printf("\r%02i %-20s %i%%",part,ptable[part].pname,(blk+1)*100/maxblock);
// send next block
if (!dload_block(part,blk,ptable[part].pimage)) {
printf("\n! Block %i of partition %i rejected (%s)",blk,part,ptable[part].pname);
printerr();
exit(-2);
}
}
// finalizing partition
if (!dload_end(ptable[part].hd.code,ptable[part].hd.psize)) {
printf("\n! Finalizing partition %i failed (%s)",part,ptable[part].pname);
printerr();
exit(-2);
}
} // end of partition cycle
}