From dee99ab0143122146ab7713cfe171790bc796dd3 Mon Sep 17 00:00:00 2001 From: Roman Yeryomin Date: Fri, 16 Aug 2013 11:44:04 +0300 Subject: Get rid of rtkload. Use OpenWrt lzma-loader (with kernel_entry hack). Use mgbin for unified tftp image generation. Signed-off-by: Roman Yeryomin --- tools/firmware-utils/src/mgbin.c | 431 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 tools/firmware-utils/src/mgbin.c (limited to 'tools/firmware-utils/src/mgbin.c') diff --git a/tools/firmware-utils/src/mgbin.c b/tools/firmware-utils/src/mgbin.c new file mode 100644 index 000000000..a16ef1e44 --- /dev/null +++ b/tools/firmware-utils/src/mgbin.c @@ -0,0 +1,431 @@ +/* + * utility to merge all binary into one image + * + * Authors: David Hsu + * + * $Id: mgbin.c,v 1.7 2008/11/25 15:09:22 bradhuang Exp $ + * + */ +#include +#include +#include +#include +#include +#include +#include +#ifdef WIN32 + #include +#else + #include +#endif +#define __mips__ + +#define CONFIG_RTL_8196C +#include "apmib.h" + +//#define DEBUG_PRINT printf +#define DEBUG_PRINT(...) do {} while(0) +#define COMPACT_FILENAME_BUFFER + +///////////////////////////////////////////////////////////////////////////// +/* Input file type */ +typedef enum { BOOT_CODE=0, CONFIG, WEB_PAGES, SYS, ROOT, ALL, INVALID_FILE=-1 } TYPE_T; + +typedef struct _sector { + TYPE_T type; +#ifdef COMPACT_FILENAME_BUFFER + const char *filename; +#else + char filename[80]; +#endif + unsigned long offset; + unsigned long size; + int with_header; +} SECTOR_T; + +///////////////////////////////////////////////////////////////////////////// +static char *copyright="Copyright (c) Realtek Semiconductor Corp., 2007. All Rights Reserved."; +static char *version="1.0"; + +static SECTOR_T sector[ROOT+1]; +static int no_hw_config=0; + +#define BYTE_SWAP(word) (((word >> 8) &0xff) | ((((unsigned char)word)<<8)&0xff00) ) + +///////////////////////////////////////////////////////////////////////////// +static TYPE_T checkInputFile(char *filename, int *pWith_header) +{ + int fh; + char signature[6]; + +#ifdef WIN32 + fh = open(filename, O_RDONLY|O_BINARY); +#else + fh = open(filename, O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); +#endif + if ( fh == -1 ) + return INVALID_FILE; + + lseek(fh, 0, SEEK_SET); + + if ( read(fh, signature, sizeof(signature)) != sizeof(signature)) { + close(fh); + return INVALID_FILE; + } + close(fh); + + *pWith_header = 1; + if ( !memcmp(signature, BOOT_HEADER, 4)) + return BOOT_CODE; + else if ( !memcmp(signature, WEB_HEADER, 3) ) + return WEB_PAGES; + + else if ( !memcmp(signature, FW_HEADER, 4) || + !memcmp(signature, FW_HEADER_WITH_ROOT, 4)) + return SYS; + + else if ( !memcmp(signature, ROOT_HEADER, 4) ) + return ROOT; + + else if ( !memcmp(signature, "h", 1) || !memcmp(signature, "COMPHS", 6)) + return CONFIG; + else if ( !memcmp(signature, "6G", 2) || !memcmp(signature, "6A", 2) || !memcmp(signature, "6g", 2) || !memcmp(signature, "6a", 2) || !memcmp(signature, "COMPDS", 6)) { + no_hw_config = 1; + return CONFIG; + } + else if ( !memcmp(signature, "\x0b\xf0\x00\x02", 4)) { + *pWith_header = 0; + return BOOT_CODE; + } + return INVALID_FILE; +} + +//////////////////////////////////////////////////////////////////////////////// +static void showHelp(void) +{ + printf("\nRTL865x utility to merge binary.\n"); + printf("%s Ver %s.\n\n", copyright, version); + printf("usage: mgbin [-s] [-c] [-a] -o outputfile bootcode config webpages linux root\n"); + printf(" -s : do byte swap\n"); + printf(" -c : cascade. May use this option to merge image for web upload\n"); + printf(" -a : add all tag in header\n"); + +} + + +//////////////////////////////////////////////////////////////////////////////// +static void do_byteswap(unsigned char *buf, int len) +{ + unsigned short wVal, *ptr; + int i=0; + + while (len > 0) { + len -= 2; + ptr = (unsigned short *)&buf[2*i]; + wVal = *ptr; + *ptr = BYTE_SWAP( wVal ); + i++; + } +} + +static unsigned short calculateChecksum(char *buf, int len, unsigned short oldv) +{ + int i, j; + unsigned short sum=oldv, tmp; + + j = (len/2)*2; + + for (i=0; i= argc) + break; +#ifdef COMPACT_FILENAME_BUFFER + outFile = argv[argNum]; +#else + sscanf(argv[argNum], "%s", outFile); +#endif + } + else if ( !strcmp(argv[argNum], "-s") ) { + byteswap = 1; + } + else if ( !strcmp(argv[argNum], "-c") ) { + cascade = 1; + } + else if ( !strcmp(argv[argNum], "-a") ) { + is_all = 1; + memset(&allHeader, '\0', sizeof(IMG_HEADER_T)); + memcpy(allHeader.signature, ALL_HEADER, SIGNATURE_LEN); + } +#if 0 + else if ( !strcmp(argv[argNum], "-a2") ) { + is_all = 1; + memset(&allHeader, '\0', sizeof(IMG_HEADER_T)); + memcpy(allHeader.signature, ALL_HEADER2, SIGNATURE_LEN); + } +#endif + else { + if (is_all) { + if ((argNum+1) < argc) { + printf("argument error, only input file could be specified!\n"); + return -1; + } +#ifdef COMPACT_FILENAME_BUFFER + sector[0].filename = argv[argNum]; +#else + strcpy(sector[0].filename,argv[argNum]); +#endif + sector[0].type=ALL; + sector[0].with_header=0; + mask |= (1 << ALL); + } + else { + type=checkInputFile(argv[argNum], &with_header); + DEBUG_PRINT("filename=%s, type=%d\n", argv[argNum], type); + if (type == INVALID_FILE) { + printf("\nInvalid input file %s!!\n", argv[argNum]); + showHelp(); + exit(1); + } +#ifdef COMPACT_FILENAME_BUFFER + sector[type].filename = argv[argNum]; +#else + strcpy(sector[type].filename, argv[argNum]); +#endif + sector[type].with_header = with_header; + sector[type].type = type; + mask |= (1 << type); + } + } + argNum++; + } + +#ifdef COMPACT_FILENAME_BUFFER + if( outFile == NULL ) +#else + if (!outFile[0]) +#endif + { + printf("No output file specified!\n"); + showHelp(); + exit(1); + } + + if (mask == 0) { + printf("No valid input image found!\n"); + exit(1); + } + + // Create output file +#ifdef WIN32 + _chmod(outFile, S_IREAD|S_IWRITE); + fh_out = open(outFile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY); +#else + chmod(outFile, S_IREAD|S_IWRITE); + fh_out = open(outFile, O_RDWR|O_CREAT|O_TRUNC, 0644); +#endif + if (fh_out == -1) { + printf("Create output file %s error!\n", outFile); + exit(1); + } + + if (is_all) { + write(fh_out, &allHeader, sizeof(allHeader)); + total += sizeof(allHeader); + printf("\nGenerate "); + } + else + printf("\nMerge "); + + for (i=BOOT_CODE; i<=ROOT ; i++) { +#ifdef COMPACT_FILENAME_BUFFER + if (sector[i].filename) +#else + if (sector[i].filename[0]) +#endif + { + if ( stat(sector[i].filename, &sbuf) != 0 ) { + printf("Stat file %s error!\n", sector[i].filename); + exit(1); + } + buf = malloc(sbuf.st_size+1); + if (buf == NULL) { + printf("allocate buffer failed %d!\n", (int)sbuf.st_size); + exit(1); + } +#ifdef WIN32 + fh_in = open(sector[i].filename, O_RDONLY|O_BINARY); +#else + fh_in = open(sector[i].filename, O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); +#endif + if (fh_in < 0) { + printf("Open file %s error!\n", sector[i].filename); + close(fh_out); + exit(1); + } + + switch(sector[i].type) { + case BOOT_CODE: + printf("BOOT-CODE "); + break; + case CONFIG: + printf("CONFIG-DATA(%s) ", (no_hw_config ? "no-hw" : "all")); + break; + case WEB_PAGES: + printf("WEB-PAGES "); + break; + case SYS: + printf("LINUX "); + break; + case ROOT: + printf("ROOT "); + break; + case ALL: + printf("ALL "); + break; + case INVALID_FILE: + break; + } + + if (read(fh_in, buf, sbuf.st_size) != sbuf.st_size) { + printf("Read file %s error!\n", sector[i].filename); + close(fh_in); + close(fh_out); + free(buf); + exit(1); + } + + if (is_all) + checksum = calculateChecksum((char *)buf, sbuf.st_size, checksum); + else { + if (sector[i].with_header) { + if (sector[i].type == CONFIG) { + if (no_hw_config == 0) + burnAddr = HW_SETTING_OFFSET; + else + burnAddr = DEFAULT_SETTING_OFFSET; + } + else { + pHeader = (IMG_HEADER_Tp)buf; + burnAddr = DWORD_SWAP(pHeader->burnAddr); + } + } + else + burnAddr = 0; + + if (byteswap) { + if (sbuf.st_size % 2) { + buf[sbuf.st_size] = '\0'; + sbuf.st_size++; + } + do_byteswap(buf, sbuf.st_size); + } + + // try to append 0 if necessary + if (!cascade && last_idx!=-1 && sector[i].with_header) { + if ((sector[last_idx].offset+sector[last_idx].size) < burnAddr) { + len = burnAddr - (sector[last_idx].offset+sector[last_idx].size); + buf1 = calloc(len, 1); + if (buf1 == NULL) { + printf("allocate buffer failed %d!\n", len); + exit(1); + } + write(fh_out, buf1, len); // pad 0 + + free(buf1); + total += len; +// printf("pad size=%d, last_idx=%d, burnAddr=%d\n", len, last_idx, burnAddr); + } + } + + // skip header if necessary + if (!cascade && sector[i].with_header && + ((sector[i].type == ROOT) || (sector[i].type == BOOT_CODE))) { + offset = sizeof(IMG_HEADER_T); +// sbuf.st_size -= sizeof(IMG_HEADER_T); + } + else + offset = 0; + } + +// printf("write offset=%d, size=%d\n", offset, sbuf.st_size); + if ( write(fh_out, buf + offset , sbuf.st_size-offset) != sbuf.st_size-offset) { + printf("Write output file %s error!\n", outFile); + close(fh_in); + close(fh_out); + free(buf); + exit(1); + } + close(fh_in); + if (burnAddr > 0) + sector[i].offset = burnAddr; + else + sector[i].offset = total; + sector[i].size = sbuf.st_size-offset; + +// printf("section[%d], offset=%d, size=%d\n", i, sector[i].offset, sector[i].size); + + total += sbuf.st_size; + free(buf); + last_idx = i; + if (is_all) + break; + } + } + + if (is_all) { + allHeader.len = DWORD_SWAP((total+2)); + checksum = calculateChecksum((char *)&allHeader, sizeof(allHeader), checksum); + checksum = WORD_SWAP((~checksum+1)); + write(fh_out, &checksum, 2); + lseek(fh_out, 0, SEEK_SET); + allHeader.len = DWORD_SWAP((total+2)); +// allHeader.startAddr = DWORD_SWAP(image_num); + write(fh_out, &allHeader, sizeof(allHeader)); + total += (2 + sizeof(allHeader)); + } + close(fh_out); + +#ifdef WIN32 + _chmod(outFile, S_IREAD); +#else + chmod(outFile, DEFFILEMODE); +#endif + + printf("=> %s ok, size=%d.\n", outFile, total); + exit(0); +} + -- cgit v1.2.3