Looking for Grub and Windows bootloader in all partitions.

(split from Two major problems with dual boot installation of openSuSE 11.1 and Windows 7)

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

I changed the default behaviour to a loop on /dev/sd* rather than /dev/sda. You can still give a specific disk as argument.

#! /bin/bash

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

[ "$1" ] && devs=(/dev/$1) 

for dev in ${devs[li]} ; do
[/li]        if [ -b $dev ] ; then
                dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in MBR on $dev"
                for pt in `fdisk -l $dev | awk '/^\/dev/ { print $1 }'` ; do
                        dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in $pt"
                        dd if=$pt bs=512 count=1 2> /dev/null | grep -q NTLDR && echo "NT/XP/VISTA Loader found in $pt"
                        dd if=$dev bs=512 count=1 2> /dev/null | grep -q BOOTMGR && echo "Windows 7 Loader found in $pt"
                done
        fi
done




That’s what I thought. But I wanted to focus on bootsectors. Maybe this code could be used as a function in a wider script to display other infos as well.

So, I have made some changes to the program. I am happy to report that it is finding my grub now, but it does not find the Windows 7 partition.

On the script file, I suggest it be placed in the ~/bin folder (~ = your home folder) and made executable there as the file findgrub:

#!/bin/bash

#: Title       : findgrub
#: Date Created: Sun Sep 26 19:40:40 CDT 2010
#: Last Edit   : Mon Sep 27 18:07:40 CDT 2010
#: Author      : please_try_again & edited by j McDaniel
#: Version     : 1.00
#: Description : Locates the Grub Boot Loader
#: Options     : name of drive, ex: sda

#
# 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 "Find Grub Version 1.0 : Syntax: findgrub [sdx] : x = a,b or c etc."
echo

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

[ "$1" ] && devs=(/dev/$1) 

for dev in ${devs
[li]} ; do[/li]        if [ -b $dev ] ; then
                dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in MBR on $dev"
                for pt in `fdisk -l $dev | awk '/^\/dev/ { print $1 }'` ; do
                        dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in partition $pt"
                        dd if=$pt bs=512 count=1 2> /dev/null | grep -q NTLDR && echo "NT/XP/VISTA Loader found in $pt"
                        dd if=$dev bs=512 count=1 2> /dev/null | grep -q BOOTMGR && echo "Windows 7 Loader found in $pt"
                done
        fi
done

echo
echo "findgrub search is complete..."
echo

exit 0
# End Of Script

To make the file executable the following terminal command:

chmod +x ~/bin/findgrub

To use findgrub, open up a terminal session and type the terminal command of findgrub. The root user password will be requested and the the applications will be run. When I run the program with no parameters it says:

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

root's password:

Find Grub Version 1.0 : Syntax: findgrub [sdx] : x = a,b or c etc.

Grub found in partition /dev/sdb2

findgrub search is complete...


This is correct for my openSUSE drive. Here are two manual commands on my Windows 7 drive, which is not found.

[b]dd if=/dev/sda bs=512 count=1[/b]
3�м|��ؾ|�����Ph������~|
                       ������▒�VU�F�F�A��U�]r��U�u      ��t�Ff`�~t&fhf�hh|hh�B�V����������|�V�v�N�n�fas�Nu
                                                                                                          �~�������U2��V�]랁&gt;�}U�un�v��u����d�����`�|���d�u����▒f#�u;f��TCPAu2��r,fh�fhffSfSfUfhfh|fah�▒Z2��|�▒�������2����<t ��������+��d�$��$�Invalid partition tableError loading operating systemMissing operating systemc{�    ��L� !��x��U�1+0 records in
1+0 records out
512 bytes (512 B) copied, 1.78e-05 s, 28.8 MB/s

[b]dd if=/dev/sda bs=512 count=1[/b]
3�м|��ؾ|�����Ph������~|
                       ������▒�VU�F�F�A��U�]r��U�u      ��t�Ff`�~t&fhf�hh|hh�B�V����������|�V�v�N�n�fas�Nu
                                                                                                          �~�������U2��V�]랁&gt;�}U�un�v��u����d�����`�|���d�u����▒f#�u;f��TCPAu2��r,fh�fhffSfSfUfhfh|fah�▒Z2��|�▒�������2����<t ��������+��d�$��$�Invalid partition tableError loading operating systemMissing operating systemc{�    ��L� !��x��U�1+0 records in
