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