@ -1,4 +1,4 @@
// Процедуры работы с таблицей разделов
// Partition table procedures
# include <stdio.h>
# include <stdint.h>
@ -20,7 +20,7 @@
int32_t lzma_decode ( uint8_t * inbuf , uint32_t fsize , uint8_t * outbuf ) ;
//******************************************************
//* поиск символического имени раздела по е г о коду
//* Search for a symbolic partition name by its code
//******************************************************
void find_pname ( unsigned int id , unsigned char * pname ) {
@ -29,10 +29,10 @@ unsigned int j;
struct {
char name [ 20 ] ;
int code ;
} pcodes [ ] = {
{ " M3Boot " , 0x20000 } ,
{ " M3Boot-ptable " , 0x10000 } ,
{ " M3Boot_R11 " , 0x200000 } ,
} pcodes [ ] = {
{ " M3Boot " , 0x20000 } ,
{ " M3Boot-ptable " , 0x10000 } ,
{ " M3Boot_R11 " , 0x200000 } ,
{ " Ptable " , 0x10000 } ,
{ " Ptable_ext_A " , 0x480000 } ,
{ " Ptable_ext_B " , 0x490000 } ,
@ -52,9 +52,9 @@ struct {
{ " Nvimg " , 0x80000 } ,
{ " System " , 0x590000 } ,
{ " System " , 0x100000 } ,
{ " APP " , 0x570000 } ,
{ " APP " , 0x5a0000 } ,
{ " APP_EXT_A " , 0x450000 } ,
{ " APP " , 0x570000 } ,
{ " APP " , 0x5a0000 } ,
{ " APP_EXT_A " , 0x450000 } ,
{ " APP_EXT_B " , 0x460000 } ,
{ " Oeminfo " , 0xa0000 } ,
{ " CDROMISO " , 0xb0000 } ,
@ -88,74 +88,71 @@ struct {
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 в тупоконечном формате
if ( pcodes [ j ] . code ! = 0 ) strcpy ( pname , pcodes [ j ] . name ) ; // name is found - copy it into the structure
else sprintf ( pname , " U%08x " , id ) ; // name not found - substitute the pseudo name Uxxxxxxxxxx in blunt-end format
}
//*******************************************************************
// Вычисление размера блока контрольных сумм раздела
// Calculation of partition checksum block size
//*******************************************************************
uint32_t crcsize ( int n ) {
return ptable [ n ] . hd . hdsize - sizeof ( struct pheader ) ;
uint32_t crcsize ( int n ) {
return ptable [ n ] . hd . hdsize - sizeof ( struct pheader ) ;
}
//*******************************************************************
// получение размера образа раздела
// Obtaining partition image size
//*******************************************************************
uint32_t psize ( int n ) {
return ptable [ n ] . hd . psize ;
uint32_t psize ( int n ) {
return ptable [ n ] . hd . psize ;
}
//*******************************************************
//* Вычисление блочной контрольной суммы заголовка
//* Header block checksum calculation
//*******************************************************
void calc_hd_crc16 ( int n ) {
void calc_hd_crc16 ( int n ) {
ptable [ n ] . hd . crc = 0 ; // очищаем старую CRC-сумму
ptable [ n ] . hd . crc = crc16 ( ( uint8_t * ) & ptable [ n ] . hd , sizeof ( struct pheader ) ) ;
ptable [ n ] . hd . crc = 0 ; // clear old CRC sum
ptable [ n ] . hd . crc = crc16 ( ( uint8_t * ) & ptable [ n ] . hd , sizeof ( struct pheader ) ) ;
}
//*******************************************************
//* Вычисление блочной контрольной суммы раздела
//* Calculating the block checksum of a partition
//*******************************************************
void calc_crc16 ( int n ) {
uint32_t csize ; // размер блока сумм в 16-битных словах
uint16_t * csblock ; // указатель на создаваемый блок
uint32_t csize ; // block size sum in 16-bit words
uint16_t * csblock ; // pointer to created block
uint32_t off , len ;
uint32_t i ;
uint32_t blocksize = ptable [ n ] . hd . blocksize ; // размер блока, охватываемого суммой
uint32_t blocksize = ptable [ n ] . hd . blocksize ; // size of the block covered by the sum
// определяем размер и создаем блок
// determine the size and create the block
csize = psize ( n ) / blocksize ;
if ( psize ( n ) % blocksize ! = 0 ) csize + + ; // Это если размер образа не кратен blocksize
if ( psize ( n ) % blocksize ! = 0 ) csize + + ; // this is if the image size is not a multiple of blocksize
csblock = ( uint16_t * ) malloc ( csize * 2 ) ;
// цикл вычисления сумм
// loop for sum calculation
for ( i = 0 ; i < csize ; i + + ) {
off = i * blocksize ; // смещение до текущего блока
off = i * blocksize ; // shift to the current block
len = blocksize ;
if ( ( ptable [ n ] . hd . psize - off ) < blocksize ) len = ptable [ n ] . hd . psize - off ; // для последнего неполного блока
if ( ( ptable [ n ] . hd . psize - off ) < blocksize ) len = ptable [ n ] . hd . psize - off ; // for the last incomplete block
csblock [ i ] = crc16 ( ptable [ n ] . pimage + off , len ) ;
}
// вписываем параметры в заголовок
if ( ptable [ n ] . csumblock ! = 0 ) free ( ptable [ n ] . csumblock ) ; // уничтожаем старый блок, если он был
}
// enter the parameters into the header
if ( ptable [ n ] . csumblock ! = 0 ) free ( ptable [ n ] . csumblock ) ; // we destroy the old block if there was one
ptable [ n ] . csumblock = csblock ;
ptable [ n ] . hd . hdsize = csize * 2 + sizeof ( struct pheader ) ;
// перевычисляем CRC заголовка
// recalculate CRC header
calc_hd_crc16 ( n ) ;
}
//*******************************************************************
//* Извлечение раздела из файла и добавление е г о в таблицу разделов
//* Extract partition from file and add it to partition table
//*
// in - входной файл прошивки
// Позиция в файле соответствует началу заголовка раздела
// * "in" is the input firmware file
// * position in file corresponds to the beginning of partition header
//*******************************************************************
void extract ( FILE * in ) {
@ -166,219 +163,210 @@ uint8_t* zbuf;
long int zlen ;
int res ;
ptable [ npart ] . zflag = 0 ;
// читаем заголовок в структуру
ptable [ npart ] . zflag = 0 ;
// read the header into the structure
ptable [ npart ] . offset = ftell ( in ) ;
fread ( & ptable [ npart ] . hd , 1 , sizeof ( struct pheader ) , in ) ; // заголовок
// Ищем символическое имя раздела по таблице
fread ( & ptable [ npart ] . hd , 1 , sizeof ( struct pheader ) , in ) ; // header
// look up the symbolic name of the partition in the table
find_pname ( ptable [ npart ] . hd . code , ptable [ npart ] . pname ) ;
// загружаем блок контрольных сумм
ptable [ npart ] . csumblock = 0 ; // пока блок не создан
crcblock = ( uint16_t * ) malloc ( crcsize ( npart ) ) ; // выделяем временную память под загружаемый блок
// load the checksum block
ptable [ npart ] . csumblock = 0 ; // until the block is created
crcblock = ( uint16_t * ) malloc ( crcsize ( npart ) ) ; // allot temporary memory for the loaded block
crcblocksize = crcsize ( npart ) ;
fread ( crcblock , 1 , crcblocksize , in ) ;
// загружаем образ раздела
// load a partition image
ptable [ npart ] . pimage = ( uint8_t * ) malloc ( psize ( npart ) ) ;
fread ( ptable [ npart ] . pimage , 1 , psize ( npart ) , in ) ;
// проверяем CRC заголовка
// check the CRC of the header
hcrc = ptable [ npart ] . hd . crc ;
ptable [ npart ] . hd . crc = 0 ; // старая CRC в рассчете не учитывается
ptable [ npart ] . hd . crc = 0 ; // check the CRC of the header
crc = crc16 ( ( uint8_t * ) & ptable [ npart ] . hd , sizeof ( struct pheader ) ) ;
if ( crc ! = hcrc ) {
printf ( " \n ! Раздел %s (%02x) - ошибка контрольной суммы заголовка " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
printf ( " \n ! Partition %s (%02x) - header checksum error " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
errflag = 1 ;
}
ptable [ npart ] . hd . crc = crc ; // восстанавливаем CRC
}
ptable [ npart ] . hd . crc = crc ; // recover CRC
// вычисляем и проверяем CRC раздела
// calculate and check the CRC of the partition
calc_crc16 ( npart ) ;
if ( crcblocksize ! = crcsize ( npart ) ) {
printf ( " \n ! Раздел %s (%02x) - неправильный размер блока контрольных сумм " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
printf ( " \n ! Partition %s (%02x) - Incorrect checksum block size " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
errflag = 1 ;
}
}
else if ( memcmp ( crcblock , ptable [ npart ] . csumblock , crcblocksize ) ! = 0 ) {
printf ( " \n ! Раздел %s (%02x) - неправильная блочная контрольная сумма " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
printf ( " \n ! Partition %s (%02x) - incorrect block checksum " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
errflag = 1 ;
}
free ( crcblock ) ;
}
free ( crcblock ) ;
ptable [ npart ] . ztype = ' ' ;
// Определение zlib-сжатия
// definition of zlib-compression
if ( ( * ( uint16_t * ) ptable [ npart ] . pimage ) = = 0xda78 ) {
ptable [ npart ] . zflag = ptable [ npart ] . hd . psize ; // сохраняем сжатый размер
ptable [ npart ] . zflag = ptable [ npart ] . hd . psize ; // keep the compressed size
zlen = 52428800 ;
zbuf = malloc ( zlen ) ; // буфер в 50М
// распаковываем образ раздела
zbuf = malloc ( zlen ) ; // buffer of 50М
// unpack the partition image
res = uncompress ( zbuf , & zlen , ptable [ npart ] . pimage , ptable [ npart ] . hd . psize ) ;
if ( res ! = Z_OK ) {
printf ( " \n ! Ошибка распаковки раздела %s (%02x)\n " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
printf ( " \n ! Error unpacking partition %s (%02x)\n " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
errflag = 1 ;
}
// создаем новый буфер образа раздела и копируем в него рапаковынные данные
// create a new partition image buffer and copy the unpacked data into it
free ( ptable [ npart ] . pimage ) ;
ptable [ npart ] . pimage = malloc ( zlen ) ;
memcpy ( ptable [ npart ] . pimage , zbuf , zlen ) ;
ptable [ npart ] . hd . psize = zlen ;
free ( zbuf ) ;
// перерассчитываем контрольные суммы
// recalculate the checksums
calc_crc16 ( npart ) ;
ptable [ npart ] . hd . crc = crc16 ( ( uint8_t * ) & ptable [ npart ] . hd , sizeof ( struct pheader ) ) ;
ptable [ npart ] . ztype = ' Z ' ;
}
// Определение lzma-сжатия
// lzma compression detection
if ( ( ptable [ npart ] . pimage [ 0 ] = = 0x5d ) & & ( * ( uint64_t * ) ( ptable [ npart ] . pimage + 5 ) = = 0xffffffffffffffff ) ) {
ptable [ npart ] . zflag = ptable [ npart ] . hd . psize ; // сохраняем сжатый размер
ptable [ npart ] . zflag = ptable [ npart ] . hd . psize ; // keep the compressed size
zlen = 100 * 1024 * 1024 ;
zbuf = malloc ( zlen ) ; // буфер в 100М
// распаковываем образ раздела
zbuf = malloc ( zlen ) ; // buffer of 100М
// unpack the partition image
zlen = lzma_decode ( ptable [ npart ] . pimage , ptable [ npart ] . hd . psize , zbuf ) ;
if ( zlen > 100 * 1024 * 1024 ) {
printf ( " \n Превышен размер буфера \n " ) ;
printf ( " \n Buffer size exceeded \n " ) ;
exit ( 1 ) ;
}
}
if ( res = = - 1 ) {
printf ( " \n ! Ошибка распаковки раздела %s (%02x)\n " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
printf ( " \n ! Error unpacking partition %s (%02x)\n " , ptable [ npart ] . pname , ptable [ npart ] . hd . code > > 16 ) ;
errflag = 1 ;
}
// создаем новый буфер образа раздела и копируем в него рапаковынные данные
// create a new partition image buffer and copy the unpacked data into it
free ( ptable [ npart ] . pimage ) ;
ptable [ npart ] . pimage = malloc ( zlen ) ;
memcpy ( ptable [ npart ] . pimage , zbuf , zlen ) ;
ptable [ npart ] . hd . psize = zlen ;
free ( zbuf ) ;
// перерассчитываем контрольные суммы
// recalculate the checksums
calc_crc16 ( npart ) ;
ptable [ npart ] . hd . crc = crc16 ( ( uint8_t * ) & ptable [ npart ] . hd , sizeof ( struct pheader ) ) ;
ptable [ npart ] . ztype = ' L ' ;
}
// продвигаем счетчик разделов
// advance the partition counter
npart + + ;
// отъезжаем, если надо, вперед на границу слова
// move forward to the word boundary if necessary
res = ftell ( in ) ;
if ( ( res & 3 ) ! = 0 ) fseek ( in , ( res + 4 ) & ( ~ 3 ) , SEEK_SET ) ;
}
//*******************************************************
//* Поиск разделов в файле прошивки
//*
//* возвращает число найденных разделов
//* Search for partitions in firmware file
//*
//* returns number of found partitions
//*******************************************************
int findparts ( FILE * in ) {
// буфер префикса BIN-файла
// BIN file prefix buffer
uint8_t prefix [ 0x5c ] ;
int32_t signsize ;
int32_t hd_dload_id ;
// Маркер начала заголовка раздела
// partition header start marker
const unsigned int dpattern = 0xa55aaa55 ;
unsigned int i ;
// поиск начала цепочки разделов в файле
// search for the beginning of the partition chain in the file
while ( fread ( & i , 1 , 4 , in ) = = 4 ) {
if ( i = = dpattern ) break ;
}
if ( feof ( in ) ) {
printf ( " \n В файле не найдены разделы - файл не содержит образа прошивки\n " ) ;
printf ( " \n No partitions found in file - the file does not contain a firmware image \n " ) ;
exit ( 0 ) ;
}
}
// текущая позиция в файле должна быть не ближе 0x60 от начала - размер заголовка всего файла
// the current position in the file should be no closer than 0x60 from the beginning - the header size of the whole file
if ( ftell ( in ) < 0x60 ) {
printf ( " \n Заголовок файла имеет неправильный размер \n " ) ;
printf ( " \n Wrong file header size \n " ) ;
exit ( 0 ) ;
}
fseek ( in , - 0x60 , SEEK_CUR ) ; // отъезжаем на начало BIN-файла
}
fseek ( in , - 0x60 , SEEK_CUR ) ; // move to the beginning of the BIN-file
// вынимаем префикс
// take out the prefix
fread ( prefix , 0x5c , 1 , in ) ;
hd_dload_id = prefix [ 0 ] ;
// если принудительно dload_id не установлен - выбираем е г о из заголовка
// if dload_id is not set forcibly - select it from the header
if ( dload_id = = - 1 ) dload_id = hd_dload_id ;
if ( dload_id > 0xf ) {
printf ( " \n Неверный код типа прошивки (dload_id) в заголовке - %x" , dload_id ) ;
printf ( " \n Incorrect firmware type code (dload_id) in header - %x" , dload_id ) ;
exit ( 0 ) ;
}
printf ( " \n Код файла прошивки : %x (%s)\n " , hd_dload_id , fw_description ( hd_dload_id ) ) ;
}
printf ( " \n Firmware file code : %x (%s)\n " , hd_dload_id , fw_description ( hd_dload_id ) ) ;
// поиск остальных разделов
// search for other partitions
do {
printf ( " \r Поиск раздела # %i" , npart ) ; fflush ( stdout ) ;
if ( fread ( & i , 1 , 4 , in ) ! = 4 ) break ; // конец файла
if ( i ! = dpattern ) break ; // образец не найден - конец цепочки разделов
fseek ( in , - 4 , SEEK_CUR ) ; // отъезжаем назад, на начало заголовка
extract ( in ) ; // извлекаем раздел
printf ( " \r Searching for partition # %i" , npart ) ; fflush ( stdout ) ;
if ( fread ( & i , 1 , 4 , in ) ! = 4 ) break ; // end of file
if ( i ! = dpattern ) break ; // sample not found - end of partition chain
fseek ( in , - 4 , SEEK_CUR ) ; // move back to the beginning of header
extract ( in ) ; // extract partition
} while ( 1 ) ;
printf ( " \r \r " ) ;
// ищем цифровую подпись
// look for a digital signature
signsize = serach_sign ( ) ;
if ( signsize = = - 1 ) printf ( " \n Цифровая подпись: не найдена " ) ;
if ( signsize = = - 1 ) printf ( " \n Digital Signature: Not found " ) ;
else {
printf ( " \n Цифровая подпись: %i байт " , signsize ) ;
printf ( " \n Хеш открытого ключа : %s" , signver_hash ) ;
printf ( " \n Digital Signature: %i bytes " , signsize ) ;
printf ( " \n Public Key Hash : %s" , signver_hash ) ;
}
if ( ( ( signsize = = - 1 ) & & ( dload_id > 7 ) ) | |
( ( signsize ! = - 1 ) & & ( dload_id < 8 ) ) )
printf ( " \n ! ВНИМАНИЕ: Наличие цифровой подписи не соответствует коду типа прошивки: %02x " , dload_id ) ;
( ( signsize ! = - 1 ) & & ( dload_id < 8 ) ) )
printf ( " \n ! WARNING: The present of a digital signature does not match the firmware type code: %02x " , dload_id ) ;
return npart ;
}
//*******************************************************
//* Поиск разделов в многофайловом режиме
//* Partition search in multi-file procedure
//*******************************************************
void findfiles ( char * fdir ) {
char filename [ 200 ] ;
char filename [ 200 ] ;
FILE * in ;
printf ( " \n Поиск файлов-образов разделов...\n \n ## Размер ID Имя Файл \n ----------------------------------------------------------------- \n " ) ;
printf ( " \n Searching for partition image files...\n \n ## Size ID Name File \n ----------------------------------------------------------------- \n " ) ;
for ( npart = 0 ; npart < 30 ; npart + + ) {
if ( find_file ( npart , fdir , filename , & ptable [ npart ] . hd . code , & ptable [ npart ] . hd . psize ) = = 0 ) break ; // конец поиска - раздела с таким ID не нашли
// получаем символическое имя раздела
if ( find_file ( npart , fdir , filename , & ptable [ npart ] . hd . code , & ptable [ npart ] . hd . psize ) = = 0 ) break ; // end of search - no partition with this ID was found
// get the symbolic name of the partition
find_pname ( ptable [ npart ] . hd . code , ptable [ npart ] . pname ) ;
printf ( " \n %02i %8i %08x %-14.14s %s " , npart , ptable [ npart ] . hd . psize , ptable [ npart ] . hd . code , ptable [ npart ] . pname , filename ) ; fflush ( stdout ) ;
// распределяем память под образ раздела
// allocate memory for the partition image
ptable [ npart ] . pimage = malloc ( ptable [ npart ] . hd . psize ) ;
if ( ptable [ npart ] . pimage = = 0 ) {
printf ( " \n ! Ошибка распределения памяти, раздел #%i, размер = %i байт \n " , npart , ptable [ npart ] . hd . psize ) ;
printf ( " \n ! Memory allocation error, partition #%i, size = %i bytes \n " , npart , ptable [ npart ] . hd . psize ) ;
exit ( 0 ) ;
}
// читаем образ в буфер
// read image to buffer
in = fopen ( filename , " rb " ) ;
if ( in = = 0 ) {
printf ( " \n Ошибка открытия файла %s" , filename ) ;
printf ( " \n Can't open file %s" , filename ) ;
return ;
}
}
fread ( ptable [ npart ] . pimage , ptable [ npart ] . hd . psize , 1 , in ) ;
fclose ( in ) ;
}
if ( npart = = 0 ) {
printf ( " \n ! Н е найдено ни одного файла с образом раздела в каталоге %s" , fdir ) ;
printf ( " \n ! No partition image files were found in directory %s" , fdir ) ;
exit ( 0 ) ;
}
}
}