· 6 years ago · Jan 14, 2020, 10:18 PM
1#!/bin/bash
2VERSION='0.61';
3RELEASE_DATE='1 April 2012';
4LAST_GIT_COMMIT='';
5RETRIEVAL_DATE='';
6################################################################################
7# #
8# Copyright (c) 2009-2010 Ulrich Meierfrankenfeld #
9# Copyright (c) 2011-2012 Gert Hulselmans #
10# #
11# Permission is hereby granted, free of charge, to any person obtaining a copy #
12# of this software and associated documentation files (the "Software"), to #
13# deal in the Software without restriction, including without limitation the #
14# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or #
15# sell copies of the Software, and to permit persons to whom the Software is #
16# furnished to do so, subject to the following conditions: #
17# #
18# The above copyright notice and this permission notice shall be included in #
19# all copies or substantial portions of the Software. #
20# #
21# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
22# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
23# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
24# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
25# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
26# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS #
27# IN THE SOFTWARE. #
28# #
29################################################################################
30# #
31# Current developer: Gert Hulselmans #
32# #
33# Past developer: Ulrich Meierfrankenfeld (meierfra) (ubuntuforums.org) #
34# Past contributor: caljohnsmith (ubuntuforums.org) #
35# #
36# Hosted at: http://sourceforge.net/projects/bootinfoscript/ #
37# #
38# The birth of Boot Info Script: #
39# http://ubuntuforums.org/showthread.php?t=837791 #
40# #
41# Tab width: 8 spaces #
42# #
43################################################################################
44
45
46
47## Check if the script is run with bash as shell interpreter.
48
49if [ -z "$BASH_VERSION" ] ; then
50 echo 'Boot Info Script needs to be run with bash as shell interpreter.' >&2;
51 exit 1;
52fi
53
54
55
56## Display help text ##
57#
58# ./bootinfoscript -h
59# ./bootinfoscript -help
60# ./bootinfoscript --help
61
62help () {
63 cat <<- HELP
64
65 Usage Boot Info Script:
66 -----------------------
67
68 Run the script as sudoer:
69
70 sudo ${0} <outputfile>
71
72 or if your operating system does not use sudo:
73
74 su -
75 ${0} <outputfile>
76
77
78 When running the script, without specifying an output file, all the output
79 is written to the file "RESULTS.txt" in the same folder as the script.
80
81 But when run from /bin, /sbin, /usr/bin, or another system folder, the file
82 "RESULTS.txt" is written to the home directory of the user.
83
84 When the file "RESULTS.txt" already exists, the results will be written to
85 "RESULTS1.txt". If "RESULTS1.txt" exists, the results will be written to
86 "RESULTS2.txt", ...
87
88
89 To get version number, release date, last git commit and git retrieval date
90 of this script, use (no root rights needed):
91
92 ${0} -v
93 ${0} -V
94 ${0} --version
95
96
97 To get this help text, use (no root rights needed):
98
99 ${0} -h
100 ${0} -help
101 ${0} --help
102
103
104 To automatically gzip a copy of the output file, use (root rights needed):
105
106 ${0} -g <outputfile>
107 ${0} --gzip <outputfile>
108
109
110 To write the output to stdout instead of a file, use (root rights needed):
111
112 ${0} --stdout
113
114
115 The last development version of Boot Info Script can be downloaded, with:
116 (no root rights needed)
117
118 ${0} --update <filename>
119
120 If no filename is specified, the file will be saved in the home dir as
121 "bootinfoscript_YYYY-MM-DD_hh:mm:ss".
122
123
124 If multiple versions of Boot Info Script are detected in the same directory,
125 Boot Info Script will list all versions found.
126 In that case you need to force Boot Info Script to run a certain version,
127 by adding "--this" as first argument (root rights needed):
128
129 ${0} --this <outputfile>
130
131 HELP
132
133 exit 0;
134}
135
136
137
138## Download the last development version of BIS from git: ##
139#
140# ./bootinfoscript --update <filename>
141#
142# If no filename is specified, the file will be saved in the home dir as
143# "bootinfoscript_YYYY-MM-DD_hh:mm:ss".
144
145update () {
146 local git_bis_url='http://bootinfoscript.git.sourceforge.net/git/gitweb.cgi?p=bootinfoscript/bootinfoscript;a=blob_plain;f=bootinfoscript;hb=HEAD';
147 local git_commit_url='http://bootinfoscript.sourceforge.net/bis-last-commit.txt'
148
149 # Check if date is available.
150 if [ $(type date > /dev/null 2>&1 ; echo $?) -ne 0 ] ; then
151 echo '"date" could not be found.' >&2;
152 exit 1;
153 fi
154
155 # Get current UTC time in YYYY-MM-DD-hh:mm:ss format.
156 UTC_TIME=$(date --utc "+%Y-%m-%d %T");
157
158 if [ ! -z "$1" ] ; then
159 GIT_BIS_FILENAME="$1";
160 else
161 GIT_BIS_FILENAME="${HOME}/bootinfoscript_${UTC_TIME/ /_}"
162 fi
163
164 # Check if wget or curl is available
165 if [ $(type wget > /dev/null 2>&1 ; echo $?) -eq 0 ] ; then
166 printf '\nDownloading last development version of Boot Info Script from git:\n\n';
167 wget -O "${GIT_BIS_FILENAME}" "${git_bis_url}";
168 LAST_GIT_COMMIT=$(wget -O - "${git_commit_url}" 2> /dev/null);
169 elif [ $(type curl > /dev/null 2>&1 ; echo $?) -eq 0 ] ; then
170 printf 'Downloading last development version of Boot Info Script from git:\n\n';
171 curl -o "${GIT_BIS_FILENAME}" "${git_bis_url}";
172 LAST_GIT_COMMIT=$(curl "${git_commit_url}");
173 else
174 printf '"wget" or "curl" could not be found.\nInstall at least one of them and try again.\n' >&2;
175 exit 1;
176 fi
177
178 # Set the retrieval date in just downloaded script.
179 sed -i -e "4,0 s@LAST_GIT_COMMIT='';@LAST_GIT_COMMIT='${LAST_GIT_COMMIT}';@" \
180 -e "5,0 s/RETRIEVAL_DATE='';/RETRIEVAL_DATE='${UTC_TIME}';/" \
181 "${GIT_BIS_FILENAME}";
182
183 printf '\nThe development version of Boot Info Script is saved as:\n"%s"\n\n' "${GIT_BIS_FILENAME}";
184 exit 0;
185}
186
187
188
189## Display version, release, last git commit and git retrieval date of the script when asked: ##
190#
191# ./bootinfoscript -v
192# ./bootinfoscript -V
193# ./bootinfoscript --version
194
195version () {
196 printf '\nBoot Info Script version: %s\nRelease date: %s' "${VERSION}" "${RELEASE_DATE}";
197
198 if [ ! -z "${LAST_GIT_COMMIT}" ] ; then
199 printf '\nLast git commit: %s\nRetrieved from git on: %s' "${LAST_GIT_COMMIT}" "${RETRIEVAL_DATE}";
200 fi
201
202 printf '\n\n';
203
204 exit 0;
205}
206
207
208
209## Run this version of BIS even when multiple versions are detected in the same directory?
210this_BIS=0; # no=0
211
212## Gzip a copy of the output file? ##
213gzip_output=0; # off=0
214
215## Write the output to the standard output instead of to a file? ##
216stdout_output=0; # off=0
217
218
219
220## Get arguments passed to the script. ##
221
222process_args () {
223 if [ ${#@} -ge 1 ] ; then
224 if [ $1 = '--this' ] ; then
225 this_BIS=1; # run this version of BIS even if multiple versions are detected.
226
227 if [ ${#@} -ge 2 ] ; then
228 shift; # shift the command line parameters ($2 -> $1), so they can be processed.
229 else
230 return 0; # exit this function when only '--this' was passed.
231 fi
232 fi
233
234 # Process other arguments.
235 case "$1" in
236 -g ) gzip_output=1; if [ ! -z "$2" ] ; then LogFile_cmd="$2"; fi;;
237 --gzip ) gzip_output=1; if [ ! -z "$2" ] ; then LogFile_cmd="$2"; fi;;
238 -h ) help;;
239 -help ) help;;
240 --help ) help;;
241 --stdout ) stdout_output=1;;
242 --update ) update "$2";;
243 -v ) version;;
244 -V ) version;;
245 --version ) version;;
246 -* ) help;;
247 * ) LogFile_cmd="$1";;
248 esac
249 fi
250}
251
252
253
254
255## Get arguments passed to the script. ##
256
257process_args ${@};
258
259
260
261## Display version number, release and git retrieval date. ##
262
263printf '\nBoot Info Script %s [%s]' "${VERSION}" "${RELEASE_DATE}";
264
265if [ ! -z "${LAST_GIT_COMMIT}" ] ; then
266 printf '\n Last git commit: %s\n Retrieved from git on: %s' "${LAST_GIT_COMMIT}" "${RETRIEVAL_DATE}";
267fi
268
269printf '\n\n';
270
271
272
273## Check whether Boot Info Script is run with root rights or not. ##
274
275if [ $(type whoami > /dev/null 2>&1 ; echo $?) -ne 0 ] ; then
276 echo 'Please install "whoami" and run Boot Info Script again.' >&2;
277 exit 1;
278elif [ $(whoami) != 'root' ] ; then
279 cat <<- EOF >&2
280 Please use "sudo" or become "root" to run this script.
281
282 Run the script as sudoer:
283
284 sudo ${0} <outputfile>
285
286 or if your operating system does not use sudo:
287
288 su -
289 ${0} <outputfile>
290
291 For more info, see the help:
292
293 ${0} --help
294
295 EOF
296 exit 1;
297fi
298
299
300
301## Check if all necessary programs are available. ##
302
303# Programs that are in /bin or /usr/bin.
304Programs='
305 basename
306 cat
307 chown
308 dd
309 dirname
310 expr
311 fold
312 grep
313 gzip
314 hexdump
315 ls
316 mkdir
317 mktemp
318 mount
319 printf
320 pwd
321 rm
322 sed
323 sort
324 umount
325 wc'
326
327# Programs that are in /usr/sbin or /sbin.
328Programs_SBIN='
329 blkid
330 fdisk
331 filefrag
332 losetup'
333
334
335Check_Prog=1;
336
337for Program in ${Programs} ${Programs_SBIN}; do
338 if [ $(type ${Program} > /dev/null 2>&1 ; echo $?) -ne 0 ] ; then
339 echo "\"${Program}\" could not be found." >&2;
340 Check_Prog=0;
341 fi
342done
343
344
345
346## Can we decompress a LZMA stream? ##
347#
348# The Grub2 (v1.99) core_dir string is contained in a LZMA stream.
349# See if we have xz or lzma installed to decompress the stream.
350#
351
352if [ $(type xz > /dev/null 2>&1 ; echo $?) -eq 0 ] ; then
353 UNLZMA='xz --format=lzma --decompress';
354elif [ $(type lzma > /dev/null 2>&1 ; echo $?) -eq 0 ] ; then
355 UNLZMA='lzma -cd';
356else
357 UNLZMA='none';
358fi
359
360
361
362## Do we have gawk? ##
363#
364# If we don't have gawk, look for "busybox awk".
365#
366
367# Make a variable named ${TAB}, needed for setting the separator for awk to a tab.
368TAB=$(printf "\t");
369
370# Set awk binary to gawk.
371AWK='gawk';
372
373
374if [ $(type gawk > /dev/null 2>&1 ; echo $?) -ne 0 ] ; then
375 # Do we have a busybox version?
376 for BUSYBOX in 'busybox' '/usr/lib/initramfs-tools/bin/busybox' ; do
377 # And if we have one, does is support "awk"?
378 if [ $(type ${BUSYBOX} > /dev/null 2>&1 ; echo $?) -eq 0 ] && [ $(echo 'test' | ${BUSYBOX} awk '{ print $0 }' > /dev/null 2>&1; echo $?) -eq 0 ] ; then
379 printf '\n"gawk" could not be found, using "%s awk" instead.\nThis may lead to unreliable results.\n\n' "${BUSYBOX}" >&2;
380
381 # Set awk binary to busybox's awk.
382 AWK="${BUSYBOX} awk";
383 break;
384 fi
385 done
386
387 # If no busybox (or one without awk support) is found, "${AWK}" is still set to "gawk".
388 if [ "${AWK}" == 'gawk' ] ; then
389 echo '"gawk" could not be found.' >&2;
390 Check_Prog=0;
391 fi
392fi
393
394
395
396if [ ${Check_Prog} -eq 0 ] ; then
397 printf '\nPlease install the missing program(s) and run Boot Info Script again.\n' >&2;
398 exit 1;
399fi
400
401
402
403## Check if there are other bootinfoscript files in the same directory. ##
404#
405# This can be useful when BIS was downloaded multiple times with Firefox, Chromium, ...
406# Those browsers will add a suffix to the filename, when there was already
407# a file with the same name:
408#
409# bootinfoscript(<number>)
410#
411# To force BIS to run a certain version, add "--this" as first argument:
412#
413# ./bootinfoscript --this <outputfile>
414#
415
416if [ ${this_BIS} -eq 0 ] ; then
417 declare -a BIS_files;
418
419 BIS_files=( $(ls "$(dirname "$0")/bootinfoscript" "$(dirname \"$0\")"/bootinfoscript\(*\) 2> /dev/null) );
420
421 if [ "${#BIS_files[*]}" -ge 2 ] ; then
422 printf 'Multiple bootinfoscript files where found:\n\n';
423
424 for i in ${!BIS_files[@]} ; do
425 eval $(echo 'BIS_'$(grep -m1 '^VERSION' "${BIS_files[$i]}") );
426 printf " - ${BIS_files[$i]}:\tversion ${BIS_VERSION}\n";
427 done
428
429 printf '\nAre you sure you want to run this version? If so, run:\n\n %s --this %s\n\n' "$0" "$*";
430 exit 1;
431 fi
432fi
433
434
435
436## List of folders which might contain files used for chainloading. ##
437
438Boot_Codes_Dir='
439 /
440 /NST/
441 '
442
443
444
445## List of files whose names will be displayed, if found. ##
446
447Boot_Prog_Normal='
448 /bootmgr /BOOTMGR
449 /boot/bcd /BOOT/bcd /Boot/bcd /boot/BCD /BOOT/BCD /Boot/BCD
450 /Windows/System32/winload.exe /WINDOWS/system32/winload.exe /WINDOWS/SYSTEM32/winload.exe /windows/system32/winload.exe
451 /Windows/System32/Winload.exe /WINDOWS/system32/Winload.exe /WINDOWS/SYSTEM32/Winload.exe /windows/system32/Winload.exe
452 /grldr /GRLDR /grldr.mbr /GRLDR.MBR
453 /ntldr /NTLDR
454 /NTDETECT.COM /ntdetect.com
455 /NTBOOTDD.SYS /ntbootdd.sys
456 /wubildr /ubuntu/winboot/wubildr
457 /wubildr.mbr /ubuntu/winboot/wubildr.mbr
458 /ubuntu/disks/root.disk
459 /ubuntu/disks/home.disk
460 /ubuntu/disks/swap.disk
461 /core.img /grub/core.img /boot/grub/core.img /grub2/core.img /boot/grub2/core.img
462 /burg/core.img /boot/burg/core.img
463 /ldlinux.sys /syslinux/ldlinux.sys /boot/syslinux/ldlinux.sys
464 /extlinux.sys /extlinux/extlinux.sys /boot/extlinux/extlinux.sys
465 /boot/map /map
466 /DEFAULT.MNU /default.mnu
467 /IO.SYS /io.sys
468 /MSDOS.SYS /msdos.sys
469 /KERNEL.SYS /kernel.sys
470 /DELLBIO.BIN /dellbio.bin /DELLRMK.BIN /dellrmk.bin
471 /COMMAND.COM /command.com
472 '
473
474Boot_Prog_Fat='
475 /bootmgr
476 /boot/bcd
477 /Windows/System32/winload.exe
478 /grldr
479 /grldr.mbr
480 /ntldr
481 /freeldr.sys
482 /NTDETECT.COM
483 /NTBOOTDD.SYS
484 /wubildr
485 /wubildr.mbr
486 /ubuntu/winboot/wubildr
487 /ubuntu/winboot/wubildr.mbr
488 /ubuntu/disks/root.disk
489 /ubuntu/disks/home.disk
490 /ubuntu/disks/swap.disk
491 /core.img /grub/core.img /boot/grub/core.img /grub2/core.img /boot/grub2/core.img
492 /burg/core.img /boot/burg/core.img
493 /ldlinux.sys /syslinux/ldlinux.sys /boot/syslinux/ldlinux.sys
494 /extlinux.sys /extlinux/extlinux.sys /boot/extlinux/extlinux.sys
495 /boot/map /map
496 /DEFAULT.MNU
497 /IO.SYS
498 /MSDOS.SYS
499 /KERNEL.SYS
500 /DELLBIO.BIN /DELLRMK.BIN
501 /COMMAND.COM
502 '
503
504
505
506## List of files whose contents will be displayed. ##
507
508Boot_Files_Normal='
509 /menu.lst /grub/menu.lst /boot/grub/menu.lst /NST/menu.lst
510 /grub.cfg /grub/grub.cfg /boot/grub/grub.cfg /grub2/grub.cfg /boot/grub2/grub.cfg
511 /burg.cfg /burg/burg.cfg /boot/burg/burg.cfg
512 /grub.conf /grub/grub.conf /boot/grub/grub.conf /grub2/grub.conf /boot/grub2/grub.conf
513 /ubuntu/disks/boot/grub/menu.lst /ubuntu/disks/install/boot/grub/menu.lst /ubuntu/winboot/menu.lst
514 /boot.ini /BOOT.INI
515 /etc/fstab
516 /etc/lilo.conf /lilo.conf
517 /syslinux.cfg /syslinux/syslinux.cfg /boot/syslinux/syslinux.cfg
518 /extlinux.conf /extlinux/extlinux.conf /boot/extlinux/extlinux.conf
519 /grldr /grub.exe
520 '
521
522Boot_Files_Fat='
523 /menu.lst /grub/menu.lst /boot/grub/menu.lst /NST/menu.lst
524 /grub.cfg /grub/grub.cfg /boot/grub/grub.cfg /grub2/grub.cfg /boot/grub2/grub.cfg
525 /burg.cfg /burg/burg.cfg /boot/burg/burg.cfg
526 /grub.conf /grub/grub.conf /boot/grub/grub.conf /grub2/grub.conf /boot/grub2/grub.conf
527 /ubuntu/disks/boot/grub/menu.lst /ubuntu/disks/install/boot/grub/menu.lst /ubuntu/winboot/menu.lst
528 /boot.ini
529 /freeldr.ini
530 /etc/fstab
531 /etc/lilo.conf /lilo.conf
532 /syslinux.cfg /syslinux/syslinux.cfg /boot/syslinux/syslinux.cfg
533 /extlinux.conf /extlinux/extlinux.conf /boot/extlinux/extlinux.conf
534 /grldr /grub.exe
535 '
536
537
538## List of files whose end point (in GiB / GB) will be displayed. ##
539
540GrubError18_Files='
541 menu.lst grub/menu.lst boot/grub/menu.lst NST/menu.lst
542 ubuntu/disks/boot/grub/menu.lst
543 grub.conf grub/grub.conf boot/grub/grub.conf grub2/grub.conf boot/grub2/grub.conf
544 grub.cfg grub/grub.cfg boot/grub/grub.cfg grub2/grub.cfg boot/grub2/grub.cfg
545 burg.cfg burg/burg.cfg boot/burg/burg.cfg
546 core.img grub/core.img boot/grub/core.img grub2/core.img boot/grub2/core.img
547 burg/core.img boot/burg/core.img
548 stage2 grub/stage2 boot/grub/stage2
549 boot/vmlinuz* vmlinuz* ubuntu/disks/boot/vmlinuz*
550 boot/initrd* initrd* ubuntu/disks/boot/initrd*
551 boot/kernel*.img
552 initramfs* boot/initramfs*
553 '
554
555SyslinuxError_Files='
556 syslinux.cfg syslinux/syslinux.cfg boot/syslinux/syslinux.cfg
557 extlinux.conf extlinux/extlinux.conf boot/extlinux/extlinux.conf
558 ldlinux.sys syslinux/ldlinux.sys boot/syslinux/ldlinux.sys
559 extlinux.sys extlinux/extlinux.sys boot/extlinux/extlinux.sys
560 *.c32 syslinux/*.c32 boot/syslinux/*.c32
561 extlinux/*.c32 boot/extlinux/*.c32
562 '
563
564
565
566## Set output filename ##
567
568if [ ${stdout_output} -eq 1 ] ; then
569 # The LogFile name is not used when --stdout is specified.
570 LogFile="";
571elif ( [ ! -z "${LogFile_cmd}" ]) ; then
572 # The RESULTS filename is specified on the commandline.
573 LogFile=$(basename "${LogFile_cmd}");
574
575 # Directory where the RESULTS file will be stored.
576 Dir=$(dirname "${LogFile_cmd}");
577
578 # Check if directory exists.
579 if [ ! -d "${Dir}" ] ; then
580 echo "The directory \"${Dir}\" does not exist.";
581 echo 'Create the directory or specify another path for the output file.';
582 exit 1;
583 fi
584
585 Dir=$(cd "${Dir}"; pwd);
586 LogFile="${Dir}/${LogFile}";
587else
588 # Directory containing this script.
589 Dir=$(cd "$(dirname "$0")"; pwd);
590
591 # Set ${Dir} to the home folder of the current user if the script is
592 # in one of the system folders.
593 # This allows placement of the script in /bin, /sbin, /usr/bin, ...
594 # while still having a normal location to write the output file to.
595
596 for systemdir in /bin /boot /cdrom /dev /etc /lib /lost+found /opt /proc /sbin /selinux /srv /sys /usr /var; do
597 if [ $(expr "${Dir}" : ${systemdir}) -ne 0 ] ; then
598 Dir="${HOME}";
599 break;
600 fi
601 done
602
603 # To avoid overwriting existing files, look for a non-existing file:
604 # RESULT.txt, RESULTS1.txt, RESULTS2.txt, ...
605
606 LogFile="${Dir}/RESULTS";
607
608 while ( [ -e "${LogFile}${j}.txt" ] ) ; do
609 if [ x"${j}" = x'' ]; then
610 j=0;
611 fi
612 j=$((${j}+1));
613 wait;
614 done
615
616 LogFile="${LogFile}${j}.txt"; ## The RESULTS file. ##
617fi
618
619
620
621## Redirect stdout to RESULT File ##
622#
623# exec 6>&1
624# exec > "${LogFile}"
625
626
627
628## Create temporary directory ##
629
630Folder=$(mktemp -t -d BootInfo-XXXXXXXX);
631
632
633
634## Create temporary filenames. ##
635
636cd ${Folder}
637Log=${Folder}/Log # File to record the summary.
638Log1=${Folder}/Log1 # Most of the information which is not part of
639 # the summary is recorded in this file.
640Error_Log=${Folder}/Error_Log # File to catch all unusal Standar Errors.
641Trash=${Folder}/Trash # File to catch all usual Standard Errors these
642 # messagges will not be included in the RESULTS.
643Mount_Error=${Folder}/Mount_Error # File to catch Mounting Errors.
644Unknown_MBR=${Folder}/Unknown_MBR # File to record all unknown MBR and Boot sectors.
645Tmp_Log=${Folder}/Tmp_Log # File to temporarily hold some information.
646core_img_file=${Folder}/core_img # File to temporarily store an embedded core.img of grub2.
647core_img_file_unlzma=${Folder}/core_img_unlzma # File to temporarily store the uncompressed part of core.img of grub2.
648PartitionTable=${Folder}/PT # File to store the Partition Table.
649FakeHardDrives=${Folder}/FakeHD # File to list devices which seem to have no corresponding drive.
650BLKID=${Folder}/BLKID # File to store the output of blkid.
651
652
653
654## Redirect all standard error to the file Error_Log. ##
655
656exec 2> ${Error_Log};
657
658
659
660## List of all hard drives ##
661#
662# Support more than 26 drives.
663
664All_Hard_Drives=$(ls /dev/hd[a-z] /dev/hd[a-z][a-z] /dev/sd[a-z] /dev/sd[a-z][a-z] 2>> ${Trash});
665
666
667## Add found RAID disks to list of hard drives. ##
668
669if [ $(type dmraid >> ${Trash} 2>> ${Trash} ; echo $?) -eq 0 ] ; then
670 InActiveDMRaid=$(dmraid -si -c);
671
672 if [ x"${InActiveDMRaid}" = x"no raid disks" ] ; then
673 InActiveDMRaid='';
674 fi
675
676 if [ x"${InActiveDMRaid}" != x'' ] ; then
677 dmraid -ay ${InActiveDMRaid} >> ${Trash};
678 fi
679
680 if [ x"$(dmraid -sa -c)" != x"no raid disks" ] ; then
681 All_DMRaid=$(dmraid -sa -c | ${AWK} '{ print "/dev/mapper/"$0 }');
682 All_Hard_Drives="${All_Hard_Drives} ${All_DMRaid}";
683 fi
684fi
685
686
687
688## Arrays to hold information about Partitions: ##
689#
690# name, starting sector, ending sector, size in sector, partition type,
691# filesystem type, UUID, kind(Logical, Primary, Extended), harddrive,
692# boot flag, parent (for logical partitions), label,
693# system(the partition id according the partition table),
694# the device associated with the partition.
695
696declare -a NamesArray StartArray EndArray SizeArray TypeArray FileArray UUIDArray KindArray DriveArray BootArray ParentArray LabelArray SystemArray DeviceArray;
697
698
699## Arrays to hold information about the harddrives. ##
700
701declare -a HDName FirstPartion LastPartition HDSize HDMBR HDHead HDTrack HDCylinder HDPT HDStart HDEnd HDUUID;
702
703
704## Array for hard drives formatted as filesystem. ##
705
706declare -a FilesystemDrives;
707
708
709
710PI=-1; ## Counter for the identification number of a partition. (each partition gets unique number) ##
711HI=0; ## Counter for the identification number of a hard drive. (each hard drive gets unique number) ##
712PTFormat='%-10s %4s%14s%14s%14s %3s %s\n'; ## standard format (hexdump) to use for partition table. ##
713
714
715
716## Get total number of blocks on a device. ##
717#
718# Sometimes "fdisk -s" seems to malfunction or isn't supported (busybox fdisk),
719# so use "sfdisk -s" if available.
720# If sfdisk isn't available, calculate the number of blocks from the number of
721# sectors (divide by 2).
722
723fdisks () {
724 if [ $(type sfdisk >> ${Trash} 2>> ${Trash} ; echo $?) -eq 0 ] ; then
725 sfdisk -s "$1" 2>> ${Trash};
726 else
727 # Calculate the number of blocks from the number of sectors (divide by 2).
728 fdisk -lu "$1" 2>> ${Trash} | awk '$0 ~ /, .*, .*, .*/ { print $(NF - 1) / 2 }';
729 fi
730}
731
732
733
734## A function which checks whether a file is on a mounted partition. ##
735
736# List of mount points for devices: also allow mount points with spaces.
737
738MountPoints=$(mount \
739 | ${AWK} -F "${TAB}" '{ if ( ($1 ~ "^/dev") && ($3 != "/") ) { sub(" on ", "\t", $0); sub(" type ", "\t", $0); print $2 } }' \
740 | sort -u);
741
742
743FileNotMounted () {
744 local File=$1 curmp=$2;
745
746 IFS_OLD="${IFS}"; # Save original IFS.
747 IFS=$'\012'; # Set IFS temporarily to newline only, so mount points with spaces can be processed too.
748
749 for mp in ${MountPoints}; do
750 if [ $(expr match "${File}" "${mp}/" ) -ne 0 ] && [ "${mp}" != "${curmp}" ] ; then
751 IFS="${IFS_OLD}"; # Restore original IFS.
752 return 1;
753 fi
754 done
755
756 IFS="${IFS_OLD}"; # Restore original IFS.
757 return 0;
758}
759
760
761
762## Function which converts the two digit hexcode to the partition type. ##
763#
764# The following list is taken from sfdisk -T and
765# http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
766# is work in progress.
767
768HexToSystem () {
769 local type=$1 system;
770
771 case ${type} in
772 0) system='Empty';;
773 1) system='FAT12';;
774 2) system='XENIX root';;
775 3) system='XENIX /usr';;
776 4) system='FAT16 <32M';;
777 5) system='Extended';;
778 6) system='FAT16';;
779 7) system='NTFS / exFAT / HPFS';;
780 8) system='AIX bootable';;
781 9) system='AIX data';;
782 a) system='OS/2 Boot Manager';;
783 b) system='W95 FAT32';;
784 c) system='W95 FAT32 (LBA)';;
785 e) system='W95 FAT16 (LBA)';;
786 f) system='W95 Extended (LBA)';;
787 10) system='OPUS';;
788 11) system='Hidden FAT12';;
789 12) system='Compaq diagnostics';;
790 14) system='Hidden FAT16 < 32M';;
791 16) system='Hidden FAT16';;
792 17) system='Hidden NTFS / HPFS';;
793 18) system='AST SmartSleep';;
794 1b) system='Hidden W95 FAT32';;
795 1c) system='Hidden W95 FAT32 (LBA)';;
796 1e) system='Hidden W95 FAT16 (LBA)';;
797 24) system='NEC DOS';;
798 27) system='Hidden NTFS (Recovery Environment)';;
799 2a) system='AtheOS File System';;
800 2b) system='SyllableSecure';;
801 32) system='NOS';;
802 35) system='JFS on OS/2';;
803 38) system='THEOS';;
804 39) system='Plan 9';;
805 3a) system='THEOS';;
806 3b) system='THEOS Extended';;
807 3c) system='PartitionMagic recovery';;
808 3d) system='Hidden NetWare';;
809 40) system='Venix 80286';;
810 41) system='PPC PReP Boot';;
811 42) system='SFS';;
812 44) system='GoBack';;
813 45) system='Boot-US boot manager';;
814 4d) system='QNX4.x';;
815 4e) system='QNX4.x 2nd part';;
816 4f) system='QNX4.x 3rd part';;
817 50) system='OnTrack DM';;
818 51) system='OnTrack DM6 Aux1';;
819 52) system='CP/M';;
820 53) system='OnTrack DM6 Aux3';;
821 54) system='OnTrack DM6 DDO';;
822 55) system='EZ-Drive';;
823 56) system='Golden Bow';;
824 57) system='DrivePro';;
825 5c) system='Priam Edisk';;
826 61) system='SpeedStor';;
827 63) system='GNU HURD or SysV';;
828 64) system='Novell Netware 286';;
829 65) system='Novell Netware 386';;
830 70) system='DiskSecure Multi-Boot';;
831 74) system='Scramdisk';;
832 75) system='IBM PC/IX';;
833 78) system='XOSL filesystem';;
834 80) system='Old Minix';;
835 81) system='Minix / old Linux';;
836 82) system='Linux swap / Solaris';;
837 83) system='Linux';;
838 84) system='OS/2 hidden C: drive';;
839 85) system='Linux extended';;
840 86) system='NTFS volume set';;
841 87) system='NTFS volume set';;
842 88) system='Linux plaintext';;
843 8a) system='Linux Kernel (AiR-BOOT)';;
844 8d) system='Free FDISK hidden Primary FAT12';;
845 8e) system='Linux LVM';;
846 90) system='Free FDISK hidden Primary FAT16 <32M';;
847 91) system='Free FDISK hidden Extended';;
848 92) system='Free FDISK hidden Primary FAT16';;
849 93) system='Amoeba/Accidently Hidden Linux';;
850 94) system='Amoeba bad block table';;
851 97) system='Free FDISK hidden Primary FAT32';;
852 98) system='Free FDISK hidden Primary FAT32 (LBA)';;
853 9a) system='Free FDISK hidden Primary FAT16 (LBA)';;
854 9b) system='Free FDISK hidden Extended (LBA)';;
855 9f) system='BSD/OS';;
856 a0) system='IBM Thinkpad hibernation';;
857 a1) system='Laptop hibernation';;
858 a5) system='FreeBSD';;
859 a6) system='OpenBSD';;
860 a7) system='NeXTSTEP';;
861 a8) system='Darwin UFS';;
862 a9) system='NetBSD';;
863 ab) system='Darwin boot';;
864 af) system='HFS / HFS+';;
865 b0) system='BootStar';;
866 b1 | b3) system='SpeedStor / QNX Neutrino Power-Safe';;
867 b2) system='QNX Neutrino Power-Safe';;
868 b4 | b6) system='SpeedStor';;
869 b7) system='BSDI fs';;
870 b8) system='BSDI swap';;
871 bb) system='Boot Wizard hidden';;
872 bc) system='Acronis BackUp';;
873 be) system='Solaris boot';;
874 bf) system='Solaris';;
875 c0) system='CTOS';;
876 c1) system='DRDOS / secured (FAT-12)';;
877 c2) system='Hidden Linux (PowerBoot)';;
878 c3) system='Hidden Linux Swap (PowerBoot)';;
879 c4) system='DRDOS secured FAT16 < 32M';;
880 c5) system='DRDOS secured Extended';;
881 c6) system='DRDOS secured FAT16';;
882 c7) system='Syrinx';;
883 cb) system='DR-DOS secured FAT32 (CHS)';;
884 cc) system='DR-DOS secured FAT32 (LBA)';;
885 cd) system='CTOS Memdump?';;
886 ce) system='DR-DOS FAT16X (LBA)';;
887 cf) system='DR-DOS secured EXT DOS (LBA)';;
888 d0) system='REAL/32 secure big partition';;
889 da) system='Non-FS data / Powercopy Backup';;
890 db) system='CP/M / CTOS / ...';;
891 dd) system='Dell Media Direct';;
892 de) system='Dell Utility';;
893 df) system='BootIt';;
894 e1) system='DOS access';;
895 e3) system='DOS R/O';;
896 e4) system='SpeedStor';;
897 e8) system='LUKS';;
898 eb) system='BeOS BFS';;
899 ec) system='SkyOS';;
900 ee) system='GPT';;
901 ef) system='EFI (FAT-12/16/32)';;
902 f0) system='Linux/PA-RISC boot';;
903 f1) system='SpeedStor';;
904 f2) system='DOS secondary';;
905 f4) system='SpeedStor';;
906 fb) system='VMware VMFS';;
907 fc) system='VMware VMswap';;
908 fd) system='Linux raid autodetect';;
909 fe) system='LANstep';;
910 ff) system='Xenix Bad Block Table';;
911 *) system='Unknown';;
912 esac
913
914 echo "${system}";
915}
916
917
918
919## Function to convert GPT's Partition Type. ##
920#
921# List from http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
922#
923# ABCDEFGH-IJKL-MNOP-QRST-UVWXYZabcdef is stored as
924# GHEFCDAB-KLIJ-OPMN-QRST-UVWXYZabcdef (without the dashes)
925#
926# For easy generation of the following list:
927# - Save list in a file "Partition_type_GUIDs.txt" in the folowing format:
928#
929# Partition Type (OS) <TAB> GUID
930# Partition Type (OS) <TAB> GUID
931# Partition Type (OS) <TAB> GUID
932#
933# - Then run the following:
934#
935# gawk -F '\t' '{ GUID=tolower($2); printf " %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) system=\"%s\";;\n", substr(GUID,7,1), substr(GUID,8,1), substr(GUID,5,1), substr(GUID,6,1), substr(GUID,3,1), substr(GUID,4,1), substr(GUID,1,1), substr(GUID,2,1), substr(GUID,12,1), substr(GUID,13,1), substr(GUID,10,1), substr(GUID,11,1), substr(GUID,17,1), substr(GUID,18,1), substr(GUID,15,1), substr(GUID,16,1), substr(GUID,20,4), substr(GUID,25,12), $1 } END { print " *) system='-';" }' Partition_type_GUIDs.txt
936#
937# - Some GUIDs are not unique for one OS. To find them, you can run:
938#
939# gawk -F "\t" '{print $2}' GUID_Partition_Table_list.txt | sort | uniq -d | grep -f - GUID_Partition_Table_list.txt
940#
941# Basic data partition (Windows) EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
942# Data partition (Linux) EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
943# ZFS (Mac OS X) 6A898CC3-1DD2-11B2-99A6-080020736631
944# /usr partition (Solaris) 6A898CC3-1DD2-11B2-99A6-080020736631
945#
946
947UUIDToSystem () {
948 local type=$1 system;
949
950 case ${type} in
951 00000000000000000000000000000000) system='Unused entry';;
952 41ee4d02e733d3119d690008c781f39f) system='MBR partition scheme';;
953 28732ac11ff8d211ba4b00a0c93ec93b) system='EFI System partition';;
954 4861682149646f6e744e656564454649) system='BIOS Boot partition';;
955
956 ## GUIDs that are not unique for one OS ##
957 a2a0d0ebe5b9334487c068b6b72699c7) system='Data partition (Windows/Linux)';;
958 c38c896ad21db21199a6080020736631) system='ZFS (Mac OS X) or /usr partition (Solaris)';;
959
960 ## Windows GUIDs ##
961 16e3c9e35c0bb84d817df92df00215ae) system='Microsoft Reserved Partition (Windows)';;
962 # Same GUID as old GUID for "Basic data partition (Linux)"
963 # a2a0d0ebe5b9334487c068b6b72699c7) system='Basic data partition (Windows)';;
964 aac808588f7ee04285d2e1e90434cfb3) system='Logical Disk Manager metadata partition (Windows)';;
965 a0609baf3114624fbc683311714a69ad) system='Logical Disk Manager data partition (Windows)';;
966 a4bb94ded106404da16abfd50179d6ac) system='Windows Recovery Environment (Windows)';;
967 90fcaf377def964e91c32d7ae055b174) system='IBM General Parallel File System (GPFS) partition (Windows)';;
968
969 ## HP-UX GUIDs ##
970 1e4c8975eb3ad311b7c17b03a0000000) system='Data partition (HP-UX)';;
971 28e7a1e2e332d611a6827b03a0000000) system='Service Partition (HP-UX)';;
972
973 ## Linux GUIDs ##
974 # Same GUID as "Basic data partition (Windows)" GUID
975 # a2a0d0ebe5b9334487c068b6b72699c7) system='Data partition (Linux)';;
976 # New GUID to avoid that Linux partitions show up as unformatted partitions in Windows.
977 af3dc60f838472478e793d69d8477de4) system='Data partition (Linux)';;
978 0f889da1fc053b4da006743f0f84911e) system='RAID partition (Linux)';;
979 6dfd5706aba4c44384e50933c84b4f4f) system='Swap partition (Linux)';;
980 79d3d6e607f5c244a23c238f2a3df928) system='Logical Volume Manager (LVM) partition (Linux)';;
981 3933a68d0700c060c436083ac8230908) system='Reserved (Linux)';;
982
983 ## FreeBSD GUIDs ##
984 9d6bbd83417fdc11be0b001560b84f0f) system='Boot partition (FreeBSD)';;
985 b47c6e51cf6ed6118ff800022d09712b) system='Data partition (FreeBSD)';;
986 b57c6e51cf6ed6118ff800022d09712b) system='Swap partition (FreeBSD)';;
987 b67c6e51cf6ed6118ff800022d09712b) system='Unix File System (UFS) partition (FreeBSD)';;
988 b87c6e51cf6ed6118ff800022d09712b) system='Vinum volume manager partition (FreeBSD)';;
989 ba7c6e51cf6ed6118ff800022d09712b) system='ZFS partition (FreeBSD)';;
990
991 ## Mac OS X GUIDs ##
992 005346480000aa11aa1100306543ecac) system='Hierarchical File System Plus (HFS+) partition (Mac OS X)';;
993 005346550000aa11aa1100306543ecac) system='Apple UFS (Mac OS X)';;
994 # c38c896ad21db21199a6080020736631) system='ZFS (Mac OS X)';;
995 444941520000aa11aa1100306543ecac) system='Apple RAID partition (Mac OS X)';;
996 444941524f5faa11aa1100306543ecac) system='Apple RAID partition offline (Mac OS X)';;
997 746f6f420000aa11aa1100306543ecac) system='Apple Boot partition (Mac OS X)';;
998 6562614c006caa11aa1100306543ecac) system='Apple Label (Mac OS X)';;
999 6f6365526576aa11aa1100306543ecac) system='Apple TV Recovery partition (Mac OS X)';;
1000
1001 ## Solaris GUIDs ##
1002 45cb826ad21db21199a6080020736631) system='Boot partition (Solaris)';;
1003 4dcf856ad21db21199a6080020736631) system='Root partition (Solaris)';;
1004 6fc4876ad21db21199a6080020736631) system='Swap partition (Solaris)';;
1005 2b648b6ad21db21199a6080020736631) system='Backup partition (Solaris)';;
1006 # c38c896ad21db21199a6080020736631) system='/usr partition (Solaris)';;
1007 e9f28e6ad21db21199a6080020736631) system='/var partition (Solaris)';;
1008 39ba906ad21db21199a6080020736631) system='/home partition (Solaris)';;
1009 a583926ad21db21199a6080020736631) system='Alternate sector (Solaris)';;
1010 3b5a946ad21db21199a6080020736631) system='Reserved partition (Solaris)';;
1011 d130966ad21db21199a6080020736631) system='Reserved partition (Solaris)';;
1012 6707986ad21db21199a6080020736631) system='Reserved partition (Solaris)';;
1013 7f23966ad21db21199a6080020736631) system='Reserved partition (Solaris)';;
1014 c72a8d6ad21db21199a6080020736631) system='Reserved partition (Solaris)';;
1015
1016 ## NetBSD GUIDs ##
1017 328df4490eb1dc11b99b0019d1879648) system='Swap partition (NetBSD)';;
1018 5a8df4490eb1dc11b99b0019d1879648) system='FFS partition (NetBSD)';;
1019 828df4490eb1dc11b99b0019d1879648) system='LFS partition (NetBSD)';;
1020 aa8df4490eb1dc11b99b0019d1879648) system='RAID partition (NetBSD)';;
1021 c419b52d0fb1dc11b99b0019d1879648) system='Concatenated partition (NetBSD)';;
1022 ec19b52d0fb1dc11b99b0019d1879648) system='Encrypted partition (NetBSD)';;
1023
1024 ## ChromeOS GUIDs ##
1025 5d2a3afe324fa741b725accc3285a309) system="ChromeOS kernel";;
1026 02e2b83c7e3bdd478a3c7ff2a13cfcec) system="ChromeOS rootfs";;
1027 3d750a2e489eb0438337b15192cb1b5e) system="ChromeOS future use";;
1028
1029 *) system='-';
1030 echo 'Unknown GPT Partiton Type' >> ${Unknown_MBR};
1031 echo ${type} >> ${Unknown_MBR};;
1032 esac
1033
1034 echo "${system}";
1035}
1036
1037
1038
1039## Function which inserts a comma every third digit of a number. ##
1040
1041InsertComma () {
1042 echo $1 | sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta';
1043}
1044
1045
1046
1047## Function to read 4 bytes starting at $1 of device $2 and convert result to decimal. ##
1048
1049Read4Bytes () {
1050 local start=$1 device=$2;
1051
1052 echo $(hexdump -v -s ${start} -n 4 -e '4 "%u"' ${device});
1053}
1054
1055
1056
1057## Function to read 8 bytes starting at $1 of device $2 and convert result to decimal. ##
1058
1059Read8Bytes () {
1060 local start=$1 device=$2;
1061 local first4 second4;
1062
1063 # Get ${first4} and ${second4} bytes at once.
1064 eval $(hexdump -v -s ${start} -n 8 -e '1/4 "first4=%u; " 1/4 "second4=%u"' ${device});
1065
1066 echo $(( ${second4} * 1073741824 + ${first4} ));
1067}
1068
1069
1070
1071## Functions to pretty print blkid output. ##
1072
1073BlkidFormat='%-16s %-38s %-10s %s\n';
1074
1075BlkidTag () {
1076 echo $(blkid -s $2 -o value $1 2>> ${Trash});
1077}
1078
1079
1080
1081PrintBlkid () {
1082 local part=$1 suffix=$2;
1083
1084 if [ x"$(blkid ${part} 2> ${Tmp_Log})" != x'' ] ; then
1085 printf "${BlkidFormat}" "${part}" "$(BlkidTag ${part} UUID)" "$(BlkidTag ${part} TYPE)" "$(BlkidTag ${part} LABEL)" >> ${BLKID}${suffix};
1086 else
1087 # blkid -p is not available on all systems.
1088 # This contructs makes sure the "usage" message is not displayed, but catches the "ambivalent" error.
1089 blkid -p "${part}" 2>&1 | grep "^${part}" >> ${BLKID}${suffix};
1090 fi
1091}
1092
1093
1094
1095## Read and display the partition table and check the partition table for errors. ##
1096#
1097# This function can be applied iteratively so extended partiton tables can also be processed.
1098#
1099# Function arguments:
1100#
1101# - arg 1: HI = HI of hard drive
1102# - arg 2: StartEx = start sector of the extended Partition
1103# - arg 3: N = number of partitions in table (4 for regular PT, 2 for logical
1104# - arg 4: PT_file = file for storing the partition table
1105# - arg 5: format = display format to use for displaying the partition table
1106# - arg 6: EPI = PI of the primary extended partition containing the extended partition.
1107# ( equals "" for hard drive)
1108# - arg 7: LinuxIndex = Last linux index assigned (the number in sdXY).
1109
1110ReadPT () {
1111 local HI=$1 StartEx=$2 N=$3 PT_file=$4 format=$5 EPI=$6 Base_Sector;
1112 local LinuxIndex=$7 boot size start end type drive system;
1113 local i=0 boot_hex label limit MBRSig;
1114
1115 drive=${HDName[${HI}]};
1116 limit=${HDSize[${HI}]};
1117
1118 dd if=${drive} skip=${StartEx} of=${Tmp_Log} count=1 2>> ${Trash};
1119
1120 MBRSig=$(hexdump -v -s 510 -n 2 -e '"%04x"' ${Tmp_Log});
1121
1122 [[ "${MBRSig}" != 'aa55' ]] && echo 'Invalid MBR Signature found.' >> ${PT_file};
1123
1124 if [[ ${StartEx} -lt ${limit} ]] ; then
1125 # set Base_Sector to 0 for hard drive, and to the start sector of the
1126 # primary extended partition otherwise.
1127 [[ x"${EPI}" = x'' ]] && Base_Sector=0 || Base_Sector=${StartArray[${EPI}]};
1128
1129 for (( i=0; i < N; i++ )) ; do
1130 dd if=${drive} skip=${StartEx} of=${Tmp_Log} count=1 2>> ${Trash};
1131
1132 boot_hex=$(hexdump -v -s $((446+16*${i})) -n 1 -e '"%02x"' ${Tmp_Log});
1133
1134 case ${boot_hex} in
1135 00) boot=' ';;
1136 80) boot='* ';;
1137 *) boot='?';;
1138 esac
1139
1140 # Get amd set: partition type, partition start, and partition size.
1141 eval $(hexdump -v -s $((450+16*${i})) -n 12 -e '1/1 "type=%x; " 3/1 "tmp=%x; " 1/4 "start=%u; " 1/4 "size=%u"' ${Tmp_Log});
1142
1143 if [[ ${size} -ne 0 ]] ; then
1144 if ( ( [ "${type}" = '5' ] || [ "${type}" = 'f' ] ) && [ ${Base_Sector} -ne 0 ] ) ; then
1145 # start sector of an extended partition is relative to the
1146 # start sector of an primary extended partition.
1147 start=$((${start}+${Base_Sector}));
1148
1149 if [[ ${i} -eq 0 ]] ; then
1150 echo 'Extended partition linking to another extended partition.' >> ${PT_file};
1151 fi
1152
1153 ReadPT ${HI} ${start} 2 ${PT_file} "${format}" ${EPI} ${LinuxIndex};
1154 else
1155 ((PI++));
1156
1157 if [[ "${type}" = '5' || "${type}" = 'f' ]] ; then
1158 KindArray[${PI}]='E';
1159 else
1160 # Start sector of a logical partition is relative to the
1161 # start sector of directly assocated extented partition.
1162 start=$((${start}+${StartEx}));
1163 [[ ${Base_Sector} -eq 0 ]] && KindArray[${PI}]='P' || KindArray[${PI}]='L';
1164 fi
1165
1166 LinuxIndex=$((${LinuxIndex}+1));
1167 end=$((${start}+${size}-1));
1168
1169 [[ "${HDPT[${HI}]}" = 'BootIt' ]] && label="${NamesArray[${EPI}]}_" || label=${drive};
1170
1171 system=$(HexToSystem ${type});
1172
1173 printf "${format}" "${label}${LinuxIndex}" "${boot}" $(InsertComma ${start}) "$(InsertComma ${end})" "$(InsertComma ${size})" "${type}" "${system}" >> ${PT_file};
1174
1175 NamesArray[${PI}]="${label}${LinuxIndex}";
1176 StartArray[${PI}]=${start};
1177 EndArray[${PI}]=${end};
1178 TypeArray[${PI}]=${type};
1179 SystemArray[${PI}]="${system}";
1180 SizeArray[${PI}]=${size};
1181 BootArray[${PI}]="${boot}";
1182 DriveArray[${PI}]=${HI};
1183 ParentArray[${PI}]=${EPI};
1184
1185 ( [[ x"${EPI}" = x'' ]] || [[ x"${DeviceArray[${EPI}]}" != x'' ]] ) && DeviceArray[${PI}]=${drive}${LinuxIndex};
1186
1187 if [[ "${type}" = '5' || "${type}" = 'f' ]] ; then
1188 ReadPT ${HI} ${start} 2 ${PT_file} "${format}" ${PI} 4;
1189 fi
1190 fi
1191
1192 elif ( [ ${Base_Sector} -ne 0 ] && [ ${i} -eq 0 ] ) ; then
1193 echo 'Empty Partition.' >> ${PT_file};
1194 else
1195 LinuxIndex=$((${LinuxIndex}+1));
1196 fi
1197 done
1198 else
1199 echo 'EBR refers to a location outside the hard drive.' >> ${PT_file};
1200 fi
1201}
1202
1203
1204
1205## Read the GPT partition table (GUID, EFI) ##
1206#
1207# Function arguments:
1208#
1209# - arg 1: HI = HI of hard drive
1210# - arg 2: GPT_file = file for storing the GPT partition table
1211
1212ReadEFI () {
1213 local HI=$1 GPT_file=$2 drive size N=0 i=0 format label PRStart start end type size system;
1214
1215 drive="${HDName[${HI}]}";
1216 format='%-10s %14s%14s%14s %s\n';
1217
1218 printf "${format}" 'Partition' 'Start Sector' 'End Sector' '# of Sectors' 'System' >> ${GPT_file};
1219
1220 HDStart[${HI}]=$( Read8Bytes 552 ${drive});
1221 HDEnd[${HI}]=$( Read8Bytes 560 ${drive});
1222 HDUUID[${HI}]=$( hexdump -v -s 568 -n 16 -e '/1 "%02x"' ${drive});
1223 PRStart=$( Read8Bytes 584 ${drive});
1224 N=$( Read4Bytes 592 ${drive});
1225 PRStart=$(( ${PRStart}*512));
1226 PRSize=$( Read4Bytes 596 ${drive});
1227
1228 for (( i = 0; i < N; i++ )) ; do
1229 type=$(hexdump -v -s $((${PRStart}+${PRSize}*${i})) -n 16 -e '/1 "%02x"' ${drive});
1230
1231 if [ "${type}" != '00000000000000000000000000000000' ] ; then
1232 ((PI++));
1233
1234 start=$(Read8Bytes $((${PRStart}+32+${PRSize}*${i})) ${drive});
1235 end=$( Read8Bytes $((${PRStart}+40+${PRSize}*${i})) ${drive});
1236
1237 size=$((${end}-${start}+1));
1238 system=$(UUIDToSystem ${type});
1239 label=${drive}$((${i}+1));
1240
1241 printf "${format}" "${label}" "$(InsertComma ${start})" "$(InsertComma ${end})" "$(InsertComma ${size})" "${system}" >> ${GPT_file};
1242
1243 NamesArray[${PI}]=${label};
1244 DeviceArray[${PI}]=${label};
1245 StartArray[${PI}]=${start};
1246 TypeArray[${PI}]=${type};
1247 SizeArray[${PI}]=${size};
1248 SystemArray[${PI}]=${system};
1249 EndArray[${PI}]=${end};
1250 DriveArray[${PI}]=${HI};
1251 KindArray[${PI}]='P';
1252 ParentArray[${PI}]='';
1253 fi
1254 done
1255}
1256
1257
1258
1259## Read the Master Partition Table of BootIt NG. ##
1260#
1261# Function arguments:
1262#
1263# - arg 1: HI = HI of hard drive
1264# - arg 2: MPT_file = file for storing the MPT
1265
1266ReadEMBR () {
1267 local HI=$1 MPT_file=$2 drive size N=0 i=0 BINGIndex label start end type format;
1268 local BINGUnknown system StoredPI FirstPI=${FirstPartition[$1]} LastPI=${PI} New;
1269
1270 drive="${HDName[${HI}]}";
1271 format='%-18s %4s%14s%14s%14s %3s %-15s %3s %2s\n';
1272
1273 printf "${format}" 'Partition' 'Boot' 'Start Sector' 'End Sector' '# of Sectors' 'Id' 'System' 'Ind' '?' >> ${MPT_file};
1274
1275 N=$(hexdump -v -s 534 -n 1 -e '"%u"' ${drive});
1276
1277 for (( i = 0; i < N; i++ )) ; do
1278 New=1;
1279 BINGUnknown=$(hexdump -v -s $((541+28*${i})) -n 1 -e '"%x"' ${drive});
1280 start=$( hexdump -v -s $((542+28*${i})) -n 4 -e '4 "%u"' ${drive});
1281 end=$( hexdump -v -s $((546+28*${i})) -n 4 -e '4 "%u"' ${drive});
1282 BINGIndex=$( hexdump -v -s $((550+28*${i})) -n 1 -e '"%u"' ${drive});
1283 type=$( hexdump -v -s $((551+28*${i})) -n 1 -e '"%x"' ${drive});
1284 size=$(( ${end}-${start}+1));
1285 label=$( hexdump -v -s $((552+28*${i})) -n 15 -e '"%_u"' ${drive}| sed -e 's/nul[^$]*//');
1286 system=$( HexToSystem ${type});
1287
1288 printf "${format}" "${label}" "-" "$(InsertComma ${start})" "$(InsertComma ${end})" "$(InsertComma ${size})" "${type}" "${system}" "${BINGIndex}" "${BINGUnknown}" >> ${MPT_file};
1289
1290 StoredPI=${PI};
1291
1292 for (( j = FirstPI; j <= LastPI; j++ )); do
1293 if (( ${StartArray[${j}]} == ${start} )) ; then
1294 PI=${j};
1295 New=0;
1296 break;
1297 fi
1298 done
1299
1300 if [ ${New} -eq 1 ] ; then
1301 ((PI++));
1302 StoredPI=${PI};
1303 StartArray[${PI}]=${start};
1304 TypeArray[${PI}]=${type};
1305 SizeArray[${PI}]=${size};
1306 SystemArray[${PI}]=${system};
1307 EndArray[${PI}]=${end};
1308 DriveArray[${PI}]=${HI};
1309 fi
1310
1311 NamesArray[${PI}]=${label};
1312
1313 if ( [ ${type} = 'f' ] || [ ${type} = '5' ] ) ; then
1314 KindArray[${PI}]='E';
1315 ParentArray[${PI}]=${PI};
1316 ReadPT ${HI} ${start} 2 ${MPT_file} "${format}" ${PI} 4;
1317 else
1318 KindArray[${PI}]='P';
1319 ParentArray[${PI}]='';
1320 fi
1321
1322 PI=${StoredPI};
1323
1324 done
1325}
1326
1327
1328
1329## Check partition table for errors. ##
1330#
1331# This function checks whether:
1332# - there are any overlapping partitions
1333# - the logical partitions are inside the extended partition
1334#
1335# Function arguments:
1336#
1337# - arg 1: PI_first = PI of first partition to consider
1338# - arg 2: PI_last = PI of last partition to consider
1339# - arg 3: CHK_file = file for the error messages
1340# - arg 4: HI = HI of containing hard drive
1341
1342CheckPT () {
1343 local PI_first=$1 PI_last=$2 CHK_file=$3 HI=$4;
1344 local Si Ei Sj Ej Ki Kj i j k cyl track head cyl_bound sec_bound;
1345
1346 cyl=${HDCylinder[${HI}]};
1347 track=${HDTrack[${HI}]};
1348 head=${HDHead[${HI}]};
1349 cyl_bound=$((cyl * track * head));
1350 sec_bound=${HDSize[${HI}]};
1351
1352 for (( i = PI_first; i <= PI_last; i++ )); do
1353 Si=${StartArray[${i}]};
1354 Ei=${EndArray[${i}]};
1355 Ki=${KindArray[${i}]};
1356 Ni=${NamesArray[${i}]};
1357
1358 if [[ "${Ei}" -gt "${sec_bound}" ]] ; then
1359 echo "${Ni} ends after the last sector of ${HDName[${HI}]}" >> ${CHK_file};
1360 elif [[ "${Ei}" -gt "${cyl_bound}" ]] ; then
1361 echo "${Ni} ends after the last cylinder of ${HDName[${HI}]}" >> ${Trash};
1362 fi
1363
1364 if [[ ${Ki} = "L" ]] ; then
1365 k=${ParentArray[${i}]};
1366 Sk=${StartArray[${k}]};
1367 Ek=${EndArray[${k}]};
1368 Nk=${NamesArray[${k}]};
1369 [[ ${Si} -le ${Sk} || ${Ei} -gt ${Ek} ]] && echo "the logical partition ${Ni} is not contained in the extended partition ${Nk}" >> ${CHK_file};
1370 fi
1371
1372 for (( j = i+1; j <= PI_last; j++ )); do
1373 Sj=${StartArray[${j}]};
1374 Ej=${EndArray[${j}]};
1375 Kj=${KindArray[${j}]};
1376 Nj=${NamesArray[${j}]};
1377
1378 ( !( ( [ "${Ki}" = 'L' ] && [ "${Kj}" = 'E' ] ) || ( [ "${Ki}" = 'E' ] && [ "${Kj}" = 'L' ] ) ) \
1379 && ( ( [ "${Si}" -lt "${Sj}" ] && [ "${Sj}" -lt "${Ei}" ] ) || ( [ "${Sj}" -lt "${Si}" ] && [ "${Si}" -lt "${Ej}" ] ) ) ) \
1380 && echo "${Ni} overlaps with ${Nj}" >> ${CHK_file};
1381
1382 done
1383 done
1384}
1385
1386
1387
1388## Syslinux ##
1389#
1390# Determine the exact Syslinux version ("SYSLINUX - version - date"), display
1391# the offset to the second stage, check the internal checksum (if not correct,
1392# the ldlinux.sys file, probably moved), display the directory to which
1393# Syslinux is installed.
1394
1395syslinux_info () {
1396 local partition=$1;
1397
1398 # Magic number used by Syslinux:
1399 local LDLINUX_MAGIC='fe02b23e';
1400
1401 local LDLINUX_BSS LDLINUX_SECTOR2 ADV_2SECTORS;
1402 local sect1ptr0_offset sect1ptr0 sect1ptr1 tmp;
1403 local magic_offset syslinux_version syslinux_dir;
1404
1405 # Patch area variables:
1406 local pa_version pa_size pa_hexdump_format pa_magic pa_instance pa_data_sectors;
1407 local pa_adv_sectors pa_dwords pa_checksum pa_maxtransfer pa_epaoffset;
1408 local pa_ldl_sectors pa_dir_inode;
1409
1410 # Extended patch area variables:
1411 local epa_size epa_hexdump_format epa_advptroffset epa_diroffset epa_dirlen;
1412 local epa_subvoloffset epa_subvollen epa_secptroffset epa_secptrcnt;
1413 local epa_sect1ptr0 epa_sect1ptr1 epa_raidpatch epa_syslinuxbanner;
1414
1415 # ADV magic numbers:
1416 local ADV_MAGIC_HEAD='a52f2d5a'; # Head signature
1417 local ADV_MAGIC_TAIL='64bf28dd'; # Tail signature
1418 local ADV_MAGIC_CHECKSUM=$((0xa3041767)); # Magic used for calculation ADV checksum
1419
1420 # ADV variables:
1421 local ADVoffset ADV_calculated_checksum ADV_read_checksum ADVentry_offset;
1422 local tag='999' tag_len label;
1423
1424 local csum;
1425
1426
1427
1428 # Clear previous Syslinux message string.
1429 Syslinux_Msg='';
1430
1431 # Read first 512 bytes of partition and convert to hex (ldlinux.bss)
1432 LDLINUX_BSS=$(hexdump -v -n512 -e '/1 "%02x"' ${partition});
1433
1434 # Look for LDLINUX_MAGIC: bytes 504-507
1435 if [ "${LDLINUX_BSS:1008:8}" = "${LDLINUX_MAGIC}" ] ; then
1436 # Syslinux 4.04-pre5 and higher.
1437 pa_version=4; # Syslinux 4.xx patch area
1438
1439 # The offset of Sect1Load in LDLINUX_BSS can be found by doing a
1440 # bitwise XOR of bytes 508-509 (little endian) with 0x1b << 9.
1441 # sect1ptr0_offset starts 2 bytes furter than Sect1Load.
1442 sect1ptr0_offset=$(( ( 0x${LDLINUX_BSS:1018:2}${LDLINUX_BSS:1016:2} ^ ( 0x1b << 9 ) ) + 2 ));
1443
1444 # Get "boot sector offset" (in sectors) of sector 1 ptr LSW: sect1ptr0
1445 # Get "boot sector offset" (in sectors) of sector 1 ptr MSW: sect1ptr1
1446 eval $(hexdump -v -s ${sect1ptr0_offset} -n 10 -e '1/4 "sect1ptr0=%u; " 1/2 "tmp=%u; " 1/4 "sect1ptr1=%u;"' ${partition});
1447
1448 else
1449 # Check if bytes 508-509 = "7f00".
1450 if [ "${LDLINUX_BSS:1016:4}" = '7f00' ] ; then
1451 # Syslinux 3.xx
1452 pa_version=3; # Syslinux 3.xx patch area
1453
1454 # Get "boot sector offset" (in sectors) of sector 1 ptr LSW: sect1ptr0
1455 eval $(hexdump -v -s 504 -n 4 -e '1/4 "sect1ptr0=%u;"' ${partition});
1456 else
1457 # Syslinux 4.00 - Syslinux 4.04-pre4.
1458 pa_version=4; # Syslinux 4.xx patch area
1459
1460 # Search for offset to sect1ptr0 (only found in Syslinux 4.xx)
1461 # 66 b8 xx xx xx xx 66 ba xx xx xx xx bb 00
1462 # [sect1ptr0] [sect1ptr1]
1463 #
1464 # Start searching for this hex string after the DOS superblock: byte 0x5a = 90
1465 eval $(echo ${LDLINUX_BSS:180:844} \
1466 | ${AWK} '{ mask_offset=match($0,"66b8........66ba........bb00"); \
1467 if (mask_offset == "0") { print "sect1ptr0_offset=0;" } \
1468 else { print "sect1ptr0_offset=" (mask_offset -1 ) / 2 + 2 + 90 } }');
1469
1470 if [ ${sect1ptr0_offset} -ne 0 ] ; then
1471 # Syslinux 4.00 - Syslinux 4.04-pre4.
1472
1473 # Get "boot sector offset" (in sectors) of sector 1 ptr LSW: sect1ptr0
1474 # Get "boot sector offset" (in sectors) of sector 1 ptr MSW: sect1ptr1
1475 eval $(hexdump -v -s ${sect1ptr0_offset} -n 10 -e '1/4 "sect1ptr0=%u; " 1/2 "tmp=%u; " 1/4 "sect1ptr1=%u;"' ${partition});
1476 else
1477 Syslinux_Msg='No evidence that this is realy a Syslinux boot sector.';
1478 return;
1479 fi
1480 fi
1481 fi
1482
1483 Syslinux_Msg="Syslinux looks at sector ${sect1ptr0} of ${partition} for its second stage.";
1484
1485 # Start reading 0.5MiB (more than enough) from second sector of the Syslinux
1486 # bootloader (= first sector of ldlinux.sys).
1487 dd if=${partition} of=${Tmp_Log} skip=${sect1ptr0} count=1000 bs=512 2>> ${Trash};
1488
1489 # Get second sector of the Syslinux bootloader (= first sector of ldlinux.sys)
1490 # and convert to hex.
1491 LDLINUX_SECTOR2=$(hexdump -v -n 512 -e '/1 "%02x"' ${Tmp_Log});
1492
1493 # Look for LDLINUX_MAGIC (8 bytes aligned) in sector 2 of the Syslinux bootloader.
1494 for (( magic_offset = $((0x10)); magic_offset < $((0x50)); magic_offset = magic_offset + 8 )); do
1495 if [ "${LDLINUX_SECTOR2:$(( ${magic_offset} * 2 )):8}" = ${LDLINUX_MAGIC} ] ; then
1496
1497 if [ ${pa_version} -eq 4 ] ; then
1498 # Syslinux 4.xx patch area.
1499
1500 # Patch area size: 4+4+2+2+4+4+2+2 = 4*4 + 4*2 = 24 bytes
1501 pa_size='24';
1502
1503 # Get pa_magic, pa_instance, pa_data_sectors, pa_adv_sectors, pa_dwords, pa_checksum, pa_maxtransfer and pa_epaoffset.
1504 pa_hexdump_format='1/4 "pa_magic=0x%04x; " 1/4 "pa_instance=0x%04x; " 1/2 "pa_data_sectors=%u; " 1/2 "pa_adv_sectors=%u; " 1/4 "pa_dwords=0x%u; " 1/4 "pa_checksum=0x%04x; " 1/2 "pa_maxtransfer=%u; " 1/2 "pa_epaoffset=%u;"';
1505
1506 eval $(hexdump -v -s ${magic_offset} -n ${pa_size} -e "${pa_hexdump_format}" ${Tmp_Log});
1507
1508 else
1509 # Syslinux 3.xx patch area.
1510
1511 # Patch area size: 4+4+2+2+4+4 = 4*4 + 2*2 = 20 bytes
1512 pa_size='20';
1513
1514 # Get pa_magic, pa_instance, pa_dwords, pa_ldl_sectors and pa_checksum.
1515 # - pa_dwords: Total dwords starting at ldlinux_sys not including ADVs.
1516 # - pa_ldl_sectors: Number of sectors - (bootsec + sector2) but including any ADVs.
1517 pa_hexdump_format='1/4 "pa_magic=0x%04x; " 1/4 "pa_instance=0x%04x; " 1/2 "pa_dwords=%u; " 1/2 "pa_ldl_sectors=%u; " 1/4 "pa_checksum=0x%04x; " 1/4 "pa_dir_inode=%u;"';
1518
1519 eval $(hexdump -v -s ${magic_offset} -n ${pa_size} -e "${pa_hexdump_format}" ${Tmp_Log});
1520
1521 # Calulate pa_data_sectors: number of sectors (not including ldlinux.bss = first sector of Syslinux).
1522 # - divide by 128 (128 dwords / 512 byte sector)
1523 pa_data_sectors=$(( ${pa_dwords} / 128 ));
1524
1525 # If total dwords is not exactly a multiple of 128, round up the number of sectors (add 1).
1526 if [ $(( ${pa_dwords}%128 )) -ne 0 ] ; then
1527 pa_data_sectors=$(( ${pa_data_sectors} + 1 ));
1528 fi
1529
1530
1531 # Some Syslinux 4.00-pre?? releases are different:
1532 # - have Syslinux 3.xx signature: bytes 508-509 = "7f00".
1533 # - have the "boot sector offset" (in sectors) of sector 1 ptr LSW (bytes 504-507)
1534 # for sect1ptr0, like Syslinux 3.xx.
1535 # - have like Syslinux 4.xx, the same location for pa_data_sectors.
1536 #
1537 # If pa_dwords is less than 1024, it contains the value of pa_data_sectors:
1538 # - if less and pa_words would really be pa_words: ldlinux.sys would be smaller than 4 kiB
1539 # - if more and pa_words would really be pa_data_sectors: ldlinux.sys would be more than 500 kiB
1540
1541 if [ ${pa_dwords} -lt 1024 ] ; then
1542 pa_data_sectors=${pa_dwords};
1543 fi
1544
1545 fi
1546
1547
1548 # Get the "SYSLINUX - version - date" string.
1549 syslinux_version=$(hexdump -v -e '"%_p"' -s 2 -n $(( ${magic_offset} - 2 )) ${Tmp_Log});
1550 syslinux_version="${syslinux_version% \.*}";
1551
1552 # Overwrite the "boot sector type" variable, which was set before calling this function,
1553 # with a more exact Syslinux version number.
1554 BST="${syslinux_version}";
1555
1556
1557 # Check integrity of Syslinux:
1558 # - Checksum starting at ldlinux.sys, stopping before the ADV part.
1559 # - checksum start = LDLINUX_MAGIC - [sum of dwords].
1560 # - add each dword to the checksum value.
1561 # - the value of the checksum after adding all dwords of ldlinux.sys should be 0.
1562
1563 csum=$(hexdump -v -n $(( ${pa_data_sectors} * 512)) -e '/4 "%u\n"' ${Tmp_Log} \
1564 | ${AWK} 'BEGIN { csum=4294967296-1051853566 } { csum=(csum + $1)%4294967296 } END {print csum}' );
1565
1566 if [ $(expr index "${csum}" 'e') -ne 0 ] ; then
1567 # Check if the ${csum} variable contains an 'e'.
1568 # "busybox awk" gives values like 3.20611e+09 instead of normal integer numbers.
1569 Syslinux_Msg="${Syslinux_Msg} The integrity of Syslinux couldn't be verified (install gawk).";
1570 elif [ ${csum} -ne 0 ] ; then
1571 Syslinux_Msg="${Syslinux_Msg} The integrity check of Syslinux failed.";
1572 return;
1573 fi
1574
1575
1576 if [ ${pa_version} -eq 4 ] ; then
1577 # Extended patch area size: 11*2 = 22 bytes
1578 epa_size='22';
1579
1580 # Get epa_advptroffset, epa_diroffset, epa_dirlen, epa_subvoloffset, epa_subvollen,
1581 # epa_secptroffset, epa_secptrcnt, epa_sect1ptr0, epa_sect1ptr1 and epa_raidpatch.
1582 epa_hexdump_format='1/2 "epa_advptroffset=%u; " 1/2 "epa_diroffset=%u; " 1/2 "epa_dirlen=%u; " 1/2 "epa_subvoloffset=%u; " 1/2 "epa_subvollen=%u; " 1/2 "epa_secptroffset=%u; " 1/2 "epa_secptrcnt=%u; " 1/2 "epa_sect1ptr0=%u; " 1/2 "epa_sect1ptr1=%u; " 1/2 "epa_raidpatch=%u; " 1/2 "epa_syslinuxbanner=%u;"';
1583
1584 eval $(hexdump -v -s ${pa_epaoffset} -n ${epa_size} -e "${epa_hexdump_format}" ${Tmp_Log});
1585
1586 # Get the Syslinux install directory.
1587 syslinux_dir=$(hexdump -v -e '"%_p"' -s ${epa_diroffset} -n ${epa_dirlen} ${Tmp_Log});
1588 syslinux_dir=${syslinux_dir%%\.*};
1589
1590 Syslinux_Msg="${Syslinux_Msg} ${syslinux_version:0:8} is installed in the ${syslinux_dir} directory.";
1591
1592
1593 # In Syslinux 4.04 and higher, the whole Syslinux banner is not in the first sector of ldlinux.sys.
1594 # Only the "SYSLINUX - version" string is still located in the first sector.
1595 # epa_syslinuxbanner points to the whole "SYSLINUX - version - date" string.
1596
1597 if [ ${epa_syslinuxbanner} -lt $(( ${pa_data_sectors} * 512 )) ] ; then
1598 # Get the "SYSLINUX - version - date" string.
1599 tmp=$(hexdump -v -e '"%_p"' -s $(( ${epa_syslinuxbanner} + 2 )) -n 100 ${Tmp_Log});
1600
1601
1602 # Check if we have Syslinux 4.04 or higher, which suppport the epa_syslinuxbanner field
1603 # by comparing the first 8 bytes ("SYSLINUX") of the Syslinux banner from sector 1 with
1604 # the 8 bytes to which epa_syslinuxbanner points.
1605
1606 if [ x"${tmp:0:8}" = x"${syslinux_version:0:8}" ] ; then
1607 syslinux_version="${tmp%%\.No DEFAULT*}";
1608
1609 # Overwrite the "boot sector type" variable, which was set before calling this function,
1610 # with a more exact Syslinux version number.
1611 BST="${syslinux_version}";
1612 fi
1613 fi
1614
1615
1616
1617 # ADV stuff starts here.
1618
1619 if [ ${pa_adv_sectors} -ne 2 ] ; then
1620 Syslinux_Msg="${Syslinux_Msg} There are ${pa_adv_sectors} ADV sectors instead of 2.";
1621 return;
1622 fi
1623
1624 # Get the ADV offset.
1625 ADVoffset=$(( pa_data_sectors * 512 ));
1626
1627 # Get the ADV.
1628 ADV_2SECTORS=$(hexdump -v -s ${ADVoffset} -n 1024 -e '/1 "%02x"' ${Tmp_Log});
1629
1630 # Check if the 2 ADV sectors are exactly the same.
1631 if [ "${ADV_2SECTORS:0:1024}" != "${ADV_2SECTORS:1024:1024}" ] ; then
1632 Syslinux_Msg="${Syslinux_Msg} The 2 ADV sectors are not the same (corrupt).";
1633 return;
1634 fi
1635
1636 # Check if the ADV area contains the ADV head and tail magic.
1637 if ( [ "${ADV_2SECTORS:0:8}" = "${ADV_MAGIC_HEAD}" ] && [ "${ADV_2SECTORS:1016:8}" = "${ADV_MAGIC_TAIL}" ] ) ; then
1638
1639 # Caculate the ADV checksum.
1640 ADV_calculated_checksum=$(hexdump -v -s $(( ${ADVoffset} + 8 )) -n $((512 - 3*4)) -e '/4 "%u\n"' ${Tmp_Log} \
1641 | awk 'BEGIN { csum='${ADV_MAGIC_CHECKSUM}' } { csum=(csum - $1 + 4294967296)%4294967296 } END { print csum }');
1642
1643 ADV_read_checksum=$(hexdump -s $(( ${ADVoffset} + 4 )) -n 4 -e '/4 "%u\n"' ${Tmp_Log});
1644
1645
1646 if [ ${ADV_calculated_checksum} -eq ${ADV_read_checksum} ] ; then
1647
1648 # Get the info stored in the ADV area:
1649 #
1650 # maximum 2 entries can be stored in the ADV, which have the following layout:
1651 # - byte 1 : tag ==> 0 = no entry, 1 = boot-once entry, 2 = menu-save entry
1652 # - byte 2 : tag_len ==> length of label string
1653 # - byte 3 - (3 + tag_len) : label ==> label name that will be used
1654
1655 # First entry starts a offset 8.
1656 ADVentry_offset=8;
1657
1658 until eval $(hexdump -s $(( ${ADVoffset} + ${ADVentry_offset} )) -n $((512 - 3*4)) \
1659 -e '1/1 "tag=%u; " 1/1 "tag_len=%u; label='\''" 498 "%_p"' ${Tmp_Log};
1660 printf "'");
1661 [ ${tag} -eq 0 ] ; do
1662
1663
1664 if [ ${tag_len} -gt 0 ] ; then
1665 label=${label:0:${tag_len}};
1666 fi
1667
1668 case ${tag} in
1669 1) Syslinux_Msg="${Syslinux_Msg} ${syslinux_version:0:8}'s ADV is set to boot label \"${label}\" next boot only.";;
1670 2) Syslinux_Msg="${Syslinux_Msg} ${syslinux_version:0:8}'s ADV is set to boot label \"${label}\" by default.";;
1671 esac
1672
1673 # Adjust the ADVentry_offset, so it points to the next entry.
1674 ADVentry_offset=$(( ${ADVentry_offset} + ${tag_len} + 2 ));
1675
1676 done
1677 else
1678 Syslinux_Msg="${Syslinux_Msg} The integrity check of the ADV area failed.";
1679 fi
1680 else
1681 Syslinux_Msg="${Syslinux_Msg} The ADV head and tail magic bytes were not found.";
1682 fi
1683 fi
1684
1685 return;
1686 fi
1687 done
1688
1689 # LDLINUX_MAGIC not found.
1690 Syslinux_Msg="${Syslinux_Msg} It is very unlikely that Syslinux is (still) installed. The second stage could not be found.";
1691
1692}
1693
1694
1695
1696## Grub Legacy ##
1697#
1698# Determine the embeded location of stage 2 in a stage 1 file,
1699# look for the stage 2 and, if found, determine the
1700# the location and the path of the embedded menu.lst.
1701
1702stage2_loc () {
1703 local stage1="$1" HI;
1704
1705 offset=$(hexdump -v -s 68 -n 4 -e '4 "%u"' "${stage1}");
1706 dr=$(hexdump -v -s 64 -n 1 -e '1/1 "%u"' "${stage1}");
1707 pa='T';
1708 Grub_Version='';
1709
1710 for HI in ${!HDName[@]}; do
1711 hdd=${HDName[${HI}]};
1712
1713 if [ ${offset} -lt ${HDSize[HI]} ] ; then
1714 tmp=$(dd if=${hdd} skip=${offset} count=1 2>> ${Trash} | hexdump -v -n 4 -e '"%x"');
1715
1716 if [[ "${tmp}" = '3be5652' || "${tmp}" = 'bf5e5652' ]] ; then
1717 # stage2 files were found.
1718 dd if=${hdd} skip=$((offset+1)) count=1 of=${Tmp_Log} 2>> ${Trash};
1719 pa=$(hexdump -v -s 10 -n 1 -e '"%d"' ${Tmp_Log});
1720 stage2_hdd=${hdd};
1721 Grub_String=$(hexdump -v -s 18 -n 94 -e '"%_u"' ${Tmp_Log});
1722 Grub_Version=$(echo ${Grub_String} | sed -e 's/nul[^$]*//');
1723 BL=${BL}${Grub_Version};
1724 menu=$(echo ${Grub_String} | sed -e 's/[^\/]*//' -e 's/nul[^$]*//');
1725 menu=${menu%% *};
1726 fi
1727 fi
1728 done
1729
1730 dr=$((${dr}-127));
1731 Stage2_Msg="looks at sector ${offset}";
1732
1733 if [ "${dr}" -eq 128 ] ; then
1734 Stage2_Msg="${Stage2_Msg} of the same hard drive";
1735 else
1736 Stage2_Msg="${Stage2_Msg} on boot drive #${dr}";
1737 fi
1738
1739 Stage2_Msg="${Stage2_Msg} for the stage2 file";
1740
1741 if [ "${pa}" = "T" ] ; then
1742 # no stage 2 file found.
1743 Stage2_Msg="${Stage2_Msg}, but no stage2 files can be found at this location.";
1744 else
1745 pa=$((${pa}+1));
1746 Stage2_Msg="${Stage2_Msg}. A stage2 file is at this location on ${stage2_hdd}. Stage2 looks on";
1747
1748 if [ "${pa}" -eq 256 ] ; then
1749 Stage2_Msg="${Stage2_Msg} the same partition";
1750 else
1751 Stage2_Msg="${Stage2_Msg} partition #${pa}";
1752 fi
1753
1754 Stage2_Msg="${Stage2_Msg} for ${menu}.";
1755 fi
1756}
1757
1758
1759
1760## Grub2 ##
1761#
1762# Determine the (embeded) location of core.img for a Grub2 boot.img file,
1763# determine the path of the grub2 directory and look for an embedded config file.
1764#
1765
1766grub2_info () {
1767 local stage1="$1" hdd="$2" grub2_version="$3";
1768
1769 local sector_offset drive_offset directory_offset sector_nr drive_nr drive_nr_hex;
1770 local partition core_dir embedded_config HI magic core_img_found=0 embedded_config_found=0;
1771 local total_module_size kernel_image_size compressed_size offset_lzma lzma_uncompressed_size;
1772 local grub_module_info_offset grub_module_magic grub_modules_offset grub_modules_size;
1773 local grub_module_type grub_module_size grub_module_header_offset grub_modules_end_offset;
1774
1775
1776 case "${grub2_version}" in
1777 1.96) sector_offset='68'; drive_offset='76'; directory_offset='553';;
1778 1.97) sector_offset='92'; drive_offset='100'; directory_offset='540';;
1779 1.99) sector_offset='92'; drive_offset='100';;
1780 esac
1781
1782 # Offset to core.img (in sectors).
1783 sector_nr=$(hexdump -v -s ${sector_offset} -n 4 -e '4 "%u"' "${stage1}" 2>> ${Trash});
1784
1785 # BIOS drive number on which grub2 looks for its second stage (=core.img):
1786 # - "0xff" means that grub2 will use the BIOS drive number passed via the DL register.
1787 # - if this value isn't "0xff", that value will used instead.
1788 drive_nr_hex=$(hexdump -v -s ${drive_offset} -n 1 -e '"0x%02x"' "${stage1}" 2>> ${Trash});
1789 drive_nr=$(( ${drive_nr_hex} - 127 ));
1790
1791 Grub2_Msg="looks at sector ${sector_nr} of the same hard drive for core.img";
1792
1793 for HI in ${!HDName[@]} ; do
1794 # If the drive name passed to grub2_info matches the drive name of the current
1795 # value of HDName, see if the sector offset to core.img is smaller than the
1796 # total number of sectors of that drive.
1797
1798 if [ ${hdd} = ${HDName[${HI}]} ] ; then
1799 if [ ${sector_nr} -lt ${HDSize[HI]} ] ; then
1800
1801 if [ ${sector_nr} -eq 1 ] ; then
1802 # Use "file/partition/drive" passed to grub2_info directly.
1803 dd if="${stage1}" of=${core_img_file} skip=${sector_nr} count=1024 2>> ${Trash};
1804 else
1805 # Use "hdd" passed to grub2_info.
1806 dd if="${hdd}" of=${core_img_file} skip=${sector_nr} count=1024 2>> ${Trash};
1807 fi
1808
1809 magic=$(hexdump -v -n 4 -e '/1 "%02x"' ${core_img_file});
1810
1811 if ( [ "${magic}" = '5256be1b' ] || [ "${magic}" = '52e82801' ] ) ; then
1812 # core.img file was found.
1813 core_img_found=1;
1814
1815 if [ ${grub2_version} = '1.99' ] ; then
1816
1817 # For Grub2 (v1.99), the core_dir is just at the beginning of the compressed part of core.img:
1818 #
1819 # Get grub_total_module_size : byte 0x208-0x20b of embedded core.img ==> byte 520
1820 # Get grub_kernel_image_size : byte 0x20c-0x20f of embedded core.img ==> byte 524
1821 # Get grub_compressed_size : byte 0x210-0x213 of embedded core.img ==> byte 528
1822 # Get grub_install_dos_part : byte 0x214-0x218 of embedded core.img ==> byte 532 --> only 1 byte needed (partition)
1823
1824 eval $(hexdump -v -s 520 -n 13 -e '1/4 "total_module_size=%u; " 1/4 "kernel_image_size=%u; " 1/4 "compressed_size=%u; " 1 "partition=%d;"' ${core_img_file});
1825
1826
1827 # Scan for "d1 e9 df fe ff ff 00 00": last 8 bytes of lzma_decode to find the offset of the lzma_stream.
1828 eval $(hexdump -v -n ${kernel_image_size} -e '1/1 "%02x"' ${core_img_file} | \
1829 ${AWK} '{ found_at=match($0, "d1e9dffeffff0000" ); if (found_at == "0") { print "offset_lzma=0" } \
1830 else { print "offset_lzma=" ((found_at - 1 ) / 2 ) + 8 } }');
1831
1832 # Do we have xz or lzma installed?
1833 if [ "${UNLZMA}" != 'none' ] ; then
1834 if [ ${offset_lzma} -ne 0 ] ; then
1835
1836 # Correct the offset to the lzma stream, when 8 subsequent bytes of zeros are at the start of this offset,
1837 if [ $(hexdump -v -s ${offset_lzma} -n 8 -e '1/1 "%02x"' ${core_img_file}) = '0000000000000000' ] ; then
1838 offset_lzma=$(( ${offset_lzma} + 8 ));
1839 fi
1840
1841 # Calculate the uncompressed size to which the compressed lzma stream needs to be expanded.
1842 lzma_uncompressed_size=$(( ${total_module_size} + ${kernel_image_size} - ${offset_lzma} + 512 ));
1843
1844 # Make lzma header (13 bytes): ${lzma_uncompressed_size} must be displayed in little endian format.
1845 printf '\x5d\x00\x00\x01\x00'$( printf '%08x' $((${total_uncompressed_size} - ${offset_lzma} + 512 )) | awk '{printf "\\x%s\\x%s\\x%s\\x%s", substr($0,7,2), substr($0,5,2), substr($0,3,2), substr($0,1,2)}' )'\x00\x00\x00\x00' > ${Tmp_Log};
1846
1847 # Get lzma_stream, add it after the lzma header and decompress it.
1848 dd if=${core_img_file} bs=${offset_lzma} skip=1 count=$((${lzma_uncompressed_size} / ${offset_lzma} + 1)) 2>> ${Trash} \
1849 | cat ${Tmp_Log} - | ${UNLZMA} > ${core_img_file_unlzma};
1850
1851 # Get core dir.
1852 core_dir=$( hexdump -v -n 64 -e '"%_c"' ${core_img_file_unlzma} );
1853 # Remove "\0"s at the end.
1854 core_dir="${core_dir%%\\0*}";
1855
1856
1857 # Offset of the grub_module_info structure in the uncompressed part.
1858 grub_module_info_offset=$(( ${kernel_image_size} - ${offset_lzma} + 512 ));
1859
1860 eval $(hexdump -v -n 12 -s ${grub_module_info_offset} -e '"grub_module_magic=" 4/1 "%_c" 1/4 "; grub_modules_offset=%u; " 1/4 "grub_modules_size=%u;"' ${core_img_file_unlzma});
1861
1862 # Check for the existence of the grub_module_magic.
1863 if [ x"${grub_module_magic}" = x'mimg' ] ; then
1864 # Embedded grub modules found.
1865 grub_modules_end_offset=$(( ${grub_module_info_offset} + ${grub_modules_size} ));
1866 grub_module_header_offset=$(( ${grub_module_info_offset} + ${grub_modules_offset} ));
1867
1868 # Traverse through the list of modules and check if it is a config module.
1869 while [ ${grub_module_header_offset} -lt ${grub_modules_end_offset} ] ; do
1870
1871 eval $(hexdump -v -n 8 -s ${grub_module_header_offset} -e '1/4 "grub_module_type=%u; " 1/4 "grub_module_size=%u;"' ${core_img_file_unlzma});
1872
1873 if [ ${grub_module_type} -eq 2 ] ; then
1874 # This module is an embedded config file.
1875 embedded_config_found=1;
1876
1877 embedded_config=$( hexdump -v -n $(( ${grub_module_size} - 8 )) -s $(( ${grub_module_header_offset} + 8 )) -e '"%_c"' ${core_img_file_unlzma} );
1878 # Remove "\0" at the end.
1879 embedded_config=$( printf "${embedded_config%\\0}" );
1880
1881 break;
1882 fi
1883
1884 grub_module_header_offset=$(( ${grub_module_header_offset} + ${grub_module_size} ));
1885
1886 done
1887 fi
1888 fi
1889 else
1890 # When xz or lzma isn't available, we can't get the core_dir, but we still can show the other info.
1891 core_dir='??';
1892
1893 echo 'To be able to see for which directory Grub2 (v1.99) looks for, install "xz" or "lzma".' >&2;
1894 fi
1895
1896 else
1897 # Grub2 (v1.96 and v1.97-1.98).
1898 partition=$(hexdump -v -s 532 -n 1 -e '"%d"' ${core_img_file});
1899 core_dir=$(hexdump -v -s ${directory_offset} -n 64 -e '"%_u"' ${core_img_file} | sed 's/nul[^$]*//');
1900 fi
1901 fi
1902 fi
1903 fi
1904 done
1905
1906
1907 if [ ${core_img_found} -eq 0 ] ; then
1908 # core.img not found.
1909 Grub2_Msg="${Grub2_Msg}, but core.img can not be found at this location";
1910 else
1911 # core.img found.
1912
1913 if [ "${drive_nr_hex}" != '0xff' ] ; then
1914 Grub2_Msg="${Grub2_Msg}. Grub2 is configured to load core.img from BIOS drive ${drive_nr} (${drive_nr_hex}) instead of using the boot drive passed by the BIOS";
1915 fi
1916
1917 Grub2_Msg="${Grub2_Msg}. core.img is at this location"
1918
1919 partition=$(( ${partition} + 1 ));
1920
1921 if [ ${embedded_config_found} -eq 0 ] ; then
1922 # No embedded config file found.
1923
1924 if [ ${partition} -eq 255 ] ; then
1925 Grub2_Msg="${Grub2_Msg} and looks for ${core_dir} on this drive";
1926 else
1927 Grub2_Msg="${Grub2_Msg} and looks in partition ${partition} for ${core_dir}";
1928 fi
1929
1930 else
1931 # Embedded config file found.
1932
1933 Grub2_Msg=$(printf "${Grub2_Msg} and uses an embedded config file:\n\n--------------------------------------------------------------------------------\n${embedded_config}\n--------------------------------------------------------------------------------\n");
1934
1935 fi
1936 fi
1937}
1938
1939
1940
1941## Get embedded menu for grub4dos (grldr/grub.exe) and wee (installed in the MBR). ##
1942#
1943# Function arguments:
1944#
1945# - arg 1: source = file (grub4dos) / device (WEE)
1946# - arg 2: titlename = first part of the title that needs to be displayed
1947#
1948
1949get_embedded_menu () {
1950 local source=$1 titlename=$2;
1951
1952 # Check if magic bytes that go before the embedded menu, are present.
1953 offset_menu=$(dd if="${source}" count=4 bs=128k 2>> ${Trash} | hexdump -v -e '/1 "%02x"' | grep -b -o 'b0021ace000000000000000000000000');
1954
1955 if [ -n "${offset_menu}" ] ; then
1956 # Magic found.
1957 titlebar_gen "${titlename}" " embedded menu";
1958 echo '--------------------------------------------------------------------------------' >> "${Log1}";
1959
1960 # Calcutate the exact offset to the embedded menu.
1961 offset_menu=$(( ( ${offset_menu%:*} / 2 ) + 16 ));
1962 dd if="${source}" count=1 skip=1 bs=${offset_menu} 2>> ${Trash} | ${AWK} 'BEGIN { RS="\0" } { if (NR == 1) print $0 }' >> "${Log1}";
1963
1964 echo '--------------------------------------------------------------------------------' >> "${Log1}";
1965 fi
1966}
1967
1968
1969
1970## Show the location (offset) of a file on a disk ##
1971#
1972# Function arguments:
1973#
1974# - arg 1: filename1
1975# - arg 2: filename2
1976# - arg 3: filename3
1977# - ......
1978#
1979
1980last_block_of_file () {
1981 local display='0';
1982
1983 # Remove an existing ${Tmp_Log} log.
1984 rm -f ${Tmp_Log};
1985
1986 # "$@" contains all function arguments (filenames).
1987 for file in $(ls "$@" 2>> ${Trash}) ; do
1988 if [[ -f ${file} ]] && [[ -s ${file} ]] && FileNotMounted "${mountname}/${file}" "${mountname}" ; then
1989
1990 # There are at least 2 versions of filefrag.
1991 # For both versions, we can get the blocksize and the location of the block
1992 # of the file that is the farest away from the beginning of the disk.
1993 # For the newer version, we can also get the number of file fragments.
1994
1995 eval $(filefrag -v "${file}" \
1996 | ${AWK} -F ' ' 'BEGIN { blocksize=0; expected=0; extents=1; ext_ind=0; last_ext_loc=0; ext_length=0; filefrag_old="false"; last_block=0 } \
1997 { if ( $1 == "Blocksize" ) { blocksize=$6; filefrag_old="true" }; \
1998 if ( filefrag_old == "true" ) { \
1999 if ( $1$2 ~ "LastBlock:" ) { print $3 }; \
2000 } else { \
2001 if ( $(NF-1) == "blocksize" ) { blocksize = substr($NF,0,length($NF) - 1) }; \
2002 if ( expected != 0 && ext_ind == $1 ) { \
2003 ext_ind += 1; \
2004 if ( last_ext_loc < $3 ) { \
2005 last_ext_loc = $3; \
2006 if ( substr($0, expected, 1) == " " ) { \
2007 ext_length = $4; } \
2008 else { \
2009 ext_length = $5; \
2010 } \
2011 } \
2012 } \
2013 if ($4 == "expected") { \
2014 expected= index($0,"expected") + 7; }; \
2015 if ($3 == "extents") { \
2016 extents=$2; \
2017 } \
2018 } } END { \
2019 if ( filefrag_old == "true" ) { \
2020 bogus = last_block; \
2021 EndByte = last_block * blocksize + 512 * '${start}'; \
2022 printf "BlockSize=" blocksize "; Filefrag_Old=" filefrag_old "; " \
2023 } else { \
2024 bogus = last_ext_loc; \
2025 EndByte = ( last_ext_loc + ext_length ) * blocksize + 512 * '${start}'; \
2026 printf "BlockSize=" blocksize "; Fragments=" extents "; Filefrag_Old=" filefrag_old "; " \
2027 } \
2028 if ( ( bogus == 0) || ( extents == 0 ) ) { \
2029 printf "EndGiByte=??; EndGByte=??;" \
2030 } else { \
2031 printf "EndGiByte=%.9f; EndGByte=%.9f;", EndByte / 1024 ^ 3, EndByte / 1000 ^ 3; \
2032 } \
2033 }');
2034
2035 if [ "${BlockSize}" -ne 0 ] ; then
2036 if [ "${Filefrag_Old}" = "true" ] ; then
2037 # Old version of filefrag.
2038 printf "%14s = %-14s %s\n" "${EndGiByte}" "${EndGByte}" "${file}" >> ${Tmp_Log};
2039 else
2040 # New version of filefrag.
2041 printf "%14s = %-14s %-45s %2s\n" "${EndGiByte}" "${EndGByte}" "${file}" "${Fragments}" >> ${Tmp_Log};
2042 fi
2043 fi
2044
2045 # If any of the files passed as arguments, is found, return 1.
2046 display=1;
2047 fi
2048 done
2049
2050 return ${display};
2051}
2052
2053
2054
2055## Get_Partition_Info search a partition for information relevant for booting. ##
2056#
2057# Function arguments:
2058#
2059# - arg 1: log = local version of RESULT.txt
2060# - arg 2: log1 = local version of log1
2061# - arg 3: part = device for the partition
2062# - arg 4: name = descriptive name for the partition
2063# - arg 5: mountname = path where partition will be mounted.
2064# - arg 6: kind = kind of the partition
2065# - arg 7: start = starting sector of the partition
2066# - arg 8: end = ending sector of the partition
2067# - arg 9: system = system of the partition
2068# - arg 10: PI = PI of the partition, (equal to "", if not a regular partition)
2069
2070Get_Partition_Info() {
2071 local Log="$1" Log1="$2" part="$3" name="$4" mountname="$5" kind="$6" start="$7" end="$8" system="$9" PI="${10}";
2072 local line size=$((end-start)) BST='' BSI='' BFI='' OS='' BootFiles='' Bytes80_to_83='' Bytes80_to_81='' offset='';
2073 local offset_menu='' part_no_mount=0 com32='' com32_version='';
2074
2075
2076 echo "Searching ${name} for information... ";
2077 PrintBlkid ${part};
2078
2079 # Type of filesystem according to blkid.
2080 type=$(BlkidTag ${part} TYPE);
2081
2082 [ "${system}" = 'BIOS Boot partition' ] && type='BIOS Boot partition';
2083 [ -n ${PI} ] && FileArray[${PI}]=${type};
2084
2085 # Display partition subtitle of 80 characters width.
2086 line='________________________________________________________________________________';
2087 line=${line:$(( ${#name} + 2 ))};
2088
2089 printf '%s: %s\n\n' "${name}" "${line}" >> "${Log}";
2090
2091 # Directory where the partition will be mounted.
2092 mkdir -p "${mountname}";
2093
2094 # Check for extended partion.
2095 if ( [ "${kind}" = 'E' ] && [ x"${type}" = x'' ] ) ; then
2096 type='Extended Partition';
2097
2098 # Don't display the error message from blkid for extended partition.
2099 cat ${Tmp_Log} >> ${Trash};
2100 else
2101 cat ${Tmp_Log} >&2;
2102 fi
2103
2104 # Display the File System Type.
2105 echo " File system: ${type}" >> "${Log}";
2106
2107 # Get bytes 0x80-0x83 of the Volume Boot Record (VBR).
2108 Bytes80_to_83=$(hexdump -v -n 4 -s $((0x80)) -e '4/1 "%02x"' ${part});
2109
2110 # Get bytes 0x80-0x81 of VBR to identify Boot sectors.
2111 Bytes80_to_81="${Bytes80_to_83:0:4}";
2112
2113
2114 case ${Bytes80_to_81} in
2115 0069) BST='ISOhybrid (Syslinux 3.72-3.73)';;
2116 010f) BST='HP Recovery';;
2117 019d) BST='BSD4.4: FAT32';;
2118 0211) BST='Dell Utility: FAT16';;
2119 0488) BST="Grub2's core.img";;
2120 0689) BST='Syslinux 3.00-3.52';
2121 syslinux_info ${part};
2122 BSI="${BSI} ${Syslinux_Msg}";;
2123 7405) BST='Windows 7: FAT32';;
2124 0734) BST='Dos_1.0';;
2125 0745) BST='Windows Vista: FAT32';;
2126 089e) BST='MSDOS5.0: FAT16';;
2127 08cd) BST='Windows XP: NTFS';;
2128 0b60) BST='Dell Utility: FAT16';;
2129 0bd0) BST='MSWIN4.1: FAT32';;
2130 0e00) BST='Dell Utility: FAT16';;
2131 0fb6) BST='ISOhybrid with partition support (Syslinux 3.82-3.86)';;
2132 2a00) BST='ReactOS';;
2133 2d5e) BST='Dos 1.1';;
2134 31c0) BST='Syslinux 4.03 or higher';
2135 syslinux_info ${part} '4.03';
2136 BSI="${BSI} ${Syslinux_Msg}";;
2137 31d2) BST="Grub2's core.img";;
2138 3a5e) BST='Recovery: FAT32';;
2139 407c) BST='ISOhybrid (Syslinux 3.82-4.04)';;
2140 4216) BST='Grub4Dos: NTFS';;
2141 4445) BST='Dell Restore: FAT32';;
2142 55aa) case ${Bytes80_to_83} in
2143 55aa750a) BST='Grub4Dos: FAT32';;
2144 55aa* ) BST='Windows Vista/7: NTFS';; # 55aa7506 = Windows Vista
2145 esac;;
2146 55cd) BST='FAT32';;
2147 5626) BST='Grub4Dos: EXT2/3/4';;
2148 638b) BST='Freedos: FAT32';;
2149 6616) BST='FAT16';;
2150 696e) BST='FAT16';;
2151 6974) BST='BootIt: FAT16';;
2152 6f65) BST='BootIt: FAT16';;
2153 6f6e) BST='-';; # 'MSWIN4.1: Fat 32'
2154 6f74) BST='FAT32';;
2155 7815) case ${Bytes80_to_83} in
2156 7815b106) BST='Syslinux 3.53-3.86';
2157 syslinux_info ${part};
2158 BSI="${BSI} ${Syslinux_Msg}";;
2159 7815* ) BST='FAT32';;
2160 esac;;
2161 7cc6) BST='MSWIN4.1: FAT32';;
2162 # 7cc6) BST='Win_98';;
2163 7e1e) BST='Grub4Dos: FAT12/16';;
2164 8a56) BST='Acronis SZ: FAT32';;
2165 83e1) BST='ISOhybrid with partition support (Syslinux 4.00-4.04)';;
2166 8ec0) BST='Windows XP: NTFS';;
2167 8ed0) BST='Dell Recovery: FAT32';;
2168 b106) BST='Syslinux 4.00-4.02';
2169 syslinux_info ${part};
2170 BSI="${BSI} ${Syslinux_Msg}";;
2171 b600) BST='Dell Utility: FAT16';;
2172 b6c6) BST='ISOhybrid with partition support (Syslinux 3.81)';;
2173 b6d1) BST='Windows XP: FAT32';;
2174 e2f7) BST='FAT32, Non Bootable';;
2175 e879) BST='ISOhybrid (Syslinux 3.74-3.80)';;
2176 e9d8) BST='Windows Vista/7: NTFS';;
2177 f6f6) BST='- (cleared BS by FDISK)';;
2178 fa33) BST='Windows XP: NTFS';;
2179 fbc0) BST='ISOhybrid (Syslinux 3.81)';;
2180
2181 ## If Grub or Grub 2 is in the boot sector, investigate the embedded information. ##
2182 48b4) BST='Grub2 (v1.96)';
2183 grub2_info ${part} ${drive} '1.96';
2184 BSI="${BSI} Grub2 (v1.96) is installed in the boot sector of ${name} and ${Grub2_Msg}.";;
2185 7c3c) BST='Grub2 (v1.97-1.98)';
2186 grub2_info ${part} ${drive} '1.97';
2187 BSI="${BSI} Grub2 (v1.97-1.98) is installed in the boot sector of ${name} and ${Grub2_Msg}.";;
2188 0020) BST='Grub2 (v1.99)';
2189 grub2_info ${part} ${drive} '1.99';
2190 BSI="${BSI} Grub2 (v1.99) is installed in the boot sector of ${name} and ${Grub2_Msg}.";;
2191 aa75 | 5272) BST='Grub Legacy';
2192 stage2_loc ${part};
2193 BSI="${BSI} Grub Legacy (v${Grub_Version}) is installed in the boot sector of ${name} and ${Stage2_Msg}";;
2194
2195 ## If Lilo is in the VBR, look for map file ##
2196 8053) BST='LILO';
2197 # 0x20-0x23 contains the offset of /boot/map.
2198 offset=$(hexdump -v -s 32 -n 4 -e '"%u"' ${part});
2199
2200 BSI="${BSI} LILO is installed in boot sector of ${part} and looks at sector ${offset} of ${drive} for the \"map\" file,";
2201
2202 # check whether offset is on the hard drive.
2203 if [ ${offset} -lt ${size} ] ; then
2204 tmp=$(dd if=${drive} skip=${offset} count=1 2>> ${Trash} | hexdump -v -s 508 -n 4 -e '"%_p"');
2205
2206 if [ "${tmp}" = 'LILO' ] ; then
2207 BSI="${BSI} and the \"map\" file was found at this location.";
2208 else
2209 BSI="${BSI} but the \"map\" file was not found at this location.";
2210 fi
2211 else
2212 BSI="${BSI} but the \"map\" file was not found at this location.";
2213 fi;;
2214
2215 0000) # If the first two bytes are zero, the boot sector does not contain any boot loader.
2216 BST='-';;
2217
2218 *) BST='Unknown';
2219 printf "Unknown BootLoader on ${name}\n\n" >> ${Unknown_MBR};
2220 hexdump -n 512 -C ${part} >> ${Unknown_MBR};
2221 echo >> ${Unknown_MBR};;
2222 esac
2223
2224 # Display the boot sector type.
2225 echo " Boot sector type: ${BST}" >> "${Log}";
2226
2227
2228
2229 ## Investigate the Boot Parameter Block (BPB) of a NTFS partition. ##
2230
2231 if [ "${type}" = 'ntfs' ] ; then
2232 offset=$(hexdump -v -s 28 -n 4 -e '"%u"' ${part});
2233 BPB_Part_Size=$(hexdump -v -s 40 -n 4 -e '"%u"' ${part})
2234 Comp_Size=$(( (${BPB_Part_Size} - ${size}) / 256 ))
2235 SectorsPerCluster=$(hexdump -v -s 13 -n 1 -e '"%d"' ${part});
2236 MFT_Cluster=$(hexdump -v -s 48 -n 4 -e '"%d"' ${part});
2237 MFT_Sector=$(( ${MFT_Cluster} * ${SectorsPerCluster} ));
2238
2239 # Track=$(hexdump -v -s 24 -n 2 -e '"%u"' ${part})'' # Number of sectors per track.
2240 # Heads=$(hexdump -v -s 26 -n 2 -e '"%u"' ${part})'' # Number of heads.
2241 #
2242 # if [ "${Heads}" -ne 255 ] || [ "${Track}" -ne 63 ] ; then
2243 # BSI="${BSI} Geometry: ${Heads} Heads and ${Track} sectors per Track."
2244 # fi
2245
2246 if [[ "${MFT_Sector}" -lt "${size}" ]] ; then
2247 MFT_FILE=$(dd if=${part} skip=${MFT_Sector} count=1 2>> ${Trash} | hexdump -v -n 4 -e '"%_u"');
2248 else
2249 MFT_FILE='';
2250 fi
2251
2252 MFT_Mirr_Cluster=$(hexdump -v -s 56 -n 4 -e '"%d"' ${part});
2253 MFT_Mirr_Sector=$(( ${MFT_Mirr_Cluster} * ${SectorsPerCluster} ));
2254
2255 if [[ "${MFT_Mirr_Sector}" -lt "${size}" ]] ; then
2256 MFT_Mirr_FILE=$(dd if=${part} skip=${MFT_Mirr_Sector} count=1 2>> ${Trash} | hexdump -v -n 4 -e '"%_u"');
2257 else
2258 MFT_Mirr_FILE='';
2259 fi
2260
2261 if ( [ "${offset}" -eq "${start}" ] && [ "${MFT_FILE}" = 'FILE' ] && [ "${MFT_Mirr_FILE}" = 'FILE' ] && [ "${Comp_Size}" -eq 0 ] ) ; then
2262 BSI="${BSI} No errors found in the Boot Parameter Block.";
2263 else
2264 if [[ "${offset}" -ne "${start}" ]] ; then
2265 BSI="${BSI} According to the info in the boot sector, ${name} starts at sector ${offset}.";
2266
2267 if [[ "${offset}" -ne 63 && "${offset}" -ne 2048 && "${offset}" -ne 0 || "${kind}" != 'L' ]] ; then
2268 BSI="${BSI} But according to the info from fdisk, ${name} starts at sector ${start}.";
2269 fi
2270 fi
2271
2272 if [[ "${MFT_FILE}" != "FILE" ]] ; then
2273 BSI="${BSI} The info in boot sector on the starting sector of the MFT is wrong.";
2274 printf "MFT Sector of ${name}\n\n" >> ${Unknown_MBR};
2275 dd if=${part} skip=${MFT_Sector} count=1 2>> ${Trash} | hexdump -C >> ${Unknown_MBR};
2276 fi
2277
2278 if [[ "${MFT_Mirr_FILE}" != 'FILE' ]] ; then
2279 BSI="${BSI} The info in the boot sector on the starting sector of the MFT Mirror is wrong.";
2280 fi
2281
2282 if [[ "${Comp_Size}" -ne 0 ]] ; then
2283 BSI="${BSI} According to the info in the boot sector, ${name} has ${BPB_Part_Size} sectors, but according to the info from fdisk, it has ${size} sectors.";
2284 fi
2285 fi
2286 fi
2287
2288
2289
2290 ## Investigate the Boot Parameter Block (BPB) of (some) FAT partition. ##
2291
2292 # Identifies Fat Bootsectors which are used for booting.
2293 # if [[ "${Bytes80_to_81}" = '7cc6' || "${Bytes80_to_81}" = '7815' || "${Bytes80_to_81}" = 'b6d1' || "${Bytes80_to_81}" = '7405' || "${Bytes80_to_81}" = '6974' || "${Bytes80_to_81}" = '0bd0' || "${Bytes80_to_81}" = '089e' ]] ;
2294
2295 if [[ "${type}" = 'vfat' ]] ; then
2296 offset=$(hexdump -v -s 28 -n 4 -e '"%d\n"' ${part}); # Starting sector the partition according to BPB.
2297 BPB_Part_Size=$(hexdump -v -s 32 -n 4 -e '"%d"' ${part}); # Partition size in sectors according to BPB.
2298 Comp_Size=$(( (BPB_Part_Size - size)/256 )) # This number will be unequal to zero, if the 2
2299 # partions sizes differ by more than 255 sectors.
2300
2301 #Track=$(hexdump -v -s 24 -n 2 -e '"%u"' ${part})'' # Number of sectors per track.
2302 #Heads=$(hexdump -v -s 26 -n 2 -e '"%u"' ${part})'' # Number of heads
2303 #if [[ "${Heads}" -ne 255 || "${Track}" -ne 63 ]] ; then # Checks for an usual geometry.
2304 # BSI=$(echo ${BSI}" "Geometry: ${Heads} Heads and ${Track} sectors per Track.) ### Report unusal geometry
2305 #fi;
2306
2307 # Check whether Partitons starting sector and the Partition Size of BPB and fdisk agree.
2308 if [[ "${offset}" -eq "${start}" && "${Comp_Size}" -eq "0" ]] ; then
2309 BSI="${BSI} No errors found in the Boot Parameter Block."; # If they agree.
2310 else # If they don't agree.
2311 if [[ "${offset}" -ne "${start}" ]] ; then # If partition starting sector disagrees.
2312 # Display the starting sector according to the BPB.
2313 BSI="${BSI} According to the info in the boot sector, ${name} starts at sector ${offset}.";
2314
2315 # Check whether partition is a logcial partition and if its starting sector value is a 63 or 2048.
2316 if [[ "${offset}" -ne "63" && "${offset}" -ne "2048" || "${kind}" != "L" ]] ; then
2317 # If not, display starting sector according to fdisk.
2318 BSI="${BSI} But according to the info from fdisk, ${name} starts at sector ${start}.";
2319 else
2320 # This is quite common occurence, and only matters if one tries to boot Windows from a logical partition.
2321 BSI="${BSI} But according to the info from fdisk, ${name} starts at sector ${start}. \"63\" and \"2048\" are quite common values for the starting sector of a logical partition and they only need to be fixed when you want to boot Windows from a logical partition.";
2322 fi
2323 fi
2324
2325 # If partition sizes from BPB and FDISK differ by more than 255 sector, display both sizes.
2326 if [[ "${Comp_Size}" -ne "0" ]] ; then
2327 BSI="${BSI} According to the info in the boot sector, ${name} has ${BPB_Part_Size} sectors.";
2328
2329 if [[ "$BPB_Part_Size" -ne 0 ]] ; then
2330 BSI="${BSI}. But according to the info from the partition table, it has ${size} sectors.";
2331 fi # Don't display a warning message in the common case BPB_Part_Size=0.
2332 fi
2333 fi # End of BPB Error if-then-else.
2334 fi # End of Investigation of the BPB of vfat partitions.
2335
2336
2337
2338 ## Display boot sector info. ##
2339
2340 printf ' Boot sector info: ' >> "${Log}";
2341 printf "${BSI}\n" | fold -s -w 55 | sed -e '/^-------------------------$/ d' -e '2~1s/.*/ &/' >> "${Log}";
2342
2343
2344
2345
2346 ## Exclude partitions which contain no information, or which we (currently) don't know how to accces. ##
2347
2348 case "${type}" in
2349 'BIOS Boot partition' ) part_no_mount=1;;
2350 'crypto_LUKS' ) part_no_mount=1;;
2351 'Extended Partition' ) part_no_mount=1;;
2352 'linux_raid_member' ) part_no_mount=1;;
2353 'LVM2_member' ) part_no_mount=1;;
2354 'swap' ) part_no_mount=1;;
2355 'unknown volume type' ) part_no_mount=1;;
2356 esac
2357
2358 if [ "${part_no_mount}" -eq 0 ] ; then
2359
2360 # Look for a mount point of the current partition.
2361 # If multiple mount points are found, use the one with the shortest pathname.
2362 CheckMount=$(mount | ${AWK} -F "${TAB}" '$0 ~ "^'${part}' " { sub(" on ", "\t", $0); sub(" type ", "\t", $0); print $2 }' | sort | ${AWK} '{ print $0; exit}');
2363
2364 # Check whether partition is already mounted.
2365 if [ x"${CheckMount}" != x'' ] ; then
2366 if [ "${CheckMount}" = "/" ] ; then
2367 mountname='';
2368 else
2369 # If yes, use the existing mount point.
2370 mountname="${CheckMount}";
2371 fi
2372 fi
2373
2374 # Try to mount the partition.
2375 if [ x"${CheckMount}" != x'' ] || mount -r -t "${type}" ${part} "${mountname}" 2>> ${Mount_Error} \
2376 || ( [ "${type}" = ntfs ] && ntfs-3g -o ro ${part} "${mountname}" 2>> ${Mount_Error} ) ; then
2377
2378 # If partition is mounted, try to identify the Operating System (OS) by looking for files specific to the OS.
2379 OS='';
2380
2381 grep -q "W.i.n.d.o.w.s. .V.i.s.t.a" "${mountname}"/{windows,Windows,WINDOWS}/{System32,system32}/{Winload,winload}.exe 2>> ${Trash} && OS='Windows Vista';
2382
2383 grep -q "W.i.n.d.o.w.s. .7" "${mountname}"/{windows,Windows,WINDOWS}/{System32,system32}/{Winload,winload}.exe 2>> ${Trash} && OS='Windows 7';
2384
2385 for WinOS in 'MS-DOS' 'MS-DOS 6.22' 'MS-DOS 6.21' 'MS-DOS 6.0' 'MS-DOS 5.0' 'MS-DOS 4.01' 'MS-DOS 3.3' 'Windows 98' 'Windows 95'; do
2386 grep -q "${WinOS}" "${mountname}"/{IO.SYS,io.sys} 2>> ${Trash} && OS="${WinOS}";
2387 done
2388
2389 [ -s "${mountname}/Windows/System32/config/SecEvent.Evt" ] || [ -s "${mountname}/WINDOWS/system32/config/SecEvent.Evt" ] || [ -s "${mountname}/WINDOWS/system32/config/secevent.evt" ] || [ -s "${mountname}/windows/system32/config/secevent.evt" ] && OS='Windows XP';
2390
2391 [ -s "${mountname}/ReactOS/system32/config/SecEvent.Evt" ] && OS='ReactOS';
2392
2393 [ -s "${mountname}/etc/issue" ] && OS=$(sed -e 's/\\. //g' -e 's/\\.//g' -e 's/^[ \t]*//' "${mountname}"/etc/issue);
2394
2395 [ -s "${mountname}/etc/slackware-version" ] && OS=$(sed -e 's/\\. //g' -e 's/\\.//g' -e 's/^[ \t]*//' "${mountname}"/etc/slackware-version);
2396
2397
2398
2399 ## Search for the files in ${Bootfiles} ##
2400 #
2401 # If found, display their content.
2402
2403 BootFiles='';
2404
2405 if [ "${type}" = 'vfat' ] ; then
2406 Boot_Files=${Boot_Files_Fat};
2407 else
2408 Boot_Files=${Boot_Files_Normal};
2409 fi
2410
2411 for file in ${Boot_Files} ; do
2412 if [ -f "${mountname}${file}" ] && [ -s "${mountname}${file}" ] && FileNotMounted "${mountname}${file}" "${mountname}" ; then
2413 BootFiles="${BootFiles} ${file}";
2414
2415 # Check whether the file is a symlink.
2416 if ! [ -h "${mountname}${file}" ] ; then
2417 # if not a symlink, display content.
2418
2419 if ( [ ${file} = '/grldr' ] || [ ${file} = '/grub.exe' ] ) ; then
2420 # Display the embedded menu of grub4dos.
2421 get_embedded_menu "${mountname}${file}" "${name}${file}";
2422 else
2423 titlebar_gen "${name}" ${file}; # Generates a titlebar above each file listed.
2424 echo '--------------------------------------------------------------------------------' >> "${Log1}";
2425 cat "${mountname}${file}" >> "${Log1}";
2426 echo '--------------------------------------------------------------------------------' >> "${Log1}";
2427 fi
2428 fi
2429 fi
2430 done
2431
2432
2433
2434 ## Search for Wubi partitions. ##
2435
2436 if [ -f "${mountname}/ubuntu/disks/root.disk" ] ; then
2437 Wubi=$(losetup -a | ${AWK} '$3 ~ "(/host/ubuntu/disks/root.disk)" { print $1; exit }' | sed 's/.$//' );
2438
2439 # check whether Wubi already has a loop device.
2440 if [[ x"${Wubi}" = x'' ]] ; then
2441 Wubi=$(losetup -f --show "${mountname}/ubuntu/disks/root.disk" );
2442 WubiDev=0;
2443 else
2444 WubiDev=1;
2445 fi
2446
2447 if [ x"${Wubi}" != x'' ] ; then
2448 Get_Partition_Info "${Log}"x "${Log1}"x "${Wubi}" "${name}/Wubi" "Wubi/${mountname}" 'Wubi' 0 0 'Wubi' '';
2449
2450 # Remove Wubu loop device, if created by BIS.
2451 [[ ${WubiDev} -eq 0 ]] && losetup -d "${Wubi}";
2452 else
2453 echo "Found Wubi on ${name}. But could not create a loop device." >&2;
2454 fi
2455 fi
2456
2457
2458
2459 ## Search for the filenames in ${Boot_Prog}. ##
2460 #
2461 # If found displays their names.
2462
2463 if [ "${type}" = 'vfat' ] ; then
2464 # Check FAT filesystems for EFI boot files.
2465 for file in "${mountname}"/efi/*/*.efi ; do
2466 # Remove "${mountname}" part of the filename.
2467 file="${file#${mountname}}";
2468
2469 if [ -f "${mountname}${file}" ] && [ -s "${mountname}${file}" ] && FileNotMounted "${mountname}${file}" "${mountname}" ; then
2470 BootFiles="${BootFiles} ${file}";
2471 fi
2472 done
2473
2474 # Other boot program files.
2475 Boot_Prog=${Boot_Prog_Fat};
2476 else
2477 Boot_Prog=${Boot_Prog_Normal};
2478 fi
2479
2480 for file in ${Boot_Prog} ; do
2481 if [ -f "${mountname}${file}" ] && [ -s "${mountname}${file}" ] && FileNotMounted "${mountname}${file}" "${mountname}" ; then
2482 BootFiles="${BootFiles} ${file}";
2483 fi
2484 done
2485
2486
2487
2488 ## Search for files containing boot codes. ##
2489
2490 # Loop through all directories which might contain boot_code files.
2491 for file in ${Boot_Codes_Dir} ; do
2492
2493 # If such directory exist ...
2494 if [ -d "${mountname}${file}" ] && FileNotMounted "${mountname}${file}" "${mountname}" ; then
2495 # Look at the content of that directory.
2496 for loader in $( ls "${mountname}${file}" ) ; do
2497 # If it is a file ...
2498 if [ -f "${mountname}${file}${loader}" ] && [ -s "${mountname}${file}${loader}" ] ; then
2499
2500 # Bootpart code has "BootPart" written at 0x101
2501 sig=$(hexdump -v -s 257 -n 8 -e '8/1 "%_p"' "${mountname}${file}${loader}");
2502
2503 if [ "${sig}" = 'BootPart' ] ; then
2504 offset=$(hexdump -v -s 241 -n 4 -e '"%d"' "${mountname}${file}${loader}");
2505 dr=$(hexdump -v -s 111 -n 1 -e '"%d"' "${mountname}${file}${loader}");
2506 dr=$((dr - 127));
2507 BFI="${BFI} BootPart in the file ${file}${loader} is trying to chainload sector #${offset} on boot drive #${dr}";
2508 fi
2509
2510 # Grub Legacy, Grub2 (v1.96) and Grub2 (v1.99) have "GRUB" written at 0x17f.
2511 sig=$(hexdump -v -s 383 -n 4 -e '4/1 "%_p"' "${mountname}${file}${loader}");
2512
2513 if [ "${sig}" = 'GRUB' ] ; then
2514 sig2=$(hexdump -v -n 2 -e '/1 "%02x"' "${mountname}${file}${loader}");
2515
2516 # Distinguish Grub Legacy and Grub2 (v1.96) by the first two bytes.
2517 case "${sig2}" in
2518 eb48) stage2_loc "${mountname}${file}${loader}";
2519 BFI="${BFI} Grub Legacy (v${Grub_Version}) in the file ${file}${loader} ${Stage2_Msg}";;
2520 eb4c) grub2_info "${mountname}${file}${loader}" ${drive} 1.96;
2521 BFI="${BFI} Grub2 (v1.96) in the file ${file}${loader} ${Grub2_Msg}.";;
2522 eb63) grub2_info "${mountname}${file}${loader}" ${drive} 1.99;
2523 BFI="${BFI} Grub2 (v1.99) in the file ${file}${loader} ${Grub2_Msg}.";;
2524 esac
2525 fi
2526
2527 # Grub2 (v1.97-1.98) has "GRUB" written at 0x188.
2528 sig=$(hexdump -v -s 392 -n 4 -e '4/1 "%_p"' "${mountname}${file}${loader}");
2529
2530 if [ "${sig}" = 'GRUB' ]; then
2531 grub2_info "${mountname}${file}${loader}" ${drive} 1.97;
2532 BFI="${BFI} Grub2 (v1.97-1.98) in the file ${file}${loader} ${Grub2_Msg}.";
2533 fi
2534 fi
2535 done # End of loop through the files in a particular Boot_Code_Directory.
2536 fi
2537 done # End of the loop through the Boot_Code_Directories.
2538
2539
2540
2541 ## Show the location (offset on disk) of all files in: ##
2542 # - the GrubError18_Files list
2543 # - the SyslinuxError_Files list
2544
2545 cd "${mountname}/";
2546
2547 if [ $( last_block_of_file ${GrubError18_Files} ; echo $? ) -ne 0 ] ; then
2548 titlebar_gen "${name}" ': Location of files loaded by Grub';
2549 printf "%11sGiB - GB%13sFile%33sFragment(s)\n\n" ' ' ' ' ' ' >> "${Log1}";
2550 cat ${Tmp_Log} >> "${Log1}";
2551 fi
2552
2553 if [ $( last_block_of_file ${SyslinuxError_Files} ; echo $? ) -ne 0 ] ; then
2554 titlebar_gen "${name}" ': Location of files loaded by Syslinux';
2555 printf "%11sGiB - GB%13sFile%33sFragment(s)\n\n" ' ' ' ' ' ' >> "${Log1}";
2556 cat ${Tmp_Log} >> "${Log1}";
2557 fi
2558
2559
2560
2561 rm -f ${Tmp_Log};
2562
2563 # Display the version of the COM32(R) modules of Syslinux.
2564
2565 for com32 in *.c32 syslinux/*.c32 extlinux/*.c32 boot/syslinux/*.c32 boot/extlinux/*.c32 ; do
2566
2567 if [ -f "${com32}" ] ; then
2568 # First 5 bytes of the COM32(R) module are a magic number (used by Syslinux too).
2569 com32_version=$(hexdump -n 5 -e '/1 "%02x"' "${com32}");
2570
2571 case ${com32_version} in
2572 b8fe4ccd21) printf ' %-35s: COM32R module (v4.xx)\n' "${com32}" >> ${Tmp_Log};;
2573 b8ff4ccd21) printf ' %-35s: COM32R module (v3.xx)\n' "${com32}" >> ${Tmp_Log};;
2574 *) printf ' %-35s: not a COM32/COM32R module\n' "${com32}" >> ${Tmp_Log};;
2575 esac
2576 fi
2577 done
2578
2579 if [ -f ${Tmp_Log} ] ; then
2580 titlebar_gen "${name}" ': Version of COM32(R) files used by Syslinux';
2581 cat ${Tmp_Log} >> "${Log1}";
2582 fi
2583
2584
2585
2586 cd "${Folder}";
2587
2588
2589
2590 echo > ${Tmp_Log};
2591
2592 if [[ x"${BFI}" != x'' ]] ; then
2593 printf " Boot file info: " >> "${Log}";
2594 printf "${BFI}\n" | fold -s -w 55 | sed -e '/^-------------------------$/ d' -e '2~1s/.*/ &/' >> "${Log}";
2595 fi
2596
2597 echo " Operating System: "${OS} | fold -s -w 55 | sed -e '2~1s/.*/ &/' >> "${Log}"
2598 printf " Boot files: " >> "${Log}";
2599 echo ${BootFiles} | fold -s -w 55 | sed -e '2~1s/.*/ &/' >> "${Log}";
2600
2601
2602
2603 # If partition was mounted by the script.
2604 if [ x"${CheckMount}" = x'' ] ; then
2605 umount "${mountname}" || umount -l "${mountname}";
2606 fi
2607
2608 # If partition failed to mount.
2609 else
2610 printf " Mounting failed: " >> "${Log}";
2611 cat ${Mount_Error} >> "${Log}";
2612 fi # End of Mounting "if then else".
2613 fi # End of Partition Type "if then else".
2614
2615 echo >> "${Log}";
2616
2617 if [[ -e "${Log}"x ]] ; then
2618 cat "${Log}"x >> "${Log}";
2619 rm "${Log}"x;
2620 fi
2621
2622 if [[ -e "${Log1}"x ]] ; then
2623 cat "${Log1}"x >> "${Log1}";
2624 rm "${Log1}"x;
2625 fi
2626} # End Get_Partition_Info function
2627
2628
2629
2630## "titlebar_gen" generates the ${name}${file} title bar to always be 80 characters in length. ##
2631
2632titlebar_gen () {
2633 local name_file name_file_length equal_signs_line_length equal_signs_line;
2634
2635 name_file="${1}${2}:";
2636 name_file_length=${#name_file};
2637
2638 equal_signs_line_length=$(((80-${name_file_length})/2-1));
2639
2640 # Build "===" string.
2641 printf -v equal_signs_line "%${equal_signs_line_length}s";
2642 printf -v equal_signs_line "%s" "${equal_signs_line// /=}";
2643
2644 if [ "$((${name_file_length}%2))" -eq 1 ]; then
2645 # If ${name_file_length} is odd, add an extra "=" at the end.
2646 printf "\n%s %s %s=\n\n" "${equal_signs_line}" "${name_file}" "${equal_signs_line}" >> "${Log1}";
2647 else
2648 printf "\n%s %s %s\n\n" "${equal_signs_line}" "${name_file}" "${equal_signs_line}" >> "${Log1}";
2649 fi
2650}
2651
2652
2653
2654## Start ##
2655
2656
2657
2658# Center title.
2659BIS_title=$(printf 'Boot Info Script %s [%s]' "${VERSION}" "${RELEASE_DATE}");
2660printf -v BIS_title_space "%$(( ( 80 - ${#BIS_title} ) / 2 - 1 ))s";
2661printf "${BIS_title_space}${BIS_title}\n" > "${Log}";
2662
2663if [ ! -z "${LAST_GIT_COMMIT}" ] ; then
2664 printf '\nLast git commit: %s\nRetrieved from git on: %s\n' "${LAST_GIT_COMMIT}" "${RETRIEVAL_DATE}" >> "${Log}";
2665fi
2666
2667printf '\n\n============================= Boot Info Summary: ===============================\n\n' >> "${Log}";
2668
2669
2670
2671# Search for hard drives which don't exist, have a corrupted partition table
2672# or don't have a parition table (whole drive is a filesystem).
2673# Information on all hard drives which a valid partition table are stored in
2674# the hard drives arrays: HD?????
2675
2676# id for Filesystem Drives.
2677FSD=0;
2678
2679# Clear blkid cache
2680blkid -g;
2681
2682for drive in ${All_Hard_Drives} ; do
2683 size=$(fdisks ${drive});
2684
2685 PrintBlkid ${drive};
2686
2687 if [ 0 -lt ${size} 2>> ${Trash} ] ; then
2688 if [ x"$(blkid ${drive})" = x'' ] || [ x"$(blkid | grep ${drive}:)" = x'' ] ; then
2689 # Drive is not a filesytem.
2690
2691 size=$((2*size));
2692
2693 HDName[${HI}]=${drive};
2694 HDSize[${HI}]=${size};
2695
2696 # Get and set HDHead[${HI}], HDTrack[${HI}] and HDCylinder[${HI}] all at once.
2697 eval $(fdisk -lu ${drive} 2>> ${Trash} | ${AWK} -F ' ' '$2 ~ "head" { print "HDHead['${HI}']=" $1 "; HDTrack['${HI}']=" $3 "; HDCylinder['${HI}']=" $5 }' );
2698
2699 # Look at the first 4 bytes of the second sector to identify the partition table type.
2700 case $(hexdump -v -s 512 -n 4 -e '"%_u"' ${drive}) in
2701 'EMBR') HDPT[${HI}]='BootIt';;
2702 'EFI ') HDPT[${HI}]='EFI';;
2703 *) HDPT[${HI}]='MSDos';;
2704 esac
2705
2706 HI=$((${HI}+1));
2707 else
2708 # Drive is a filesystem.
2709
2710 if [ $( expr match "$(BlkidTag "${drive}" TYPE)" '.*raid') -eq 0 ] || [ x"$(BlkidTag "${drive}" UUID)" != x'' ] ; then
2711 FilesystemDrives[${FSD}]="${drive}";
2712 ((FSD++));
2713 fi
2714 fi
2715 else
2716 printf "$(basename ${drive}) " >> ${FakeHardDrives};
2717 fi
2718done
2719
2720
2721
2722## Identify the MBR of each hard drive. ##
2723echo 'Identifying MBRs...';
2724
2725for HI in ${!HDName[@]} ; do
2726 drive="${HDName[${HI}]}";
2727 Message="is installed in the MBR of ${drive}";
2728
2729 # Read the whole MBR in hexadecimal format.
2730 MBR_512=$(hexdump -v -n 512 -e '/1 "%02x"' ${drive});
2731
2732 ## Look at the first 2,3,4 or 8 bytes of the hard drive to identify the boot code installed in the MBR. ##
2733 #
2734 # If it is not enough, look at more bytes.
2735
2736 MBR_sig2="${MBR_512:0:4}";
2737 MBR_sig3="${MBR_512:0:6}";
2738 MBR_sig4="${MBR_512:0:8}";
2739 MBR_sig8="${MBR_512:0:16}";
2740
2741 ## Bytes 0x80-0x81 of the MBR. ##
2742 #
2743 # Use it to differentiate between different versions of the same bootloader.
2744
2745 MBR_bytes80to81="${MBR_512:256:4}";
2746
2747
2748 case ${MBR_sig2} in
2749
2750 eb48) ## Grub Legacy is in the MBR. ##
2751 BL="Grub Legacy";
2752
2753 # 0x44 contains the offset to the next stage.
2754 offset=$(hexdump -v -s 68 -n 4 -e '"%u"' ${drive});
2755
2756 if [ "${offset}" -ne 1 ] ; then
2757 # Grub Legacy is installed without stage1.5 files.
2758 stage2_loc ${drive};
2759 Message="${Message} and ${Stage2_Msg}";
2760 else
2761 # Grub is installed with stage1.5 files.
2762 Grub_String=$(hexdump -v -s 1042 -n 94 -e '"%_u"' ${drive});
2763 Grub_Version="${Grub_String%%nul*}";
2764
2765 BL="Grub Legacy (v${Grub_Version})";
2766
2767 tmp="/${Grub_String#*/}";
2768 tmp="${tmp%%nul*}";
2769
2770 eval $(echo ${tmp} | ${AWK} '{ print "stage=" $1 "; menu=" $2 }');
2771
2772 [[ x"$menu" = x'' ]] || stage="${stage} and ${menu}";
2773
2774 part_info=$((1045 + ${#Grub_Version}));
2775 eval $(hexdump -v -s ${part_info} -n 2 -e '1/1 "pa=%u; " 1/1 "dr=%u"' ${drive});
2776
2777 dr=$(( ${dr} - 127 ));
2778 pa=$(( ${pa} + 1 ));
2779
2780 if [ "${dr}" -eq 128 ] ; then
2781 Message="${Message} and looks on the same drive in partition #${pa} for ${stage}";
2782 else
2783 Message="${Message} and looks on boot drive #${dr} in partition #${pa} for ${stage}";
2784 fi
2785 fi;;
2786
2787 eb4c) ## Grub2 (v1.96) is in the MBR. ##
2788 BL='Grub2 (v1.96)';
2789
2790 grub2_info ${drive} ${drive} '1.96';
2791
2792 Message="${Message} and ${Grub2_Msg}";;
2793
2794 eb63) ## Grub2 is in the MBR. ##
2795 case ${MBR_bytes80to81} in
2796 7c3c) grub2_version='1.97'; BL='Grub2 (v1.97-1.98)';;
2797 0020) grub2_version='1.99'; BL='Grub2 (v1.99)';;
2798 esac
2799
2800 grub2_info ${drive} ${drive} ${grub2_version};
2801
2802 Message="${Message} and ${Grub2_Msg}";;
2803
2804 0ebe) BL='ThinkPad';;
2805 31c0) # Look at the first 8 bytes of the hard drive to identify the boot code installed in the MBR.
2806 case ${MBR_sig8} in
2807 31c08ed0bc007c8e) BL='SUSE generic MBR';;
2808 31c08ed0bc007cfb) BL='Acer PQService MBR';;
2809 esac;;
2810 33c0) # Look at the first 3 bytes of the hard drive to identify the boot code installed in the MBR.
2811 case ${MBR_sig3} in
2812 33c08e) BL='Windows';;
2813 33c090) BL='DiskCryptor';;
2814 33c0fa) BL='Syslinux MBR (4.04 and higher)';;
2815 esac;;
2816 33ed) # Look at bytes 0x80-0x81 to be more specific about the Syslinux variant/version.
2817 case ${MBR_bytes80to81} in
2818 407c) BL='ISOhybrid (Syslinux 4.04 and higher)';;
2819 83e1) BL='ISOhybrid with partition support (Syslinux 4.04 and higher)';;
2820 esac;;
2821 33ff) BL='HP/Gateway';;
2822 b800) BL='Plop';;
2823 ea05) BL='XOSL';;
2824 ea1e) BL='Truecrypt Boot Loader';;
2825 eb04) BL='Solaris';;
2826 eb31) BL='Paragon';;
2827 eb5e) # Look at the first 3 bytes of the hard drive to identify the boot code installed in the MBR.
2828 case ${MBR_sig3} in
2829 eb5e00) BL='fbinst';;
2830 eb5e80) BL='Grub4Dos';;
2831 eb5e90) BL='WEE';
2832 # Get the embedded menu of WEE.
2833 get_embedded_menu "${drive}" "WEE's (${drive})";;
2834 esac;;
2835 fa31) # Look at the first 3 bytes of the hard drive to identify the boot code installed in the MBR.
2836 case ${MBR_sig3} in
2837 fa31c0) # Look at bytes 0x80-0x81 to be more specific about the Syslinux variant/version.
2838 case ${MBR_bytes80to81} in
2839 0069) BL='ISOhybrid (Syslinux 3.72-3.73)';;
2840 7c66) BL='Syslinux MBR (3.61-4.03)';;
2841 7cb8) BL='Syslinux MBR (3.36-3.51)';;
2842 b442) BL='Syslinux MBR (3.00-3.35)';;
2843 bb00) BL='Syslinux MBR (3.52-3.60)';;
2844 e879) BL='ISOhybrid (Syslinux 3.74-3.80)';;
2845 esac;;
2846 fa31c9) BL='Master Boot LoaDeR';;
2847 fa31ed) # Look at bytes 0x80-0x81 to be more specific about the Syslinux variant/version.
2848 case ${MBR_bytes80to81} in
2849 0069) BL='ISOhybrid (Syslinux 3.72-3.73)';;
2850 0fb6) BL='ISOhybrid with partition support (Syslinux 3.82-3.86)';;
2851 407c) BL='ISOhybrid (Syslinux 3.82-4.03)';;
2852 83e1) BL='ISOhybrid with partition support (Syslinux 4.00-4.03)';;
2853 b6c6) BL='ISOhybrid with partition support (Syslinux 3.81)';;
2854 fbc0) BL='ISOhybrid (Syslinux 3.81)';;
2855 esac;;
2856 esac;;
2857 fa33) BL='MS-DOS 3.30 through Windows 95 (A)';;
2858 fab8) # Look at the first 4 bytes of the hard drive to identify the boot code installed in the MBR.
2859 case ${MBR_sig4} in
2860 fab80000) BL='FreeDOS (eXtended FDisk)';;
2861 fab8* ) BL="No boot loader";;
2862 esac;;
2863 fabe) BL='No boot loader?';;
2864 faeb) BL='Lilo';;
2865 fafc) BL='ReactOS';;
2866 fc31) BL='Testdisk';;
2867 fc33) BL='GAG';;
2868 fceb) BL='BootIt NG';;
2869 0000) BL='No boot loader';;
2870 *) BL='No known boot loader';
2871 printf "Unknown MBR on ${drive}\n\n" >> ${Unknown_MBR};
2872 hexdump -v -n 512 -C ${drive} >> ${Unknown_MBR};
2873 echo >> ${Unknown_MBR};;
2874 esac
2875
2876
2877 ## Output message at beginning of summary that gives MBR info for each drive: ##
2878
2879 printf ' => ' >> "${Log}";
2880 printf "${BL} ${Message}.\n" | fold -s -w 75 | sed -e '/^-----$/ d' -e '2~1s/.*/ &/' >> "${Log}";
2881
2882 HDMBR[${HI}]=${BL};
2883done
2884
2885echo >> "${Log}";
2886
2887
2888
2889## Store and Display all the partitions tables. ##
2890
2891for HI in ${!HDName[@]} ; do
2892 drive=${HDName[${HI}]};
2893
2894 echo "Computing Partition Table of ${drive}...";
2895
2896 FP=$((PI+1)); # used if non-MS_DOS partition table is not in use.
2897 FirstPartition[${HI}]=${FP};
2898 PTType=${HDPT[${HI}]};
2899 HDPT[${HI}]='MSDos';
2900
2901 echo "Drive: $(basename ${drive} ) _____________________________________________________________________" >> ${PartitionTable};
2902 fdisk -lu ${drive} 2>> ${Trash} | sed '/omitting/ d' | sed '6,$ d' >> ${PartitionTable};
2903
2904 printf "\n${PTFormat}\n" 'Partition' 'Boot' 'Start Sector' 'End Sector' '# of Sectors' 'Id' 'System' >> ${PartitionTable};
2905
2906 ReadPT ${HI} 0 4 ${PartitionTable} "${PTFormat}" '' 0;
2907
2908 echo >> ${PartitionTable};
2909 LastPartition[${HI}]=${PI};
2910 LP=${PI};
2911
2912 CheckPT ${FirstPartition[${HI}]} ${LastPartition[${HI}]} ${PartitionTable} ${HI};
2913
2914 echo >> ${PartitionTable};
2915 HDPT[${HI}]=${PTType};
2916
2917 case ${PTType} in
2918 BootIt) printf 'BootIt NG Partition Table detected' >> ${PartitionTable};
2919 [[ "${HDMBR[${HI}]}" = 'BootIt NG' ]] || printf ', but does not seem to be used' >> ${PartitionTable};
2920 printf '.\n\n' >> ${PartitionTable};
2921
2922 ReadEMBR ${HI} ${PartitionTable};
2923 echo >> ${PartitionTable};
2924
2925 if [ "${HDMBR[${HI}]}" = 'BootIt NG' ] ; then
2926 LastPartition[${HI}]=${PI};
2927 CheckPT ${FirstPartition[${HI}]} ${LastPartition[${HI}]} ${PartitionTable} ${HI};
2928 else
2929 FirstPartition[${HI}]=${FP};
2930 fi;;
2931 EFI) FirstPartition[${HI}]=$((PI+1));
2932 EFIee=$(hexdump -v -s 450 -n 1 -e '"%x"' ${drive});
2933 printf 'GUID Partition Table detected' >> ${PartitionTable};
2934 [[ "${EFIee}" = 'ee' ]] || printf ', but does not seem to be used' >> ${PartitionTable};
2935 printf '.\n\n' >> ${PartitionTable};
2936
2937 ReadEFI ${HI} ${PartitionTable};
2938 echo >> ${PartitionTable};
2939
2940 if [ "${EFIee}" = 'ee' ] ; then
2941 LastPartition[${HI}]=${PI};
2942 CheckPT ${FirstPartition[${HI}]} ${LastPartition[${HI}]} ${PartitionTable} ${HI};
2943 else
2944 FirstPartition[${HI}]=${FP};
2945 fi;;
2946 esac
2947done
2948
2949
2950
2951## Loop through all Hard Drives. ##
2952
2953for HI in ${!HDName[@]} ; do
2954 drive=${HDName[${HI}]};
2955
2956 ## And then loop through the partitions on that drive. ##
2957 for (( PI = FirstPartition[${HI}]; PI <= LastPartition[${HI}]; PI++ )); do
2958 part_type=${TypeArray[${PI}]}; # Type of the partition according to fdisk
2959 start=${StartArray[${PI}]};
2960 size=${SizeArray[${PI}]};
2961 end=${EndArray[${PI}]};
2962 kind=${KindArray[${PI}]};
2963 system=${SystemArray[${PI}]};
2964
2965 if [[ x"${DeviceArray[${PI}]}" = x'' ]] ; then
2966 name="${NamesArray[${PI}]}";
2967 mountname=$(basename ${drive})"_"${PI};
2968 part=$(losetup -f --show -o $((start*512)) ${drive});
2969 # --sizelimit $((size*512)) --sizelimit seems to be a recently added option for losetup. Failed on Hardy.
2970 else
2971 part="${DeviceArray[${PI}]}";
2972 name=$(basename ${part}); # Name of the partition (/dev/sda8 -> sda8).
2973 mountname=${name};
2974 fi
2975
2976 Get_Partition_Info "${Log}" "${Log1}" "${part}" "${name}" "${mountname}" "${kind}" "${start}" "${end}" "${system}" "${PI}";
2977
2978 [[ "${DeviceArray[${PI}]}" = '' ]] && losetup -d ${part};
2979
2980 done
2981done
2982
2983
2984
2985## Deactivate dmraid's activated by the script. ##
2986
2987if [ x"$InActiveDMRaid" != x'' ] ; then
2988 dmraid -an ${InActiveDMRaid};
2989fi
2990
2991
2992
2993## Search LVM partitions for information. ##
2994#
2995# Only works if the "LVM2"-package is installed.
2996
2997if [ $(type lvscan lvdisplay lvchange >> ${Trash} 2>> ${Trash} ; echo $?) -eq 0 ] ; then
2998
2999 LVM_Partitions=$(lvscan | ${AWK} '{ split($2, lvm_dev, "/"); print "/dev/mapper/" lvm_dev[3] "-" lvm_dev[4] }');
3000
3001 for LVM in ${LVM_Partitions}; do
3002 LVM_Size=$(lvdisplay -c ${LVM} | ${AWK} -F ':' '{ print $7 }');
3003 LVM_Status=$(lvdisplay ${LVM} | ${AWK} '$0 ~ "LV Status" { print $3 }');
3004 lvchange -ay ${LVM};
3005 name=${LVM:12};
3006 mountname="LVM/${name}";
3007 kind='LVM';
3008 start=0;
3009 end=${LVM_Size};
3010 system='';
3011 PI='';
3012
3013 Get_Partition_Info "${Log}" "${Log1}" "$LVM" "${name}" "${mountname}" "${kind}" "${start}" "${end}" "${system}" "${PI}";
3014
3015 # deactivate all LVM's, which were not active.
3016 [[ "${LVM_Status}" = 'NOT' ]] && lvchange -an "${LVM}";
3017
3018 done
3019fi
3020
3021
3022
3023## Search MDRaid Partitons for Information ##
3024#
3025# Only works if "mdadm" is installed.
3026
3027if [ $(type mdadm >> ${Trash} 2>> ${Trash} ; echo $?) -eq 0 ] ; then
3028
3029 # All arrays which are already assembled.
3030 MD_Active_Array=$(mdadm --detail --scan | ${AWK} '{ print $2 }');
3031
3032 # Assemble all arrays.
3033 mdadm --assemble --scan;
3034
3035 # All arrays.
3036 MD_Array=$(mdadm --detail --scan | ${AWK} '{ print $2 }');
3037
3038 for MD in ${MD_Array}; do
3039 MD_Size=$(fdisks ${MD}); # size in blocks
3040 MD_Size=$((2*${MD_Size})); # size in sectors
3041 MD_Active=0;
3042
3043 # Check whether MD is active.
3044 for MDA in ${MD_Active_Array}; do
3045 if [[ "${MDA}" = "${MD}" ]] ; then
3046 MD_Active=1;
3047 break;
3048 fi
3049 done
3050
3051 name=${MD:5};
3052 mountname="MDRaid/${name}";
3053 kind="MDRaid";
3054 start=0;
3055 end=${MD_Size};
3056 system='';
3057 PI='';
3058
3059 Get_Partition_Info "${Log}" "${Log1}" "${MD}" "${name}" "${mountname}" "${kind}" "${start}" "${end}" "${system}" "${PI}";
3060
3061 # deactivate all MD_Raid's, which were not active.
3062 [[ "${MD_Active}" -eq 0 ]] && mdadm --stop "${MD}";
3063
3064 done
3065fi
3066
3067
3068
3069## Search filesystem hard drives for information. ##
3070
3071for FD in ${FilesystemDrives[@]} ; do
3072 FD_Size=$(fdisks ${FD}); # size in blocks
3073 FD_Size=$((2*${FD_Size})); # size in sectors
3074 name=${FD:5};
3075 mountname="FD/${name}";
3076 kind="FD";
3077 start=0;
3078 end=${FD_Size};
3079 system='';
3080 PI='';
3081
3082 Get_Partition_Info "${Log}" "${Log1}" "${FD}" "${name}" "${mountname}" "${kind}" "${start}" "${end}" "${system}" "${PI}";
3083
3084done
3085
3086
3087
3088## Drive/partition info. ##
3089
3090printf '============================ Drive/Partition Info: =============================\n\n' >> "${Log}";
3091
3092[ -e ${PartitionTable} ] && cat ${PartitionTable} >> "${Log}" || echo 'no valid partition table found' >> "${Log}";
3093
3094
3095printf '"blkid" output: ________________________________________________________________\n\n' >> "${Log}";
3096
3097printf "${BlkidFormat}" Device UUID TYPE LABEL >> "${Log}";
3098
3099echo >> "${Log}";
3100
3101for dev in $(blkid -o device | sort); do
3102 PrintBlkid ${dev} '_summary';
3103done
3104
3105cat "${BLKID}_summary" >> "${Log}";
3106echo >> "${Log}";
3107
3108
3109
3110if [ $(ls -R /dev/mapper 2>> ${Trash} | wc -l) -gt 2 ] ; then
3111 printf '========================= "ls -R /dev/mapper/" output: =========================\n\n' >> "${Log}";
3112 ls -R /dev/mapper >> "${Log}";
3113 echo >> "${Log}";
3114fi
3115
3116
3117
3118## Mount points. ##
3119
3120printf '================================ Mount points: =================================\n\n' >> "${Log}";
3121
3122MountFormat='%-16s %-24s %-10s %s\n';
3123
3124printf "${MountFormat}\n" 'Device' 'Mount_Point' 'Type' 'Options' >> "${Log}";
3125
3126# No idea for which mount version this is even needed.
3127# original:
3128# mount | grep ' / '| grep -v '^/'| sed 's/ on /'$Fis'/' |sed 's/ type /'$Fis'/'|sed 's/ (/'$Fis'(/'| gawk -F $Fis '{printf "'"$MountFormat"'", $1, $2, $3, $4 }'>>"$Log";
3129# new:
3130# mount | sort | gawk -F "${TAB}" '$0 ~ " / " { if ($1 !~ "^/") { sub(" on ", "\t", $0); sub(" type ", "\t", $0); optionsstart=index($3, " ("); printf "'"${MountFormat}"'", $1, $2, substr($3, 1, optionsstart - 1), substr($3, optionsstart + 1) } } END { printf "\n" }' >> "${Log}";
3131
3132mount | sort | ${AWK} -F "${TAB}" '$0 ~ "^/dev" \
3133 { sub(" on ", "\t", $0); sub(" type ", "\t", $0); optionsstart=index($3, " ("); \
3134 printf "'"${MountFormat}"'", $1, $2, substr($3, 1, optionsstart - 1), substr($3, optionsstart + 1) } END { printf "\n" }' >> "${Log}";
3135
3136
3137
3138## Write the content of Log1 to the log file. ##
3139
3140[ -e "${Log1}" ] && cat "${Log1}" >> "${Log}";
3141echo >> "${Log}";
3142
3143
3144
3145## Add unknown MBRs/Boot Sectors to the log file, if any. ##
3146
3147if [ -e ${Unknown_MBR} ] ; then
3148 printf '======================== Unknown MBRs/Boot Sectors/etc: ========================\n\n' >> "${Log}";
3149 cat ${Unknown_MBR} >> "${Log}";
3150 echo >> "${Log}";
3151fi
3152
3153
3154
3155## Add fake hard drives to the log file, if any. ##
3156
3157if [ -e ${FakeHardDrives} ] ; then
3158 printf "========= Devices which don't seem to have a corresponding hard drive: =========\n\n" >> "${Log}";
3159 cat ${FakeHardDrives} >> "${Log}";
3160 printf "\n\n" >> "${Log}";
3161fi
3162
3163
3164
3165## Write the Error Log to the log file. ##
3166
3167if [ -s ${Error_Log} ] ; then
3168 printf '=============================== StdErr Messages: ===============================\n\n' >> "${Log}";
3169 cat ${Error_Log} >> "${Log}";
3170fi
3171
3172
3173
3174## Write a final newline. ##
3175
3176echo >> "${Log}";
3177
3178
3179
3180if [ ${stdout_output} -eq 1 ] ; then
3181 ## If --stdout is specified, show the output.
3182 cat "${Log}";
3183else
3184 ## Copy the log file to RESULTS file and make the user the owner of RESULTS file. ##
3185
3186 cp "${Log}" "${LogFile}";
3187
3188 if [ "${SUDO_UID}:${SUDO_GID}" != ':' ] ; then
3189 chown "${SUDO_UID}:${SUDO_GID}" "${LogFile}";
3190 fi
3191
3192
3193
3194 ## gzip the RESULTS file, for easy uploading. ##
3195 #
3196 # gzip a copy of the RESULTS file only when -g or --gzip is passed on the command line.
3197 #
3198 # ./bootinfoscript -g <outputfile>
3199 # ./bootinfoscript --gzip <outputfile>
3200
3201 if [ ${gzip_output} -eq 1 ] ; then
3202 cat "${LogFile}" | gzip -9 > "${LogFile}.gz";
3203
3204 if [ "${SUDO_UID}:${SUDO_GID}" != ':' ] ; then
3205 chown "${SUDO_UID}:${SUDO_GID}" "${LogFile}.gz";
3206 fi
3207 fi
3208
3209
3210
3211 ## Reset the Standard Output to the Terminal. ##
3212 #
3213 # exec 1>&-;
3214 # exec 1>&6;
3215 # exec 6>&-;
3216
3217
3218
3219 printf '\nFinished. The results are in the file "%s"\nlocated in "%s".\n\n' "$(basename "${LogFile}")" "${Dir}/";
3220fi
3221
3222exit 0;