Looking for Grub and Windows bootloader in all partitions.

So I did load aterm, but it still does not work. Also, I can’t figure out how to copy the text that you see to show you what it does. Now it is different than before in that I do get an output, unlike when in say konsole, just no color and the color commands print out in front of each line. It kind of looks like this:

LinuxUser:/home/james # findgrub2

31;1m - reading MBR on disk /dev/sda                    37;0m...
 - searching partition 34;1m/dev/sda1   (NTFS)          37;0m... --> 37;1mWindows7/Vista Loader found in 31;1m/dev/sda137;0m

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can add the following entry to 37;1m/boot/grub/menu.lst37;0m :
32;1m
###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on /dev/sda1
    rootnoverify (hd0,0)
    chainloader +1
37;0m
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

31;1m - reading MBR on disk /dev/sdb                    37;0m...
 - skiping partition   33m/dev/sdb1   (swap)         37;0m
 - reading bootsector  36;1m/dev/sdb2   (LINUX)         37;0m... --> 37;1mGrub found in 31;1m/dev/sdb237;0m
 - reading bootsector  36;1m/dev/sdb3   (LINUX)         37;0m...
31;1m - reading MBR on disk /dev/sdc                    37;0m...
 - searching partition 34;1m/dev/sdc1   (NTFS)          37;0m...

I just pasted your original code with color into a file I called findgrub2. Now see what I said about the color thing before in your program. Was I right? Anyway, the color is nice I am sure, but not required really. The script without color is fine, or you can just work on it some more if you wish. If it is important, just work on it this weekend. There is no need to keep sending it online until you are happy or give up (on just the color thing). I would get a second opinion as well. Surely someone else here could see if I am just off base for some reason.

Thank You,

The escape character is missing everywhere. Maybe it’s a copy/paste problem (or maybe the text editor you’re using).

On 2010-10-01 02:36, please try again wrote:
>
> jdmcdaniel3;2231076 Wrote:
>> You seem to be using the escape sequence mode and not tput which did
>> work for me in other scripts.
> That’s right. :frowning:
> I could use tput as well (have to find out whether it uses terminfo or
> termcap syntax under openSUSE) or nothing at all (just remove all the
> escape sequences)

IMO, you should not use any color or special formatting. Just text that is easy to paste into a message.


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

