]> code.delx.au - refind/blob - mvrefind.sh
b1e14ec840a641464f99c10b71e2e639a7662fa2
[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=`readlink -f ${1}`
28 TargetDir=`readlink -f ${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 if [[ -f $SourceDir/grubx64.efi ]] ; then
82 SourceX64="grubx64.efi"
83 TargetX64=$SourceX64
84 if [[ $EspSourceDir == "/efi/boot" ]] ; then
85 SourceShim="bootx64.efi"
86 elif [[ $EspSourceDir == "/efi/microsoft/boot" ]] ; then
87 SourceShim="bootmgfw.efi"
88 fi
89 else
90 SourceShim="none"
91 TargetShim="none"
92 if [[ $EspSourceDir == "/efi/boot" ]] ; then
93 SourceX64="bootx64.efi"
94 SourceIA32="bootia32.efi"
95 elif [[ $EspSourceDir == "/efi/microsoft/boot" ]] ; then
96 SourceX64="bootmgfw.efi"
97 fi
98 fi
99
100 if [[ $EspTargetDir == "/efi/boot" ]] ; then
101 if [[ $TargetShim == "none" ]] ; then
102 TargetX64="bootx64.efi"
103 TargetIA32="bootia32.efi"
104 else
105 TargetShim="bootx64.efi"
106 fi
107 elif [[ $EspTargetDir == "/efi/microsoft/boot" ]] ; then
108 if [[ $TargetShim == "none" ]] ; then
109 TargetX64="bootmgfw.efi"
110 else
111 TargetShim="bootmgfw.efi"
112 fi
113 fi
114 } # AdjustFilenames()
115
116 # Checks for the presence of necessary files, including both boot loaders
117 # and support utilities (efibootmgr, etc.)
118 CheckForFiles() {
119 if [[ (! -f $SourceDir/$SourceX64 && ! -f $SourceDir/$SourceIA32) ||
120 ($SourceShim != "none" && ! -f $SourceDir/SourceShim) ||
121 ! -f $SourceDir/refind.conf ]] ; then
122 echo "There doesn't seem to be a rEFInd installation at $SourceDir!"
123 echo "Aborting!"
124 exit 1
125 fi
126 if [[ $EspTargetDir != "/efi/boot" && $EspTargetDir != "/efi/microsoft/boot" ]] ; then
127 Efibootmgr=`which efibootmgr 2> /dev/null`
128 if [[ ! -f $Efibootmgr ]] ; then
129 echo "Moving to a non-default directory requires a working efibootmgr utility, but"
130 echo "one can't be found! Aborting!"
131 exit 1
132 elif [[ ! -d "/sys/firmware/efi" ]] ; then
133 echo "Moving to a non-default directory requires a boot into EFI mode, but we seem"
134 echo "to be running in BIOS mode. (Perhaps typing 'modprobe efivars' will fix this."
135 echo "Aborting!"
136 fi
137 fi
138 } # CheckForFiles()
139
140 # Do final checks & then move the files!
141 MoveFiles() {
142 ExistingFiles=`find $TargetDir -name "*.efi" 2> /dev/null`
143 if [[ -n $ExistingFiles && $EspTargetDir != "/efi/boot" && $EspTargetDir != "/efi/microsoft/boot" ]] ; then
144 echo "$TargetDir isn't empty! Aborting!"
145 exit 1
146 fi
147
148 if [[ $EspTargetDir == "/efi/boot" && -d $TargetDir ]] ; then
149 if [[ -d $InstallDir/EFI/BOOT-rEFIndBackup ]] ; then
150 echo ""
151 echo "Caution: An existing backup of a default boot loader exists! If the current"
152 echo "default boot loader and the backup are different boot loaders, the current"
153 echo "one will become inaccessible."
154 echo ""
155 echo -n "Do you want to proceed with moving (Y/N)? "
156 read YesNo
157 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
158 echo "OK; continuing with the move..."
159 else
160 exit 0
161 fi
162 else
163 mv $TargetDir $InstallDir/EFI/BOOT-refindBackup &> /dev/null
164 fi
165 fi
166
167 if [[ $EspTargetDir == "/efi/microsoft/boot" && -d $TargetDir ]] ; then
168 mv -n $EspTargetDir/bootmgfw.efi $InstallDir/EFI/Microsoft/
169 fi
170
171 mkdir -p $TargetDir
172 mv $SourceDir/icons $TargetDir/ 2> /dev/null
173 mv $SourceDir/icons-backup $TargetDir/ 2> /dev/null
174 mv $SourceDir/drivers_* $TargetDir/ 2> /dev/null
175 mv $SourceDir/keys $TargetDir 2> /dev/null
176 mv $SourceDir/$SourceX64 $TargetDir/$TargetX64 2> /dev/null
177 mv $SourceDir/$SourceIA32 $TargetDir/$TargetIA32 2> /dev/null
178 mv $SourceDir/$SourceShim $TargetDir/$TargetShim 2> /dev/null
179 mv $SourceDir/refind.conf* $TargetDir/ 2> /dev/null
180 rmdir $SourceDir 2> /dev/null
181 } # MoveFiles()
182
183 # Clean up after moving files -- mainly restoring old backed-up files, if present
184 PostMoveCleanup() {
185 if [[ $EfiSourceDir == "/efi/boot" && -d $InstallDir/EFI/BOOT-rEFIndBackup && ! -d $SourceDir ]] ; then
186 mv $InstallDir/EFI/BOOT-rEFIndBackup $SourceDir 2> /dev/null
187 fi
188 if [[ $EfiSourceDir == "/efi/microsoft/boot" && -f $InstallDir/EFI/Microsoft/bootmgfw.efi ]] ; then
189 mv -n $InstallDir/EFI/Microsoft/bootmgfw.efi $SourceDir/bootmgfw.efi
190 fi
191 } # PostMoveCleanup()
192
193 # If necessary, create a new NVRAM entry for the new location
194 AddNvramEntry() {
195 InstallIt="0"
196 Efibootmgr=`which efibootmgr 2> /dev/null`
197 InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
198 PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
199
200 if [[ $TargetShim != "none" ]] ; then
201 EntryFilename=$EspTargetDir/$TargetShim
202 else
203 CpuType=`uname -m`
204 if [[ $CpuType == 'x86_64' ]] ; then
205 EntryFilename=$EspTargetDir/$TargetX64
206 else
207 EntryFilename=$EspTargetDir/$TargetIA32
208 fi
209 fi # if/else
210
211 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
212 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
213 ExistingEntry=`$Efibootmgr -v | grep -i $EfiEntryFilename2`
214
215 if [[ $ExistingEntry ]] ; then
216 ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
217 FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
218 if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
219 $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
220 InstallIt="1"
221 fi
222 else
223 InstallIt="1"
224 fi
225
226 if [[ $InstallIt == "1" ]] ; then
227 if [[ $EfiTargetDir == "/efi/microsoft/boot" ]] ; then
228 # Name it the way some firmware expects -- see http://mjg59.dreamwidth.org/20187.html
229 $Efibootmgr -c -l $EfiEntryFilename -L "Windows Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null
230 else
231 $Efibootmgr -c -l $EfiEntryFilename -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null
232 fi
233 if [[ $? != 0 ]] ; then
234 EfibootmgrProblems=1
235 fi
236 fi
237
238 if [[ $EfibootmgrProblems ]] ; then
239 echo
240 echo "ALERT: There were problems running the efibootmgr program! Your moved rEFInd"
241 echo "might not run!"
242 echo
243 fi
244 } # AddNvramEntry
245
246 #
247 # Main body of script
248 #
249
250 if [[ $# != 2 ]] ; then
251 echo "Usage: $0 {source-directory} {target-directory}"
252 exit 1
253 fi
254 if [[ `whoami` != "root" ]] ; then
255 echo "Not running as root! Aborting!"
256 exit 1
257 fi
258
259 FindLinuxESP
260 AdjustFilenames
261 CheckForFiles
262 MoveFiles
263 PostMoveCleanup
264 AddNvramEntry