]> code.delx.au - refind/blob - install.sh
Version 0.6.1 official release
[refind] / install.sh
1 #!/bin/bash
2 #
3 # Linux/MacOS X script to install rEFInd
4 #
5 # Usage:
6 #
7 # ./install.sh [options]
8 #
9 # options include:
10 # "--esp" to install to the ESP rather than to the system's root
11 # filesystem. This is the default on Linux
12 # "--usedefault {devicefile}" to install as default
13 # (/EFI/BOOT/BOOTX64.EFI and similar) to the specified device
14 # (/dev/sdd1 or whatever) without registering with the NVRAM.
15 # "--alldrivers" to install all drivers along with regular files
16 # "--nodrivers" to suppress driver installation (default in Linux is
17 # driver used on /boot; --nodrivers is OS X default)
18 # "--shim {shimfile}" to install a shim.efi file for Secure Boot
19 # "--localkeys" to re-sign x86-64 binaries with a locally-generated key
20 #
21 # The "esp" option is valid only on Mac OS X; it causes
22 # installation to the EFI System Partition (ESP) rather than
23 # to the current OS X boot partition. Under Linux, this script
24 # installs to the ESP by default.
25 #
26 # This program is copyright (c) 2012 by Roderick W. Smith
27 # It is released under the terms of the GNU GPL, version 3,
28 # a copy of which should be included in the file COPYING.txt.
29 #
30 # Revision history:
31 #
32 # 0.6.1 -- Added --root option; minor bug fixes
33 # 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option;
34 # changed default driver installation behavior in Linux to install
35 # the driver needed to read /boot (if available)
36 # 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
37 # 0.5.1.1 -- Fixed bug that caused script failure under OS X
38 # 0.5.1 -- Added --shim & --localkeys options & create sample refind_linux.conf
39 # in /boot
40 # 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
41 # 0.4.5 -- Fixed check for rEFItBlesser in OS X
42 # 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
43 # 0.4.1 -- Added check for rEFItBlesser in OS X
44 # 0.3.3.1 -- Fixed OS X 10.7 bug; also works as make target
45 # 0.3.2.1 -- Check for presence of source files; aborts if not present
46 # 0.3.2 -- Initial version
47 #
48 # Note: install.sh version numbers match those of the rEFInd package
49 # with which they first appeared.
50
51 RootDir="/"
52 TargetDir=/EFI/refind
53 LocalKeysBase="refind_local"
54 ShimSource="none"
55 TargetX64="refind_x64.efi"
56 TargetIA32="refind_ia32.efi"
57 LocalKeys=0
58 DeleteRefindDir=0
59
60 #
61 # Functions used by both OS X and Linux....
62 #
63
64 GetParams() {
65 InstallToEspOnMac=0
66 if [[ $OSName == "Linux" ]] ; then
67 # Install the driver required to read /boot, if it's available
68 InstallDrivers="boot"
69 else
70 InstallDrivers="none"
71 fi
72 while [[ $# -gt 0 ]]; do
73 case $1 in
74 --esp | --ESP) InstallToEspOnMac=1
75 ;;
76 --usedefault) TargetDir=/EFI/BOOT
77 TargetPart=$2
78 TargetX64="bootx64.efi"
79 TargetIA32="bootia32.efi"
80 shift
81 ;;
82 --root) RootDir=$2
83 shift
84 ;;
85 --localkeys) LocalKeys=1
86 ;;
87 --shim) ShimSource=$2
88 shift
89 ;;
90 --drivers | --alldrivers) InstallDrivers="all"
91 ;;
92 --nodrivers) InstallDrivers="none"
93 ;;
94 * ) echo "Usage: $0 [--esp | --usedefault {device-file} | --root {directory} ]"
95 echo " [--nodrivers | --alldrivers] [--shim {shim-filename}]"
96 echo " [--localkeys]"
97 exit 1
98 esac
99 shift
100 done
101
102 if [[ $InstallToEspOnMac == 1 && $TargetDir == '/EFI/BOOT' ]] ; then
103 echo "You may use --esp OR --usedefault, but not both! Aborting!"
104 exit 1
105 fi
106 if [[ $RootDir != '/' && $TargetDir == '/EFI/BOOT' ]] ; then
107 echo "You may use --usedefault OR --root, but not both! Aborting!"
108 exit 1
109 fi
110 if [[ $RootDir != '/' && $InstallToEspOnMac == 1 ]] ; then
111 echo "You may use --root OR --esp, but not both! Aborting!"
112 exit 1
113 fi
114
115 RLConfFile="$RootDir/boot/refind_linux.conf"
116 EtcKeysDir="$RootDir/etc/refind.d/keys"
117 } # GetParams()
118
119 # Abort if the rEFInd files can't be found.
120 # Also sets $ConfFile to point to the configuration file,
121 # $IconsDir to point to the icons directory, and
122 # $ShimSource to the source of the shim.efi file (if necessary).
123 CheckForFiles() {
124 # Note: This check is satisfied if EITHER the 32- or the 64-bit version
125 # is found, even on the wrong platform. This is because the platform
126 # hasn't yet been determined. This could obviously be improved, but it
127 # would mean restructuring lots more code....
128 if [[ ! -f $RefindDir/refind_ia32.efi && ! -f $RefindDir/refind_x64.efi ]] ; then
129 echo "The rEFInd binary file is missing! Aborting installation!"
130 exit 1
131 fi
132
133 if [[ -f $RefindDir/refind.conf-sample ]] ; then
134 ConfFile=$RefindDir/refind.conf-sample
135 elif [[ -f $ThisDir/refind.conf-sample ]] ; then
136 ConfFile=$ThisDir/refind.conf-sample
137 else
138 echo "The sample configuration file is missing! Aborting installation!"
139 exit 1
140 fi
141
142 if [[ -d $RefindDir/icons ]] ; then
143 IconsDir=$RefindDir/icons
144 elif [[ -d $ThisDir/icons ]] ; then
145 IconsDir=$ThisDir/icons
146 else
147 echo "The icons directory is missing! Aborting installation!"
148 exit 1
149 fi
150
151 if [[ $ShimSource != "none" ]] ; then
152 if [[ -f $ShimSource ]] ; then
153 TargetX64="grubx64.efi"
154 MokManagerSource=`dirname $ShimSource`/MokManager.efi
155 else
156 echo "The specified shim file, $ShimSource, doesn't exist!"
157 echo "Aborting installation!"
158 exit 1
159 fi
160 fi
161 } # CheckForFiles()
162
163 # Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
164 # available) to target.
165 CopyShimFiles() {
166 cp $ShimSource $InstallDir/$TargetDir/$TargetShim
167 if [[ $? != 0 ]] ; then
168 Problems=1
169 fi
170 if [[ -f $MokManagerSource ]] ; then
171 cp $MokManagerSource $InstallDir/$TargetDir/
172 fi
173 if [[ $? != 0 ]] ; then
174 Problems=1
175 fi
176 } # CopyShimFiles()
177
178 # Copy the public keys to the installation medium
179 CopyKeys() {
180 if [[ $LocalKeys == 1 ]] ; then
181 mkdir -p $InstallDir/$TargetDir/keys/
182 cp $EtcKeysDir/$LocalKeysBase.cer $InstallDir/$TargetDir/keys/
183 cp $EtcKeysDir/$LocalKeysBase.crt $InstallDir/$TargetDir/keys/
184 # else
185 # cp $ThisDir/refind.cer $InstallDir/$TargetDir/keys/
186 # cp $ThisDir/refind.crt $InstallDir/$TargetDir/keys/
187 fi
188 } # CopyKeys()
189
190 # Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
191 # honoring the $InstallDrivers condition. Must be passed a suitable
192 # architecture code (ia32 or x64).
193 CopyDrivers() {
194 if [[ $InstallDrivers == "all" ]] ; then
195 mkdir -p $InstallDir/$TargetDir/drivers_$1
196 cp $RefindDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
197 cp $ThisDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
198 elif [[ $InstallDrivers == "boot" && -x `which blkid` ]] ; then
199 BootPart=`df /boot | grep dev | cut -f 1 -d " "`
200 BootFS=`blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
201 DriverType=""
202 case $BootFS in
203 ext2 | ext3 | ext4) DriverType="ext4"
204 ;;
205 reiserfs) DriverType="reiserfs"
206 ;;
207 hfsplus) DriverType="hfs"
208 ;;
209 *) BootFS=""
210 esac
211 if [[ -n $BootFS ]] ; then
212 echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
213 mkdir -p $InstallDir/$TargetDir/drivers_$1
214 cp $RefindDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
215 cp $ThisDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
216 fi
217 fi
218 }
219
220 # Copy the rEFInd files to the ESP or OS X root partition.
221 # Sets Problems=1 if any critical commands fail.
222 CopyRefindFiles() {
223 mkdir -p $InstallDir/$TargetDir &> /dev/null
224 if [[ $TargetDir == '/EFI/BOOT' ]] ; then
225 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 2> /dev/null
226 if [[ $? != 0 ]] ; then
227 echo "Note: IA32 (x86) binary not installed!"
228 fi
229 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64 2> /dev/null
230 if [[ $? != 0 ]] ; then
231 Problems=1
232 fi
233 if [[ $ShimSource != "none" ]] ; then
234 TargetShim="bootx64.efi"
235 CopyShimFiles
236 fi
237 if [[ $InstallDrivers == "all" ]] ; then
238 cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
239 cp -r $ThisDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
240 fi
241 Refind=""
242 CopyKeys
243 elif [[ $Platform == 'EFI32' ]] ; then
244 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32
245 if [[ $? != 0 ]] ; then
246 Problems=1
247 fi
248 CopyDrivers ia32
249 Refind="refind_ia32.efi"
250 elif [[ $Platform == 'EFI64' ]] ; then
251 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64
252 if [[ $? != 0 ]] ; then
253 Problems=1
254 fi
255 CopyDrivers x64
256 Refind="refind_x64.efi"
257 CopyKeys
258 if [[ $ShimSource != "none" ]] ; then
259 TargetShim=`basename $ShimSource`
260 CopyShimFiles
261 Refind=$TargetShim
262 if [[ $LocalKeys == 0 ]] ; then
263 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
264 mkdir -p $EtcKeysDir
265 cp $ThisDir/keys/refind.cer $EtcKeysDir
266 cp $ThisDir/keys/refind.crt $EtcKeysDir
267 fi
268 fi
269 else
270 echo "Unknown platform! Aborting!"
271 exit 1
272 fi
273 echo "Copied rEFInd binary files"
274 echo ""
275 if [[ -d $InstallDir/$TargetDir/icons ]] ; then
276 rm -rf $InstallDir/$TargetDir/icons-backup &> /dev/null
277 mv -f $InstallDir/$TargetDir/icons $InstallDir/$TargetDir/icons-backup
278 echo "Notice: Backed up existing icons directory as icons-backup."
279 fi
280 cp -r $IconsDir $InstallDir/$TargetDir
281 if [[ $? != 0 ]] ; then
282 Problems=1
283 fi
284 cp -rf $ThisDir/keys $InstallDir/$TargetDir/
285 if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then
286 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
287 echo "to avoid overwriting your customizations."
288 echo ""
289 cp -f $ConfFile $InstallDir/$TargetDir
290 if [[ $? != 0 ]] ; then
291 Problems=1
292 fi
293 else
294 echo "Copying sample configuration file as refind.conf; edit this file to configure"
295 echo "rEFInd."
296 echo ""
297 cp -f $ConfFile $InstallDir/$TargetDir/refind.conf
298 if [[ $? != 0 ]] ; then
299 Problems=1
300 fi
301 fi
302 if [[ $DeleteRefindDir == 1 ]] ; then
303 echo "Deleting the temporary directory $RefindDir"
304 rm -r $RefindDir
305 fi
306 } # CopyRefindFiles()
307
308 # Mount the partition the user specified with the --usedefault option
309 MountDefaultTarget() {
310 InstallDir=/tmp/refind_install
311 mkdir -p $InstallDir
312 if [[ $OSName == 'Darwin' ]] ; then
313 mount -t msdos $TargetPart $InstallDir
314 elif [[ $OSName == 'Linux' ]] ; then
315 mount -t vfat $TargetPart $InstallDir
316 fi
317 if [[ $? != 0 ]] ; then
318 echo "Couldn't mount $TargetPart ! Aborting!"
319 rmdir $InstallDir
320 exit 1
321 fi
322 UnmountEsp=1
323 } # MountDefaultTarget()
324
325 #
326 # A series of OS X support functions....
327 #
328
329 # Mount the ESP at /Volumes/ESP or determine its current mount
330 # point.
331 # Sets InstallDir to the ESP mount point
332 # Sets UnmountEsp if we mounted it
333 MountOSXESP() {
334 # Identify the ESP. Note: This returns the FIRST ESP found;
335 # if the system has multiple disks, this could be wrong!
336 Temp=`diskutil list | grep " EFI "`
337 Esp=/dev/`echo $Temp | cut -f 5 -d ' '`
338 # If the ESP is mounted, use its current mount point....
339 Temp=`df | grep $Esp`
340 InstallDir=`echo $Temp | cut -f 6 -d ' '`
341 if [[ $InstallDir == '' ]] ; then
342 mkdir /Volumes/ESP &> /dev/null
343 mount -t msdos $Esp /Volumes/ESP
344 if [[ $? != 0 ]] ; then
345 echo "Unable to mount ESP! Aborting!\n"
346 exit 1
347 fi
348 UnmountEsp=1
349 InstallDir="/Volumes/ESP"
350 fi
351 } # MountOSXESP()
352
353 # Control the OS X installation.
354 # Sets Problems=1 if problems found during the installation.
355 InstallOnOSX() {
356 echo "Installing rEFInd on OS X...."
357 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
358 MountDefaultTarget
359 elif [[ $InstallToEspOnMac == "1" ]] ; then
360 MountOSXESP
361 else
362 InstallDir="$RootDir/"
363 fi
364 echo "Installing rEFInd to the partition mounted at '$InstallDir'"
365 Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
366 CopyRefindFiles
367 if [[ $InstallToEspOnMac == "1" ]] ; then
368 bless --mount $InstallDir --setBoot --file $InstallDir/$TargetDir/$Refind
369 elif [[ $TargetDir != "/EFI/BOOT" ]] ; then
370 bless --setBoot --folder $InstallDir/$TargetDir --file $InstallDir/$TargetDir/$Refind
371 fi
372 if [[ $? != 0 ]] ; then
373 Problems=1
374 fi
375 if [[ -f /Library/StartupItems/rEFItBlesser || -d /Library/StartupItems/rEFItBlesser ]] ; then
376 echo
377 echo "/Library/StartupItems/rEFItBlesser found!"
378 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
379 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
380 read YesNo
381 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
382 echo "Deleting /Library/StartupItems/rEFItBlesser..."
383 rm -r /Library/StartupItems/rEFItBlesser
384 else
385 echo "Not deleting rEFItBlesser."
386 fi
387 fi
388 echo
389 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
390 echo "bless status with 'bless --info', since this is known to cause disk corruption"
391 echo "on some systems!!"
392 echo
393 } # InstallOnOSX()
394
395
396 #
397 # Now a series of Linux support functions....
398 #
399
400 # Check for evidence that we're running in Secure Boot mode. If so, and if
401 # appropriate options haven't been set, warn the user and offer to abort.
402 # If we're NOT in Secure Boot mode but the user HAS specified the --shim
403 # or --localkeys option, warn the user and offer to abort.
404 #
405 # FIXME: Although I checked the presence (and lack thereof) of the
406 # /sys/firmware/efi/vars/SecureBoot* files on my Secure Boot test system
407 # before releasing this script, I've since found that they are at least
408 # sometimes present when Secure Boot is absent. This means that the first
409 # test can produce false alarms. A better test is highly desirable.
410 CheckSecureBoot() {
411 VarFile=`ls -d /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
412 if [[ -n $VarFile && $TargetDir != '/EFI/BOOT' && $ShimSource == "none" ]] ; then
413 echo ""
414 echo "CAUTION: Your computer appears to support Secure Boot, but you haven't"
415 echo "specified a valid shim.efi file source. If you've disabled Secure Boot and"
416 echo "intend to leave it disabled, this is fine; but if Secure Boot is active, the"
417 echo "resulting installation won't boot. You can read more about this topic at"
418 echo "http://www.rodsbooks.com/refind/secureboot.html."
419 echo ""
420 echo -n "Do you want to proceed with installation (Y/N)? "
421 read ContYN
422 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
423 echo "OK; continuing with the installation..."
424 else
425 exit 0
426 fi
427 fi
428
429 if [[ $ShimSource != "none" && ! -n $VarFile ]] ; then
430 echo ""
431 echo "You've specified installing using a shim.efi file, but your computer does not"
432 echo "appear to be running in Secure Boot mode. Although installing in this way"
433 echo "should work, it's unnecessarily complex. You may continue, but unless you"
434 echo "plan to enable Secure Boot, you should consider stopping and omitting the"
435 echo "--shim option. You can read more about this topic at"
436 echo "http://www.rodsbooks.com/refind/secureboot.html."
437 echo ""
438 echo -n "Do you want to proceed with installation (Y/N)? "
439 read ContYN
440 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
441 echo "OK; continuing with the installation..."
442 else
443 exit 0
444 fi
445 fi
446
447 if [[ $LocalKeys != 0 && ! -n $VarFile ]] ; then
448 echo ""
449 echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
450 echo "but your computer does not appear to be running in Secure Boot mode. The"
451 echo "keys you generate will be useless unless you enable Secure Boot. You may"
452 echo "proceed with this installation, but before you do so, you may want to read"
453 echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
454 echo ""
455 echo -n "Do you want to proceed with installation (Y/N)? "
456 read ContYN
457 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
458 echo "OK; continuing with the installation..."
459 else
460 exit 0
461 fi
462 fi
463
464 } # CheckSecureBoot()
465
466 # Check for the presence of locally-generated keys from a previous installation in
467 # $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
468 # openssl.
469 GenerateKeys() {
470 PrivateKey=$EtcKeysDir/$LocalKeysBase.key
471 CertKey=$EtcKeysDir/$LocalKeysBase.crt
472 DerKey=$EtcKeysDir/$LocalKeysBase.cer
473 OpenSSL=`which openssl 2> /dev/null`
474
475 # Do the work only if one or more of the necessary keys is missing
476 # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
477 # is also missing, this will fail. This could be improved.
478 if [[ ! -f $PrivateKey || ! -f $CertKey || ! -f $DerKey ]] ; then
479 echo "Generating a fresh set of local keys...."
480 mkdir -p $EtcKeysDir
481 chmod 0700 $EtcKeysDir
482 if [[ ! -x $OpenSSL ]] ; then
483 echo "Can't find openssl, which is required to create your private signing keys!"
484 echo "Aborting!"
485 exit 1
486 fi
487 if [[ -f $PrivateKey ]] ; then
488 echo "Backing up existing $PrivateKey"
489 cp -f $PrivateKey $PrivateKey.backup 2> /dev/null
490 fi
491 if [[ -f $CertKey ]] ; then
492 echo "Backing up existing $CertKey"
493 cp -f $CertKey $CertKey.backup 2> /dev/null
494 fi
495 if [[ -f $DerKey ]] ; then
496 echo "Backing up existing $DerKey"
497 cp -f $DerKey $DerKey.backup 2> /dev/null
498 fi
499 $OpenSSL req -new -x509 -newkey rsa:2048 -keyout $PrivateKey -out $CertKey \
500 -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
501 $OpenSSL x509 -in $CertKey -out $DerKey -outform DER
502 chmod 0600 $PrivateKey
503 else
504 echo "Using existing local keys...."
505 fi
506 }
507
508 # Sign a single binary. Requires parameters:
509 # $1 = source file
510 # $2 = destination file
511 # Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
512 # appropriately.
513 # Aborts script on error
514 SignOneBinary() {
515 $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
516 if [[ $? != 0 ]] ; then
517 echo "Problem signing the binary $1! Aborting!"
518 exit 1
519 fi
520 }
521
522 # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
523 # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
524 # not, try to generate new keys and store them in $EtcKeysDir.
525 ReSignBinaries() {
526 SBSign=`which sbsign 2> /dev/null`
527 echo "Found sbsign at $SBSign"
528 TempDir="/tmp/refind_local"
529 if [[ ! -x $SBSign ]] ; then
530 echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
531 echo "Aborting!"
532 exit 1
533 fi
534 GenerateKeys
535 mkdir -p $TempDir/drivers_x64
536 cp $RefindDir/refind.conf-sample $TempDir 2> /dev/null
537 cp $ThisDir/refind.conf-sample $TempDir 2> /dev/null
538 cp $RefindDir/refind_ia32.efi $TempDir
539 cp -a $RefindDir/drivers_ia32 $TempDir 2> /dev/null
540 cp -a $ThisDir/drivers_ia32 $TempDir 2> /dev/null
541 SignOneBinary $RefindDir/refind_x64.efi $TempDir/refind_x64.efi
542 for Driver in `ls $RefindDir/drivers_x64/*.efi $ThisDir/drivers_x64/*.efi 2> /dev/null` ; do
543 TempName=`basename $Driver`
544 SignOneBinary $Driver $TempDir/drivers_x64/$TempName
545 done
546 RefindDir=$TempDir
547 DeleteRefindDir=1
548 }
549
550 # Identifies the ESP's location (/boot or /boot/efi, or these locations under
551 # the directory specified by --root); aborts if the ESP isn't mounted at
552 # either location.
553 # Sets InstallDir to the ESP mount point.
554 FindLinuxESP() {
555 EspLine=`df $RootDir/boot/efi 2> /dev/null | grep boot/efi`
556 if [[ ! -n $EspLine ]] ; then
557 EspLine=`df $RootDir/boot | grep boot`
558 fi
559 InstallDir=`echo $EspLine | cut -d " " -f 6`
560 if [[ -n $InstallDir ]] ; then
561 EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
562 fi
563 if [[ $EspFilesystem != 'vfat' ]] ; then
564 echo "$RootDir/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be"
565 echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
566 exit 1
567 fi
568 echo "ESP was found at $InstallDir using $EspFilesystem"
569 } # MountLinuxESP
570
571 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
572 # If this fails, sets Problems=1
573 AddBootEntry() {
574 InstallIt="0"
575 Efibootmgr=`which efibootmgr 2> /dev/null`
576 if [[ $Efibootmgr ]] ; then
577 modprobe efivars &> /dev/null
578 InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
579 PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
580 EntryFilename=$TargetDir/$Refind
581 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
582 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
583 ExistingEntry=`$Efibootmgr -v | grep $EfiEntryFilename2`
584 # NOTE: Below protects against duplicate entries, but only for non-Secure Boot
585 # installations.
586 # TODO: Improve to detect & protect against duplicating a Secure Boot entry.
587 if [[ $ExistingEntry && $ShimSource == "none" ]] ; then
588 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
589 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
590 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
591 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
592 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
593 echo "manager. If this is NOT what you want, you should use efibootmgr to"
594 echo "manually adjust your EFI's boot order."
595 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
596 InstallIt="1"
597 fi
598 else
599 InstallIt="1"
600 fi
601 if [[ $InstallIt == "1" ]] ; then
602 echo "Installing it!"
603 $Efibootmgr -c -l $EfiEntryFilename -L rEFInd -d $InstallDisk -p $PartNum &> /dev/null
604 if [[ $? != 0 ]] ; then
605 EfibootmgrProblems=1
606 Problems=1
607 fi
608 fi
609 else
610 EfibootmgrProblems=1
611 Problems=1
612 fi
613 if [[ $EfibootmgrProblems ]] ; then
614 echo
615 echo "ALERT: There were problems running the efibootmgr program! You may need to"
616 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
617 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
618 echo
619 fi
620 } # AddBootEntry()
621
622 # Create a minimal/sample refind_linux.conf file in /boot.
623 GenerateRefindLinuxConf() {
624 if [[ ! -f $RLConfFile ]] ; then
625 if [[ -f "$RootDir/etc/default/grub" ]] ; then
626 # We want the default options used by the distribution, stored here....
627 source "$RootDir/etc/default/grub"
628 fi
629 RootFS=`df $RootDir | grep dev | cut -f 1 -d " "`
630 StartOfDevname=`echo $RootFS | cut -b 1-7`
631 if [[ $StartOfDevname == "/dev/sd" || $StartOfDevName == "/dev/hd" ]] ; then
632 # Identify root filesystem by UUID rather than by device node, if possible
633 Uuid=`blkid -o export $RootFS 2> /dev/null | grep UUID=`
634 if [[ -n $Uuid ]] ; then
635 RootFS=$Uuid
636 fi
637 fi
638 DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
639 echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
640 echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
641 echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
642 fi
643 }
644
645 # Controls rEFInd installation under Linux.
646 # Sets Problems=1 if something goes wrong.
647 InstallOnLinux() {
648 echo "Installing rEFInd on Linux...."
649 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
650 MountDefaultTarget
651 else
652 FindLinuxESP
653 fi
654 CpuType=`uname -m`
655 if [[ $CpuType == 'x86_64' ]] ; then
656 Platform="EFI64"
657 if [[ $LocalKeys == 1 ]] ; then
658 ReSignBinaries
659 fi
660 elif [[ $CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686' ]] ; then
661 if [[ $ShimSource != "none" && $TargetDir != "/BOOT/EFI" ]] ; then
662 echo ""
663 echo "CAUTION: Neither rEFInd nor shim currently supports 32-bit systems, so you"
664 echo "should not use the --shim option to install on such systems. Aborting!"
665 echo ""
666 exit 1
667 fi
668 Platform="EFI32"
669 echo
670 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
671 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
672 echo "on a 64-bit computer, you should manually install the 64-bit version of"
673 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
674 echo "you're positive you want to continue with this installation, answer 'Y'"
675 echo "to the following question..."
676 echo
677 echo -n "Are you sure you want to continue (Y/N)? "
678 read ContYN
679 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
680 echo "OK; continuing with the installation..."
681 else
682 exit 0
683 fi
684 else
685 echo "Unknown CPU type '$CpuType'; aborting!"
686 exit 1
687 fi
688 CheckSecureBoot
689 CopyRefindFiles
690 if [[ $TargetDir != "/EFI/BOOT" ]] ; then
691 AddBootEntry
692 GenerateRefindLinuxConf
693 fi
694 } # InstallOnLinux()
695
696 #
697 # The main part of the script. Sets a few environment variables,
698 # performs a few startup checks, and then calls functions to
699 # install under OS X or Linux, depending on the detected platform.
700 #
701
702 OSName=`uname -s`
703 GetParams $@
704 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
705 RefindDir="$ThisDir/refind"
706 ThisScript="$ThisDir/`basename $0`"
707 if [[ `whoami` != "root" ]] ; then
708 echo "Not running as root; attempting to elevate privileges via sudo...."
709 sudo $ThisScript "$@"
710 if [[ $? != 0 ]] ; then
711 echo "This script must be run as root (or using sudo). Exiting!"
712 exit 1
713 else
714 exit 0
715 fi
716 fi
717 CheckForFiles
718 if [[ $OSName == 'Darwin' ]] ; then
719 if [[ $ShimSource != "none" ]] ; then
720 echo "The --shim option is not supported on OS X! Exiting!"
721 exit 1
722 fi
723 if [[ $LocalKeys != 0 ]] ; then
724 echo "The --localkeys option is not supported on OS X! Exiting!"
725 exit 1
726 fi
727 InstallOnOSX $1
728 elif [[ $OSName == 'Linux' ]] ; then
729 InstallOnLinux
730 else
731 echo "Running on unknown OS; aborting!"
732 fi
733
734 if [[ $Problems ]] ; then
735 echo
736 echo "ALERT:"
737 echo "Installation has completed, but problems were detected. Review the output for"
738 echo "error messages and take corrective measures as necessary. You may need to"
739 echo "re-run this script or install manually before rEFInd will work."
740 echo
741 else
742 echo
743 echo "Installation has completed successfully."
744 echo
745 fi
746
747 if [[ $UnmountEsp ]] ; then
748 echo "Unmounting install dir"
749 umount $InstallDir
750 fi
751
752 if [[ $InstallDir == /tmp/refind_install ]] ; then
753 # sleep 5
754 rmdir $InstallDir
755 fi