Initial to English translated release

master
Robert Zaage 2 years ago
parent c0ebd14883
commit 7f807afcea

@ -1,18 +1,18 @@
CC = gcc
LIBS =
LIBS =
CFLAGS = -O2 -g -Wno-unused-result
.PHONY: all clean
all: balong-usbdload ptable-injector loader-patch ptable-list
clean:
clean:
rm *.o
rm balong-usbdload
rm ptable-injector
rm loader-patch
rm ptable-list
#.c.o:
# $(CC) -o $@ $(LIBS) $^ qcio.o
@ -21,10 +21,9 @@ balong-usbdload: balong-usbdload.o parts.o patcher.o
ptable-injector: ptable-injector.o parts.o
@gcc $^ -o $@ $(LIBS)
loader-patch: loader-patch.o patcher.o
@gcc $^ -o $@ $(LIBS)
ptable-list: ptable-list.o parts.o
@gcc $^ -o $@ $(LIBS)

@ -1,27 +1,11 @@
# balong-usbdload
**Please read "getting help" section carefully before asking any questions!**
## Russian section
Утилита для аварийной USB-загрузки модемов на чипсете Balong V2R7, V7R11 и V7R22.
Позволяет загрузить внешний загрузчик-прошивальщик (usbloader) через аварийный USB-serial порт загрузки, создаваемый модемом при повреждении прошивки или замыкании на землю контакта аварийной загрузки на плате модема.
Многие загрузчики могут быть автоматически пропатчены данной утилитой в процессе загрузки. Патч необходим потому, что оригинальный usbloader стирает всю флеш-память в процессе загрузки, включая уникальные данные, хранящиеся в NVRAM.
**Эта утилита может вывести ваше устройство из строя!**
Используйте ее, только если осознаете все риски и последствия. В случае каких-либо возникших проблем, не ждите помощи, рассчитывайте только на свои собственные силы.
Пожалуйста, воздержитесь от любых вопросов, не касающихся программы напрямую, в том числе и о вопросах о файлах-загрузчиках. У нас их нет. Нет, мы не знаем, где их взять.
## English section
### About
Balong-usbdload is an emergency USB boot loader utility for Huawei LTE modems and routers with Balong V2R7, V7R11 and V7R22 chipsets.
Balong-usbdload is an emergency USB boot loader utility for Huawei LTE modems and routers with Balong V2R7, V7R11 and V7R22 chipsets.
It loads external boot loader/firmware update tool file (usbloader.bin) via emergency serial port available if the firmware is corrupted or boot pin (test point) is shorted to the ground.
**This utility can make your device unbootable!**
**This utility can make your device unbootable!**
Use it only if you fully understand all risks and consequences. In case of any issues, you're on your own. Do not expect any help.
### Where to get USB loader files (usbloader.bin)?
@ -55,7 +39,7 @@ We have no idea where boot pin is on your model. Look [here](https://routerunloc
* Please **DO NOT ASK** Windows-relared questions or ask for Windows builds.
Main development is focused on Linux version only.
Main development is focused on Linux version only.
Windows part is maintained by [**@rust3028**](https://github.com/rust3028) and is out of scope of this repository.
**To sum it up**: feel free to ask questions about the program itself; Report bugs if it could be reproduced in Linux. No questions about loader files allowed. Pull requests with functionality changes or bug fixes are welcome.

@ -1,5 +1,6 @@
// Загрузчик usbloader.bin через аварийный порт для модемов на платформе Balong V7R2.
//
// Balong-usbdload is an emergency USB boot loader utility for Huawei LTE modems and routers with Balong V2R7, V7R11 and V7R22 chipsets.
// It loads external boot loader/firmware update tool file (usbloader.bin) via emergency serial port available if the firmware is corrupted or boot pin (test point) is shorted to the ground.
//
#include <stdio.h>
#include <stdint.h>
@ -35,7 +36,7 @@ FILE* ldr;
//*************************************************
//* HEX-дамп области памяти *
//* HEX-dump of the memory area *
//*************************************************
void dump(unsigned char buffer[],int len) {
@ -51,12 +52,12 @@ for (i=0;i<len;i+=16) {
printf(" *");
for (j=0;j<16;j++) {
if ((i+j) < len) {
// преобразование байта для символьного отображения
// byte conversion for character display
ch=buffer[i+j];
if ((ch < 0x20)||((ch > 0x7e)&&(ch<0xc0))) putchar('.');
else putchar(ch);
}
// заполнение пробелами для неполных строк
}
// filling with spaces for incomplete lines
else printf(" ");
}
printf("*\n");
@ -65,26 +66,25 @@ for (i=0;i<len;i+=16) {
//*************************************************
//* Рассчет контрольной суммы командного пакета
//* Calculating the checksum of a command packet *
//*************************************************
void csum(unsigned char* buf, int len) {
unsigned int i,c,csum=0;
unsigned int cconst[]={0,0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF};
for (i=0;i<(len-2);i++) {
c=(buf[i]&0xff);
csum=((csum<<4)&0xffff)^cconst[(c>>4)^(csum>>12)];
csum=((csum<<4)&0xffff)^cconst[(c&0xf)^(csum>>12)];
}
}
buf[len-2]=(csum>>8)&0xff;
buf[len-1]=csum&0xff;
}
//*************************************************
//* Отсылка командного пакета модему
//* Sending a command packet to a modem *
//*************************************************
int sendcmd(unsigned char* cmdbuf, int len) {
@ -93,7 +93,7 @@ unsigned int replylen;
#ifndef WIN32
csum(cmdbuf,len);
write(siofd,cmdbuf,len); // отсылка команды
write(siofd,cmdbuf,len); // sending a command
tcdrain(siofd);
replylen=read(siofd,replybuf,1024);
#else
@ -109,55 +109,55 @@ replylen=read(siofd,replybuf,1024);
ReadFile(hSerial, replybuf, 1024, (LPDWORD)&replylen, NULL);
} while (replylen == 0 && GetTickCount() - t < 1000);
#endif
if (replylen == 0) return 0;
if (replylen == 0) return 0;
if (replybuf[0] == 0xaa) return 1;
return 0;
}
//*************************************
// Открытие и настройка последовательного порта
//*************************************
//*************************************************
// Opening and configuring the serial port *
//*************************************************
int open_port(char* devname) {
//============= Linux ========================
//============= Linux ===============
#ifndef WIN32
int i,dflag=1;
char devstr[200]={0};
// Вместо полного имени устройства разрешается передавать только номер ttyUSB-порта
// only the ttyUSB port number can be transmitted instead of the full device name.
// Проверяем имя устройства на наличие нецифровых символов
// check the device name for nonnumeric characters
for(i=0;i<strlen(devname);i++) {
if ((devname[i]<'0') || (devname[i]>'9')) dflag=0;
}
// Если в строке - только цифры, добавляем префикс /dev/ttyUSB
// if there are only digits in the string, add the prefix /dev/ttyUSB
if (dflag) strcpy(devstr,"/dev/ttyUSB");
// копируем имя устройства
// copy the device name
strcat(devstr,devname);
siofd = open(devstr, O_RDWR | O_NOCTTY |O_SYNC);
if (siofd == -1) return 0;
bzero(&sioparm, sizeof(sioparm)); // готовим блок атрибутов termios
bzero(&sioparm, sizeof(sioparm)); // prepare the attribute block termios
sioparm.c_cflag = B115200 | CS8 | CLOCAL | CREAD ;
sioparm.c_iflag = 0; // INPCK;
sioparm.c_oflag = 0;
sioparm.c_lflag = 0;
sioparm.c_cc[VTIME]=30; // timeout
sioparm.c_cc[VMIN]=0;
sioparm.c_cc[VTIME]=30; // timeout
sioparm.c_cc[VMIN]=0;
tcsetattr(siofd, TCSANOW, &sioparm);
return 1;
//============= Win32 ========================
//============= Win32 ===============
#else
char device[20] = "\\\\.\\COM";
DCB dcbSerialParams = {0};
COMMTIMEOUTS CommTimeouts;
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;
@ -192,11 +192,11 @@ return 1;
#endif
}
//*************************************
//* Поиск linux-ядра в образе раздела
//*************************************
//*******************************************************
//* Searching for the linux core in the partition image *
//*******************************************************
int locate_kernel(char* pbuf, uint32_t size) {
int off;
for(off=(size-8);off>0;off--) {
@ -268,10 +268,10 @@ static int find_port(int* port_no, char* port_name)
void main(int argc, char* argv[]) {
unsigned int i,res,opt,datasize,pktcount,adr;
int bl; // текущий блок
int bl; // current block
unsigned char c;
int fbflag=0, tflag=0, mflag=0, bflag=0, cflag=0;
int koff; // смещение до ANDROID-заголовка
int koff; // offset to ANDROID header
char ptfile[100];
FILE* pt;
@ -284,15 +284,15 @@ unsigned char cmdhead[14]={0xfe,0, 0xff};
unsigned char cmddata[1040]={0xda,0,0};
unsigned char cmdeod[5]={0xed,0,0,0,0};
// список разделов, которым нужно установить файловый флаг
// list of partitions to set the file flag
uint8_t fileflag[41];
struct {
int lmode; // режим загрузки: 1 - прямой старт, 2 - через перезапуск A-core
int size; // размер компонента
int adr; // адрес загрузки компонента в память
int offset; // смещение до компонента от начала файла
char* pbuf; // буфер для загрузки образа компонента
int lmode; // loading mode: 1 - direct start, 2 - via restarting A-core
int size; // size of a component
int adr; // address of the component loading into memory
int offset; // offset to the component from the beginning of the file
char* pbuf; // buffer for loading the component image
} blk[10];
@ -313,23 +313,23 @@ memset(fileflag, 0, sizeof(fileflag));
while ((opt = getopt(argc, argv, "hp:ft:ms:bc")) != -1) {
switch (opt) {
case 'h':
printf("\n Утилита предназначена для аварийной USB-загрузки устройств на чипете Balong V7\n\n\
%s [ключи] <имя файла для загрузки>\n\n\
Допустимы следующие ключи:\n\n"
case 'h':
printf("\n This utility is intended for emergency USB loading of devices on the Balong V7 chip\n\n\
%s [option] <boot file name>\n\n\
The following options are allowed:\n\n"
#ifndef WIN32
"-p <tty> - последовательный порт для общения с загрузчиком (по умолчанию /dev/ttyUSB0)\n"
"-p <tty> - serial port for communicating with the bootloader (by default /dev/ttyUSB0)\n"
#else
"-p # - номер последовательного порта для общения с загрузчиком (например, -p8)\n"
" если ключ -p не указан, производится автоопределение порта\n"
"-p # - number of the serial port for communicating with the loader (e.g. -p8)\n"
" if the -p switch is not specified, the port is auto-detected\n"
#endif
"-f - грузить usbloader только до fastboot (без запуска линукса)\n\
-b - аналогично -f, дополнительно отключить проверку дефектных блоков при стирании\n\
-t <file>- взять таблицу разделов из указанного файла\n\
-m - показать таблицу разделов загрузчика и завершить работу\n\
-s n - установить файловый флаг для раздела n (ключ можно указать несколько раз)\n\
-c - не производить автоматический патч стирания разделов\n\
"-f - Load usbloader only to fastboot (without starting Linux)\n\
-b - Similarly to -f, additionally disable check of defective blocks during wipeout\n\
-t <file> - Take partition table from specified file\n\
-m - Show the loader partition table and exit\n\
-s n - Set file flag for partition n (option can be set multiple times)\n\
-c - Do not automatically patch partitions\n\
\n",argv[0]);
return;
@ -362,134 +362,134 @@ printf("\n Утилита предназначена для аварийной U
case 's':
i=atoi(optarg);
if (i>41) {
printf("\n Раздела #%i не существует\n",i);
printf("\n Partition #%i does not exist\n",i);
return;
}
fileflag[i]=1;
break;
case '?':
case ':':
case ':':
return;
}
}
}
printf("\n Аварийный USB-загрузчик Balong-чипсета, версия 2.20, (c) forth32, 2015");
printf("\n Balong-chipset emergency USB loader, version 2.20, (c) forth32, 2015\n");
printf("\n English Version (c) robertzaage, 2022");
#ifdef WIN32
printf("\n Порт для Windows 32bit (c) rust3028, 2016");
printf("\n Windows Port 32bit (c) rust3028, 2016");
#endif
if (optind>=argc) {
printf("\n - Не указано имя файла для загрузки\n");
printf("\n - File to upload is not specified\n");
return;
}
}
ldr=fopen(argv[optind],"rb");
if (ldr == 0) {
printf("\n Ошибка открытия %s",argv[optind]);
printf("\n Opening error %s",argv[optind]);
return;
}
// Прверяем сигнатуру usloader
// Checking the usloader signature
fread(&i,1,4,ldr);
if (i != 0x20000) {
printf("\n Файл %s не является загрузчиком usbloader\n",argv[optind]);
printf("\n File %s is not a usbloader\n",argv[optind]);
return;
}
}
fseek(ldr,36,SEEK_SET); // начало описателей блоков для загрузки
fseek(ldr,36,SEEK_SET); // beginning of block descriptors to load
// Разбираем заголовок
// parsing the header
fread(&blk[0],1,16,ldr); // raminit
fread(&blk[1],1,16,ldr); // usbldr
//---------------------------------------------------------------------
// Чтение компонентов в память
// reading components into memory
for(bl=0;bl<2;bl++) {
// выделяем память под полный образ раздела
// allocate memory for the full image of the partition
blk[bl].pbuf=(char*)malloc(blk[bl].size);
// читаем образ раздела в память
// read partition image into memory
fseek(ldr,blk[bl].offset,SEEK_SET);
res=fread(blk[bl].pbuf,1,blk[bl].size,ldr);
if (res != blk[bl].size) {
printf("\n Неожиданный конец файла: прочитано %i ожидалось %i\n",res,blk[bl].size);
printf("\n Unexpected end of file: read %i expected %i\n",res,blk[bl].size);
return;
}
if (bl == 0) continue; // для raminit более ничего делать не надо
if (bl == 0) continue; // nothing more needs to be done for raminit
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// fastboot-патч
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// fastboot patch
if (fbflag) {
koff=locate_kernel(blk[bl].pbuf,blk[bl].size);
if (koff != 0) {
blk[bl].pbuf[koff]=0x55; // патч сигнатуры
blk[bl].size=koff+8; // обрезаем раздел до начала ядра
blk[bl].pbuf[koff]=0x55; // patch the signature
blk[bl].size=koff+8; // trim the partition to the start of the kernel
}
else {
printf("\n В загрузчике нет ANDROID-компонента - fastboot-загрузка невозможна\n");
printf("\n There is no ANDROID component in the loader - fastboot-loading is not possible.\n");
exit(0);
}
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Ищем таблицу разделов в загрузчике
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// look for the partition table in the boot loader
ptoff=find_ptable_ram(blk[bl].pbuf,blk[bl].size);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// патч таблицы разделов
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// patch partition table
if (tflag) {
pt=fopen(ptfile,"rb");
if (pt == 0) {
printf("\n Не найден файл %s - замена таблицы разделов невозможна\n",ptfile);
if (pt == 0) {
printf("\n File %s is not found - partition table cannot be replaced\n",ptfile);
return;
}
}
fread(ptbuf,1,2048,pt);
fclose(pt);
if (memcmp(headmagic,ptbuf,sizeof(headmagic)) != 0) {
printf("\n Файл %s не явлется таблицей разделов\n",ptfile);
printf("\n The file %s is not a partition table\n",ptfile);
return;
}
}
if (ptoff == 0) {
printf("\n В загрузчике не найдена таблица разделов - замена невозможна");
printf("\n No partition table found in loader - cannot be replaced");
return;
}
memcpy(blk[bl].pbuf+ptoff,ptbuf,2048);
}
ptable=(struct ptable_t*)(blk[bl].pbuf+ptoff);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Патч файловых флагов
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// patch file flags
for(i=0;i<41;i++) {
if (fileflag[i]) {
ptable->part[i].nproperty |= 1;
}
}
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Вывод таблицы разделов
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// output partition table
if (mflag) {
if (ptoff == 0) {
printf("\n Таблица разделов не найдена - вывод карты невозможен\n");
printf("\n Partition table not found - mapping output not possible\n");
return;
}
show_map(*ptable);
return;
}
// Патч erase-процедуры на предмет игнорировани бедблоков
// patch the erase procedure to ignore deadlocks
if (bflag) {
res=perasebad(blk[bl].pbuf, blk[bl].size);
if (res == 0) {
printf("\n! Не найдена сигнатура isbad - загрузка невозможна\n");
if (res == 0) {
printf("\n! No isbad signature found - cannot load\n");
return;
}
}
}
// Удаление процедуры flash_eraseall
// removing the flash_eraseall procedure
if (!cflag) {
res = pv7r1(blk[bl].pbuf, blk[bl].size);
if (res == 0)
@ -502,9 +502,9 @@ for(bl=0;bl<2;bl++) {
res = pv7r22_2(blk[bl].pbuf, blk[bl].size);
if (res == 0)
res = pv7r22_3(blk[bl].pbuf, blk[bl].size);
if (res != 0) printf("\n\n * Удалена процедура flash_eraseall по смещению %08x", blk[bl].offset + res);
if (res != 0) printf("\n\n * Removed flash_eraseall procedure at offset %08x", blk[bl].offset + res);
else {
printf("\n Процедура eraseall не найдена в загрузчике - используйте ключ -с для загрузки без патча!\n");
printf("\n Procedure eraseall not found in the bootloader - use key -s to boot without patch!\n");
return;
}
}
@ -516,28 +516,27 @@ for(bl=0;bl<2;bl++) {
#ifdef WIN32
if (*devname == '\0')
{
printf("\n\nПоиск порта аварийной загрузки...\n");
printf("\n\nSearching for the emergency loading port...\n");
if (find_port(&port_no, port_name) == 0)
{
sprintf(devname, "%d", port_no);
printf("Порт: \"%s\"\n", port_name);
printf("Port: \"%s\"\n", port_name);
}
else
{
printf("Порт не обнаружен!\n");
printf("No port found!\n");
return;
}
}
#endif
if (!open_port(devname)) {
printf("\n Последовательный порт не открывается\n");
printf("\n Can't open serial port\n");
return;
}
}
// Проверяем загрузочный порт
// Check the boot port
c=0;
#ifndef WIN32
write(siofd,"A",1);
@ -549,66 +548,63 @@ res=read(siofd,&c,1);
ReadFile(hSerial, &c, 1, &bytes_read, NULL);
#endif
if (c != 0x55) {
printf("\n ! Порт не находится в режиме USB Boot\n");
printf("\n! Port is not in USB-Boot mode\n");
return;
}
}
//----------------------------------
// главный цикл загрузки - загружаем все блоки, найденные в заголовке
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// main loading cycle - load all the blocks found in the header
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
printf("\n\n Компонент Адрес Размер %%загрузки\n------------------------------------------\n");
printf("\n\n Component Address Size %% loaded\n------------------------------------------\n");
for(bl=0;bl<2;bl++) {
datasize=1024;
pktcount=1;
// фрмируем пакет начала блока
// create a package of the beginning of the block
*((unsigned int*)&cmdhead[4])=htonl(blk[bl].size);
*((unsigned int*)&cmdhead[8])=htonl(blk[bl].adr);
cmdhead[3]=blk[bl].lmode;
// отправляем пакет начала блока
// send a block start packet
res=sendcmd(cmdhead,14);
if (!res) {
printf("\nМодем отверг пакет заголовка\n");
printf("\nModem rejected the header packet\n");
return;
}
}
// ---------- Цикл поблочной загрузки данных ---------------------
// ---------- Block-by-block data loading cycle ------------
for(adr=0;adr<blk[bl].size;adr+=1024) {
// формируем размер последнего загружаемого пакета
if ((adr+1024)>=blk[bl].size) datasize=blk[bl].size-adr;
// get the size of the last downloaded packet
if ((adr+1024)>=blk[bl].size) datasize=blk[bl].size-adr;
printf("\r %s %08x %8i %i%%",bl?"usbboot":"raminit",blk[bl].adr,blk[bl].size,(adr+datasize)*100/blk[bl].size);
printf("\r %s %08x %8i %i%%",bl?"usbboot":"raminit",blk[bl].adr,blk[bl].size,(adr+datasize)*100/blk[bl].size);
// готовим пакет данных
// prepare the data package
cmddata[1]=pktcount;
cmddata[2]=(~pktcount)&0xff;
memcpy(cmddata+3,blk[bl].pbuf+adr,datasize);
pktcount++;
if (!sendcmd(cmddata,datasize+5)) {
printf("\nМодем отверг пакет данных");
printf("\nModem rejected the data packet");
return;
}
}
}
free(blk[bl].pbuf);
// Фрмируем пакет конца данных
// prepare an end-of-data packet
cmdeod[1]=pktcount;
cmdeod[2]=(~pktcount)&0xff;
if (!sendcmd(cmdeod,5)) {
printf("\nМодем отверг пакет конца данных");
printf("\nModem rejected the end of data packet");
}
printf("\n");
}
printf("\n Загрузка окончена\n");
printf("\n");
}
printf("\n Loading finished!\n");
}

@ -18,7 +18,7 @@
//#######################################################################################################
void main(int argc, char* argv[]) {
FILE* in;
FILE* out;
uint8_t* buf;
@ -28,18 +28,17 @@ uint8_t outfilename[100];
int oflag=0,bflag=0;
uint32_t res;
// Разбор командной строки
// parsing command line
while ((opt = getopt(argc, argv, "o:bh")) != -1) {
switch (opt) {
case 'h':
printf("\n Программа для автоматического патча загрузчиков платформ Balong V7\n\n\
%s [ключи] <файл загрузчика usbloader>\n\n\
Допустимы следующие ключи:\n\n\
-o file - имя выходного файла. По умолчанию производится только проверка возможности патча\n\
-b - добавить патч, отключающий проверку дефектных блоков\n\
case 'h':
printf("\n Program for automatic patching of Balong V7 bootloaders\n\n\
%s [options] <usbloader file>\n\n\
Following options are allowed:\n\n\
-o file - Name of the output file (by default, only a patch test is performed)\n\
-b - Add a patch that disables checking of defective blocks\n\
\n",argv[0]);
return;
@ -51,33 +50,34 @@ printf("\n Программа для автоматического патча
case 'b':
bflag=1;
break;
case '?':
case ':':
case ':':
return;
}
}
}
printf("\n Программа автоматической модификации загрузчиков Balong V7, (c) forth32");
printf("\n Program for automatic modification of Balong V7 loaders, (c) forth32");
printf("\n English Version (c) robertzaage, 2022");
if (optind>=argc) {
printf("\n - Не указано имя файла для загрузки\n - Для подсказки укажите ключ -h\n");
if (optind>=argc) {
printf("\n - Name of the file to load is not specified\n - add -h option for help\n");
return;
}
}
in=fopen(argv[optind],"rb");
if (in == 0) {
printf("\n Ошибка открытия файла %s",argv[optind]);
printf("\n Can't open file %s",argv[optind]);
return;
}
// определяем размер файла
// determine file size
fseek(in,0,SEEK_END);
fsize=ftell(in);
rewind(in);
// выделяем буфер и читаем туда весь файл
// select a buffer and read the whole file there
buf=malloc(fsize);
fread(buf,1,fsize,in);
fclose(in);
@ -86,49 +86,49 @@ fclose(in);
res=pv7r1(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R1 по смещению %08x",res);
printf("\n* V7R1 type signature found at offset %08x",res);
goto endpatch;
}
}
res=pv7r2(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R2 по смещению %08x",res);
printf("\n* V7R2 type signature found at offset %08x",res);
goto endpatch;
}
}
res=pv7r11(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R11 по смещению %08x",res);
printf("\n* V7R11 type signature found at offset %08x",res);
goto endpatch;
}
}
res=pv7r22(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R22 по смещению %08x",res);
printf("\n* V7R22 type signature found at offset %08x",res);
goto endpatch;
}
}
res=pv7r22_2(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R22_2 по смещению %08x",res);
printf("\n* V7R22_2 type signature found at offset %08x",res);
goto endpatch;
}
res=pv7r22_3(buf, fsize);
if (res != 0) {
printf("\n* Найдена сигнатура типа V7R22_3 по смещению %08x",res);
printf("\n* V7R22_3 type signature found at offset %08x",res);
goto endpatch;
}
printf("\n! Сигнатура eraseall-патча не найдена");
printf("\n! Patch eraseall signature not found");
//==================================================================================
endpatch:
if (bflag) {
res=perasebad(buf, fsize);
if (res != 0) printf("\n* Найдена сигнатура isbad по смещению %08x",res);
else printf("\n! Сигнатура isbad не найдена");
if (res != 0) printf("\n* Found isbad signature at offset %08x",res);
else printf("\n! Signature isbad not found");
}
if (oflag) {
@ -137,10 +137,8 @@ if (oflag) {
fwrite(buf,1,fsize,out);
fclose(out);
}
else printf("\n Ошибка открытия выходного файла %s",outfilename);
else printf("\n Error opening output file %s",outfilename);
}
free(buf);
printf("\n");
}