On 2010-09-27 15:36, please try again wrote:
>
> (split from ‘Two major problems with dual boot installation of openSuSE
> 11.1 and Windows 7’ (http://tinyurl.com/2wsvqy9))
>
> Carlos E. R.;2228981 Wrote:
>>
>> Thinking… I would perhaps do a for loop on /dev/sd*, checking for
>> strings (is the "strings"program, or something else, always installed?)
>>
>
> I thought it would be enough to look for GRUB, NTLDR and BOOTMGR, since
> Grub (legacy and Grub2) contains ‘GRUB’ in its stage1, Windows from NT
> to Vista ‘NTLDR’ and Windows 7 ‘BOOTMGR’ in their bootcode. I reallly
> wanted to check those strings only (explaining why I didn’t use a case
> insensitive grep). But I must be missing a string for Windows 7 since
> ‘the script couldn’t find it on James’s sda1’
> (http://tinyurl.com/35essxj)

:slight_smile:

Thinking again - look at this one-liner (output edited for brevity):


Minas-Anor:~ # file -s /dev/sda*
/dev/sda:  x86 boot sector; partition 1: ID=0x7, ...; partition 2: ID=0x7,  ...; partition 3:
ID=0x7,.... ; partition 4: ID=0xf, active,... code offset 0xc0
/dev/sda1: x86 boot sector, code offset 0x52, OEM-ID "NTFS    ", sectors/cluster 8, reserved
sectors 0, Media descriptor 0xf8, heads 255, hidden sectors 2048, dos < 4.0 BootSector (0x80)
....
/dev/sda4: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, LBA flag 0x1, 1st sector
stage2 0x149f2dcc, GRUB version 0.97; partition 1: ID=0x82, ...; partition 2: ID=0x5, ..., code
offset 0x48
/dev/sda5: Linux/i386 swap file (new style) 1 (4K pages) size 1572353 pages Label Swap
/dev/sda6: Linux rev 1.0 ext2 filesystem data
/dev/sda7: ReiserFS V3.6
....

partition 1 above is boot partition of win7, by the way. sda2 and sda3 show the same info, except
the size, of course.

If I look for strings, this is what I have:

MBR: RecoveryMgr
sda1: NTFS… BOOTMGR (there is no NTLDR)
sda2, 3: NTFS… Bootmgr (and messages in Spanish).
sda4: GRUB.

IMO, using the good old trusty “file” is more reliable :wink:

Still, we have nothing yet to see what they boot, if they boot something. But the above info is a
lot of good info for diagnosis, to start with :slight_smile:


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

On 2010-09-30 18:06, please try again wrote:

> Well, I wouldn’t say that either. I didn’t want to have to read the
> filesystem. The good job would have been to only read the bootsector.
> It’s amazingly easy when you’re looking for Grub … but Windows … is
> Windows. It’s not too bad because even if the bootsector is valid, we
> still have to make sure that the booloader is present (the file
> ‘bootmgr’ or ‘ntldr’).

Grub is not so easy, either.

In dos/windows, you look for certain hidden files, mapped directly into the bootsector code. I mean,
the 512 bytes code of the bootsector knows what exact sectors of the disk it has to load to load
those boot files, without knowing the format of the disk.

Grub does the same, but instead of hidden files it uses the reserved space before the partition
starts for real, which are not normally used, and it also has hardcoded where they are.

Lilo had a map of the necessary files coded into the very boot sector - and after a kernel change
the map had to be updated. Very similar to what the dos loader did with the sys command as part of
its task.

This is necessary because the bootloaders only have a grand total of 512 bytes of code and data
available, and they only can use BIOS functions to read the disk, raw; meaning, no filesystem
structure (dirs, ect) can be read. Just sectors at a known place and length, pre-programmed.

This is true for any boot loader: dos, windows, lilo, grub… all have to read something at a known
place to do the real booting or system load and start.

Things have not changed that much since IBM designed the first PC. We are using the original design
for boot code, and making do as we can to add more things that were not forecasted, without touching
the basics.

Not sure if I explain myself clearly :-?

Thus, to learn if grub is really installed, you have to decode where the stage 1.5 and 2 should be,
and if they are there. For windows, you have to find if the bootmngr or whatever it is nowdays is
there… etc.

It is quite complex :slight_smile:


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

Yep. Definetely not! We can also just leave it.

I have been using kwrite for everything. Now I did say earlier that the escape sequence was missing? Right? I would also say that I would not try to imbed that character. Lets just go B&W for now.

Here is how I would present the findgrub code. This is just me now.

#!/bin/bash

#: Title       : findgrub
#: Date Created: Wed Sep 29 20:02:40 CDT 2010
#: Last Edit   : Thu Sep 30 21:23:00 CDT 2010
#: Author      : please_try_again & edited by j McDaniel
#: Version     : 2.00
#: Description : Locates the Grub Boot Loader & Windows BootLoader, Creates Grub Menu.Lst Entries
#: Options     : -h | --help, -w | -- writemenu OR -d | --debug 

# Created for the openSUSE forums September 30th in the year 2010 with loving care and presented to all of our great openSUSE USERS!

#
# Copy and paste this text into a text file and save it in your home area, bin folder (~/bin) as the file findgrub
# Once the file is saved, you must make the file executable using the terminal command: chmod +u ~/bin/findgrub
#

# default mointpoint
mnt=/mnt

#
# Check to see if we are root
#

if [[ $UID -ne 0 ]]; then
  echo "Root User Permissions are required, Please Enter the ..."
  echo
  sudo $0 $1
  exit 0
fi

echo
echo "Find Grub Version 2.00 - Written for openSUSE Forums"
echo

function help {
    cat << EOFHELP

findgrub - description and help
options:
-h --help      : show this help 
-w --writemenu : add boot entries to /boot/grub/men.lst 
-d --debug     : print Win bootsectors to standard output

EOFHELP
exit
}

function Linux2LegacyGrub {
    eval `echo ${1:2} | sed 's|\(.\)|maj=\1;min=|;s|$|;|'`
    let min--
    echo "(hd$(($(printf "%d
" \'$maj) - 97)),$min)" 
}

function chainloadEntry { 

if  [ "${WRITEMENU}" ] ; then
    printf " - append boot entry to chainload Windows bootmanager on %s to /boot/grub/menu.lst
" $1
    cp /boot/grub/menu.lst{,.findgrub}
    cat << EOFWriteGrubEntry | sed '/^[     ][     ]*$/d' >> /boot/grub/menu.lst 

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    $makeactive
    chainloader +1

EOFWriteGrubEntry
else
    printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can add the following entry to /boot/grub/menu.lst :
"
    cat << EOFDisplayGrubEntry | sed '/^[     ]*$/d'

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    $makeactive
    chainloader +1

EOFDisplayGrubEntry
    printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
fi
}

function printbs {
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%s Bootsector
---------------------------------------------------------------------------
 " $1     
dd if=$1 bs=512 count=1 2>/dev/null | tr -cd "[:alnum:] [:space:]"
printf " 
----------------------------------------------------------------------------
"
dd if=/dev/sda1 bs=512 count=1 2>/dev/null | od -x 
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"     
}

function printptbl {
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%s Partition table
---------------------------------------------------------------
" $1     
dd if=$1 bs=1 skip=446 count=64 2>/dev/null | od -x | head -4
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"     
}

function findbootmgr {
    case $3 in
        6|b|c|e) fs=vfat ;;
        7) fs=ntfs;;
    esac

      mp=`mount | grep $1 | awk '{ print $3 }'`

    if [ "x$mp" == "x" ] ; then
        mp=$mnt
        mount | grep -q "$p " && mp=/findgrub
        [ -d $mp ] || mkdir $mp
        mount -t $fs $1 $mp
        UNMOUNT=1
    else
        unset UNMOUNT
    fi

    case $2 in
        bootmgr)
            find $mp -maxdepth 1 -iname "bootmgr" | grep -q -i "bootmgr" && {
            printf " --> Windows7/Vista Loader found in %s
" $pt
            chainloadEntry $pt
        }
    ;;
        ntldr)
            find $mp -maxdepth 1 -iname "ntldr" | grep -q  -i "ntldr" && {
            printf " --> Windows NT/2K/XP Loader found in %s
" $pt
            chainloadEntry $pt
        }
     ;;
    esac


    if    [ "$UNMOUNT" ] ; then
        umount $mp
    fi
    [ -d /findgrub ] && rmdir /findgrub
}


