]> code.delx.au - refind/blob - install.sh
0559d584412e8c8f83d3a961f809f2b60dd644b9
[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 esac
210 if [[ -n $BootFS ]] ; then
211 echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
212 mkdir -p $InstallDir/$TargetDir/drivers_$1
213 cp $RefindDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
214 cp $ThisDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
215 fi
216 fi
217 }
218
219 # Copy the rEFInd files to the ESP or OS X root partition.
220 # Sets Problems=1 if any critical commands fail.
221 CopyRefindFiles() {
222 mkdir -p $InstallDir/$TargetDir &> /dev/null
223 if [[ $TargetDir == '/EFI/BOOT' ]] ; then
224 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 2> /dev/null
225 if [[ $? != 0 ]] ; then
226 echo "Note: IA32 (x86) binary not installed!"
227 fi
228 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64 2> /dev/null
229 if [[ $? != 0 ]] ; then
230 Problems=1
231 fi
232 if [[ $ShimSource != "none" ]] ; then
233 TargetShim="bootx64.efi"
234 CopyShimFiles
235 fi
236 if [[ $InstallDrivers == "all" ]] ; then
237 cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
238 cp -r $ThisDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
239 fi
240 Refind=""
241 CopyKeys
242 elif [[ $Platform == 'EFI32' ]] ; then
243 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32
244 if [[ $? != 0 ]] ; then
245 Problems=1
246 fi
247 CopyDrivers ia32
248 Refind="refind_ia32.efi"
249 elif [[ $Platform == 'EFI64' ]] ; then
250 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64
251 if [[ $? != 0 ]] ; then
252 Problems=1
253 fi
254 CopyDrivers x64
255 Refind="refind_x64.efi"
256 CopyKeys
257 if [[ $ShimSource != "none" ]] ; then
258 TargetShim=`basename $ShimSource`
259 CopyShimFiles
260 Refind=$TargetShim
261 if [[ $LocalKeys == 0 ]] ; then
262 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
263 mkdir -p $EtcKeysDir
264 cp $ThisDir/keys/refind.cer $EtcKeysDir
265 cp $ThisDir/keys/refind.crt $EtcKeysDir
266 fi
267 fi
268 else
269 echo "Unknown platform! Aborting!"
270 exit 1
271 fi
272 echo "Copied rEFInd binary files"
273 echo ""
274 if [[ -d $InstallDir/$TargetDir/icons ]] ; then
275 rm -rf $InstallDir/$TargetDir/icons-backup &> /dev/null
276 mv -f $InstallDir/$TargetDir/icons $InstallDir/$TargetDir/icons-backup
277 echo "Notice: Backed up existing icons directory as icons-backup."
278 fi
279 cp -r $IconsDir $InstallDir/$TargetDir
280 if [[ $? != 0 ]] ; then
281 Problems=1
282 fi
283 cp -rf $ThisDir/keys $InstallDir/$TargetDir/
284 if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then
285 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
286 echo "to avoid overwriting your customizations."
287 echo ""
288 cp -f $ConfFile $InstallDir/$TargetDir
289 if [[ $? != 0 ]] ; then
290 Problems=1
291 fi
292 else
293 echo "Copying sample configuration file as refind.conf; edit this file to configure"
294 echo "rEFInd."
295 echo ""
296 cp -f $ConfFile $InstallDir/$TargetDir/refind.conf
297 if [[ $? != 0 ]] ; then
298 Problems=1
299 fi
300 fi
301 if [[ $DeleteRefindDir == 1 ]] ; then
302 echo "Deleting the temporary directory $RefindDir"
303 rm -r $RefindDir
304 fi
305 } # CopyRefindFiles()
306
307 # Mount the partition the user specified with the --usedefault option
308 MountDefaultTarget() {
309 InstallDir=/tmp/refind_install
310 mkdir -p $InstallDir
311 if [[ $OSName == 'Darwin' ]] ; then
312 mount -t msdos $TargetPart $InstallDir
313 elif [[ $OSName == 'Linux' ]] ; then
314 mount -t vfat $TargetPart $InstallDir
315 fi
316 if [[ $? != 0 ]] ; then
317 echo "Couldn't mount $TargetPart ! Aborting!"
318 rmdir $InstallDir
319 exit 1
320 fi
321 UnmountEsp=1
322 } # MountDefaultTarget()
323
324 #
325 # A series of OS X support functions....
326 #
327
328 # Mount the ESP at /Volumes/ESP or determine its current mount
329 # point.
330 # Sets InstallDir to the ESP mount point
331 # Sets UnmountEsp if we mounted it
332 MountOSXESP() {
333 # Identify the ESP. Note: This returns the FIRST ESP found;
334 # if the system has multiple disks, this could be wrong!
335 Temp=`diskutil list | grep " EFI "`
336 Esp=/dev/`echo $Temp | cut -f 5 -d ' '`
337 # If the ESP is mounted, use its current mount point....
338 Temp=`df | grep $Esp`
339 InstallDir=`echo $Temp | cut -f 6 -d ' '`
340 if [[ $InstallDir == '' ]] ; then
341 mkdir /Volumes/ESP &> /dev/null
342 mount -t msdos $Esp /Volumes/ESP
343 if [[ $? != 0 ]] ; then
344 echo "Unable to mount ESP! Aborting!\n"
345 exit 1
346 fi
347 UnmountEsp=1
348 InstallDir="/Volumes/ESP"
349 fi
350 } # MountOSXESP()
351
352 # Control the OS X installation.
353 # Sets Problems=1 if problems found during the installation.
354 InstallOnOSX() {
355 echo "Installing rEFInd on OS X...."
356 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
357 MountDefaultTarget
358 elif [[ $InstallToEspOnMac == "1" ]] ; then
359 MountOSXESP
360 else
361 InstallDir="$RootDir/"
362 fi
363 echo "Installing rEFInd to the partition mounted at '$InstallDir'"
364 Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
365 CopyRefindFiles
366 if [[ $InstallToEspOnMac == "1" ]] ; then
367 bless --mount $InstallDir --setBoot --file $InstallDir/$TargetDir/$Refind
368 elif [[ $TargetDir != "/EFI/BOOT" ]] ; then
369 bless --setBoot --folder $InstallDir/$TargetDir --file $InstallDir/$TargetDir/$Refind
370 fi
371 if [[ $? != 0 ]] ; then
372 Problems=1
373 fi
374 if [[ -f /Library/StartupItems/rEFItBlesser || -d /Library/StartupItems/rEFItBlesser ]] ; then
375 echo
376 echo "/Library/StartupItems/rEFItBlesser found!"
377 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
378 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
379 read YesNo
380 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
381 echo "Deleting /Library/StartupItems/rEFItBlesser..."
382 rm -r /Library/StartupItems/rEFItBlesser
383 else
384 echo "Not deleting rEFItBlesser."
385 fi
386 fi
387 echo
388 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
389 echo "bless status with 'bless --info', since this is known to cause disk corruption"
390 echo "on some systems!!"
391 echo
392 } # InstallOnOSX()
393
394
395 #
396 # Now a series of Linux support functions....
397 #
398
399 # Check for evidence that we're running in Secure Boot mode. If so, and if
400 # appropriate options haven't been set, warn the user and offer to abort.
401 # If we're NOT in Secure Boot mode but the user HAS specified the --shim
402 # or --localkeys option, warn the user and offer to abort.
403 #
404 # FIXME: Although I checked the presence (and lack thereof) of the
405 # /sys/firmware/efi/vars/SecureBoot* files on my Secure Boot test system
406 # before releasing this script, I've since found that they are at least
407 # sometimes present when Secure Boot is absent. This means that the first
408 # test can produce false alarms. A better test is highly desirable.
409 CheckSecureBoot() {
410 VarFile=`ls -d /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
411 if [[ -n $VarFile && $TargetDir != '/EFI/BOOT' && $ShimSource == "none" ]] ; then
412 echo ""
413 echo "CAUTION: Your computer appears to support Secure Boot, but you haven't"
414 echo "specified a valid shim.efi file source. If you've disabled Secure Boot and"
415 echo "intend to leave it disabled, this is fine; but if Secure Boot is active, the"
416 echo "resulting installation won't boot. You can read more about this topic at"
417 echo "http://www.rodsbooks.com/refind/secureboot.html."
418 echo ""
419 echo -n "Do you want to proceed with installation (Y/N)? "
420 read ContYN
421 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
422 echo "OK; continuing with the installation..."
423 else
424 exit 0
425 fi
426 fi
427
428 if [[ $ShimSource != "none" && ! -n $VarFile ]] ; then
429 echo ""
430 echo "You've specified installing using a shim.efi file, but your computer does not"
431 echo "appear to be running in Secure Boot mode. Although installing in this way"
432 echo "should work, it's unnecessarily complex. You may continue, but unless you"
433 echo "plan to enable Secure Boot, you should consider stopping and omitting the"
434 echo "--shim option. You can read more about this topic at"
435 echo "http://www.rodsbooks.com/refind/secureboot.html."
436 echo ""
437 echo -n "Do you want to proceed with installation (Y/N)? "
438 read ContYN
439 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
440 echo "OK; continuing with the installation..."
441 else
442 exit 0
443 fi
444 fi
445
446 if [[ $LocalKeys != 0 && ! -n $VarFile ]] ; then
447 echo ""
448 echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
449 echo "but your computer does not appear to be running in Secure Boot mode. The"
450 echo "keys you generate will be useless unless you enable Secure Boot. You may"
451 echo "proceed with this installation, but before you do so, you may want to read"
452 echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
453 echo ""
454 echo -n "Do you want to proceed with installation (Y/N)? "
455 read ContYN
456 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
457 echo "OK; continuing with the installation..."
458 else
459 exit 0
460 fi
461 fi
462
463 } # CheckSecureBoot()
464
465 # Check for the presence of locally-generated keys from a previous installation in
466 # $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
467 # openssl.
468 GenerateKeys() {
469 PrivateKey=$EtcKeysDir/$LocalKeysBase.key
470 CertKey=$EtcKeysDir/$LocalKeysBase.crt
471 DerKey=$EtcKeysDir/$LocalKeysBase.cer
472 OpenSSL=`which openssl 2> /dev/null`
473
474 # Do the work only if one or more of the necessary keys is missing
475 # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
476 # is also missing, this will fail. This could be improved.
477 if [[ ! -f $PrivateKey || ! -f $CertKey || ! -f $DerKey ]] ; then
478 echo "Generating a fresh set of local keys...."
479 mkdir -p $EtcKeysDir
480 chmod 0700 $EtcKeysDir
481 if [[ ! -x $OpenSSL ]] ; then
482 echo "Can't find openssl, which is required to create your private signing keys!"
483 echo "Aborting!"
484 exit 1
485 fi
486 if [[ -f $PrivateKey ]] ; then
487 echo "Backing up existing $PrivateKey"
488 cp -f $PrivateKey $PrivateKey.backup 2> /dev/null
489 fi
490 if [[ -f $CertKey ]] ; then
491 echo "Backing up existing $CertKey"
492 cp -f $CertKey $CertKey.backup 2> /dev/null
493 fi
494 if [[ -f $DerKey ]] ; then
495 echo "Backing up existing $DerKey"
496 cp -f $DerKey $DerKey.backup 2> /dev/null
497 fi
498 $OpenSSL req -new -x509 -newkey rsa:2048 -keyout $PrivateKey -out $CertKey \
499 -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
500 $OpenSSL x509 -in $CertKey -out $DerKey -outform DER
501 chmod 0600 $PrivateKey
502 else
503 echo "Using existing local keys...."
504 fi
505 }
506
507 # Sign a single binary. Requires parameters:
508 # $1 = source file
509 # $2 = destination file
510 # Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
511 # appropriately.
512 # Aborts script on error
513 SignOneBinary() {
514 $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
515 if [[ $? != 0 ]] ; then
516 echo "Problem signing the binary $1! Aborting!"
517 exit 1
518 fi
519 }
520
521 # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
522 # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
523 # not, try to generate new keys and store them in $EtcKeysDir.
524 ReSignBinaries() {
525 SBSign=`which sbsign 2> /dev/null`
526 echo "Found sbsign at $SBSign"
527 TempDir="/tmp/refind_local"
528 if [[ ! -x $SBSign ]] ; then
529 echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
530 echo "Aborting!"
531 exit 1
532 fi
533 GenerateKeys
534 mkdir -p $TempDir/drivers_x64
535 cp $RefindDir/refind.conf-sample $TempDir 2> /dev/null
536 cp $ThisDir/refind.conf-sample $TempDir 2> /dev/null
537 cp $RefindDir/refind_ia32.efi $TempDir
538 cp -a $RefindDir/drivers_ia32 $TempDir 2> /dev/null
539 cp -a $ThisDir/drivers_ia32 $TempDir 2> /dev/null
540 SignOneBinary $RefindDir/refind_x64.efi $TempDir/refind_x64.efi
541 for Driver in `ls $RefindDir/drivers_x64/*.efi $ThisDir/drivers_x64/*.efi 2> /dev/null` ; do
542 TempName=`basename $Driver`
543 SignOneBinary $Driver $TempDir/drivers_x64/$TempName
544 done
545 RefindDir=$TempDir
546 DeleteRefindDir=1
547 }
548
549 # Identifies the ESP's location (/boot or /boot/efi, or these locations under
550 # the directory specified by --root); aborts if the ESP isn't mounted at
551 # either location.
552 # Sets InstallDir to the ESP mount point.
553 FindLinuxESP() {
554 EspLine=`df $RootDir/boot/efi 2> /dev/null | grep boot/efi`
555 if [[ ! -n $EspLine ]] ; then
556 EspLine=`df $RootDir/boot | grep boot`
557 fi
558 InstallDir=`echo $EspLine | cut -d " " -f 6`
559 if [[ -n $InstallDir ]] ; then
560 EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
561 fi
562 if [[ $EspFilesystem != 'vfat' ]] ; then
563 echo "$RootDir/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be"
564 echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
565 exit 1
566 fi
567 echo "ESP was found at $InstallDir using $EspFilesystem"
568 } # MountLinuxESP
569
570 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
571 # If this fails, sets Problems=1
572 AddBootEntry() {
573 InstallIt="0"
574 Efibootmgr=`which efibootmgr 2> /dev/null`
575 if [[ $Efibootmgr ]] ; then
576 modprobe efivars &> /dev/null
577 InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
578 PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
579 EntryFilename=$TargetDir/$Refind
580 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
581 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
582 ExistingEntry=`$Efibootmgr -v | grep $EfiEntryFilename2`
583 # NOTE: Below protects against duplicate entries, but only for non-Secure Boot
584 # installations.
585 # TODO: Improve to detect & protect against duplicating a Secure Boot entry.
586 if [[ $ExistingEntry && $ShimSource == "none" ]] ; then
587 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
588 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
589 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
590 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
591 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
592 echo "manager. If this is NOT what you want, you should use efibootmgr to"
593 echo "manually adjust your EFI's boot order."
594 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
595 InstallIt="1"
596 fi
597 else
598 InstallIt="1"
599 fi
600 if [[ $InstallIt == "1" ]] ; then
601 echo "Installing it!"
602 $Efibootmgr -c -l $EfiEntryFilename -L rEFInd -d $InstallDisk -p $PartNum &> /dev/null
603 if [[ $? != 0 ]] ; then
604 EfibootmgrProblems=1
605 Problems=1
606 fi
607 fi
608 else
609 EfibootmgrProblems=1
610 Problems=1
611 fi
612 if [[ $EfibootmgrProblems ]] ; then
613 echo
614 echo "ALERT: There were problems running the efibootmgr program! You may need to"
615 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
616 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
617 echo
618 fi
619 } # AddBootEntry()
620
621 # Create a minimal/sample refind_linux.conf file in /boot.
622 GenerateRefindLinuxConf() {
623 if [[ ! -f $RLConfFile ]] ; then
624 if [[ -f /etc/default/grub ]] ; then
625 # We want the default options used by the distribution, stored here....
626 source /etc/default/grub
627 fi
628 RootFS=`df $RootDir | grep dev | cut -f 1 -d " "`
629 StartOfDevname=`echo $RootFS | cut -b 1-7`
630 if [[ $StartOfDevname == "/dev/sd" || $StartOfDevName == "/dev/hd" ]] ; then
631 # Identify root filesystem by UUID rather than by device node, if possible
632 Uuid=`blkid -o export $RootFS 2> /dev/null | grep UUID=`
633 if [[ -n $Uuid ]] ; then
634 RootFS=$Uuid
635 fi
636 fi
637 DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
638 echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
639 echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
640 echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
641 fi
642 }
643
644 # Controls rEFInd installation under Linux.
645 # Sets Problems=1 if something goes wrong.
646 InstallOnLinux() {
647 echo "Installing rEFInd on Linux...."
648 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
649 MountDefaultTarget
650 else
651 FindLinuxESP
652 fi
653 CpuType=`uname -m`
654 if [[ $CpuType == 'x86_64' ]] ; then
655 Platform="EFI64"
656 if [[ $LocalKeys == 1 ]] ; then
657 ReSignBinaries
658 fi
659 elif [[ $CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686' ]] ; then
660 if [[ $ShimSource != "none" && $TargetDir != "/BOOT/EFI" ]] ; then
661 echo ""
662 echo "CAUTION: Neither rEFInd nor shim currently supports 32-bit systems, so you"
663 echo "should not use the --shim option to install on such systems. Aborting!"
664 echo ""
665 exit 1
666 fi
667 Platform="EFI32"
668 echo
669 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
670 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
671 echo "on a 64-bit computer, you should manually install the 64-bit version of"
672 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
673 echo "you're positive you want to continue with this installation, answer 'Y'"
674 echo "to the following question..."
675 echo
676 echo -n "Are you sure you want to continue (Y/N)? "
677 read ContYN
678 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
679 echo "OK; continuing with the installation..."
680 else
681 exit 0
682 fi
683 else
684 echo "Unknown CPU type '$CpuType'; aborting!"
685 exit 1
686 fi
687 CheckSecureBoot
688 CopyRefindFiles
689 if [[ $TargetDir != "/EFI/BOOT" ]] ; then
690 AddBootEntry
691 GenerateRefindLinuxConf
692 fi
693 } # InstallOnLinux()
694
695 #
696 # The main part of the script. Sets a few environment variables,
697 # performs a few startup checks, and then calls functions to
698 # install under OS X or Linux, depending on the detected platform.
699 #
700
701 OSName=`uname -s`
702 GetParams $@
703 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
704 RefindDir="$ThisDir/refind"
705 ThisScript="$ThisDir/`basename $0`"
706 if [[ `whoami` != "root" ]] ; then
707 echo "Not running as root; attempting to elevate privileges via sudo...."
708 sudo $ThisScript "$@"
709 if [[ $? != 0 ]] ; then
710 echo "This script must be run as root (or using sudo). Exiting!"
711 exit 1
712 else
713 exit 0
714 fi
715 fi
716 CheckForFiles
717 if [[ $OSName == 'Darwin' ]] ; then
718 if [[ $ShimSource != "none" ]] ; then
719 echo "The --shim option is not supported on OS X! Exiting!"
720 exit 1
721 fi
722 if [[ $LocalKeys != 0 ]] ; then
723 echo "The --localkeys option is not supported on OS X! Exiting!"
724 exit 1
725 fi
726 InstallOnOSX $1
727 elif [[ $OSName == 'Linux' ]] ; then
728 InstallOnLinux
729 else
730 echo "Running on unknown OS; aborting!"
731 fi
732
733 if [[ $Problems ]] ; then
734 echo
735 echo "ALERT:"
736 echo "Installation has completed, but problems were detected. Review the output for"
737 echo "error messages and take corrective measures as necessary. You may need to"
738 echo "re-run this script or install manually before rEFInd will work."
739 echo
740 else
741 echo
742 echo "Installation has completed successfully."
743 echo
744 fi
745
746 if [[ $UnmountEsp ]] ; then
747 echo "Unmounting install dir"
748 umount $InstallDir
749 fi
750
751 if [[ $InstallDir == /tmp/refind_install ]] ; then
752 # sleep 5
753 rmdir $InstallDir
754 fi