Сделана прошивка из группы сырых бинарников

master
forth32 9 years ago
parent b8fec219d7
commit 757def7310

@ -11,19 +11,57 @@
#include "hdlcio.h"
//******************************************************
//* поиск символического имени раздела по его коду
//******************************************************
void find_pname(unsigned int id,unsigned char* pname) {
unsigned int j;
struct {
char name[20];
int code;
} pcodes[]={
{"M3Boot",0x20000},
{"Ptable",0x10000},
{"Fastboot",0x110000},
{"Kernel",0x30000},
{"VxWorks",0x40000},
{"M3Image",0x50000},
{"DSP",0x60000},
{"NVRAM",0x70000},
{"System",0x590000},
{"APP",0x5a0000},
{"CD_WUI_VER",0xa0000},
{"CDROMISO",0xb0000},
{"WEBUI",0x5b0000},
{0,0}
};
for(j=0;pcodes[j].code != 0;j++) {
if(pcodes[j].code == id) break;
}
if (pcodes[j].code != 0) strcpy(pname,pcodes[j].name); // имя найдено - копируем его в структуру
else sprintf(pname,"U%08x",id); // имя не найдено - подставляем псевдоимя Uxxxxxxxx в тупоконечном формате
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void main(int argc, char* argv[]) {
struct termios sioparm;
unsigned int i,j,res,opt,npart=0,iolen,part,blk,blksize;
FILE* in;
FILE* out;
struct {
unsigned int offset;
unsigned int size;
unsigned int code;
unsigned int offset; // позиция образа раздела
unsigned int hdoffset; // позиция заголовка раздела
unsigned int size; // размер образа раздела
unsigned int hdsize; // размер заголовка раздела
unsigned int code; // ID раздела
unsigned char pname[20]; // буквенное имя раздела
unsigned char filename[50]; // имя файла, соответствующее разделу
}ptable[100];
unsigned char buf[4096];
@ -36,9 +74,11 @@ unsigned char OKrsp[]={0x0d, 0x0a, 0x4f, 0x4b, 0x0d, 0x0a};
unsigned char NAKrsp[]={0x03, 0x00, 0x02, 0xba, 0x0a, 0x7e};
unsigned int dpattern=0xa55aaa55;
unsigned int mflag=0,eflag=0,rflag=0;
unsigned int mflag=0,eflag=0,rflag=0,sflag=0,nflag=0;
unsigned char filename [100];
unsigned char fdir[40]; // каталог для мультифайловой прошивки
unsigned char cmdver[7]={0x0c}; // версия протокола
unsigned char cmddone[7]={0x1}; // команда выхода из HDLC
unsigned char cmd_reset[7]={0xa}; // команда выхода из HDLC
@ -46,37 +86,20 @@ unsigned char cmd_dload_init[15]={0x41}; // команда начала раз
unsigned char cmd_data_packet[11000]={0x42}; // команда начала пакета
unsigned char cmd_dload_end[30]={0x43}; // команда конца раздела
// Коды типов разделов
struct {
char name[20];
int code;
} pcodes[]={
{"M3Boot",0x20000},
{"Ptable",0x10000},
{"Fastboot",0x110000},
{"Kernel",0x30000},
{"VxWorks",0x40000},
{"M3Image",0x50000},
{"DSP",0x60000},
{"NVRAM",0x70000},
{"System",0x590000},
{"APP",0x5a0000},
{"CD_WUI_VER",0xa0000},
{"CDROMISO",0xb0000},
{"WEBUI",0x5b0000},
{0,0}
};
//-d - попытка переключить модем из режима HDLC в АТ-режим\n\
while ((opt = getopt(argc, argv, "hp:mer")) != -1) {
while ((opt = getopt(argc, argv, "hp:mersn")) != -1) {
switch (opt) {
case 'h':
printf("\n Утилита предназначена для прошивки модемов E3372S\n\n\
%s [ключи] <имя файла для загрузки>\n\n\
%s [ключи] <имя файла для загрузки или имя каталога с файлами>\n\n\
Допустимы следующие ключи:\n\n\
-p <tty> - последовательный порт для общения с загрузчиком (по умолчанию /dev/ttyUSB0\n\
-p <tty> - последовательный порт для общения с загрузчиком (по умолчанию /dev/ttyUSB0)\n\
-n - режим мультифайловой прошивки из указанного каталога\n\
-m - вывести карту файла прошивки и завершить работу\n\
-e - разобрать файл прошивки на разделы и завершить работу\n\
-e - разобрать файл прошивки на разделы без заголовков\n\
-s - разобрать файл прошивки на разделы с заголовками\n\
-r - выйти из режима прошивки и перезагрузить модем\n\
\n",argv[0]);
return;
@ -89,6 +112,10 @@ printf("\n Утилита предназначена для прошивки м
mflag=1;
break;
case 'n':
nflag=1;
break;
case 'r':
rflag=1;
break;
@ -97,75 +124,127 @@ printf("\n Утилита предназначена для прошивки м
eflag=1;
break;
case 's':
sflag=1;
break;
case '?':
case ':':
return;
}
}
if ((optind>=argc)&rflag) goto sio; // перезагрузка без указания файла
if (eflag&sflag) {
printf("\n Ключи -s и -e несовместимы\n");
return;
}
if (nflag&(eflag|sflag|mflag)) {
printf("\n Ключ -n несовместим с ключами -s, -m и -e\n");
return;
}
// ------ перезагрузка без указания файла
//--------------------------------------------
if ((optind>=argc)&rflag) goto sio;
// Открытие входного файла
//--------------------------------------------
if (optind>=argc) {
if (nflag)
printf("\n - Не указан каталог с файлами\n");
else
printf("\n - Не указано имя файла для загрузки\n");
return;
return;
}
if (nflag)
// для -n - просто копируем префикс
strncpy(fdir,argv[optind],39);
else {
// для однофайловых операций
in=fopen(argv[optind],"r");
if (in == 0) {
printf("\n Ошибка открытия %s",argv[optind]);
return;
}
}
// Поиск разделов внутри файла
printf("\n Разбираем файл прошвки...");
while (fread(&i,1,4,in) == 4) {
if (i != dpattern) continue; // ищем разделитель
ptable[npart].offset=ftell(in); // позиция начала раздела
fread(buf,1,96,in); // заголовок
ptable[npart].offset+=*((unsigned int*)&buf[0])-4; // выкидываем из смещения длину заголовка+КС
ptable[npart].size=*((unsigned int*)&buf[20]); // размер раздела
ptable[npart].code=*((unsigned int*)&buf[16]); // тип раздела
npart++;
}
if (npart == 0) {
printf("\nРазделы не найдены!");
return ;
//--------------------------------------------
if (!nflag) {
printf("\n Разбираем файл прошвки...");
while (fread(&i,1,4,in) == 4) {
if (i != dpattern) continue; // ищем разделитель
// Выделяем параметры раздела
ptable[npart].hdoffset=ftell(in); // позиция начала заголовка раздела
fread(buf,1,96,in); // заголовок
ptable[npart].hdsize=*((unsigned int*)&buf[0])-4; // размер заголовка
ptable[npart].offset=ptable[npart].hdoffset+ptable[npart].hdsize; // смещение до тела раздела
ptable[npart].size=*((unsigned int*)&buf[20]); // размер раздела
ptable[npart].code=*((unsigned int*)&buf[16]); // тип раздела
// Ищем символическое имя раздела по таблице
find_pname(ptable[npart].code,ptable[npart].pname);
// увеличиваем счетчик разделов
npart++;
}
if (npart == 0) {
printf("\nРазделы не найдены!");
return ;
}
}
printf(" найдено %i разделов",npart);
//------ Режим вывода карты файла прошивки
// Поиск файлов прошивок в указанном каталоге
//--------------------------------------------
else {
printf("\n Поиск файлов-образов разделов...\n\n ## Размер ID Имя Файл\n-----------------------------------------------------------------\n");
for (npart=0;npart<30;npart++) {
if (find_file(npart, fdir, ptable[npart].filename, &ptable[npart].code, &ptable[npart].size) == 0) break; // конец поиска - раздела с таким ID не нашли
// получаем символическое имя раздела
find_pname(ptable[npart].code,ptable[npart].pname);
printf("\n %02i %8i %08x %-8.8s %s",npart,ptable[npart].size,ptable[npart].code,ptable[npart].pname,ptable[npart].filename);
}
}
printf("\n Найдено %i разделов",npart);
//------ Режим вывода карты файла прошивки
//--------------------------------------------
if (mflag) {
printf("\n Таблица разделов, найденных в файле:\n\n ## Смещение Размер Имя\n-------------------------------------");
for (i=0;i<npart;i++) {
printf("\n %02i %08x %8i ",i,ptable[i].offset,ptable[i].size);
for(j=0;pcodes[j].code != 0;j++) {
if(pcodes[j].code == ptable[i].code) break;
}
if (pcodes[j].code != 0) printf("%s",pcodes[j].name);
else printf("Неопределенный раздел - %08x",ptable[i].code);
}
printf("\n");
return;
for (i=0;i<npart;i++)
printf("\n %02i %08x %8i %s",i,ptable[i].offset,ptable[i].size,ptable[i].pname);
printf("\n");
return;
}
//------- Режим разрезания файла прошивки
if (eflag) {
//--------------------------------------------
if (eflag|sflag) {
printf("\n Выделение разделов из файла прошивки:\n\n ## Смещение Размер Имя\n-------------------------------------");
for (i=0;i<npart;i++) {
printf("\n %02i %08x %8i ",i,ptable[i].offset,ptable[i].size);
for(j=0;pcodes[j].code != 0;j++) {
if(pcodes[j].code == ptable[i].code) break;
}
if (pcodes[j].code != 0) {
printf("%s",pcodes[j].name);
sprintf(filename,"%02i-%s",i,pcodes[j].name);
}
else {
printf("Неопределенный раздел - %08x",ptable[i].code);
sprintf(filename,"%02i-U%08x",i,ptable[i].code);
}
printf("\n %02i %08x %8i %s",i,ptable[i].offset,ptable[i].size,ptable[i].pname);
// формируем имя файла
sprintf(filename,"%02i-%08x-%s.%s",i,ptable[i].code,ptable[i].pname,(eflag?"bin":"fw"));
out=fopen(filename,"w");
if(sflag) {
// запись заголовка
fwrite(&dpattern,1,4,out); // маркер- magic заголовка блока
fseek(in,ptable[i].hdoffset,SEEK_SET); // встаем на начало заголовка
fread(buf,1,ptable[i].offset-ptable[i].hdoffset,in);
fwrite(buf,1,ptable[i].offset-ptable[i].hdoffset,out);
}
// запись тела
fseek(in,ptable[i].offset,SEEK_SET); // встаем на начало
for(j=0;j<ptable[i].size;j+=4) {
fread(buf,4,1,in);
@ -177,7 +256,10 @@ printf("\n");
return;
}
sio:
//--------- Основной режим - запись прошивки
//--------------------------------------------
// Настройка SIO
@ -191,7 +273,6 @@ if (!open_port(devname)) {
}
tcsetattr(siofd, TCSANOW, &sioparm);
tcflush(siofd,TCIOFLUSH); // очистка выходного буфера
// выходим из режима HDLC - если модем уже был в нем
@ -244,17 +325,7 @@ if ((optind>=argc)&rflag) goto reset; // перезагрузка без ука
// Главный цикл записи разделов
for(part=0;part<npart;part++) {
printf("\n Записываем раздел %i -",part);
// выводим имя раздела
for(j=0;pcodes[j].code != 0;j++) {
if(pcodes[j].code == ptable[part].code) break;
}
if (pcodes[j].code != 0) {
printf("%s\n",pcodes[j].name);
}
else {
printf("код %08x\n",ptable[npart].code);
}
printf("\n Записываем раздел %i - %s",part,ptable[part].pname);
// заполняем командный пакет
*((unsigned int*)&cmd_dload_init[1])=htonl(ptable[part].code);
@ -262,15 +333,23 @@ for(part=0;part<npart;part++) {
// отсылаем команду
iolen=send_cmd(cmd_dload_init,12,replybuf);
if ((iolen == 0) || (replybuf[1] != 2)) {
printf("\n Заголовок раздела не принят, код ошибки = %02x\n",replybuf[3]);
// dump(cmd_dload_init,13,0);
printf("\n Заголовок раздела не принят, код ошибки = %02x %02x %02x\n",replybuf[1],replybuf[2],replybuf[3]);
dump(cmd_dload_init,13,0);
printf("\nreply\n");
dump(replybuf,iolen,0);
return;
}
// Подготовка к поблочному циклу
blksize=4096; // начальное значение размера блока
if (!nflag)
// встаем на начало раздела в однофайловом режиме
fseek(in,ptable[part].offset,SEEK_SET);
else
// открываем файл в многофайловом режиме
in=fopen(ptable[part].filename,"r");
// Поблочный цикл
blksize=4096;
fseek(in,ptable[part].offset,SEEK_SET);
for(blk=0;blk<((ptable[part].size+4095)/4096);blk++) {
printf("\r Блок %i из %i",blk,(ptable[part].size+4095)/4096); fflush(stdout);
res=ptable[part].size+ptable[part].offset-ftell(in); // размер оставшегося куска до конца файла
@ -280,18 +359,21 @@ for(part=0;part<npart;part++) {
fread(cmd_data_packet+7,1,blksize,in); // читаем очередной кусок раздела в буфер команды
iolen=send_cmd(cmd_data_packet,blksize+7,replybuf); // отсылаем команду
if ((iolen == 0) || (replybuf[1] != 2)) {
printf("\n Блок %i раздела не принят, код ошибки = %02x\n",blk,replybuf[3]);
printf("\n Блок %i раздела не принят, код ошибки = %02x %02x %02x\n",blk,replybuf[1],replybuf[2],replybuf[3]);
// dump(cmd_data_packet,blksize+7,0);
return;
}
}
// Закрытие файла в многофайловом режиме
if (nflag) fclose(in);
// Закрытие потока
*((unsigned int*)&cmd_dload_end[1])=htonl(ptable[part].size);
*((unsigned int*)&cmd_dload_end[8])=htonl(ptable[part].code);
iolen=send_cmd(cmd_dload_end,24,replybuf); // отсылаем команду
if ((iolen == 0) || (replybuf[1] != 2)) {
printf("\n Ошибка закрытия раздела, код ошибки = %02x\n",replybuf[3]);
printf("\n Ошибка закрытия раздела, код ошибки = %02x %02x %02x\n",blk,replybuf[1],replybuf[2],replybuf[3]);
dump(replybuf,iolen,0);
printf("\nИсходная команда:");
dump(cmd_data_packet,24,0);

@ -12,7 +12,7 @@
#include <windows.h>
#include "printf.h"
#endif
#include <dirent.h>
#include "hdlcio.h"
unsigned int nand_cmd=0x1b400000;
@ -343,3 +343,85 @@ sioparm.c_cc[VMIN]=0;
tcsetattr(siofd, TCSANOW, &sioparm);
#endif
}
//*************************************************
//* Поиск файла по номеру в указанном каталоге
//*
//* num - # файла
//* filename - буфер для полного имени файла
//* id - переменная, в которую будет записан идентификатор раздела
//*
//* return 0 - не найдено
//* 1 - найдено
//*************************************************
int find_file(int num, char* dirname, char* filename,unsigned int* id, unsigned int* size) {
DIR* fdir;
FILE* in;
unsigned int pt;
struct dirent* dentry;
char fpattern[5];
sprintf(fpattern,"%02i",num); // образец для поиска файла по 3 цифрам номера
fdir=opendir(dirname);
if (fdir == 0) {
printf("\n Каталог %s не открывается\n");
exit(1);
}
// главный цикл - поиск нужного нам файла
while ((dentry=readdir(fdir)) != 0) {
if (dentry->d_type != DT_REG) continue; // пропускаем все кроме регулярных файлов
if (strncmp(dentry->d_name,fpattern,2) == 0) break; // нашли нужный файл. Точнее, файл с нужными 3 цифрами в начале имени.
}
closedir(fdir);
// формируем полное имя файла в буфере результата
if (dentry == 0) return 0; // не нашли
strcpy(filename,dirname);
strcat(filename,"/");
// копируем имя файла в буфер результата
strcat(filename,dentry->d_name);
// 00-00000200-M3Boot.bin
//проверяем имя файла на наличие знаков '-'
if ((dentry->d_name[2] != '-') || (dentry->d_name[11] != '-')) {
printf("\n Неправильный формат имени файла - %s\n",dentry->d_name);
exit(1);
}
// проверяем цифровое поле ID раздела
if (strspn(dentry->d_name+3,"0123456789AaBbCcDdEeFf") != 8) {
printf("\n Ошибка в идентификаторе раздела - нецифрвой знак - %s\n",filename);
exit(1);
}
sscanf(dentry->d_name+3,"%8x",id);
// Проверяем доступность и читаемость файла
in=fopen(filename,"r");
if (in == 0) {
printf("\n Ошибка открытия файла %s\n",filename);
exit(1);
}
if (fread(&pt,1,4,in) != 4) {
printf("\n Ошибка чтения файла %s\n",filename);
exit(1);
}
// проверяем, что файл - сырой образ, без заголовка
if (pt == 0xa55aaa55) {
printf("\n Файл %s имеет заголовок - для прошивки не подходит\n",filename);
exit(1);
}
// Что еще можно проверить? Пока не придумал.
// Получаем размер файла
fseek(in,0,SEEK_END);
*size=ftell(in);
fclose(in);
return 1;
}

@ -3,3 +3,4 @@ extern int siofd; // fd для работы с Последовательным
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);

Loading…
Cancel
Save