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