]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/boot/userboot/userboot/userboot_disk.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / sys / boot / userboot / userboot / userboot_disk.c
1 /*-
2  * Copyright (c) 2011 Google, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * Userboot disk image handling.
32  */
33
34 #include <stand.h>
35
36 #include <stdarg.h>
37 #include <uuid.h>
38
39 #include <bootstrap.h>
40
41 #include "disk.h"
42 #include "libuserboot.h"
43
44 int userboot_disk_maxunit = 0;
45
46 static int      userdisk_init(void);
47 static int      userdisk_strategy(void *devdata, int flag, daddr_t dblk,
48                     size_t size, char *buf, size_t *rsize);
49 static int      userdisk_open(struct open_file *f, ...);
50 static int      userdisk_close(struct open_file *f);
51 static void     userdisk_print(int verbose);
52
53 struct devsw userboot_disk = {
54         "disk",
55         DEVT_DISK,
56         userdisk_init,
57         userdisk_strategy,
58         userdisk_open,
59         userdisk_close,
60         noioctl,
61         userdisk_print,
62         NULL
63 };
64
65 /*
66  * Nothing to do here.
67  */
68 static int
69 userdisk_init(void)
70 {
71
72         return(0);
73 }
74
75 /*
76  * Print information about disks
77  */
78 static void
79 userdisk_print(int verbose)
80 {
81         int                     i;
82         char                    line[80];
83         struct disk_devdesc     dev;
84
85         for (i = 0; i < userboot_disk_maxunit; i++) {
86                 sprintf(line, "    disk%d:   Guest drive image\n", i);
87                 pager_output(line);
88                 dev.d_dev = &userboot_disk;
89                 dev.d_unit = i;
90                 dev.d_slice = -1;
91                 dev.d_partition = -1;
92                 dev.d_offset = 0;
93                 sprintf(line, "    disk%d", i);
94                 disk_print(&dev, line, verbose);
95         }
96 }
97
98 /*
99  * Attempt to open the disk described by (dev) for use by (f).
100  */
101 static int
102 userdisk_open(struct open_file *f, ...)
103 {
104         va_list                 ap;
105         struct disk_devdesc     *dev;
106
107         va_start(ap, f);
108         dev = va_arg(ap, struct disk_devdesc *);
109         va_end(ap);
110
111         if (dev->d_unit < 0 || dev->d_unit >= userboot_disk_maxunit)
112                 return (EIO);
113
114         return (disk_open(dev));
115 }
116
117 static int
118 userdisk_close(struct open_file *f)
119 {
120
121         return(0);
122 }
123
124 static int
125 userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
126     char *buf, size_t *rsize)
127 {
128         struct disk_devdesc *dev = devdata;
129         uint64_t        off;
130         size_t          resid;
131         int             rc;
132
133         if (rw == F_WRITE)
134                 return (EROFS);
135         if (rw != F_READ)
136                 return (EINVAL);
137         if (rsize)
138                 *rsize = 0;
139         off = (dblk + dev->d_offset) * DISK_SECSIZE;
140         rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid);
141         if (rc)
142                 return (rc);
143         if (rsize)
144                 *rsize = size - resid;
145         return (0);
146 }