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