1+0 records out
512 bytes (512 B) copied, 2.0506e-05 s, 25.0 MB/s

Hope this information is helpful. I put in enough instructions so all users could follow along if they wish to do so.
Thank You,

You did read and post twice the MBR of sda. The most interesting ouput would be the bs in /dev/sda1 (if it is your Windows 7 partition), so:

dd if=/dev/sda1 bs=512 count=1

This should show which string Windows 7 uses in its bootcode (last time I checked it was BOOTMGR).

I can only say please_try_again, thanks for hanging in there with me. It is the details that kill you and me. lol!

sudo dd if=/dev/sda1 bs=512 count=1
�R�NTFS   �?���w��
                  ����^��^��3�м|�h�hfˈf�>NTFSu�A��U�r
                                                     ��U�u��u����▒h▒�H�������▒�Xr�;
                                                                                   u�.Z3۹ +�f�����K+�w����▒f#�u-f��TCPAu$��rh�hph       fSfSfUh�fa�▒3�(������_��f`f�ffhfPShh�B����fYZfYfY�f����u�faà��       ����������&lt;t    ������
A disk read error occurred
BOOTMGR is missing
BOOTMGR is compressed
Press Ctrl+Alt+Del to restart
����U�1+0 records in
1+0 records out
512 bytes (512 B) copied, 2.0948e-05 s, 24.4 MB/s


It is kind of funny that it says the BOOTMGR is missing & the BOOTMGR is compressed at the same time.

Thank You,

Whether BOOTMGR is missing or compressed, this is the string the script was looking for in this bootsector. So I don’t quite understand why it didn’t also display:
Windows 7 Loader found in /dev/sda1
:\

So, I surely don’t know what is wrong, but I notice that $dev=/dev/sda (where you are looking) while $pt=/dev/sda1 (which you say it was found). count 1 2, does this read in one or two sectors?

dd if=$dev bs=512 count=1 2> /dev/null | grep -q BOOTMGR && echo "Windows 7 Loader found in $pt"

So, for some reason, it just does not like my Windows drive, even as it seems some output should come out. Humm…

Thank You,

It reads 1 sector. Reading 2 sectors would be ‘count=2’.
2 > /dev/null redirects standard error to nowhere, meaning we’re not interesting at reading dd extra output.
You can see the difference if you compare the output of :
dd if=/dev/sda1 bs=512 count=1
with the one of
dd if=/dev/sda1 bs=512 count=1 2> /dev/null
In the later case, it doesn’t display a similar message at the end:

1+0 records out
512 bytes (512 B) copied, 6.3077e-05 s, 8.1 MB/s

You can append ‘2> /dev/null’ to any command if you’re not interesting in warnings or error messages.

OOOPs ! Yes. It should be $pt ! I slept. :shame:
But now you’re going to find more than one partition. :frowning:

So I made that change (as well as another) and indeed now, I see two partitions as having the Windows boot loader. The first is correct, while the second is not. It is just an NTFS partition on a USB 3 hard drive.

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

root's password:

Find Grub Version 1.0 : Syntax: findgrub [sdx] : x = a,b or c etc.

Searching Partition /dev/sda1
Windows 7 Loader found in /dev/sda1
Searching Partition /dev/sdb1
Searching Partition /dev/sdb2
Grub found in partition /dev/sdb2
Searching Partition /dev/sdb3
Searching Partition /dev/sdc1
Windows 7 Loader found in /dev/sdc1

findgrub search is complete...

So what is our next step?

Thank You,

Hi James, Thank you for finding my bugs !

Well, I didn’t want to read (mount) the filesystems, but I don’t seem to have the choice. It might not work if the filesystem is busy.
Now it makes the script definitely longer. I have no idea how/if it works if the Windows partitions are already mounted (actually I do have an idea, since I had to unmount them). But let’s hope that people looking for their Windows boot partition don’t have it mounted already.lol!

I removed the device arguments but added an option “–writemenu” to append the (hopefully) correct Windows boot entry to /boot/grub/menu.lst.

In the ideal case, you’ll just have to run the script and if you are happy with the ouput (in green if you did copy/paste the escape sequences), run it again with the option --writemenu … then reboot Windows (I said “in the ideal case!”).