# some partition types with color

x6=FAT16                ; c6='33;1m'
xb=FAT32                ; cb='32;1m'
xc=FAT32                ; cc='32;1m'
xe=FAT32                ; ce='32;1m'
x5=Extended                ; c5='32;1m'
xf=Extended                ; cf='32;1m'
x7=NTFS                    ; c7='34;1m'
x27="Win Recovery"        ; c27='31m'
x82=swap                ; c82='33m'
x83=LINUX                ; c83='36;1m'
xee=EFI                    ; cee='31m'
xaf=HFS                    ; caf='35m'
xa5=FreeBSD                ; ca5='35m'
xa6=OpenBSD                ; ca6='35m'
xa9=NetBSD                ; ca9='35m'
 

# Main - BEGIN --------------------------

devs=(`fdisk -l 2&gt;/dev/null | sed -n 's|^Disk \(/dev/[hs]d[a-z]\):.*|\1|p'`)

case "$1" in
    -w|--writemenu) WRITEMENU=1 ; shift ;;
    -d|--debug) 
        DEBUG=1
        shift 
        case "$1" in
            -n|--nocolor) COLOR=0 ;;
        esac    
    ;;
    -h|--help) help ;;
esac


# look for GRUB signature in MBR, Linux(0x83) and Extended(0x05, 0x0f) partitions 
# skip EFI (0xee), swap (0x82) and BSD (0xa5, 0xa6, 0xa9) partitions
# !!! deliberately skip Windows Recovery (0x27) partition

# look for strings 'BOOTMGR' or 'NTLDR' in all other partitions bootsector and
# if found mount the partition and search for files bootmgr or ntldr   

# in debug mode, output bootsector of NTFS and FAT  partitons in ASCII and HEX
# output partition table


# get all partitions ids
eval `fdisk -l 2&gt;/dev/null | awk '/^\/dev/ { if ($2 == "*") ID = $6 ; else ID = $5 ; print $1"="ID";" }' | sed s'|/dev/||'`


for dev in ${devs
[li]} ; do[/li]    if [ -b $dev ] ; then
        printf "
 - reading MBR on disk %-27s ..." "$dev"
        dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && {
printf " --> Grub found in MBR" 
[ "$dev" == "/dev/sda" ] && makeactive=makeactive
}
        for pt in `fdisk -l $dev 2&gt;/dev/null | awk '/^\/dev/ { print $1 }'` ; do
            PT=$(basename $pt)    fs=${!PT}
            f=x${fs} ; FS=${!f} 
            if [ "$DEBUG" ] ; then
                case $fs in
                    6|b|c|e|7) printbs $pt ;;
                esac
            else
                case $fs in
                    ee|af|a5|a6|a9|82|27) 
                    printf "
 - skiping partition   %-11s %-15s" "$pt" "($FS)"
                    ;;
                    83|5|f)
                    printf "
 - reading bootsector  %-11s %-15s ..."  "$pt" "($FS)"
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && printf " --> Grub found in %s" $pt
                    ;;
                    *)
                    printf "
 - searching partition %-11s %-15s ..." "$pt" "($FS)"
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q NTLDR && findbootmgr $pt ntldr $fs
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q BOOTMGR && findbootmgr $pt bootmgr $fs
                    ;;
                esac
            fi    
        done
        [ "$DEBUG" ] && printptbl $dev
    fi
done

printf "
"

[ -d /findgrub ] && rmdir /findgrub

# Main - END ---------------------------

exit 0
# End Of Script

I would copy the above code into a text editor and save it as the file findgrub in the folder /home/yourname/bin, which can also be referenced to as ~/bin. Once you have saved the code into your bin folder, execute the following terminal command:

chmod +u ~/bin/findgrub

To use the program, open up a terminal session and type the command findgrub and enter the root password when requested.

We would like everyone that reads this message to give this program a try and report back with your findings. We need your help now.

Thank You,

‘BOOTMGR’ is for Windows 7 and Vista, ‘NTLDR’ for NT, W2K and (I guess) XP. That’s why I look for both.

I dont’ thing it’s more reliable, but it would be faster, as you could just parse all the infos in one step.

Thats’ true … I won’t post the huge output it produced here with all the Linux and Unix partitions I have. But it’s interesting for sure (last mounted, last written etc).

Yes but that’s not what I meant. Finding stage1 in the bs doesn’t mean that it’s going to find the other stages anywhere and that’s not what I’m looking for. So if you run the script on a machine with several Linux partitions, only the ones having Grub stage1 in their BS will show up (it doesn’t say it will boot but its a good indication that it should). On the other hand, any Windows partition will show up because - not sure as I haven’t installed Windows for many years - I think the simple fact of formating a drive will write either ‘BOOTMGR’ or ‘NTLDR’ or ‘MSDOS’ in the bootsector. So searching ‘GRUB’ will give all the partitions which could/should potentially boot, while searching ‘BOOTMGR’ will also give partitions which aren’t going to boot Windows. That’s why I had to mount such partitions and look for either ‘bootmgr’ or ‘ntldr’ (but if you have a better solution, I’ll take it, since it would be nicer not to mount the filesystem - unfortunately - I meant ‘fortunately’ all I have on my computers is an old 252MB drive C with an old MSDOS/NT bootsector I wrote in assembler many years ago in the purpose of hacking something - I definetly lost the code. It already booted XP, but it won’t probably boot Vista or Windows 7 - and I have no intention to try). And after all, this script (only) intends to write the approriate entries in /boot/grub/menu.lst.

