1210 lines
30 KiB
C
Executable File
1210 lines
30 KiB
C
Executable File
/*
|
||
* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
* General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
*/
|
||
|
||
/* July 29, 2004
|
||
*
|
||
* This is a hacked replacement for the 'trx' utility used to create
|
||
* wrt54g .trx firmware files. It isn't pretty, but it does the job
|
||
* for me.
|
||
*
|
||
* As an extension, you can specify a larger maximum length for the
|
||
* .trx file using '-m'. It will be rounded up to be a multiple of 4K.
|
||
* NOTE: This space will be malloc()'d.
|
||
*
|
||
* August 16, 2004
|
||
*
|
||
* Sigh... Make it endian-neutral.
|
||
*
|
||
* TODO: Support '-b' option to specify offsets for each file.
|
||
*
|
||
* February 19, 2005 - mbm
|
||
*
|
||
* Add -a (align offset) and -b (absolute offset)
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
#include <errno.h>
|
||
#include <unistd.h>
|
||
#include <byteswap.h>
|
||
#include <getopt.h>
|
||
#include <fcntl.h>
|
||
#include <time.h>
|
||
#include <elf.h>
|
||
#include <sys/stat.h>
|
||
|
||
|
||
#include "mkimage.h"
|
||
#include "md5_interface.h"
|
||
|
||
|
||
#if 0
|
||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||
|
||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||
#define STORE32_LE(X) bswap_32(X)
|
||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||
#define STORE32_LE(X) (X)
|
||
#endif
|
||
|
||
|
||
#define STORE32_LE(X) bswap_32(X)
|
||
#endif
|
||
|
||
|
||
#define CLOUD_ID_STR_LEN 33
|
||
#define BUFFER_LEN64 64
|
||
|
||
#ifdef INCLUDE_FLASH_NAND
|
||
#define MTD_BLOCK_SIZE 0x20000
|
||
#else /* INCLUDE_FLASH_NAND */
|
||
#define MTD_BLOCK_SIZE 0x10000
|
||
#endif /* INCLUDE_FLASH_NAND */
|
||
|
||
|
||
typedef struct _DEV_INFO
|
||
{
|
||
unsigned int sw_revision;
|
||
unsigned int platform_ver;
|
||
unsigned int special_ver;
|
||
unsigned int product_id;
|
||
unsigned int product_ver;
|
||
unsigned int add_hver;
|
||
char model_name[BUFFER_LEN64];
|
||
char build_date[BUFFER_LEN64];
|
||
unsigned int build_time;
|
||
char dev_ver[BUFFER_LEN64];
|
||
unsigned char hw_id[CLOUD_ID_BYTE_LEN];
|
||
unsigned char fw_id[CLOUD_ID_BYTE_LEN];
|
||
unsigned char oem_id[CLOUD_ID_BYTE_LEN];
|
||
unsigned char is_beta;
|
||
unsigned char is_trans;
|
||
unsigned char is_datecode;
|
||
char build_spec[BUFFER_LEN64];
|
||
}DEV_INFO;
|
||
|
||
static LINUX_FLASH_STRUCT l_flash_struct;
|
||
static DEV_INFO l_dev_info;
|
||
|
||
static int l_flash_size = 0;
|
||
static int l_boot_size = 0;
|
||
static int l_kernel_size = 0;
|
||
static int l_misc_size = 0;
|
||
static int l_target_endian = -1; /* 0-big, 1-little */
|
||
|
||
#define STORE32_LE(X) (l_target_endian ? (X) : bswap_32(X))
|
||
|
||
|
||
|
||
/**********************************************************************/
|
||
|
||
void usage(void) __attribute__ (( __noreturn__ ));
|
||
|
||
void replaceBlank(char *str);
|
||
int getStrAttrVal(char *buf, char *attr, char *value, int maxLen);
|
||
int idstrToByte(const char *pIdstr, unsigned char *pByte);
|
||
int getVersion(const char *reduced_xml_name);
|
||
int fill_buffer(char *buffer, char filename[][MAX_FILENAME_LEN], char *vmlinux);
|
||
|
||
|
||
void usage(void)
|
||
{
|
||
fprintf(stderr,
|
||
"Usage: mkimage [OPTIONS]\n\n"
|
||
" -s, --flashsize=SIZE Flash size\n"
|
||
" -l, --bootsize=SIZE MAX Bootloader size\n"
|
||
" -m, --maxkernelsize=SIZE MAX Kernel size\n"
|
||
" -n, --miscsize=SIZE Reserved for Misc size\n"
|
||
" -e, --targetEndian=endian Target CPU endian\n"
|
||
" -b, --boot=FILE Boot file\n"
|
||
" -k, --kernel=FILE Kernel file\n"
|
||
" -f, --fs=FILE Filesystem file\n"
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK HGU model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
" -r, --romfile=FILE romfile file\n"
|
||
#endif
|
||
/* End Add. */
|
||
" -o, --output=FILE Output Filename prefix\n"
|
||
" -i, --image-path=PATH image path\n"
|
||
" -p, --xmlName=FILE reduced_data_model file\n"
|
||
" -d, --dualImage Have Dual Image(Only for 16M flash,8M up bin)\n"
|
||
" -t, --mtdType=type MTD part type\n"
|
||
" -c, --confrom=FILE config file\n"
|
||
" -h, --help Display this message\n");
|
||
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
void replaceBlank(char *str)
|
||
{
|
||
if (NULL == str)
|
||
{
|
||
fprintf(stderr, "Get NULL replace blank string\n");
|
||
return;
|
||
}
|
||
|
||
while(*str != '\0')
|
||
{
|
||
if (' ' == *str)
|
||
{
|
||
*str = '_';
|
||
}
|
||
|
||
*str++;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
int getStrAttrVal(char *buf, char *attr, char *value, int maxLen)
|
||
{
|
||
char *p = NULL;
|
||
char *q = NULL;
|
||
char *valStart = NULL;
|
||
char *valEnd = NULL;
|
||
|
||
if ((buf == NULL) || (attr == NULL) || (value == NULL))
|
||
{
|
||
fprintf(stderr, "%s(): get attr \"%s\" parameter error\n", __FUNCTION__, attr);
|
||
return -1;
|
||
}
|
||
|
||
p = strstr(buf, attr);
|
||
if (p == NULL)
|
||
{
|
||
fprintf(stderr, "%s(): cannot find attr %s\n", __FUNCTION__, attr);
|
||
return -1;
|
||
}
|
||
|
||
q = strstr(p , "d=");
|
||
p = strchr(q, '>');
|
||
if ((q == NULL) || (p == NULL))
|
||
{
|
||
fprintf(stderr, "%s(): \"%s\" cannot find \"d=\" Or \">\"\n", __FUNCTION__, attr);
|
||
return -1;
|
||
}
|
||
|
||
q += 2;
|
||
|
||
while (isspace(*q))
|
||
{
|
||
q++;
|
||
}
|
||
|
||
/*string value with quote */
|
||
if ((*q == '\"') || (*q == '\''))
|
||
{
|
||
valStart = q + 1;
|
||
valEnd = strchr(valStart, *q);
|
||
|
||
if ((valEnd > p) || (valEnd - valStart > maxLen))
|
||
{
|
||
fprintf(stderr, "%s(): \"%s\" can't find right quote Or exceed max len\n", __FUNCTION__, attr);
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
valStart = q;
|
||
|
||
while(!isspace(*q) && (*q != '>'))
|
||
{
|
||
if ((*q) == '/' && (*(q + 1) == '>'))
|
||
{
|
||
break;
|
||
}
|
||
q++;
|
||
}
|
||
valEnd = q;
|
||
|
||
if (valEnd - valStart > maxLen)
|
||
{
|
||
fprintf(stderr, "%s(): value of attr \"%s\" exceed max length\n", __FUNCTION__, attr);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
memcpy(value, valStart, valEnd - valStart);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int idstrToByte(const char *pIdstr, unsigned char *pByte)
|
||
{
|
||
int i = 0, c = 0;
|
||
|
||
for (i = 0; i < 16; i++)
|
||
{
|
||
if (*pIdstr >= '0' && *pIdstr <= '9')
|
||
{
|
||
c = (unsigned char) (*pIdstr++ - '0');
|
||
}
|
||
else if (*pIdstr >= 'a' && *pIdstr <= 'f')
|
||
{
|
||
c = (unsigned char) (*pIdstr++ - 'a') + 10;
|
||
}
|
||
else if (*pIdstr >= 'A' && *pIdstr <= 'F')
|
||
{
|
||
c = (unsigned char) (*pIdstr++ - 'A') + 10;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
c <<= 4;
|
||
|
||
if (*pIdstr >= '0' && *pIdstr <= '9')
|
||
{
|
||
c |= (unsigned char) (*pIdstr++ - '0');
|
||
}
|
||
else if (*pIdstr >= 'a' && *pIdstr <= 'f')
|
||
{
|
||
c |= (unsigned char) (*pIdstr++ - 'a') + 10;
|
||
}
|
||
else if (*pIdstr >= 'A' && *pIdstr <= 'F')
|
||
{
|
||
c |= (unsigned char) (*pIdstr++ - 'A') + 10;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pByte[i] = (unsigned char) c;
|
||
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int getVersion(const char *reduced_xml_name)
|
||
{
|
||
int fd;
|
||
char tmp[12] = {0};
|
||
char tmpId[33] = {0};
|
||
|
||
#define MAX_LEN (80 * 1024)
|
||
char buf[MAX_LEN] = {0};
|
||
|
||
fd = open(reduced_xml_name, O_RDONLY);
|
||
|
||
if (fd < 0)
|
||
{
|
||
perror("open profile error\n");
|
||
return -1;
|
||
}
|
||
|
||
while (read(fd, buf, MAX_LEN - 1) > 0)
|
||
{
|
||
buf[MAX_LEN - 1] = 0;
|
||
|
||
/* Get software revision */
|
||
char *q = strstr(buf, "X_TP_SoftwareRevision");
|
||
char *p = strstr(q, "d=");
|
||
char *pEnd = NULL;
|
||
int strLen = 0;
|
||
|
||
if (p != 0)
|
||
{
|
||
p += 2;
|
||
strncpy(tmp, p, 10);
|
||
l_dev_info.sw_revision = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get platform version */
|
||
p = strstr(buf, "X_TP_PlatformVersion");
|
||
q = strstr(p, "d=");
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.platform_ver = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get product Id */
|
||
p = strstr(buf, "X_TP_ProductID");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.product_id = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get product version */
|
||
p = strstr(buf, "X_TP_ProductVersion");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.product_ver = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get special version */
|
||
p = strstr(buf, "X_TP_SpecialVersion");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.special_ver = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
|
||
/* Get Additional HardwareVersion */
|
||
memset(tmp, 0, 12);
|
||
if (getStrAttrVal(buf, "AdditionalHardwareVersion", tmp, 10) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
l_dev_info.add_hver = strtoul(tmp, NULL, 16);
|
||
|
||
/* Get build date */
|
||
if (getStrAttrVal(buf, "X_TP_BuildDate", l_dev_info.build_date, BUFFER_LEN64) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/* Get build time */
|
||
p = strstr(buf, "X_TP_BuildTime");
|
||
q = strstr(p, "d=");
|
||
|
||
memset(tmp, 0, 12);
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 5);
|
||
l_dev_info.build_time = strtoul(tmp, NULL, 10);
|
||
}
|
||
|
||
/* Get device model version */
|
||
if (getStrAttrVal(buf, "X_TP_DevModelVersion", l_dev_info.dev_ver, BUFFER_LEN64) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/* Get model name */
|
||
if (getStrAttrVal(buf, "ModelName", l_dev_info.model_name, BUFFER_LEN64) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/* Get HardwareID */
|
||
if (getStrAttrVal(buf, "X_TP_HardwareID", tmpId, CLOUD_ID_STR_LEN) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
printf("hwid is %s\n", tmpId);
|
||
|
||
if (idstrToByte(tmpId, l_dev_info.hw_id) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/* Get FirmwareID */
|
||
if (getStrAttrVal(buf, "X_TP_FirmwareID", tmpId, CLOUD_ID_STR_LEN) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
printf("fwid is %s\n", tmpId);
|
||
|
||
if (idstrToByte(tmpId, l_dev_info.fw_id) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
|
||
/* Get OemID */
|
||
if (getStrAttrVal(buf, "X_TP_OemID", tmpId, CLOUD_ID_STR_LEN) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
printf("oemid is %s\n", tmpId);
|
||
|
||
if (idstrToByte(tmpId, l_dev_info.oem_id) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/* Get beta info */
|
||
p = strstr(buf, "X_TP_IsBeta");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.is_beta = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get trans info */
|
||
p = strstr(buf, "X_TP_IsTrans");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.is_trans = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get date code info */
|
||
p = strstr(buf, "X_TP_IsDateCode");
|
||
q = strstr(p, "d=");
|
||
|
||
if (q != 0)
|
||
{
|
||
q += 2;
|
||
strncpy(tmp, q, 10);
|
||
l_dev_info.is_datecode = strtoul(tmp, NULL, 16);
|
||
}
|
||
|
||
/* Get build date */
|
||
if (getStrAttrVal(buf, "X_TP_BuildSpec", l_dev_info.build_spec, BUFFER_LEN64) != 0)
|
||
{
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
close(fd);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int fill_buffer(char *buffer, char filename[][MAX_FILENAME_LEN], char *vmlinux)
|
||
{
|
||
FILE *in;
|
||
size_t n;
|
||
size_t boot_len, kernel_len, fs_len;
|
||
uint32_t cur_len;
|
||
char *buf = buffer;
|
||
unsigned long maxlen = l_flash_size;
|
||
struct _LINUX_FILE_TAG *kernel_tag, *boot_tag;
|
||
unsigned long image_len;
|
||
int vm_fd;
|
||
Elf32_Ehdr ehdr;
|
||
Elf32_Shdr shdr;
|
||
|
||
/* 1) bootloader */
|
||
boot_tag = (struct _LINUX_FILE_TAG *)buf;
|
||
|
||
cur_len = BOOTLOADER_TAG_LEN;
|
||
|
||
if (!(in= fopen(filename[BOOT], "r"))) {
|
||
fprintf(stderr, "can not open \"%s\" for reading\n", filename[BOOT]);
|
||
usage();
|
||
}
|
||
fprintf(stderr, "bootloader is 0x%x\n", cur_len);
|
||
n = fread(buf + cur_len, 1, maxlen - cur_len, in); /* BOOTд<54><D0B4>buffer */
|
||
if (!feof(in)) {
|
||
fprintf(stderr, "fread failure or file \"%s\" too large\n", filename[BOOT]);
|
||
fclose(in);
|
||
return EXIT_FAILURE;
|
||
}
|
||
fclose(in);
|
||
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰnΪ816645<34><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE>n<EFBFBD><6E>Ϊ816648 */
|
||
if (n & (ROUND-1)) {
|
||
memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
|
||
n += ROUND - (n & (ROUND-1));
|
||
}
|
||
|
||
boot_len = n;
|
||
|
||
if (boot_len > l_boot_size)
|
||
{
|
||
fprintf(stderr, "boot size is %x, too large %x\n", boot_len, (l_flash_struct.kernelOffset - l_flash_struct.bootOffset));
|
||
return EXIT_FAILURE;
|
||
}
|
||
/* end read bootloader */
|
||
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
/* mtk romfile */
|
||
cur_len = l_flash_struct.romfileOffset + BOOTLOADER_TAG_LEN;
|
||
memset(buf + cur_len, 0, l_boot_size >> 1);
|
||
|
||
if (!(in= fopen(filename[ROMFILE], "r"))) {
|
||
fprintf(stderr, "can not open \"%s\" for reading\n", filename[ROMFILE]);
|
||
usage();
|
||
}
|
||
fprintf(stderr, "romfile is 0x%x\n", cur_len);
|
||
n = fread(buf + cur_len, 1, maxlen - cur_len, in);
|
||
if (!feof(in)) {
|
||
fprintf(stderr, "fread failure or file \"%s\" too large\n", filename[ROMFILE]);
|
||
fclose(in);
|
||
return EXIT_FAILURE;
|
||
}
|
||
fclose(in);
|
||
|
||
if (n & (ROUND-1)) {
|
||
memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
|
||
n += ROUND - (n & (ROUND-1));
|
||
}
|
||
#endif
|
||
/* End Add. */
|
||
|
||
/* 2) linux kernel */
|
||
cur_len = l_flash_struct.kernelOffset + BOOTLOADER_TAG_LEN;
|
||
kernel_tag = (struct _LINUX_FILE_TAG *) (buf + cur_len);
|
||
|
||
cur_len += TAG_LEN;
|
||
|
||
if (!(in= fopen(filename[KERNEL], "r"))) {
|
||
fprintf(stderr, "can not open \"%s\" for reading\n", filename[KERNEL]);
|
||
usage();
|
||
}
|
||
fprintf(stderr, "kernel is 0x%x\n", cur_len);
|
||
n = fread(buf + cur_len, 1, maxlen - cur_len, in);
|
||
if (!feof(in)) {
|
||
fprintf(stderr, "fread failure or file \"%s\" too large\n", filename[KERNEL]);
|
||
fclose(in);
|
||
return EXIT_FAILURE;
|
||
}
|
||
fclose(in);
|
||
|
||
if (n & (ROUND-1)) {
|
||
memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
|
||
n += ROUND - (n & (ROUND-1));
|
||
}
|
||
|
||
kernel_len = n;
|
||
|
||
/* use dynamic value by yangxv, 2011.11.20 */
|
||
/* if (kernel_len >= MAX_KERNEL_SIZE) */
|
||
if (kernel_len > l_kernel_size-TAG_LEN)
|
||
{
|
||
fprintf(stderr, "kernel size is %x, too large\n", kernel_len);
|
||
return EXIT_FAILURE;
|
||
}
|
||
/* end read linux kernel */
|
||
|
||
/* 3) rootfs */
|
||
cur_len = l_flash_struct.rootfsOffset + BOOTLOADER_TAG_LEN;
|
||
|
||
if (!(in= fopen(filename[FS], "r"))) {
|
||
fprintf(stderr, "can not open \"%s\" for reading\n", filename[FS]);
|
||
usage();
|
||
}
|
||
|
||
fprintf(stderr, "rootfs is 0x%x\n", cur_len);
|
||
n = fread(buf + cur_len, 1, maxlen - cur_len, in);
|
||
if (!feof(in)) {
|
||
fprintf(stderr, "fread failure or file \"%s\" too large\n", filename[FS]);
|
||
fclose(in);
|
||
return EXIT_FAILURE;
|
||
}
|
||
fclose(in);
|
||
|
||
if (n & (ROUND-1)) {
|
||
memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
|
||
n += ROUND - (n & (ROUND-1));
|
||
}
|
||
|
||
fs_len = n;
|
||
|
||
if (fs_len > l_flash_struct.appSize)
|
||
{
|
||
fprintf(stderr, "rootfs size is %x, too large\n", fs_len);
|
||
return EXIT_FAILURE;
|
||
}
|
||
/* end read rootfs */
|
||
|
||
/* 3.5) config_rom */
|
||
cur_len = l_flash_struct.configOffset + BOOTLOADER_TAG_LEN;
|
||
|
||
if (!(in= fopen(filename[CONFIG], "r"))) {
|
||
fprintf(stderr, "\e[0;31mConfig rom file \"%s\" not exist, please check\e[0m\n", filename[CONFIG]);
|
||
}
|
||
else {
|
||
fprintf(stderr, "config_rom is 0x%x\n", cur_len);
|
||
n = fread(buf + cur_len, 1, maxlen - cur_len, in);
|
||
if (!feof(in)) {
|
||
fprintf(stderr, "fread failure or file \"%s\" too large\n", filename[CONFIG]);
|
||
fclose(in);
|
||
return EXIT_FAILURE;
|
||
}
|
||
fclose(in);
|
||
}
|
||
/* end read config_rom */
|
||
|
||
/* 4) kernel tag */
|
||
if (!(vm_fd = open(vmlinux, O_RDONLY))) {
|
||
fprintf(stderr, "can not open \"%s\" for reading\n", optarg);
|
||
usage();
|
||
}
|
||
|
||
read(vm_fd, &ehdr, sizeof(ehdr));
|
||
read(vm_fd, &shdr, sizeof(shdr));
|
||
|
||
close(vm_fd);
|
||
|
||
printf("Entry Point: %#X\n", STORE32_LE(ehdr.e_entry));
|
||
printf("Text Addr: %#X\n", STORE32_LE(shdr.sh_addr));
|
||
|
||
kernel_tag->tagVersion = STORE32_LE(TAG_VERSION);
|
||
memcpy(kernel_tag->magicNum, magicNum, MAGIC_NUM_LEN);
|
||
|
||
kernel_tag->productId = STORE32_LE(l_dev_info.product_id);
|
||
kernel_tag->productVer = STORE32_LE(l_dev_info.product_ver);
|
||
|
||
kernel_tag->swRevision = STORE32_LE(l_dev_info.sw_revision);
|
||
kernel_tag->platformVer = STORE32_LE(l_dev_info.platform_ver);
|
||
kernel_tag->addHver = STORE32_LE(l_dev_info.add_hver);
|
||
|
||
kernel_tag->specialVer = STORE32_LE(l_dev_info.special_ver);
|
||
|
||
memcpy(kernel_tag->hardwareId, l_dev_info.hw_id, CLOUD_ID_BYTE_LEN);
|
||
memcpy(kernel_tag->firmwareId, l_dev_info.fw_id, CLOUD_ID_BYTE_LEN);
|
||
memcpy(kernel_tag->oemId, l_dev_info.oem_id, CLOUD_ID_BYTE_LEN);
|
||
|
||
memset(kernel_tag->imageValidToken, 0, TOKEN_LEN);
|
||
|
||
kernel_tag->kernelTextAddr = (shdr.sh_addr);
|
||
kernel_tag->kernelEntryPoint = (ehdr.e_entry);
|
||
|
||
image_len = l_flash_struct.appSize;
|
||
kernel_tag->totalImageLen = STORE32_LE(image_len);
|
||
|
||
kernel_tag->bootAddress = STORE32_LE(0x0);
|
||
kernel_tag->bootLen = STORE32_LE(0x0);
|
||
|
||
kernel_tag->kernelAddress = STORE32_LE(TAG_LEN);
|
||
kernel_tag->kernelLen = STORE32_LE(kernel_len);
|
||
|
||
kernel_tag->rootfsAddress = STORE32_LE(l_flash_struct.rootfsOffset - l_flash_struct.kernelOffset);
|
||
kernel_tag->rootfsLen = STORE32_LE(fs_len);
|
||
|
||
kernel_tag->binCrc32 = STORE32_LE(calc_crc32((const char *)kernel_tag + TAG_LEN, l_flash_struct.appSize - TAG_LEN));
|
||
|
||
memset(kernel_tag->sig, 0, SIG_LEN);
|
||
memset(kernel_tag->resSig, 0, SIG_LEN);
|
||
|
||
/* open it by renjun 2017.7.6*/
|
||
#if 1
|
||
unsigned char md5[MD5_HASH_SIZE];
|
||
|
||
memcpy(kernel_tag->imageValidToken, md5Key, 16);
|
||
md5_make_digest(md5, (unsigned char*)kernel_tag, image_len);
|
||
memcpy(kernel_tag->imageValidToken, md5, MD5_HASH_SIZE);
|
||
/* end fill kernel tag */
|
||
#endif
|
||
|
||
#if 0
|
||
/* 5) bootloader tag */
|
||
int up_boot_image_len = l_flash_struct.configOffset + BOOTLOADER_TAG_LEN;
|
||
|
||
/* some value use are same as kernel tag */
|
||
memcpy(boot_tag, kernel_tag, TAG_LEN);
|
||
|
||
boot_tag->totalImageLen = STORE32_LE(up_boot_image_len);
|
||
boot_tag->bootloaderAddress = STORE32_LE(0x0);
|
||
boot_tag->bootloaderLen = STORE32_LE(boot_len);
|
||
|
||
memcpy(boot_tag->imageValidationToken, mk5Key_bootloader, 16);
|
||
md5_make_digest(md5, (unsigned char*)boot_tag, up_boot_image_len);
|
||
memcpy(boot_tag->imageValidationToken, md5, MD5_HASH_SIZE);
|
||
/* end fill boot tag */
|
||
#endif
|
||
/* 5) fill default mac and pin */
|
||
memcpy(buf + BOOTLOADER_TAG_LEN + l_flash_size - l_misc_size + MAC_MISC_OFFSET, def_mac, 6);
|
||
memset(buf + BOOTLOADER_TAG_LEN + l_flash_size - l_misc_size + PIN_MISC_OFFSET, 0, 8);
|
||
/* end fill mac and pin */
|
||
|
||
/* 6) bootloader tag */
|
||
int up_boot_image_len
|
||
= l_flash_struct.appSize + (l_flash_struct.kernelOffset - l_flash_struct.bootOffset) + BOOTLOADER_TAG_LEN;
|
||
|
||
/* some value use are same as kernel tag */
|
||
memcpy(boot_tag, kernel_tag, TAG_LEN);
|
||
|
||
boot_tag->totalImageLen = STORE32_LE(up_boot_image_len);
|
||
boot_tag->bootAddress = STORE32_LE(0x0);
|
||
boot_tag->bootLen = STORE32_LE(boot_len);
|
||
boot_tag->kernelAddress = STORE32_LE(l_boot_size);
|
||
|
||
#if 1
|
||
|
||
memcpy(boot_tag->imageValidToken, mk5Key_bootloader, 16);
|
||
/*unsigned char md5[MD5_HASH_SIZE];*/
|
||
md5_make_digest(md5, (unsigned char*)boot_tag, up_boot_image_len);
|
||
memcpy(boot_tag->imageValidToken, md5, MD5_HASH_SIZE);
|
||
#endif
|
||
/* end fill boot tag */
|
||
}
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
FILE *out = stdout;
|
||
char *ofn = NULL;
|
||
char *buf;
|
||
char filename[FILE_NUM][MAX_FILENAME_LEN] = {0, 0, 0};
|
||
|
||
char vmlinux_name[MAX_FILENAME_LEN] = {0};
|
||
char reduced_xml_name[MAX_FILENAME_LEN] = {0};
|
||
char image_path[MAX_FILENAME_LEN] = {0};
|
||
|
||
int c = 0;
|
||
|
||
char prefix[MAX_FILENAME_LEN] = {0};
|
||
char bin_file[MAX_FILENAME_LEN] = {0};
|
||
char bin_file_nodate[MAX_FILENAME_LEN] = {0};
|
||
char update_file[MAX_FILENAME_LEN] = {0};
|
||
char update_file_boot[MAX_FILENAME_LEN] = {0};
|
||
char update_file_boot_nodate[MAX_FILENAME_LEN] = {0};
|
||
char tag_kernel[MAX_FILENAME_LEN] = {0};
|
||
|
||
char image_name_prefix[MAX_FILENAME_LEN] = {0};
|
||
char image_name_suffix[MAX_FILENAME_LEN] = {0};
|
||
|
||
int dual_image = 0;
|
||
int mtd_type = 0;
|
||
|
||
fprintf(stderr, "YangXv <yangxu@tp-link.com.cn> modified from trx for make image\n");
|
||
|
||
static const struct option arg_options[] = {
|
||
{"flashsize", required_argument, 0, 's'},
|
||
{"bootsize", required_argument, 0, 'l'},
|
||
{"maxkernelsize", required_argument, 0, 'm'},
|
||
{"miscsize", required_argument, 0, 'n'},
|
||
{"targetEndian",required_argument, 0, 'e'},
|
||
{"boot", required_argument, 0, 'b'},
|
||
{"kernel", required_argument, 0, 'k'},
|
||
{"fs", required_argument, 0, 'f'},
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
{"romfile", required_argument, 0, 'r'},
|
||
#endif
|
||
/* End Add. */
|
||
{"output", required_argument, 0, 'o'},
|
||
{"xmlName", required_argument, 0, 'p'},
|
||
{"imagep", required_argument, 0, 'i'},
|
||
{"vmlinux", required_argument, 0, 'v'},
|
||
{"dualImage", required_argument, 0, 'd'},
|
||
{"mtdType", required_argument, 0, 't'},
|
||
{"confrom", required_argument, 0, 'c'},
|
||
{"help", no_argument, 0, 'h'},
|
||
{0, 0, 0, 0}
|
||
};
|
||
|
||
/* get options */
|
||
while (1) {
|
||
int option_index = 0;
|
||
/* Modified By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifndef GPON_HGU_MTK_FLASH
|
||
c = getopt_long(argc, argv, "s:l:m:n:e:b:k:f:o:p:i:c:v:d:t:h", arg_options, &option_index);
|
||
#else
|
||
c = getopt_long(argc, argv, "s:l:m:n:e:b:k:f:r:o:p:i:c:v:d:t:h", arg_options, &option_index);
|
||
#endif
|
||
/* End Modify. */
|
||
if (c == -1) break;
|
||
|
||
switch (c) {
|
||
case 's':
|
||
sscanf(optarg, "%X", &l_flash_size);
|
||
break;
|
||
case 'l':
|
||
sscanf(optarg, "%X", &l_boot_size);
|
||
break;
|
||
case 'm':
|
||
sscanf(optarg, "%X", &l_kernel_size);
|
||
break;
|
||
case 'n':
|
||
sscanf(optarg, "%X", &l_misc_size);
|
||
break;
|
||
case 'e':
|
||
sscanf(optarg, "%d", &l_target_endian);
|
||
break;
|
||
case 'b':
|
||
strncpy(filename[BOOT], optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'k':
|
||
strncpy(filename[KERNEL], optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'f':
|
||
strncpy(filename[FS], optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
case 'r':
|
||
strncpy(filename[ROMFILE], optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
#endif
|
||
/* End Add. */
|
||
case 'v':
|
||
strncpy(vmlinux_name, optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'o':
|
||
strncpy(prefix, optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'p':
|
||
strncpy(reduced_xml_name, optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'i':
|
||
strncpy(image_path, optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'd':
|
||
dual_image = 1;
|
||
break;
|
||
case 't':
|
||
sscanf(optarg, "%d", &mtd_type);
|
||
break;
|
||
case 'c':
|
||
strncpy(filename[CONFIG], optarg,
|
||
strlen(optarg) > MAX_FILENAME_LEN?MAX_FILENAME_LEN:strlen(optarg));
|
||
break;
|
||
case 'h':
|
||
usage();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (filename[BOOT] == 0 || filename[KERNEL] == 0 || filename[FS] == 0
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
|| filename[ROMFILE] == 0
|
||
#endif
|
||
/* End Add. */
|
||
|| image_path[0] == 0 || vmlinux_name[0] == 0)
|
||
{
|
||
fprintf(stderr, "None file name\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
if (-1 == l_target_endian)
|
||
{
|
||
fprintf(stderr, "Must set cpu endian\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
/* malloc image buffer */
|
||
if (l_flash_size == 0)
|
||
{
|
||
fprintf(stderr, "Must set flash size\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
if (!(buf = malloc(l_flash_size)))
|
||
{
|
||
fprintf(stderr, "malloc failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
memset(buf, 0xFF, l_flash_size);
|
||
|
||
if (l_boot_size == 0)
|
||
{
|
||
fprintf(stderr, "None MAX Bootloader size\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
/* add by yangxv for accept dynamic max kernel size, 2011.11.20 */
|
||
if (l_kernel_size == 0)
|
||
{
|
||
fprintf(stderr, "None MAX kernel size\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
if (l_misc_size == 0)
|
||
{
|
||
fprintf(stderr, "None Reserved for Misc size\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
l_flash_struct.bootOffset = 0;
|
||
l_flash_struct.kernelOffset = l_boot_size;
|
||
l_flash_struct.rootfsOffset = l_flash_struct.kernelOffset + l_kernel_size;
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
/* Ĭ<><C4AC>boot<6F><74><EFBFBD>벿<EFBFBD>ִ<EFBFBD>romfile */
|
||
l_flash_struct.romfileOffset = l_boot_size >> 1;
|
||
#endif
|
||
/* End Add. */
|
||
l_flash_struct.configOffset = l_flash_size - l_misc_size + 5 * MTD_BLOCK_SIZE;
|
||
l_flash_struct.appSize = l_flash_size - l_boot_size - l_misc_size;
|
||
fprintf(stderr, "configOffset is %x\n", l_flash_struct.configOffset);
|
||
fprintf(stderr, "appSize is %x\n", l_flash_struct.appSize);
|
||
fprintf(stderr, "bootOffset is %x\n", l_flash_struct.bootOffset);
|
||
/* Added By Shangguan Weijie, 2017-02-23. */
|
||
/* Just for MTK PON model */
|
||
#ifdef GPON_HGU_MTK_FLASH
|
||
/* Ĭ<><C4AC>boot<6F><74><EFBFBD>벿<EFBFBD>ִ<EFBFBD>romfile */
|
||
fprintf(stderr, "romfileOffset is %x\n", l_flash_struct.romfileOffset);
|
||
#endif
|
||
/* End Add. */
|
||
fprintf(stderr, "kernelOffset is %x\n", l_flash_struct.kernelOffset);
|
||
fprintf(stderr, "rootfsOffset is %x\n", l_flash_struct.rootfsOffset);
|
||
/* end added */
|
||
|
||
if (getVersion(reduced_xml_name) < 0)
|
||
{
|
||
fprintf(stderr, "get version error!\n");
|
||
return -1;
|
||
}
|
||
|
||
replaceBlank(l_dev_info.model_name);
|
||
|
||
fprintf(stderr, "ModelName is %s\n", l_dev_info.model_name);
|
||
fprintf(stderr, "BuildSpec is %s\n", l_dev_info.build_spec);
|
||
fprintf(stderr, "product_id is 0x%08x\n", l_dev_info.product_id);
|
||
fprintf(stderr, "product_ver is 0x%08x\n", l_dev_info.product_ver);
|
||
fprintf(stderr, "swRevision is 0x%08x\n", l_dev_info.sw_revision);
|
||
fprintf(stderr, "platformVer is 0x%08x\n", l_dev_info.platform_ver);
|
||
fprintf(stderr, "addHwVer is 0x%08x\n", l_dev_info.add_hver);
|
||
fprintf(stderr, "specilaVer is 0x%08x\n", l_dev_info.special_ver);
|
||
fprintf(stderr, "devModelVer is v%d\n", strtoul(l_dev_info.dev_ver, 0, 0));
|
||
fprintf(stderr, "buildDate is %s\n", l_dev_info.build_date);
|
||
fprintf(stderr, "buildTime is %d\n", l_dev_info.build_time);
|
||
fprintf(stderr, "isBeta is %d\n", l_dev_info.is_beta);
|
||
fprintf(stderr, "isTrans is %d\n", l_dev_info.is_trans);
|
||
fprintf(stderr, "isDateCode is %d\n\n", l_dev_info.is_datecode);
|
||
|
||
fill_buffer(buf, filename, vmlinux_name);
|
||
|
||
if (l_dev_info.is_datecode==1)
|
||
{
|
||
sprintf(image_name_prefix, "%s/%s(%s)v%d",
|
||
image_path,
|
||
(prefix[0] == 0) ? l_dev_info.model_name : prefix,
|
||
l_dev_info.build_spec,
|
||
strtoul(l_dev_info.dev_ver, 0, 0));
|
||
}
|
||
else
|
||
{
|
||
sprintf(image_name_prefix, "%s/%s(%s)v%d_%d.%d.0_%d.%d.%d",
|
||
image_path,
|
||
(prefix[0] == 0) ? l_dev_info.model_name : prefix,
|
||
l_dev_info.build_spec,
|
||
strtoul(l_dev_info.dev_ver, 0, 0),
|
||
(l_dev_info.sw_revision >> 8) & 0xff,
|
||
l_dev_info.sw_revision & 0xff,
|
||
(l_dev_info.platform_ver >> 16) & 0xff,
|
||
(l_dev_info.platform_ver >> 8) & 0xff,
|
||
l_dev_info.platform_ver & 0xff);
|
||
|
||
}
|
||
|
||
if (l_dev_info.is_datecode==1)
|
||
{
|
||
sprintf(image_name_suffix, "Datecode%s%02u%02u", l_dev_info.build_date, l_dev_info.build_time/3600, (l_dev_info.build_time%3600)/60);
|
||
}
|
||
else
|
||
{
|
||
sprintf(image_name_suffix, "%s", l_dev_info.is_trans? "_trans": (l_dev_info.is_beta? "_beta":""));
|
||
}
|
||
|
||
sprintf(bin_file, "%s_flash(%s)%s.bin", image_name_prefix, l_dev_info.build_date, image_name_suffix);
|
||
sprintf(update_file, "%s_up(%s)%s.bin", image_name_prefix, l_dev_info.build_date, image_name_suffix);
|
||
|
||
if (l_dev_info.is_datecode==1)
|
||
{
|
||
sprintf(update_file_boot, "%s_%s.bin", image_name_prefix, image_name_suffix);
|
||
sprintf(update_file_boot_nodate, "%s_%s.bin", image_name_prefix, "Datecode");
|
||
}
|
||
else
|
||
{
|
||
sprintf(update_file_boot, "%s_up_boot(%s)%s.bin", image_name_prefix, l_dev_info.build_date, image_name_suffix);
|
||
sprintf(update_file_boot_nodate, "%s_up_boot%s.bin", image_name_prefix, image_name_suffix);
|
||
}
|
||
|
||
sprintf(bin_file_nodate, "%s_flash%s.bin", image_name_prefix, image_name_suffix);
|
||
if (prefix[0] == 0)
|
||
{
|
||
sprintf(tag_kernel, "%s_tag_kernel(%s).bin", image_name_prefix, l_dev_info.build_date);
|
||
}
|
||
else
|
||
{
|
||
sprintf(tag_kernel, "%s/%s_tag_kernel.bin", image_path, prefix);
|
||
}
|
||
|
||
|
||
#if FULL_BUILD
|
||
if(l_dev_info.is_beta==0 && l_dev_info.is_trans==0 && l_dev_info.is_datecode==0)
|
||
{
|
||
/* create image */
|
||
if (!(out = fopen(bin_file, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", bin_file);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
/* end create */
|
||
|
||
/* create image */
|
||
if (!(out = fopen(bin_file_nodate, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", bin_file_nodate);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
/* end create */
|
||
}
|
||
/* only provide update firmware with bootloader
|
||
* yangxv, 2013.05.07
|
||
*/
|
||
#if 0
|
||
/* create update firmware without bootloader */
|
||
if (!(out = fopen(update_file, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", update_file);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + l_flash_struct.kernelOffset + BOOTLOADER_TAG_LEN, l_flash_struct.configOffset - l_flash_struct.kernelOffset, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
/* end create */
|
||
#endif
|
||
|
||
/* create update firmware with bootloader */
|
||
if (!(out = fopen(update_file_boot, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", update_file_boot);
|
||
usage();
|
||
}
|
||
|
||
int up_boot_len = l_flash_struct.appSize + (l_flash_struct.kernelOffset - l_flash_struct.bootOffset) + BOOTLOADER_TAG_LEN;
|
||
|
||
if (!fwrite(buf, up_boot_len, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
/* end create */
|
||
|
||
if(l_dev_info.is_trans==0)
|
||
{
|
||
/* create update firmware with bootloader */
|
||
if (!(out = fopen(update_file_boot_nodate, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", update_file_boot_nodate);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf, up_boot_len, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
/* end create */
|
||
}
|
||
|
||
if (1 == dual_image && l_dev_info.is_beta==0 && l_dev_info.is_trans==0 && l_dev_info.is_datecode==0)
|
||
{
|
||
sprintf(bin_file, "%s_flash_%dM(%s)%s.bin", image_name_prefix, l_flash_size*2/0x100000, l_dev_info.build_date, image_name_suffix);
|
||
|
||
if (!(out = fopen(bin_file, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", bin_file);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) ||
|
||
!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
sprintf(bin_file, "%s_flash_%dM%s.bin", image_name_prefix, l_flash_size*2/0x100000, image_name_suffix);
|
||
|
||
if (!(out = fopen(bin_file, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", bin_file);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) ||
|
||
!fwrite(buf + BOOTLOADER_TAG_LEN, l_flash_size, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
|
||
fclose(out);
|
||
}
|
||
|
||
#else /* FULL_BUILD */
|
||
/* create kernel with tag */
|
||
if (!(out = fopen(tag_kernel, "w"))) {
|
||
fprintf(stderr, "can not open \"%s\" for writing\n", tag_kernel);
|
||
usage();
|
||
}
|
||
|
||
if (!fwrite(buf + l_flash_struct.kernelOffset + BOOTLOADER_TAG_LEN, l_flash_struct.rootfsOffset - l_flash_struct.kernelOffset, 1, out) || fflush(out)) {
|
||
fprintf(stderr, "fwrite failed\n");
|
||
return EXIT_FAILURE;
|
||
}
|
||
/*end create */
|
||
#endif /* FULL_BUILD */
|
||
|
||
free(buf);
|
||
|
||
return EXIT_SUCCESS;
|
||
}
|