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
report(const char * label)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
fatal(const char * label)40 static __dead void fatal(const char *label)
41 {
42 report(label);
43 exit(1);
44 }
45
bread(FILE * f,char * name,void * buf,size_t len)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
readblock(off_t blk,char * buf,int block_size)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
writeblock(off_t blk,const char * buf,int block_size)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 */
install_master(const char * device,char * masterboot,char ** guide)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
isoption(const char * option,const char * test)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