Moving a Windows installation to a new disk

Situation

A Windows install exists on a old 64 GB Crucial M4 SSD.

According to SMART data (attribute 202), the SSD is reaching the end of its life (20% remaining).

The Windows installation boots with the legacy/PC/BIOS/MBR -> VBR -> bootmgr boot method.

Mission

A new 500 GB SSD has been purchased and the Windows install is to be transferred to the new drive.

The Windows installation's filesystem is to be expanded to make use of the increased space.

Execution

Attach the new SSD to a spare SATA port.

Boot into Linux.

Use fdisk to examine the MBR partition table on the old SSD. There are actually three partitions:

No

Type

Flags

Size

Description

1

0x07

active

100 MiB

"system" partition (Windows boot loader)

2

0x07

none

~64 GiB

"boot" partition (Windows installation)

3

0x07

none

508 MiB

recovery partition

Yes, in Windows terminology the partition with the boot loader code is called the "system" partition, and the partition with the Windows system files is called the "boot" partition πŸ™„.

Use fdisk to create a new MBR partition table on the new SSD. This tool is preferred over parted because it gives precise control over the partition numbers/offsets/sizes.

Preserve the offset and size of the system partition.

Preserve the size of the recovery partition, but situate it at the end of the disk.

Create a new boot partition in between the other two partitions, filling the remaining space.

Transfer the contents of all three partitions to their counterparts on the new disk. This is done with cp, whcih has the advantage of preserving the filesystem IDs so that the Windows installation does not become confused when booted from the new disk; as well as the volume boot record from the "system" partition, that is needed to load bootmgr (the Windows boot manager). Since the old SSD is quite small, only an insignificant amount of time is wasted by copying unallocated blocks.

Use ntfsresize to expand the new "boot" partition to take advantage of its increased size.

Install a boot loader into the new SSD's MBR; I used TestDisk, alternatives are mbr or ms-sys.

Power off and remove the old SSD. Move the new SSD to the SATA port used by the old SSD.

Power on and see if the boot sequence is able to load Windows.

Discover that it doesn't with a very generic error code: 0xc00000e(?) from winload. At least this means that the MBR boot code -> "system" partition VBR boot code -> bootmgr sequence worked. But it looks like (and I'm not 100% sure) bootmgr was not able to load winload? In any case, it's time to begin recovery.

Prepare a Windows installer USB disk and boot from it.

Explore recovery options:

  • As is normal with such Windows features, the automated recovery process takes a very long time to do nothing useful at all
  • bootrec /RebuildBcd fails

  • Give up and drop to command prompt

Research the Windows boot sequence and learn about the BCD which is found on the "system" partition at boot\bcd.

Is this partition mounted? diskpart -> list vol shows that it is mounted at C:. Also our "boot" partition is mounted at H:.

From the command prompt we can examine the BCD. Note the device and osdevice attributes of the entries:

  • X:\> bcdedit /store C:\boot\bcd /enum
    
    Windows Boot Manager
    --------------------
    identifier {bootmgr}
    device unknown
    description Windows Boot Manager
    locale en-US
    inherit {globalsettings}
    default {current}
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    displayorder {current}
    toolsdisplayorder {memdiag}
    timeout 30
    
    Windows Boot Loader
    -------------------
    identifier {default}
    device unknown
    path \WINDOWS\system32\winload.exe
    description Windows 10
    locale en-US
    inherit {bootloadersettings}
    recoverysequence {be7cca88-d4dd-11ea-952c-d64492fae58f}
    displaymessageoverride Recovery
    recoveryenabled Yes
    allowedinmemorysettings 0x15000075
    osdevice unknown
    systemroot \WINDOWS
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    nx OptIn
    bootmenupolicy Standard

Whatever method the BCD entry uses to identify partitions is not recognizing the "boot" partition and it's printing unknown.

The fix is to run:

  • bcdedit /store C:\boot\bcd /set {bootmgr} device partition=C:

  • bcdedit /store C:\boot\bcd /set {default} device partition=H:

  • bcdedit /store C:\boot\bcd /set {default} osdevice partition=H:

After that, bcdedit /store C:\boot\bcd /enum no longer prints unknown and instead prints partition=C: and partition=H: for the {bootmgr} and {default} entries, respectively.

Reboot. Windows boots up. Success!

Now to battle with Windows Activation. Or so I expected... but running slmgr /xpr shows that the system is still activated; so swapping out the install disk hasn't deactivated the installation.

We're done!

Post-mortem

We really could have used a better diagnostic information from bootmgr than a single extremely generic error code.

In order to figure out why the bootmgr couldn't find the new "system" and "boot" partitions, we must examine the BCD and get our thinking caps on:

