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