GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/installboot/i386_softraid.c Lines: 0 86 0.0 %
Date: 2017-11-07 Branches: 0 44 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: i386_softraid.c,v 1.10 2016/04/28 16:48:18 krw Exp $	*/
2
/*
3
 * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/param.h>	/* DEV_BSIZE */
19
#include <sys/disklabel.h>
20
#include <sys/dkio.h>
21
#include <sys/ioctl.h>
22
#include <sys/stat.h>
23
24
#include <dev/biovar.h>
25
#include <dev/softraidvar.h>
26
#include <ufs/ufs/dinode.h>
27
28
#include <err.h>
29
#include <fcntl.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <unistd.h>
34
#include <util.h>
35
36
#include "installboot.h"
37
#include "i386_installboot.h"
38
39
void	sr_install_bootblk(int, int, int);
40
void	sr_install_bootldr(int, char *);
41
42
void
43
sr_install_bootblk(int devfd, int vol, int disk)
44
{
45
	struct bioc_disk bd;
46
	struct disklabel dl;
47
	struct partition *pp;
48
	uint32_t poffset;
49
	char *dev;
50
	char part, efipart;
51
	int diskfd;
52
53
	/* Get device name for this disk/chunk. */
54
	memset(&bd, 0, sizeof(bd));
55
	bd.bd_volid = vol;
56
	bd.bd_diskid = disk;
57
	if (ioctl(devfd, BIOCDISK, &bd) == -1)
58
		err(1, "BIOCDISK");
59
60
	/* Check disk status. */
61
	if (bd.bd_status != BIOC_SDONLINE && bd.bd_status != BIOC_SDREBUILD) {
62
		fprintf(stderr, "softraid chunk %u not online - skipping...\n",
63
		    disk);
64
		return;
65
	}
66
67
	if (strlen(bd.bd_vendor) < 1)
68
		errx(1, "invalid disk name");
69
	part = bd.bd_vendor[strlen(bd.bd_vendor) - 1];
70
	if (part < 'a' || part >= 'a' + MAXPARTITIONS)
71
		errx(1, "invalid partition %c\n", part);
72
	bd.bd_vendor[strlen(bd.bd_vendor) - 1] = '\0';
73
74
	/* Open this device and check its disklabel. */
75
	if ((diskfd = opendev(bd.bd_vendor, (nowrite? O_RDONLY:O_RDWR),
76
	    OPENDEV_PART, &dev)) < 0)
77
		err(1, "open: %s", dev);
78
79
	/* Get and check disklabel. */
80
	if (ioctl(diskfd, DIOCGDINFO, &dl) != 0)
81
		err(1, "disklabel: %s", dev);
82
	if (dl.d_magic != DISKMAGIC)
83
		err(1, "bad disklabel magic=0x%08x", dl.d_magic);
84
85
	/* Warn on unknown disklabel types. */
86
	if (dl.d_type == 0)
87
		warnx("disklabel type unknown");
88
89
	efipart = findgptefisys(diskfd, &dl);
90
	if (efipart != -1) {
91
		write_efisystem(&dl, (char)efipart);
92
		return;
93
	}
94
95
	/* Determine poffset and set symbol value. */
96
	pp = &dl.d_partitions[part - 'a'];
97
	if (pp->p_offseth != 0)
98
		errx(1, "partition offset too high");
99
	poffset = pp->p_offset;			/* Offset of RAID partition. */
100
	poffset += SR_BOOT_LOADER_OFFSET;	/* SR boot loader area. */
101
	sym_set_value(pbr_symbols, "_p_offset", poffset);
102
103
	if (verbose)
104
		fprintf(stderr, "%s%c: installing boot blocks on %s, "
105
		    "part offset %u\n", bd.bd_vendor, part, dev, poffset);
106
107
	/* Write boot blocks to device. */
108
	write_bootblocks(diskfd, dev, &dl);
109
110
	close(diskfd);
111
}
112
113
void
114
sr_install_bootldr(int devfd, char *dev)
115
{
116
	struct bioc_installboot bb;
117
	struct stat sb;
118
	struct ufs1_dinode *ino_p;
119
	uint32_t bootsize, inodeblk, inodedbl;
120
	uint16_t bsize = SR_FS_BLOCKSIZE;
121
	uint16_t nblocks;
122
	uint8_t bshift = 5;		/* fragsize == blocksize */
123
	int fd, i;
124
	u_char *p;
125
126
	/*
127
	 * Install boot loader into softraid boot loader storage area.
128
	 *
129
	 * In order to allow us to reuse the existing biosboot we construct
130
	 * a fake FFS filesystem with a single inode, which points to the
131
	 * boot loader.
132
	 */
133
134
	nblocks = howmany(SR_BOOT_LOADER_SIZE, SR_FS_BLOCKSIZE / DEV_BSIZE);
135
	inodeblk = nblocks - 1;
136
	bootsize = nblocks * SR_FS_BLOCKSIZE;
137
138
	p = calloc(1, bootsize);
139
	if (p == NULL)
140
		err(1, NULL);
141
142
	fd = open(stage2, O_RDONLY, 0);
143
	if (fd == -1)
144
		err(1, NULL);
145
146
	if (fstat(fd, &sb) == -1)
147
		err(1, NULL);
148
149
	nblocks = howmany(sb.st_blocks, SR_FS_BLOCKSIZE / DEV_BSIZE);
150
	if (sb.st_blocks * S_BLKSIZE > bootsize -
151
	    (int)(sizeof(struct ufs1_dinode)))
152
		errx(1, "boot code will not fit");
153
154
	/* We only need to fill the direct block array. */
155
	ino_p = (struct ufs1_dinode *)&p[bootsize - sizeof(struct ufs1_dinode)];
156
157
	ino_p->di_mode = sb.st_mode;
158
	ino_p->di_nlink = 1;
159
	ino_p->di_inumber = 0xfeebfaab;
160
	ino_p->di_size = read(fd, p, sb.st_blocks * S_BLKSIZE);
161
	ino_p->di_blocks = nblocks;
162
	for (i = 0; i < nblocks; i++)
163
		ino_p->di_db[i] = i;
164
165
	inodedbl = ((u_char*)&ino_p->di_db[0] -
166
	    &p[bootsize - SR_FS_BLOCKSIZE]) + INODEOFF;
167
168
	memset(&bb, 0, sizeof(bb));
169
	bb.bb_bootldr = p;
170
	bb.bb_bootldr_size = bootsize;
171
	bb.bb_bootblk = "XXX";
172
	bb.bb_bootblk_size = sizeof("XXX");
173
	strncpy(bb.bb_dev, dev, sizeof(bb.bb_dev));
174
	if (!nowrite) {
175
		if (verbose)
176
			fprintf(stderr, "%s: installing boot loader on "
177
			    "softraid volume\n", dev);
178
		if (ioctl(devfd, BIOCINSTALLBOOT, &bb) == -1)
179
			errx(1, "softraid installboot failed");
180
	}
181
182
	/*
183
	 * Set the values that will need to go into biosboot
184
	 * (the partition boot record, a.k.a. the PBR).
185
	 */
186
	sym_set_value(pbr_symbols, "_fs_bsize_p", (bsize / 16));
187
	sym_set_value(pbr_symbols, "_fs_bsize_s", (bsize / 512));
188
	sym_set_value(pbr_symbols, "_fsbtodb", bshift);
189
	sym_set_value(pbr_symbols, "_inodeblk", inodeblk);
190
	sym_set_value(pbr_symbols, "_inodedbl", inodedbl);
191
	sym_set_value(pbr_symbols, "_nblocks", nblocks);
192
193
	if (verbose)
194
		fprintf(stderr, "%s is %d blocks x %d bytes\n",
195
		    stage2, nblocks, bsize);
196
197
	free(p);
198
	close(fd);
199
}