Annotation of sys/arch/mvme88k/stand/tftpboot/tftpfs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: tftpfs.c,v 1.3 2006/08/13 23:08:43 miod Exp $ */
2:
3: /*-
4: * Copyright (c) 2001 Steve Murphree, Jr.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by TooLs GmbH.
18: * 4. The name of TooLs GmbH may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * TFTP file system.
35: */
36:
37: #include <sys/param.h>
38: #include <sys/time.h>
39: #include <sys/stat.h>
40: #include <ufs/ffs/fs.h>
41: #include <lib/libkern/libkern.h>
42:
43: #include "stand.h"
44: #include "tftpfs.h"
45:
46: /*
47: * In-core open file.
48: */
49: struct tftp_file {
50: char filename[128];
51: off_t f_seekp; /* seek pointer */
52: char *f_buf; /* buffer for data block */
53: off_t f_off; /* index into buffer for data block */
54: daddr_t f_buf_blkno; /* block number of data block */
55: size_t f_buf_size;
56: };
57:
58: #define TFTP_BLOCK_SHIFT 9
59: #define TFTP_BLOCK_SIZE (1<<TFTP_BLOCK_SHIFT) /* 512 by tftp convention */
60: #define TFTP_BLOCK_NO(x) ((x >> TFTP_BLOCK_SHIFT) + 1)
61: #define TFTP_BLOCK_OFF(x) (x % TFTP_BLOCK_SIZE)
62:
63: static int tftp_read_file(struct open_file *, char **, size_t *);
64:
65: /*
66: * Read a portion of a file into an internal buffer. Return
67: * the location in the buffer and the amount in the buffer.
68: */
69:
70: char tftp_buf[TFTP_BLOCK_SIZE]; /* static */
71: struct tftp_file tftp_ctrl;
72:
73: static int
74: tftp_read_file(f, buf_p, size_p)
75: struct open_file *f;
76: char **buf_p; /* out */
77: size_t *size_p; /* out */
78: {
79: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
80: long off;
81: register daddr_t file_block;
82: size_t block_size;
83: int i, rc;
84:
85: off = TFTP_BLOCK_OFF(fp->f_seekp);
86: file_block = TFTP_BLOCK_NO(fp->f_seekp);
87: block_size = TFTP_BLOCK_SIZE;
88:
89: if (file_block == fp->f_buf_blkno + 1) {
90: /*
91: * Normal, incremental block transfer.
92: */
93: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
94: file_block, block_size, fp->f_buf, &fp->f_buf_size);
95: if (rc)
96: return (rc);
97: if (!(file_block % 4)) /* twiddle every 4 blocks */
98: twiddle();
99: fp->f_buf_blkno = file_block;
100: } else if (file_block > fp->f_buf_blkno + 1) {
101: /*
102: * Read ahead to the requested block; If we need
103: * those we skipped, see below.
104: */
105: for (i = (fp->f_buf_blkno + 1); i <= file_block; i++) {
106: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
107: i, block_size, fp->f_buf, &fp->f_buf_size);
108: if (rc)
109: return (rc);
110: }
111: fp->f_buf_blkno = file_block;
112: } else if (file_block < fp->f_buf_blkno) {
113: /*
114: * Uh oh... We can't rewind. Reopen the file
115: * and start again.
116: */
117: char filename[64];
118: strlcpy(filename, fp->filename, sizeof filename);
119: tftpfs_close(f);
120: tftpfs_open(filename, f);
121: for (i = 1; i <= file_block; i++) {
122: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
123: i, block_size, fp->f_buf, &fp->f_buf_size);
124: if (rc)
125: return (rc);
126: }
127: fp->f_buf_blkno = file_block;
128: }
129:
130: /*
131: * Return address of byte in buffer corresponding to
132: * offset, and size of remainder of buffer after that
133: * byte.
134: */
135: *buf_p = fp->f_buf + off;
136: *size_p = fp->f_buf_size - off;
137:
138: /*
139: * But truncate buffer at end of file.
140: */
141: if (fp->f_buf_size > block_size){
142: twiddle();
143: return(EIO);
144: }
145:
146:
147: return (0);
148: }
149:
150: /*
151: * Open a file.
152: */
153: int
154: tftpfs_open(path, f)
155: char *path;
156: struct open_file *f;
157: {
158: struct tftp_file *fp;
159: int rc = 0;
160:
161: /* locate file system specific data structure and zero it.*/
162: fp = &tftp_ctrl;
163: bzero(fp, sizeof(struct tftp_file));
164: f->f_fsdata = (void *)fp;
165: fp->f_seekp = 0;
166: fp->f_buf = tftp_buf;
167: bzero(fp->f_buf, TFTP_BLOCK_SIZE);
168: fp->f_buf_size = 0;
169:
170: strlcpy(fp->filename, path, sizeof fp->filename);
171:
172: if (f->f_dev->dv_open == NULL) {
173: panic("No device open()!");
174: }
175: twiddle();
176: rc = (f->f_dev->dv_open)(f, path);
177: return (rc);
178: }
179:
180: int
181: tftpfs_close(f)
182: struct open_file *f;
183: {
184: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
185:
186: fp->f_buf = (void *)0;
187: f->f_fsdata = (void *)0;
188: (f->f_dev->dv_close)(f);
189: return (0);
190: }
191:
192: /*
193: * Copy a portion of a file into kernel memory.
194: * Cross block boundaries when necessary.
195: */
196: int
197: tftpfs_read(f, start, size, resid)
198: struct open_file *f;
199: void *start;
200: size_t size;
201: size_t *resid; /* out */
202: {
203: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
204: register size_t csize;
205: char *buf;
206: size_t buf_size;
207: int rc = 0;
208: register char *addr = start;
209:
210: while (size != 0) {
211: rc = tftp_read_file(f, &buf, &buf_size);
212: if (rc)
213: break;
214:
215: csize = size;
216: if (csize > buf_size)
217: csize = buf_size;
218:
219: bcopy(buf, addr, csize);
220:
221: fp->f_seekp += csize;
222: addr += csize;
223: size -= csize;
224: }
225: if (resid)
226: *resid = size;
227: return (rc);
228: }
229:
230: /*
231: * Not implemented.
232: */
233: int
234: tftpfs_write(f, start, size, resid)
235: struct open_file *f;
236: void *start;
237: size_t size;
238: size_t *resid; /* out */
239: {
240:
241: return (EROFS);
242: }
243:
244: /*
245: * We only see forward. We can't rewind.
246: */
247: off_t
248: tftpfs_seek(f, offset, where)
249: struct open_file *f;
250: off_t offset;
251: int where;
252: {
253: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
254:
255: switch (where) {
256: case SEEK_SET:
257: fp->f_seekp = offset;
258: break;
259: case SEEK_CUR:
260: fp->f_seekp += offset;
261: break;
262: case SEEK_END:
263: errno = EIO;
264: return (-1);
265: break;
266: default:
267: return (-1);
268: }
269: return (fp->f_seekp);
270: }
271:
272: int
273: tftpfs_stat(f, sb)
274: struct open_file *f;
275: struct stat *sb;
276: {
277: return EIO;
278: }
279:
280: #ifndef NO_READDIR
281: int
282: tftpfs_readdir (struct open_file *f, char *name)
283: {
284: return EIO;
285: }
286: #endif
287:
CVSweb