Dual-boot Win 10 & EFI
Markus Köberl
markus.koeberl at tugraz.at
Mon Aug 12 14:04:08 CEST 2019
On Wednesday, 5 June 2019 08:53:19 CEST John G Heim wrote:
> Anybody know how to save & restore the signature file for a Windows 10
> install on a disk partitioned with GPT? Some time ago, I got a tip on
> this list on doing a dual boot install. Copy some blocks from /dev/sda
> to a temp file and then copy them back after partitioning the disk.
>
> dd if=/dev/sda of=/tmp/fai/signature ibs=1 skip=440 count=4
> ...
> dd if=/tmp/fai/signature of=/dev/sda obs=1 seek=440 count=4
>
> That works great on a machine with an msdos partition table. But it does
> not seem to work on a disk partitioned via GPT.
I got it working, put it is not a very clean solution. You have to modify the files.
Probably you see less partitions used by Windows. The number changed after an Windows update on my systems and of course made grub stop working. The usual funny unexpected thing with Microsoft I guess :-(
Inline in this email are the files I have in the fai config space. Attached are my scripts for creating and restoring an image of the windows installation and a script to change the windows hostname.
I but an image of the windows installation on a network share which a can access during the installation.
The renaming is necessary as I have a fill lab with identical hosts which I am cloning this way.
You have to change some paths in the scripts like `/usr/local/SPSCscripts/fai` which is the place where I put all the scripts and how to access the images `mfsmount -H cfshm /clusterFS` mounts out MooseFS cluster file system. In some of the scrips I am using regular expressions to match a group of hosts. So have a closer look at the scripts and change what is necessary.
You will also have to install some packages into your fai nfsroot necessary for manipulating the partition information.
I had to change the scripts several times (moved form bios boot to uefi boot). So they got a little bit messy and I never found the time to clean it up. It is working with uefi boot and disabled secure boot and legacy mode on a M2 SSD using nvme protocol.
But probably will also work with different settings but is untested and I may have broken things while changing the scripts.
Be careful with uefi that you also run the fai installation via uefi mode. I remember that I had problems with that years ago.
Let me know if i forgot a script or something is unclear. I hope it is of use although it is not generic and will only work in my environment without changes...
disk_config/WINDOWS:
####################################
# gpt partiton table for uefi bios #
####################################
disk_config disk1 disklabel:gpt align-at:1M fstabkey:uuid bootable:2
# windows boot partition
primary - 450 - -
# uefi boot partition
primary /boot/efi 100 vfat rw
# windows reserved partition
primary - 16 - -
# windows C:
primary - 142773 - -
primary - 859 - -
# linux:
primary / 40G ext4 rw,noatime,errors=remount-ro tuneopts="-c 0 -i 0"
primary /tmp 20G ext4 rw,noatime createopts="-L tmp -m 5" tuneopts="-c 0 -i 0"
primary /var/cache/openafs 5G ext2 rw,noatime createopts="-L openafs -m 5" tuneopts="-c 0 -i 0"
primary swap 5G swap rw
primary /home 10G- ext4 rw,noatime createopts="-L srv -m 1" tuneopts="-c 0 -i 0"
hooks/mountdisks.WINDOWS:
#!/bin/bash
error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code
if [ -z "$BOOT_DEVICE" ]; then
exit 189
fi
if ifclass GRUB_PC; then
# force partition id on partition 1 and 2 to id 7 (NTFS) necessary for first installation
# and mark windows boot partiotin as bootable (necessary for updates to work)
sfdisk -d ${BOOT_DEVICE} | \
sed -e 's#^\('${BOOT_DEVICE}'1 .*type=\).*$#\17, bootable#' | \
sed -e 's#^\('${BOOT_DEVICE}'2 .*type=\).*$#\17#' | \
sfdisk ${BOOT_DEVICE}
fi
if ifclass GRUB_UEFI; then
# Disk GUID
sgdisk --disk-guid=692A8440-E7A6-4F1E-8D8E-B6ABF895F247 ${BOOT_DEVICE}
# Partiton GUID
sgdisk --partition-guid=1:B8BAA86C-B3D4-4A02-8713-03FE4B7AC42D ${BOOT_DEVICE}
sgdisk --partition-guid=2:BC9CC09F-D739-4FF3-9650-72FD84BD92AB ${BOOT_DEVICE}
sgdisk --partition-guid=3:98D35356-2FB2-4A07-A1F3-1ACF486F8642 ${BOOT_DEVICE}
sgdisk --partition-guid=4:6848A458-2A6C-4C73-AD6D-6B6CC9DAF8D6 ${BOOT_DEVICE}
sgdisk --partition-guid=5:262EFA0A-1DE4-4DC1-B2F7-F203A8D2A712 ${BOOT_DEVICE}
# Partiton type
sgdisk --typecode=1:2700 ${BOOT_DEVICE}
sgdisk --typecode=2:EF00 ${BOOT_DEVICE}
sgdisk --typecode=3:0C01 ${BOOT_DEVICE}
sgdisk --typecode=4:0700 ${BOOT_DEVICE}
sgdisk --typecode=5:2700 ${BOOT_DEVICE}
# Partition name
sgdisk --change-name=1:"Basic data partition" ${BOOT_DEVICE}
sgdisk --change-name=2:"EFI system partition" ${BOOT_DEVICE}
sgdisk --change-name=3:"Microsoft reserved partition" ${BOOT_DEVICE}
sgdisk --change-name=4:"Basic data partition" ${BOOT_DEVICE}
# Partition attributes
sgdisk --attributes=1:set:0 ${BOOT_DEVICE}
sgdisk --attributes=1:set:63 ${BOOT_DEVICE}
sgdisk --attributes=2:set:63 ${BOOT_DEVICE}
sgdisk --attributes=3:set:63 ${BOOT_DEVICE}
sgdisk --attributes=5:set:0 ${BOOT_DEVICE}
sgdisk --attributes=5:set:63 ${BOOT_DEVICE}
fi
exit $error
fai-config/scripts/WINDOWS/60-restore:
#!/bin/bash
error=0; trap 'error=$(($?>$error?$?:$error))' ERR # save maximum error code
# skip the rest, if not an initial installation
if [ $FAI_ACTION = "install" ]; then
# restore windows
if ifclass WINDOWS; then
# configure network for clusterFS usage
ifconfig ${NIC1}:1 172.16.${IPADDR#129.27.*}
# mount clusterFS
mkdir /clusterFS
mfsmount -H cfshm /clusterFS
# restore latest windows
cd ${target}/usr/local/SPSCscripts/fai
if ifclass GRUB_PC; then
# get dev
windows_dev=$(echo ${disklist} | awk '{print $1}')
./restoreWindowsFromClusterFS.sh -e -d -q --backup newest --dev "/dev/${windows_dev}"
# Windows C: should be partition 2
./renameWindows10.sh "/dev/${windows_dev}2"
# add grub menue entry for Windows (partitin 1)
# get UUID
eval "$(blkid -o udev /dev/${windows_dev}1)"
# create custom menue entry
cat >> $target/etc/grub.d/40_custom <<-EOF
menuentry "Windows 10" --class windows --class os {
insmod ntfs
search --no-floppy --set=root --fs-uuid ${ID_FS_UUID}
ntldr /bootmgr
}
EOF
# set timeout
perl -pi -pe "s/GRUB_TIMEOUT=\d+/GRUB_TIMEOUT=30/" $target/etc/default/grub
$ROOTCMD update-grub
fi
if ifclass GRUB_UEFI; then
# usually windows is installed on first disk
WINDOWS_BOOT_DEVICE="/dev/$(echo ${disklist} | awk '{print $1}')"
# restore filesystem images
./restoreEfiWindowsFromClusterFS.sh --backup newest -e --dev "${WINDOWS_BOOT_DEVIC}"
# set windows hostname
TYPE="EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"
WINDOWS_PARTITION=`sfdisk -J "${WINDOWS_BOOT_DEVICE}" | jq '.partitiontable.partitions | .[] | select(.type=="'${TYPE}'") | .node' | sed 's/"//g'`
./renameWindows10.sh "${WINDOWS_PARTITION}"
# set timeout
perl -pi -pe "s/GRUB_TIMEOUT=\d+/GRUB_TIMEOUT=30/" $target/etc/default/grub
$ROOTCMD update-grub
fi
cd /
# umount clusterFS
umount /clusterFS
# take network interface for clusterFS down
ifconfig ${NIC1}:1 down
fi
fi
exit $error
fai-config/scripts/GRUB_UEFI/10-setup:
#!/bin/bash
error=0 ; trap "error=$((error|1))" ERR
set -a
[[ $FAI_ACTION != "softupdate" ]] || exit 0
if [ -z "$BOOT_DEVICE" ]; then
exit 189
fi
modprobe efivars
# force target arch in case we did not boot using uefi pxe boot
if ifclass AMD64; then
GRUB_TARGET_ARCH="--target=x86_64-efi"
fi
$ROOTCMD grub-install $GRUB_TARGET_ARCH $BOOT_DEVICE
$ROOTCMD update-grub
# update boot order
# get number for debian
EFI_DEBIAN_NUMBER=`$ROOTCMD efibootmgr | awk 'match($0,/Boot(.*)\* debian/,var) {print var[1]}'`
# get order into array
EFI_BOOT_ORDER=(`$ROOTCMD efibootmgr | awk 'match($0,/BootOrder: (.*)/,var) {print var[1]}' | tr -t ',' ' '`)
$ROOTCMD efibootmgr -o ${EFI_DEBIAN_NUMBER},`echo ${EFI_BOOT_ORDER[@]/$EFI_DEBIAN_NUMBER} | tr -t ' ' ','`
exit $error
regard
Markus Köberl
--
Markus Koeberl
Graz University of Technology
Signal Processing and Speech Communication Laboratory
E-mail: markus.koeberl at tugraz.at
-------------- next part --------------
A non-text attachment was scrubbed...
Name: backupEfiWindowsToClusterFS.sh
Type: application/x-shellscript
Size: 11270 bytes
Desc: not available
URL: <http://lists.uni-koeln.de/pipermail/linux-fai/attachments/20190812/41e19dad/attachment-0005.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: backupWindowsToClusterFS.sh
Type: application/x-shellscript
Size: 9502 bytes
Desc: not available
URL: <http://lists.uni-koeln.de/pipermail/linux-fai/attachments/20190812/41e19dad/attachment-0006.bin>
-------------- next part --------------
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Wed Nov 28 12:25:16 2012
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
#
# 2) differing output - Some programs produce different output each time
# they run. The "date" command is an obvious example. Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer. If this causes a problem, delete these patterns or replace
# them with wildcards. An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt). The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don
set timeout -1
# get hostname
spawn "/bin/hostname"
expect
set myname $expect_out(buffer)
puts "hostname : $myname";
spawn chntpw -e /mnt/win/Windows/System32/config/SYSTEM
match_max 100000
expect -exact "> "
send -- "cd ControlSet001"
expect -exact "cd ControlSet001"
send -- "\r"
expect -exact "\\ControlSet001> "
send -- "cd Control"
expect -exact "cd Control"
send -- "\r"
expect -exact "\\ControlSet001\\Control> "
send -- "cd ComputerName"
expect -exact "cd ComputerName"
send -- "\r"
expect -exact "\\ControlSet001\\Control\\ComputerName> "
send -- "cd ComputerName"
expect -exact "cd ComputerName"
send -- "\r"
expect -exact "(...)\\Control\\ComputerName\\ComputerName> "
send -- "ed ComputerName"
expect -exact "ed ComputerName"
send -- "\r"
expect -exact "-> "
send -- "$myname"
expect -exact "(...)\\Control\\ComputerName\\ComputerName> "
send -- "q\r"
expect -exact "Write hive files? (y/n) \[n\] : "
send -- "y\r"
expect eof
-------------- next part --------------
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Wed Nov 28 12:29:16 2012
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
#
# 2) differing output - Some programs produce different output each time
# they run. The "date" command is an obvious example. Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer. If this causes a problem, delete these patterns or replace
# them with wildcards. An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt). The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don
set timeout -1
# get hostname
spawn "/bin/hostname"
expect
set myname $expect_out(buffer)
puts "hostname : $myname";
spawn chntpw -e /mnt/win/Windows/System32/config/SYSTEM
match_max 100000
expect -exact "> "
send -- "cd ControlSet001"
expect -exact "cd ControlSet001"
send -- "\r"
expect -exact "\\ControlSet001> "
send -- "cd Services"
expect -exact "cd Services"
send -- "\r"
expect -exact "\\ControlSet001\\Services> "
send -- "cd Tcpip"
expect -exact "cd Tcpip"
send -- "\r"
expect -exact "\\ControlSet001\\Services\\Tcpip> "
send -- "cd Parameters"
expect -exact "cd Parameters"
send -- "\r"
expect -exact "\\ControlSet001\\Services\\Tcpip\\Parameters> "
send -- "ed HostName"
expect -exact "ed HostName"
send -- "\r"
expect -exact "-> "
send -- "$myname"
send -- "\r"
expect -exact "\\ControlSet001\\Services\\Tcpip\\Parameters> "
send -- "ed NV HostName"
expect -exact "ed NV HostName"
send -- "\r"
expect -exact "-> "
send -- "$myname"
send -- "\r"
expect -exact "\\ControlSet001\\Services\\Tcpip\\Parameters> "
send -- "q\r"
expect -exact "Write hive files? (y/n) \[n\] : "
send -- "y\r"
expect eof
-------------- next part --------------
A non-text attachment was scrubbed...
Name: restoreEfiWindowsFromClusterFS.sh
Type: application/x-shellscript
Size: 13174 bytes
Desc: not available
URL: <http://lists.uni-koeln.de/pipermail/linux-fai/attachments/20190812/41e19dad/attachment-0007.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: renameWindows10.sh
Type: application/x-shellscript
Size: 1138 bytes
Desc: not available
URL: <http://lists.uni-koeln.de/pipermail/linux-fai/attachments/20190812/41e19dad/attachment-0008.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: restoreWindowsFromClusterFS.sh
Type: application/x-shellscript
Size: 11390 bytes
Desc: not available
URL: <http://lists.uni-koeln.de/pipermail/linux-fai/attachments/20190812/41e19dad/attachment-0009.bin>
More information about the linux-fai
mailing list