In other words - when we are dealing with only one partition at a time - finding ‘GRUB’ in the BS is a necessary and sufficient condition to ‘assume’ that the partition is going to boot (and desserves an entry in /boot/grub/menu.lst), while finding ‘BOOTMGR’ or ‘NTLDR’ is a necessary but not sufficient condition to assume that Windows is going to boot (more precisely the Windows Boot manager is going to chainload), since it won’t if the ‘bootmgr’ or ‘ntldr’ file is missing. Again, I’m not worrying about Grub stage2 (at least not in this script). But, agreed, I shouldn’t have sait that Grub was easy. :wink:

Right. The escape character got lost in the code I posted. :shame:
It couldn’t have worked for you nor for anybody else.

I would also say that I would not try to imbed that character.

Actually I looked in kwrite out of curiousity but didn’t find how to insert the escape character (usually it would be: ctrl-v + esc ). However the ones in the script are displayed.

Lets just go B&W for now.

Yep. I’ll post a link to download the color version (just for fun).

Yes ! Thanks for adding that! I add a condition in order not to bother superusers with that warning, otherwise perfect!


#
# Check to see if we are root
#

if  $UID -ne 0 ]]; then
  id -Gn | grep -q wheel || echo "Root User Permissions are required, Please Enter the ..."
  echo
  sudo $0 $1
  exit 0
fi

I also modified two sed commands because TABs were part of the regexp, and you seem to have a setting in your editor which replace tabs by spaces. Nog big deal. The consequence would have been one blank line in the middle of a section while appending boot entries to Grub menu.

I put the 2 scripts findgrub and cfindgrub (for colored fingrub) in an archive available here: http://www.unixversal.com/unixversal/linux/openSUSE/findgrub201.tgz

please_try_again looks like we have a wrap on this script. You did a very fine job. The color script also works fine on my system, so we do have a basic problem with transferring text back and forth in code blocks and perhaps there is a problem with the text editor that is being used. Downloading a ready to go file is a very good thing unless you are also trying to impart how to write a script.

None the less, findgrub was super fine scripting job!

Thank You,

Minor changes :
some partitions IDs added, since Solaris ZFS wasn’t identified, as is the example here (sda3) : Unable to boot CentOS 5.5 with SUSE 11.3 grub

Below, the latest version (2.02), also available here: http://www.unixversal.com/unixversal/linux/openSUSE/findgrub202.tgz


#!/bin/bash

#: Title       : findgrub
#: Date Created: Wed Sep 29 20:02:40 CDT 2010
#: Last Edit   : Thu Sep 30 21:23:00 CDT 2010
#: Author      : please_try_again & edited by j McDaniel
#: Version     : 2.02
#: Description : Locates the Grub Boot Loader & Windows BootLoader, Creates Grub Menu.Lst Entries
#: Options     : -h | --help, -w | -- writemenu OR -d | --debug 

# Created for the openSUSE forums September 30th in the year 2010 with loving care and presented to all of our great openSUSE USERS!

#
# Copy and paste this text into a text file and save it in your home area, bin folder (~/bin) as the file findgrub
# Once the file is saved, you must make the file executable using the terminal command: chmod +u ~/bin/findgrub
#

# default mountpoint
mnt=/mnt

#
# Check to see if we are root
#

if [[ $UID -ne 0 ]]; then
  id -Gn | grep -q wheel || echo "Root User Permissions are required, Please Enter the ..."
  echo
  sudo $0 $1
  exit 0
fi

echo
echo "Find Grub Version 2.02 - Written for openSUSE Forums"
echo

function help {
    cat << EOFHELP

$0 - description and help
options:
-h --help      : show this help 
-w --writemenu : add boot entries to /boot/grub/men.lst 
-d --debug     : print Win bootsectors to standard output

EOFHELP
exit
}

function Linux2LegacyGrub {
    eval `echo ${1:2} | sed 's|\(.\)|maj=\1;min=|;s|$|;|'`
    let min--
    echo "(hd$(($(printf "%d
" \'$maj) - 97)),$min)" 
}

function chainloadEntry { 

if  [ "${WRITEMENU}" ] ; then
    printf " - append boot entry to chainload Windows bootmanager on %s to /boot/grub/menu.lst
" $1
    cp /boot/grub/menu.lst{,.findgrub}
    cat << EOFWriteGrubEntry | sed '/^  *$/d' >> /boot/grub/menu.lst 

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    $makeactive
    chainloader +1

EOFWriteGrubEntry
else
    printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can add the following entry to /boot/grub/menu.lst :
"
    cat << EOFDisplayGrubEntry | sed '/^  *$/d'

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    $makeactive
    chainloader +1

EOFDisplayGrubEntry
    printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
fi
}

function printbs {
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%s Bootsector
---------------------------------------------------------------------------
 " $1     
dd if=$1 bs=512 count=1 2>/dev/null | tr -cd "[:alnum:] [:space:]"
printf " 
----------------------------------------------------------------------------
"
dd if=/dev/sda1 bs=512 count=1 2>/dev/null | od -x 
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"     
}

