userboot_disk.c revision 223695
1223695Sdfr/*-
2223695Sdfr * Copyright (c) 2011 Google, Inc.
3223695Sdfr * All rights reserved.
4223695Sdfr *
5223695Sdfr * Redistribution and use in source and binary forms, with or without
6223695Sdfr * modification, are permitted provided that the following conditions
7223695Sdfr * are met:
8223695Sdfr * 1. Redistributions of source code must retain the above copyright
9223695Sdfr *    notice, this list of conditions and the following disclaimer.
10223695Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11223695Sdfr *    notice, this list of conditions and the following disclaimer in the
12223695Sdfr *    documentation and/or other materials provided with the distribution.
13223695Sdfr *
14223695Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15223695Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16223695Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17223695Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18223695Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19223695Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20223695Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21223695Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22223695Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23223695Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24223695Sdfr * SUCH DAMAGE.
25223695Sdfr */
26223695Sdfr
27223695Sdfr#include <sys/cdefs.h>
28223695Sdfr__FBSDID("$FreeBSD: head/sys/boot/userboot/userboot/userboot_disk.c 223695 2011-06-30 16:08:56Z dfr $");
29223695Sdfr
30223695Sdfr/*
31223695Sdfr * Userboot disk image handling.
32223695Sdfr */
33223695Sdfr
34223695Sdfr#include <stand.h>
35223695Sdfr
36223695Sdfr#include <stdarg.h>
37223695Sdfr#include <uuid.h>
38223695Sdfr
39223695Sdfr#include <bootstrap.h>
40223695Sdfr
41223695Sdfr#include "disk.h"
42223695Sdfr#include "libuserboot.h"
43223695Sdfr
44223695Sdfrint userboot_disk_maxunit = 0;
45223695Sdfr
46223695Sdfrstatic int	userdisk_init(void);
47223695Sdfrstatic int	userdisk_strategy(void *devdata, int flag, daddr_t dblk,
48223695Sdfr		    size_t size, char *buf, size_t *rsize);
49223695Sdfrstatic int	userdisk_open(struct open_file *f, ...);
50223695Sdfrstatic int	userdisk_close(struct open_file *f);
51223695Sdfrstatic void	userdisk_print(int verbose);
52223695Sdfr
53223695Sdfrstruct devsw userboot_disk = {
54223695Sdfr	"disk",
55223695Sdfr	DEVT_DISK,
56223695Sdfr	userdisk_init,
57223695Sdfr	userdisk_strategy,
58223695Sdfr	userdisk_open,
59223695Sdfr	userdisk_close,
60223695Sdfr	noioctl,
61223695Sdfr	userdisk_print,
62223695Sdfr	NULL
63223695Sdfr};
64223695Sdfr
65223695Sdfr/*
66223695Sdfr * Nothing to do here.
67223695Sdfr */
68223695Sdfrstatic int
69223695Sdfruserdisk_init(void)
70223695Sdfr{
71223695Sdfr
72223695Sdfr	return(0);
73223695Sdfr}
74223695Sdfr
75223695Sdfr/*
76223695Sdfr * Print information about disks
77223695Sdfr */
78223695Sdfrstatic void
79223695Sdfruserdisk_print(int verbose)
80223695Sdfr{
81223695Sdfr	int			i;
82223695Sdfr	char			line[80];
83223695Sdfr	struct disk_devdesc	dev;
84223695Sdfr
85223695Sdfr	for (i = 0; i < userboot_disk_maxunit; i++) {
86223695Sdfr		sprintf(line, "    disk%d:   Guest drive image\n", i);
87223695Sdfr		pager_output(line);
88223695Sdfr		dev.d_dev = &userboot_disk;
89223695Sdfr		dev.d_unit = i;
90223695Sdfr		dev.d_slice = -1;
91223695Sdfr		dev.d_partition = -1;
92223695Sdfr		dev.d_offset = 0;
93223695Sdfr		sprintf(line, "    disk%d", i);
94223695Sdfr		disk_print(&dev, line, verbose);
95223695Sdfr	}
96223695Sdfr}
97223695Sdfr
98223695Sdfr/*
99223695Sdfr * Attempt to open the disk described by (dev) for use by (f).
100223695Sdfr */
101223695Sdfrstatic int
102223695Sdfruserdisk_open(struct open_file *f, ...)
103223695Sdfr{
104223695Sdfr	va_list			ap;
105223695Sdfr	struct disk_devdesc	*dev;
106223695Sdfr
107223695Sdfr	va_start(ap, f);
108223695Sdfr	dev = va_arg(ap, struct disk_devdesc *);
109223695Sdfr	va_end(ap);
110223695Sdfr
111223695Sdfr	if (dev->d_unit < 0 || dev->d_unit >= userboot_disk_maxunit)
112223695Sdfr		return (EIO);
113223695Sdfr
114223695Sdfr	return (disk_open(dev));
115223695Sdfr}
116223695Sdfr
117223695Sdfrstatic int
118223695Sdfruserdisk_close(struct open_file *f)
119223695Sdfr{
120223695Sdfr
121223695Sdfr	return(0);
122223695Sdfr}
123223695Sdfr
124223695Sdfrstatic int
125223695Sdfruserdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
126223695Sdfr    char *buf, size_t *rsize)
127223695Sdfr{
128223695Sdfr	struct disk_devdesc *dev = devdata;
129223695Sdfr	uint64_t	off;
130223695Sdfr	size_t		resid;
131223695Sdfr	int		rc;
132223695Sdfr
133223695Sdfr	if (rw == F_WRITE)
134223695Sdfr		return (EROFS);
135223695Sdfr	if (rw != F_READ)
136223695Sdfr		return (EINVAL);
137223695Sdfr	if (rsize)
138223695Sdfr		*rsize = 0;
139223695Sdfr	off = (dblk + dev->d_offset) * DISK_SECSIZE;
140223695Sdfr	rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid);
141223695Sdfr	if (rc)
142223695Sdfr		return (rc);
143223695Sdfr	if (rsize)
144223695Sdfr		*rsize = size - resid;
145223695Sdfr	return (0);
146223695Sdfr}
147