xref: /freebsd/stand/common/md.c (revision e98f952c82907ec39cebb4e66efd92691c835e05)
1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh  * Copyright (c) 2009 Marcel Moolenaar
3ca987d46SWarner Losh  * All rights reserved.
4ca987d46SWarner Losh  *
5ca987d46SWarner Losh  * Redistribution and use in source and binary forms, with or without
6ca987d46SWarner Losh  * modification, are permitted provided that the following conditions
7ca987d46SWarner Losh  * are met:
8ca987d46SWarner Losh  * 1. Redistributions of source code must retain the above copyright
9ca987d46SWarner Losh  *    notice, this list of conditions and the following disclaimer.
10ca987d46SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
11ca987d46SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
12ca987d46SWarner Losh  *    documentation and/or other materials provided with the distribution.
13ca987d46SWarner Losh  *
14ca987d46SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ca987d46SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ca987d46SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ca987d46SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ca987d46SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ca987d46SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ca987d46SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ca987d46SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ca987d46SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ca987d46SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ca987d46SWarner Losh  * SUCH DAMAGE.
25ca987d46SWarner Losh  */
26ca987d46SWarner Losh 
27ca987d46SWarner Losh #include <sys/cdefs.h>
28ca987d46SWarner Losh __FBSDID("$FreeBSD$");
29ca987d46SWarner Losh 
30ca987d46SWarner Losh #include <stand.h>
31ca987d46SWarner Losh #include <sys/param.h>
32ca987d46SWarner Losh #include <sys/endian.h>
33ca987d46SWarner Losh #include <sys/queue.h>
34ca987d46SWarner Losh #include <machine/stdarg.h>
35ca987d46SWarner Losh 
36ca987d46SWarner Losh #include "bootstrap.h"
37ca987d46SWarner Losh 
38ca987d46SWarner Losh #define	MD_BLOCK_SIZE	512
39ca987d46SWarner Losh 
40ca987d46SWarner Losh #ifndef MD_IMAGE_SIZE
41ca987d46SWarner Losh #error Must be compiled with MD_IMAGE_SIZE defined
42ca987d46SWarner Losh #endif
43ca987d46SWarner Losh #if (MD_IMAGE_SIZE == 0 || MD_IMAGE_SIZE % MD_BLOCK_SIZE)
44ca987d46SWarner Losh #error Image size must be a multiple of 512.
45ca987d46SWarner Losh #endif
46ca987d46SWarner Losh 
47ca987d46SWarner Losh /*
48ca987d46SWarner Losh  * Preloaded image gets put here.
49ca987d46SWarner Losh  * Applications that patch the object with the image can determine
50ca987d46SWarner Losh  * the size looking at the start and end markers (strings),
51ca987d46SWarner Losh  * so we want them contiguous.
52ca987d46SWarner Losh  */
53ca987d46SWarner Losh static struct {
54ca987d46SWarner Losh 	u_char start[MD_IMAGE_SIZE];
55ca987d46SWarner Losh 	u_char end[128];
56ca987d46SWarner Losh } md_image = {
57ca987d46SWarner Losh 	.start = "MFS Filesystem goes here",
58ca987d46SWarner Losh 	.end = "MFS Filesystem had better STOP here",
59ca987d46SWarner Losh };
60ca987d46SWarner Losh 
61ca987d46SWarner Losh /* devsw I/F */
62ca987d46SWarner Losh static int md_init(void);
63ca987d46SWarner Losh static int md_strategy(void *, int, daddr_t, size_t, char *, size_t *);
64ca987d46SWarner Losh static int md_open(struct open_file *, ...);
65ca987d46SWarner Losh static int md_close(struct open_file *);
66ca987d46SWarner Losh static int md_print(int);
67ca987d46SWarner Losh 
68ca987d46SWarner Losh struct devsw md_dev = {
69143452f7SWarner Losh 	.dv_name = "md",
70143452f7SWarner Losh 	.dv_type = DEVT_DISK,
71143452f7SWarner Losh 	.dv_init = md_init,
72143452f7SWarner Losh 	.dv_strategy = md_strategy,
73143452f7SWarner Losh 	.dv_open = md_open,
74143452f7SWarner Losh 	.dv_close = md_close,
75143452f7SWarner Losh 	.dv_ioctl = noioctl,
76143452f7SWarner Losh 	.dv_print = md_print,
77*e98f952cSWarner Losh 	.dv_cleanup = nullsys,
78ca987d46SWarner Losh };
79ca987d46SWarner Losh 
80ca987d46SWarner Losh static int
81ca987d46SWarner Losh md_init(void)
82ca987d46SWarner Losh {
83ca987d46SWarner Losh 
84ca987d46SWarner Losh 	return (0);
85ca987d46SWarner Losh }
86ca987d46SWarner Losh 
87ca987d46SWarner Losh static int
88ca987d46SWarner Losh md_strategy(void *devdata, int rw, daddr_t blk, size_t size,
89ca987d46SWarner Losh     char *buf, size_t *rsize)
90ca987d46SWarner Losh {
91ca987d46SWarner Losh 	struct devdesc *dev = (struct devdesc *)devdata;
92ca987d46SWarner Losh 	size_t ofs;
93ca987d46SWarner Losh 
94ca987d46SWarner Losh 	if (dev->d_unit != 0)
95ca987d46SWarner Losh 		return (ENXIO);
96ca987d46SWarner Losh 
97ca987d46SWarner Losh 	if (blk < 0 || blk >= (MD_IMAGE_SIZE / MD_BLOCK_SIZE))
98ca987d46SWarner Losh 		return (EIO);
99ca987d46SWarner Losh 
100ca987d46SWarner Losh 	if (size % MD_BLOCK_SIZE)
101ca987d46SWarner Losh 		return (EIO);
102ca987d46SWarner Losh 
103ca987d46SWarner Losh 	ofs = blk * MD_BLOCK_SIZE;
104ca987d46SWarner Losh 	if ((ofs + size) > MD_IMAGE_SIZE)
105ca987d46SWarner Losh 		size = MD_IMAGE_SIZE - ofs;
106ca987d46SWarner Losh 
107ca987d46SWarner Losh 	if (rsize != NULL)
108ca987d46SWarner Losh 		*rsize = size;
109ca987d46SWarner Losh 
110ca987d46SWarner Losh 	switch (rw & F_MASK) {
111ca987d46SWarner Losh 	case F_READ:
112ca987d46SWarner Losh 		bcopy(md_image.start + ofs, buf, size);
113ca987d46SWarner Losh 		return (0);
114ca987d46SWarner Losh 	case F_WRITE:
115ca987d46SWarner Losh 		bcopy(buf, md_image.start + ofs, size);
116ca987d46SWarner Losh 		return (0);
117ca987d46SWarner Losh 	}
118ca987d46SWarner Losh 
119ca987d46SWarner Losh 	return (ENODEV);
120ca987d46SWarner Losh }
121ca987d46SWarner Losh 
122ca987d46SWarner Losh static int
123ca987d46SWarner Losh md_open(struct open_file *f, ...)
124ca987d46SWarner Losh {
125ca987d46SWarner Losh 	va_list ap;
126ca987d46SWarner Losh 	struct devdesc *dev;
127ca987d46SWarner Losh 
128ca987d46SWarner Losh 	va_start(ap, f);
129ca987d46SWarner Losh 	dev = va_arg(ap, struct devdesc *);
130ca987d46SWarner Losh 	va_end(ap);
131ca987d46SWarner Losh 
132ca987d46SWarner Losh 	if (dev->d_unit != 0)
133ca987d46SWarner Losh 		return (ENXIO);
134ca987d46SWarner Losh 
135ca987d46SWarner Losh 	return (0);
136ca987d46SWarner Losh }
137ca987d46SWarner Losh 
138ca987d46SWarner Losh static int
139ca987d46SWarner Losh md_close(struct open_file *f)
140ca987d46SWarner Losh {
141ca987d46SWarner Losh 	struct devdesc *dev;
142ca987d46SWarner Losh 
143ca987d46SWarner Losh 	dev = (struct devdesc *)(f->f_devdata);
144ca987d46SWarner Losh 	return ((dev->d_unit != 0) ? ENXIO : 0);
145ca987d46SWarner Losh }
146ca987d46SWarner Losh 
147ca987d46SWarner Losh static int
148ca987d46SWarner Losh md_print(int verbose)
149ca987d46SWarner Losh {
150ca987d46SWarner Losh 
151ca987d46SWarner Losh 	printf("%s devices:", md_dev.dv_name);
152ca987d46SWarner Losh 	if (pager_output("\n") != 0)
153ca987d46SWarner Losh 		return (1);
154ca987d46SWarner Losh 
155ca987d46SWarner Losh 	printf("MD (%u bytes)", MD_IMAGE_SIZE);
156ca987d46SWarner Losh 	return (pager_output("\n"));
157ca987d46SWarner Losh }
158