function printptbl {
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%s Partition table
---------------------------------------------------------------
" $1     
dd if=$1 bs=1 skip=446 count=64 2>/dev/null | od -x | head -4
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"     
}

function findbootmgr {
    case $3 in
        6|b|c|e) fs=vfat ;;
        7) fs=ntfs;;
    esac

    mp=`mount | grep $1 | awk '{ print $3 }'`

    if [ "x$mp" == "x" ] ; then
        mp=$mnt
        mount | grep -q "$p " && mp=/findgrub
        [ -d $mp ] || mkdir $mp
        mount -t $fs $1 $mp
        UNMOUNT=1
    else
        unset UNMOUNT
    fi

    case $2 in
        bootmgr)
            find $mp -maxdepth 1 -iname "bootmgr" | grep -q -i "bootmgr" && {
            printf " --> Windows7/Vista Loader found in %s
" $pt
            chainloadEntry $pt
        }
    ;;
        ntldr)
            find $mp -maxdepth 1 -iname "ntldr" | grep -q  -i "ntldr" && {
            printf " --> Windows NT/2K/XP Loader found in %s
" $pt
            chainloadEntry $pt
        }
    ;;
    esac


    if [ "$UNMOUNT" ] ; then
        umount $mp
    fi
    [ -d /findgrub ] && rmdir /findgrub
}


# some partition types with color

x6=FAT16                ; c6='33;1m'
x16="Hidden FAT16"      ; c16='33;1m'
xb=FAT32                ; cb='32;1m'
xc=FAT32                ; cc='32;1m'
xe=FAT32                ; ce='32;1m'
x1b="Hidden FAT32"      ; c1b='32;1m'
x1c="Hidden FAT32"      ; c1c='32;1m'
x1e="Hidden FAT32"      ; c1e='32;1m'
x5=Extended             ; c5='32;1m'
xf=Extended             ; cf='32;1m'
x7=NTFS                 ; c7='34;1m'
x17="Hidden NTFS"       ; c17='31m'
x27="Win Recovery"      ; c27='31m'
x82=swap                ; c82='33m'
x83=LINUX               ; c83='36;1m'
x8e="LINUX LVM"         ; c8e='36;1m'
xee=GPT                 ; cee='31m'
xef=EFI                 ; cef='31m'
xaf=HFS                 ; caf='35m'
xa5=FreeBSD             ; ca5='35m'
xa6=OpenBSD             ; ca6='35m'
xa7="Next Step"         ; ca7='35m'
xa8=Darwin              ; ca8='35m'
xa9=NetBSD              ; ca9='35m'
x39=Plan9               ; c39='36m'
x4d=QNX4                ; c4d='36m'
x4e=QNX4                ; c4e='36m'
x4f=QNX4                ; c4f='36m'
x63="GNU HURD"          ; c63='36m'
x81=MINIX               ; c81='36m'
xbe="Solaris boot"      ; cbe='36m'
xbf="Solaris"           ; cbf='36m'
xeb="BeOS"              ; ceb='36m'
xfb="VMware VMFS"       ; cfb='36m'
xfc="VMware VMKCORE"    ; cfc='36m'
xfd="LINUX RAID AUTO"   ; cfd='36m'

# Main - BEGIN --------------------------

devs=(`fdisk -l 2&gt;/dev/null | sed -n 's|^Disk \(/dev/[hs]d[a-z]\):.*|\1|p'`)

case "$1" in
    -w|--writemenu) WRITEMENU=1 ; shift ;;
    -d|--debug) 
        DEBUG=1
        shift 
        case "$1" in
            -n|--nocolor) COLOR=0 ;;
        esac    
    ;;
    -h|--help) help ;;
esac


# look for GRUB signature in MBR, Linux(0x83) and Extended(0x05, 0x0f) partitions 
# skip EFI (0xee), swap (0x82) and BSD (0xa5, 0xa6, 0xa9) partitions
# !!! deliberately skip Windows Recovery (0x27) partition

# look for strings 'BOOTMGR' or 'NTLDR' in all other partitions bootsector and
# if found mount the partition and search for files bootmgr or ntldr   

# in debug mode, output bootsector of NTFS and FAT  partitons in ASCII and HEX
# output partition table


# get all partitions ids
eval `fdisk -l 2&gt;/dev/null | awk '/^\/dev/ { if ($2 == "*") ID = $6 ; else ID = $5 ; print $1"="ID";" }' | sed s'|/dev/||'`


for dev in ${devs[li]} ; do[/li]    if [ -b $dev ] ; then
        printf "
 - reading MBR on disk %-27s ..." "$dev"
        dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && {
printf " --> Grub found in MBR" 
[ "$dev" == "/dev/sda" ] && makeactive=makeactive
}
        for pt in `fdisk -l $dev 2&gt;/dev/null | awk '/^\/dev/ { print $1 }'` ; do
            PT=$(basename $pt)    fs=${!PT}
            f=x${fs} ; FS=${!f} 
            if [ "$DEBUG" ] ; then
                case $fs in
                    6|b|c|e|7) printbs $pt ;;
                esac
            else
                case $fs in
                    ee|af|a5|a6|a9|82|27) 
                    printf "
 - skiping partition   %-11s %-15s" "$pt" "($FS)"
                    ;;
                    83|5|f)
                    printf "
 - reading bootsector  %-11s %-15s ..."  "$pt" "($FS)"
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && printf " --> Grub found in %s" $pt
                    ;;
                    *)
                    printf "
 - searching partition %-11s %-15s ..." "$pt" "($FS)"
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q NTLDR && findbootmgr $pt ntldr $fs
                    dd if=$pt bs=512 count=1 2> /dev/null | grep -q BOOTMGR && findbootmgr $pt bootmgr $fs
                    ;;
                esac
            fi    
        done
        [ "$DEBUG" ] && printptbl $dev
    fi
