2 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/kernel.h>
31 #include <sys/proc_internal.h>
32 #include <sys/systm.h>
33 #include <sys/systm.h>
34 #include <sys/mount_internal.h>
35 #include <sys/filedesc.h>
36 #include <sys/vnode_internal.h>
37 #include <sys/imageboot.h>
39 #include <pexpert/pexpert.h>
41 extern struct filedesc filedesc0
;
43 extern int (*mountroot
)(void);
44 extern char rootdevice
[];
46 #define DEBUG_IMAGEBOOT 0
49 #define DBG_TRACE(...) printf(__VA_ARGS__)
51 #define DBG_TRACE(...) do {} while(0)
54 extern int di_root_image(const char *path
, char devname
[], dev_t
*dev_p
);
56 #define kIBFilePrefix "file://"
59 imageboot_needed(void)
62 char *root_path
= NULL
;
64 DBG_TRACE("%s: checking for presence of root path\n", __FUNCTION__
);
66 MALLOC_ZONE(root_path
, caddr_t
, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
67 if (root_path
== NULL
)
68 panic("%s: M_NAMEI zone exhausted", __FUNCTION__
);
70 if(PE_parse_boot_argn("rp", root_path
, MAXPATHLEN
) == TRUE
) {
71 /* Got it, now verify scheme */
73 if (strncmp(root_path
, kIBFilePrefix
,
74 strlen(kIBFilePrefix
)) == 0) {
75 DBG_TRACE("%s: Found %s\n", __FUNCTION__
, root_path
);
78 DBG_TRACE("%s: Invalid URL scheme for %s\n",
79 __FUNCTION__
, root_path
);
82 FREE_ZONE(root_path
, MAXPATHLEN
, M_NAMEI
);
89 * We know there's an image. Attach it, and
90 * switch over to root off it
92 * NB: p is always kernproc
100 char *root_path
= NULL
;
102 DBG_TRACE("%s: entry\n", __FUNCTION__
);
104 MALLOC_ZONE(root_path
, caddr_t
, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
105 if (root_path
== NULL
)
108 if(PE_parse_boot_argn("rp", root_path
, MAXPATHLEN
) == FALSE
) {
113 printf("%s: root image url is %s\n", __FUNCTION__
, root_path
);
114 error
= di_root_image(root_path
, rootdevice
, &dev
);
116 printf("%s: di_root_image failed: %d\n", __FUNCTION__
, error
);
122 printf("%s: root device 0x%x\n", __FUNCTION__
, rootdev
);
123 error
= vfs_mountroot();
125 if (error
== 0 && rootvnode
!= NULL
) {
126 vnode_t newdp
, old_rootvnode
;
127 mount_t new_rootfs
, old_rootfs
;
130 * Get the vnode for '/'.
131 * Set fdp->fd_fd.fd_cdir to reference it.
133 if (VFS_ROOT(TAILQ_LAST(&mountlist
,mntlist
), &newdp
, vfs_context_kernel()))
134 panic("%s: cannot find root vnode", __FUNCTION__
);
136 old_rootvnode
= rootvnode
;
137 old_rootfs
= rootvnode
->v_mount
;
139 mount_list_remove(old_rootfs
);
141 mount_lock(old_rootfs
);
142 #ifdef CONFIG_IMGSRC_ACCESS
143 old_rootfs
->mnt_kern_flag
|= MNTK_BACKS_ROOT
;
144 #endif /* CONFIG_IMGSRC_ACCESS */
145 old_rootfs
->mnt_flag
&= ~MNT_ROOTFS
;
146 mount_unlock(old_rootfs
);
150 new_rootfs
= rootvnode
->v_mount
;
151 mount_lock(new_rootfs
);
152 new_rootfs
->mnt_flag
|= MNT_ROOTFS
;
153 mount_unlock(new_rootfs
);
157 filedesc0
.fd_cdir
= newdp
;
158 DBG_TRACE("%s: root switched\n", __FUNCTION__
);
160 #ifdef CONFIG_IMGSRC_ACCESS
161 if (PE_imgsrc_mount_supported()) {
162 imgsrc_rootvnode
= old_rootvnode
;
164 vnode_getalways(old_rootvnode
);
165 vnode_rele(old_rootvnode
);
166 vnode_put(old_rootvnode
);
169 vnode_getalways(old_rootvnode
);
170 vnode_rele(old_rootvnode
);
171 vnode_put(old_rootvnode
);
172 #endif /* CONFIG_IMGSRC_ACCESS */
177 FREE_ZONE(root_path
, MAXPATHLEN
, M_NAMEI
);
179 DBG_TRACE("%s: exit\n", __FUNCTION__
);