Добавлена работа с цифровой подписью

Оптимизирована процедура обмена АТ-командами
Уменьшена нестабильность перехода в HDLC-режим
This commit is contained in:
forth32 2016-08-02 18:24:54 +03:00
parent 3f3a4b7e37
commit 9c4f5702b8
3 changed files with 115 additions and 98 deletions

View File

@ -11,6 +11,9 @@
#include "hdlcio.h"
unsigned char replybuf[4096];
//******************************************************
//* поиск символического имени раздела по его коду
//******************************************************
@ -66,12 +69,65 @@ if (pcodes[j].code != 0) strcpy(pname,pcodes[j].name); // имя найдено
else sprintf(pname,"U%08x",id); // имя не найдено - подставляем псевдоимя Uxxxxxxxx в тупоконечном формате
}
//****************************************************
//* Отсылка модему АТ-команды
//*
//* cmd - буфер с командой
//* rbuf - буфер для записи ответа
//*
//* Возвращает длину ответа
//****************************************************
int atcmd(char* cmd, char* rbuf) {
int res;
char cbuf[128];
strcpy(cbuf,"AT");
strcat(cbuf,cmd);
strcat(cbuf,"\r");
port_timeout(100);
// Вычищаем буфер приемника и передатчика
tcflush(siofd,TCIOFLUSH);
// отправка команды
write(siofd,cbuf,strlen(cbuf));
usleep(100000);
// чтение результата
res=read(siofd,rbuf,200);
return res;
}
//****************************************************
//* Определение версии прошивальщика
//*
//* 0 - нет ответа на команду
//* 1 - версия 2.0
//* -1 - версия не 2.0
//****************************************************
int dloadversion() {
int res;
int i;
res=atcmd("^DLOADVER?",replybuf);
if (res == 0) return 0;
if (strncmp(replybuf+2,"2.0",3) == 0) return 1;
for (i=2;i<res;i++) {
if (replybuf[i] == 0x0d) replybuf[i]=0;
}
printf("! Неправильная версия монитора прошивки - [%i]%s\n",res,replybuf+2);
dump(replybuf,res,0);
return -1;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void main(int argc, char* argv[]) {
unsigned int i,j,res,opt,npart=0,iolen,part,blk,blksize;
unsigned int i,j,opt,npart=0,iolen,part,blk,blksize;
int res;
FILE* in;
FILE* out;
@ -87,16 +143,21 @@ struct {
unsigned char buf[40960];
unsigned char devname[50]="/dev/ttyUSB0";
unsigned char replybuf[4096];
unsigned char datamodecmd[]="AT^DATAMODE";
unsigned char resetcmd[]="AT^RESET";
unsigned char* signver[2]={
"^SIGNVER=1,0,778A8D175E602B7B779D9E05C330B5279B0661BF2EED99A20445B366D63DD697,2958", // прошивка
"^SIGNVER=6,0,778A8D175E602B7B779D9E05C330B5279B0661BF2EED99A20445B366D63DD697,1110" // морда
};
unsigned int err;
unsigned char OKrsp[]={0x0d, 0x0a, 0x4f, 0x4b, 0x0d, 0x0a};
unsigned char NAKrsp[]={0x03, 0x00, 0x02, 0xba, 0x0a, 0x7e};
// ответ на ^signver
unsigned char SVrsp[]={0x0d, 0x0a, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x4f, 0x4b, 0x0d, 0x0a};
unsigned int dpattern=0xa55aaa55;
unsigned int mflag=0,eflag=0,rflag=0,sflag=0,nflag=0;
int gflag=-1;
unsigned char filename [100];
unsigned char fdir[40]; // каталог для мультифайловой прошивки
@ -110,7 +171,7 @@ unsigned char cmd_dload_end[30]={0x43}; // команда конца ра
// Коды типов разделов
//-d - попытка переключить модем из режима HDLC в АТ-режим\n\
while ((opt = getopt(argc, argv, "hp:mersn")) != -1) {
while ((opt = getopt(argc, argv, "hp:mersng")) != -1) {
switch (opt) {
case 'h':
@ -119,6 +180,7 @@ printf("\n Утилита предназначена для прошивки м
Допустимы следующие ключи:\n\n\
-p <tty> - последовательный порт для общения с загрузчиком (по умолчанию /dev/ttyUSB0)\n\
-n - режим мультифайловой прошивки из указанного каталога\n\
-g - прошивки в режиме цифровой подписи\n\
-m - вывести карту файла прошивки и завершить работу\n\
-e - разобрать файл прошивки на разделы без заголовков\n\
-s - разобрать файл прошивки на разделы с заголовками\n\
@ -150,6 +212,10 @@ printf("\n Утилита предназначена для прошивки м
sflag=1;
break;
case 'g':
gflag=10;
break;
case '?':
case ':':
return;
@ -283,14 +349,18 @@ sio:
//--------- Основной режим - запись прошивки
//--------------------------------------------
// определяем режим цифровой подписи
if (gflag == 10) {
if (strcmp(ptable[0].pname,"Oeminfo") == 0) gflag=1; // режим вебморды
else gflag=0; // режим прошивки
printf("\nРежим цифровой подписи: %s",gflag?"Webui":"Firmware");
}
// Настройка SIO
if (!open_port(devname)) {
#ifndef WIN32
printf("\n - Последовательный порт %s не открывается\n", devname);
#else
printf("\n - Последовательный порт COM%s не открывается\n", devname);
#endif
return;
}
@ -298,15 +368,29 @@ if (!open_port(devname)) {
tcflush(siofd,TCIOFLUSH); // очистка выходного буфера
// выходим из режима HDLC - если модем уже был в нем
port_timeout(1);
send_cmd(cmddone,1,replybuf);
// port_timeout(1);
// send_cmd(cmddone,1,replybuf);
// usleep(100000);
res=dloadversion();
if (res == -1) return;
if (res == 0) {
printf("\n Модем уже находится в HDLC-режиме");
goto hdlc;
}
// Если надо, отправляем команду цифровой подписи
if (gflag != -1) {
printf("\n Отправлем signver...");
res=atcmd(signver[gflag],replybuf);
if (memcmp(replybuf,SVrsp,sizeof(SVrsp)) != 0) {
printf("\n Ошибка проверки цифровой сигнатуры\n");
dump(replybuf,res,0);
return;
}
}
// Входим в HDLC-режим
printf("\n Входим в режим HDLC...");
port_timeout(100);
for (err=0;err<10;err++) {
@ -315,24 +399,30 @@ if (err == 10) {
return;
}
write(siofd,datamodecmd,strlen(datamodecmd));
res=read(siofd,replybuf,6);
usleep(100000);
res=atcmd("^DATAMODE",replybuf);
if (res != 6) {
printf("\n Неправильная длина ответа на ^DATAMODE, повторяем попытку...");
dump(replybuf,res,0);
continue;
}
if (memcmp(replybuf,OKrsp,6) != 0) {
printf("\n Команда ^DATAMODE отвергнута, повторяем попытку...");
continue;
}
iolen=send_cmd(cmdver,1,replybuf);
if ((iolen == 0)||(replybuf[1] != 0x0d)) {
printf("\n Ошибка получения версии протокола, повторяем попытку...");
dump(replybuf,res,0);
continue;
}
break;
}
// Вошли в HDLC
//------------------------------
hdlc:
iolen=send_cmd(cmdver,1,replybuf);
if ((iolen == 0)||(replybuf[1] != 0x0d)) {
printf("\n Ошибка получения версии протокола\n");
return;
}
i=replybuf[2];
replybuf[3+i]=0;
@ -340,6 +430,7 @@ printf("ok");
printf("\n Версия протокола: %s",replybuf+3);
printf("\n");
if ((optind>=argc)&rflag) goto reset; // перезагрузка без указания файла
@ -408,7 +499,7 @@ reset:
if (rflag) {
printf("\n Перезарузка модема...\n");
send_cmd(cmd_reset,1,replybuf);
write(siofd,resetcmd,strlen(resetcmd));
atcmd("^RESET",replybuf);
}
else send_cmd(cmddone,1,replybuf);
}

View File

@ -4,14 +4,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef WIN32
#include <strings.h>
#include <termios.h>
#include <unistd.h>
#else
#include <windows.h>
#include "printf.h"
#endif
#include <dirent.h>
#include "hdlcio.h"
@ -25,11 +20,7 @@ char flash_descr[30]={0};
unsigned int oobsize=0;
#ifndef WIN32
struct termios sioparm;
#else
static HANDLE hSerial;
#endif
int siofd; // fd для работы с Последовательным портом
@ -107,30 +98,6 @@ for(i=0;i<len;i++) crc=crctab[(buf[i]^crc)&0xff]^((crc>>8)&0xff);
return (~crc)&0xffff;
}
#ifdef WIN32
static int read(int siofd, unsigned char* buf, int len)
{
DWORD bytes_read = 0;
DWORD t = GetTickCount();
do {
ReadFile(hSerial, buf, len, &bytes_read, NULL);
} while (bytes_read == 0 && GetTickCount() - t < 1000);
return bytes_read;
}
static int write(int siofd, unsigned char* buf, int len)
{
DWORD bytes_written = 0;
WriteFile(hSerial, buf, len, &bytes_written, NULL);
return bytes_written;
}
#endif
//*************************************************
//* отсылка буфера в модем
@ -138,19 +105,11 @@ static int write(int siofd, unsigned char* buf, int len)
unsigned int send_unframed_buf(char* outcmdbuf, unsigned int outlen) {
#ifndef WIN32
tcflush(siofd,TCIOFLUSH); // сбрасываем недочитанный буфер ввода
#else
PurgeComm(hSerial, PURGE_RXCLEAR);
#endif
write(siofd,"\x7e",1); // отсылаем префикс
if (write(siofd,outcmdbuf,outlen) == 0) { printf("\n Ошибка записи команды");return 0; }
#ifndef WIN32
tcdrain(siofd); // ждем окончания вывода блока
#else
FlushFileBuffers(hSerial);
#endif
return 1;
}
@ -221,9 +180,6 @@ return iolen;
}
//##############33
//***********************************************************
//* Преобразование командного буфера с Escape-подстановкой
//***********************************************************
@ -284,7 +240,6 @@ return receive_reply(iobuf,0);
int open_port(char* devname)
{
#ifndef WIN32
siofd = open(devname, O_RDWR | O_NOCTTY |O_SYNC);
if (siofd == -1) return 0;
@ -297,34 +252,6 @@ sioparm.c_cc[VTIME]=30; // timeout
sioparm.c_cc[VMIN]=0;
tcsetattr(siofd, TCSANOW, &sioparm);
return 1;
#else
char device[20] = "\\\\.\\COM";
DCB dcbSerialParams = {0};
strcat(device, devname);
hSerial = CreateFileA(device, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial == INVALID_HANDLE_VALUE)
return 0;
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams))
{
CloseHandle(hSerial);
return 0;
}
dcbSerialParams.BaudRate=CBR_115200;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams))
{
CloseHandle(hSerial);
return 0;
}
return 1;
#endif
}
//*************************************
@ -332,7 +259,6 @@ return 1;
//*************************************
void port_timeout(int timeout) {
#ifndef WIN32
bzero(&sioparm, sizeof(sioparm)); // готовим блок атрибутов termios
sioparm.c_cflag = B115200 | CS8 | CLOCAL | CREAD ;
sioparm.c_iflag = 0; // INPCK;
@ -341,7 +267,6 @@ sioparm.c_lflag = 0;
sioparm.c_cc[VTIME]=timeout; // timeout
sioparm.c_cc[VMIN]=0;
tcsetattr(siofd, TCSANOW, &sioparm);
#endif
}
//*************************************************

View File

@ -4,3 +4,4 @@ void dump(char buffer[],int len,long base);
int send_cmd(unsigned char* incmdbuf, int blen, unsigned char* iobuf);
int open_port(char* devname);
int find_file(int num, char* dirname, char* filename,unsigned int* id, unsigned int* size);
void port_timeout();