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