]> code.delx.au - refind/blob - install.sh
Changes to RPM .spec file and installation script to make for better
[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
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 # NOTE: Below protects against duplicate entries, but only for non-Secure Boot
603 # installations.
604 # TODO: Improve to detect & protect against duplicating a Secure Boot entry.
605 if [[ $ExistingEntry && $ShimSource == "none" ]] ; then
606 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
607 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
608 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
609 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
610 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
611 echo "manager. If this is NOT what you want, you should use efibootmgr to"
612 echo "manually adjust your EFI's boot order."
613 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
614 InstallIt="1"
615 fi
616 else
617 InstallIt="1"
618 fi
619 if [[ $InstallIt == "1" ]] ; then
620 echo "Installing it!"
621 $Efibootmgr -c -l $EfiEntryFilename -L rEFInd -d $InstallDisk -p $PartNum &> /dev/null
622 if [[ $? != 0 ]] ; then
623 EfibootmgrProblems=1
624 Problems=1
625 fi
626 fi
627 else
628 EfibootmgrProblems=1
629 Problems=1
630 fi
631 if [[ $EfibootmgrProblems ]] ; then
632 echo
633 echo "ALERT: There were problems running the efibootmgr program! You may need to"
634 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
635 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
636 echo
637 fi
638 } # AddBootEntry()
639
640 # Create a minimal/sample refind_linux.conf file in /boot.
641 GenerateRefindLinuxConf() {
642 if [[ -f $RLConfFile ]] ; then
643 echo "Existing $RLConfFile found; not overwriting."
644 else
645 if [[ -f "$RootDir/etc/default/grub" ]] ; then
646 # We want the default options used by the distribution, stored here....
647 source "$RootDir/etc/default/grub"
648 fi
649 RootFS=`df $RootDir | grep dev | cut -f 1 -d " "`
650 StartOfDevname=`echo $RootFS | cut -b 1-7`
651 if [[ $StartOfDevname == "/dev/sd" || $StartOfDevName == "/dev/hd" ]] ; then
652 # Identify root filesystem by UUID rather than by device node, if possible
653 Uuid=`blkid -o export $RootFS 2> /dev/null | grep UUID=`
654 if [[ -n $Uuid ]] ; then
655 RootFS=$Uuid
656 fi
657 fi
658 DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
659 echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
660 echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
661 echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
662 fi
663 }
664
665 # Controls rEFInd installation under Linux.
666 # Sets Problems=1 if something goes wrong.
667 InstallOnLinux() {
668 echo "Installing rEFInd on Linux...."
669 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
670 MountDefaultTarget
671 else
672 FindLinuxESP
673 fi
674 CpuType=`uname -m`
675 if [[ $CpuType == 'x86_64' ]] ; then
676 Platform="EFI64"
677 if [[ $LocalKeys == 1 ]] ; then
678 ReSignBinaries
679 fi
680 elif [[ $CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686' ]] ; then
681 if [[ $ShimSource != "none" && $TargetDir != "/BOOT/EFI" ]] ; then
682 echo ""
683 echo "CAUTION: Neither rEFInd nor shim currently supports 32-bit systems, so you"
684 echo "should not use the --shim option to install on such systems. Aborting!"
685 echo ""
686 exit 1
687 fi
688 Platform="EFI32"
689 echo
690 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
691 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
692 echo "on a 64-bit computer, you should manually install the 64-bit version of"
693 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
694 echo "you're positive you want to continue with this installation, answer 'Y'"
695 echo "to the following question..."
696 echo
697 echo -n "Are you sure you want to continue (Y/N)? "
698 ReadYesNo
699 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
700 echo "OK; continuing with the installation..."
701 else
702 exit 0
703 fi
704 else
705 echo "Unknown CPU type '$CpuType'; aborting!"
706 exit 1
707 fi
708 CheckSecureBoot
709 CopyRefindFiles
710 if [[ $TargetDir != "/EFI/BOOT" ]] ; then
711 AddBootEntry
712 GenerateRefindLinuxConf
713 fi
714 } # InstallOnLinux()
715
716 #
717 # The main part of the script. Sets a few environment variables,
718 # performs a few startup checks, and then calls functions to
719 # install under OS X or Linux, depending on the detected platform.
720 #
721
722 OSName=`uname -s`
723 GetParams $@
724 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
725 RefindDir="$ThisDir/refind"
726 ThisScript="$ThisDir/`basename $0`"
727 if [[ `whoami` != "root" ]] ; then
728 echo "Not running as root; attempting to elevate privileges via sudo...."
729 sudo $ThisScript "$@"
730 if [[ $? != 0 ]] ; then
731 echo "This script must be run as root (or using sudo). Exiting!"
732 exit 1
733 else
734 exit 0
735 fi
736 fi
737 CheckForFiles
738 if [[ $OSName == 'Darwin' ]] ; then
739 if [[ $ShimSource != "none" ]] ; then
740 echo "The --shim option is not supported on OS X! Exiting!"
741 exit 1
742 fi
743 if [[ $LocalKeys != 0 ]] ; then
744 echo "The --localkeys option is not supported on OS X! Exiting!"
745 exit 1
746 fi
747 InstallOnOSX $1
748 elif [[ $OSName == 'Linux' ]] ; then
749 InstallOnLinux
750 else
751 echo "Running on unknown OS; aborting!"
752 fi
753
754 if [[ $Problems ]] ; then
755 echo
756 echo "ALERT:"
757 echo "Installation has completed, but problems were detected. Review the output for"
758 echo "error messages and take corrective measures as necessary. You may need to"
759 echo "re-run this script or install manually before rEFInd will work."
760 echo
761 else
762 echo
763 echo "Installation has completed successfully."
764 echo
765 fi
766
767 if [[ $UnmountEsp ]] ; then
768 echo "Unmounting install dir"
769 umount $InstallDir
770 fi
771
772 if [[ $InstallDir == /tmp/refind_install ]] ; then
773 # sleep 5
774 rmdir $InstallDir
775 fi