I used (to use) makeactive to boot Windows … but to be honnest I don’t boot Windows. I completely disagree with openSUSE boot strategy (like Grub in the extended partition and activate the root partition, whether it is a primary or not). But anymay, if you think “makeactive” is bothering - you might know better than I do - feel free to remove or comment out that line in the script.


#! /bin/bash

# if execute with option --writemenu, add boot entries to /boot/grub/menu.lst

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
	echo "append boot entry to chainload Windows bootmanager on $1 to /boot/grub/menu.lst"
	cp /boot/grub/menu.lst{,.findgrub}
	cat >> /boot/grub/menu.lst << EOFWriteGrubEntry

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

EOFWriteGrubEntry
else
	echo You can add the following entry to /boot/grub/menu.lst:
	cat << EOFDisplayGrubEntry
e[32;1m
###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    makeactive
    chainloader +1
e[37;0m
EOFDisplayGrubEntry
fi
}

function findbootmgr {
	fs=`sfdisk -c ${pt%%[0-9]*} ${pt/#*d[a-z]} 2&gt;/dev/null`
	case $fs in
	27) 
		echo "Windows 7 recovery partition found in $pt"
		return
		;;
	6|b|c|e) fs=vfat ;;
	7) fs=ntfs;;
	esac
	[ -d /findgrub ] || mkdir /findgrub
	mount -t $fs $pt /findgrub
	case $2 in
		bootmgr)
			find /findgrub -maxdepth 1 -iname "bootmgr" | grep -q -i "bootmgr" && {
			echo "Windows7/Vista Loader found in $pt"
			chainloadEntry $pt
		}
	;;
		ntldr)
			find /findgrub -maxdepth 1 -iname "ntldr" | grep -q  -i "ntldr" && {
			echo "Windows NT/2K/XP Loader found in $pt"
			chainloadEntry $pt
		}
 	;;
	esac
	umount /findgrub
}


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

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

# add boot entry to /boot/grub/menu.lst
if [ "$1" == "--writemenu" ] ; then
	WRITEMENU=1
	shift		
fi


#[ "$1" ] && devs=(/dev/$1) 

for dev in ${devs[li]} ; do
[/li]	if [ -b $dev ] ; then
		dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in MBR on $dev"
		for pt in `fdisk -l $dev | awk '/^\/dev/ { print $1 }'` ; do
			dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && echo "Grub found in $pt"
			dd if=$pt bs=512 count=1 2> /dev/null | grep -q NTLDR && findbootmgr $pt ntldr
			dd if=$pt bs=512 count=1 2> /dev/null | grep -q BOOTMGR && findbootmgr $pt bootmgr
		done
	fi
done

[ -d /findgrub ] && rmdir /findgrub

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

I know, it’s kinda “write only” shell scripting style …

OK, I have two NTFS partitions, so I UMOUNTed them and then ran findgrub2. Here is the output. /dev/sda1 is my Windows 7 boot drive.

LinuxUser:/home/james # findgrub2
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)                                                                                                                      
    makeactive                                                                                                                                
    chainloader +1                                                                                                                            
                                                                                                                                              
Grub found in /dev/sdb2

So, it works, without a doubt for Windows 7. I wish you did not have to force NTFS partitions offline manually, but if the setup is all FuBar, it is doubtful they will be mounted. It is just a small snag as you have once again, did an outstanding job.

Since this script is VERY useful, I would suggest you add more comments. I would also suggest you recommend it be saved in the ~/bin folder, so that you do not need to use the ./findgrub command. Now it can be argued that anyone that can do these things are just playing with your script, but we do want it to be easy to use. If you can write something good, I know you can come up with the rest. I also offer my services if you wish, to do anything that you like. Of course, you don’t look like you really need my help.

Again, good job please_try_again!!!

Thank You,

I think it is fixed in the new version I will post.

Sounds great! I was actually hoping you would make the script “human readable” somehow. Feel free to edit the help function. You can just write plain text (no ‘echo’!) between
cat << EOFHELP


and
EOFHELP

It will be displayed when user type : findgrub --help

