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