]> code.delx.au - refind/blob - install.sh
Version 0.5.0 release.
[refind] / install.sh
1 #!/bin/bash
2 #
3 # Linux/MacOS X script to install rEFInd
4 #
5 # Usage:
6 #
7 # ./install.sh [options]
8 #
9 # options include:
10 # "--esp" to install to the ESP rather than to the system's root
11 # filesystem. This is the default on Linux
12 # "--usedefault {devicefile}" to install as default
13 # (/EFI/BOOT/BOOTX64.EFI and similar) to the specified
14 # device (/dev/sdd1 or whatever) without registering with
15 # the NVRAM
16 # "--drivers" to install drivers along with regular files
17 #
18 # The "esp" option is valid only on Mac OS X; it causes
19 # installation to the EFI System Partition (ESP) rather than
20 # to the current OS X boot partition. Under Linux, this script
21 # installs to the ESP by default.
22 #
23 # This program is copyright (c) 2012 by Roderick W. Smith
24 # It is released under the terms of the GNU GPL, version 3,
25 # a copy of which should be included in the file COPYING.txt.
26 #
27 # Revision history:
28 #
29 # 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
30 # 0.4.5 -- Fixed check for rEFItBlesser in OS X
31 # 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
32 # 0.4.1 -- Added check for rEFItBlesser in OS X
33 # 0.3.3.1 -- Fixed OS X 10.7 bug; also works as make target
34 # 0.3.2.1 -- Check for presence of source files; aborts if not present
35 # 0.3.2 -- Initial version
36 #
37 # Note: install.sh version numbers match those of the rEFInd package
38 # with which they first appeared.
39
40 TargetDir=/EFI/refind
41 EtcKeysDir=/etc/refind.d/keys
42 SBModeInstall=0
43
44 #
45 # Functions used by both OS X and Linux....
46 #
47
48 GetParams() {
49 InstallToEspOnMac=0
50 InstallDrivers=0
51 while [[ $# -gt 0 ]]; do
52 case $1 in
53 --esp | --ESP) InstallToEspOnMac=1
54 ;;
55 --usedefault) TargetDir=/EFI/BOOT
56 TargetPart=$2
57 shift
58 ;;
59 --drivers) InstallDrivers=1
60 ;;
61 * ) echo "Usage: $0 [--esp | --usedefault {device-file}] [--drivers]"
62 echo "Aborting!"
63 exit 1
64 esac
65 shift
66 done
67 if [[ $InstallToEspOnMac == 1 && $TargetDir == '/EFI/BOOT' ]] ; then
68 echo "You may use --esp OR --usedefault, but not both! Aborting!"
69 exit 1
70 fi
71 # exit 1
72 } # GetParams()
73
74 # Abort if the rEFInd files can't be found.
75 # Also sets $ConfFile to point to the configuration file, and
76 # $IconsDir to point to the icons directory
77 CheckForFiles() {
78 # Note: This check is satisfied if EITHER the 32- or the 64-bit version
79 # is found, even on the wrong platform. This is because the platform
80 # hasn't yet been determined. This could obviously be improved, but it
81 # would mean restructuring lots more code....
82 if [[ ! -f $RefindDir/refind_ia32.efi && ! -f $RefindDir/refind_x64.efi ]] ; then
83 echo "The rEFInd binary file is missing! Aborting installation!"
84 exit 1
85 fi
86
87 if [[ -f $RefindDir/refind.conf-sample ]] ; then
88 ConfFile=$RefindDir/refind.conf-sample
89 elif [[ -f $ThisDir/refind.conf-sample ]] ; then
90 ConfFile=$ThisDir/refind.conf-sample
91 else
92 echo "The sample configuration file is missing! Aborting installation!"
93 exit 1
94 fi
95
96 if [[ -d $RefindDir/icons ]] ; then
97 IconsDir=$RefindDir/icons
98 elif [[ -d $ThisDir/icons ]] ; then
99 IconsDir=$ThisDir/icons
100 else
101 echo "The icons directory is missing! Aborting installation!"
102 fi
103 } # CheckForFiles()
104
105 # Copy the rEFInd files to the ESP or OS X root partition.
106 # Sets Problems=1 if any critical commands fail.
107 CopyRefindFiles() {
108 mkdir -p $InstallDir/$TargetDir &> /dev/null
109 if [[ $TargetDir == '/EFI/BOOT' ]] ; then
110 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/bootia32.efi 2> /dev/null
111 if [[ $? != 0 ]] ; then
112 echo "Note: IA32 (x86) binary not installed!"
113 fi
114 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/bootx64.efi 2> /dev/null
115 if [[ $? != 0 ]] ; then
116 Problems=1
117 fi
118 if [[ $InstallDrivers == 1 ]] ; then
119 cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/
120 fi
121 Refind=""
122 cp $ThisDir/refind.cer $InstallDir/$TargetDir
123 cp $ThisDir/refind.crt $InstallDir/$TargetDir
124 elif [[ $Platform == 'EFI32' ]] ; then
125 cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir
126 if [[ $? != 0 ]] ; then
127 Problems=1
128 fi
129 if [[ $InstallDrivers == 1 ]] ; then
130 mkdir -p $InstallDir/$TargetDir/drivers_ia32
131 cp -r $RefindDir/drivers_ia32/*_ia32.efi $InstallDir/$TargetDir/drivers_ia32/
132 fi
133 Refind="refind_ia32.efi"
134 elif [[ $Platform == 'EFI64' ]] ; then
135 cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir
136 if [[ $? != 0 ]] ; then
137 Problems=1
138 fi
139 if [[ $InstallDrivers == 1 ]] ; then
140 mkdir -p $InstallDir/$TargetDir/drivers_x64
141 cp -r $RefindDir/drivers_x64/*_x64.efi $InstallDir/$TargetDir/drivers_x64/
142 fi
143 Refind="refind_x64.efi"
144 cp $ThisDir/refind.cer $InstallDir/$TargetDir
145 cp $ThisDir/refind.crt $InstallDir/$TargetDir
146 if [[ $SBModeInstall == 1 ]] ; then
147 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
148 mkdir -p $EtcKeysDir
149 cp $ThisDir/refind.cer $EtcKeysDir
150 cp $ThisDir/refind.crt $EtcKeysDir
151 fi
152 else
153 echo "Unknown platform! Aborting!"
154 exit 1
155 fi
156 echo "Copied rEFInd binary file $Refind"
157 echo ""
158 if [[ -d $InstallDir/$TargetDir/icons ]] ; then
159 rm -rf $InstallDir/$TargetDir/icons-backup &> /dev/null
160 mv -f $InstallDir/$TargetDir/icons $InstallDir/$TargetDir/icons-backup
161 echo "Notice: Backed up existing icons directory as icons-backup."
162 fi
163 cp -r $IconsDir $InstallDir/$TargetDir
164 if [[ $? != 0 ]] ; then
165 Problems=1
166 fi
167 if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then
168 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
169 echo "to avoid collision."
170 echo ""
171 cp -f $ConfFile $InstallDir/$TargetDir
172 if [[ $? != 0 ]] ; then
173 Problems=1
174 fi
175 else
176 echo "Copying sample configuration file as refind.conf; edit this file to configure"
177 echo "rEFInd."
178 echo ""
179 cp -f $ConfFile $InstallDir/$TargetDir/refind.conf
180 if [[ $? != 0 ]] ; then
181 Problems=1
182 fi
183 fi
184 } # CopyRefindFiles()
185
186 # Mount the partition the user specified with the --usedefault option
187 MountDefaultTarget() {
188 InstallDir=/tmp/refind_install
189 mkdir -p $InstallDir
190 if [[ $OSName == 'Darwin' ]] ; then
191 mount -t msdos $TargetPart $InstallDir
192 elif [[ $OSName == 'Linux' ]] ; then
193 mount -t vfat $TargetPart $InstallDir
194 fi
195 if [[ $? != 0 ]] ; then
196 echo "Couldn't mount $TargetPart ! Aborting!"
197 rmdir $InstallDir
198 exit 1
199 fi
200 UnmountEsp=1
201 } # MountDefaultTarget()
202
203 #
204 # A series of OS X support functions....
205 #
206
207 # Mount the ESP at /Volumes/ESP or determine its current mount
208 # point.
209 # Sets InstallDir to the ESP mount point
210 # Sets UnmountEsp if we mounted it
211 MountOSXESP() {
212 # Identify the ESP. Note: This returns the FIRST ESP found;
213 # if the system has multiple disks, this could be wrong!
214 Temp=`diskutil list | grep " EFI "`
215 Esp=/dev/`echo $Temp | cut -f 5 -d ' '`
216 # If the ESP is mounted, use its current mount point....
217 Temp=`df | grep $Esp`
218 InstallDir=`echo $Temp | cut -f 6 -d ' '`
219 if [[ $InstallDir == '' ]] ; then
220 mkdir /Volumes/ESP &> /dev/null
221 mount -t msdos $Esp /Volumes/ESP
222 if [[ $? != 0 ]] ; then
223 echo "Unable to mount ESP! Aborting!\n"
224 exit 1
225 fi
226 UnmountEsp=1
227 InstallDir="/Volumes/ESP"
228 fi
229 } # MountOSXESP()
230
231 # Control the OS X installation.
232 # Sets Problems=1 if problems found during the installation.
233 InstallOnOSX() {
234 echo "Installing rEFInd on OS X...."
235 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
236 MountDefaultTarget
237 elif [[ $InstallToEspOnMac == "1" ]] ; then
238 MountOSXESP
239 else
240 InstallDir="/"
241 fi
242 echo "Installing rEFInd to the partition mounted at '$InstallDir'"
243 Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
244 CopyRefindFiles
245 if [[ $InstallToEspOnMac == "1" ]] ; then
246 bless --mount $InstallDir --setBoot --file $InstallDir/$TargetDir/$Refind
247 elif [[ $TargetDir != "/EFI/BOOT" ]] ; then
248 bless --setBoot --folder $InstallDir/$TargetDir --file $InstallDir/$TargetDir/$Refind
249 fi
250 if [[ $? != 0 ]] ; then
251 Problems=1
252 fi
253 if [[ -f /Library/StartupItems/rEFItBlesser || -d /Library/StartupItems/rEFItBlesser ]] ; then
254 echo
255 echo "/Library/StartupItems/rEFItBlesser found!"
256 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
257 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
258 read YesNo
259 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
260 echo "Deleting /Library/StartupItems/rEFItBlesser..."
261 rm -r /Library/StartupItems/rEFItBlesser
262 else
263 echo "Not deleting rEFItBlesser."
264 fi
265 fi
266 echo
267 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
268 echo "bless status with 'bless --info', since this is known to cause disk corruption"
269 echo "on some systems!!"
270 echo
271 } # InstallOnOSX()
272
273
274 #
275 # Now a series of Linux support functions....
276 #
277
278 # Check for evidence that we're running in Secure Boot mode. If so, warn the
279 # user and confirm installation.
280 # TODO: Perform a reasonable Secure Boot installation.
281 CheckSecureBoot() {
282 VarFile=`ls -ld /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
283 if [[ -n $VarFile && $TargetDir != '/EFI/BOOT' ]] ; then
284 echo ""
285 echo "CAUTION: The computer seems to have been booted with Secure Boot active."
286 echo "Although rEFInd, when installed in conjunction with the shim boot loader, can"
287 echo "work on a Secure Boot computer, this installation script doesn't yet support"
288 echo "direct installation in a way that will work on such a computer. You may"
289 echo "proceed with installation with this script, but if you intend to boot with"
290 echo "Secure Boot active, you must then reconfigure your boot programs to add shim"
291 echo "to the process. Alternatively, you may terminate this script and do a manual"
292 echo "installation, as described at http://www.rodsbooks.com/refind/secureboot.html."
293 echo ""
294 echo -n "Do you want to proceed with installation (Y/N)? "
295 read ContYN
296 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
297 echo "OK; continuing with the installation..."
298 else
299 exit 0
300 SBModeInstall=1
301 fi
302 fi
303 }
304
305 # Identifies the ESP's location (/boot or /boot/efi); aborts if
306 # the ESP isn't mounted at either location.
307 # Sets InstallDir to the ESP mount point.
308 FindLinuxESP() {
309 EspLine=`df /boot/efi | grep boot`
310 InstallDir=`echo $EspLine | cut -d " " -f 6`
311 EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
312 if [[ $EspFilesystem != 'vfat' ]] ; then
313 echo "/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be mounted at"
314 echo "/boot or /boot/efi and it must be VFAT! Aborting!"
315 exit 1
316 fi
317 echo "ESP was found at $InstallDir using $EspFilesystem"
318 } # MountLinuxESP
319
320 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
321 # If this fails, sets Problems=1
322 AddBootEntry() {
323 InstallIt="0"
324 Efibootmgr=`which efibootmgr 2> /dev/null`
325 if [[ $Efibootmgr ]] ; then
326 modprobe efivars &> /dev/null
327 InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
328 PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
329 EntryFilename=$TargetDir/$Refind
330 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
331 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
332 ExistingEntry=`$Efibootmgr -v | grep $EfiEntryFilename2`
333 if [[ $ExistingEntry ]] ; then
334 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
335 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
336 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
337 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
338 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
339 echo "manager. If this is NOT what you want, you should use efibootmgr to"
340 echo "manually adjust your EFI's boot order."
341 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
342 InstallIt="1"
343 fi
344 else
345 InstallIt="1"
346 fi
347 if [[ $InstallIt == "1" ]] ; then
348 echo "Installing it!"
349 $Efibootmgr -c -l $EfiEntryFilename -L rEFInd -d $InstallDisk -p $PartNum &> /dev/null
350 if [[ $? != 0 ]] ; then
351 EfibootmgrProblems=1
352 Problems=1
353 fi
354 fi
355 else
356 EfibootmgrProblems=1
357 Problems=1
358 fi
359 if [[ $EfibootmgrProblems ]] ; then
360 echo
361 echo "ALERT: There were problems running the efibootmgr program! You may need to"
362 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
363 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
364 echo
365 fi
366 } # AddBootEntry()
367
368 # Controls rEFInd installation under Linux.
369 # Sets Problems=1 if something goes wrong.
370 InstallOnLinux() {
371 echo "Installing rEFInd on Linux...."
372 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
373 MountDefaultTarget
374 else
375 FindLinuxESP
376 fi
377 CpuType=`uname -m`
378 if [[ $CpuType == 'x86_64' ]] ; then
379 Platform="EFI64"
380 elif [[ $CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686' ]] ; then
381 Platform="EFI32"
382 echo
383 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
384 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
385 echo "on a 64-bit computer, you should manually install the 64-bit version of"
386 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
387 echo "you're positive you want to continue with this installation, answer 'Y'"
388 echo "to the following question..."
389 echo
390 echo -n "Are you sure you want to continue (Y/N)? "
391 read ContYN
392 if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
393 echo "OK; continuing with the installation..."
394 else
395 exit 0
396 fi
397 else
398 echo "Unknown CPU type '$CpuType'; aborting!"
399 exit 1
400 fi
401 CheckSecureBoot
402 CopyRefindFiles
403 if [[ $TargetDir != "/EFI/BOOT" ]] ; then
404 AddBootEntry
405 fi
406 } # InstallOnLinux()
407
408 #
409 # The main part of the script. Sets a few environment variables,
410 # performs a few startup checks, and then calls functions to
411 # install under OS X or Linux, depending on the detected platform.
412 #
413
414 GetParams $@
415 OSName=`uname -s`
416 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
417 RefindDir="$ThisDir/refind"
418 ThisScript="$ThisDir/`basename $0`"
419 CheckForFiles
420 if [[ `whoami` != "root" ]] ; then
421 echo "Not running as root; attempting to elevate privileges via sudo...."
422 sudo $ThisScript $1 $2 $3
423 if [[ $? != 0 ]] ; then
424 echo "This script must be run as root (or using sudo). Exiting!"
425 exit 1
426 else
427 exit 0
428 fi
429 fi
430 if [[ $OSName == 'Darwin' ]] ; then
431 InstallOnOSX $1
432 elif [[ $OSName == 'Linux' ]] ; then
433 InstallOnLinux
434 else
435 echo "Running on unknown OS; aborting!"
436 fi
437
438 if [[ $Problems ]] ; then
439 echo
440 echo "ALERT:"
441 echo "Installation has completed, but problems were detected. Review the output for"
442 echo "error messages and take corrective measures as necessary. You may need to"
443 echo "re-run this script or install manually before rEFInd will work."
444 echo
445 else
446 echo
447 echo "Installation has completed successfully."
448 echo
449 fi
450
451 if [[ $UnmountEsp ]] ; then
452 echo "Unmounting install dir"
453 umount $InstallDir
454 fi
455
456 if [[ $InstallDir == /tmp/refind_install ]] ; then
457 # sleep 5
458 rmdir $InstallDir
459 fi