Skip to content

Commit 25237c9

Browse files
committed
Add Fedora 43
0 parents  commit 25237c9

4 files changed

Lines changed: 374 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Build Fedora QCOW2
2+
3+
on:
4+
push:
5+
paths:
6+
- 'Fedora.json' # 只有当 Fedora.json 文件被修改时触发
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
# Step 1: 检出代码
14+
- name: Checkout repository
15+
uses: actions/checkout@v3
16+
17+
# Step 2: 解析 Fedora.json 文件
18+
- name: Parse Fedora.json
19+
id: parse-fedora-json
20+
run: |
21+
# 使用 jq 解析 JSON 文件
22+
NAME=$(jq -r '.name' Fedora.json)
23+
VERSION=$(jq -r '.version' Fedora.json)
24+
URL=$(jq -r '.url' Fedora.json)
25+
26+
# 设置环境变量
27+
echo "NAME=$NAME" >> $GITHUB_ENV
28+
echo "VERSION=$VERSION" >> $GITHUB_ENV
29+
echo "DOWNLOAD_URL=$URL" >> $GITHUB_ENV
30+
31+
# Step 3: 下载 .raw.xz 文件
32+
- name: Download Fedora raw.xz file
33+
run: |
34+
mkdir -p input
35+
wget -O input/source.raw.xz "${{ env.DOWNLOAD_URL }}"
36+
37+
# Step 4: 安装依赖工具
38+
- name: Install dependencies
39+
run: |
40+
sudo apt-get update -qq
41+
sudo apt-get install -y qemu-utils e2fsprogs util-linux xz-utils rsync jq
42+
43+
# Step 5: 转换为 qcow2 文件
44+
- name: Convert to qcow2
45+
run: |
46+
mkdir -p output
47+
TARGET_FILE="output/hish-${{ env.NAME }}-${{ env.VERSION }}.qcow2"
48+
sudo ./convert.fedora.sh input/source.raw.xz "$TARGET_FILE"
49+
50+
# Step 6: 上传生成的 qcow2 文件到 Release
51+
- name: Create Release and upload artifact
52+
uses: softprops/action-gh-release@v1
53+
with:
54+
tag_name: "hish-${{ env.NAME }}-${{ env.VERSION }}"
55+
name: "hish-${{ env.NAME }}-${{ env.VERSION }}"
56+
files: output/hish-${{ env.NAME }}-${{ env.VERSION }}.qcow2
57+
env:
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Fedora.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "Fedora",
3+
"version": "43-1.6",
4+
"url": "https://download.fedoraproject.org/pub/fedora/linux/releases/43/Spins/aarch64/images/Fedora-Minimal-43-1.6.aarch64.raw.xz"
5+
}

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# HiSH Linux Image
2+
3+
用于生成 [HiSH](https://github.com/harmoninux/HiSH) 支持的 Linux 镜像。HiSH 是一个运行在 HarmonyOS 上的 Linux 模拟器。
4+
5+
## 工作原理
6+
7+
本仓库通过 GitHub Actions 自动将官方 Linux 发行版的原始镜像转换为 HiSH 可用的 qcow2 格式镜像,并发布为 GitHub Release。
8+
9+
### 转换流程
10+
11+
1. 下载官方 `.raw.xz` 格式的镜像
12+
2. 解压并挂载原始镜像的根分区
13+
3. 创建 120G 的 qcow2 镜像并格式化为 ext4
14+
4. 将根文件系统内容复制到新镜像
15+
5. 创建 `/init``/sbin/init` 的符号链接(HiSH 启动需要)
16+
6. 禁用内核更新(避免更新后无法启动)
17+
7. 压缩输出最终的 qcow2 镜像
18+
19+
## 支持的发行版
20+
21+
| 发行版 | 配置文件 | 说明 |
22+
|--------|----------|------|
23+
| Fedora Minimal | `Fedora.json` | Fedora 最小化安装 |
24+
25+
## 使用方法
26+
27+
### 下载镜像
28+
29+
前往 [Releases](../../releases) 页面下载所需的 qcow2 镜像文件,然后在 HiSH 中导入即可使用。
30+
31+
### 触发构建
32+
33+
修改对应发行版的 JSON 配置文件(如 `Fedora.json`)并推送到仓库,即可自动触发 GitHub Actions 构建新的镜像。
34+
35+
`Fedora.json` 为例:
36+
37+
```json
38+
{
39+
"name": "Fedora-Minimal",
40+
"version": "43-1.6",
41+
"url": "https://download.fedoraproject.org/pub/fedora/linux/releases/43/Spins/aarch64/images/Fedora-Minimal-43-1.6.aarch64.raw.xz"
42+
}
43+
```
44+
45+
| 字段 | 说明 |
46+
|------|------|
47+
| `name` | 发行版名称 |
48+
| `version` | 版本号 |
49+
| `url` | 官方 aarch64 原始镜像下载地址 |
50+
51+
### 本地构建
52+
53+
如果需要本地构建镜像,可以运行转换脚本:
54+
55+
```bash
56+
sudo ./convert.fedora.sh <source.raw.xz> <output.qcow2>
57+
```
58+
59+
**依赖:** `qemu-utils``e2fsprogs``mount``util-linux``xz-utils``rsync`
60+
61+
> **注意:** 脚本必须以 root 权限运行。
62+
63+
## 相关项目
64+
65+
- [HiSH](https://github.com/harmoninux/HiSH) - HarmonyOS 上的 Linux 模拟器

convert.fedora.sh

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#!/bin/bash
2+
3+
# 检查参数数量
4+
if [ "$#" -ne 2 ]; then
5+
echo "Usage: $0 <source.raw.xz> <target.qcow2>"
6+
exit 1
7+
fi
8+
9+
SOURCE=$1
10+
TARGET=$2
11+
RAW_FILE="temp.raw"
12+
QCOW2_FILE="temp.qcow2"
13+
MOUNT_DIR="mnt"
14+
SOURCE_MOUNT_DIR="mnt_source"
15+
NBD_DEVICE="/dev/nbd0"
16+
LOOP_DEVICE=""
17+
PARTITION_LOOP_DEVICE=""
18+
19+
# 检查是否以 root 用户运行
20+
if [ "$(id -u)" -ne 0 ]; then
21+
echo "Error: This script must be run as root."
22+
exit 1
23+
fi
24+
25+
# 定义依赖包列表
26+
DEPENDENCIES=("qemu-utils" "e2fsprogs" "mount" "util-linux" "xz-utils" "rsync")
27+
28+
# 安装所有依赖项
29+
echo "Installing required dependencies..."
30+
apt-get update -qq
31+
apt-get install -y "${DEPENDENCIES[@]}"
32+
if [ $? -ne 0 ]; then
33+
echo "Failed to install required dependencies. Exiting..."
34+
exit 1
35+
fi
36+
37+
# 检查 source 文件是否存在
38+
if [ ! -f "$SOURCE" ]; then
39+
echo "Error: Source file $SOURCE does not exist."
40+
exit 1
41+
fi
42+
43+
# 创建临时目录
44+
mkdir -p "$MOUNT_DIR"
45+
mkdir -p "$SOURCE_MOUNT_DIR"
46+
47+
# Step 1: 解压 .raw.xz 文件为 .raw
48+
echo "Decompressing .raw.xz to .raw..."
49+
xz -d -k "$SOURCE" -c > "$RAW_FILE"
50+
if [ $? -ne 0 ]; then
51+
echo "Failed to decompress .raw.xz file."
52+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
53+
exit 1
54+
fi
55+
56+
# Step 2: 使用 losetup 挂载 .raw 文件为块设备
57+
echo "Attaching .raw file to loop device..."
58+
LOOP_DEVICE=$(losetup -f)
59+
losetup "$LOOP_DEVICE" "$RAW_FILE"
60+
if [ $? -ne 0 ]; then
61+
echo "Failed to attach .raw file to loop device."
62+
rm -f "$RAW_FILE"
63+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
64+
exit 1
65+
fi
66+
67+
# Step 3: 获取第三个分区的起始扇区和大小
68+
echo "Reading partition table..."
69+
PART_INFO=$(fdisk -l "$LOOP_DEVICE" | grep "^${LOOP_DEVICE}p")
70+
if [ $? -ne 0 ]; then
71+
echo "Failed to read partition table."
72+
losetup -d "$LOOP_DEVICE"
73+
rm -f "$RAW_FILE"
74+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
75+
exit 1
76+
fi
77+
78+
# 提取第三个分区的信息
79+
PART_START=$(echo "$PART_INFO" | awk 'NR==3 {print $2}')
80+
PART_SIZE=$(echo "$PART_INFO" | awk 'NR==3 {print $4}')
81+
if [ -z "$PART_START" ] || [ -z "$PART_SIZE" ]; then
82+
echo "Failed to extract partition information for the third partition."
83+
losetup -d "$LOOP_DEVICE"
84+
rm -f "$RAW_FILE"
85+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
86+
exit 1
87+
fi
88+
89+
# Step 4: 使用 losetup 挂载第三个分区
90+
echo "Attaching third partition to loop device..."
91+
PARTITION_LOOP_DEVICE=$(losetup -f)
92+
losetup -o $((PART_START * 512)) --sizelimit $((PART_SIZE * 512)) "$PARTITION_LOOP_DEVICE" "$LOOP_DEVICE"
93+
if [ $? -ne 0 ]; then
94+
echo "Failed to attach third partition to loop device."
95+
losetup -d "$LOOP_DEVICE"
96+
rm -f "$RAW_FILE"
97+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
98+
exit 1
99+
fi
100+
101+
# Step 5: 创建一个 120G 的 qcow2 文件
102+
echo "Creating a 120G qcow2 file..."
103+
qemu-img create -f qcow2 "$QCOW2_FILE" 120G
104+
if [ $? -ne 0 ]; then
105+
echo "Failed to create qcow2 file."
106+
losetup -d "$LOOP_DEVICE"
107+
losetup -d "$PARTITION_LOOP_DEVICE"
108+
rm -f "$RAW_FILE"
109+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
110+
exit 1
111+
fi
112+
113+
# Step 6: 使用 nbd 挂载 qcow2 文件
114+
echo "Attaching qcow2 file to NBD device..."
115+
modprobe nbd max_part=8
116+
qemu-nbd -c "$NBD_DEVICE" "$QCOW2_FILE"
117+
if [ $? -ne 0 ]; then
118+
echo "Failed to attach qcow2 file to NBD device."
119+
losetup -d "$LOOP_DEVICE"
120+
losetup -d "$PARTITION_LOOP_DEVICE"
121+
rm -f "$RAW_FILE" "$QCOW2_FILE"
122+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
123+
exit 1
124+
fi
125+
126+
# 等待设备就绪
127+
sleep 5
128+
129+
# Step 7: 格式化 nbd 分区为 ext4
130+
echo "Formatting NBD partition with ext4..."
131+
mkfs.ext4 "$NBD_DEVICE"
132+
if [ $? -ne 0 ]; then
133+
echo "Failed to format NBD partition."
134+
qemu-nbd -d "$NBD_DEVICE"
135+
losetup -d "$LOOP_DEVICE"
136+
losetup -d "$PARTITION_LOOP_DEVICE"
137+
rm -f "$RAW_FILE" "$QCOW2_FILE"
138+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
139+
exit 1
140+
fi
141+
142+
# Step 8: 挂载分区
143+
echo "Mounting NBD partition..."
144+
mount "$NBD_DEVICE" "$MOUNT_DIR"
145+
if [ $? -ne 0 ]; then
146+
echo "Failed to mount NBD partition."
147+
qemu-nbd -d "$NBD_DEVICE"
148+
losetup -d "$LOOP_DEVICE"
149+
losetup -d "$PARTITION_LOOP_DEVICE"
150+
rm -f "$RAW_FILE" "$QCOW2_FILE"
151+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
152+
exit 1
153+
fi
154+
155+
# Step 9: 挂载第三个分区
156+
echo "Mounting third partition..."
157+
mount "$PARTITION_LOOP_DEVICE" "$SOURCE_MOUNT_DIR"
158+
if [ $? -ne 0 ]; then
159+
echo "Failed to mount third partition."
160+
umount "$MOUNT_DIR"
161+
qemu-nbd -d "$NBD_DEVICE"
162+
losetup -d "$LOOP_DEVICE"
163+
losetup -d "$PARTITION_LOOP_DEVICE"
164+
rm -f "$RAW_FILE" "$QCOW2_FILE"
165+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
166+
exit 1
167+
fi
168+
169+
# Step 10: 将第三个分区的内容复制到目标分区
170+
echo "Copying data from third partition to mounted directory..."
171+
rsync -a --info=progress2 "$SOURCE_MOUNT_DIR/" "$MOUNT_DIR/"
172+
if [ $? -ne 0 ]; then
173+
echo "Failed to copy data from third partition."
174+
umount "$SOURCE_MOUNT_DIR"
175+
umount "$MOUNT_DIR"
176+
qemu-nbd -d "$NBD_DEVICE"
177+
losetup -d "$LOOP_DEVICE"
178+
losetup -d "$PARTITION_LOOP_DEVICE"
179+
rm -f "$RAW_FILE" "$QCOW2_FILE"
180+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
181+
exit 1
182+
fi
183+
184+
umount "$SOURCE_MOUNT_DIR"
185+
186+
# Step 11: 创建 /sbin/init 到 /init 的相对路径软链接
187+
echo "Creating relative symbolic link sbin/init -> init..."
188+
cd "$MOUNT_DIR" || { echo "Failed to change directory to $MOUNT_DIR"; exit 1; }
189+
ln -srf "sbin/init" "init"
190+
if [ $? -ne 0 ]; then
191+
echo "Failed to create relative symbolic link sbin/init -> init."
192+
cd -
193+
umount "$MOUNT_DIR"
194+
qemu-nbd -d "$NBD_DEVICE"
195+
losetup -d "$LOOP_DEVICE"
196+
losetop -d "$PARTITION_LOOP_DEVICE"
197+
rm -f "$RAW_FILE" "$QCOW2_FILE"
198+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
199+
exit 1
200+
fi
201+
cd -
202+
203+
# Step 12: 禁用 kernel 和 kernel-core 的更新
204+
echo "Disabling kernel updates in DNF configuration..."
205+
DNF_CONF="$MOUNT_DIR/etc/dnf/dnf.conf"
206+
if [ -f "$DNF_CONF" ]; then
207+
# 添加 exclude 规则
208+
echo "exclude=kernel* kernel-core*" >> "$DNF_CONF"
209+
if [ $? -ne 0 ]; then
210+
echo "Failed to update DNF configuration."
211+
umount "$MOUNT_DIR"
212+
qemu-nbd -d "$NBD_DEVICE"
213+
losetup -d "$LOOP_DEVICE"
214+
losetup -d "$PARTITION_LOOP_DEVICE"
215+
rm -f "$RAW_FILE" "$QCOW2_FILE"
216+
rm -rf "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
217+
exit 1
218+
fi
219+
else
220+
echo "Warning: DNF configuration file not found at $DNF_CONF. Skipping kernel update disable."
221+
fi
222+
223+
# Step 13: 卸载分区并断开 nbd 和 loop 连接
224+
echo "Unmounting and detaching devices..."
225+
umount "$MOUNT_DIR"
226+
qemu-nbd -d "$NBD_DEVICE"
227+
losetup -d "$LOOP_DEVICE"
228+
losetup -d "$PARTITION_LOOP_DEVICE"
229+
if [ $? -ne 0 ]; then
230+
echo "Failed to detach devices."
231+
exit 1
232+
fi
233+
234+
# Step 14: 使用 qemu-img convert 压缩 qcow2 文件为目标文件
235+
echo "Compressing qcow2 file using qemu-img convert..."
236+
qemu-img convert -O qcow2 -c "$QCOW2_FILE" "$TARGET"
237+
if [ $? -ne 0 ]; then
238+
echo "Failed to compress qcow2 file."
239+
exit 1
240+
fi
241+
242+
# 清理临时文件
243+
echo "Cleaning up temporary files..."
244+
rm -rf "$RAW_FILE" "$QCOW2_FILE" "$MOUNT_DIR" "$SOURCE_MOUNT_DIR"
245+
246+
echo "Conversion completed successfully. Target file: $TARGET"

0 commit comments

Comments
 (0)