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