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 * Read from the host filesystem
32 */
33
34#include <sys/param.h>
35#include <sys/time.h>
36#include <stddef.h>
37#include <stdarg.h>
38#include <string.h>
39#include <stand.h>
40#include <bootstrap.h>
41
42#include "libuserboot.h"
43
44/*
45 * Open a file.
46 */
47static int
48host_open(const char *upath, struct open_file *f)
49{
50
51	if (f->f_dev != &host_dev)
52		return (EINVAL);
53
54	return (CALLBACK(open, upath, &f->f_fsdata));
55}
56
57static int
58host_close(struct open_file *f)
59{
60
61        CALLBACK(close, f->f_fsdata);
62	f->f_fsdata = (void *)0;
63
64	return (0);
65}
66
67/*
68 * Copy a portion of a file into memory.
69 */
70static int
71host_read(struct open_file *f, void *start, size_t size, size_t *resid)
72{
73
74	return (CALLBACK(read, f->f_fsdata, start, size, resid));
75}
76
77/*
78 * Don't be silly - the bootstrap has no business writing anything.
79 */
80static int
81host_write(struct open_file *f, void *start, size_t size, size_t *resid)
82{
83
84	return (EROFS);
85}
86
87static off_t
88host_seek(struct open_file *f, off_t offset, int where)
89{
90
91	return (CALLBACK(seek, f->f_fsdata, offset, where));
92}
93
94static int
95host_stat(struct open_file *f, struct stat *sb)
96{
97	int mode;
98	int uid;
99	int gid;
100	uint64_t size;
101
102	CALLBACK(stat, f->f_fsdata, &mode, &uid, &gid, &size);
103	sb->st_mode = mode;
104	sb->st_uid = uid;
105	sb->st_gid = gid;
106	sb->st_size = size;
107	return (0);
108}
109
110static int
111host_readdir(struct open_file *f, struct dirent *d)
112{
113	uint32_t fileno;
114	uint8_t type;
115	size_t namelen;
116	int rc;
117
118	rc = CALLBACK(readdir, f->f_fsdata, &fileno, &type, &namelen,
119            d->d_name);
120	if (rc)
121		return (rc);
122
123	d->d_fileno = fileno;
124	d->d_type = type;
125	d->d_namlen = namelen;
126
127	return (0);
128}
129
130static int
131host_dev_init(void)
132{
133
134	return (0);
135}
136
137static void
138host_dev_print(int verbose)
139{
140	char line[80];
141
142	sprintf(line, "    host%d:   Host filesystem\n", 0);
143	pager_output(line);
144}
145
146/*
147 * 'Open' the host device.
148 */
149static int
150host_dev_open(struct open_file *f, ...)
151{
152	va_list		args;
153	struct devdesc	*dev;
154
155	va_start(args, f);
156	dev = va_arg(args, struct devdesc*);
157	va_end(args);
158
159	return (0);
160}
161
162static int
163host_dev_close(struct open_file *f)
164{
165
166	return (0);
167}
168
169static int
170host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
171    char *buf, size_t *rsize)
172{
173
174	return (ENOSYS);
175}
176
177struct fs_ops host_fsops = {
178	"host",
179	host_open,
180	host_close,
181	host_read,
182	host_write,
183	host_seek,
184	host_stat,
185	host_readdir
186};
187
188struct devsw host_dev = {
189	.dv_name = "host",
190	.dv_type = DEVT_NET,
191	.dv_init = host_dev_init,
192	.dv_strategy = host_dev_strategy,
193	.dv_open = host_dev_open,
194	.dv_close = host_dev_close,
195	.dv_ioctl = noioctl,
196	.dv_print = host_dev_print,
197	.dv_cleanup = NULL
198};
199