libgrub_cmd.c revision 753a6d457b330b1b29b2d3eefcd0831116ce950d
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * CDDL HEADER START
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * The contents of this file are subject to the terms of the
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Common Development and Distribution License (the "License").
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * You may not use this file except in compliance with the License.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * or http://www.opensolaris.org/os/licensing.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * See the License for the specific language governing permissions
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * and limitations under the License.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * When distributing Covered Code, include this CDDL HEADER in each
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * If applicable, add the following below this CDDL HEADER, with the
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * fields enclosed by brackets "[]" replaced with your own identifying
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * information: Portions Copyright [yyyy] [name of copyright owner]
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * CDDL HEADER END
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Use is subject to license terms.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * This file contains all the functions that implement the following
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * GRUB commands:
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * kernel, kernel$, module, module$, findroot, bootfs
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success, errno on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <stdio.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <stdlib.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <assert.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <alloca.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <errno.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <strings.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <unistd.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <fcntl.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/types.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/fs/ufs_mount.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/dktp/fdisk.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#if defined(__i386)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/x86_archext.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#endif /* __i386 */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include "libgrub_impl.h"
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#define RESET_MODULE(barg) ((barg)->gb_module[0] = 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#if defined(__i386)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic const char cpuid_dev[] = "/dev/cpu/self/cpuid";
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 1 if the system supports 64-bit mode, 0 if it doesn't,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * or -1 on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorecpuid_64bit_capable(void)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int fd, ret = -1;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore uint32_t cp_eax, cp_ebx, cp_ecx, cp_edx;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } cpuid_regs;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((fd = open(cpuid_dev, O_RDONLY)) == -1)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (pread(fd, &cpuid_regs, sizeof (cpuid_regs), 0x80000001) ==
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (cpuid_regs))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = ((CPUID_AMD_EDX_LM & cpuid_regs.cp_edx) != 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) close(fd);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#endif /* __i386 */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Expand $ISAIDR
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#if !defined(__i386)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/* ARGSUSED */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#endif /* __i386 */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic size_t
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorebarg_isadir_var(char *var, int sz)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#if defined(__i386)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (cpuid_64bit_capable() == 1)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (strlcpy(var, "amd64", sz));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#endif /* __i386 */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore var[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Expand $ZFS-BOOTFS
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic size_t
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorebarg_bootfs_var(const grub_barg_t *barg, char *var, int sz)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int n;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore assert(barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore n = snprintf(var, sz, "zfs-bootfs=%s,bootpath=\"%s\"",
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_physpath);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore var[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore n = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (n);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Expand all the variables without appending them more than once.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreexpand_var(char *arg, size_t argsz, const char *var, size_t varsz,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *val, size_t valsz)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *sp = arg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t sz = argsz, len;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *buf, *dst, *src;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore buf = alloca(argsz);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore dst = buf;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore while ((src = strstr(sp, var)) != NULL) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore len = src - sp;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (len + valsz > sz) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = E2BIG;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore break;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) bcopy(sp, dst, len);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) bcopy(val, dst + len, valsz);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore dst += len + valsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sz -= len + valsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sp = src + varsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(dst, sp, sz) >= sz)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = E2BIG;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (ret == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bcopy(buf, arg, argsz);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorematch_bootfs(zfs_handle_t *zfh, void *data)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *zfn;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_barg_t *barg = (grub_barg_t *)data;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = (zfs_get_type(zfh) == ZFS_TYPE_FILESYSTEM &&
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (zfn = zfs_get_name(zfh)) != NULL &&
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore strcmp(barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, zfn) == 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (ret != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_walkret = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore else
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) zfs_iter_filesystems(zfh, match_bootfs, barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_close(zfh);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (barg->gb_walkret == 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic void
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorereset_root(grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) memset(&barg->gb_root, 0, sizeof (barg->gb_root));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_bootsign[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_kernel[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore RESET_MODULE(barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/* ARGSUSED */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreskip_line(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/* ARGSUSED */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreerror_line(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_INVALIDLINE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorekernel(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore RESET_MODULE(barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >=
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_kernel))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooremodule(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >=
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_module))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooredollar_kernel(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t bfslen, isalen;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char isadir[32];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char bootfs[BOOTARGS_MAX];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore RESET_MODULE(barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >=
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_kernel))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bfslen = barg_bootfs_var(barg, bootfs, sizeof (bootfs));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore isalen = barg_isadir_var(isadir, sizeof (isadir));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (bfslen >= sizeof (bootfs) || isalen >= sizeof (isadir))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EINVAL);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel),
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ZFS_BOOT_VAR, strlen(ZFS_BOOT_VAR), bootfs, bfslen)) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel),
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooredollar_module(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t isalen;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char isadir[32];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >=
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_module))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((isalen = barg_isadir_var(isadir, sizeof (isadir))) >= sizeof
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (isadir))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EINVAL);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = expand_var(barg->gb_module, sizeof (barg->gb_module),
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorefindroot(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t sz, bsz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *sign;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore reset_root(barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sign = lp->gl_arg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_prtnum = (uint_t)PRTNUM_INVALID;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_slcnum = (uint_t)SLCNUM_WHOLE_DISK;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (sign[0] == '(') {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ++sign;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((pos = strchr(sign, ',')) == NULL || (sz = pos - sign) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_FINDROOTFMT);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ++pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (!IS_PRTNUM_VALID(barg->gb_prtnum = pos[0] - '0'))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_FINDROOTFMT);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ++pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (pos[0] != ',' ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore !IS_SLCNUM_VALID(barg->gb_slcnum = pos[1]) ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos[2] != ')')
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_FINDROOTFMT);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sz = strlen(sign);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bsz = strlen(BOOTSIGN_DIR "/");
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (bsz + sz + 1 > sizeof (barg->gb_bootsign))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bcopy(BOOTSIGN_DIR "/", barg->gb_bootsign, bsz);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore bcopy(sign, barg->gb_bootsign + bsz, sz);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_bootsign [bsz + sz] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (grub_find_bootsign(barg));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorebootfs(const grub_line_t *lp, grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_handle_t *zfh;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_menu_t *mp = barg->gb_entry->ge_menu;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *gfs_devp;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t gfs_dev_len;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* Check if root is zfs */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_NOTZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore gfs_devp = barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore gfs_dev_len = sizeof (barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * If the bootfs value is the same as the bootfs for the pool,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * do nothing.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(lp->gl_arg, gfs_devp) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strlcpy(gfs_devp, lp->gl_arg, gfs_dev_len) >= gfs_dev_len)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (E2BIG);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* check if specified bootfs belongs to the root pool */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((zfh = zfs_open(mp->gm_fs.gf_lzfh,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_dev,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ZFS_TYPE_FILESYSTEM)) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_OPENZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_walkret = EG_UNKBOOTFS;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) zfs_iter_filesystems(zfh, match_bootfs, barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_close(zfh);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (barg->gb_walkret == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) grub_fsd_get_mountp(barg->gb_root.gr_fs +
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore GRBM_ZFS_BOOTFS, MNTTYPE_ZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (barg->gb_walkret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}