Skip to content

fix: azure 缺少磁盘驱动#153

Open
cha0sCat wants to merge 2 commits intobohanwood:masterfrom
cha0sCat:fix-azure
Open

fix: azure 缺少磁盘驱动#153
cha0sCat wants to merge 2 commits intobohanwood:masterfrom
cha0sCat:fix-azure

Conversation

@cha0sCat
Copy link
Copy Markdown
Contributor

@cha0sCat cha0sCat commented Mar 18, 2026

新增可选参数 --hyperv-pci-hotfix,用于处理 Azure NVMe / Hyper-V vPCI 场景下 installer 无法识别系统盘的问题。

开启后会在生成 installer 时,提前下载与 installer 内核匹配的 Debian kernel 包,并将该包写入 installer initrd。
同时写入一个 installer 启动早期执行的 startup hook,在 installer 环境内本地解包该 kernel 包,提取并加载 pci-hyperv.ko

理论上讲没有副作用,就算不是 azure/不需要这个驱动,也可以使用这个 arg

关联 issue #143

@cha0sCat cha0sCat force-pushed the fix-azure branch 3 times, most recently from db5f3cc to 29bcc29 Compare March 18, 2026 10:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 为 debi.sh 增加了一个可选热修复开关,用于在 Azure NVMe / Hyper-V vPCI 场景下,让 Debian installer 在早期加载 pci-hyperv.ko 以解决安装器无法识别系统盘的问题(关联 #143)。

Changes:

  • 新增 --hyperv-pci-hotfix 参数:生成 installer 时下载与 installer 内核匹配的 Debian kernel 包并注入 initrd,同时写入 installer startup hook 以加载 pci-hyperv.ko
  • 更新 README(英文/中文/日文)补充新参数说明与 Azure 场景示例。

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
debi.sh 增加 hotfix 注入逻辑与命令行参数开关,并在生成 initrd 时按需注入启动 hook 与 kernel 包。
README.md 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例。
README.zh-CN.md 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例,并清理末尾多余字符。
README.ja-JP.md 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +182 to +186
tmpdir=\$(mktemp -d /tmp/debi-hv-pci.XXXXXX) || exit 0
data_member=\$(ar t "\$package_path" 2> /dev/null | awk '/^data\\.tar\\./ { print; exit }')
ar p "\$package_path" "\$data_member" > "\$tmpdir/\$data_member" 2> /dev/null || exit 0
mkdir -p "\$tmpdir/extract" "\$(dirname "\$module_path")"
xzcat "\$tmpdir/\$data_member" | tar -xf - -C "\$tmpdir/extract" "./lib/modules/\$kernel_version/kernel/drivers/pci/controller/pci-hyperv.ko" 2> /dev/null || exit 0
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the installer startup hook, data_member is matched as data.tar.* but the extraction always uses xzcat. If the .deb uses data.tar.zst or data.tar.gz, the hotfix will silently do nothing. Consider detecting the data_member suffix and using the matching decompressor (xz/gz/zstd), or constrain the match to data.tar.xz and error clearly otherwise.

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +168
cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF
#!/bin/sh
set -eu

kernel_version=$installer_kernel_version
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

installer_kernel_version comes from the downloaded initrd contents and is interpolated directly into the generated /lib/debian-installer-startup.d/... shell script without quoting/sanitization. If it contains unexpected characters, this can break the hook or (with a malicious initrd/mirror) lead to shell injection. Please validate it against an allowlist (e.g. [A-Za-z0-9.+-]) and/or write it as a safely quoted shell literal in the heredoc.

Suggested change
cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF
#!/bin/sh
set -eu
kernel_version=$installer_kernel_version
case ${installer_kernel_version-} in
''|*[!A-Za-z0-9.+-]*)
err "Invalid installer kernel version: ${installer_kernel_version-}"
;;
esac
cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF
#!/bin/sh
set -eu
kernel_version='${installer_kernel_version}'

