mirror of
https://github.com/gnuton/asuswrt-merlin.ng.git
synced 2025-05-18 23:41:30 +02:00
742 lines
26 KiB
C
742 lines
26 KiB
C
/***********************************************************************
|
|
*
|
|
* Copyright (c) 2010 Broadcom Corporation
|
|
* All Rights Reserved
|
|
*
|
|
<:label-BRCM:2012:DUAL/GPL:standard
|
|
|
|
Unless you and Broadcom execute a separate written software license
|
|
agreement governing use of this software, this software is licensed
|
|
to you under the terms of the GNU General Public License version 2
|
|
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
|
|
with the following added to such license:
|
|
|
|
As a special exception, the copyright holders of this software give
|
|
you permission to link this software with independent modules, and
|
|
to copy and distribute the resulting executable under terms of your
|
|
choice, provided that you also meet, for each linked independent
|
|
module, the terms and conditions of the license of that module.
|
|
An independent module is a module which is not derived from this
|
|
software. The special exception does not apply to any modifications
|
|
of the software.
|
|
|
|
Not withstanding the above, under no circumstances may you combine
|
|
this software in any way with any other Broadcom software provided
|
|
under a license other than the GPL, without Broadcom's express prior
|
|
written consent.
|
|
|
|
:>
|
|
*
|
|
************************************************************************/
|
|
|
|
//**************************************************************************************
|
|
// File Name : bcmImageBuilder.c
|
|
//
|
|
// Description: Build a image with a header (tag), a compressed kernel and
|
|
// a compress JFFS2 root file system
|
|
//
|
|
// Created : 04/23/2002
|
|
//
|
|
// Modified : 05/18/2002
|
|
// Redefined the tag info. Add imageType and getting all the flash address
|
|
// from "board.h" which is shared by CFE and web uploading code.
|
|
//
|
|
// : 04/18/2003 seanl
|
|
// add the support for cramfs and new flash image layout:
|
|
// 1). minicfe : 64k
|
|
// 2). TAG: 256b
|
|
// 3). cramfs:
|
|
// 4). kernel:
|
|
// 5). psi: 16k (default)
|
|
//
|
|
//
|
|
//**************************************************************************************
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <netinet/in.h>
|
|
#include "include/bcmTargetEndian.h"
|
|
|
|
#define BCMTAG_EXE_USE
|
|
#include "bcmTag.h"
|
|
|
|
/* The BCM963xx flash memory map contains five sections: boot loader,
|
|
* file system, kernel, nvram storage, persistent storage. This program
|
|
* defines the starting address for the boot loader, file system and kernel.
|
|
* The run-time flash driver determines the starting address of the nvram
|
|
* and persistent storage sections based on the flash part size.
|
|
*/
|
|
#include "board.h"
|
|
|
|
/* Typedefs.h */
|
|
typedef unsigned char byte;
|
|
typedef unsigned int UINT32;
|
|
|
|
typedef struct _img_option {
|
|
int littleendian;
|
|
char *chipid;
|
|
char *board;
|
|
unsigned int blksize;
|
|
char *imageversion;
|
|
char *outputfile;
|
|
char *cfefile;
|
|
char *rootfsfile;
|
|
char *kernelfile;
|
|
char *dtb_mdata_file;
|
|
int includecfe;
|
|
int emmcimage;
|
|
int imageflags;
|
|
}img_option;
|
|
|
|
#define BUF_SIZE 100 * 1024
|
|
static byte buffer[BUF_SIZE];
|
|
|
|
/*
|
|
struct option {
|
|
char *name;
|
|
int has_arg;
|
|
int *flag;
|
|
int val;
|
|
};
|
|
|
|
The name field should contain the option name without the leading double
|
|
dash.
|
|
The has_arg field should be one of:
|
|
no_argument no argument to the option is expect.
|
|
required_argument an argument to the option is required.
|
|
optional_argument an argument to the option may be presented.
|
|
If flag is non-NULL, then the integer pointed to by it will be set to the
|
|
value in the val field. If the flag field is NULL, then the val field
|
|
will be returned. Setting flag to NULL and setting val to the correspond-
|
|
ing short option will make this function act just like getopt(3).
|
|
*/
|
|
static struct option longopts[] = {
|
|
{ "help", 0, 0, 'h' },
|
|
{ "version", 0, 0, 'v' },
|
|
{ "littleendian", 0, 0, 'l'},
|
|
{ "bigendian", 0, 0, 'b'},
|
|
{ "chip", 1, 0, 0},
|
|
{ "board", 1, 0, 0},
|
|
{ "blocksize", 1, 0, 0},
|
|
{ "image-version", 1, 0, 0},
|
|
{ "output", 1, 0, 0},
|
|
{ "cfefile", 1, 0, 0},
|
|
{ "rootfsfile", 1, 0, 0},
|
|
{ "kernelfile", 1, 0, 0},
|
|
{ "bootfsfile", 1, 0, 0},
|
|
{ "dtbfile", 1, 0, 0},
|
|
{ "mdatafile", 1, 0, 0},
|
|
{ "include-cfe", 0, 0, 'i'},
|
|
{ "ddrtype", 1, 0, 0},
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
static char version[] = "Broadcom Image Builder version 0.3";
|
|
|
|
static char usage[] = "Usage:\t%s {-h|--help|-v|--version}\n"
|
|
"\t[--littleendian]\n"
|
|
"\t--chip <chipid> -- chip id {63268|6328|6362|6368|6816|6818|6828}\n"
|
|
"\t--board <boardid> --blocksize {64|128}\n"
|
|
"\t--ddrtype ddr3|ddr4\n"
|
|
"\t--output <filename> --cfefile <filename>\n"
|
|
"\tNOR Image:\n"
|
|
"\t[--rootfsfile <filename> --kernelfile <filename> --dtbfile <filename> [-i|--include-cfe]]\n"
|
|
"\teMMC Image:\n"
|
|
"\t[--rootfsfile <filename> --bootfsfile <filename> --mdatafile <filename> [-i|--include-cfe]]\n";
|
|
|
|
static char *progname;
|
|
|
|
/***************************************************************************
|
|
// Function Name: getCrc32
|
|
// Description : caculate the CRC 32 of the given data.
|
|
// Parameters : pdata - array of data.
|
|
// size - number of input data bytes.
|
|
// crc - either CRC32_INIT_VALUE or previous return value.
|
|
// Returns : crc.
|
|
****************************************************************************/
|
|
UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc)
|
|
{
|
|
while (size-- > 0)
|
|
crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
|
|
|
|
return crc;
|
|
}
|
|
|
|
/***************************************************************************
|
|
// Function Name: build image
|
|
// Description : builds a complete norflash or emmc image
|
|
// Parameters : little endian - endianess.
|
|
// chipid - chipid
|
|
// board - boardid
|
|
// blksize - flash block size for combined cfe(NOR) or cferom(EMMC)
|
|
// imageversiona - image version
|
|
// outputfile - final output image name
|
|
// cfefile - Name of cfe(NOR) or cferom(EMMC) binary
|
|
// rootfsfile - root fs image name
|
|
// kernelfile - compressed kernel(NOR) or bootfs image(EMMC) name
|
|
// dtb_mdata_file- dtb(NOR) or metadata blob(EMMC) name
|
|
// includecfe - flag to to include cfe(NOR) or cferom(EMMC)
|
|
// emmcimage - flag to indicate an emmcimage build
|
|
// imageflags - image flag such ddr type, same as wfiTag
|
|
// Returns : none.
|
|
****************************************************************************/
|
|
static void build_image(img_option* opt)
|
|
{
|
|
FILE *stream_cfe = NULL;
|
|
FILE *stream_rootfs = NULL;
|
|
FILE *stream_kernel = NULL;
|
|
FILE *stream_dtb_mdata = NULL;
|
|
FILE *stream_output = NULL;
|
|
unsigned int total_size, cfe_size, rootfs_size, kernel_size, dtb_mdata_size, count, numWritten;
|
|
unsigned int cfeaddr = 0;
|
|
unsigned int fskerneladdr;
|
|
FILE_TAG tag;
|
|
UINT32 imageCrc, tagCrc, fsCrc, kernelCrc, dtb_mdata_crc;
|
|
|
|
/* emmc image starts right after the TAG */
|
|
if( opt->emmcimage )
|
|
cfeaddr = 0;
|
|
else
|
|
cfeaddr = IMAGE_BASE;
|
|
|
|
if ((stream_cfe = fopen(opt->cfefile, "rb")) == NULL) {
|
|
printf("bcmImageBuilder: Failed to open cfe file: %s\n", opt->cfefile);
|
|
fclose(stream_cfe);
|
|
exit(1);
|
|
}
|
|
|
|
if (strlen(opt->rootfsfile) != 0 && strlen(opt->kernelfile) != 0 && strlen(opt->dtb_mdata_file) != 0) {
|
|
if ((stream_rootfs = fopen(opt->rootfsfile, "rb")) == NULL) {
|
|
printf("bcmImageBuilder: Failed to open root file system file: %s\n", opt->rootfsfile);
|
|
fclose(stream_cfe);
|
|
exit(1);
|
|
}
|
|
if ((stream_kernel = fopen(opt->kernelfile, "rb")) == NULL) {
|
|
printf("bcmImageBuilder: Filed to open kernel file: %s\n", opt->kernelfile);
|
|
fclose(stream_cfe);
|
|
fclose(stream_rootfs);
|
|
exit(1);
|
|
}
|
|
if ((stream_dtb_mdata = fopen(opt->dtb_mdata_file, "rb")) == NULL) {
|
|
printf("bcmImageBuilder: Filed to open dtb file: %s\n", opt->dtb_mdata_file);
|
|
fclose(stream_cfe);
|
|
fclose(stream_rootfs);
|
|
fclose(stream_kernel);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if((stream_output = fopen(opt->outputfile, "wb")) == NULL) {
|
|
printf("bcmImageBuilder: Failed to create output file: %s\n", opt->outputfile);
|
|
fclose(stream_cfe);
|
|
fclose(stream_kernel);
|
|
fclose(stream_rootfs);
|
|
fclose(stream_dtb_mdata);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
total_size = cfe_size = rootfs_size = kernel_size = dtb_mdata_size = count = 0;
|
|
imageCrc = CRC32_INIT_VALUE;
|
|
fsCrc = CRC32_INIT_VALUE;
|
|
kernelCrc = CRC32_INIT_VALUE;
|
|
dtb_mdata_crc = CRC32_INIT_VALUE;
|
|
while (!feof( stream_cfe )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_cfe);
|
|
if (ferror( stream_cfe)) {
|
|
perror( "bcmImageBuilder: Read error" );
|
|
exit(1);
|
|
}
|
|
imageCrc = getCrc32(buffer, count, imageCrc);
|
|
/* Total up actual bytes read */
|
|
total_size += count;
|
|
cfe_size += count;
|
|
}
|
|
|
|
if( cfe_size > opt->blksize ){
|
|
printf("bcmImageBuilder: cfe size too large, maximum size %d\n", opt->blksize);
|
|
fclose(stream_cfe);
|
|
fclose(stream_kernel);
|
|
fclose(stream_rootfs);
|
|
fclose(stream_dtb_mdata);
|
|
exit(1);
|
|
}
|
|
|
|
/* For eMMC: image layout doesnt correspond to flash layout, so start
|
|
* bootfs right after.
|
|
* For NOR: Calculate address after cfe in flash; Tag is before fs now */
|
|
if( opt->emmcimage )
|
|
/* If cferom is included, fskernel starts after cfe
|
|
* if not, then fskernel starts right after tag */
|
|
if( opt->includecfe )
|
|
fskerneladdr = cfeaddr + cfe_size;
|
|
else
|
|
fskerneladdr = 0;
|
|
else
|
|
fskerneladdr = cfeaddr + opt->blksize;
|
|
|
|
if (stream_rootfs && stream_kernel && stream_dtb_mdata) {
|
|
if (!opt->includecfe) {
|
|
/* CFE is not included in this image */
|
|
total_size = 0;
|
|
imageCrc = CRC32_INIT_VALUE;
|
|
fclose(stream_cfe);
|
|
stream_cfe = NULL;
|
|
}
|
|
|
|
while (!feof( stream_rootfs )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_rootfs);
|
|
if (ferror( stream_rootfs)) {
|
|
perror( "bcmImageBuilder: Read error" );
|
|
exit(1);
|
|
}
|
|
imageCrc = getCrc32(buffer, count, imageCrc);
|
|
fsCrc = getCrc32(buffer, count, fsCrc);
|
|
/* Total up actual bytes read */
|
|
total_size += count;
|
|
rootfs_size += count;
|
|
}
|
|
|
|
while (!feof( stream_kernel )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_kernel );
|
|
if (ferror( stream_kernel)) {
|
|
perror( "bcmImageBuilder: Read error" );
|
|
exit(1);
|
|
}
|
|
imageCrc = getCrc32(buffer, count, imageCrc);
|
|
kernelCrc = getCrc32(buffer, count, kernelCrc);
|
|
/* Total up actual bytes read */
|
|
total_size += count;
|
|
kernel_size += count;
|
|
}
|
|
|
|
while (!feof( stream_dtb_mdata )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_dtb_mdata );
|
|
if (ferror( stream_dtb_mdata)) {
|
|
perror( "bcmImageBuilder: Read error" );
|
|
exit(1);
|
|
}
|
|
imageCrc = getCrc32(buffer, count, imageCrc);
|
|
dtb_mdata_crc = getCrc32(buffer, count, dtb_mdata_crc);
|
|
/* Total up actual bytes read */
|
|
total_size += count;
|
|
dtb_mdata_size += count;
|
|
}
|
|
}
|
|
|
|
if (!stream_cfe) {
|
|
cfeaddr = 0;
|
|
cfe_size = 0;
|
|
}
|
|
|
|
if (!stream_rootfs || !stream_kernel || !stream_dtb_mdata) {
|
|
fskerneladdr = 0;
|
|
rootfs_size = 0;
|
|
kernel_size = 0;
|
|
dtb_mdata_size = 0;
|
|
}
|
|
|
|
// fill the tag structure
|
|
memset(&tag, 0, sizeof(FILE_TAG));
|
|
|
|
strcpy(tag.tagVersion, BCM_TAG_VER);
|
|
strncpy(tag.signiture_1, BCM_SIG_1, SIG_LEN -1);
|
|
strncpy(tag.signiture_2, BCM_SIG_2, SIG_LEN_2 -1);
|
|
strncpy(tag.chipId, opt->chipid, CHIP_ID_LEN - 1);
|
|
strncpy(tag.boardId, opt->board, BOARD_ID_LEN -1);
|
|
strncpy(tag.imageVersion, opt->imageversion, IMAGE_VER_LEN -1);
|
|
tag.imageFlags = opt->imageflags;
|
|
|
|
if (opt->littleendian)
|
|
strcpy(tag.bigEndian, "0");
|
|
else
|
|
strcpy(tag.bigEndian, "1");
|
|
|
|
sprintf(tag.totalImageLen,"%d",total_size);
|
|
|
|
if( opt->emmcimage )
|
|
sprintf(tag.cfeAddress, "%u", cfeaddr + TAG_LEN);
|
|
else
|
|
sprintf(tag.cfeAddress, "%u", cfeaddr);
|
|
|
|
sprintf(tag.cfeLen,"%d",cfe_size);
|
|
|
|
if (!stream_rootfs || !stream_kernel || !stream_dtb_mdata)
|
|
{
|
|
sprintf(tag.rootfsAddress,"%u",(uint32_t ) 0);
|
|
sprintf(tag.rootfsLen,"%d",rootfs_size);
|
|
sprintf(tag.kernelAddress,"%u", 0);
|
|
sprintf(tag.kernelLen,"%d",kernel_size);
|
|
if( opt->emmcimage ) {
|
|
sprintf(tag.mdataAddress,"%u", 0);
|
|
sprintf(tag.mdataLen,"%d",dtb_mdata_size);
|
|
} else {
|
|
sprintf(tag.dtbAddress,"%u", 0);
|
|
sprintf(tag.dtbLen,"%d",dtb_mdata_size);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(tag.rootfsAddress,"%u",(uint32_t ) (fskerneladdr + TAG_LEN));
|
|
sprintf(tag.rootfsLen,"%d",rootfs_size);
|
|
sprintf(tag.kernelAddress,"%u", fskerneladdr + rootfs_size + TAG_LEN);
|
|
sprintf(tag.kernelLen,"%d",kernel_size);
|
|
if( opt->emmcimage ) {
|
|
sprintf(tag.mdataAddress,"%u", fskerneladdr + rootfs_size + kernel_size + TAG_LEN);
|
|
sprintf(tag.mdataLen,"%d",dtb_mdata_size);
|
|
} else {
|
|
sprintf(tag.dtbAddress,"%u", fskerneladdr + rootfs_size + kernel_size + TAG_LEN);
|
|
sprintf(tag.dtbLen,"%d",dtb_mdata_size);
|
|
}
|
|
}
|
|
|
|
imageCrc = BCM_HOST_TO_TARGET32(imageCrc);
|
|
fsCrc = BCM_HOST_TO_TARGET32(fsCrc);
|
|
kernelCrc = BCM_HOST_TO_TARGET32(kernelCrc);
|
|
dtb_mdata_crc = BCM_HOST_TO_TARGET32(dtb_mdata_crc);
|
|
memcpy(tag.imageValidationToken, (byte*)&imageCrc, CRC_LEN);
|
|
memcpy(tag.imageValidationToken + CRC_LEN, (byte*)&fsCrc, CRC_LEN);
|
|
memcpy(tag.imageValidationToken + (CRC_LEN * 2), (byte*)&kernelCrc, CRC_LEN);
|
|
memcpy(tag.imageValidationToken + (CRC_LEN * 3), (byte*)&dtb_mdata_crc, CRC_LEN);
|
|
|
|
// get tag crc
|
|
tagCrc = CRC32_INIT_VALUE;
|
|
tagCrc = getCrc32((byte*)&tag, TAG_LEN-TOKEN_LEN, tagCrc);
|
|
tagCrc = BCM_HOST_TO_TARGET32(tagCrc);
|
|
memcpy(tag.tagValidationToken, (byte*)&tagCrc, CRC_LEN);
|
|
|
|
#ifdef DEBUG
|
|
printf ("tagVersion %s\n", tag.tagVersion);
|
|
printf ("signiture_1 %s\n", tag.signiture_1);
|
|
printf ("signiture_2 %s\n", tag.signiture_2);
|
|
printf ("chipId %s\n", tag.chipId);
|
|
printf ("boardId %s\n", tag.boardId);
|
|
printf ("bigEndian %s\n", tag.bigEndian);
|
|
printf ("totalImageLen %s\n", tag.totalImageLen);
|
|
printf ("cfeAddress %s, 0x%08X\n", tag.cfeAddress, (unsigned int)cfeaddr);
|
|
printf ("cfeLen %s\n", tag.cfeLen);
|
|
printf ("rootfsAddress %s, 0x%08X\n", tag.rootfsAddress, (unsigned int) fskerneladdr);
|
|
printf ("rootfsLen %s\n", tag.rootfsLen);
|
|
printf ("kernelAddress %s, 0x%08X\n", tag.kernelAddress, (unsigned int) (fskerneladdr + rootfs_size));
|
|
printf ("kernelLen %s\n", tag.kernelLen);
|
|
if( opt->emmcimage ) {
|
|
printf ("mdataAddress %s, 0x%08X\n", tag.dtbAddress, (unsigned int) (fskerneladdr + rootfs_size + kernel_size));
|
|
printf ("mdataLen %s\n", tag.dtbLen);
|
|
} else {
|
|
printf ("dtbAddress %s, 0x%08X\n", tag.dtbAddress, (unsigned int) (fskerneladdr + rootfs_size + kernel_size));
|
|
printf ("dtbLen %s\n", tag.dtbLen);
|
|
}
|
|
printf ("image flags 0x%x\n", tag.imageFlags);
|
|
printf ("tag structure reserve left %d\n", RESERVED_LEN);
|
|
#endif
|
|
|
|
//----------------Start to write image file---------------------------
|
|
//Write tag first
|
|
numWritten = fwrite((byte*)&tag, sizeof(byte), TAG_LEN, stream_output);
|
|
if (numWritten != TAG_LEN) {
|
|
printf("bcmImageBuilder: Failed to write tag: byte written: %d byte\n", numWritten);
|
|
exit(1);
|
|
}
|
|
|
|
//Write the cfe if exist
|
|
if (stream_cfe) {
|
|
rewind(stream_cfe);
|
|
while (!feof( stream_cfe )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_cfe );
|
|
if (ferror(stream_cfe)) {
|
|
perror("bcmImageBuilder: Read cfe file error");
|
|
exit(1);
|
|
}
|
|
numWritten = fwrite(buffer, sizeof(byte), count, stream_output);
|
|
if (ferror(stream_output)) {
|
|
perror("bcmImageBuilder: Write image file error");
|
|
exit(1);
|
|
}
|
|
}
|
|
fclose(stream_cfe);
|
|
}
|
|
|
|
//Write the rootfs
|
|
if (stream_rootfs) {
|
|
rewind(stream_rootfs);
|
|
while (!feof( stream_rootfs )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_rootfs );
|
|
if (ferror(stream_rootfs)) {
|
|
perror("bcmImageBuilder: Read root file system file error");
|
|
exit(1);
|
|
}
|
|
numWritten = fwrite(buffer, sizeof(byte), count, stream_output);
|
|
if (ferror(stream_output)) {
|
|
perror("bcmImageBuilder: Write image file error");
|
|
exit(1);
|
|
}
|
|
}
|
|
fclose(stream_rootfs);
|
|
}
|
|
|
|
//Write the kernel
|
|
if (stream_kernel) {
|
|
rewind(stream_kernel);
|
|
while (!feof( stream_kernel )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_kernel );
|
|
if (ferror(stream_kernel)) {
|
|
perror("bcmImageBuilder: Read kerenl file error");
|
|
exit(1);
|
|
}
|
|
numWritten = fwrite(buffer, sizeof(byte), count, stream_output);
|
|
if (ferror(stream_output)) {
|
|
perror("bcmImageBuilder: Write image file error");
|
|
exit(1);
|
|
}
|
|
}
|
|
fclose(stream_kernel);
|
|
}
|
|
|
|
//Write the dtb
|
|
if (stream_dtb_mdata) {
|
|
rewind(stream_dtb_mdata);
|
|
while (!feof( stream_dtb_mdata )) {
|
|
count = fread( buffer, sizeof(byte), BUF_SIZE, stream_dtb_mdata );
|
|
if (ferror(stream_dtb_mdata)) {
|
|
perror("bcmImageBuilder: Read dtb file error");
|
|
exit(1);
|
|
}
|
|
numWritten = fwrite(buffer, sizeof(byte), count, stream_output);
|
|
if (ferror(stream_output)) {
|
|
perror("bcmImageBuilder: Write image file error");
|
|
exit(1);
|
|
}
|
|
}
|
|
fclose(stream_dtb_mdata);
|
|
}
|
|
|
|
|
|
fclose(stream_output);
|
|
|
|
printf("bcmImageBuilder\n");
|
|
|
|
printf("\tTarget endianess : ");
|
|
if (opt->littleendian == 1)
|
|
printf("little\n");
|
|
else
|
|
printf("big\n");
|
|
|
|
if (stream_cfe)
|
|
printf("\tCFE image size : %u\n", cfe_size);
|
|
|
|
printf("\tFile tag size : %d\n", TAG_LEN);
|
|
|
|
if (stream_rootfs)
|
|
printf("\tRoot filesystem image size : %u\n", rootfs_size);
|
|
if (stream_kernel)
|
|
if( opt->emmcimage )
|
|
printf("\tBootfs image size : %u\n", kernel_size);
|
|
else
|
|
printf("\tKernel image size : %u\n", kernel_size);
|
|
if (stream_dtb_mdata) {
|
|
if( opt->emmcimage )
|
|
printf("\tMetadata image size : %u\n", dtb_mdata_size);
|
|
else
|
|
printf("\tDtb image size : %u\n", dtb_mdata_size);
|
|
|
|
}
|
|
|
|
printf("\tCombined image file size : %u\n\n", total_size+TAG_LEN);
|
|
}
|
|
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
int optc;
|
|
int h = 0, v = 0, littleendian = 0, includecfe = 0, lose = 0, emmcimage = 0;
|
|
int option_index = 0;
|
|
char cfefile[256], rootfsfile[256], kernelfile[256], dtb_mdata_file[256], outputfile[256];
|
|
char boardid[BOARD_ID_LEN];
|
|
char chipid[CHIP_ID_LEN];
|
|
char imageversion[IMAGE_VER_LEN*2];
|
|
unsigned int blksize = 0, imageflags =0;
|
|
img_option opt;
|
|
|
|
progname = argv[0];
|
|
chipid[0] = boardid[0] = cfefile[0] = kernelfile[0] = rootfsfile[0] = dtb_mdata_file[0] = outputfile[0] = '\0';
|
|
|
|
while ((optc = getopt_long (argc, argv, "hvbli", longopts, &option_index)) != EOF) {
|
|
switch (optc){
|
|
case 0:
|
|
#ifdef DEBUG
|
|
printf ("option %s", longopts[option_index].name);
|
|
if (optarg)
|
|
printf (" with arg %s", optarg);
|
|
printf ("\n");
|
|
#endif
|
|
if (strcmp(longopts[option_index].name, "cfefile") == 0)
|
|
strcpy(cfefile, optarg);
|
|
else if (strcmp(longopts[option_index].name, "rootfsfile") == 0)
|
|
strcpy(rootfsfile, optarg);
|
|
else if (strcmp(longopts[option_index].name, "kernelfile") == 0) {
|
|
emmcimage = 0;
|
|
strcpy(kernelfile, optarg);
|
|
}
|
|
else if (strcmp(longopts[option_index].name, "dtbfile") == 0) {
|
|
emmcimage = 0;
|
|
strcpy(dtb_mdata_file, optarg);
|
|
}
|
|
else if (strcmp(longopts[option_index].name, "bootfsfile") == 0) {
|
|
emmcimage = 1;
|
|
strcpy(kernelfile, optarg);
|
|
}
|
|
else if (strcmp(longopts[option_index].name, "mdatafile") == 0) {
|
|
emmcimage = 1;
|
|
strcpy(dtb_mdata_file, optarg);
|
|
}
|
|
else if (strcmp(longopts[option_index].name, "output") == 0)
|
|
strcpy(outputfile, optarg);
|
|
else if (strcmp(longopts[option_index].name, "chip") == 0)
|
|
strcpy(chipid, optarg);
|
|
else if (strcmp(longopts[option_index].name, "board") == 0)
|
|
strcpy(boardid, optarg);
|
|
else if (strcmp(longopts[option_index].name, "blocksize") == 0)
|
|
blksize = atoi(optarg) * 1024;
|
|
else if (strcmp(longopts[option_index].name, "image-version") == 0)
|
|
strcpy(imageversion, optarg);
|
|
else if (strcmp(longopts[option_index].name, "ddrtype") == 0) {
|
|
if (strncasecmp(optarg, "ddr3", 4) == 0)
|
|
imageflags |= WFI_FLAG_DDR_TYPE_DDR3;
|
|
else if (strncasecmp(optarg, "ddr4", 4)==0)
|
|
imageflags |= WFI_FLAG_DDR_TYPE_DDR4;
|
|
else {
|
|
fprintf (stderr, "invalid ddr type parameter %s\n", optarg);
|
|
exit (1);
|
|
}
|
|
}
|
|
break;
|
|
case 'v':
|
|
v = 1;
|
|
break;
|
|
case 'h':
|
|
h = 1;
|
|
break;
|
|
case 'b':
|
|
littleendian = 0;
|
|
break;
|
|
case 'l':
|
|
littleendian = 1;
|
|
BCM_SET_TARGET_ENDIANESS(BCM_TARGET_LITTLE_ENDIAN);
|
|
break;
|
|
case 'i':
|
|
includecfe = 1;
|
|
break;
|
|
default:
|
|
lose = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (lose || optind < argc || argc < 2)
|
|
{
|
|
/* Print error message and exit. */
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
|
|
if (v) {
|
|
/* Print version number. */
|
|
fprintf (stderr, "%s\n", version);
|
|
if (! h)
|
|
exit (0);
|
|
}
|
|
|
|
if (h) {
|
|
/* Print help info and exit. */
|
|
fprintf (stderr, "%s\n", version);
|
|
fprintf (stderr, usage, progname);
|
|
fputs ("\n", stderr);
|
|
fputs (" -h, --help Print a summary of the options\n", stderr);
|
|
fputs (" -v, --version Print the version number\n", stderr);
|
|
fputs (" -l, --littleendian Build little endian image\n", stderr);
|
|
fputs (" -b, --bigendian Build big endian image\n", stderr);
|
|
fputs (" --chip <chip id> Chip id\n", stderr);
|
|
fputs (" --board <board name> Board name\n", stderr);
|
|
fputs (" --blocksize <block size> Flash memory block size in KBytes\n", stderr);
|
|
fputs (" --output <filename> Output image file name\n", stderr);
|
|
fputs (" --cfefile <filename> CFE imgage name\n", stderr);
|
|
fputs (" --kernelfile <filename> Kernel image name\n", stderr);
|
|
fputs (" --bootfsfile <filename> eMMC bootfs image name\n", stderr);
|
|
fputs (" --dtbfile <filename> Device tree blob file name\n", stderr);
|
|
fputs (" --rootfsfile <filename> Root file system image name\n", stderr);
|
|
fputs (" --mdatafile <filename> eMMC metadata file name\n", stderr);
|
|
fputs (" -i, --include-cfe Add CFE to kernel and rootfs image\n", stderr);
|
|
fputs (" -e, --emmc-image Generate an eMMC compatible image\n", stderr);
|
|
fputs (" --ddrtype ddr3|ddr4 DDR type for the image\n", stderr);
|
|
exit (0);
|
|
}
|
|
|
|
|
|
if (strlen(chipid) == 0 || strlen(boardid) == 0 || strlen(outputfile) == 0
|
|
|| strlen(cfefile) == 0)
|
|
{
|
|
fprintf (stderr, "Required input parameters are missing\n\n");
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
|
|
if(!emmcimage)
|
|
{
|
|
if (blksize % 64*1024)
|
|
{
|
|
fprintf (stderr, "invalid block size %d, must be the multiple of 64KB\n\n", blksize);
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
if ((strlen(rootfsfile) == 0 && strlen(kernelfile) != 0) ||
|
|
(strlen(rootfsfile) != 0 && strlen(kernelfile) == 0) )
|
|
{
|
|
fprintf (stderr, "Options --rootfsfile and --kernelfile must be used together\n\n");
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
if (strlen(chipid) > (CHIP_ID_LEN - 1))
|
|
{
|
|
fprintf (stderr, "Maximum chip id length is %d characters\n\n", (CHIP_ID_LEN - 1));
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
if (strlen(boardid) > 15)
|
|
{
|
|
fprintf (stderr, "Maximum board name length is 15 characters\n\n");
|
|
fprintf (stderr, usage, progname);
|
|
exit (1);
|
|
}
|
|
if (strnlen (imageversion, IMAGE_VER_LEN) > IMAGE_VER_LEN -1)
|
|
{
|
|
imageversion[IMAGE_VER_LEN-1] = '\0';
|
|
imageversion[IMAGE_VER_LEN-2] = '+';
|
|
fprintf (stderr,"\n");
|
|
fprintf (stderr,"WARNING! bcmImageBuilder truncating version string %s exceeds maximum length\n", imageversion);
|
|
fprintf (stderr,"\n");
|
|
}
|
|
|
|
|
|
opt.littleendian = littleendian;
|
|
opt.chipid = chipid;
|
|
opt.board = boardid;
|
|
opt.blksize = blksize;
|
|
opt.imageversion = imageversion;
|
|
opt.outputfile = outputfile;
|
|
opt.cfefile = cfefile;
|
|
opt.rootfsfile = rootfsfile;
|
|
opt.kernelfile = kernelfile;
|
|
opt.dtb_mdata_file = dtb_mdata_file;
|
|
opt.includecfe = includecfe;
|
|
opt.emmcimage = emmcimage;
|
|
opt.imageflags = imageflags;
|
|
|
|
build_image(&opt);
|
|
|
|
exit(0);
|
|
}
|
|
|