Unfortunately the output of bcdedit is not useful for this purpose:

  • If an attribute refers to a partition that contains a mounted filesytem, it prints e.g., partition=C: depending on the drive letter of the filesystem

  • If an attribute refers to a partition that contains an unmounted filesystem, it prints e.g., partition=\Device\HarddiskVolume1

  • If an attribute refers to a partition that can't be found, it prints unknown; in this case there's no way to find out exactly why the partition can't be found

Fortunately there is an undocumented /raw flag that shows the 'actual' contents of the attributes instead of their interpretation, given currently present partitions.

After booting successfully we can use this to discover exactly how attributes refer to partitions, and deduce why the "boot" partition couldn't be found after transfer.

  • PS C:\Users\root> bcdedit /enum /raw
    
    Windows Boot Manager
    --------------------
    identifier {bootmgr}
    device PartEx 100000 HD MBR Sig:30ed3ac0
    description Windows Boot Manager
    locale en-US
    inherit {globalsettings}
    default {current}
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    displayorder {current}
    toolsdisplayorder {memdiag}
    timeout 30
    
    Windows Boot Loader
    -------------------
    identifier {current}
    device PartEx 6500000 HD MBR Sig:30ed3ac0
    path \WINDOWS\system32\winload.exe
    description Windows 10
    locale en-US
    inherit {bootloadersettings}
    recoverysequence {be7cca88-d4dd-11ea-952c-d64492fae58f}
    displaymessageoverride Recovery
    recoveryenabled Yes
    allowedinmemorysettings 0x15000075
    osdevice PartEx 6500000 HD MBR Sig:30ed3ac0
    systemroot \WINDOWS
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    nx OptIn
    bootmenupolicy Standard

And now we can see how a partition is referred to in the database.

PartEx 6500000 HD MBR Sig:30ed3ac0

We can deduce that partitions (on a disk with an MBR partition table) are identified by "disk signature" (4 bytes in the MBR) and offset (the larger number).

In creating a new MBR partition table on the new disk, I forgot to preserve the "disk signature" from the old disk. Thus the BCD entries were referring to partitions on the old disk, which couldn't be found.

We know the larger number is the partition table offset in big-endian hexadecimal, because our "system" and "boot" partition start exactly 1 and 101 MiB into the disk, respectively, and using Python we can convert that into exact byte offsets, formatted in hexadecimal.

  • >>> hex(1 * 2**20)
    '0x100000'
    
    >>> hex(101 * 2**20)
    '0x6500000'

And we can confirm what we already know, that the attribute now matches the "disk signature" of the new SSD's partition table:

  • PS C:\Users\root> diskpart
    
    Microsoft DiskPart version 10.0.19041.964
    
    Copyright (C) Microsoft Corporation.
    On computer: TYCHO
    
    DISKPART> select disk 0
    
    Disk 0 is now the selected disk.
    
    DISKPART> uniqueid disk
    
    Disk ID: 30ED3AC0

