blob: f99fd62260a10b5091e8119619e2cd6080f610d7 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <cfgparse.h>
int verbose = 0;
#define dprintf(fmt, args...) if (verbose) printf(fmt, ##args)
static void
print_usage(void)
{
printf
("Usage: build_romfs [-?] [--help] [-s|--romfs-size <romfs_size>]\n"
"\t[-p|--smart-pad] [-n|--notime] <config-file> <output-file>\n");
}
unsigned long
str_to_num(const char *str)
{
char *s = (char *) str;
unsigned long num = strtoul(s, &s, 0);
if (s) {
if (s[0] == 'K')
num <<= 10;
if (s[0] == 'M')
num <<= 20;
}
return num;
}
/*
* NOTE: We should consider to install an exit handler which does the
* unlink() of the output file. In case of error we just do exit() and
* forget about all the clumsy error handling free/close code, which
* blows up the code significantly and makes it hard to read.
*/
int
main(int argc, char *argv[])
{
int conf_file, rc;
struct ffs_chain_t ffs_chain;
int c;
int smart_pad = 0; /* default */
int notime = 0;
const char *config_file = "boot_rom.ffs";
const char *output_file = "boot_rom.bin";
memset((void *) &ffs_chain, 0, sizeof(struct ffs_chain_t));
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"romfs-size", 1, 0, 's'},
{"smart-pad", 0, 0, 'p'},
{"notime", 0, 0, 'n'},
{"verbose", 0, 0, 'v'},
{"help", 1, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "s:ph?nv", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
case 's':
ffs_chain.romfs_size = str_to_num(optarg);
break;
case 'p':
smart_pad = 1;
break;
case 'n':
notime = 1;
break;
case 'v':
verbose = 1;
break;
case '?':
case 'h':
print_usage();
return EXIT_SUCCESS;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
/* two files must always be specified: config-file and output-file */
if (optind + 2 != argc) {
print_usage();
return EXIT_FAILURE;
}
config_file = argv[optind++];
output_file = argv[optind++];
dprintf("ROMFS FILESYSTEM CREATION V0.3 (bad parser)\n"
"Build directory structure...\n"
" smart padding %s, maximum romfs size %d bytes\n",
smart_pad ? "enabled" : "disabled", ffs_chain.romfs_size);
conf_file = open(config_file, O_RDONLY);
if (0 >= conf_file) {
perror("load config file:");
return EXIT_FAILURE;
}
rc = read_config(conf_file, &ffs_chain);
close(conf_file);
if (rc < 1) {
fprintf(stderr, "flash cannot be built due to config errors\n");
return EXIT_FAILURE;
}
rc = EXIT_SUCCESS;
if (verbose)
dump_fs_contents(&ffs_chain);
if (smart_pad)
/* FIXME: size is only verified during reorder */
rc = reorder_ffs_chain(&ffs_chain);
if (rc == EXIT_FAILURE)
goto out;
dprintf("Build ffs and write to image file...\n");
if (build_ffs(&ffs_chain, output_file, notime) != 0) {
fprintf(stderr, "build ffs failed\n");
rc = EXIT_FAILURE;
} else {
rc = EXIT_SUCCESS;
}
/* Check if there are any duplicate entries in the image,
print warning if this is the case. */
find_duplicates(&ffs_chain);
free_chain_memory(&ffs_chain);
dprintf("\n");
out:
/* If the build failed, remove the target image file */
if (rc == EXIT_FAILURE)
unlink(output_file);
return rc;
}