done

printf "
"

[ -d /findgrub ] && rmdir /findgrub

# Main - END ---------------------------

exit 0
# End Of Script

jdmcdaniel3 and please_try_again this script looks very useful. well done

Looking good please_try_again. Here is the findgrub version 2.02 output from my three drives:

james@LinuxUser:~> findgrub
Root User Permissions are required, Please Enter the ...

root's password:

Find Grub Version 2.02 - Written for openSUSE Forums


 - reading MBR on disk /dev/sda                    ...
 - searching partition /dev/sda1   (NTFS)          ... --> Windows7/Vista Loader found in /dev/sda1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can add the following entry to /boot/grub/menu.lst :

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on /dev/sda1
    rootnoverify (hd0,0)
    chainloader +1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 - reading MBR on disk /dev/sdb                    ...
 - skiping partition   /dev/sdb1   (swap)         
 - reading bootsector  /dev/sdb2   (LINUX)         ... --> Grub found in /dev/sdb2
 - reading bootsector  /dev/sdb3   (LINUX)         ...
 - reading MBR on disk /dev/sdc                    ...
 - searching partition /dev/sdc1   (NTFS)          ...

Now I have a question for you. Notice that you found Windows on /dev/sda1 and grub is on /dev/sdb2. Since I am running grub from a drive that is not the first drive and booting from the second, the suggested Windows startup may not work. In fact, here is what I am using:

###Don't change this comment - YaST2 identifier: Original name: windows###
title Windows 7 Home Premium
    map (hd1) (hd0)
    map (hd0) (hd1)
    rootnoverify (hd1,0)
    chainloader +1

Now the missing command that I would add is the map command, which is supposed to fool Windows into thinking it was the boot drive. When you install openSUSE and modify the device.map file such that HD0 is not the first physical hard drive, you then get the map command added for you. So, it seems to be required in such a case. You also get the makeactive command, but this is not required and I don’t like resetting this on every boot. If something goes wrong, your partition might be toast.

So, if you find Windows booting on the first drive and grub on another, the map command may be required. Just something to think about. Also, if Windows boot is not on the first drive or on the same drive as grub, then they may be swapping drives around, creating a future problem for themselves and worth a warning of some sort.

Thank You,

How are you actually booting from the second drive? Are you using the map command in your openSUSE entry as well (so sdb is actually BIOS drive 0x80 = the first one) … or do you have a BIOS which allows to change boot order without changing BIOS order? (?)

Now the missing command that I would add is the map command, which is supposed to fool Windows into thinking it was the boot drive. When you install openSUSE and modify the device.map file such that HD0 is not the first physical hard drive, you then get the map command added for you.

That’s what I was afraid of. How does your device.map look like? Actually the one openSUSE generates contains disk by-id entries, so it’s not going to tell me which is the first one.

So, it seems to be required in such a case.

It is definitely not required for Linux. It is required for DOS and DOS based (like Windows 95 to Millenium). As far as I know, it is not required for NT and followers, since you can boot them from another drive with the appopriate entry in boot.ini (or whatever replaces boot.ini on Windows7). But I really lack knowledge about Windows (specially 7).

You also get the makeactive command, but this is not required and I don’t like resetting this on every boot.

This is absolutely harmless. It would be required if you had other OS on primary partitions which need to be active too. If you boot only one partition per drive, you don’t need to reset the bootflag for sure.

If something goes wrong, your partition might be toast.

I would have eaten lots of toasts then since I rewrite partitions tables at any boot - I don’t know how many times per day - for … I won’t tell how many years. I’m still alive so far .

So, if you find Windows booting on the first drive and grub on another, the map command may be required. Just something to think about.

I see what you mean but they are to many exceptions to this rule. YaST doesn’t handle it correctly in all cases.

Also, if Windows boot is not on the first drive or on the same drive as grub, then they may be swapping drives around, creating a future problem for themselves and worth a warning of some sort.

Yes, in most cases but … yes. However it’s not a problem for Linux as long as you mount only Linux filesystems and if you don’t use device names in your /etc/fstab and in Grub menu. If you have to mount other filesystems by device names (like BSD ufs slices for example), that it becomes also a problem under Linux - it already drove me crazy. It wouldn’t be a problem for Windows either if boot.ini entries would match BIOS drives (speaking for NT-XP, don’t know about 7). Maybe the difference is that Linux users know how to edit their boot entries while Windows users don’t.

So, the number one change required in order to boot from a drive that is not the first drive in hardware order (like /dev/sdb), is the ability to select that drive as the boot drive in your BIOS. For Grub Legacy, that means the boot drive is always HD0, no matter its hardware position. Here is a copy of my device.map, with UID and then changed to the old style, so it can be understood better:

(hd1)    /dev/disk/by-id/ata-ST32000641AS_9WM0BWE8
(hd0)    /dev/disk/by-id/ata-WDC_WD6000HLHX-01JJPV0_WD-WXA1C20K0415

