1 /* Based on original installboot from MINIX 3.
2  *
3  *	installboot 3.0 - Make a device bootable	Author: Kees J. Bot
4  *								21 Dec 1991
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <dirent.h>
13 #include <sys/stat.h>
14 
15 #include "installboot.h"
16 
17 #define BOOTBLOCK	0	/* Of course */
18 #define BOOT_BLOCK_SIZE 1024
19 #define SIGNATURE	0xAA55	/* Boot block signature. */
20 #define SIGPOS		510	/* Where to put signature word. */
21 #define PARTPOS		446	/* Offset to the partition table in a master
22 				 * boot block.
23 				 */
24 
25 
26 static int rawfd;	/* File descriptor to open device. */
27 static const char *rawdev;	/* Name of device. */
28 
29 
30 static void report(const char *label)
31 /* installboot: label: No such file or directory */
32 {
33 	fprintf(stderr, "installboot: %s: %s\n", label, strerror(errno));
34 }
35 
36 static __dead void fatal(const char *label)
37 {
38 	report(label);
39 	exit(1);
40 }
41 
42 static void bread(FILE *f, char *name, void *buf, size_t len)
43 /* Read len bytes.  Don't dare return without them. */
44 {
45 	if (len > 0 && fread(buf, len, 1, f) != 1) {
46 		if (ferror(f)) fatal(name);
47 		fprintf(stderr, "installboot: Unexpected EOF on %s\n", name);
48 		exit(1);
49 	}
50 }
51 
52 static void readblock(off_t blk, char *buf, int block_size)
53 /* For rawfs, so that it can read blocks. */
54 {
55 	int n;
56 
57 	if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
58 		|| (n= read(rawfd, buf, block_size)) < 0
59 	) fatal(rawdev);
60 
61 	if (n < block_size) {
62 		fprintf(stderr, "installboot: Unexpected EOF on %s\n", rawdev);
63 		exit(1);
64 	}
65 }
66 
67 static void writeblock(off_t blk, const char *buf, int block_size)
68 /* Add a function to write blocks for local use. */
69 {
70 	if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
71 		|| write(rawfd, buf, block_size) < 0
72 	) fatal(rawdev);
73 }
74 
75 
76 /* A temp stub until fdisk is ported to MINIX */
77 void install_master(const char *device, char *masterboot, char **guide)
78 /* Booting a hard disk is a two stage process:  The master bootstrap in sector
79  * 0 loads the bootstrap from sector 0 of the active partition which in turn
80  * starts the operating system.  This code installs such a master bootstrap
81  * on a hard disk.  If guide[0] is non-null then the master bootstrap is
82  * guided into booting a certain device.
83  */
84 {
85 	FILE *masf;
86 	unsigned long size;
87 	static char buf[BOOT_BLOCK_SIZE];
88 
89 	/* Open device. */
90 	if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
91 
92 	/* Open the master boot code. */
93 	if ((masf= fopen(masterboot, "r")) == NULL) fatal(masterboot);
94 
95 	size= PARTPOS;
96 
97 	/* Read the master boot block, patch it, write. */
98 	readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
99 
100 	memset(buf, 0, PARTPOS);
101 	(void) bread(masf, masterboot, buf, size);
102 
103 	/* Install signature. */
104 	buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
105 	buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
106 
107 	writeblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
108 }
109 
110 int isoption(const char *option, const char *test)
111 /* Check if the option argument is equals "test".  Also accept -i as short
112  * for -image, and the special case -x for -extract.
113  */
114 {
115 	if (strcmp(option, test) == 0) return 1;
116 	if (option[0] != '-' && strlen(option) != 2) return 0;
117 	if (option[1] == test[1]) return 1;
118 	if (option[1] == 'x' && test[1] == 'e') return 1;
119 	return 0;
120 }
121