linux下制作windows启动U盘

众所周知,在linux下制作linux启动盘是非常容易的,假如/path/to/livecd.iso是一个linux系统的镜像,我们可以直接使用dd命令将其写入到优盘上。假如u盘是/dev/sdb,那么我们可以直接使用linux自带的命令:

$ sudo dd if=/path/to/livecd.iso of=/dev/sdb bs=4MiB && sync

来将镜像直接整体写入u盘中,完全不需要任何第三方的软件帮助。

然而,制作windows的系统镜像是有一定的困难的,一般需要下载第三方的软件。windows上有微软第一方的启动盘制作工具,也有久负盛名的rufus。但是在linux下,有太多可选择的软件,对于有选择困难症的人而言,很容易出现不知道选哪个的情况。

这里,我们介绍一个利用rufus的资源文件实现windows启动盘制作的方法。

具体流程

软件依赖 parted,ntfs-3g.

在ubuntu为例,可以这样安装依赖:

$ sudo apt install parted ntfs-3g

以archlinux为例,可以这样安装依赖:

$ sudo pacman -S parted ntfs-3g

但是这两个软件很有可能在系统中已经存在,可以使用:

$ parted -h
$ mkntfs -h

来检查是否已经安装成功。

资源依赖

uefi-nefs.img

uefi-ntfs.img

windows.iso(后续假定为这个名字,将这个名字改为下载文件的名字)

[](https://www.microsoft.com/zh-cn/software-download/windows10www.microsoft.com/zh-cn/software-download/windows10)

u盘分区

我们首先使用fdisk来查看u盘的信息:

$ sudo fdisk -l

找到u盘部分,例如:

Disk /dev/sdb: 14.32 GiB, 15376000000 bytes, 30031250 sectors
Disk model: Ultra USB 3.0   
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: gpt
Disk identifier: 0B815605-FFAD-47FE-9A34-1BF5E93C11AD

Device        Start      End  Sectors  Size Type
/dev/sdb1      2048 30027775 30025728 14.3G Microsoft basic data
/dev/sdb2  30027776 30029823     2048    1M Microsoft basic data

我们关注的是第一行和第三行:该u盘有30031250个扇区,每个扇区512个字节。我们按照1MiB对齐,也就是2048个扇区,计算第一个分区的结束位置和第二个分区的结束位置:

我们使用parted来进行u盘分区:

$ sudo parted /dev/sdb

进入交互式的命令界面后,新建分区表和两个分区:

(parted) mklabel gpt
(parted) mkpart windows-iso ntfs 1MiB 30027775s
(parted) mkpart efi fat32 30027776s 30029823s
(parted) set 2 boot on
(parted) quit

然后回到shell后,首先再次使用 sudo fdisk -l 确认第二个分区的扇区数乘以每扇区大小为1MiB:

Disk /dev/sdb: 14.32 GiB, 15376000000 bytes, 30031250 sectors
Disk model: Ultra USB 3.0   
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: gpt
Disk identifier: 0B815605-FFAD-47FE-9A34-1BF5E93C11AD

Device        Start      End  Sectors  Size Type
/dev/sdb1      2048 30027775 30025728 14.3G Microsoft basic data
/dev/sdb2  30027776 30029823     2048    1M Microsoft basic data

也就是最后一行的2048 * 第三行的512 = 1024 * 1024,然后格式化这两个分区:

$ sudo mkntfs -F /dev/sdb1
$ sudo mkfs -t vfat /dev/sdb2

写入efi分区

$ sudo dd if=/path/to/uefi-nefs.img of=/dev/sdb2 bs=1MiB && sync

写入windows系统镜像

首先我们将iso镜像挂载为虚拟磁盘:

$ sudo mkdir /mnt/windows-iso
$ sudo mount -t udf,iso9660 -o loop /path/to/windows.iso /mnt/windows-iso

然后挂载u盘的第一个分区:

$ sudo mkdir /mnt/usb-drive
$ sudo mount /dev/sdb1 /mnt/usb-drive

note!

如果提示 Mount is denied because the NTFS volume is already exclusively opened. The volume may be already mounted, or another software may use it which could be identified for example by the help of the 'fuser' command. 错误,说明这个挂载的卷被占用,可以使用 sudo fuser -m -u /dev/sdb1 查看占用的进程号,然后使用 sudo kill num 杀死这个进程再执行挂载命令就可以了。

然后将iso镜像内的文件全部拷贝到u盘中:

$ sudo cp -r /mnt/windows-iso/* /mnt/usb-drive

使用sync命令确定所有内容均已写入了u盘中:

$ sync

然后卸载挂载的设备并删除挂载点:

$ sudo umount /mnt/usb-drive
$ sudo umount /mnt/windows-drive
$ sudo rmdir /mnt/usb-drive
$ sudo rmdir /mnt/windows-drive

这样启动u盘就制作完成并且可以拔下来了。

原理

现在的windows镜像本身就是一个efi分区,但是其中的install.wim文件现在通常是大于4G的,也就大于了fat32分区所能够支持的最大文件大小。因此,我们没有办法把windows镜像直接拷入一个fat32的分区。虽然并无规定禁止efi从除了fat以外的文件系统启动(例如一些intel出的NUC就可以从ntfs直接启动),但是通常的uefi固件不见得会支持ntfs。

由于上述的原因,我们选择将windows镜像的文件拷入一个ntfs的文件系统中,然后使用第二个fat32的文件系统来进行启动,并加载ntfs文件系统的驱动,然后链式启动ntfs文件系统的中windows启动文件。这第二个分区的内容正是rufus的贡献,我们可以通过dd直接将其写入第二个分区。而第一个ntfs分区只是普通的分区罢了,格式好后,挂载时也可以通过系统的托盘挂载,拷贝时也可以选择打开文件管理器,然后使用ctrl+c和ctrl+v 来复制粘贴。