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