(hd1)    /dev/sda
(hd0)    /dev/sdb

My third drive is USB 3 and so it can’t be booted from and is not shown in the device.map. This will be true until both Intel and AMD include native support for USB 3 in their chipsets.

I went in and removed the map commands and low and behold the copy of Windows does still work, so map and makactive commands do not seem required (Just as you said). However, notice that there is still one change that must be made. Look closely to the setup that works when Grub is not on the Windows boot drive:

###Don't change this comment - YaST2 identifier: Original name: windows###
title Windows 7 Home Premium
    rootnoverify (hd1,0)
    chainloader +1

Did you notice the difference with the rootnoverify command? It is set for (hd1,0) and not (hd0,0). This must be that way to work if you are booting from a second or third hard drive (an internal or external hard drive), as selected by your BIOS, which is not the first boot drive in your system, based on its hardware order.

The ability to load and boot openSUSE from a hard drive that is not first allows one to leave the first hard drive unmodified, staying away from all sorts of possible problems with Windows. If you remove or disconnect the second drive or stop it from being the boot drive in your BIOS, your Window drive works normally. The only difference for you would be a change in the suggested menu.lst entry from rootnoverify (hd0,0) to rootnoverify (hd1,0) if grub is not on the same drive as the Windows boot partition.

This is really a minor detail for findgrub, but I suggest booting openSUSE from a second drive to anyone that will listen. If you are using a dual boot computer, and one of the OS’ is Windows, this is how I would install and run openSUSE if you have an option.

Thank You,

It that (in red above) is true - and I believe it is - than you’re not booting from your second drive but from your first drive - and it is just Linux which names this drive sdb according to your device.map (which is not only unnecessary but also confusing - although I understand what sense it makes).

If you remove that drive or disable it in your BIOS, the second drive will become the first drive, with its Generic bootcode in MBR and its 1st primary partition active, and the Windows bootloader will show up whatever device.map you might have had or not under Linux before.

I went in and removed the map commands and low and behold the copy of Windows does still work, so map and makactive commands do not seem required (Just as you said).

As long as you never use makeactive on another partition, you won’t need it. However, this is an example where something which is not needed can not hurt.

However, notice that there is still one change that must be made. Look closely to the setup that works when Grub is not on the Windows boot drive:

###Don't change this comment - YaST2 identifier: Original name: windows###
title Windows 7 Home Premium
    rootnoverify (hd1,0)
    chainloader +1

It depends. If your drive weren’t mapped, the script would find Windows in sdb and write the same (hd1,0). I don’t say you should unmap your drive though! If it works, don’t touch it!

It is set for (hd1,0) and not (hd0,0). This must be that way to work if you are booting from a second or third hard drive (an internal or external hard drive), as selected by your BIOS, which is not the first boot drive in your system, based on its hardware order.

hd0, hd1, hd2 match BIOS order 0x80, 0x81, 0x82.
sda, sdb, sdc match what Linux believe they are.

The ability to load and boot openSUSE from a hard drive that is not first allows one to leave the first hard drive unmodified, staying away from all sorts of possible problems with Windows.

Yes, but this is not what you are doing. You are booting Linux from your first drive and make it believe it is the second one, nothing else. Well, actually yes, something else : you make it also believe that the second drive (Windows) is the first one.

The only difference for you would be a change in the suggested menu.lst entry from rootnoverify (hd0,0) to rootnoverify (hd1,0) if grub is not on the same drive as the Windows boot partition.This is really a minor detail for findgrub.

Yes, but not because grub is not on the same drive as Windows. I would have to check if your drives are mapped, so … read the devices by-id entries out of your device.map, find out the linux device names (sda sdb) and convert them into grub/bios devices (hd0, hd1)… unless somebody suggests a faster way.

Until now I have been reading bootsectors (which is fine) and checking for the existence of files (which is ok … so far). If I had to read the content of files - like device.map - the script might become as reliable as the content of this file (?). And using the map command might be usefull in some cases, as for example if you had a primary Windows on each drive…

You are right about the fact that findgrub doesn’t take device mapping in account. But as they are different strategies and only exceptions to that rules, it seems difficult (for a script) to make the right suggestion.

Well, I see that you spent a lot of time looking at the situation, but no, I am not booting from the first drive please_try_again. I can remove the second drive totally and there is no grub menu to select from and Windows boots normally.

When I install openSUSE to a second or third hard drive (internal or external) I do the following:

  1. Load Generic Boot code into the MBR of /dev/sdb (New drives like external USB drives have nothing here, so this action is a must)
  2. Load Grub into openSUSE partition
  3. Set the openSUSE partition as booting
  4. I load nothing on the drive /dev/sda

Here is a fdisk -l command again, from my system:

LinuxUser:/home/james # fdisk -l

Disk /dev/sda: 2000.4 GB, 2000397852160 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4cbc9c09

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1      243202  1953512448    7  HPFS/NTFS

Disk /dev/sdb: 600.1 GB, 600127266816 bytes
255 heads, 63 sectors/track, 72961 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x46f71f1a

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         262     2104483+  82  Linux swap / Solaris
/dev/sdb2   *         263       19092   151251975   83  Linux
/dev/sdb3           19093       72962   432705294   83  Linux

Disk /dev/sdc: 1500.3 GB, 1500301910016 bytes
255 heads, 63 sectors/track, 182401 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0009698d

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1               1      182402  1465136128    7  HPFS/NTFS