There are actually a number of other entries in the BCD to do with resuming from hibernation and booting into the recovery partition.

  • PS C:\Users\root> bcdedit /enum all /raw
    
    Windows Boot Manager
    --------------------
    identifier {bootmgr}
    device PartEx 100000 HD MBR Sig:30ed3ac0
    description Windows Boot Manager
    locale en-US
    inherit {globalsettings}
    default {current}
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    displayorder {current}
    toolsdisplayorder {memdiag}
    timeout 30
    
    Windows Boot Loader
    -------------------
    identifier {current}
    device PartEx 6500000 HD MBR Sig:30ed3ac0
    path \WINDOWS\system32\winload.exe
    description Windows 10
    locale en-US
    inherit {bootloadersettings}
    recoverysequence {be7cca88-d4dd-11ea-952c-d64492fae58f}
    displaymessageoverride Recovery
    recoveryenabled Yes
    allowedinmemorysettings 0x15000075
    osdevice PartEx 6500000 HD MBR Sig:30ed3ac0
    systemroot \WINDOWS
    resumeobject {08903c75-d529-11ea-bc49-e1ca39795d5d}
    nx OptIn
    bootmenupolicy Standard
    
    Windows Boot Loader
    -------------------
    identifier {13c7b309-851c-11e1-9794-8a7ddd0bbd15}
    device RAMDISK Image:0/0 File PartEx 6500000 HD MBR Sig:5a0cba8d \Recovery13円c7b309-851c-11e1-9794-8a7ddd0bbd15\Winre.wim
    path \windows\system32\winload.exe
    description Windows Recovery Environment
    inherit {bootloadersettings}
    osdevice RAMDISK Image:0/0 File PartEx 6500000 HD MBR Sig:5a0cba8d \Recovery13円c7b309-851c-11e1-9794-8a7ddd0bbd15\Winre.wim
    systemroot \windows
    nx OptIn
    winpe Yes
    
    Windows Boot Loader
    -------------------
    identifier {ae221c28-5a77-11e8-aa97-b089d7fd1b5f}
    device RAMDISK Image:0/0 File PartEx ecbe00000 HD MBR Sig:5a0cba8d \Recovery\WindowsRE\Winre.wim
    path \windows\system32\winload.exe
    description Windows Recovery Environment
    locale en-US
    inherit {bootloadersettings}
    displaymessage Recovery
    osdevice RAMDISK Image:0/0 File PartEx ecbe00000 HD MBR Sig:5a0cba8d \Recovery\WindowsRE\Winre.wim
    systemroot \windows
    nx OptIn
    bootmenupolicy Standard
    winpe Yes
    
    Windows Boot Loader
    -------------------
    identifier {be7cca88-d4dd-11ea-952c-d64492fae58f}
    device RAMDISK Image:0/0 File PartEx ec8400000 HD MBR Sig:5a0cba8d \Recovery\WindowsRE\Winre.wim
    path \windows\system32\winload.exe
    description Windows Recovery Environment
    locale en-US
    inherit {bootloadersettings}
    displaymessage Recovery
    osdevice RAMDISK Image:0/0 File PartEx ec8400000 HD MBR Sig:5a0cba8d \Recovery\WindowsRE\Winre.wim
    systemroot \windows
    nx OptIn
    bootmenupolicy Standard
    winpe Yes
    
    Resume from Hibernate
    ---------------------
    identifier {08903c75-d529-11ea-bc49-e1ca39795d5d}
    device PartEx 6500000 HD MBR Sig:30ed3ac0
    path \WINDOWS\system32\winresume.exe
    description Windows Resume Application
    locale en-US
    inherit {resumeloadersettings}
    recoverysequence {be7cca88-d4dd-11ea-952c-d64492fae58f}
    recoveryenabled Yes
    allowedinmemorysettings 0x15000075
    filedevice PartEx 6500000 HD MBR Sig:30ed3ac0
    filepath \hiberfil.sys
    bootmenupolicy Standard
    debugoptionenabled No
    
    Windows Memory Tester
    ---------------------
    identifier {memdiag}
    device PartEx 100000 HD MBR Sig:5a0cba8d
    path \boot\memtest.exe
    description Windows Memory Diagnostic
    locale en-US
    inherit {globalsettings}
    badmemoryaccess Yes
    
    EMS Settings
    ------------
    identifier {emssettings}
    bootems No
    
    Debugger Settings
    -----------------
    identifier {dbgsettings}
    debugtype Serial
    debugport 1
    baudrate 115200
    
    RAM Defects
    -----------
    identifier {badmemory}
    
    Global Settings
    ---------------
    identifier {globalsettings}
    inherit {dbgsettings}
     {emssettings}
     {badmemory}
    
    Boot Loader Settings
    --------------------
    identifier {bootloadersettings}
    inherit {globalsettings}
     {hypervisorsettings}
    
    Hypervisor Settings
    -------------------
    identifier {hypervisorsettings}
    hypervisordebugtype Serial
    hypervisordebugport 1
    hypervisorbaudrate 115200
    
    Resume Loader Settings
    ----------------------
    identifier {resumeloadersettings}
    inherit {globalsettings}
    
    Device options
    --------------
    identifier {13c7b30a-851c-11e1-9794-8a7ddd0bbd15}
    description Ramdisk Options
    ramdisksdidevice PartEx 6500000 HD MBR Sig:5a0cba8d
    ramdisksdipath \Recovery13円c7b309-851c-11e1-9794-8a7ddd0bbd15\boot.sdi
    
    Device options
    --------------
    identifier {be7cca89-d4dd-11ea-952c-d64492fae58f}
    description Windows Recovery
    ramdisksdidevice PartEx ec8400000 HD MBR Sig:5a0cba8d
    ramdisksdipath \Recovery\WindowsRE\boot.sdi

I should probably go through each entry and fix up any that still reference partitions on my old disk, which I can see has the "disk signature" of 5a0cba8d. But to be honest I never use hibernation and if I need to boot the recovery partition I'll just boot off a separate USB, so this is not urgent.

Sources

robots.org.uk: MovingWindowsInstallationToNewDisk (last edited 2022εΉ΄11月02ζ—₯ 15:44:24 by sam )

© Sam Morris <sam@robots.org.uk>.
Content may be distributed and modified providing this notice is preserved.

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /