1/*	$NetBSD: genprom.c,v 1.7 2007/12/25 18:33:33 perry Exp $	 */
2
3/*
4 * mainly from netbsd:sys/arch/i386/netboot/genprom.c
5 */
6
7/*
8 * Read a binary image of a bios extension, generate the
9 * appropriate block count and checksum and write them
10 * into the rom image (replacing 2nd and 5th bytes)
11 * The binary image should be sized before being filtered
12 * through this routine.
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <stdlib.h>
18
19#define PROM_SIZE 0x10000	/* max */
20
21static char *progname;
22
23static void bail(const char *);
24int main(int, char **);
25
26static void
27bail(const char *msg)
28{
29	(void)fprintf(stderr, "%s: %s\n", progname, msg);
30	exit(1);
31}
32
33int
34main(int argc, char **argv)
35{
36	char            w[PROM_SIZE];
37	int             i, sum;
38	int             romsize;
39	unsigned short  ck16;
40
41	if ((progname = strrchr(argv[0], '/')) != NULL)
42		progname++;
43	else
44		progname = argv[0];
45
46	if (argc > 1) {
47		if (sscanf(argv[1], "%d", &romsize) != 1)
48			bail("bad arg");
49	} else {
50		bail("arg: romsize / bytes");
51	}
52
53	(void)memset(w, 0x0, PROM_SIZE);
54	i = fread(w, 1, PROM_SIZE, stdin);
55
56	(void)fprintf(stderr, "bios extension size: %d (0x%x), read %d bytes\n",
57	    romsize, romsize, i);
58
59	if (i > romsize)
60		bail("read longer than expected");
61
62	w[2] = romsize / 512;	/* BIOS extension size */
63
64	i = w[0x18] + (w[0x19] << 8);	/* if this is a PCI ROM, this is the
65					 * offset to the "PCI data structure" */
66	if ((i < romsize - 0x18) && (w[i] == 'P') && (w[i + 1] == 'C')
67	    && (w[i + 2] == 'I') && (w[i + 3] == 'R')) {
68		fprintf(stderr, "PCI Data Structure found\n");
69		w[i + 0x10] = romsize / 512;	/* BIOS extension size again */
70	}
71	for (sum = 0, i = 0; i < romsize; i++)
72		sum += w[i];
73
74	w[5] = -sum;		/* left free for checksum adjustment */
75
76	/* calculate CRC as used by PROM programmers */
77	for (ck16 = 0, i = 0; i < romsize; i++)
78		ck16 += (unsigned char) w[i];
79	(void)fprintf(stderr, "ROM CRC: 0x%04x\n", ck16);
80
81	(void)fwrite(w, 1, romsize, stdout);
82	return (0);
83}
84