]> code.delx.au - refind/blob - mvrefind.sh
bdab41a548adfafaddda9c6ad77e5835fa793308
[refind] / mvrefind.sh
1 #!/bin/bash
2 #
3 # Linux script to move an existing rEFInd installation from one directory to another
4 #
5 # Usage:
6 #
7 # ./mvrefind.sh /path/to/source /path/to/destination
8 #
9 # Typically used to "hijack" or "unhijack" a Windows boot loader location or
10 # to help convert a rEFInd installation made in BIOS mode to one that works
11 # in EFI mode.
12 #
13 # Revision history:
14 #
15 # 0.6.3 -- Initial release
16 #
17 # Note: mvrefind.sh version numbers match those of the rEFInd package
18 # with which they first appeared.
19
20 RootDir="/"
21 SourceX64="refind_x64.efi"
22 TargetX64=$SourceX64
23 SourceIA32="refind_ia32.efi"
24 TargetIA32=$SourceIA32
25 SourceShim="shim.efi"
26 TargetShim=$SourceShim
27 SourceDir=${1}
28 TargetDir=${2}
29
30 # Identifies the ESP's location (/boot or /boot/efi); aborts if the ESP isn't
31 # mounted at either location. Also splits the ESP location from SourceDir and
32 # TargetDir, leaving them intact but creating new EspSourceDir and EspTargetDir
33 # variables containing only the ESP components thereof. These new variables
34 # are also converted to all-lowercase and any trailing slash is stripped, to
35 # assist in comparisons. (This is reasonable because FAT is case-insensitive.)
36 # Sets InstallDir to the ESP mount point.
37 FindLinuxESP() {
38 EspLine=`df $RootDir/boot/efi 2> /dev/null | grep boot/efi`
39 if [[ ! -n $EspLine ]] ; then
40 EspLine=`df $RootDir/boot | grep boot`
41 fi
42 InstallDir=`echo $EspLine | cut -d " " -f 6`
43 if [[ -n $InstallDir ]] ; then
44 EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
45 fi
46 if [[ $EspFilesystem != 'vfat' ]] ; then
47 echo "$RootDir/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be"
48 echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
49 exit 1
50 fi
51
52 # Sanity check on source & target....
53 EspPathLength=`expr length $InstallDir`
54 Temp=`echo $SourceDir | cut -c 1-$EspPathLength`
55 if [[ $Temp != $InstallDir ]] ; then
56 echo "$SourceDir isn't on the ESP ($InstallDir)! Aborting!"
57 exit 1
58 fi
59 Temp=`echo $TargetDir | cut -c 1-$EspPathLength`
60 if [[ $Temp != $InstallDir ]] ; then
61 echo "$TargetDir isn't on the ESP ($InstallDir)! Aborting!"
62 exit 1
63 fi
64
65 # Temporarily replace "/" in pathnames with ",", so as to enable sed to
66 # work on them
67 TempInstallDir=`echo $InstallDir | tr '/' ','`
68 Temp=`echo $SourceDir | tr '/' ',' | sed s/${TempInstallDir}//g | tr ',' '/' | tr '[A-Z]' '[a-z]'`
69 EspSourceDir=`dirname $Temp`/`basename $Temp`
70 Temp=`echo $TargetDir | tr '/' ',' | sed s/${TempInstallDir}//g | tr ',' '/' | tr '[A-Z]' '[a-z]'`
71 EspTargetDir=`dirname $Temp`/`basename $Temp`
72 if [[ $EspSourceDir == $EspTargetDir ]] ; then
73 echo "$SourceDir is the same as $TargetDir! Aborting!"
74 exit 1
75 fi
76 } # FindLinuxESP
77
78 # Adjust filename variables appropriately for their locations and detected
79 # presence (or lack thereof) of shim installation
80 AdjustFilenames() {
81 echo "Entering AdjustFilenames()"
82 if [[ -f $SourceDir/grubx64.efi ]] ; then
83 SourceX64="grubx64.efi"
84 TargetX64=$SourceX64
85 if [[ $EspSourceDir == "/efi/boot" ]] ; then
86 SourceShim="bootx64.efi"
87 elif [[ $EspSourceDir == "/efi/microsoft/boot" ]] ; then
88 SourceShim="bootmgfw.efi"
89 fi
90 else
91 SourceShim="none"
92 TargetShim="none"
93 if [[ $EspSourceDir == "/efi/boot" ]] ; then
94 SourceX64="bootx64.efi"
95 SourceIA32="bootia32.efi"
96 elif [[ $EspSourceDir == "/efi/microsoft/boot" ]] ; then
97 SourceX64="bootmgfw.efi"
98 fi
99 fi
100
101 if [[ $EspTargetDir == "/efi/boot" ]] ; then
102 if [[ $TargetShim == "none" ]] ; then
103 TargetX64="bootx64.efi"
104 TargetIA32="bootia32.efi"
105 else
106 TargetShim="bootx64.efi"
107 fi
108 elif [[ $EspTargetDir == "/efi/microsoft/boot" ]] ; then
109 if [[ $TargetShim == "none" ]] ; then
110 TargetX64="bootmgfw.efi"
111 else
112 TargetShim="bootmgfw.efi"
113 fi
114 fi
115
116 echo "Leaving AdjustFilenames():"
117 echo " SourceX64 = $SourceX64, TargetX64 = $TargetX64"
118 echo " SourceIA32 = $SourceIA32, TargetIA32 = $TargetIA32"
119 echo " SourceShim = $SourceShim, TargetShim = $TargetShim"
120 } # AdjustFilenames()
121
122 # Checks for the presence of necessary files, including both boot loaders
123 # and support utilities (efibootmgr, etc.)
124 CheckForFiles() {
125 echo "Entering CheckForFiles()"
126 if [[ (! -f $SourceDir/$SourceX64 && ! -f $SourceDir/$SourceIA32) ||
127 ($SourceShim != "none" && ! -f $SourceDir/SourceShim) ||
128 ! -f $SourceDir/refind.conf ]] ; then
129 echo "There doesn't seem to be a rEFInd installation at $SourceDir!"
130 echo "Aborting!"
131 exit 1
132 fi
133 if [[ $EspTargetDir != "/efi/boot" && $EspTargetDir != "/efi/microsoft/boot" ]] ; then
134 Efibootmgr=`which efibootmgr 2> /dev/null`
135 if [[ ! -f $Efibootmgr ]] ; then
136 echo "Moving to a non-default directory requires a working efibootmgr utility, but"
137 echo "one can't be found! Aborting!"
138 exit 1
139 elif [[ ! -d "/sys/firmware/efi" ]] ; then
140 echo "Moving to a non-default directory requires a boot into EFI mode, but we seem"
141 echo "to be running in BIOS mode. (Perhaps typing 'modprobe efivars' will fix this."
142 echo "Aborting!"
143 fi
144 fi
145 } # CheckForFiles()
146
147 # Do final checks & then move the files!
148 MoveFiles() {
149 echo "Entering MoveFiles()"
150 ExistingFiles=`find $TargetDir -name "*.efi" 2> /dev/null`
151 if [[ -n $ExistingFiles && $EspTargetDir != "/efi/boot" && $EspTargetDir != "/efi/microsoft/boot" ]] ; then
152 echo "$TargetDir isn't empty! Aborting!"
153 exit 1
154 fi
155
156 if [[ $EspTargetDir == "/efi/boot" && -d $TargetDir ]] ; then
157 if [[ -d $InstallDir/EFI/BOOT-rEFIndBackup ]] ; then
158 echo ""
159 echo "Caution: An existing backup of a default boot loader exists! If the current"
160 echo "default boot loader and the backup are different boot loaders, the current"
161 echo "one will become inaccessible."
162 echo ""
163 echo -n "Do you want to proceed with moving (Y/N)? "
164 read YesNo
165 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
166 echo "OK; continuing with the move..."
167 else
168 exit 0
169 fi
170 else
171 mv $TargetDir $InstallDir/EFI/BOOT-refindBackup &> /dev/null
172 fi
173 fi
174
175 if [[ $EspTargetDir == "/efi/microsoft/boot" && -d $TargetDir ]] ; then
176 mv -n $EspTargetDir/bootmgfw.efi $InstallDir/EFI/Microsoft/
177 fi
178
179 mkdir -p $TargetDir
180 mv $SourceDir/icons $TargetDir/ 2> /dev/null
181 mv $SourceDir/icons-backup $TargetDir/ 2> /dev/null
182 mv $SourceDir/drivers_* $TargetDir/ 2> /dev/null
183 mv $SourceDir/keys $TargetDir 2> /dev/null
184 mv $SourceDir/$SourceX64 $TargetDir/$TargetX64 2> /dev/null
185 mv $SourceDir/$SourceIA32 $TargetDir/$TargetIA32 2> /dev/null
186 mv $SourceDir/$SourceShim $TargetDir/$TargetShim 2> /dev/null
187 mv $SourceDir/refind.conf* $TargetDir/ 2> /dev/null
188 rmdir $SourceDir 2> /dev/null
189 } # MoveFiles()
190
191 # Clean up after moving files -- mainly restoring old backed-up files, if present
192 PostMoveCleanup() {
193 if [[ $EfiSourceDir == "/efi/boot" && -d $InstallDir/EFI/BOOT-rEFIndBackup && ! -d $SourceDir ]] ; then
194 mv $InstallDir/EFI/BOOT-rEFIndBackup $SourceDir 2> /dev/null
195 fi
196 if [[ $EfiSourceDir == "/efi/microsoft/boot" && -f $InstallDir/EFI/Microsoft/bootmgfw.efi ]] ; then
197 mv -n $InstallDir/EFI/Microsoft/bootmgfw.efi $SourceDir/bootmgfw.efi
198 fi
199 } # PostMoveCleanup()
200
201 # If necessary, create a new NVRAM entry for the new location
202 AddNvramEntry() {
203 echo "Entering AddNvramEntry()"
204 InstallIt="0"
205 Efibootmgr=`which efibootmgr 2> /dev/null`
206 InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
207 PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
208
209 if [[ $TargetShim != "none" ]] ; then
210 EntryFilename=$TargetDir/$TargetShim
211 else
212 CpuType=`uname -m`
213 if [[ $CpuType == 'x86_64' ]] ; then
214 EntryFilename=$TargetDir/$TargetX64
215 else
216 EntryFilename=$TargetDir/$TargetIA32
217 fi
218 fi # if/else
219
220 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
221 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
222 ExistingEntry=`$Efibootmgr -v | grep $EfiEntryFilename2`
223
224 if [[ $ExistingEntry ]] ; then
225 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
226 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
227 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
228 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
229 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
230 echo "manager. If this is NOT what you want, you should use efibootmgr to"
231 echo "manually adjust your EFI's boot order."
232 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
233 InstallIt="1"
234 fi
235 else
236 InstallIt="1"
237 fi
238
239 if [[ $InstallIt == "1" ]] ; then
240 $Efibootmgr -c -l $EfiEntryFilename -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null
241 if [[ $? != 0 ]] ; then
242 EfibootmgrProblems=1
243 fi
244 fi
245
246 if [[ $EfibootmgrProblems ]] ; then
247 echo
248 echo "ALERT: There were problems running the efibootmgr program! Your moved rEFInd"
249 echo "might not run!"
250 echo
251 fi
252 } # AddNvramEntry
253
254 #
255 # Main body of script
256 #
257
258 if [[ $# != 2 ]] ; then
259 echo "Usage: $0 {source-directory} {target-directory}"
260 exit 1
261 fi
262 if [[ `whoami` != "root" ]] ; then
263 echo "Not running as root! Aborting!"
264 exit 1
265 fi
266
267 FindLinuxESP
268 AdjustFilenames
269 CheckForFiles
270 MoveFiles
271 PostMoveCleanup
272 echo "EspTargetDir == \"$EspTargetDir\""
273 if [[ $EspTargetDir != "/efi/boot" && $EspTargetDir != "/efi/microsoft/boot" ]] ; then
274 AddNvramEntry
275 fi