@ -11,11 +11,11 @@
#include "parts.h"
// сигнатура заголовка таблицы
const uint8_t headmagic[16]={0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80};
// header signature table
const uint8_t headmagic[16]={0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80};
//*********************************************
//* Поиск таблицы разделов в загрузчике
//* Search for the partition table in the loader
//*********************************************
uint32_t find_ptable(FILE* ldr) {
@ -29,16 +29,16 @@ while (fread(rbuf,1,16,ldr) == 16) {
}
return 0;
}
//*********************************************
//* Печать таблицы разделов
//* Printing the partition table
//*********************************************
void show_map(struct ptable_t ptable) {
int pnum;
printf("\n Версия таблицы разделов: %16.16s",ptable.version);
printf("\n Версия прошивки: %16.16s\n",ptable.product);
printf("\n Partition table version: %16.16s",ptable.version);
printf("\n Firmware version: %16.16s\n",ptable.product);
printf("\n ## ----- NAME ----- start len loadsize loadaddr entry flags type count\n------------------------------------------------------------------------------------------");
@ -64,11 +64,11 @@ printf("\n");
}
//*********************************************
//* Поиск таблицы разделов в памяти
//* Search for partition table in memory
//*********************************************
uint32_t find_ptable_ram(char* buf, uint32_t size) {
// сигнатура заголовка таблицы
// header signature table
uint32_t off;
for(off=0;off<(size-16);off+=4) {
@ -76,4 +76,3 @@ for(off=0;off<(size-16);off+=4) {
}
return 0;
}

@ -1,18 +1,18 @@
// Структура описателя раздела
// partition descriptor structure
struct ptable_line{
char name[16];
unsigned start;
unsigned lsize;
unsigned length;
unsigned loadaddr;
unsigned entry;
unsigned type;
unsigned nproperty; // флаги раздела
unsigned loadaddr;
unsigned entry;
unsigned type;
unsigned nproperty; // partition flags
unsigned count;
};
// Полная структура страницы таблицы разделов
// pull page structure from partition table
struct ptable_t {
uint8_t head[16];
uint8_t version[16];
@ -21,7 +21,7 @@ struct ptable_t {
uint8_t tail[32];
};
// сигнатура заголовка таблицы
// header signature table
extern const uint8_t headmagic[16];
uint32_t find_ptable(FILE* ldr);

@ -4,21 +4,21 @@
#include <stdlib.h>
//***********************************************************************
//* Поиск сигнатуры и наложение патча
//* Find the signature and apply the patch
//*
//* ptype=0 - nop-патч
//* ptype=1 - br-патч
//* ptype=0 - nop-patch
//* ptype=1 - br-patch
//***********************************************************************
uint32_t patch(struct defpatch fp, uint8_t* buf, uint32_t fsize, uint32_t ptype) {
// накладываемый патч - mov r0,#0
const char nop0[4]={0, 0, 0xa0, 0xe3};
// overlapping patch - mov r0,#0
const char nop0[4]={0, 0, 0xa0, 0xe3};
uint32_t i;
uint8_t c;
for(i=8;i<(fsize-60);i+=4) {
if (memcmp(buf+i,fp.sig, fp.sigsize) == 0) {
// найдена сигнатура - накладываем патч и уходим
// a signature is found - apply the patch and exit
switch (ptype) {
case 0:
memcpy(buf+i+fp.sigsize+fp.poffset,nop0,4);
@ -35,17 +35,17 @@ for(i=8;i<(fsize-60);i+=4) {
}
}
}
// сигнатрура не найдена
// no signature found
return 0;
}
//**********************************************
// Описатели патчей
// Patch Descriptors
//**********************************************
const char sigburn_v7r22[]={
0x12, 0x3B, 0xA0, 0xE3, 0x4A, 0x35, 0x4A, 0xE3, 0x00, 0x20, 0xA0, 0xE3,
0x78, 0x20, 0xC3, 0xE5, 0x79, 0x20, 0xC3, 0xE5, 0x7A, 0x20, 0xC3, 0xE5,
0x78, 0x20, 0xC3, 0xE5, 0x79, 0x20, 0xC3, 0xE5, 0x7A, 0x20, 0xC3, 0xE5,
0x7B, 0x20, 0xC3, 0xE5, 0x00, 0x00, 0xA0, 0xE3};
const char sigburn_v7r22_2[]={
@ -57,35 +57,35 @@ const char sigburn_v7r22_3[]={
0x18, 0x30, 0x94, 0xE5, 0x14, 0x30, 0x8D, 0xE5};
const char sigburn_v7r11[]={
0x00, 0x00, 0x50, 0xE3, 0x70, 0x80, 0xBD, 0x08, 0x00, 0x30, 0xA0, 0xE3,
0x4E, 0x26, 0x04, 0xE3, 0xE0, 0x3F, 0x44, 0xE3, 0x55, 0x22, 0x44, 0xE3,
0x4C, 0x01, 0x9F, 0xE5, 0x4E, 0xC6, 0x04, 0xE3, 0x48, 0x41, 0x9F, 0xE5,
0x02, 0x10, 0xA0, 0xE1, 0x4C, 0xC4, 0x44, 0xE3, 0x5C, 0x23, 0x83, 0xE5,
0x00, 0x00, 0x50, 0xE3, 0x70, 0x80, 0xBD, 0x08, 0x00, 0x30, 0xA0, 0xE3,
0x4E, 0x26, 0x04, 0xE3, 0xE0, 0x3F, 0x44, 0xE3, 0x55, 0x22, 0x44, 0xE3,
0x4C, 0x01, 0x9F, 0xE5, 0x4E, 0xC6, 0x04, 0xE3, 0x48, 0x41, 0x9F, 0xE5,
0x02, 0x10, 0xA0, 0xE1, 0x4C, 0xC4, 0x44, 0xE3, 0x5C, 0x23, 0x83, 0xE5,
0x00, 0x00, 0x8F, 0xE0, 0x40, 0xC3, 0x83, 0xE5};
const char sigburn_v7r2[]={
const char sigburn_v7r2[]={
0x00, 0x30, 0xA0, 0xE3, 0x9A, 0x3F, 0x07, 0xEE, 0xFF, 0x2F, 0x0F, 0xE3,
0xE1, 0x2F, 0x44, 0xE3, 0x07, 0x30, 0x02, 0xE5, 0x9A, 0x3F, 0x07, 0xEE,
0x00, 0x40, 0xA0, 0xE3, 0xE0, 0x4F, 0x44, 0xE3, 0x4E, 0x36, 0x04, 0xE3,
0xE1, 0x2F, 0x44, 0xE3, 0x07, 0x30, 0x02, 0xE5, 0x9A, 0x3F, 0x07, 0xEE,
0x00, 0x40, 0xA0, 0xE3, 0xE0, 0x4F, 0x44, 0xE3, 0x4E, 0x36, 0x04, 0xE3,
0x4C, 0x34, 0x44, 0xE3, 0x30, 0x33, 0x84, 0xE5};
const char sigburn_v7r1[]={
0x3D, 0xE2, 0xE0, 0xE3, 0x00, 0xE0, 0x9E, 0xE5, 0x5C, 0xC3, 0x9F, 0xE5,
const char sigburn_v7r1[]={
0x3D, 0xE2, 0xE0, 0xE3, 0x00, 0xE0, 0x9E, 0xE5, 0x5C, 0xC3, 0x9F, 0xE5,
0x0C, 0x00, 0x5E, 0xE1, 0x00, 0x00, 0x00, 0x0A};
const char sigbad[]={0x04, 0x10, 0x8D, 0xE2, 0x04, 0x00, 0xA0, 0xE1};
struct defpatch patch_v7r22={sigburn_v7r22, sizeof(sigburn_v7r22), -37};
struct defpatch patch_v7r22_2={sigburn_v7r22_2, sizeof(sigburn_v7r22_2), 0};
struct defpatch patch_v7r22_3={sigburn_v7r22_3, sizeof(sigburn_v7r22_3), 0};
struct defpatch patch_v7r11={sigburn_v7r11, sizeof(sigburn_v7r11), 4};
struct defpatch patch_v7r2={sigburn_v7r2, sizeof(sigburn_v7r2), 16};
struct defpatch patch_v7r1={sigburn_v7r1, sizeof(sigburn_v7r1), 0};
struct defpatch patch_erasebad={sigbad, sizeof(sigbad), 0};
struct defpatch patch_v7r11={sigburn_v7r11, sizeof(sigburn_v7r11), 4};
struct defpatch patch_v7r2={sigburn_v7r2, sizeof(sigburn_v7r2), 16};
struct defpatch patch_v7r1={sigburn_v7r1, sizeof(sigburn_v7r1), 0};
struct defpatch patch_erasebad={sigbad, sizeof(sigbad), 0};
//****************************************************
//* Процедуры патча под разные чипсеты и задачи
//* Patch procedures for different chipsets and tasks
//****************************************************
uint32_t pv7r2 (uint8_t* buf, uint32_t fsize) { return patch(patch_v7r2, buf, fsize,0); }
@ -95,4 +95,3 @@ uint32_t pv7r22 (uint8_t* buf, uint32_t fsize) { return patch(patch_v7r22, buf,
uint32_t pv7r22_2 (uint8_t* buf, uint32_t fsize) { return patch(patch_v7r22_2, buf, fsize,0); }
uint32_t pv7r22_3 (uint8_t* buf, uint32_t fsize) { return patch(patch_v7r22_3, buf, fsize,0); }
uint32_t perasebad (uint8_t* buf, uint32_t fsize) { return patch(patch_erasebad, buf, fsize,0); }

@ -1,6 +1,5 @@
// Программа для замены таблицы разделов в загрузчике usbloader
//
//
// Program to replace the partition table in the usbloader
//
#include <stdio.h>
#include <stdint.h>
@ -18,13 +17,12 @@
#include "parts.h"
//############################################################################################################3
void main(int argc, char* argv[]) {
int opt;
int opt;
int mflag=0;
char ptfile[100];
int rflag=0,xflag=0;
@ -38,64 +36,63 @@ FILE* in;
while ((opt = getopt(argc, argv, "mr:hx")) != -1) {
switch (opt) {
case 'h':
printf("\n Утилита для замены таблицы разделов в загрузчиках usbloader\
case 'h':
printf("\n Utility for partition table replacement in usbloaders\
\n\n\
%s [ключи] <имя файла usbloader>\n\n\
Допустимы следующие ключи:\n\n\
-m - показать текущую карту разделов в usbloader\n\
-x - извлечь текущую карту в файл ptable.bin\n\
-r <file>- заменить карту разделов на карту из указанного файла\n\
%s [options] <file name usbloader>\n\n\
Following options are allowed:\n\n\
-m - Show current partition map in usbloader\n\
-x - Extract current partition map to ptable.bin file\n\
-r <file> - Replace current partition map with map from specified file\n\
\n",argv[0]);
return;
case 'm':
mflag=1;
break;
case 'x':
xflag=1;
break;
case 'r':
rflag=1;
strcpy (ptfile,optarg);
break;
case '?':
case ':':
case ':':
return;
}
}
}
}
if (optind>=argc) {
printf("\n - Не указано имя файла загрузчика\n");
printf("\n - Loader file name is not specified\n");
return;
}
}
ldr=fopen(argv[optind],"r+b");
if (ldr == 0) {
printf("\n Ошибка открытия файла %s\n",argv[optind]);
printf("\n Can't open file %s\n",argv[optind]);
return;
}
// Ищем таблицу разделов в файле загрузчика
// searching for the partition table in the loader file
ptaddr=find_ptable(ldr);
if (ptaddr == 0) {
printf("\n Таблица разделов в загрузчике не найдена\n");
return ;
}
// читаем текущую таблицу
// read the current table
fread(&ptable,sizeof(ptable),1,ldr);
if (xflag) {
out=fopen("ptable.bin","wb");
fwrite(&ptable,sizeof(ptable),1,out);
fclose(out);
}
}
if (mflag) {
show_map(ptable);
@ -103,24 +100,23 @@ if (mflag) {
if (mflag | xflag) return;
if (rflag) {
if (rflag) {
in=fopen(ptfile,"rb");
if (in == 0) {
printf("\n Ошибка открытия файла %s",ptfile);
printf("\n Can't open file %s",ptfile);
return;
}
fread(&ptable,sizeof(ptable),1,in);
fclose(in);
// проверяем файл
// check the file
if (memcmp(ptable.head,headmagic,16) != 0) {
printf("\n Входной файл не является таблицей разделов\n");
printf("\n Input file is not a partition table\n");
return;
}
fseek(ldr,ptaddr,SEEK_SET);
fwrite(&ptable,sizeof(ptable),1,ldr);
fclose(ldr);
}
}
}

@ -1,6 +1,5 @@
// Программа для замены таблицы разделов в загрузчике usbloader
//
//
// Program to replace the partition table in the usbloader
//
#include <stdio.h>
#include <stdint.h>
@ -18,35 +17,32 @@
#include "parts.h"
//############################################################################################################3
void main(int argc, char* argv[]) {
struct ptable_t ptable;
FILE* in;
if (argc != 2) {
printf("\n - Не указано имя файла с таблицей разделов\n");
printf("\n - Partition table file name is not specified\n");
return;
}
}
in=fopen(argv[optind],"r+b");
if (in == 0) {
printf("\n Ошибка открытия файла %s\n",argv[optind]);
printf("\n Can't open file %s\n",argv[optind]);
return;
}
// читаем текущую таблицу
// read current table
fread(&ptable,sizeof(ptable),1,in);
if (strncmp(ptable.head, "pTableHead", 16) != 0) {
printf("\n Файл не является таблицей разделов\n");
printf("\n File is not a partition table\n");
return ;
}
show_map(ptable);
}

Loading…
Cancel
Save