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