Compare commits

...

3 Commits

6 changed files with 448 additions and 74 deletions

View File

@ -11,19 +11,18 @@
One-Click Script to Reinstall System [中文](README.md) One-Click Script to Reinstall System [中文](README.md)
![Sponsors](https://raw.githubusercontent.com/bin456789/sponsors/refs/heads/master/sponsors.svg) [![Sponsors](https://raw.githubusercontent.com/bin456789/sponsors/refs/heads/master/sponsors.svg)](https://github.com/sponsors/bin456789)
## Highlights ## Highlights
- One-click Linux installation: Supports 19 common distributions. - One-click Linux installation: Supports 19 common distributions.
- One-click Windows installation: Uses the official ISO for installation instead of custom images. The script can automatically ~~retrieves the ISO link~~ and installs common drivers like `Virtio`. - One-click Windows installation: Uses the official ISO for installation instead of custom images. The script can automatically ~~retrieves the ISO link~~ and installs common drivers like `Virtio`.
- Supports installation in any direction, i.e., `Linux to Linux`, `Linux to Windows`, `Windows to Windows`, `Windows to Linux` - Supports installation in any direction, i.e., `Linux to Linux`, `Linux to Windows`, `Windows to Windows`, `Windows to Linux`
- No need to input IP parameters; automatically recognizes dynamic and static IPs, supports `/32`, `/128`, `gateway outside subnet`, `IPv6 only`, `dual NIC` and other special network configurations - No need to input IP parameters; automatically recognizes dynamic and static IPs, supports `/32`, `/128`, `gateway outside subnet`, `IPv6 only`, `dual NIC`
- Specially optimized for low-spec servers, requires less memory than the official netboot - Specially optimized for low-spec servers, requires less memory than the official netboot
- Uses partition table ID to identify hard drives throughout the process, ensuring no wrong disk is written - Uses partition table ID to identify hard drives throughout the process, ensuring no wrong disk is written
- Supports BIOS and EFI boot, and ARM Server - Supports BIOS and EFI boot, and ARM Server
- No homemades image included, all resources are obtained in real-time from mirror sites - No homemades image included, all resources are obtained in real-time from mirror sites
- Includes many comments.
## System Requirements ## System Requirements
@ -32,7 +31,7 @@ The original system can be any system listed in the table.
The system requirements for the target system are as follows: The system requirements for the target system are as follows:
| System | Version | Memory | Disk | | System | Version | Memory | Disk |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | --------- | -----------------| | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | --------- | ---------------- |
| <img width="16" height="16" src="https://www.alpinelinux.org/alpine-logo.ico" /> Alpine | 3.18, 3.19, 3.20, 3.21 | 256 MB | 1 GB | | <img width="16" height="16" src="https://www.alpinelinux.org/alpine-logo.ico" /> Alpine | 3.18, 3.19, 3.20, 3.21 | 256 MB | 1 GB |
| <img width="16" height="16" src="https://www.debian.org/favicon.ico" /> Debian | 9, 10, 11, 12 | 256 MB | 1 ~ 1.5 GB ^ | | <img width="16" height="16" src="https://www.debian.org/favicon.ico" /> Debian | 9, 10, 11, 12 | 256 MB | 1 ~ 1.5 GB ^ |
| <img width="16" height="16" src="https://github.com/bin456789/reinstall/assets/7548515/f74b3d5b-085f-4df3-bcc9-8a9bd80bb16d" /> Kali | Rolling | 256 MB | 1 ~ 1.5 GB ^ | | <img width="16" height="16" src="https://github.com/bin456789/reinstall/assets/7548515/f74b3d5b-085f-4df3-bcc9-8a9bd80bb16d" /> Kali | Rolling | 256 MB | 1 ~ 1.5 GB ^ |
@ -144,6 +143,7 @@ bash reinstall.sh anolis 7|8|23
kali kali
arch arch
gentoo gentoo
aosc
fnos fnos
``` ```
@ -329,6 +329,14 @@ bash reinstall.sh windows \
--iso "https://go.microsoft.com/fwlink/?linkid=2289029" --iso "https://go.microsoft.com/fwlink/?linkid=2289029"
``` ```
or Magnet Link
```bash
bash reinstall.sh windows \
--image-name "Windows 11 Enterprise LTSC 2024" \
--iso "magnet:?xt=urn:btih:7352bd2db48c3381dffa783763dc75aa4a6f1cff"
```
<details> <details>
<summary>The following website provides ISO links.</summary> <summary>The following website provides ISO links.</summary>
@ -336,6 +344,8 @@ bash reinstall.sh windows \
- General - General
- <https://msdl.gravesoft.dev> - <https://msdl.gravesoft.dev>
- <https://massgrave.dev/genuine-installation-media> - <https://massgrave.dev/genuine-installation-media>
- <https://next.itellyou.cn>
- <https://www.xitongku.com>
- <https://www.microsoft.com/software-download/windows10> (Need to open it with a non-Windows User-Agent) - <https://www.microsoft.com/software-download/windows10> (Need to open it with a non-Windows User-Agent)
- <https://www.microsoft.com/software-download/windows11> - <https://www.microsoft.com/software-download/windows11>
- <https://www.microsoft.com/software-download/windows11arm64> - <https://www.microsoft.com/software-download/windows11arm64>
@ -349,8 +359,8 @@ bash reinstall.sh windows \
- <https://www.microsoft.com/evalcenter/download-windows-server-2022> - <https://www.microsoft.com/evalcenter/download-windows-server-2022>
- <https://www.microsoft.com/evalcenter/download-windows-server-2025> - <https://www.microsoft.com/evalcenter/download-windows-server-2025>
- Insider Preview - Insider Preview
- <https://www.microsoft.com/software-download/windowsinsiderpreviewiso> - <https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewiso>
- <https://www.microsoft.com/software-download/windowsinsiderpreviewserver> - <https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewserver>
</details> </details>
@ -361,10 +371,9 @@ bash reinstall.sh windows \
- `--rdp-port PORT` Change RDP port - `--rdp-port PORT` Change RDP port
- `--ssh-port PORT` Change SSH port (for log observation during installation) - `--ssh-port PORT` Change SSH port (for log observation during installation)
- `--web-port PORT` Change Web port (for log observation during installation) - `--web-port PORT` Change Web port (for log observation during installation)
- `--add-driver-dir DIR` Adds additional driver, specifying the folder where the .inf file is located. - `--add-driver INF_OR_DIR` Add additional driver, specifying .inf path, or the folder contains .inf file.
- The driver must be downloaded locally first. - The driver must be downloaded locally first.
- This parameter can be set multiple times to add different driver folders. - This parameter can be set multiple times to add different driver.
- The script will copy the entire folder, so no other files should be placed inside the folder.
- `--hold 2` Allow SSH connections for modifying the disk content before rebooting into the official Windows installation program, with the disk mounted at `/os`. - `--hold 2` Allow SSH connections for modifying the disk content before rebooting into the official Windows installation program, with the disk mounted at `/os`.
#### The following drivers will automatic download and install as needed, without the need for manual addition #### The following drivers will automatic download and install as needed, without the need for manual addition

View File

@ -11,19 +11,18 @@
一键重装脚本 [English](README.en.md) 一键重装脚本 [English](README.en.md)
![捐赠者](https://raw.githubusercontent.com/bin456789/sponsors/refs/heads/master/sponsors.svg) [![Sponsors](https://raw.githubusercontent.com/bin456789/sponsors/refs/heads/master/sponsors.svg)](https://github.com/sponsors/bin456789)
## 亮点 ## 亮点
- 一键安装 Linux支持 19 种常见发行版 - 一键安装 Linux支持 19 种常见发行版
- 一键安装 Windows使用官方 ISO 安装而非自制镜像,~~脚本会自动获取 ISO 链接~~、自动安装 Virtio 等常见驱动 - 一键安装 Windows使用官方 ISO 安装而非自制镜像,~~脚本会自动获取 ISO 链接~~、自动安装 Virtio 等常见驱动
- 支持任意方向重装,即 `Linux to Linux``Linux to Windows``Windows to Windows``Windows to Linux` - 支持任意方向重装,即 `Linux to Linux``Linux to Windows``Windows to Windows``Windows to Linux`
- 无需填写 IP 参数,自动识别动静态,支持 `/32``/128``网关不在子网范围内``纯 IPv6``双网卡` 等特殊网络 - 无需填写 IP 参数,自动识别动静态,支持 `/32``/128``网关不在子网范围内``纯 IPv6``双网卡`
- 专门适配低配小鸡,比官方 netboot 需要更少的内存 - 专门适配低配小鸡,比官方 netboot 需要更少的内存
- 全程用分区表 ID 识别硬盘,确保不会写错硬盘 - 全程用分区表 ID 识别硬盘,确保不会写错硬盘
- 支持 BIOS、EFI 引导,支持 ARM 服务器 - 支持 BIOS、EFI 引导,支持 ARM 服务器
- 不含自制包,所有资源均实时从镜像源获得 - 不含自制包,所有资源均实时从镜像源获得
- 有很多注释
## 系统要求 ## 系统要求
@ -330,6 +329,14 @@ bash reinstall.sh windows \
--iso "https://go.microsoft.com/fwlink/?linkid=2289029" --iso "https://go.microsoft.com/fwlink/?linkid=2289029"
``` ```
或者磁力链接
```bash
bash reinstall.sh windows \
--image-name "Windows 11 Enterprise LTSC 2024" \
--iso "magnet:?xt=urn:btih:7352bd2db48c3381dffa783763dc75aa4a6f1cff"
```
<details> <details>
<summary>以下网站可找到 ISO 链接</summary> <summary>以下网站可找到 ISO 链接</summary>
@ -337,6 +344,8 @@ bash reinstall.sh windows \
- 正式版 - 正式版
- <https://msdl.gravesoft.dev> - <https://msdl.gravesoft.dev>
- <https://massgrave.dev/genuine-installation-media> - <https://massgrave.dev/genuine-installation-media>
- <https://next.itellyou.cn>
- <https://www.xitongku.com>
- <https://www.microsoft.com/software-download/windows10> (需用非 Windows User-Agent 打开) - <https://www.microsoft.com/software-download/windows10> (需用非 Windows User-Agent 打开)
- <https://www.microsoft.com/software-download/windows11> - <https://www.microsoft.com/software-download/windows11>
- <https://www.microsoft.com/software-download/windows11arm64> - <https://www.microsoft.com/software-download/windows11arm64>
@ -350,8 +359,8 @@ bash reinstall.sh windows \
- <https://www.microsoft.com/evalcenter/download-windows-server-2022> - <https://www.microsoft.com/evalcenter/download-windows-server-2022>
- <https://www.microsoft.com/evalcenter/download-windows-server-2025> - <https://www.microsoft.com/evalcenter/download-windows-server-2025>
- Insider 预览版 - Insider 预览版
- <https://www.microsoft.com/software-download/windowsinsiderpreviewiso> - <https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewiso>
- <https://www.microsoft.com/software-download/windowsinsiderpreviewserver> - <https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewserver>
</details> </details>
@ -362,10 +371,9 @@ bash reinstall.sh windows \
- `--rdp-port PORT` 更改 RDP 端口 - `--rdp-port PORT` 更改 RDP 端口
- `--ssh-port PORT` 修改 SSH 端口(安装期间观察日志用) - `--ssh-port PORT` 修改 SSH 端口(安装期间观察日志用)
- `--web-port PORT` 修改 Web 端口(安装期间观察日志用) - `--web-port PORT` 修改 Web 端口(安装期间观察日志用)
- `--add-driver-dir DIR` 添加额外驱动,填写 .inf 所在的文件夹 - `--add-driver INF_OR_DIR` 添加额外驱动,填写 .inf 路径,或者 .inf 所在的文件夹
- 需先下载驱动到本地 - 需先下载驱动到本地
- 可多次设置该参数以添加不同的驱动文件夹 - 可多次设置该参数以添加不同的驱动
- 脚本将复制整个文件夹,因此文件夹内不要放置其他文件
- `--hold 2` 在进入 Windows 官方安装程序之前,可以 SSH 登录修改硬盘内容,硬盘挂载在 `/os` - `--hold 2` 在进入 Windows 官方安装程序之前,可以 SSH 登录修改硬盘内容,硬盘挂载在 `/os`
#### 以下驱动会自动按需下载安装,无需手动添加 #### 以下驱动会自动按需下载安装,无需手动添加

View File

@ -81,8 +81,15 @@ EOF
} }
info() { info() {
upper=$(to_upper <<<"$@") local msg
echo_color_text '\e[32m' "***** $upper *****" >&2 if [ "$1" = false ]; then
shift
msg=$*
else
msg=$(to_upper <<<"$@")
fi
echo_color_text '\e[32m' "***** $msg *****" >&2
} }
warn() { warn() {
@ -91,7 +98,7 @@ warn() {
error() { error() {
echo_color_text '\e[31m' "***** ERROR *****" >&2 echo_color_text '\e[31m' "***** ERROR *****" >&2
echo_color_text '\e[31m' "Error: $*" >&2 echo_color_text '\e[31m' "$*" >&2
} }
echo_color_text() { echo_color_text() {
@ -609,6 +616,12 @@ is_virt() {
$_is_virt $_is_virt
} }
is_absolute_path() {
# 检查路径是否以/开头
# 注意语法和 ash 不同
[[ "$1" = /* ]]
}
assert_cpu_supports_x86_64_v3() { assert_cpu_supports_x86_64_v3() {
# 用 ld.so/cpuid/coreinfo.exe 更准确 # 用 ld.so/cpuid/coreinfo.exe 更准确
# centos 7 /usr/lib64/ld-linux-x86-64.so.2 没有 --help # centos 7 /usr/lib64/ld-linux-x86-64.so.2 没有 --help
@ -2150,7 +2163,13 @@ del_empty_lines() {
sed '/^[[:space:]]*$/d' sed '/^[[:space:]]*$/d'
} }
trim() {
# sed -E -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//'
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
prompt_password() { prompt_password() {
info "prompt password"
while true; do while true; do
IFS= read -r -p "Password [$DEFAULT_PASSWORD]: " password IFS= read -r -p "Password [$DEFAULT_PASSWORD]: " password
IFS= read -r -p "Retype password [$DEFAULT_PASSWORD]: " password_confirm IFS= read -r -p "Retype password [$DEFAULT_PASSWORD]: " password_confirm
@ -3192,11 +3211,13 @@ EOF
# 6. debian 11 initrd 无法识别 set -E # 6. debian 11 initrd 无法识别 set -E
# 7. debian 11 initrd 无法识别 trap ERR # 7. debian 11 initrd 无法识别 trap ERR
# 8. debian 9 initrd 无法识别 ${string//find/replace} # 8. debian 9 initrd 无法识别 ${string//find/replace}
# 9. debian 12 initrd 无法识别 . <(
# 删除或注释,可能会导致空方法而报错,因此改为替换成'\n: #' # 删除或注释,可能会导致空方法而报错,因此改为替换成'\n: #'
replace='\n: #' replace='\n: #'
sed -Ei \ sed -Ei \
-e "s/> >/$replace/" \ -e "s/> >/$replace/" \
-e "s/< </$replace/" \ -e "s/< </$replace/" \
-e "s/\. <\(/$replace/" \
-e "s/^[[:space:]]*apk[[:space:]]/$replace/" \ -e "s/^[[:space:]]*apk[[:space:]]/$replace/" \
-e "s/^[[:space:]]*trap[[:space:]]/$replace/" \ -e "s/^[[:space:]]*trap[[:space:]]/$replace/" \
-e "s/\\$\{.*\/\/.*\/.*\}/$replace/" \ -e "s/\\$\{.*\/\/.*\/.*\}/$replace/" \
@ -3459,16 +3480,12 @@ This script is outdated, please download reinstall.sh again.
fi fi
# 添加自定义 windows 驱动 # 添加自定义 windows 驱动
if [ "$distro" = windows ]; then if [ "$distro" = windows ] && [ -n "$custom_infs" ]; then
mkdir -p $initrd_dir/custom_drivers # shellcheck disable=SC1090
i=0 . <(curl -L $confhome/windows-driver-utils.sh)
while IFS= read -r dir; do echo "$custom_infs" | while read -r inf; do
if [ -d "$dir" ]; then parse_inf_and_cp_driever "$inf" "$initrd_dir/custom_drivers" "$basearch_alt" true
((i += 1)) done
info "add custom driver: $dir"
cp -r "$dir" "$initrd_dir/custom_drivers/$i"
fi
done < <(echo "$custom_driver_dirs")
fi fi
# alpine live 不精简 initrd # alpine live 不精简 initrd
@ -3594,7 +3611,7 @@ fi
long_opts= long_opts=
for o in ci installer debug minimal allow-ping force-cn \ for o in ci installer debug minimal allow-ping force-cn \
add-driver-dir: \ add-driver: \
hold: sleep: \ hold: sleep: \
iso: \ iso: \
image-name: \ image-name: \
@ -3687,26 +3704,45 @@ while true; do
web_port=$2 web_port=$2
shift 2 shift 2
;; ;;
--add-driver-dir) --add-driver)
# 指定 dir 而不是指定 inf
# 防止用户将 inf 放在 / 而复制整个 /
# 路径转换 # 路径转换
if is_in_windows; then if is_in_windows; then
# 输入的路径是 / 开头也没问题 # 输入的路径是 / 开头也没问题
dir="$(cygpath -u "$2")" inf_or_dir="$(cygpath -u "$2")"
else else
dir=$2 inf_or_dir=$2
fi fi
# 防止重复添加 # alpine busybox 不支持 readlink -m
if ! grep -Fqx "$dir" <<<"$custom_driver_dirs"; then # readlink -m /asfsafasfsaf/fasf
# shellcheck disable=SC2010 # 因此需要先判断路径是否存在
{ [ -d "$dir" ] && ls "$dir" | grep -Eiq '\.inf$'; } || error_and_exit "Invalid Driver Directory: $2"
# 一行一个驱动文件夹 if ! [ -d "$inf_or_dir" ] &&
custom_driver_dirs+="$dir ! { [ -f "$inf_or_dir" ] && [[ "$inf_or_dir" =~ \.[iI][nN][fF]$ ]]; }; then
" error_and_exit "Not a inf or dir: $2"
fi fi
# 转为绝对路径
inf_or_dir=$(readlink -f "$inf_or_dir")
info "finding inf in $inf_or_dir"
# find /tmp -type f -iname '*.inf' 只要 /tmp 存在就会返回 0
if infs=$(find "$inf_or_dir" -type f -iname '*.inf' | grep .); then
while IFS= read -r inf; do
# 防止重复添加
if ! grep -Fqx "$inf" <<<"$custom_infs"; then
echo "inf found: $inf"
# 一行一个 inf
if [ -n "$custom_infs" ]; then
custom_infs+=$'\n'
fi
custom_infs+=$inf
fi
done <<<"$infs"
else
error_and_exit "Can't find inf files in $2"
fi
shift 2 shift 2
;; ;;
--force-old-windows-setup) --force-old-windows-setup)
@ -3760,7 +3796,7 @@ fi
# 密码 # 密码
if ! is_netboot_xyz && [ -z "$password" ]; then if ! is_netboot_xyz && [ -z "$password" ]; then
if is_use_dd || [ "$distro" = fnos ]; then if is_use_dd; then
echo " echo "
This password is only used for SSH access to view logs during the installation. This password is only used for SSH access to view logs during the installation.
Password of the image will NOT modify. Password of the image will NOT modify.
@ -4215,8 +4251,15 @@ elif is_alpine_live; then
elif is_use_dd; then elif is_use_dd; then
echo 'Reboot to start DD.' echo 'Reboot to start DD.'
elif [ "$distro" = fnos ]; then elif [ "$distro" = fnos ]; then
echo "Special note for FNOS:"
echo "Reboot to start the installation." echo "Reboot to start the installation."
echo "After install, you need to config the system on http://SERVER_IP:5666 as soon as possible." echo "SSH login is disabled when installation completed."
echo "You need to config the account and password on http://SERVER_IP:5666 as soon as possible."
echo
echo "飞牛 OS 注意事项:"
echo "重启后开始安装。"
echo "安装完成后不支持 SSH 登录。"
echo "你需要尽快在 http://SERVER_IP:5666 配置账号密码。"
else else
echo "Reboot to start the installation." echo "Reboot to start the installation."
fi fi

View File

@ -20,13 +20,28 @@ error() {
color='\e[31m' color='\e[31m'
plain='\e[0m' plain='\e[0m'
echo -e "${color}***** ERROR *****${plain}" >&2 echo -e "${color}***** ERROR *****${plain}" >&2
echo -e "${color}Error: $*${plain}" >&2 echo -e "${color}$*${plain}" >&2
} }
info() { info() {
color='\e[32m' color='\e[32m'
plain='\e[0m' plain='\e[0m'
echo -e "${color}***** $(echo "$*" | to_upper) *****${plain}" >&2 local msg
if [ "$1" = false ]; then
shift
msg=$*
else
msg=$(echo "$*" | to_upper)
fi
echo -e "${color}***** $msg *****${plain}" >&2
}
warn() {
color='\e[33m'
plain='\e[0m'
echo -e "${color}Warning: $*${plain}" >&2
} }
error_and_exit() { error_and_exit() {
@ -754,6 +769,10 @@ to_lower() {
tr '[:upper:]' '[:lower:]' tr '[:upper:]' '[:lower:]'
} }
del_cr() {
sed 's/\r//g'
}
del_empty_lines() { del_empty_lines() {
sed '/^[[:space:]]*$/d' sed '/^[[:space:]]*$/d'
} }
@ -3901,12 +3920,12 @@ install_fnos() {
# 更新 initrd # 更新 initrd
# chroot $os_dir update-initramfs -u # chroot $os_dir update-initramfs -u
# 删除自带的 root 密码 # 更改密码
# chroot $os_dir passwd -d root # chroot $os_dir passwd -d root
echo "root:$(get_password_linux_sha512)" | chroot $os_dir chpasswd -e
# ssh root 登录,测试用 # ssh root 登录,测试用
if false; then if false; then
echo "root:$(get_password_linux_sha512)" | chroot $os_dir chpasswd -e
allow_root_password_login $os_dir allow_root_password_login $os_dir
chroot $os_dir systemctl enable ssh chroot $os_dir systemctl enable ssh
fi fi
@ -4982,6 +5001,12 @@ get_filesize_mb() {
du -m "$1" | awk '{print $1}' du -m "$1" | awk '{print $1}'
} }
is_absolute_path() {
# 检查路径是否以/开头
# 注意语法和 bash 不同
[[ "$1" = "/*" ]]
}
install_windows() { install_windows() {
get_wim_prop() { get_wim_prop() {
wim=$1 wim=$1
@ -5190,7 +5215,7 @@ install_windows() {
# 变量名 使用场景 # 变量名 使用场景
# arch_uname arch命令 / uname -m x86_64 aarch64 # arch_uname arch命令 / uname -m x86_64 aarch64
# arch_wim wiminfo x86 x86_64 ARM64 # arch_wim wiminfo x86 x86_64 ARM64
# arch virtio iso / unattend.xml x86 amd64 arm64 # arch virtio iso / unattend.xml / .inf x86 amd64 arm64
# arch_xdd virtio msi / xen驱动 x86 x64 # arch_xdd virtio msi / xen驱动 x86 x64
# arch_dd 华为云驱动 32 64 # arch_dd 华为云驱动 32 64
@ -5219,6 +5244,10 @@ install_windows() {
drv=/os/drivers drv=/os/drivers
mkdir -p "$drv" # 驱动下载临时文件夹 mkdir -p "$drv" # 驱动下载临时文件夹
# 下载脚本
# shellcheck disable=SC1090
. <(wget -O- $confhome/windows-driver-utils.sh)
# 这里有坑 # 这里有坑
# $(get_cloud_vendor) 调用了 cache_dmi_and_virt # $(get_cloud_vendor) 调用了 cache_dmi_and_virt
# 但是 $(get_cloud_vendor) 运行在 subshell 里面 # 但是 $(get_cloud_vendor) 运行在 subshell 里面
@ -5647,13 +5676,10 @@ install_windows() {
# 因此只能交给用户自己添加驱动 # 因此只能交给用户自己添加驱动
add_driver_custom() { add_driver_custom() {
for dir in /custom_drivers/*; do if [ -d /custom_drivers/ ]; then
if [ -d "$dir" ]; then cp_drivers custom /custom_drivers/
info "Add custom drivers: $dir"
cp_drivers custom "$dir"
# 复制后不删除,因为脚本可能再次运行 # 复制后不删除,因为脚本可能再次运行
fi fi
done
} }
# 修改应答文件 # 修改应答文件
@ -5718,21 +5744,20 @@ install_windows() {
cp_drivers() { cp_drivers() {
if [ "$1" = custom ]; then if [ "$1" = custom ]; then
shift shift
dst="/wim/custom_drivers/$(basename "$1")" dst="/wim/custom_drivers"
else else
dst=/wim/drivers dst=/wim/drivers
fi fi
mkdir -p "$dst"
src=$1 src=$1
shift shift
find $src \ # -not -iname "*.pdb" \
-type f \ # -not -iname "dpinst.exe" \
-not -iname "*.pdb" \
-not -iname "dpinst.exe" \ find $src -type f -iname "*.inf" "$@" | while read -r inf; do
"$@" \ parse_inf_and_cp_driever "$inf" "$dst" "$arch" false
-exec cp -rfv {} "$dst" \; done
} }
# 添加驱动 # 添加驱动

278
windows-driver-utils.sh Normal file
View File

@ -0,0 +1,278 @@
#!/bin/ash
# shellcheck shell=dash
# shellcheck disable=SC3001,SC3010
# reinstall.sh / trans.sh 共用此文件
del_inf_comment() {
sed 's/;.*//'
}
simply_inf() {
del_cr | del_inf_comment | trim | del_empty_lines
}
simply_inf_word() {
# 1 删除引号 "
# 2 删除两边空格
# 3 \ 和 .\ 换成 /
# 4 连续的 / 替换成单个 /
# 5 删除最前面的 /
sed -E \
-e 's,",,g' \
-e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//' \
-e 's,\.?\\,/,g' \
-e 's,/+,/,g' \
-e 's,^/,,'
}
# reinstall.sh 下无法判断 iso 是 32 位还是 64 位,此时 mix_x86_x86_64 为 true
# trans.sh 下可以判断 iso 是 32 位还是 64 位,此时 mix_x86_x86_64 为 false
list_files_from_inf() {
local inf=$1
local arch=$2 # x86 amd64 arm64
local mix_x86_x86_64=$3
# 所有字段不区分大小写
inf_txts=$(simply_inf <"$inf" | to_lower)
is_match_section() {
local section=$1
[ "$line" = "[$section]" ] || [ "$line" = "[$section.$arch]" ] ||
{ $mix_x86_x86_64 && [ "$arch" = x86 ] && [ "$line" = "[$section.amd64]" ]; } ||
{ $mix_x86_x86_64 && [ "$arch" = amd64 ] && [ "$line" = "[$section.x86]" ]; }
}
is_match_catalogfile() {
local left
left=$(echo "$line" | awk -F= '{print $1}' | simply_inf_word)
# catalogfile.nt 是指所有 nt ?
[ "$left" = "catalogfile" ] ||
[ "$left" = "catalogfile.nt" ] ||
[ "$left" = "catalogfile.nt$arch" ] ||
{ $mix_x86_x86_64 && [ "$arch" = x86 ] && [ "$left" = "catalogfile.ntamd64" ]; } ||
{ $mix_x86_x86_64 && [ "$arch" = amd64 ] && [ "$left" = "catalogfile.ntx86" ]; }
}
is_match_manufacturer_arch() {
# x86 可写 NT / NTx86, 其它必须明确架构
# https://learn.microsoft.com/en-us/windows-hardware/drivers/install/inf-manufacturer-section
case "$arch" in
x86) $mix_x86_x86_64 && regex='NT|NTx86|NTamd64' || regex='NT|NTx86' ;;
amd64) $mix_x86_x86_64 && regex='NT|NTx86|NTamd64' || regex='NTamd64' ;;
arm64) regex='NTarm64' ;;
esac
# 注意 cut awk 结果不同
# 虽然在这里不会造成影响
# echo 1 | cut -d, -f2-
# 1
# echo 1 | awk -F, '{print $2}'
# 空白
echo "$line" | awk -F, '{for(i=2;i<=NF;i++) print $i}' | grep -Eiwq "$regex"
}
# 还需要从 [Strings] 读取字符串?
# 0. 检测 inf 是否适合当前架构
# 目前没有对比版本号
# 例子1
# [Manufacturer]
# %Amazon% = AWSNVME, NTamd64, NTARM64
# 例子2
# [Manufacturer]
# %MyName% = MyName,NTx86.6.0,NTx86.5.1,
# .
# [MyName.NTx86.6.0] ; Empty section, so this INF does not support
# . ; NT 6.0 and later.
# .
# [MyName.NTx86.5.1] ; Used for NT 5.1 and later
# . ; (but not NT 6.0 and later due to the NTx86.6.0 entry)
# %MyDev% = InstallB,hwid
# .
# [MyName] ; Empty section, so this INF does not support
# . ; Win2000
# .
# 例子3
# 系统自带的驱动,没有 [Manufacturer]
# 例子4
# C:\Windows\INF\wfcvsc.inf
# %StdMfg%=Standard,NTamd64...0x0000001,NTamd64...0x0000002,NTamd64...0x0000003
in_section=false
arch_matched=false
has_manufacturer=false
# 未添加 IFS= 时read 会删除行首行尾的空白字符
while read -r line; do
if [[ "$line" = "["* ]]; then
is_match_section manufacturer && has_manufacturer=true && in_section=true || in_section=false
continue
fi
if $in_section; then
if is_match_manufacturer_arch; then
arch_matched=true
break
fi
fi
done < <(echo "$inf_txts")
if $has_manufacturer && ! $arch_matched; then
return 10
fi
# 1. 输出 .inf 文件名
basename "$inf"
# 2. 输出 .cat 相对路径
# 例子
# [version]
# CatalogFile = "xxxxx.cat"
# CatalogFile.NTAMD64=Balloon.cat
in_section=false
# 未添加 IFS= 时read 会删除行首行尾的空白字符
while read -r line; do
if [[ "$line" = "["* ]]; then
is_match_section version && in_section=true || in_section=false
continue
fi
if $in_section && is_match_catalogfile; then
echo "$line" | awk -F= '{print $2}' | simply_inf_word
fi
done < <(echo "$inf_txts")
# 3. 获取 SourceDisksNames
# 例子
# [SourceDisksNames]
# 1 = "Windows NT CD-ROM",file.tag,, "\common"
SourceDisksNames=
in_section=false
# 未添加 IFS= 时read 会删除行首行尾的空白字符
while read -r line; do
if [[ "$line" = "["* ]]; then
is_match_section sourcedisksnames && in_section=true || in_section=false
continue
fi
# 注意可能有空格和引号
if $in_section; then
num=$(echo "$line" | awk -F= '{print $1}' | simply_inf_word)
dir=$(echo "$line" | awk -F, '{print $4}' | simply_inf_word)
# 每行一条记录
if [ -n "$SourceDisksNames" ]; then
SourceDisksNames="$SourceDisksNames
"
fi
SourceDisksNames="$SourceDisksNames$num:$dir"
fi
done < <(echo "$inf_txts")
# 4. 打印 SourceDisksFiles 的绝对路径
# 例子
# [SourceDisksFiles]
# aha154x.sys = 1 , "\x86" ,,
in_section=false
# 未添加 IFS= 时read 会删除行首行尾的空白字符
while read -r line; do
if [[ "$line" = "["* ]]; then
is_match_section sourcedisksfiles && in_section=true || in_section=false
continue
fi
if $in_section; then
file=$(echo "$line" | awk -F= '{print $1}' | simply_inf_word)
num=$(echo "$line" | awk -F'=|,' '{print $2}' | simply_inf_word)
sub_dir=$(echo "$line" | awk -F, '{print $2}' | simply_inf_word)
# 可能有多个
while IFS= read -r parent_dir; do
echo "$parent_dir/$sub_dir/$file" | simply_inf_word
done < <(echo "$SourceDisksNames" | awk -F: "\$1==\"$num\" {print \$2}")
fi
done < <(echo "$inf_txts")
}
find_file_ignore_case() {
# 同时支持参数和管道
local path
path=$({ if [ -n "$1" ]; then echo "$1"; else cat; fi; })
# 用 / 分割路径,提取成列表
# 例如: ///a///b/c.inf -> a b c.inf
# shellcheck disable=SC2046
set -- $(echo "$path" | grep -o '[^/]*')
(
# windows 安装驱动时,只会安装相同架构的驱动文件到系统,即使 inf 里有列出其它架构的驱动
# 因此导出驱动时,也就不会包含其它架构的驱动文件
# 因此这里只警告,不中断脚本
local output=
if is_absolute_path "$path"; then
cd /
output=/
fi
while [ $# -gt 0 ]; do
local part=$1
# shellcheck disable=SC2010
if part=$(ls -1 | grep -Fix "$part"); then
# 大于 1 表示当前 part 是目录
if [ $# -gt 1 ]; then
if cd "$part"; then
output="$output$part/"
else
warn "Can't cd $path"
return 1
fi
else
# 最后 part
output="$output$part"
fi
else
warn "Can't find $path" >&2
return 1
fi
shift
done
echo "$output"
)
}
parse_inf_and_cp_driever() {
local inf=$1
local dst=$2
local arch=$3
local mix_x86_x86_64=$4
info false "Add driver: $inf"
# 首先创建目录,否则无法通过 ls 文件数得到编号
mkdir -p "$dst"
# shellcheck disable=SC2012
inf_index=$(($(ls -1 "$dst" | wc -l) + 1))
inf_old_dir=$(dirname "$inf")
inf_new_dir=$dst/$inf_index
if driver_files=$(list_files_from_inf "$inf" "$arch" "$mix_x86_x86_64"); then
mkdir -p "$inf_new_dir"
(
cd "$inf_old_dir" || error_and_exit "Can't cd $inf_old_dir"
while read -r file; do
if file=$(find_file_ignore_case "$file"); then
cp -v --parents "$file" "$inf_new_dir"
fi
done < <(echo "$driver_files")
)
else
if [ $? -eq 10 ]; then
warn "$inf arch not match."
else
error_and_exit "Unknown error while parse $inf."
fi
fi
}

View File

@ -22,15 +22,26 @@ rem win8 pe 没有 powercfg
call powercfg /s 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 2>nul call powercfg /s 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 2>nul
rem 安装 SCSI 驱动 rem 安装 SCSI 驱动
for %%F in ("X:\drivers\*.inf") do ( if exist X:\drivers\ (
for /f "delims=" %%F in ('dir /s /b "X:\drivers\*.inf" 2^>nul') do (
call :drvload_if_scsi "%%~F" call :drvload_if_scsi "%%~F"
)
rem 官网写了可以安装但仅会加载关键驱动
rem Gcore 的 virtio-gpu 在安装时没有显示
rem 即使安装时加载了显卡驱动
rem 进入系统后才有显示
rem find /i "viogpudo" "%%~F" >nul
rem if not errorlevel 1 (
rem drvload "%%~F"
rem )
) )
rem 安装自定义 SCSI 驱动 rem 安装自定义 SCSI 驱动
rem 可以用 forfiles /p X:\custom_drivers /m *.inf /c "cmd /c echo @path" rem 可以用 forfiles /p X:\custom_drivers /m *.inf /c "cmd /c echo @path"
rem 不可以用 for %%F in ("X:\custom_drivers\*\*.inf") rem 不可以用 for %%F in ("X:\custom_drivers\*\*.inf")
if exist X:\custom_drivers\ ( if exist X:\custom_drivers\ (
for /f "delims=" %%F in ('dir /s /b "X:\custom_drivers\*.inf"') do ( for /f "delims=" %%F in ('dir /s /b "X:\custom_drivers\*.inf" 2^>nul') do (
call :drvload_if_scsi "%%~F" call :drvload_if_scsi "%%~F"
) )
) )