openwrt/tools/firmware-utils/src/zyimage.c

149 lines
3.1 KiB
C

/*
* Copyright (C) 2014 Soul Trace <S-trace@list.ru>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
*/
#define _POSIX_SOURCE
#define _POSIX_C_SOURCE 199309L /* getopt */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#define szbuf 32768
u_int32_t crc_tab[256];
u_int32_t chksum_crc32 (FILE *f)
{
register unsigned long crc;
unsigned long i, j;
char *buffer = malloc(szbuf);
char *buf;
crc = 0xFFFFFFFF;
while (!feof(f))
{
j = fread(buffer, 1, szbuf, f);
buf = buffer;
for (i = 0; i < j; i++)
crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *buf++) & 0xFF];
}
free(buffer);
return crc;
}
void chksum_crc32gentab ()
{
unsigned long crc, poly;
int i, j;
poly = 0xEDB88320L;
for (i = 0; i < 256; i++)
{
crc = i;
for (j = 8; j > 0; j--)
{
if (crc & 1)
crc = (crc >> 1) ^ poly;
else
crc >>= 1;
}
crc_tab[i] = crc;
}
}
void usage(char *progname)
{
printf("Usage: %s [ -v Version ] [ -d Device_ID ] <input file>\n", progname);
exit(1);
}
int main(int argc, char *argv[]) {
struct signature
{
const char magic[4];
unsigned int device_id;
char firmware_version[48];
unsigned int crc32;
}
sign =
{
{ 'Z', 'N', 'B', 'G' },
1,
{ "V.1.0.0(1.0.0)" },
0
};
FILE *f;
struct signature oldsign;
char *filename;
static const char *optString;
int opt;
if (argc < 1)
usage(argv[0]);
optString = "v:d:h";
opt = getopt( argc, argv, optString );
while( opt != -1 ) {
switch( opt ) {
case 'v':
if (optarg == NULL)
usage(argv[0]);
strncpy(sign.firmware_version, optarg, sizeof(sign.firmware_version)-1);
sign.firmware_version[sizeof(sign.firmware_version)-1]='\0'; /* Make sure that string is terminated correctly */
break;
case 'd':
sign.device_id = atoi(optarg);
if (sign.device_id == 0)
sign.device_id = (int)strtol(optarg, NULL, 16);
break;
case '?':
case 'h':
usage(argv[0]);
break;
default:
break;
}
opt = getopt( argc, argv, optString );
}
chksum_crc32gentab();
filename=argv[optind];
if (access(filename, W_OK) || access(filename, R_OK))
{
printf("Not open input file %s\n", filename);
exit(1);
}
f = fopen(argv[optind], "r+");
if (f != NULL)
{
fseek(f, sizeof(sign)*-1, SEEK_END);
fread(&oldsign, sizeof(oldsign), 1, f);
if (strncmp(oldsign.magic,"ZNBG", sizeof(oldsign.magic)) == 0 )
{
printf("Image is already signed as:\nDevice ID: 0x%08x\nFirmware version: %s\nImage CRC32: 0x%x\n", oldsign.device_id, oldsign.firmware_version, oldsign.crc32);
exit(0);
}
fseek(f, 0, SEEK_SET);
sign.crc32 = chksum_crc32(f);
fwrite(&sign, sizeof(sign), 1, f);
fclose(f);
printf("Image signed as:\nDevice ID: 0x%08x\nFirmware version: %s\nImage CRC32: 0x%x\n", sign.device_id, sign.firmware_version, sign.crc32);
}
return 0;
}