2002-04-19 20:43:38 +04:00
|
|
|
/* $NetBSD: installboot.c,v 1.3 2002/04/19 16:43:38 heinz Exp $ */
|
|
|
|
|
2001-09-25 22:47:55 +04:00
|
|
|
#include <err.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "../aout2bb/chksum.h"
|
|
|
|
|
|
|
|
/* XXX Must be kept in sync with bbstart.s! */
|
|
|
|
#define CMDLN_LOC 0x10
|
|
|
|
#define CMDLN_LEN 0x20
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]);
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]){
|
|
|
|
|
|
|
|
char *line;
|
|
|
|
char *progname;
|
|
|
|
char *bootnam, *devnam;
|
2001-09-25 23:07:00 +04:00
|
|
|
char *dline;
|
2001-09-25 22:47:55 +04:00
|
|
|
int bootfd, devfd;
|
|
|
|
int rc; /* read, write */
|
|
|
|
int c; /* getopt */
|
|
|
|
int sumlen;
|
|
|
|
u_int32_t sum2, sum16;
|
|
|
|
|
|
|
|
u_int32_t block[128*16];
|
|
|
|
|
|
|
|
progname = argv[0];
|
|
|
|
while ((c = getopt(argc, argv, "l:")) != -1) {
|
|
|
|
switch(c) {
|
|
|
|
case 'l':
|
|
|
|
line = optarg;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errx(1,
|
|
|
|
"usage: %s [-l newcommandline] bootblock device",
|
|
|
|
progname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
if (argc != 2) {
|
|
|
|
errx(1, "usage: %s [-l newcommandline] bootblock device",
|
|
|
|
progname);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
bootnam = *argv++;
|
|
|
|
devnam = *argv;
|
|
|
|
|
|
|
|
bootfd = open(bootnam, O_RDONLY, 0);
|
|
|
|
if (bootfd < 0) {
|
|
|
|
err(1, "Can't open bootblock for reading");
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
devfd = open(devnam, O_CREAT|O_RDWR, 0666);
|
|
|
|
if (devfd < 0) {
|
|
|
|
err(1, "Can't open output device for writing");
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = read(bootfd, block, sizeof(block));
|
|
|
|
|
|
|
|
if (rc < sizeof(block)) {
|
|
|
|
err(1, "Can't read bootblock");
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX the choices should not be hardcoded */
|
|
|
|
|
|
|
|
sum2 = chksum(block, 1024/4);
|
|
|
|
sum16 = chksum(block, 8192/4);
|
|
|
|
|
|
|
|
if (sum16 == 0xffffffff) {
|
|
|
|
sumlen = 8192/4;
|
|
|
|
} else if (sum2 == 0xffffffff) {
|
|
|
|
sumlen = 1024/4;
|
|
|
|
} else {
|
|
|
|
errx(1, "%s: wrong checksum", bootnam);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sum2 == sum16) {
|
|
|
|
warnx("eek - both sums are the same");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (line) {
|
2001-09-25 23:07:00 +04:00
|
|
|
dline = (char *)&(block[CMDLN_LOC/4]);
|
|
|
|
/* XXX keep the default default line in sync with bbstart.s */
|
|
|
|
if (strcmp(dline, "netbsd -ASn2") != 0) {
|
|
|
|
errx(1, "Old bootblock version? Can't change command line.");
|
|
|
|
}
|
|
|
|
(void)strncpy(dline, line, CMDLN_LEN-1);
|
2001-09-25 22:47:55 +04:00
|
|
|
|
|
|
|
block[1] = 0;
|
|
|
|
block[1] = 0xffffffff - chksum(block, sumlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = write(devfd, block, sizeof(block));
|
|
|
|
|
|
|
|
if (rc < sizeof(block)) {
|
|
|
|
err(1, "Can't write bootblock");
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|