1200460Smarcel/*-
2200460Smarcel * Copyright (c) 2009 Marcel Moolenaar
3200460Smarcel * All rights reserved.
4200460Smarcel *
5200460Smarcel * Redistribution and use in source and binary forms, with or without
6200460Smarcel * modification, are permitted provided that the following conditions
7200460Smarcel * are met:
8200460Smarcel * 1. Redistributions of source code must retain the above copyright
9200460Smarcel *    notice, this list of conditions and the following disclaimer.
10200460Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11200460Smarcel *    notice, this list of conditions and the following disclaimer in the
12200460Smarcel *    documentation and/or other materials provided with the distribution.
13200460Smarcel *
14200460Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15200460Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16200460Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17200460Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18200460Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19200460Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20200460Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21200460Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22200460Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23200460Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24200460Smarcel * SUCH DAMAGE.
25200460Smarcel */
26200460Smarcel
27200460Smarcel#include <sys/cdefs.h>
28200460Smarcel__FBSDID("$FreeBSD$");
29200460Smarcel
30200460Smarcel#include <sys/param.h>
31200460Smarcel#include <sys/endian.h>
32200460Smarcel#include <sys/queue.h>
33200460Smarcel#include <machine/stdarg.h>
34200460Smarcel#include <stand.h>
35200460Smarcel
36200460Smarcel#include "bootstrap.h"
37200460Smarcel
38200460Smarcel#define	MD_BLOCK_SIZE	512
39200460Smarcel
40200460Smarcel#ifndef MD_IMAGE_SIZE
41200460Smarcel#error Must be compiled with MD_IMAGE_SIZE defined
42200460Smarcel#endif
43200460Smarcel#if (MD_IMAGE_SIZE == 0 || MD_IMAGE_SIZE % MD_BLOCK_SIZE)
44200460Smarcel#error Image size must be a multiple of 512.
45200460Smarcel#endif
46200460Smarcel
47200460Smarcel/*
48200460Smarcel * Preloaded image gets put here.
49200460Smarcel * Applications that patch the object with the image can determine
50200460Smarcel * the size looking at the start and end markers (strings),
51200460Smarcel * so we want them contiguous.
52200460Smarcel */
53200460Smarcelstatic struct {
54200460Smarcel	u_char start[MD_IMAGE_SIZE];
55200460Smarcel	u_char end[128];
56200460Smarcel} md_image = {
57200460Smarcel	.start = "MFS Filesystem goes here",
58200460Smarcel	.end = "MFS Filesystem had better STOP here",
59200460Smarcel};
60200460Smarcel
61200460Smarcel/* devsw I/F */
62200460Smarcelstatic int md_init(void);
63200460Smarcelstatic int md_strategy(void *, int, daddr_t, size_t, char *, size_t *);
64200460Smarcelstatic int md_open(struct open_file *, ...);
65200460Smarcelstatic int md_close(struct open_file *);
66200460Smarcelstatic void md_print(int);
67200460Smarcel
68200460Smarcelstruct devsw md_dev = {
69200460Smarcel	"md",
70200460Smarcel	DEVT_DISK,
71200460Smarcel	md_init,
72200460Smarcel	md_strategy,
73200460Smarcel	md_open,
74200460Smarcel	md_close,
75200460Smarcel	noioctl,
76200460Smarcel	md_print
77200460Smarcel};
78200460Smarcel
79200460Smarcelstatic int
80200460Smarcelmd_init(void)
81200460Smarcel{
82200460Smarcel
83200460Smarcel	return (0);
84200460Smarcel}
85200460Smarcel
86200460Smarcelstatic int
87200460Smarcelmd_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
88200460Smarcel    size_t *rsize)
89200460Smarcel{
90200460Smarcel	struct devdesc *dev = (struct devdesc *)devdata;
91200460Smarcel	size_t ofs;
92200460Smarcel
93200460Smarcel	if (dev->d_unit != 0)
94200460Smarcel		return (ENXIO);
95200460Smarcel
96200460Smarcel	if (blk < 0 || blk >= (MD_IMAGE_SIZE / MD_BLOCK_SIZE))
97200460Smarcel		return (EIO);
98200460Smarcel
99200460Smarcel	if (size % MD_BLOCK_SIZE)
100200460Smarcel		return (EIO);
101200460Smarcel
102200460Smarcel	ofs = blk * MD_BLOCK_SIZE;
103200460Smarcel	if ((ofs + size) > MD_IMAGE_SIZE)
104200460Smarcel		size = MD_IMAGE_SIZE - ofs;
105200460Smarcel
106200460Smarcel	if (rsize != 0)
107200460Smarcel		*rsize = size;
108200460Smarcel
109200460Smarcel	switch (rw) {
110200460Smarcel	case F_READ:
111200460Smarcel		bcopy(md_image.start + ofs, buf, size);
112200460Smarcel		return (0);
113200460Smarcel	case F_WRITE:
114200460Smarcel		bcopy(buf, md_image.start + ofs, size);
115200460Smarcel		return (0);
116200460Smarcel	}
117200460Smarcel
118200460Smarcel	return (ENODEV);
119200460Smarcel}
120200460Smarcel
121200460Smarcelstatic int
122200460Smarcelmd_open(struct open_file *f, ...)
123200460Smarcel{
124200460Smarcel	va_list ap;
125200460Smarcel	struct devdesc *dev;
126200460Smarcel
127200460Smarcel	va_start(ap, f);
128200460Smarcel	dev = va_arg(ap, struct devdesc *);
129200460Smarcel	va_end(ap);
130200460Smarcel
131200460Smarcel	if (dev->d_unit != 0)
132200460Smarcel		return (ENXIO);
133200460Smarcel
134200460Smarcel	return (0);
135200460Smarcel}
136200460Smarcel
137200460Smarcelstatic int
138200460Smarcelmd_close(struct open_file *f)
139200460Smarcel{
140200460Smarcel	struct devdesc *dev;
141200460Smarcel
142200460Smarcel	dev = (struct devdesc *)(f->f_devdata);
143200460Smarcel	return ((dev->d_unit != 0) ? ENXIO : 0);
144200460Smarcel}
145200460Smarcel
146200460Smarcelstatic void
147200460Smarcelmd_print(int verbose)
148200460Smarcel{
149200460Smarcel
150200460Smarcel	printf("MD (%u bytes)\n", MD_IMAGE_SIZE);
151200460Smarcel}
152