/*
 * main.c  -  Utility program to create a bootrom image
 *
 * Copyright (C) 1997-2007 Gero Kuhlmann <gero@gkminix.han.de>
 *
 *  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
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: main.c,v 1.20 2007/02/01 12:09:21 gkminix Exp $
 */

#include <common.h>
#include <nblib.h>
#include "makerom.h"
#include "doconfig.h"



/*
 * Public variables
 */
unsigned long serno = 0L;		/* bootrom serial number */



/*
 * Private variables
 */
static char *batchname = NULL;		/* name of system to batch process */



/*
 * Strings representing various configuration constants
 */
static char *bnames[] = { "ISA", "EISA", "MCA", "PCI" };
static char *dnames[] = { "packet", "ndis", "undi" };
static char *onames[] = { "binary",
				"intel hex", "motorola hex", "tektronix hex",
				"bios", "flash" };



/*
 * Copyright information
 */
static char *copyright[] = {
	COPYRIGHT,
	NULL
};



/*
 * Command line options
 */
static struct cmdopt opts[] = {
	{ NULL, 0, copyrightmsg, {copyright}, NULL, NULL		},
	{ "batch-sys", 'b', strval, {&batchname},
	  "name of system to process", "SYSTEM"				},
	{ "drivers", 'd', strval, {&config.drvdbname},
	  "name of file with network driver definitions", "FILE"	},
	{ "md5sums", 'm', strval, {&config.md5fname},
	  "name of file with network driver MD5 sums", "FILE"		},
	{ NULL, 0, noval, {NULL}, NULL, NULL				}
};



/*
 * Print boot definition record for debugging purposes
 */
static void printbootdef __F((bp), const struct bootdef *bp)
{
  int i;

  if (bp->name != NULL)
	prnlog(LOGLEVEL_INFO, "Bootrom building definitions for %s\n",
								bp->name);
  else
	prnlog(LOGLEVEL_INFO, "Bootrom building definitions\n");
  prnlog(LOGLEVEL_INFO, "Kernel file         = %s\n", bp->kernelname);
  prnlog(LOGLEVEL_INFO, "Kernel flags        = %d\n", bp->kernel_flags);

  if (bp->bus_type != BUSTYPE_NONE)
	prnlog(LOGLEVEL_INFO, "Bus type            = %s\n",
						bnames[bp->bus_type - 1]);

  if (bp->bus_type == BUSTYPE_PCI) {
	prnlog(LOGLEVEL_INFO, "PCI vendor ID       = %04X\n", bp->pci_vendid);
	prnlog(LOGLEVEL_INFO, "PCI device ID       = %04X\n", bp->pci_devid);
  } else if (bp->pnp_devid != NULL)
	prnlog(LOGLEVEL_INFO, "PnP device ID       = %s\n", bp->pnp_devid);
  prnlog(LOGLEVEL_INFO, "\n");

  for (i = 0; i < bp->loadernum; i++) {
	prnlog(LOGLEVEL_INFO, "Loader binary %d     = %s\n", i,
					bp->loaders[i].name);
	prnlog(LOGLEVEL_INFO, "Output file %d       = %s (int %dh)\n", i,
					bp->loaders[i].outname,
					bp->loaders[i].useint18 ? 18 : 19);
	prnlog(LOGLEVEL_INFO, "Size of ROM image %d = ", i);
	if (bp->loaders[i].outsize > 0)
		prnlog(LOGLEVEL_INFO, "%d kB\n", bp->loaders[i].outsize);
	else
		prnlog(LOGLEVEL_INFO, "default\n");
	prnlog(LOGLEVEL_INFO, "Type of out file %d  = %s\n", i,
					onames[bp->loaders[i].outtype - 1]);
  }
  prnlog(LOGLEVEL_INFO, "\n");

  prnlog(LOGLEVEL_INFO, "Network interface   = %s (%s)\n", bp->netdrv.name,
					dnames[bp->netdrv.drivertype - 1]);

  if (bp->netdrv.drivertype == DRVTYPE_PD) {
	const struct progdef *pdp = &(bp->netdrv.driverdefs.pd.progs);

	for (i = 0; i < pdp->prognum; i++) {
		prnlog(LOGLEVEL_INFO, "Driver %d program    = %s\n", i,
					pdp->prognames[i]);
		prnlog(LOGLEVEL_INFO, "Driver %d arguments  = ", i);
		if (pdp->progargs[i] != NULL)
			prnlog(LOGLEVEL_INFO, "%s\n", pdp->progargs[i]);
		else
			prnlog(LOGLEVEL_INFO, "none\n");
	}
  } else if (bp->netdrv.drivertype == DRVTYPE_NDIS) {
	const struct progdef *np = &(bp->netdrv.driverdefs.ndis.progs);

	for (i = 0; i < np->prognum; i++) {
		prnlog(LOGLEVEL_INFO, "Driver %d program    = %s\n", i,
					np->prognames[i]);
		prnlog(LOGLEVEL_INFO, "Driver %d arguments  = ", i);
		if (np->progargs[i] != NULL)
			prnlog(LOGLEVEL_INFO, "%s\n", np->progargs[i]);
		else
			prnlog(LOGLEVEL_INFO, "none\n");
	}
  } else if (bp->netdrv.drivertype == DRVTYPE_UNDI) {
	const struct undidef *up = &(bp->netdrv.driverdefs.undi);

	prnlog(LOGLEVEL_INFO, "Driver file         = %s\n", up->name);
  }
  prnlog(LOGLEVEL_INFO, "\n");
}



/*
 * Main program
 */
int main __F((argc, argv), int argc AND char **argv)
{
  struct bootdef *bp;

  /* Parse command line and read configuration information */
  doconfig(argc, argv, opts);
  prnlog(LOGLEVEL_NORMAL, "\nBootrom configuration program, " VERSION "\n"
							COPYRIGHT "\n\n");
  prnlog(LOGLEVEL_NOTICE, "Binaries directory         = %s\n",
						config.bindir);
  prnlog(LOGLEVEL_NOTICE, "Network driver directory   = %s\n",
						config.netdrvdir);
  prnlog(LOGLEVEL_NOTICE, "Utilities directory        = %s\n",
						config.utilsdir);
  if (config.drvdbname != NULL)
	prnlog(LOGLEVEL_NOTICE, "Driver definition database = %s\n",
						config.drvdbname);
  if (config.md5fname != NULL)
	prnlog(LOGLEVEL_NOTICE, "Driver MD5 sums file       = %s\n",
						config.md5fname);
  prnlog(LOGLEVEL_NOTICE,"\n");

  /* Get bootrom specification either from the user or the database */
  if (batchname != NULL)
	bp = getdb(batchname);
  else
	bp = getuser();

  /* Generate output files */
  printbootdef(bp);
  dopasses(bp);
  prnlog(LOGLEVEL_NORMAL, "Generated bootrom with serial number 0x%lx\n",
								serno);

  /* Write system definition to systems database */
  if (batchname == NULL && bp->name != NULL) {
	putdb(bp);
	prnlog(LOGLEVEL_NORMAL, "Wrote database entry \"%s\"\n", bp->name);
  }
  nbexit(EXIT_SUCCESS);
#if !defined(__GNUC__) || __GNUC__ < 3
  /* Make the compiler happy, GCC knows that nbexit() never returns */
  return(0);
#endif
}

