xref: /netbsd-src/sys/arch/ews4800mips/stand/common/bootfs.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: bootfs.c,v 1.3 2007/12/15 00:39:16 perry Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <lib/libsa/stand.h>
40 #include <lib/libkern/libkern.h>
41 
42 #include <machine/param.h>
43 #include <machine/bfs.h>
44 #include <machine/sector.h>
45 
46 #include "local.h"
47 
48 /* System V bfs */
49 
50 FS_DEF(bfs);
51 
52 struct fs_ops bfs_ops = {
53 	bfs_open, bfs_close, bfs_read, bfs_write, bfs_seek, bfs_stat
54 };
55 
56 struct bfs_file {
57 	struct bfs *bfs;
58 	int start, end;
59 	size_t size;
60 	int cur;
61 	uint8_t buf[DEV_BSIZE];
62 };
63 
64 int
65 bfs_open(const char *name, struct open_file *f)
66 {
67 	struct bfs_file *file;
68 
69 	if ((file = alloc(sizeof *file)) == 0)
70 		return -1;
71 	memset(file, 0, sizeof *file);
72 
73 	if (bfs_init(&file->bfs) != 0) {
74 		dealloc(file, sizeof *file);
75 		return -2;
76 	}
77 
78 	if (!bfs_file_lookup(file->bfs, name, &file->start, &file->end,
79 	    &file->size)) {
80 		bfs_fini(file->bfs);
81 		dealloc(file, sizeof *file);
82 		return -3;
83 	}
84 
85 	printf("%s: %s %d %d %d\n", __func__, name, file->start,
86 	    file->end, file->size);
87 
88 	f->f_fsdata = file;
89 
90 	return 0;
91 }
92 
93 int
94 bfs_close(struct open_file *f)
95 {
96 	struct bfs_file *file = f->f_fsdata;
97 
98 	bfs_fini(file->bfs);
99 
100 	return 0;
101 }
102 
103 int
104 bfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
105 {
106 	struct bfs_file *file = f->f_fsdata;
107 	int n, start, end;
108 	uint8_t *p = buf;
109 	size_t bufsz = size;
110 	int cur = file->cur;
111 
112 	if (cur + size > file->size)
113 		size = file->size - cur;
114 
115 	start = file->start + (cur >> DEV_BSHIFT);
116 	end = file->start + ((cur + size) >> DEV_BSHIFT);
117 
118 	/* first sector */
119 	if (!sector_read(0, file->buf, start))
120 		return -2;
121 	n = TRUNC_SECTOR(cur) + DEV_BSIZE - cur;
122 	if (n >= size) {
123 		memcpy(p, file->buf + DEV_BSIZE - n, size);
124 		goto done;
125 	}
126 	memcpy(p, file->buf + DEV_BSIZE - n, n);
127 	p += n;
128 
129 	if ((end - start - 1) > 0) {
130 		if (!sector_read_n(0, p, start + 1, end - start - 1))
131 			return -2;
132 		p += (end - start - 1) * DEV_BSIZE;
133 	}
134 
135 	/* last sector */
136 	if (!sector_read(0, file->buf, end))
137 		return -2;
138 	n = cur + size - TRUNC_SECTOR(cur + size);
139 	memcpy(p, file->buf, n);
140 
141  done:
142 	file->cur += size;
143 
144 	if (resid)
145 		*resid = bufsz - size;
146 
147 	return 0;
148 }
149 
150 int
151 bfs_write(struct open_file *f, void *start, size_t size, size_t *resid)
152 {
153 
154 	return -1;
155 }
156 
157 off_t
158 bfs_seek(struct open_file *f, off_t offset, int where)
159 {
160 	struct bfs_file *file = f->f_fsdata;
161 	int cur;
162 
163 	switch (where) {
164 	case SEEK_SET:
165 		cur = offset;
166 		break;
167 	case SEEK_CUR:
168 		cur = file->cur + offset;
169 		break;
170 	case SEEK_END:
171 		cur = file->size + offset;
172 		break;
173 	default:
174 		return EINVAL;
175 	}
176 
177 	if (cur  < 0 || cur >= file->size) {
178 		return EINVAL;
179 	}
180 
181 	file->cur = cur;
182 
183 	return (off_t)cur;
184 }
185 
186 int
187 bfs_stat(struct open_file *f, struct stat *stat)
188 {
189 	struct bfs_file *file = f->f_fsdata;
190 
191 	stat->st_size = file->size;
192 
193 	return 0;
194 }
195