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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file contains functions for constructing boot arguments
28 * from GRUB menu for Fast Reboot.
37 #include <sys/types.h>
40 #include "libgrub_impl.h"
43 #define CUR_ELFDATA ELFDATA2MSB
45 #define CUR_ELFDATA ELFDATA2LSB
49 * Open the kernel file.
50 * Return zero on sucess or error code otherwise.
51 * On success the kernel file descriptor is returned in fdp.
54 get_kernel_fd(const char *path
, int *fdp
)
57 int fd
= -1, class, format
;
58 char ident
[EI_NIDENT
];
60 /* kernel basename must be unix */
61 if ((bname
= strrchr(path
, '/')) == NULL
)
66 if (strcmp(bname
, "unix") != 0) {
67 if (strcmp(bname
, "xen.gz") == 0)
68 return (EG_XVMNOTSUP
);
72 if ((fd
= open64(path
, O_RDONLY
)) >= 0 &&
73 (pread64(fd
, ident
, sizeof (ident
), 0) == sizeof (ident
))) {
75 class = ident
[EI_CLASS
];
76 format
= ident
[EI_DATA
];
78 if ((class == ELFCLASS32
|| class == ELFCLASS64
) &&
79 (memcmp(&ident
[EI_MAG0
], ELFMAG
, 4) == 0) &&
80 format
== CUR_ELFDATA
) {
88 return (EG_OPENKERNFILE
);
92 * Construct boot arguments for Fast Reboot from the ge_barg field of
94 * Return 0 on success, errno on failure.
97 barg2bootargs(const grub_barg_t
*barg
, grub_boot_args_t
*fbarg
)
100 char path
[BOOTARGS_MAX
];
101 char rpath
[BOOTARGS_MAX
];
102 const grub_fsdesc_t
*fsd
;
105 bzero(fbarg
, sizeof (*fbarg
));
106 fbarg
->gba_kernel_fd
= -1;
108 if (!IS_BARG_VALID(barg
))
110 if ((fsd
= grub_get_rootfsd(&barg
->gb_root
)) == NULL
)
111 return (EG_UNKNOWNFS
);
113 bcopy(fsd
, &fbarg
->gba_fsd
, sizeof (fbarg
->gba_fsd
));
114 bcopy(barg
->gb_kernel
, fbarg
->gba_kernel
, sizeof (fbarg
->gba_kernel
));
115 bcopy(barg
->gb_module
, fbarg
->gba_module
, sizeof (fbarg
->gba_module
));
117 if (fbarg
->gba_fsd
.gfs_mountp
[0] == 0 &&
118 (rc
= grub_fsd_mount_tmp(&fbarg
->gba_fsd
,
119 barg
->gb_root
.gr_fstyp
)) != 0)
122 if (snprintf(path
, sizeof (path
), "%s%s", fbarg
->gba_fsd
.gfs_mountp
,
123 fbarg
->gba_kernel
) >= sizeof (path
)) {
127 (void) strtok(path
, " \t");
128 (void) clean_path(path
);
131 * GRUB requires absolute path, no symlinks, so do we
133 if ((rc
= resolvepath(path
, rpath
, sizeof (rpath
))) == -1)
137 if (strcmp(rpath
, path
) != 0)
140 rc
= get_kernel_fd(rpath
, &fbarg
->gba_kernel_fd
);
143 /* construct bootargs command-line */
144 if (rc
== 0 && snprintf(fbarg
->gba_bootargs
,
145 sizeof (fbarg
->gba_bootargs
), "%s %s", fbarg
->gba_fsd
.gfs_mountp
,
146 fbarg
->gba_kernel
) >= sizeof (fbarg
->gba_bootargs
))
151 grub_cleanup_boot_args(fbarg
);
157 * Construct boot arguments for Fast Reboot from grub_menu_t.
158 * Return 0 on success, errno on failure.
161 grub_entry_get_boot_args(grub_entry_t
*ent
, grub_boot_args_t
*fbarg
)
163 int rc
= EG_INVALIDENT
;
165 if (IS_ENTRY_VALID(ent
) && (rc
= grub_entry_construct_barg(ent
)) == 0)
166 return (barg2bootargs(&ent
->ge_barg
, fbarg
));
172 * Construct boot arguments for Fast Reboot from grub_menu_t and the
174 * Return 0 on success, errno on failure.
177 grub_menu_get_boot_args(const grub_menu_t
*mp
, int num
,
178 grub_boot_args_t
*fbarg
)
185 if ((ent
= grub_menu_get_entry(mp
, num
)) == NULL
)
188 return (grub_entry_get_boot_args(ent
, fbarg
));
192 * Construct boot arguments from the specified GRUB menu entry.
193 * Caller must allocate space for fbarg, and call grub_cleanup_boot_args()
194 * when it's done with fbarg to clean up.
196 * Return 0 on success, errno on failure.
199 grub_get_boot_args(grub_boot_args_t
*fbarg
, const char *menupath
, int num
)
205 if ((rc
= grub_menu_init(menupath
, &mp
)) == 0) {
206 rc
= grub_menu_get_boot_args(mp
, num
, fbarg
);
213 * Clean up when done with fbarg: close file handle, unmount file
214 * systems. Must be safe to call even if not all the fields are
218 grub_cleanup_boot_args(grub_boot_args_t
*fbarg
)
223 (void) close(fbarg
->gba_kernel_fd
);
224 grub_fsd_umount_tmp(&fbarg
->gba_fsd
);