4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Simple nfs ops - open, close, read, and lseek.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <rpc/types.h>
32 #include <sys/t_lock.h>
34 #include <sys/fcntl.h>
37 #include <sys/promif.h>
41 #include <sys/bootvfs.h>
42 #include <sys/bootdebug.h>
43 #include <sys/salib.h>
44 #include <sys/sacache.h>
47 #include <rpcsvc/nfs_prot.h>
48 #include "socket_inet.h"
52 ushort_t vttoif_tab
[] = {
53 0, S_IFREG
, S_IFDIR
, S_IFBLK
, S_IFCHR
, S_IFLNK
, S_IFIFO
,
54 S_IFDOOR
, 0, S_IFSOCK
, 0
57 static int file_desc
= 1;
58 static struct nfs_files
{
61 struct nfs_files
*next
;
66 #define dprintf if (boothowto & RB_DEBUG) printf
68 static int boot_nfs_open(char *filename
, int flags
);
69 static int boot_nfs_close(int fd
);
70 static ssize_t
boot_nfs_read(int fd
, caddr_t buf
, size_t size
);
71 static off_t
boot_nfs_lseek(int, off_t
, int);
72 static int boot_nfs_fstat(int fd
, struct bootstat
*stp
);
73 static void boot_nfs_closeall(int flag
);
74 static int boot_nfs_getdents(int fd
, struct dirent
*dep
, unsigned size
);
76 struct boot_fs_ops boot_nfs_ops
= {
90 * bootops.c calls a closeall() function to close all open files. Since
91 * we only permit one open file at a time (not counting the device), this
92 * is simple to implement.
97 boot_nfs_closeall(int flag
)
99 struct nfs_files
*filep
;
102 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
103 printf("boot_nfs_closeall(%x)\n", flag
);
106 if (nfs_files
->file
.version
== 0 &&
107 nfs_files
->desc
== 0 &&
108 nfs_files
->next
== NULL
)
111 /* delete any dynamically allocated entries */
112 while ((filep
= nfs_files
->next
) != NULL
) {
113 nfs_files
->next
= filep
->next
;
114 bkmem_free((caddr_t
)filep
, sizeof (struct nfs_files
));
117 /* clear the first, static file */
118 bzero((caddr_t
)nfs_files
, sizeof (struct nfs_files
));
121 release_cache(mac_get_dev());
127 * Get a file pointer given a file descriptor. Return 0 on error
129 static struct nfs_files
*
132 struct nfs_files
*filep
;
134 for (filep
= nfs_files
; filep
; filep
= filep
->next
) {
135 if (fd
== filep
->desc
)
142 * Unmount the root fs -- not supported for this fstype.
146 boot_nfs_unmountroot(void)
152 * open a file for reading. Note: writing is NOT supported.
156 boot_nfs_open(char *path
, int flags
)
158 struct nfs_files
*filep
, *newfilep
;
162 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
163 printf("boot_nfs_open(%s, %x)\n", path
, flags
);
166 /* file can only be opened readonly. */
167 if (flags
& ~O_RDONLY
) {
168 dprintf("boot_nfs_open: files can only be opened O_RDONLY.\n");
172 if (path
== NULL
|| *path
== '\0') {
173 dprintf("boot_nfs_open: NULL or EMPTY pathname argument.\n");
177 /* Try and find a vacant file pointer */
181 if (filep
->desc
== 0) {
182 filep
->desc
= file_desc
++;
184 break; /* We've got a file pointer */
186 /* Get next entry if not at end of list */
189 } while (filep
->next
);
191 /* If a a vacant file pointer cannot be found, make one */
193 if ((newfilep
= (struct nfs_files
*)
194 bkmem_zalloc(sizeof (struct nfs_files
))) == 0) {
195 dprintf("open: Cannot allocate file pointer\n");
198 filep
->next
= newfilep
;
200 filep
->desc
= file_desc
++;
203 if (lookup(path
, &filep
->file
, FALSE
) != 0) {
205 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
206 printf("boot_nfs_open(): Cannot open '%s'.\n", path
);
208 /* zero file pointer */
209 bzero((caddr_t
)filep
, sizeof (struct nfs_file
));
213 bzero(&filep
->file
.cookie
, sizeof (filep
->file
.cookie
));
216 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
217 printf("boot_nfs_open(): '%s' successful, fd = 0x%x\n",
220 return (filep
->desc
);
224 * close a previously opened file.
227 boot_nfs_close(int fd
)
229 struct nfs_files
*filep
;
232 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
233 printf("boot_nfs_close(%d)\n", fd
);
235 if ((filep
= get_filep(fd
)) == 0)
241 bzero((caddr_t
)&filep
->file
, sizeof (struct nfs_file
));
255 boot_nfs_read(int fd
, char *buf
, size_t size
)
257 struct nfs_files
*filep
;
261 dprintf("boot_nfs_read: Bad file number.\n");
265 dprintf("boot_nfs_read: Bad address.\n");
270 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
271 printf("boot_nfs_read(%d, %x, 0x%x)\n", fd
, buf
, size
);
274 /* initialize for read */
275 if ((filep
= get_filep(fd
)) == 0)
278 switch (filep
->file
.version
) {
280 count
= nfsread(&filep
->file
, buf
, size
);
283 count
= nfs3read(&filep
->file
, buf
, size
);
286 count
= nfs4read(&filep
->file
, buf
, size
);
289 printf("boot_nfs_read: NFS Version %d not supported\n",
290 filep
->file
.version
);
296 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
297 printf("boot_nfs_read(): 0x%x bytes.\n", count
);
303 * lseek - move read file pointer.
307 boot_nfs_lseek(int fd
, off_t offset
, int whence
)
309 struct nfs_files
*filep
;
312 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
313 printf("boot_nfs_lseek(%d, 0x%x, %d)\n", fd
, offset
, whence
);
317 dprintf("boot_nfs_lseek: Bad file number.\n");
321 if ((filep
= get_filep(fd
)) == 0)
328 * file ptr is set to offset from beginning of file
330 filep
->file
.offset
= offset
;
334 * file ptr is set to offset from current position
336 filep
->file
.offset
+= offset
;
340 * file ptr is set to current size of file plus offset.
341 * But since we only support reading, this is illegal.
345 * invalid offset origin
347 dprintf("boot_nfs_lseek: invalid whence value.\n");
352 return (filep
->file
.offset
);
355 * BROKE - lseek should return the offset seeked to on a
356 * successful seek, not zero - This must be fixed in the
357 * kernel before It can be fixed here.
364 * This version of fstat supports mode, size, inode #, and times only.
365 * It can be enhanced if more is required,
369 boot_nfs_fstat(int fd
, struct bootstat
*stp
)
372 struct nfs_files
*filep
;
376 if ((boothowto
& DBFLAGS
) == DBFLAGS
) {
377 printf("boot_nfs_fstat(%d, 0x%x)\n", fd
, stp
);
381 dprintf("boot_nfs_fstat(): Bad file number 0.\n");
385 if ((filep
= get_filep(fd
)) == 0)
388 bzero((char *)&va
, sizeof (va
));
389 va
.va_mask
= AT_TYPE
| AT_SIZE
| AT_MODE
| AT_NODEID
|
390 AT_ATIME
| AT_CTIME
| AT_MTIME
;
392 switch (filep
->file
.version
) {
394 status
= nfsgetattr(&filep
->file
, &va
);
397 status
= nfs3getattr(&filep
->file
, &va
);
400 status
= nfs4getattr(&filep
->file
, &va
);
403 printf("boot_nfs_fstat: NFS Version %d not supported\n",
404 filep
->file
.version
);
412 if (va
.va_size
> (u_offset_t
)MAXOFF_T
) {
413 dprintf("boot_nfs_fstat(): File too large.\n");
416 stp
->st_size
= (off_t
)va
.va_size
;
417 stp
->st_mode
= VTTOIF(va
.va_type
) | va
.va_mode
;
418 stp
->st_atim
.tv_sec
= va
.va_atime
.tv_sec
;
419 stp
->st_atim
.tv_nsec
= va
.va_atime
.tv_nsec
;
420 stp
->st_ctim
.tv_sec
= va
.va_ctime
.tv_sec
;
421 stp
->st_ctim
.tv_nsec
= va
.va_ctime
.tv_nsec
;
422 stp
->st_mtim
.tv_sec
= va
.va_mtime
.tv_sec
;
423 stp
->st_mtim
.tv_nsec
= va
.va_mtime
.tv_nsec
;
424 stp
->st_ino
= (ino_t
)va
.va_nodeid
;
427 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
428 printf("boot_nfs_fstat(): done.\n");
434 boot_nfs_getdents(int fd
, struct dirent
*dep
, unsigned size
)
436 struct nfs_files
*filep
;
440 if ((boothowto
& DBFLAGS
) == DBFLAGS
) {
441 printf("boot_nfs_getdents(%d, 0x%x, 0x%x)\n", fd
, dep
, size
);
446 dprintf("boot_nfs_getdents(): Bad file number 0.\n");
450 if ((filep
= get_filep(fd
)) == 0)
453 switch (filep
->file
.version
) {
455 status
= nfsgetdents(&filep
->file
, dep
, size
);
458 status
= nfs3getdents(&filep
->file
, dep
, size
);
461 printf("boot_nfs_getdents: NFS Version %d not supported\n",
462 filep
->file
.version
);
467 if ((boothowto
& DBFLAGS
) == DBFLAGS
)
468 printf("boot_nfs_getdents(): done.\n");