Copilot uses AI. Check for mistakes.
[ -n "$installer_kernel_version" ] ||
err "Could not determine the installer kernel version from $initrd_file"

tmpdir=$(mktemp -d)
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inject_hyperv_pci_hotfix creates a temp directory but relies on manual rm -rf calls. With set -e enabled, any failing command (e.g. a download error) will exit the script and leave $tmpdir behind. Add a trap after mktemp -d to ensure the temp directory is always cleaned up on EXIT/INT/TERM.

Suggested change
tmpdir=$(mktemp -d)
tmpdir=$(mktemp -d)
trap "rm -rf \"$tmpdir\"" EXIT INT TERM

Copilot uses AI. Check for mistakes.
Comment on lines +93 to +130
local package_name filename

package_name="linux-image-$1"
filename=$(
gzip -dc "$2" | awk -v pkg="$package_name" '
BEGIN { RS = ""; FS = "\n" }
$1 == "Package: " pkg {
for (i = 1; i <= NF; i++) {
if ($i ~ /^Filename: /) {
sub(/^Filename: /, "", $i)
print $i
exit
}
}
}
'
)
[ -n "$filename" ] && {
printf '%s\n' "$filename"
return 0
}

package_name="linux-image-$1-unsigned"
filename=$(
gzip -dc "$2" | awk -v pkg="$package_name" '
BEGIN { RS = ""; FS = "\n" }
$1 == "Package: " pkg {
for (i = 1; i <= NF; i++) {
if ($i ~ /^Filename: /) {
sub(/^Filename: /, "", $i)
print $i
exit
}
}
}
'
)
[ -n "$filename" ] && printf '%s\n' "$filename"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find_kernel_package runs the same gzip|awk scan twice (for signed and unsigned). This can be simplified by iterating over candidate package names in a loop and reusing the same extraction logic, which will make the function easier to maintain and slightly reduce work on large Packages.gz files.

Suggested change
local package_name filename
package_name="linux-image-$1"
filename=$(
gzip -dc "$2" | awk -v pkg="$package_name" '
BEGIN { RS = ""; FS = "\n" }
$1 == "Package: " pkg {
for (i = 1; i <= NF; i++) {
if ($i ~ /^Filename: /) {
sub(/^Filename: /, "", $i)
print $i
exit
}
}
}
'
)
[ -n "$filename" ] && {
printf '%s\n' "$filename"
return 0
}
package_name="linux-image-$1-unsigned"
filename=$(
gzip -dc "$2" | awk -v pkg="$package_name" '
BEGIN { RS = ""; FS = "\n" }
$1 == "Package: " pkg {
for (i = 1; i <= NF; i++) {
if ($i ~ /^Filename: /) {
sub(/^Filename: /, "", $i)
print $i
exit
}
}
}
'
)
[ -n "$filename" ] && printf '%s\n' "$filename"
local package_base package_name filename
package_base="linux-image-$1"
for suffix in "" "-unsigned"; do
package_name="${package_base}${suffix}"
filename=$(
gzip -dc "$2" | awk -v pkg="$package_name" '
BEGIN { RS = ""; FS = "\n" }
$1 == "Package: " pkg {
for (i = 1; i <= NF; i++) {
if ($i ~ /^Filename: /) {
sub(/^Filename: /, "", $i)
print $i
exit
}
}
}
'
)
if [ -n "$filename" ]; then
printf '%s\n' "$filename"
return 0
fi
done

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@cha0sCat
Copy link
Copy Markdown
Contributor Author

cha0sCat commented Mar 27, 2026

补丁时机踩过的坑

1. 安装前(未重启)做全程

  • 工具不保证齐全,环境不一致
  • 示例:Azure Debian 13 缺少 ar

2. Installer 内做全程

  • preseed/early_command

    • 网络未就绪 → 无法下载
  • partman/early_command

    • 磁盘已加载 → 已错过补丁时机
  • 补丁必须在磁盘加载前应用


最终方案

  • 当前系统:下载
  • Installer:解压 + 应用

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants