@@ -17,6 +17,7 @@ RED='\033[1;31m'
17
17
BGTYELLOW=' \033[1;93m'
18
18
NC=' \033[0m' # No Color
19
19
20
+ # Show basic usage.
20
21
usage () {
21
22
echo " Usage: $( basename $0 ) <source> [options] <system>"
22
23
echo
@@ -27,6 +28,7 @@ echo "-h, --help Display full usage information."
27
28
exit 1
28
29
}
29
30
31
+ # Show full help.
30
32
help () {
31
33
echo " Usage: $( basename $0 ) <source> [options] <system>"
32
34
echo
35
37
exit
36
38
}
37
39
40
+ # Remove existing boot loader and resume entries for matching device (11000001).
38
41
remove_duplicates () {
39
42
if [[ " $3 " == " uefi" ]]; then
40
43
bcdpath=" $2 /EFI/Microsoft/Boot/BCD"
74
77
done
75
78
}
76
79
80
+ # Build main and recovery stores using blank BCD-NEW file and reg templates.
77
81
build_stores () {
78
82
if [[ " $verbose " == " true" ]]; then echo " Build the main BCD store..." ; fi
79
83
$resdir /winload.sh " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 " " $8 " " $9 " " ${10} " " ${11} " " ${12} " > $tmpdir /winload.txt
@@ -95,6 +99,7 @@ elif [[ "$3" == "bios" ]]; then
95
99
fi
96
100
}
97
101
102
+ # Build new Windows entry and update existing BCD stores.
98
103
update_winload () {
99
104
remove_duplicates " $1 " " $2 " " $3 " " ${11} " " ${12} "
100
105
if [[ " $verbose " == " true" ]]; then echo " Update main BCD hive with new entries..." ; fi
@@ -109,6 +114,7 @@ elif [[ "$3" == "bios" ]]; then
109
114
fi
110
115
}
111
116
117
+ # Copy the WBM files for the specified firmware and set the file attributes the same as bcdboot.
112
118
copy_bootmgr () {
113
119
if [[ " $3 " == " uefi" ]]; then
114
120
if [[ " $verbose " == " true" ]]; then echo " Copy the EFI boot files to the ESP..." ; fi
@@ -137,6 +143,8 @@ elif [[ "$3" == "bios" ]]; then
137
143
fi
138
144
}
139
145
146
+ # Used when no syspath is specified in the arguments.
147
+ # Look for an ESP or active primary partition on the Windows disk or the first disk (/dev/sda).
140
148
get_syspath () {
141
149
firmware=" $1 "
142
150
windisk=" $2 "
@@ -196,6 +204,8 @@ elif [[ "$firmware" == "bios" || "$firmware" == "both" ]]; then
196
204
fi
197
205
}
198
206
207
+ # Used when a syspath is provided in the arguments.
208
+ # Find the block device (and active partition if BIOS/BOTH) for the specified mount point.
199
209
get_device () {
200
210
firmware=" $1 "
201
211
syspath=" $2 "
@@ -223,6 +233,7 @@ elif [[ "$firmware" == "bios" || "$firmware" == "both" ]]; then
223
233
fi
224
234
}
225
235
236
+ # Load the NBD module if needed then find a free block device to use.
226
237
attach_vdisk () {
227
238
errormsg=$( modinfo nbd 2>&1> /dev/null)
228
239
if [[ -z $( command -v qemu-nbd) ]]; then missing+=" qemu-utils" ; fi
243
254
sudo qemu-nbd -c " $vrtdisk " " $imgpath "
244
255
}
245
256
257
+ # Display partitions on virtual disk and mount the specified volume.
246
258
mount_vpart () {
247
259
vrtpath=" /mnt/virtwin"
248
260
mntopts=" rw,nosuid,nodev,relatime,uid=$( id -u) ,gid=$( id -g) ,iocharset=utf8,windows_names"
258
270
sudo mkdir -p " $vrtpath " && sudo mount -t ntfs3 -o" $mntopts " /dev/$vtwinpart " $vrtpath "
259
271
}
260
272
273
+ # Unmount volume and detach virtual disk then unload NBD module if no longer needed.
261
274
umount_vpart () {
262
275
if [[ " $verbose " == " true" ]]; then echo " Removing temporary VHDX mount point..." ; fi
263
276
sudo umount " $vrtpath " && sudo rm -rf " $vrtpath "
@@ -268,16 +281,19 @@ if [[ "$unloadnbd" == "true" ]]; then
268
281
fi
269
282
}
270
283
284
+ # Check for the WBM in the current firmware boot options.
271
285
get_wbmoption () {
272
286
wbmoptnum=$( efibootmgr | grep " Windows Boot Manager" | awk ' {print $1}' | sed ' s/Boot//;s/\*//' )
273
287
}
274
288
289
+ # Update the WBM firmware option and device data in the BCD entry.
275
290
create_wbmfwvar () {
276
291
if [[ " $verbose " == " true" ]]; then echo " Update main BCD with current WBM firware variable..." ; fi
277
292
$resdir /wbmfwvar.sh $1 > $tmpdir /wbmfwvar.txt
278
293
sudo hivexsh -w " $2 /EFI/Microsoft/Boot/BCD" -f $tmpdir /wbmfwvar.txt
279
294
}
280
295
296
+ # Remove hivexsh scripts and BCD files created during the build process.
281
297
cleanup () {
282
298
if [[ " $verbose " == " true" ]]; then echo " Clean up temporary files..." ; fi
283
299
rm -f $tmpdir /winload.txt $tmpdir /recovery.txt $tmpdir /wbmfwvar.txt $tmpdir /BCD-Windows $tmpdir /BCD-Recovery
@@ -290,12 +306,14 @@ if [[ ! -z "$missing" ]]; then
290
306
fi
291
307
}
292
308
309
+ # Script starts here.
293
310
if [[ $( uname) != " Linux" ]]; then echo " Unsupported platform detected." ; exit 1; fi
294
311
295
312
if [[ $# -eq 0 ]]; then
296
313
usage
297
314
fi
298
315
316
+ # Check for required packages that are missing.
299
317
if [[ -z $( command -v hivexsh) ]]; then missing+=" hivex" ; fi
300
318
if [[ -z $( command -v hivexregedit) ]]; then missing+=" hivexregedit" ; fi
301
319
if [[ -z $( command -v setfattr) ]]; then missing+=" attr/setfattr" ; fi
@@ -357,13 +375,16 @@ while (( "$#" )); do
357
375
done
358
376
shopt -u nocasematch
359
377
378
+ # Check if source is a virtual disk file.
360
379
if [[ " $winpath " == * " .vhdx" * && -f " $winpath " ]]; then
361
380
virtual=" true"
362
381
imgpath=" $winpath "
363
382
attach_vdisk
364
383
sleep 1 && mount_vpart
365
384
fi
366
385
386
+ # Check source for path to the WBM files then get the block device.
387
+ # Get the mount point, file path and block device that contains the virtual disk file.
367
388
if [[ -d " $winpath /Windows/Boot" ]]; then
368
389
windisk=$( lsblk -o path,mountpoint | grep " $winpath " | awk ' {print $1}' | sed ' s/[0-9]\+$//' )
369
390
elif [[ " $virtual " == " true" && -d " $vrtpath /Windows/Boot" ]]; then
@@ -377,6 +398,12 @@ else
377
398
exit 1
378
399
fi
379
400
401
+ # Perform the actions appropriate for the specified firmware type.
402
+ # Compare the WBM product versions of the source and system volumes.
403
+ # Copy the boot files if missing or older than the source version.
404
+ # Create new BCD stores or update existing ones with new entries.
405
+ # Create a WBM firmware entry in the first or last position when needed.
406
+ # Unmount the virtual disk and remove the temporary hive scripts/files.
380
407
if [[ " $firmware " != " uefi" && " $firmware " != " bios" && " $firmware " != " both" ]]; then
381
408
echo -e " ${RED} Unsupport firmware: Only UEFI, BIOS or BOTH.${NC} "
382
409
exit 1
@@ -443,14 +470,16 @@ else
443
470
else
444
471
copy_bootmgr " $winpath " " $syspath " " $fwmode "
445
472
fi
446
- build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
473
+ build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
474
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
447
475
if [[ " $setfwmod " == " false" && " $efibootvars " == " true" ]]; then
448
476
if [[ ! -z " $wbmoptnum " ]]; then
449
477
if [[ " $verbose " == " true" ]]; then echo " Remove the current Windows Boot Manager option..." ; fi
450
478
sudo efibootmgr -b " $wbmoptnum " -B > /dev/null
451
479
fi
452
480
if [[ " $verbose " == " true" ]]; then echo " Add the Windows Boot Manager to the firmware..." ; fi
453
- sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" -@ $resdir /Templates/wbmoptdata.bin > /dev/null
481
+ sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" \
482
+ -@ $resdir /Templates/wbmoptdata.bin > /dev/null
454
483
get_wbmoption && create_wbmfwvar " $wbmoptnum " " $syspath "
455
484
if [[ " $setwbmlast " == " true" ]]; then
456
485
bootorder=$( efibootmgr | grep BootOrder: | awk ' {print $2}' | sed " s/$wbmoptnum ,//" )
@@ -473,11 +502,13 @@ else
473
502
copy_bootmgr " $winpath " " $syspath " " $fwmode "
474
503
fi
475
504
fi
476
- build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
505
+ build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
506
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
477
507
if [[ " $setfwmod " == " false" && " $efibootvars " == " true" ]]; then
478
508
if [[ -z " $wbmoptnum " ]]; then
479
509
if [[ " $verbose " == " true" ]]; then echo " Add the Windows Boot Manager to the firmware..." ; fi
480
- sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" -@ $resdir /Templates/wbmoptdata.bin > /dev/null
510
+ sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" \
511
+ -@ $resdir /Templates/wbmoptdata.bin > /dev/null
481
512
get_wbmoption
482
513
if [[ " $setwbmlast " == " true" ]]; then
483
514
bootorder=$( efibootmgr | grep BootOrder: | awk ' {print $2}' | sed " s/$wbmoptnum ,//" )
@@ -504,10 +535,12 @@ else
504
535
sudo mv " $syspath /EFI/BCD-BOOT" " $syspath /EFI/Microsoft/Boot/BCD"
505
536
sudo mv " $syspath /EFI/BCD-RECOVERY" " $syspath /EFI/Microsoft/Recovery/BCD"
506
537
fi
507
- update_winload " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
538
+ update_winload " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
539
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
508
540
if [[ " $setfwmod " == " false" && " $efibootvars " == " true" && -z " $wbmoptnum " ]]; then
509
541
if [[ " $verbose " == " true" ]]; then echo " Add the Windows Boot Manager to the firmware..." ; fi
510
- sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" -@ $resdir /Templates/wbmoptdata.bin > /dev/null
542
+ sudo efibootmgr -c -d " $efidisk " -p " $efinum " -l " $wbmefipath " -L " Windows Boot Manager" \
543
+ -@ $resdir /Templates/wbmoptdata.bin > /dev/null
511
544
get_wbmoption && create_wbmfwvar " $wbmoptnum " " $syspath "
512
545
if [[ " $setwbmlast " == " true" ]]; then
513
546
bootorder=$( efibootmgr | grep BootOrder: | awk ' {print $2}' | sed " s/$wbmoptnum ,//" )
585
618
else
586
619
copy_bootmgr " $winpath " " $syspath " " $fwmode " " $sysfstype "
587
620
fi
588
- build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
621
+ build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
622
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
589
623
elif [[ " $sysbtmgr " == " true" && " $clean " == " true" ]]; then
590
624
if [[ " $verbose " == " true" ]]; then echo " Remove current BCD store..." ; fi
591
625
sudo rm -f " $syspath " /Boot/BCD
600
634
fi
601
635
fi
602
636
fi
603
- build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
637
+ build_stores " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
638
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
604
639
else
605
640
createbcd=" false"
606
641
if [[ " $sysuwfver " != " $localuwfver " || " $sysvhdver " != " $localvhdver " ]]; then
618
653
sudo mv " $syspath /BCD" " $syspath /Boot"
619
654
fi
620
655
fi
621
- update_winload " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
656
+ update_winload " $winpath " " $syspath " " $fwmode " " $setfwmod " " $createbcd " " $prewbmdef " \
657
+ " $prodname " " $locale " " $verbose " " $virtual " " $vrtpath " " $imgstring "
622
658
fi
623
659
if [[ " $syspath " == " /mnt/winsys" ]]; then
624
660
if [[ " $verbose " == " true" ]]; then echo " Removing temporary system mount point..." ; fi
0 commit comments