1753a6d4Sherry Moore/* 2753a6d4Sherry Moore * CDDL HEADER START 3753a6d4Sherry Moore * 4753a6d4Sherry Moore * The contents of this file are subject to the terms of the 5753a6d4Sherry Moore * Common Development and Distribution License (the "License"). 6753a6d4Sherry Moore * You may not use this file except in compliance with the License. 7753a6d4Sherry Moore * 8753a6d4Sherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9753a6d4Sherry Moore * or http://www.opensolaris.org/os/licensing. 10753a6d4Sherry Moore * See the License for the specific language governing permissions 11753a6d4Sherry Moore * and limitations under the License. 12753a6d4Sherry Moore * 13753a6d4Sherry Moore * When distributing Covered Code, include this CDDL HEADER in each 14753a6d4Sherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15753a6d4Sherry Moore * If applicable, add the following below this CDDL HEADER, with the 16753a6d4Sherry Moore * fields enclosed by brackets "[]" replaced with your own identifying 17753a6d4Sherry Moore * information: Portions Copyright [yyyy] [name of copyright owner] 18753a6d4Sherry Moore * 19753a6d4Sherry Moore * CDDL HEADER END 20753a6d4Sherry Moore */ 21753a6d4Sherry Moore/* 22753a6d4Sherry Moore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23753a6d4Sherry Moore * Use is subject to license terms. 24753a6d4Sherry Moore */ 251a902efHans Rosenfeld/* 261a902efHans Rosenfeld * Copyright 2015 Nexenta Systems, Inc. 271a902efHans Rosenfeld */ 28753a6d4Sherry Moore 29753a6d4Sherry Moore/* 30753a6d4Sherry Moore * This file contains all the functions that implement the following 31753a6d4Sherry Moore * GRUB commands: 32753a6d4Sherry Moore * kernel, kernel$, module, module$, findroot, bootfs 33753a6d4Sherry Moore * Return 0 on success, errno on failure. 34753a6d4Sherry Moore */ 35753a6d4Sherry Moore#include <stdio.h> 36753a6d4Sherry Moore#include <stdlib.h> 37753a6d4Sherry Moore#include <assert.h> 38753a6d4Sherry Moore#include <alloca.h> 39753a6d4Sherry Moore#include <errno.h> 40753a6d4Sherry Moore#include <strings.h> 41753a6d4Sherry Moore#include <unistd.h> 42753a6d4Sherry Moore#include <fcntl.h> 43753a6d4Sherry Moore#include <sys/types.h> 44753a6d4Sherry Moore#include <sys/fs/ufs_mount.h> 45753a6d4Sherry Moore#include <sys/dktp/fdisk.h> 46753a6d4Sherry Moore#if defined(__i386) 47753a6d4Sherry Moore#include <sys/x86_archext.h> 48753a6d4Sherry Moore#endif /* __i386 */ 49753a6d4Sherry Moore 50753a6d4Sherry Moore#include "libgrub_impl.h" 51753a6d4Sherry Moore 52753a6d4Sherry Moore#define RESET_MODULE(barg) ((barg)->gb_module[0] = 0) 53753a6d4Sherry Moore 54c5aaf10Konstantin Ananyev#define BPROP_ZFSBOOTFS "zfs-bootfs" 55c5aaf10Konstantin Ananyev#define BPROP_BOOTPATH "bootpath" 56c5aaf10Konstantin Ananyev 57753a6d4Sherry Moore#if defined(__i386) 58753a6d4Sherry Moorestatic const char cpuid_dev[] = "/dev/cpu/self/cpuid"; 59753a6d4Sherry Moore 60753a6d4Sherry Moore/* 61753a6d4Sherry Moore * Return 1 if the system supports 64-bit mode, 0 if it doesn't, 62753a6d4Sherry Moore * or -1 on failure. 63753a6d4Sherry Moore */ 64753a6d4Sherry Moorestatic int 65753a6d4Sherry Moorecpuid_64bit_capable(void) 66753a6d4Sherry Moore{ 67753a6d4Sherry Moore int fd, ret = -1; 68753a6d4Sherry Moore struct { 69753a6d4Sherry Moore uint32_t cp_eax, cp_ebx, cp_ecx, cp_edx; 70753a6d4Sherry Moore } cpuid_regs; 71753a6d4Sherry Moore 72753a6d4Sherry Moore if ((fd = open(cpuid_dev, O_RDONLY)) == -1) 73753a6d4Sherry Moore return (ret); 74753a6d4Sherry Moore 75753a6d4Sherry Moore if (pread(fd, &cpuid_regs, sizeof (cpuid_regs), 0x80000001) == 76753a6d4Sherry Moore sizeof (cpuid_regs)) 77753a6d4Sherry Moore ret = ((CPUID_AMD_EDX_LM & cpuid_regs.cp_edx) != 0); 78753a6d4Sherry Moore 79753a6d4Sherry Moore (void) close(fd); 80753a6d4Sherry Moore return (ret); 81753a6d4Sherry Moore} 82753a6d4Sherry Moore#endif /* __i386 */ 83753a6d4Sherry Moore 84753a6d4Sherry Moore 85753a6d4Sherry Moore/* 86753a6d4Sherry Moore * Expand $ISAIDR 87753a6d4Sherry Moore */ 88753a6d4Sherry Moore#if !defined(__i386) 89753a6d4Sherry Moore/* ARGSUSED */ 90753a6d4Sherry Moore#endif /* __i386 */ 91753a6d4Sherry Moorestatic size_t 92753a6d4Sherry Moorebarg_isadir_var(char *var, int sz) 93753a6d4Sherry Moore{ 94753a6d4Sherry Moore#if defined(__i386) 95753a6d4Sherry Moore if (cpuid_64bit_capable() == 1) 96753a6d4Sherry Moore return (strlcpy(var, "amd64", sz)); 97753a6d4Sherry Moore#endif /* __i386 */ 98753a6d4Sherry Moore 99753a6d4Sherry Moore var[0] = 0; 100753a6d4Sherry Moore return (0); 101753a6d4Sherry Moore} 102753a6d4Sherry Moore 103753a6d4Sherry Moore/* 104753a6d4Sherry Moore * Expand $ZFS-BOOTFS 105753a6d4Sherry Moore */ 106753a6d4Sherry Moorestatic size_t 107753a6d4Sherry Moorebarg_bootfs_var(const grub_barg_t *barg, char *var, int sz) 108753a6d4Sherry Moore{ 109753a6d4Sherry Moore int n; 110753a6d4Sherry Moore 111753a6d4Sherry Moore assert(barg); 112753a6d4Sherry Moore if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) == 0) { 113c5aaf10Konstantin Ananyev n = snprintf(var, sz, 114c5aaf10Konstantin Ananyev BPROP_ZFSBOOTFS "=%s," BPROP_BOOTPATH "=\"%s\"", 115753a6d4Sherry Moore barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, 116753a6d4Sherry Moore barg->gb_root.gr_physpath); 117753a6d4Sherry Moore } else { 118753a6d4Sherry Moore var[0] = 0; 119753a6d4Sherry Moore n = 0; 120753a6d4Sherry Moore } 121753a6d4Sherry Moore return (n); 122753a6d4Sherry Moore} 123753a6d4Sherry Moore 124753a6d4Sherry Moore/* 125753a6d4Sherry Moore * Expand all the variables without appending them more than once. 126753a6d4Sherry Moore */ 127753a6d4Sherry Moorestatic int 128753a6d4Sherry Mooreexpand_var(char *arg, size_t argsz, const char *var, size_t varsz, 129753a6d4Sherry Moore char *val, size_t valsz) 130753a6d4Sherry Moore{ 131753a6d4Sherry Moore char *sp = arg; 132753a6d4Sherry Moore size_t sz = argsz, len; 133753a6d4Sherry Moore char *buf, *dst, *src; 134753a6d4Sherry Moore int ret = 0; 135753a6d4Sherry Moore 136753a6d4Sherry Moore buf = alloca(argsz); 137753a6d4Sherry Moore dst = buf; 138753a6d4Sherry Moore 139753a6d4Sherry Moore while ((src = strstr(sp, var)) != NULL) { 140753a6d4Sherry Moore 141753a6d4Sherry Moore len = src - sp; 142753a6d4Sherry Moore 143753a6d4Sherry Moore if (len + valsz > sz) { 144753a6d4Sherry Moore ret = E2BIG; 145753a6d4Sherry Moore break; 146753a6d4Sherry Moore } 147753a6d4Sherry Moore 148753a6d4Sherry Moore (void) bcopy(sp, dst, len); 149753a6d4Sherry Moore (void) bcopy(val, dst + len, valsz); 150753a6d4Sherry Moore dst += len + valsz; 151753a6d4Sherry Moore sz -= len + valsz; 152753a6d4Sherry Moore sp = src + varsz; 153753a6d4Sherry Moore } 154753a6d4Sherry Moore 155753a6d4Sherry Moore if (strlcpy(dst, sp, sz) >= sz) 156753a6d4Sherry Moore ret = E2BIG; 157753a6d4Sherry Moore 158753a6d4Sherry Moore if (ret == 0) 159753a6d4Sherry Moore bcopy(buf, arg, argsz); 160753a6d4Sherry Moore return (ret); 161753a6d4Sherry Moore} 162753a6d4Sherry Moore 163c5aaf10Konstantin Ananyev/* 164c5aaf10Konstantin Ananyev * Searches first occurence of boot-property 'bprop' in str. 165c5aaf10Konstantin Ananyev * str supposed to be in format: 166c5aaf10Konstantin Ananyev * " [-B prop=[value][,prop=[value]]...] 167c5aaf10Konstantin Ananyev */ 168c5aaf10Konstantin Ananyevstatic const char * 169c5aaf10Konstantin Ananyevfind_bootprop(const char *str, const char *bprop) 170c5aaf10Konstantin Ananyev{ 171c5aaf10Konstantin Ananyev const char *s; 172c5aaf10Konstantin Ananyev size_t bplen, len; 173c5aaf10Konstantin Ananyev 174c5aaf10Konstantin Ananyev assert(str); 175c5aaf10Konstantin Ananyev assert(bprop); 176c5aaf10Konstantin Ananyev 177c5aaf10Konstantin Ananyev bplen = strlen(bprop); 178c5aaf10Konstantin Ananyev s = str; 179c5aaf10Konstantin Ananyev 180c5aaf10Konstantin Ananyev while ((str = strstr(s, " -B")) != NULL || 181c5aaf10Konstantin Ananyev (str = strstr(s, "\t-B")) != NULL) { 182c5aaf10Konstantin Ananyev s = str + 3; 183c5aaf10Konstantin Ananyev len = strspn(s, " \t"); 184c5aaf10Konstantin Ananyev 185c5aaf10Konstantin Ananyev /* empty -B option, skip it */ 186c5aaf10Konstantin Ananyev if (len != 0 && s[len] == '-') 187c5aaf10Konstantin Ananyev continue; 188c5aaf10Konstantin Ananyev 189c5aaf10Konstantin Ananyev s += len; 190c5aaf10Konstantin Ananyev do { 191c5aaf10Konstantin Ananyev len = strcspn(s, "= \t"); 192c5aaf10Konstantin Ananyev if (s[len] != '=') 193c5aaf10Konstantin Ananyev break; 194c5aaf10Konstantin Ananyev 195c5aaf10Konstantin Ananyev /* boot property we are looking for? */ 196c5aaf10Konstantin Ananyev if (len == bplen && strncmp(s, bprop, bplen) == 0) 197c5aaf10Konstantin Ananyev return (s); 198c5aaf10Konstantin Ananyev 199c5aaf10Konstantin Ananyev s += len; 200c5aaf10Konstantin Ananyev 201c5aaf10Konstantin Ananyev /* skip boot property value */ 202c5aaf10Konstantin Ananyev while ((s = strpbrk(s + 1, "\"\', \t")) != NULL) { 203c5aaf10Konstantin Ananyev 204c5aaf10Konstantin Ananyev /* skip quoted */ 205c5aaf10Konstantin Ananyev if (s[0] == '\"' || s[0] == '\'') { 206c5aaf10Konstantin Ananyev if ((s = strchr(s + 1, s[0])) == NULL) { 207c5aaf10Konstantin Ananyev /* unbalanced quotes */ 208c5aaf10Konstantin Ananyev return (s); 209c5aaf10Konstantin Ananyev } 210c5aaf10Konstantin Ananyev } 211c5aaf10Konstantin Ananyev else 212c5aaf10Konstantin Ananyev break; 213c5aaf10Konstantin Ananyev } 214c5aaf10Konstantin Ananyev 215c5aaf10Konstantin Ananyev /* no more boot properties */ 216c5aaf10Konstantin Ananyev if (s == NULL) 217c5aaf10Konstantin Ananyev return (s); 218c5aaf10Konstantin Ananyev 219c5aaf10Konstantin Ananyev /* no more boot properties in that -B block */ 220c5aaf10Konstantin Ananyev if (s[0] != ',') 221c5aaf10Konstantin Ananyev break; 222c5aaf10Konstantin Ananyev 223c5aaf10Konstantin Ananyev s += strspn(s, ","); 224c5aaf10Konstantin Ananyev } while (s[0] != ' ' && s[0] != '\t'); 225c5aaf10Konstantin Ananyev } 226c5aaf10Konstantin Ananyev return (NULL); 227c5aaf10Konstantin Ananyev} 228c5aaf10Konstantin Ananyev 229c5aaf10Konstantin Ananyev/* 230c5aaf10Konstantin Ananyev * Add bootpath property to str if 231c5aaf10Konstantin Ananyev * 1. zfs-bootfs property is set explicitly 232c5aaf10Konstantin Ananyev * and 233c5aaf10Konstantin Ananyev * 2. bootpath property is not set 234c5aaf10Konstantin Ananyev */ 235c5aaf10Konstantin Ananyevstatic int 236c5aaf10Konstantin Ananyevupdate_bootpath(char *str, size_t strsz, const char *bootpath) 237c5aaf10Konstantin Ananyev{ 238c5aaf10Konstantin Ananyev size_t n; 239c5aaf10Konstantin Ananyev char *buf; 240c5aaf10Konstantin Ananyev const char *bfs; 241c5aaf10Konstantin Ananyev 242c5aaf10Konstantin Ananyev /* zfs-bootfs is not specified, or bootpath is allready set */ 243c5aaf10Konstantin Ananyev if ((bfs = find_bootprop(str, BPROP_ZFSBOOTFS)) == NULL || 244c5aaf10Konstantin Ananyev find_bootprop(str, BPROP_BOOTPATH) != NULL) 245c5aaf10Konstantin Ananyev return (0); 246c5aaf10Konstantin Ananyev 247c5aaf10Konstantin Ananyev n = bfs - str; 248c5aaf10Konstantin Ananyev buf = alloca(strsz); 249c5aaf10Konstantin Ananyev 250c5aaf10Konstantin Ananyev bcopy(str, buf, n); 251c5aaf10Konstantin Ananyev if (snprintf(buf + n, strsz - n, BPROP_BOOTPATH "=\"%s\",%s", 252c5aaf10Konstantin Ananyev bootpath, bfs) >= strsz - n) 253c5aaf10Konstantin Ananyev return (E2BIG); 254c5aaf10Konstantin Ananyev 255c5aaf10Konstantin Ananyev bcopy(buf, str, strsz); 256c5aaf10Konstantin Ananyev return (0); 257c5aaf10Konstantin Ananyev} 258c5aaf10Konstantin Ananyev 259753a6d4Sherry Moorestatic int 260753a6d4Sherry Moorematch_bootfs(zfs_handle_t *zfh, void *data) 261753a6d4Sherry Moore{ 262753a6d4Sherry Moore int ret; 263753a6d4Sherry Moore const char *zfn; 264753a6d4Sherry Moore grub_barg_t *barg = (grub_barg_t *)data; 265753a6d4Sherry Moore 266753a6d4Sherry Moore ret = (zfs_get_type(zfh) == ZFS_TYPE_FILESYSTEM && 267753a6d4Sherry Moore (zfn = zfs_get_name(zfh)) != NULL && 268753a6d4Sherry Moore strcmp(barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, zfn) == 0); 269753a6d4Sherry Moore 270753a6d4Sherry Moore if (ret != 0) 271753a6d4Sherry Moore barg->gb_walkret = 0; 272753a6d4Sherry Moore else 273753a6d4Sherry Moore (void) zfs_iter_filesystems(zfh, match_bootfs, barg); 274753a6d4Sherry Moore 275753a6d4Sherry Moore zfs_close(zfh); 276753a6d4Sherry Moore return (barg->gb_walkret == 0); 277753a6d4Sherry Moore} 278753a6d4Sherry Moore 279753a6d4Sherry Moorestatic void 280753a6d4Sherry Moorereset_root(grub_barg_t *barg) 281753a6d4Sherry Moore{ 282753a6d4Sherry Moore (void) memset(&barg->gb_root, 0, sizeof (barg->gb_root)); 283753a6d4Sherry Moore barg->gb_bootsign[0] = 0; 284753a6d4Sherry Moore barg->gb_kernel[0] = 0; 285753a6d4Sherry Moore RESET_MODULE(barg); 286753a6d4Sherry Moore} 287753a6d4Sherry Moore 288753a6d4Sherry Moore/* ARGSUSED */ 289753a6d4Sherry Mooreint 290753a6d4Sherry Mooreskip_line(const grub_line_t *lp, grub_barg_t *barg) 291753a6d4Sherry Moore{ 292753a6d4Sherry Moore return (0); 293753a6d4Sherry Moore} 294753a6d4Sherry Moore 295753a6d4Sherry Moore/* ARGSUSED */ 296753a6d4Sherry Mooreint 297753a6d4Sherry Mooreerror_line(const grub_line_t *lp, grub_barg_t *barg) 298753a6d4Sherry Moore{ 299fda6624Konstantin Ananyev if (lp->gl_cmdtp == GRBM_ROOT_CMD) 300fda6624Konstantin Ananyev return (EG_ROOTNOTSUPP); 301753a6d4Sherry Moore return (EG_INVALIDLINE); 302753a6d4Sherry Moore} 303753a6d4Sherry Moore 304753a6d4Sherry Mooreint 305753a6d4Sherry Moorekernel(const grub_line_t *lp, grub_barg_t *barg) 306753a6d4Sherry Moore{ 307753a6d4Sherry Moore RESET_MODULE(barg); 308753a6d4Sherry Moore if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >= 309753a6d4Sherry Moore sizeof (barg->gb_kernel)) 310753a6d4Sherry Moore return (E2BIG); 311753a6d4Sherry Moore 312753a6d4Sherry Moore return (0); 313753a6d4Sherry Moore} 314753a6d4Sherry Moore 315753a6d4Sherry Mooreint 316753a6d4Sherry Mooremodule(const grub_line_t *lp, grub_barg_t *barg) 317753a6d4Sherry Moore{ 318753a6d4Sherry Moore if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >= 319753a6d4Sherry Moore sizeof (barg->gb_module)) 320753a6d4Sherry Moore return (E2BIG); 321753a6d4Sherry Moore 322753a6d4Sherry Moore return (0); 323753a6d4Sherry Moore} 324753a6d4Sherry Moore 325753a6d4Sherry Mooreint 326753a6d4Sherry Mooredollar_kernel(const grub_line_t *lp, grub_barg_t *barg) 327753a6d4Sherry Moore{ 328753a6d4Sherry Moore int ret; 329753a6d4Sherry Moore size_t bfslen, isalen; 330753a6d4Sherry Moore char isadir[32]; 331753a6d4Sherry Moore char bootfs[BOOTARGS_MAX]; 332753a6d4Sherry Moore 333753a6d4Sherry Moore RESET_MODULE(barg); 334753a6d4Sherry Moore if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >= 335753a6d4Sherry Moore sizeof (barg->gb_kernel)) 336753a6d4Sherry Moore return (E2BIG); 337753a6d4Sherry Moore 338753a6d4Sherry Moore bfslen = barg_bootfs_var(barg, bootfs, sizeof (bootfs)); 339753a6d4Sherry Moore isalen = barg_isadir_var(isadir, sizeof (isadir)); 340753a6d4Sherry Moore 341753a6d4Sherry Moore if (bfslen >= sizeof (bootfs) || isalen >= sizeof (isadir)) 342753a6d4Sherry Moore return (EINVAL); 343753a6d4Sherry Moore 344753a6d4Sherry Moore if ((ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel), 345753a6d4Sherry Moore ZFS_BOOT_VAR, strlen(ZFS_BOOT_VAR), bootfs, bfslen)) != 0) 346753a6d4Sherry Moore return (ret); 347753a6d4Sherry Moore 348c5aaf10Konstantin Ananyev if ((ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel), 349c5aaf10Konstantin Ananyev ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen)) != 0) 350c5aaf10Konstantin Ananyev return (ret); 351c5aaf10Konstantin Ananyev 352c5aaf10Konstantin Ananyev if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) == 0) 353c5aaf10Konstantin Ananyev ret = update_bootpath(barg->gb_kernel, sizeof (barg->gb_kernel), 354c5aaf10Konstantin Ananyev barg->gb_root.gr_physpath); 355753a6d4Sherry Moore 356753a6d4Sherry Moore return (ret); 357753a6d4Sherry Moore} 358753a6d4Sherry Moore 359753a6d4Sherry Mooreint 360753a6d4Sherry Mooredollar_module(const grub_line_t *lp, grub_barg_t *barg) 361753a6d4Sherry Moore{ 362753a6d4Sherry Moore int ret; 363753a6d4Sherry Moore size_t isalen; 364753a6d4Sherry Moore char isadir[32]; 365753a6d4Sherry Moore 366753a6d4Sherry Moore if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >= 367753a6d4Sherry Moore sizeof (barg->gb_module)) 368753a6d4Sherry Moore return (E2BIG); 369753a6d4Sherry Moore 370753a6d4Sherry Moore if ((isalen = barg_isadir_var(isadir, sizeof (isadir))) >= sizeof 371753a6d4Sherry Moore (isadir)) 372753a6d4Sherry Moore return (EINVAL); 373753a6d4Sherry Moore 374753a6d4Sherry Moore ret = expand_var(barg->gb_module, sizeof (barg->gb_module), 375753a6d4Sherry Moore ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen); 376753a6d4Sherry Moore 377753a6d4Sherry Moore return (ret); 378753a6d4Sherry Moore} 379753a6d4Sherry Moore 380753a6d4Sherry Moore 381753a6d4Sherry Mooreint 382753a6d4Sherry Moorefindroot(const grub_line_t *lp, grub_barg_t *barg) 383753a6d4Sherry Moore{ 384753a6d4Sherry Moore size_t sz, bsz; 385753a6d4Sherry Moore const char *sign; 386753a6d4Sherry Moore 387753a6d4Sherry Moore reset_root(barg); 388753a6d4Sherry Moore 389753a6d4Sherry Moore sign = lp->gl_arg; 390753a6d4Sherry Moore barg->gb_prtnum = (uint_t)PRTNUM_INVALID; 391753a6d4Sherry Moore barg->gb_slcnum = (uint_t)SLCNUM_WHOLE_DISK; 392753a6d4Sherry Moore 393753a6d4Sherry Moore if (sign[0] == '(') { 394753a6d4Sherry Moore const char *pos; 395753a6d4Sherry Moore 396753a6d4Sherry Moore ++sign; 397753a6d4Sherry Moore if ((pos = strchr(sign, ',')) == NULL || (sz = pos - sign) == 0) 398753a6d4Sherry Moore return (EG_FINDROOTFMT); 399753a6d4Sherry Moore 400753a6d4Sherry Moore ++pos; 401753a6d4Sherry Moore if (!IS_PRTNUM_VALID(barg->gb_prtnum = pos[0] - '0')) 402753a6d4Sherry Moore return (EG_FINDROOTFMT); 403753a6d4Sherry Moore 404753a6d4Sherry Moore ++pos; 4055763162Toomas Soome /* 4065763162Toomas Soome * check the slice only when its presented 4075763162Toomas Soome */ 4085763162Toomas Soome if (pos[0] != ')') { 4095763162Toomas Soome if (pos[0] != ',' || 4105763162Toomas Soome !IS_SLCNUM_VALID(barg->gb_slcnum = pos[1]) || 4115763162Toomas Soome pos[2] != ')') 4125763162Toomas Soome return (EG_FINDROOTFMT); 4135763162Toomas Soome } 414753a6d4Sherry Moore } else { 415753a6d4Sherry Moore sz = strlen(sign); 416753a6d4Sherry Moore } 417753a6d4Sherry Moore 418753a6d4Sherry Moore bsz = strlen(BOOTSIGN_DIR "/"); 419753a6d4Sherry Moore if (bsz + sz + 1 > sizeof (barg->gb_bootsign)) 420753a6d4Sherry Moore return (E2BIG); 421753a6d4Sherry Moore 422753a6d4Sherry Moore bcopy(BOOTSIGN_DIR "/", barg->gb_bootsign, bsz); 423753a6d4Sherry Moore bcopy(sign, barg->gb_bootsign + bsz, sz); 424753a6d4Sherry Moore barg->gb_bootsign [bsz + sz] = 0; 425753a6d4Sherry Moore 426753a6d4Sherry Moore return (grub_find_bootsign(barg)); 427753a6d4Sherry Moore} 428753a6d4Sherry Moore 429753a6d4Sherry Mooreint 430753a6d4Sherry Moorebootfs(const grub_line_t *lp, grub_barg_t *barg) 431753a6d4Sherry Moore{ 432753a6d4Sherry Moore zfs_handle_t *zfh; 433753a6d4Sherry Moore grub_menu_t *mp = barg->gb_entry->ge_menu; 434753a6d4Sherry Moore char *gfs_devp; 435753a6d4Sherry Moore size_t gfs_dev_len; 436753a6d4Sherry Moore 437753a6d4Sherry Moore /* Check if root is zfs */ 438753a6d4Sherry Moore if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) != 0) 439753a6d4Sherry Moore return (EG_NOTZFS); 440753a6d4Sherry Moore 441753a6d4Sherry Moore gfs_devp = barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev; 442753a6d4Sherry Moore gfs_dev_len = sizeof (barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev); 443753a6d4Sherry Moore 444753a6d4Sherry Moore /* 445753a6d4Sherry Moore * If the bootfs value is the same as the bootfs for the pool, 446753a6d4Sherry Moore * do nothing. 447753a6d4Sherry Moore */ 448753a6d4Sherry Moore if (strcmp(lp->gl_arg, gfs_devp) == 0) 449753a6d4Sherry Moore return (0); 450753a6d4Sherry Moore 451753a6d4Sherry Moore if (strlcpy(gfs_devp, lp->gl_arg, gfs_dev_len) >= gfs_dev_len) 452753a6d4Sherry Moore return (E2BIG); 453753a6d4Sherry Moore 454753a6d4Sherry Moore /* check if specified bootfs belongs to the root pool */ 455753a6d4Sherry Moore if ((zfh = zfs_open(mp->gm_fs.gf_lzfh, 456753a6d4Sherry Moore barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_dev, 457753a6d4Sherry Moore ZFS_TYPE_FILESYSTEM)) == NULL) 458753a6d4Sherry Moore return (EG_OPENZFS); 459753a6d4Sherry Moore 460753a6d4Sherry Moore barg->gb_walkret = EG_UNKBOOTFS; 461753a6d4Sherry Moore (void) zfs_iter_filesystems(zfh, match_bootfs, barg); 462753a6d4Sherry Moore zfs_close(zfh); 463753a6d4Sherry Moore 464753a6d4Sherry Moore if (barg->gb_walkret == 0) 465753a6d4Sherry Moore (void) grub_fsd_get_mountp(barg->gb_root.gr_fs + 466753a6d4Sherry Moore GRBM_ZFS_BOOTFS, MNTTYPE_ZFS); 467753a6d4Sherry Moore 468753a6d4Sherry Moore return (barg->gb_walkret); 469753a6d4Sherry Moore} 470