Notice that Windows is the boot partition on /dev/sda1 and no grub was found in the MBR. fdisk -l can not tell what drive I boot from, just like the openSUSE install program can not guess this fact either. Even so, I am booting from /dev/sdb1 (a BIOS setting), not /dev/sda. Look back at the output from your very fine program findgrub:

james@LinuxUser:~> findgrub
Root User Permissions are required, Please Enter the ...

root's password:

Find Grub Version 2.02 - Written for openSUSE Forums


 - reading MBR on disk /dev/sda                    ...
 - searching partition /dev/sda1   (NTFS)          ... --> Windows7/Vista Loader found in /dev/sda1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can add the following entry to /boot/grub/menu.lst :

###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on /dev/sda1
    rootnoverify (hd0,0)
    chainloader +1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 - reading MBR on disk /dev/sdb                    ...
 - skiping partition   /dev/sdb1   (swap)         
 - reading bootsector  /dev/sdb2   (LINUX)         ... --> Grub found in /dev/sdb2
 - reading bootsector  /dev/sdb3   (LINUX)         ...
 - reading MBR on disk /dev/sdc                    ...
 - searching partition /dev/sdc1   (NTFS)          ...

please_try_again there are many many things I do not know or understand. Looking at your findgrub script it is obvious that you know a whole lot more about partition data and OS setup. Even so, booting from an external hard drive was the very first thing I figured out how to do back with version 10 of SuSE. I blew away my Windows setup time and time again trying to make this work, needing to restore Windows back using ghost until I finally figured it all out. As smart as you are, why do you refuse to see the true here? When you setup the install as required in openSUSE to load everything on a second or third hard drive, nothing is installed on your default or first booting hard drive. Since you are electing to boot from the second (or third or forth) hard drive, it matters not what is loaded on the first drive, though the intent (of loading openSUSE fully on a different drive) is to not mess up the original boot drive, which is most often a copy of Windows.

I do need for you to understand how this works so you will be a believer as well. Why does this even matter to me so much? I think of all of those people in the world with a work owned laptop who would not dare load openSUSE on their computer. But for a mere $50 or so, you can load openSUSE on an external hard drive, allowing full access to openSUSE and media files and the internet and web mail, without doing anything to your company official setup. A setup that often examines and records everything that you do, in or out of the office. This was my plight in the beginning and openSUSE allowed me to over come it by installing and booting openSUSE from an external USB hard drive. The same could be done for others as well, thus expanding the horizons and thousands of new openSUSE users, around the world.

Thank You,

OK. I believe you, James :wink:

Here is a fdisk -l command again, from my system:

I know how your fdisk looks like. I just don’t know if I should trust it. In the ideal case - and fortunately in most cases - sda refers to the first drive. But there are other cases where in does not, and it depends on your mainboard bios, on the drives you might mix together (like IDE and SATA), whether you map drives or not when installing grub, etc.

Even so, I am booting from /dev/sdb1 (a BIOS setting), not /dev/sda. Look back at the output from your very fine program findgrub:

So, Windows is on your first drive, right? Normally, you would chainload (hd0,0). But, because you chose to boot from your second drive, the drives got mapped when you (more precisely openSUSE setup) installed Grub the first time. Now you have to use (hd1,0) to boot Windows. Does it describe the situation?

Now you suggested the following:

Now that The only difference for you would be a change in the suggested menu.lst entry from rootnoverify (hd0,0) to rootnoverify (hd1,0) if grub is not on the same drive as the Windows boot partition.

It refers to a particular case, but you can find cases where Grub and Windows are on the same drive and drives are mapped, as well as cases where Grub and Windows are not on the same drive and drives are not mapped, and you can have Windows as well as several Grub on both drives, whether they are mapped or not.

device.map is only relevant for grub command line. You can change device.map and nothing will happen. It would provide an indication but somehow … the script would have to assume that the user didn’t change this file for any reason beyond common sense.

Grub2 has a tool called grub-mkdevicemap which would do exactly what you want. :frowning:

I blew away my Windows setup time and time again trying to make this work, needing to restore Windows back using ghost until I finally figured it all out.

For that particular problem, I finally found a solution a couple years ago: I decided not to install Windows anymore on anyone’s computer for anything in the world. It just changed my life.

As smart as you are, why do you refuse to see the true here?

I see at least two reasons:

  1. I’m not smart
  2. There is no truth

When you setup the install as required in openSUSE to load everything on a second or third hard drive, nothing is installed on your default or first booting hard drive. Since you are electing to boot from the second (or third or forth) hard drive, it matters not what is loaded on the first drive, though the intent (of loading openSUSE fully on a different drive) is to not mess up the original boot drive, which is most often a copy of Windows.

It’s a … way of boot. It’s not mine. But it makes sense. Anyway, when you know what you are doing, you can boot pretty much everything in any order and in any situation.

I do need for you to understand how this works so you will be a believer as well.

What do you want me to believe??? You won’t make me believe that I should install a generic bootcode in MBR … as I don’t have any free primary for Linux and I need Legacy Grub (and not Grub2!) to rewrite my partition tables and chainload my BSDs as well as Linux distros grubs in logical partitions. When I don’t pay attention while installing openSUSE - as I do pretty often install it - it rewrites a generic bootcode in MBR and just kills me. See, they are many exceptions to this rule.