I wouldn’t say that. It’s really time consuming to write documentation and comments. And when you consider my english, I’m not sure it is worth the effort.
You can add headers and comments, write howtos, take screenshots, everything what could be helpful, but be careful with the code. After all we’re playing with bootsectors, even if we’re just reading them.

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’).

#! /bin/bash

# set COLOR to 0 to copy/paste or redirect debug output to a file 
COLOR=1  

# default mointpoint
mnt=/mnt

function help {
	cat << EOFHELP

findgrub - description and help
options:
[37;1m-h --help[37;0m      : show this help 
[37;1m-w --writemenu[37;0m : add boot entries to /boot/grub/men.lst 
[37;1m-d --debug [-n --nocolor] [37;0m  : 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 [31;1m%s[37;0m to [37;1m/boot/grub/menu.lst[37;0m
" $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 [37;1m/boot/grub/menu.lst[37;0m :
"
	cat << EOFDisplayGrubEntry | sed '/^[	 ]*$/d'
[32;1m
###Don't change this comment - YaST2 identifier: Original name: WindowsBootLoader###
title Windows on $1
    rootnoverify $(Linux2LegacyGrub ${1#/dev/*})
    $makeactive
    chainloader +1
[37;0m
EOFDisplayGrubEntry
	printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
fi
}

function printbs {
if [ $COLOR -eq 1 ] ; then	
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[37;1m%s [37;0mBootsector
---------------------------------------------------------------------------
 [36;1m" $1	 
dd if=$1 bs=512 count=1 2>/dev/null | tr -cd "[:alnum:] [:space:]"
printf " [37;0m
----------------------------------------------------------------------------
"
dd if=/dev/sda1 bs=512 count=1 2>/dev/null | od -x | awk '{  if ( NF == 9 ) { printf "[35m%s|[33;1m %s %s %s %s %s %s %s", $1, $2, $3, $4, $5, $6, $7, $8 ; if ( $9 == "aa55" ) printf " [31;1m%s[35;0m
", $9 ; else printf " %s[35;0m
", $9 }}'
printf " [37;0m
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"	 
else
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 " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"	 
fi
}

function printptbl {
if [ $COLOR -eq 1 ] ; then	
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[37;1m%s[37;0m Partition table
---------------------------------------------------------------
" $1	 
dd if=$1 bs=1 skip=446 count=64 2>/dev/null | od -x | head -4 | awk '{HD=substr($2,1,2) ; BF=substr($2,3,2); FE=substr($4,1,2) ; ID=substr($4,3,2); if ( BF == "80" ) BF="[31;1m"BF ; printf "[35m%s|[32;1m %s%s [32;1m%s %s[37;1m%s [32;1m%s %s %s %s %s[35;0m
", $1, HD, BF, $3, FE, ID, $5, $6, $7, $8 , $9}'
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"	 
else
printf "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%s Partition table
---------------------------------------------------------------
" $1	 
dd if=$1 bs=1 skip=446 count=64 2>/dev/null | od -x | head -4
printf " 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"	 
fi
}

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 " --> [37;1mWindows7/Vista Loader found in [31;1m%s[37;0m
" $pt
			chainloadEntry $pt
		}
	;;
		ntldr)
			find $mp -maxdepth 1 -iname "ntldr" | grep -q  -i "ntldr" && {
			printf " --> [37;1mWindows NT/2K/XP Loader found in [31;1m%s[37;0m
" $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 "
[31;1m - reading MBR on disk %-27s [37;0m..." "$dev"
		dd if=$dev bs=512 count=1 2> /dev/null | grep -q GRUB && {
printf " --> [37;1mGrub found in [31;1mMBR[37;0m" 
[ "$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} ; c=c${fs} ; CL=${!c}
			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   [%s%-11s %-15s[37;0m" $CL "$pt" "($FS)"
					;;
					83|5|f)
					printf "
 - reading bootsector  [%s%-11s %-15s [37;0m..." $CL "$pt" "($FS)"
					dd if=$pt bs=512 count=1 2> /dev/null | grep -q GRUB && printf " --> [37;1mGrub found in [31;1m%s[37;0m" $pt
					;;
					*)
					printf "
 - searching partition [%s%-11s %-15s [37;0m..." $CL "$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 ---------------------------

I hope this script is not going to get longer or people will be afraid of using it.

So far, I tested it on an Aspire revo with Windows 7 preinstalled (3 partitions), on an iMac ( redirecting all the GPT related warnings) and on one of my computers full of Linux and Unix partitions. It seems to work but … I’m sure there are bugs.

I add a ‘makeactive’ to the Windows partition only if Grub is found in MBR. (so it won’t infringe openSUSE policies)

usage :


[ul]
[li]findgrub[/li][li]findgrub -h | --help[/li][li]findgrub -w | – writemenu[/li][li]findgrub -d | --debug [ -n | --nocolor ][/li][/ul]

the option --debug is used to display bootsectors (like in that example
Help: I borked my WindowsXP boot when installing OpenSUSE 11.3
), so we can tell if they are garbaged (or encrypted like in the example) and not bootable with Grub.

Use --debug --nocolor ( or -d -n ) if you want to post the output (otherwise it will be full of escape sequences).

What else ? … I don’t know. Just enjoy.

please_try_again, the latest version is again not producing any displayed output. I am almost certain it has to do with the color display, though I can’t seem to disable it. You seem to be using the escape sequence mode and not tput which did work for me in other scripts. You seem to be saving several steps somehow on displaying color which escapes even me. What is the chance we could take that feature out? Can you get feedback from anyone else that says the colors are working for them? I tried it in every terminal program I have. By the way, our code display can corrupt any non displaying character. Further, copying and pasting between code blocks here create problems as it must first go back to a text editor before being placed back into a code block in another message.

Thank You,

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)

I dont’ know. (?)

What is the chance we could take that feature out?

Tha’ts not difficult. But does --debug --nocolor output something for you? It should if it’s a terminal issue.

I asked But how come that escape sequences do not work in your terminals? Or what did it I tweak on my systems (?). I must have done something since I used the same colored scripts in several different terminals (Linux and Unix). But for now I only tried in aterm and … the one I have running in my background - must be rxvt-unicode, I guess. I rarely type something in KDE konsole … I guess I should.

Yes, that’s why I added the --nocolor option (but only for debbuging).

OK. First I’ll put a version without any escape sequences. That would be the easiest way to check if the script is working otherwise. I’ll see later what to do with colors.

I have tried it in Konsole and Yakuake and it does not work. While they both are the same, not working in Konsole is a problem in my mind. You may need a pure terminal emulator for it to work, but I am not sure. Lets go colorless for now as I can see the script has got lots of power within. I also understand the disappointment of one not showing off your color selections. It is kind of weird, but you feel more creative with color even as it has little real meaning. Go figure?

Thank You,

Here’s a ‘black and white’ version (if you have output issues because of the escape sequences).

#! /bin/bash

# default mountpoint
mnt=/mnt

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 [-n --nocolor]   : 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 ---------------------------

Here is the output now. I have pasted it into my original shell I had created.

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

root's password:

Find Grub Version 2.00 - 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)          ...

So it works like a charm. We can call it a wrap if you wish. I would be happy to add color using tput if you can convert my text above into your intended colors. This is your script, and it is a very good one. What would you have me do at this time?

Thank You,

Great! And if you had Grub in MBR, you would have seen that :


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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)
    **makeactive**
    chainloader +1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

The red color above doesn’t use escape sequences lol!

I wish you would see how the colored version is supposed to look like, especially findgrub --debug , as it also displays the bootsector and the partition table in hex and highlights the bootflag and the partitions IDs. In this case, it becomes more human readable with colors. Maybe you could try it in aterm ? It’s a very simple terminal (kind of deprecated since it doesn’t support unicode). You might have to tell it to use a black background - as I do not trust KDE with Xresources, so:

aterm -bg black -fg white

But if I look in the colored case of the printptbl function, it seems more complicated to produce such an output with tput, since the escape sequences are just strings like any others from the awk point of vue. Sure it’s possible but you have to mix tput and awk commands several times to print aligned hex values (have to be good with awk)… or use only tput (have to be even better with tput).

Well, if you could write a help section, which looks like a man page (NAME, SYNOPSIS, DESCRIPTION, etc) , explain in a post what the script does and how to use it … and encourage people to use it and give feedback, that would be great! It might still not work in any case (?), if Windows uses another string in its BS (like ‘MSDOS’) or another file for its loader (I vaguely recall ‘arcldr’ or something similar).

Thanks a lot for your help. I appreciate it.