CF-R4は、2006年発売、Windows XP SP2を搭載したノートPCです。
2011年に秋葉原の中古PCショップで3万円ぐらいで購入したような記憶があります。
メモリを1GB増設し、内蔵HDDをSSDに換装し、現在はDebian 12を動かしています。
ここで「バッテリー充電のECOモードを切り替えたい」など、元々のWindows XP環境が必要になったケースを考えます。
換装前のHDDにWindows XP環境があるにはあるのですが、内蔵ストレージを付け替えるには筐体をだいぶバラす必要があり大変です。
また、残念なことにCF-R7以前の導入済みドライバーの公開が終了しており、WindowsをクリーンインストールしてECOモード関係のツールをインストールする手も使えなさそうです。
というわけで、換装後のSSD上にリカバリ領域を復元し、そこからWindows XPをリカバリしてみることにしました。
最終的にWindows XPとDebianのデュアルブートにするところまで行います。
リカバリ領域の復元
CF-R4は本来、BIOSセットアップユーティリティのメニューからリカバリを実行できるようになっていますが、リカバリ領域が破壊されるなどするとメニューに表示されなくなるようです。
ここではオリジナルと同様に、BIOSからリカバリメニューに入れる状態にすることを目指します。
リカバリ領域のイメージ作成
SSD換装前の元のHDDを適当なLinuxマシンに繋いで中身を見てみると、リカバリ領域はパーティションとしては見えていません。
% sudo fdisk -l /dev/sdb
Disk /dev/sdb: 55.89 GiB, 60011642880 bytes, 117210240 sectors
Disk model: USB Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000021
Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 63 41945714 41945652 20G 7 HPFS/NTFS/exFAT
/dev/sdb2 41945715 110912759 68967045 32.9G 7 HPFS/NTFS/exFAT
sdb2の最後のセクタの次のセクタ(110912760)を読んでみると、なんとなくそれっぽい領域が見えます。
% sudo dd if=/dev/sdb bs=512 skip=110912760 count=1 status=none | hexdump -C
00000000 eb 58 90 49 42 4d 20 20 37 2e 31 00 02 08 20 00 |.X.IBM 7.1... .|
00000010 02 00 00 00 00 f8 00 00 3f 00 ff 00 f8 64 9c 06 |........?....d..|
00000020 88 17 60 00 00 18 00 00 00 00 00 00 02 00 00 00 |..`.............|
00000030 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 80 00 29 0c 15 24 12 48 44 52 45 43 4f 56 45 52 |..)..$.HDRECOVER|
00000050 59 20 46 41 54 33 32 20 20 20 fa 33 c0 8e d0 bc |Y FAT32 .3....|
:
000001d0 e3 93 5a f7 e2 03 d3 c3 49 42 4d 42 49 4f 20 20 |..Z.....IBMBIO |
000001e0 43 4f 4d 49 42 4d 44 4f 53 20 20 43 4f 4d 0d 0a |COMIBMDOS COM..|
000001f0 42 6f 6f 74 20 66 61 69 6c 75 72 65 00 00 55 aa |Boot failure..U.|
00000200
110912760〜ディスク末尾までをイメージファイルとして書き出します。
% sudo dd if=/dev/sdb bs=512 skip=110912760 of=CF-R4_HDRecovery.img status=progress
6297480+0 records in
6297480+0 records out
3224309760 bytes (3.2 GB, 3.0 GiB) copied, 163.134 s, 19.8 MB/s
書き出したイメージをfile
コマンドで見てみると、ちゃんとパーティションとして認識されていそうです。
% file CF-R4_HDRecovery.img
CF-R4_HDRecovery.img: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "IBM 7.1", sectors/cluster 8, Media descriptor 0xf8, sectors/track 63, heads 255, hidden sectors 110912760, sectors 6297480 (volumes > 32 MB), FAT (32 bit), sectors/FAT 6144, serial number 0x1224150c, label: "HDRECOVERY "
ここで、hidden sectors
の値(110912760
)は、元のHDD上のリカバリ領域の先頭セクタの値と一致しています。
後でSSDに復元するときに書き換えたほうが良さそうです。
この値は、先頭セクタの28バイト目(0x1c)から31バイト目(0x1f)の4バイトにあります。(110912760 = 0x69C64F8 (f8 64 9c 06))
(参考: FATファイルシステムのしくみと操作法)
00000000 eb 58 90 49 42 4d 20 20 37 2e 31 00 02 08 20 00 |.X.IBM 7.1... .|
00000010 02 00 00 00 00 f8 00 00 3f 00 ff 00 f8 64 9c 06 |........?....d..|
00000020 88 17 60 00 00 18 00 00 00 00 00 00 02 00 00 00 |..`.............|
:
復元先の準備
換装後のSSD(64GB)にはDebianが入っています。
元のパーティションテーブルは以下のとおりです。
- sda1: Debianのルート(/)
- sda2: 拡張パーティション
- sda5: SWAP領域
% sudo fdisk -l
Disk /dev/sda: 59.63 GiB, 64023257088 bytes, 125045424 sectors
Disk model: CFD CSSD-PMM64WJ
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3cbed967
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 121094143 121092096 57.7G 83 Linux
/dev/sda2 121096190 125044735 3948546 1.9G 5 Extended
/dev/sda5 121096192 125044735 3948544 1.9G 82 Linux swap / Solaris
- 元のHDDサイズ117210240 - リカバリ領域サイズ6297480 = 先頭位置110912760
- 換装後SSDサイズ125045424 - リカバリ領域サイズ6297480 = 先頭位置118747944
ということで、以下の方針で進めます。
- sda1とsda2を118747943セクタまで縮める
- sda2(sda5 スワップ)は一旦削除
- sda1をresize2fsで一旦50Gぐらいまで縮める
※ここでリカバリ領域の先頭位置をシリンダ境界に合わせる必要があったのですが、それは後述…
GParted Liveで起動してsda1を縮めます。
# e2fsck -f /dev/sda1
# resize2fs /dev/sda1 50G
# fdisk /dev/sda
:
/dev/sda1 * 2048 118747943 118745896 56.6G 83 Linux
:
# e2fsck -f /dev/sda1
# resize2fs /dev/sda1
復元先へのイメージ書き込み
# dd if=CF-R4_HDRecovery.img bs=512 seek=118747944 conv=notrunc status=progress of=/dev/sda
:
6297480+0 records in
6297480+0 records out
3224309760 bytes (3.2 GB, 3.0 GiB) copied, 438.675 s, 7.4 MB/s
この時点では、BIOSにリカバリメニューは復活しませんでした。
単純にイメージを書き戻しただけではダメなようです。
リカバリ領域から起動できるようにする
リカバリ領域をパーティションテーブルに作成してみる
ここで、CF-R4内のSSDは/dev/sda
として認識されています。
fdiskで先頭118747944からサイズ6297480のパーティションを作成します。
# fdisk /dev/sda
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 4
First sector (118747944-125045423, default 118749184): 118747944
Last sector, +/-sectors or +/-size{K,M,G,T,P} (118747944-125045423, default 125045423):
Created a new partition 4 of type 'Linux' and of size 3 GiB.
Command (m for help): t
Partition number (1,4, default 4): 4
Hex code or alias (type L to list all): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.
Command (m for help): a
Partition number (1,4, default 4): 4
The bootable flag on partition 4 is enabled now.
Command (m for help): a
Partition number (1,4, default 4): 1
The bootable flag on partition 1 is disabled now.
Command (m for help): p
Disk /dev/sda: 59.63 GiB, 64023257088 bytes, 125045424 sectors
Disk model: CFD CSSD-PMM64WJ
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3cbed967
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 118747943 118745896 56.6G 83 Linux
/dev/sda4 * 118747944 125045423 6297480 3G c W95 FAT32 (LBA)
Command (m for help): w
The partition table has been altered.
Syncing disks.
リカバリ領域のhidden sectors値を書き換える
パーティション先頭セクタのhidden sectors部分を110912760
から118747944
に書き換えておきます。
第4パーティションの先頭セクタをファイルにダンプします。
# dd if=/dev/sda bs=512 skip=118747944 count=1 status=none of=sda4_pbr.bin
# file sda4_pbr.bin
sda4_pbr.bin: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "IBM 7.1", sectors/cluster 8, Media descriptor 0xf8, sectors/track 63, heads 255, hidden sectors 110912760, sectors 6297480 (volumes > 32 MB), FAT (32 bit), sectors/FAT 6144, serial number 0x1224150c, label: "HDRECOVERY "
適当なバイナリエディタで書き換えます。
# bvi sda4_pbr.bin
:
# file sda4_pbr.bin
sda4_pbr.bin: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "IBM 7.1", sectors/cluster 8, Media descriptor 0xf8, sectors/track 63, heads 255, hidden sectors 118747944, sectors
6297480 (volumes > 32 MB), FAT (32 bit), sectors/FAT 6144, serial number 0x1224150c, label: "HDRECOVERY "
SSDに書き込みます。
# dd if=sda4_pbr.bin bs=512 seek=118747944 conv=notrunc count=1 of=/dev/sda
GRUBからリカバリ領域を起動しようとしてみる
このSSDにはDebianをインストールしていたので、ブートローダにはGRUB2が入っています。
GRUBのコマンドシェルからリカバリ領域(第4パーティション)を起動できるか試してみます。
参考: GRUB - ArchWiki
grub> set root=(hd0,4)
grub> chainloader +1
grub> boot
うまくいけば、ここでリカバリが起動できるはずです。
うまくいかなかった例:
chainloader +1
でerror: invalid signature.
になる- →パーティションテーブルの先頭セクタの値が間違っている
boot
の後、Starting PC DOS...
から進まない- →パーティションのタイプ変更漏れ(FAT32に変更すべきところがLinuxのままになっていた)
boot
の後、Boot failure
になる- →hidden sectorsの値が間違っている
BIOSのメニューからリカバリ領域を起動できるようにする
起動したリカバリ環境でCtrl+C
を押すと終了してプロンプトに移行することができます。
ここでmakebeer
コマンドやrecvmode
コマンドを使うことで、BIOSメニューにリカバリメニューを復元できそうなので試してみます。
参考: Let’snoteテンプレ - リカバリ関連 (Internet Archive)
makebeer /copy
ERROR:Invalid Partition Address (0x0713f328), expected=0x0713c61f
どうもパーティションの先頭をシリンダ境界に合わせないとダメそうです。
今回の環境では、63セクタ×255ヘッド = 16065セクタがシリンダ境界となります。
第4パーティションの位置を現在の118747944から、直近の16065の倍数になるところ(118736415)に変更してみます。
- sda1の縮小(Windows用に10GB確保するため、45GB)
e2fsck -f /dev/sda1
resize2fs /dev/sda1 44G
(後でパーティションに合わせて拡大する)fdisk /dev/sda
- sda4の削除
- sda4の作成
fdisk /dev/sda
- 118736415~125033894 (6297480 sectors)
- type c (W95 FAT32 (LBA))
- イメージの書き込み
dd if=CF-R4_HDRecovery.img bs=512 status=progress of=/dev/sda4
- hidden sectors値の書き換え(118736415)
その後、makebeer /copy
、makebeer /ndos
、recvmode /normal
を実行して電源を入れ直します。
F2
でBIOSメニューに入り「終了」を選ぶと、「ハードディスク リカバリー / 消去」メニューが出現しました。
選択するとリカバリが起動できました。
デュアルブートにする
既存のDebianを残したまま、Windowsをインストールするための領域を確保し、そこにリカバリを行います。
また、GRUBのメニューでWindowsを起動できるようにします。
既存のLinuxパーティションを移動する
GUIのあるgparted
ではパーティションの移動が行えますが、CUIのparted
ではmove
コマンドが3.0以降無くなったようです。
gpartedが動くLinux Live USBをいくつか試しましたが、i686と1.5GBのメモリで動くような古いものだと、最近のLinuxで作成したパーティションに対してe2fsck
できず、パーティションのリサイズが行えないことがありました。
GParted LiveではXが起動できなかったので、CUIでなんとかすることにします。
ということで、以下の方針で進めます。
- sda1を10GBに縮小する
- sda2を同じサイズで作成する
- sda1の内容をsda2にdumpする
dd if=/dev/sda1 of=/dev/sda2 bs=4096 status=progress
- sda1を削除し再作成する
- 先頭は63ではなく2048セクタからにしておく
- sda2を拡張する
Linuxがsda2から起動できるようにする
そのままブートすると、sda1から起動していました。
今回は
- sda2のUUIDを変更、
/boot/grub/grub.cfg
を変更 - GRUBのコマンドシェルでsda2のgrub.cfgを読ませる
grub> configfile (hd0,2)/boot/grub/grub.cfg
という手順でsda2からブートするようにしましたが、
sda1のUUIDを変更してしまうのが手っ取り早かったかもしれません。
GRUBの設定変更
GRUBがWindowsを見つけられるように、/etc/default/grub
にGRUB_DISABLE_OS_PROBER=false
を追加しておきます。
update-grub
してgrub-install /dev/sda
しておきます。
最初のパーティションにWindowsをリストアする
セットアップユーティリティから「ハードディスク リカバリー / 消去」を実行します。
「最初のパーティションにWindowsを再インストールする」を選びます。
GRUBが壊れた
MBRはWindowsに書き換えられるかと思いきや、GRUBが残っていました。
起動すると、一瞬GRUBの文字が表示されますが、すぐに再起動してしまいます。
おそらくMBR以降のセクタに書かれていたcore.img部分が消えてしまったのではないかと思います。
GRUBを再インストールする
復旧のため、GRUBを再インストールします。
GParted Liveで起動し、sda2をマウントし、chroot
してDebianに入っているgrubを使ってインストールします。
# mount /dev/sda2 /mnt
# mount --bind /dev /mnt/dev
# mount --bind /dev/pts /mnt/dev/pts
# mount --bind /proc /mnt/proc
# mount --bind /sys /mnt/sys
# chroot /mnt
# update-grub
# grub-install --target=i386-pc /dev/sda
# exit
grub-install
でtarget
を指定しないと以下のようなエラーになりました。chroot環境下でうまく自動判定できなかったのかもしれません。
grub-install: error: /usr/lib/grub/i386-ieee1275/modinfo.sh doesn't exist. Please specify --target or --directory
再起動するとGRUBのメニューが表示されるようになりました。
メニューからWindows XPを起動すると、無事起動し、OOBE画面になりました。
Windowsリカバリ後の第1パーティションの先頭位置
リカバリ前にあらかじめsda1を開始セクタ2048で作成していたのですが、リカバリ後にパーティションテーブルを確認すると、開始セクタは63、終了セクタも変わっている(シリンダ境界にアラインされている)ので、既存のパーティションはリカバリ時に一度削除され、再作成されたように見えます。
Debian側の時刻設定
RTCをWindows側に合わせてUTCではなくローカル時刻として運用するよう設定変更します。
# timedatectl set-local-rtc 1
おまけ1: MAKEBEERコマンドのヘルプ
makebeerコマンドは、USBメモリから起動したDOSで実行するとうまく内蔵HDD/SSDを認識できないようです。(USBメモリが最初のHDDとして認識されているためか?)ERROR:Failed to Read BEER Sector.
やERROR:Failed to Write BEER Sector.
のようなエラーが出ます。
USB接続のフロッピーディスクドライブからDOSを起動するか、内蔵HDD/SSDからDOSを起動して実行するとうまくいくようです。
Usage:MAKEBEER.EXE [Option Switch]
X make the BEER sector, X is Recovery Area size (GB in decimal)
/FAT32 change Recovery Partition's ID to FAT32
/BUPFAT32 change Backup Partition's ID to FAT32
/ACTIVE make the 4th Partition active
/NDOS change Recovery Partition's ID to Non-DOS (0x84)
/BUPNDOS change Backup Partition's ID to Non-DOS (0x84)
/REMOVE remove the 4th partition entry from the partition table
/BOOTCLR clear the Boot Sector of the Recovery Partition
/COPY make a BEER sector based on the Partition Table 4th Entry
/REGISTER register a Backup Area with the BEER sector
/SETVOLn= (n=1,2,3,4) set specified partition's Volume Label
/CHECK check the BEER sector and the 4th partition
/CHECKBEER check the BEER sector for Recovery Area
/CHKRCVBEER check the BEER sector for Recovery Area
/CHECKBOOT check the BEER sector and Recovery Partition's Boot sector
/CHECKPT4 /CHECKBOOT and additional check that the 4th entry is empty
/CHKBUPBEER check the BEER sector for Backup Area
/CHKBUPBOOT check the BEER sector and Boot Sector of the Backup Partition
/F make first partition active
おまけ2: RECVMODEコマンドのヘルプ
Usage:RECVMODE.EXE [/NORMAL|/BACKUP|/EDIT|/DISABLE] [/LASTACTIVE] [/SHOWALL]
/NORMAL set Normal Mode
/BACKUP set Backup Mode
/EDIT set Edit Mode
/DISABLE set Disable Mode
/LASTACTIVE set active flag of the last active partition
/SHOWALL show the CMOS settings with Hard Disk Recovery