# Grub2 issues



## markbsd2 (Jun 30, 2014)

Hi guys,

I'm trying to install grub2 as my bootloader with no success. I'm using ZFS GPT with the following partition table:

```
# gpart show
=>       34  134217661  ada0  GPT  (64G)
         34      40960     1  bios-boot  (20M)
      40994    4194304     2  freebsd-swap  (2.0G)
    4235298  129982397     3  freebsd-zfs  (62G)
```
When I run `grub-install` I got the error:

```
# grub-install --force /dev/ada0
Path `/boot/grub' is not readable by GRUB on boot. Installation is impossible. Aborting.
Exit 1
```
I tried also install using grub2-pcbsd port, with a different error:

```
# grub-install --force /dev/ada0
Installing for i386-pc platform.
grub-install: error: unknown filesystem.
Exit 1
```
I have no idea what I can do. Anyone could help me?

Thanks.


----------



## wblock@ (Jun 30, 2014)

Using the port verifies that it will work on FreeBSD.  When I tried this, it needed a small partition just for Grub itself.  But the error makes me think Grub can't read or boot from a ZFS partition.  Assuming PC-BSD can do that, the easy way would be to check their installer and see what it does.


----------



## markbsd2 (Jun 30, 2014)

Hi wblock,

Thanks your for answer. I have an update about this subject. I tried to install grub on FreeBSD 9.2 and it worked, but with one exception: i had to remove label config on my install.

For instance, i was using gpart() like this:


```
gpart create -s gpt ada0
gpart add -s 1M -t bios-boot ada0
gpart add -s 2g -t freebsd-swap -l swap ada0
gpart add -t freebsd-zfs -l disk0 ada0
```

I had to replace with (no label):


```
gpart create -s gpt ada0
gpart add -s 1M -t bios-boot ada0
gpart add -s 2g -t freebsd-swap ada0
gpart add -t freebsd-zfs ada0
```

After that was possible to install grub, but only on FreeBSD 9.2. Using FreeBSD 10, wasn't possible even without labels.

I read PCBSD install scripts as you suggested and they are doing the same as I did. To tell you the truth i don't know what could be different with FreeBSD 10.


----------



## markbsd2 (Jun 30, 2014)

Another update.

After installed FreeBSD 10, running with verbose mode i can see the following:


```
# grub-install -vvv --force /dev/ada0

grub-core/kern/emu/hostdisk.c:236: reusing open device `/dev/ada0'
grub-core/kern/disk.c:421: Read out of range: sector 0x7bff7bd (attempt to read or write outside of partition).
grub-core/kern/fs.c:78: cbfs detection failed.
grub-core/kern/fs.c:56: Detecting btrfs...
grub-core/kern/fs.c:78: btrfs detection failed.
grub-core/kern/fs.c:56: Detecting bfs...
grub-core/kern/fs.c:78: bfs detection failed.
grub-core/kern/fs.c:56: Detecting afs...
grub-core/kern/fs.c:78: afs detection failed.
grub-core/kern/fs.c:56: Detecting affs...
grub-core/kern/fs.c:78: affs detection failed.
grub-install: error: unknown filesystem.
```

Any idea what's going on?

Thanks


----------



## jrm@ (Jul 1, 2014)

Hi @markbsd2,

I don't know the answer to your latest question, but I did what @wblock@ suggested and it worked like a charm. That is, I checked out the PC-BSD repository and modified the GRUB configuration to remove the graphics and made a few customizations. The bonus is that it works with boot environments. IIRC, you want to look in overlays/install-overlay/boot/grub.


----------



## markbsd2 (Jul 1, 2014)

Hi @jrm,

Are you using FreeBSD 10 with ZFS?

Thanks


----------



## jrm@ (Jul 1, 2014)

No.  I'm using 9-STABLE with ZFS.  I initially  chose the GRUB bootloader because there was a BIOS bug in my Lenovo X220 that caused problems.  I think Allan Jude built a workaround in his installer, but I'll probably stick with GRUB for the benefits I mentioned above.  I took a closer look and the file to work with from the PC-BSD repo is src-sh/pc-extractoverlay/ports-overlay/usr/local/etc/grub.d/10_ktrueos.  Below is my edited version that I used to replace /usr/local/etc/grub.d/10_kfreebsd from sysutils/grub2.  Don't forget to run `grub-mkconfig -o /boot/grub/grub.cfg`.  The only thing I miss is seeing Beastie when I boot up.  One of these days I'll set that up. 


```
#!/bin/sh
#
# Copyright 2013 iXsystems (Kris Moore)
# Minor modifications by Joseph Mingrone
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted providing that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# Script to detect FreeBSD disk installations and create grub
# entries for them

ROOTFS=`mount | awk '/ \/ / {print $1}'`
BEDS="$( echo ${ROOTFS} | awk -F '/' '{print $2}' )"
if [ "$BEDS" = "dev" ] ; then BEDS="ROOT"; fi


display_loaderopts()
{
  # Optional ARG1, set to a ZFS dataset to mount and read values from
  if [ -n "$1" ] ; then
     fMnt="/mnt.$$"
     mkdir $fMnt
     mount -t zfs  ${1} $fMnt >/dev/null 
     if [ $? -ne 0 ] ; then
        echo "Failed to mount ${1}" >&2
        return
     fi
  else
     fMnt=""
  fi
  
  # Create our placeholder to save _load entries to parse
  touch /tmp/.lRObjs.$$
  touch /tmp/.lSysCtls.$$

  # Loader files, in order of which to read them
  lFiles="${fMnt}/boot/loader.conf.local ${fMnt}/boot/loader.conf"
  for f in $lFiles
  do
     if [ ! -e "$f" ] ; then continue ; fi

     # Lets parse any of the _load= lines
     grep "_load=" ${f} | grep -v "^#" >/tmp/.lObjs.$$
     while read line
     do
       loadVal="`echo $line | cut -d '=' -f 1`"
       # Is this value already set in a higher priority file?
       grep -q "^${loadVal}" /tmp/.lRObjs.$$
       if [ $? -eq 0 ];then continue; fi

       # Save this value for later
       echo "$line" >> /tmp/.lRObjs.$$
       haveObjs=1

     done < /tmp/.lObjs.$$
     rm /tmp/.lObjs.$$

     # Lets look for any sysctls to set
     grep "." ${f} | grep "=" | grep -v "^#" | grep -v "_load" >/tmp/.sObjs.$$
     while read line
     do
       loadVal="`echo $line | cut -d '=' -f 1`"
       # Is this value already set in a higher priority file?
       grep -q "^${loadVal}" /tmp/.lSysCtls.$$
       if [ $? -eq 0 ];then continue; fi

       # Save this value for later
       echo "$line" >> /tmp/.lSysCtls.$$
       haveSysCtls=1

     done < /tmp/.sObjs.$$
     rm /tmp/.sObjs.$$
  done

  # Now lets echo out the modules to load
  if [ "$haveObjs" = "1" ] ; then
    while read line
    do
      echo "$line" | grep -q '"YES"'
      if [ $? -ne 0 ] ; then continue ; fi
      module="`echo $line | cut -d '=' -f 1 | sed 's|_load||g'`"
      # Try to locate module now
      if [ -e "${fMnt}/boot/kernel/${module}.ko" ] ; then
        mPath="kernel"
      elif [ -e "${fMnt}/boot/modules/${module}.ko" ] ; then
        mPath="modules"
      else
	# This isn't a module that we can see, lets set it as a variable
	#echo "No such module $line, setting as a variable" >&2
        echo "$line" >> /tmp/.lSysCtls.$$
        continue
      fi
      echo "    kfreebsd_module_elf ${loadPrefix}/@/boot/${mPath}/${module}.ko"
    done < /tmp/.lRObjs.$$
  fi

  # Any sysctls to set?
  if [ "$haveSysCtls" = "1" ] ; then
    while read line
    do
      # Strip out the vfs.root.mountfrom, we set that elsewhere
      echo "$line" | grep -q "vfs.root.mountfrom"
      if [ $? -eq 0 ] ; then continue ; fi

      val="`echo $line | sed 's|"||g'`"
      echo "    set kFreeBSD.${val}"
    done < /tmp/.lSysCtls.$$
  fi

  rm /tmp/.lRObjs.$$
  rm /tmp/.lSysCtls.$$
  if [ -n "$1" ] ; then
     umount /mnt.$$ >/dev/null
     rmdir /mnt.$$ >/dev/null
  fi
}

detect_beadm()
{
   which -s beadm
   if [ $? -ne 0 ] ; then return 0; fi

   # Check if we are running from the installer and use its beadm
   if [ -e "/root/beadm.install" ] ; then
      BEADM="/root/beadm.install"
   else
      BEADM="`which beadm`"
   fi

   ${BEADM} list >/dev/null 2>/dev/null
   if [ $? -ne 0 ] ; then return 0; fi


   NICK="FreeBSD"

   # Get list of beadm datasets
   for b in `${BEADM} list 2>/dev/null| grep -v "Created" | cut -d ' ' -f 1`
   do
      # Got a beadm snapshot, lets get the complete dataset name
      beLine=`${BEADM} list -a | grep "/$BEDS/${b}"`
      cdataset=`echo $beLine | awk '{print $1}'`
      cdatadate=`echo $beLine | awk '{print $5}'`
      cdatatime=`echo $beLine | awk '{print $6}'`
      ztank=`echo $cdataset | cut -d '/' -f 1`
      shortdataset="/`echo $cdataset | cut -d '/' -f 2-5`"

      # First part of this dataset
      cat > /tmp/.grubdataset.$$.1 << EOF
    insmod zfs
    search --no-floppy -s -l $ztank
EOF

      # Second part of loader to save
      cat > /tmp/.grubdataset.$$.2 << EOF
    kfreebsd_module ${shortdataset}/@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache
    set kFreeBSD.vfs.root.mountfrom=zfs:$cdataset
EOF
      
      # Now lets look for options in loader.conf to load
      loadPrefix="${shortdataset}"
      # If this is the current mounted dataset, we can skip mounting it
      mount | grep -q -e "$cdataset on / (" -e "$cdataset on /mnt ("
      if [ $? -eq 0 ] ; then
        display_loaderopts >>/tmp/.grubdataset.$$.2
      else
        display_loaderopts $cdataset >> /tmp/.grubdataset.$$.2
      fi

      # Lets start a submenu for each BE
cat << EOF
# Start FreeBSD BE Submenu
submenu "${NICK} ($b) - ${cdatadate} ${cdatatime}" {
EOF
  
  # Lets do the default entry first
  #################################
  cat << EOF
  menuentry "Standard Bootup" {
EOF
  # Get the dataset guts
  cat /tmp/.grubdataset.$$.1
  echo "    kfreebsd ${shortdataset}/@/boot/kernel/kernel"
  echo "    kfreebsd_loadenv ${shortdataset}@/boot/device.hints"
  cat /tmp/.grubdataset.$$.2

  # Set any options
  cat << EOF
  }
EOF

  # Next lets do single user mode
  #################################
  cat << EOF
  menuentry "Single User Mode" {
EOF
  # Get the dataset guts
  cat /tmp/.grubdataset.$$.1
  echo "    kfreebsd ${shortdataset}/@/boot/kernel/kernel -s"
  echo "    kfreebsd_loadenv ${shortdataset}@/boot/device.hints"
  cat /tmp/.grubdataset.$$.2

  # Set any options
  cat << EOF
  }
EOF

      # Close the submenu section
      cat << EOF
}
# End FreeBSD BE

EOF
   done

   # Cleanup after ourselves
   if [ -e "/tmp/.grubdataset.$$.1" ] ; then
     rm /tmp/.grubdataset.$$.1
     rm /tmp/.grubdataset.$$.2
   fi
}

# Detect our types of disk layouts
detect_beadm
```


----------

