2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2013 Joyent, Inc. All rights reserved.
16 #include <sys/bootconf.h>
17 #include <sys/types.h>
18 #include <sys/param.h>
19 #include <sys/vnode.h>
20 #include <sys/fs/ufs_fsdir.h>
21 #include <sys/fs/ufs_fs.h>
22 #include <sys/fs/ufs_inode.h>
23 #include <sys/sysmacros.h>
24 #include <sys/bootvfs.h>
25 #include <sys/bootinfo.h>
26 #include <sys/filep.h>
29 #include "../common/util.h"
31 #include <sys/sunddi.h>
34 #define MAX_FILES MAX_BOOT_MODULES
37 extern void *bkmem_alloc(size_t);
38 extern void bkmem_free(void *, size_t);
41 * TODO: Replace these declarations with inclusion of the ordinary userland
42 * bootfs headers once they're available.
44 typedef struct bfile
{
45 char bf_name
[MAXPATHLEN
];
48 struct bfile
*bf_next
;
52 typedef struct bf_fd
{
58 static uint_t init_done
;
59 static bf_fd_t fds
[MAX_FDS
];
61 static char cpath
[MAXPATHLEN
]; /* For canonicalising filenames */
63 static void bbootfs_closeall(int);
66 canonicalise(const char *fn
, char *out
)
73 static char scratch
[MAXPATHLEN
];
81 * Remove leading slashes and condense all multiple slashes into one.
87 for (q
= scratch
; *p
!= '\0'; p
++) {
88 if (*p
== '/' && !is_slash
) {
91 } else if (*p
!= '/') {
98 if (strncmp(scratch
, "system/boot/", 12) == 0 ||
99 strcmp(scratch
, "system/boot") == 0) {
105 for (last
= strsep(&s
, "/"), q
= oc
= out
; last
!= NULL
;
106 last
= strsep(&s
, "/")) {
107 if (strcmp(last
, ".") == 0)
109 if (strcmp(last
, "..") == 0) {
110 for (oc
= q
; oc
> out
&& *oc
!= '/'; oc
--)
117 q
+= snprintf(q
, MAXPATHLEN
- (q
- out
), "%s", last
);
125 bbootfs_mountroot(char *str
)
131 bbootfs_unmountroot(void)
144 for (i
= 0; i
< MAX_FILES
; i
++) {
145 (void) snprintf(propname
, sizeof (propname
),
146 "module-name-%u", i
);
147 if (do_bsys_getproplen(NULL
, propname
) < 0)
150 if ((fp
= bkmem_alloc(sizeof (bfile_t
))) == NULL
) {
155 (void) do_bsys_getprop(NULL
, propname
, cpath
);
156 canonicalise(cpath
, fp
->bf_name
);
158 (void) snprintf(propname
, sizeof (propname
),
159 "module-addr-%u", i
);
160 if (do_bsys_getproplen(NULL
, propname
) != sizeof (uint64_t)) {
161 bkmem_free(fp
, sizeof (bfile_t
));
164 (void) do_bsys_getprop(NULL
, propname
, &propval
);
165 fp
->bf_addr
= (void *)(uintptr_t)propval
;
167 (void) snprintf(propname
, sizeof (propname
),
168 "module-size-%u", i
);
169 if (do_bsys_getproplen(NULL
, propname
) != sizeof (uint64_t)) {
170 bkmem_free(fp
, sizeof (bfile_t
));
173 (void) do_bsys_getprop(NULL
, propname
, &propval
);
174 fp
->bf_size
= (size_t)propval
;
186 bbootfs_open(char *fn
, int flags
)
192 if (bbootfs_init() != 0)
198 canonicalise(fn
, cpath
);
200 for (fp
= head
; fp
!= NULL
; fp
= fp
->bf_next
) {
201 if (strcmp(fp
->bf_name
, cpath
) == 0)
208 for (i
= 0; i
< MAX_FDS
; i
++) {
209 if (fds
[i
].fd_file
== NULL
) {
220 bbootfs_close(int fd
)
222 if (fds
[fd
].fd_file
== NULL
)
225 fds
[fd
].fd_file
= NULL
;
232 bbootfs_read(int fd
, caddr_t buf
, size_t size
)
235 bf_fd_t
*fdp
= &fds
[fd
];
237 if (fdp
->fd_file
== NULL
)
240 if (fdp
->fd_pos
>= fdp
->fd_file
->bf_size
)
243 if (fdp
->fd_pos
+ size
> fdp
->fd_file
->bf_size
)
244 len
= fdp
->fd_file
->bf_size
- fdp
->fd_pos
;
248 bcopy(fdp
->fd_file
->bf_addr
+ fdp
->fd_pos
, buf
, len
);
256 bbootfs_lseek(int fd
, off_t addr
, int whence
)
258 bf_fd_t
*fdp
= &fds
[fd
];
260 if (fdp
->fd_file
== NULL
)
271 fdp
->fd_pos
= fdp
->fd_file
->bf_size
;
281 bbootfs_fstat(int fd
, struct bootstat
*bsp
)
283 bf_fd_t
*fdp
= &fds
[fd
];
285 if (fdp
->fd_file
== NULL
)
289 bsp
->st_ino
= fdp
->fd_file
->bf_ino
;
292 bsp
->st_uid
= bsp
->st_gid
= 0;
294 bsp
->st_size
= fdp
->fd_file
->bf_size
;
296 bsp
->st_blocks
= fdp
->fd_file
->bf_size
;
297 (void) strcpy(bsp
->st_fstype
, "bootfs");
304 bbootfs_closeall(int flag
)
308 while (head
!= NULL
) {
310 head
= head
->bf_next
;
312 bkmem_free(fp
, sizeof (bfile_t
));
318 struct boot_fs_ops bbootfs_ops
= {