Initial to English translated release

master
Robert Zaage 2 years ago
parent c0ebd14883
commit 7f807afcea

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

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

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

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

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

@ -4,21 +4,21 @@
#include <stdlib.h> #include <stdlib.h>
//*********************************************************************** //***********************************************************************
//* Поиск сигнатуры и наложение патча //* Find the signature and apply the patch
//* //*
//* ptype=0 - nop-патч //* ptype=0 - nop-patch
//* ptype=1 - br-патч //* ptype=1 - br-patch
//*********************************************************************** //***********************************************************************
uint32_t patch(struct defpatch fp, uint8_t* buf, uint32_t fsize, uint32_t ptype) { uint32_t patch(struct defpatch fp, uint8_t* buf, uint32_t fsize, uint32_t ptype) {
// накладываемый патч - mov r0,#0 // overlapping patch - mov r0,#0
const char nop0[4]={0, 0, 0xa0, 0xe3}; const char nop0[4]={0, 0, 0xa0, 0xe3};
uint32_t i; uint32_t i;
uint8_t c; uint8_t c;
for(i=8;i<(fsize-60);i+=4) { for(i=8;i<(fsize-60);i+=4) {
if (memcmp(buf+i,fp.sig, fp.sigsize) == 0) { if (memcmp(buf+i,fp.sig, fp.sigsize) == 0) {
// найдена сигнатура - накладываем патч и уходим // a signature is found - apply the patch and exit
switch (ptype) { switch (ptype) {
case 0: case 0:
memcpy(buf+i+fp.sigsize+fp.poffset,nop0,4); 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; return 0;
} }
//********************************************** //**********************************************
// Описатели патчей // Patch Descriptors
//********************************************** //**********************************************
const char sigburn_v7r22[]={ const char sigburn_v7r22[]={
0x12, 0x3B, 0xA0, 0xE3, 0x4A, 0x35, 0x4A, 0xE3, 0x00, 0x20, 0xA0, 0xE3, 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}; 0x7B, 0x20, 0xC3, 0xE5, 0x00, 0x00, 0xA0, 0xE3};
const char sigburn_v7r22_2[]={ const char sigburn_v7r22_2[]={
@ -57,35 +57,35 @@ const char sigburn_v7r22_3[]={
0x18, 0x30, 0x94, 0xE5, 0x14, 0x30, 0x8D, 0xE5}; 0x18, 0x30, 0x94, 0xE5, 0x14, 0x30, 0x8D, 0xE5};
const char sigburn_v7r11[]={ const char sigburn_v7r11[]={
0x00, 0x00, 0x50, 0xE3, 0x70, 0x80, 0xBD, 0x08, 0x00, 0x30, 0xA0, 0xE3, 0x00, 0x00, 0x50, 0xE3, 0x70, 0x80, 0xBD, 0x08, 0x00, 0x30, 0xA0, 0xE3,
0x4E, 0x26, 0x04, 0xE3, 0xE0, 0x3F, 0x44, 0xE3, 0x55, 0x22, 0x44, 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, 0x4C, 0x01, 0x9F, 0xE5, 0x4E, 0xC6, 0x04, 0xE3, 0x48, 0x41, 0x9F, 0xE5,
0x02, 0x10, 0xA0, 0xE1, 0x4C, 0xC4, 0x44, 0xE3, 0x5C, 0x23, 0x83, 0xE5, 0x02, 0x10, 0xA0, 0xE1, 0x4C, 0xC4, 0x44, 0xE3, 0x5C, 0x23, 0x83, 0xE5,
0x00, 0x00, 0x8F, 0xE0, 0x40, 0xC3, 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, 0x00, 0x30, 0xA0, 0xE3, 0x9A, 0x3F, 0x07, 0xEE, 0xFF, 0x2F, 0x0F, 0xE3,
0xE1, 0x2F, 0x44, 0xE3, 0x07, 0x30, 0x02, 0xE5, 0x9A, 0x3F, 0x07, 0xEE, 0xE1, 0x2F, 0x44, 0xE3, 0x07, 0x30, 0x02, 0xE5, 0x9A, 0x3F, 0x07, 0xEE,
0x00, 0x40, 0xA0, 0xE3, 0xE0, 0x4F, 0x44, 0xE3, 0x4E, 0x36, 0x04, 0xE3, 0x00, 0x40, 0xA0, 0xE3, 0xE0, 0x4F, 0x44, 0xE3, 0x4E, 0x36, 0x04, 0xE3,
0x4C, 0x34, 0x44, 0xE3, 0x30, 0x33, 0x84, 0xE5}; 0x4C, 0x34, 0x44, 0xE3, 0x30, 0x33, 0x84, 0xE5};
const char sigburn_v7r1[]={ const char sigburn_v7r1[]={
0x3D, 0xE2, 0xE0, 0xE3, 0x00, 0xE0, 0x9E, 0xE5, 0x5C, 0xC3, 0x9F, 0xE5, 0x3D, 0xE2, 0xE0, 0xE3, 0x00, 0xE0, 0x9E, 0xE5, 0x5C, 0xC3, 0x9F, 0xE5,
0x0C, 0x00, 0x5E, 0xE1, 0x00, 0x00, 0x00, 0x0A}; 0x0C, 0x00, 0x5E, 0xE1, 0x00, 0x00, 0x00, 0x0A};
const char sigbad[]={0x04, 0x10, 0x8D, 0xE2, 0x04, 0x00, 0xA0, 0xE1}; 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={sigburn_v7r22, sizeof(sigburn_v7r22), -37};
struct defpatch patch_v7r22_2={sigburn_v7r22_2, sizeof(sigburn_v7r22_2), 0}; 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_v7r22_3={sigburn_v7r22_3, sizeof(sigburn_v7r22_3), 0};
struct defpatch patch_v7r11={sigburn_v7r11, sizeof(sigburn_v7r11), 4}; struct defpatch patch_v7r11={sigburn_v7r11, sizeof(sigburn_v7r11), 4};
struct defpatch patch_v7r2={sigburn_v7r2, sizeof(sigburn_v7r2), 16}; struct defpatch patch_v7r2={sigburn_v7r2, sizeof(sigburn_v7r2), 16};
struct defpatch patch_v7r1={sigburn_v7r1, sizeof(sigburn_v7r1), 0}; struct defpatch patch_v7r1={sigburn_v7r1, sizeof(sigburn_v7r1), 0};
struct defpatch patch_erasebad={sigbad, sizeof(sigbad), 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); } 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_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 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); } 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 <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -18,13 +17,12 @@
#include "parts.h" #include "parts.h"
//############################################################################################################3 //############################################################################################################3
void main(int argc, char* argv[]) { void main(int argc, char* argv[]) {
int opt; int opt;
int mflag=0; int mflag=0;
char ptfile[100]; char ptfile[100];
int rflag=0,xflag=0; int rflag=0,xflag=0;
@ -38,64 +36,63 @@ FILE* in;
while ((opt = getopt(argc, argv, "mr:hx")) != -1) { while ((opt = getopt(argc, argv, "mr:hx")) != -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
printf("\n Утилита для замены таблицы разделов в загрузчиках usbloader\ printf("\n Utility for partition table replacement in usbloaders\
\n\n\ \n\n\
%s [ключи] <имя файла usbloader>\n\n\ %s [options] <file name usbloader>\n\n\
Допустимы следующие ключи:\n\n\ Following options are allowed:\n\n\
-m - показать текущую карту разделов в usbloader\n\ -m - Show current partition map in usbloader\n\
-x - извлечь текущую карту в файл ptable.bin\n\ -x - Extract current partition map to ptable.bin file\n\
-r <file>- заменить карту разделов на карту из указанного файла\n\ -r <file> - Replace current partition map with map from specified file\n\
\n",argv[0]); \n",argv[0]);
return; return;
case 'm': case 'm':
mflag=1; mflag=1;
break; break;
case 'x': case 'x':
xflag=1; xflag=1;
break; break;
case 'r': case 'r':
rflag=1; rflag=1;
strcpy (ptfile,optarg); strcpy (ptfile,optarg);
break; break;
case '?': case '?':
case ':': case ':':
return; return;
} }
} }
if (optind>=argc) { if (optind>=argc) {
printf("\n - Не указано имя файла загрузчика\n"); printf("\n - Loader file name is not specified\n");
return; return;
} }
ldr=fopen(argv[optind],"r+b"); ldr=fopen(argv[optind],"r+b");
if (ldr == 0) { if (ldr == 0) {
printf("\n Ошибка открытия файла %s\n",argv[optind]); printf("\n Can't open file %s\n",argv[optind]);
return; return;
} }
// searching for the partition table in the loader file
// Ищем таблицу разделов в файле загрузчика
ptaddr=find_ptable(ldr); ptaddr=find_ptable(ldr);
if (ptaddr == 0) { if (ptaddr == 0) {
printf("\n Таблица разделов в загрузчике не найдена\n"); printf("\n Таблица разделов в загрузчике не найдена\n");
return ; return ;
} }
// читаем текущую таблицу // read the current table
fread(&ptable,sizeof(ptable),1,ldr); fread(&ptable,sizeof(ptable),1,ldr);
if (xflag) { if (xflag) {
out=fopen("ptable.bin","wb"); out=fopen("ptable.bin","wb");
fwrite(&ptable,sizeof(ptable),1,out); fwrite(&ptable,sizeof(ptable),1,out);
fclose(out); fclose(out);
} }
if (mflag) { if (mflag) {
show_map(ptable); show_map(ptable);
@ -103,24 +100,23 @@ if (mflag) {
if (mflag | xflag) return; if (mflag | xflag) return;
if (rflag) {
if (rflag) {
in=fopen(ptfile,"rb"); in=fopen(ptfile,"rb");
if (in == 0) { if (in == 0) {
printf("\n Ошибка открытия файла %s",ptfile); printf("\n Can't open file %s",ptfile);
return; return;
} }
fread(&ptable,sizeof(ptable),1,in); fread(&ptable,sizeof(ptable),1,in);
fclose(in); fclose(in);
// проверяем файл // check the file
if (memcmp(ptable.head,headmagic,16) != 0) { if (memcmp(ptable.head,headmagic,16) != 0) {
printf("\n Входной файл не является таблицей разделов\n"); printf("\n Input file is not a partition table\n");
return; return;
} }
fseek(ldr,ptaddr,SEEK_SET); fseek(ldr,ptaddr,SEEK_SET);
fwrite(&ptable,sizeof(ptable),1,ldr); fwrite(&ptable,sizeof(ptable),1,ldr);
fclose(ldr); fclose(ldr);
} }
} }

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

Loading…
Cancel
Save