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