基于Ubuntu_amd64平台定制Ubuntu20_04_arm64_iso

本文详细描述了如何在PC机虚拟机上定制一个能在arm64平台上安装的Ubuntu20操作系统iso。
大致过程分三步,
第一步基于目标板编译出对应的内核镜像包。
第二步用第一步编译出来内核镜像包替换官方发布的ubuntu-20.04.3-live-server-arm64.iso中的内核镜像包
第三步将替换了内核镜像包的ubuntu-20.04.3-live-server-arm64_customize.iso拷贝到U盘,通过目标板端的BIOS引导U盘启动安装。

内核镜像包制作

内核源码打包

从linux kernel官网下载5.4.96内核包,下载网址:linux-5.4.96.tar.gz

内核编译

针对目标板编译出内核镜像,这不是本章节重点,这里不叙述详细过程。
编译得到:

1
2
1. linux-headers-5.4.96_arm64.deb //Linux头文件
2. linux-image-5.4.96_arm64.deb //Linux内核镜像

ISO定制

准备工作

  1. 从ubuntu官网下载原始ISO:ubuntu-20.04.3-live-server-arm64.iso
  2. 已制作好的5.4.96内核镜像包:
    1
    2
    linux-headers-5.4.96_arm64.deb //Linux头文件
    linux-image-5.4.96_arm64.deb //Linux内核镜像
  3. 获取net-tools_1.60+git20161116.90da8a0-1ubuntu1_arm64.deb包。

ISO定制交叉环境构建

如果是基于ARM服务器那么跳过这个交叉环境构建步骤;如果是x86服务器则需要构建一个模拟器来构建镜像定制交叉环境;可以通过docker或者qemu模拟器方式构建;本文通过qemu构建交叉环境;

准备工作

准备具有root权限的arm服务器或者基于x86服务器创建一个ARM虚拟机

安装qemu

1
sudo apt install -y qemu-system-arm

安装aarch64架构的系统

下载aarch64对应的UEFI固件QEMU_EFI.fd

创建虚拟机工作目录

1
mkdir qemu_system //虚拟机启动所需文件都放在该目录下;

将QEMU_EFI.fd拷贝到qemu_system目录下

下载虚拟机操作系统

ubuntu-18.04-server-arm64.iso,这个操作系统是运行在QEMU虚拟机上的arm64操作系统。要定制arm64的Ubuntu ISO,就需要在arm64环境下制作,运行在PC上的VM虚拟机只能安装amd64的Ubuntu版本。

创建虚拟硬盘

利用qemu-img指令可以创建1个空的虚拟硬盘,便于后面安装的时候将系统安装到虚拟硬盘上;在qemu_system目录下执行如下指令:

1
xxx@szxphisprb03543:~/pc/emei/ubuntu/qemu_system$qemu-img create ubuntuimg.img 40G

基于QEMU创建arm64虚拟机

  1. 在qemu_system目录下执行如下命令:
    1
    qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.fd -nographic -drive if=none,file=ubuntu-18.04-server-arm64.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom -drive if=none,file=ubuntuimg.img,id=hd0 -device virtio-blk-device,drive=hd0
  2. 执行上述命令后,会出现安装界面,直接回车选择安装Ubuntu Server,装完成后就可以看到提示登录的命令了。
  3. 编写虚拟机启动脚本,方便下次启动虚拟机,在qemu_system目录下新建run.sh文件,编写run.sh内容如下:
    1
    qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.fd -nographic  -device virtio-scsi-device -drive if=none,file=ubuntuimg.img,format=raw,index=0,id=hd0 -device virtio-blk-device,drive=hd0 -net nic -net user

创建root用户

1
sudo passwd root

退出虚拟机

1
sudo poweroff

启动已安装的虚拟机

在qemu_system目录下执行./run.sh

虚拟机和宿主机文件拷贝

可以使用scp协议复制文件,主机(host)下的默认IP:10.0.2.2,其中username就是在宿主机的用户名:

1
2
宿主机->虚拟机的文件传输:执行 scp username@10.0.2.2:xxx ./
虚拟机->宿主机的文件传输:执行 scp -r ./yyy username@10.0.2.2:/home/user/zzz

安装必要的工具

虚拟机的/etc/apt/source.list内容为对应正确的资源服务器,海思内部服务器参考脚本附件;

1
2
3
apt-get update
apt-get install liblz4-tool
apt install genisoimage

ISO定制步骤

  1. 服务器创建一个目录(此处是ubuntu_live),并将ubuntu-20.04.3-live-server-arm64.iso放入
    1
    2
    root@kwephicprd24193:~/ubuntu_live# ls 
    ubuntu-20.04.3-live-server-arm64.iso
  2. 创建一个mnt目录,用于挂载iso。
    1
    2
    root@kwephicprd24193:~/ubuntu_live# mkdir mnt
    root@kwephicprd24193:~/ubuntu_live# mount -o loop ubuntu-20.04.3-live-server-arm64.iso mnt
  3. 创建extract-cd目录,将iso内容提取到该目录,后续用于定制后重新打包。
    1
    2
    root@kwephicprd24193:~/ubuntu_live# mkdir extract-cd
    root@kwephicprd24193:~/ubuntu_live# rsync --exclude=/casper/filesystem.squashfs -a mnt/ extract-cd
  4. 解压filesystem.squashfs文件系统,生成squashfs-root目录。
    1
    root@kwephicprd24193:~/ubuntu_live# unsquashfs mnt/casper/filesystem.squashfs
  5. 将制作好的5.4.96内核包和所有用户态deb包拷贝到home目录下。这里需要说明下,如果不联网安装,需要把net-tools_1.60+git20161116.90da8a0-1ubuntu1_arm64.deb工具一并拷贝到home目录下,便于系统安装完成后配置ip。
    1
    root@kwephicprd24193:~/ubuntu_live# cp [user_path]/*deb squashfs-root/home/
  6. chroot到文件系统目录进行定制。
    1
    root@kwephicprd24193:~/ubuntu_live# chroot squashfs-root/
  7. 挂载相关目录(注意后面要卸载)
    1
    2
    3
    mount -t proc none /proc
    mount -t sysfs none /sys
    mount -t devpts none /dev/pts
  8. 为了避免区域问题以及导入 GPG keys,配置如下环境变量。
    1
    2
    export HOME=/root
    export LC_ALL=C
  9. 安装home下所有deb包
    1
    2
    dpkg -i /home/*.deb
    ubuntu20.04.3安装5.4.96内核包过程中更新initrd会有cryptsetup报错,这个可以先忽略。
  10. 修改initrd压缩格式为lzma
    1
    2
    3
    vi /etc/initramfs-tools/initramfs.conf
    修改COMPRESS=lzma
    说明:后面initrd需进行定制,重新打包成lz4不可用,因此改成lzma。
  11. 删除home所有deb包。
    1
    2
    3
    4
    5
    rm /home/*.deb
    修改ko_load.conf 在soc_vou 前面增加 uapi_panel
    vi /usr/lib/modules-load.d/ko_load.conf
    uapi_panel
    soc_vou
  12. 清理环境并退出chroot,依次执行如下命令:
    1
    2
    3
    4
    5
    6
    7
    8
    apt-get clean
    rm -rf /tmp/* ~/.bash_history
    umount /proc
    umount /sys
    umount /dev/pts
    export HISTSIZE=0
    exit
    umount mnt
  13. 制作EFI
    1
    2
    3
    root@kwephicprd24193:~/ubuntu_live# mount -o loop extract-cd/boot/grub/efi.img mnt
    root@kwephicprd24193:~/ubuntu_live# cp mnt/efi extract-cd/ -rf
    root@kwephicprd24193:~/ubuntu_live# umount mnt
  14. 替换内核
    1
    root@kwephicprd24193:~/ubuntu_live# cp squashfs-root/boot/vmlinuz-5.4.96-pangum900+ extract-cd/casper/vmlinuz
  15. 制作并替换initrd
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    系统原始的initrd目录为extract-cd/casper/initrd,其格式为lz4格式,因此先使用lz4解压(服务器需安装liblz4-tool):
    新建目录:
    解压后的initrd_new为cpio格式,进一步解压(注意创建一个目录将initrd_new放进去,因为会解压到当前目录)
    mkdir initrd
    cp extract-cd/casper/initrd ./initrd/
    cd ./initrd
    lz4 -d initrd initrd_new
    mkdir -p initrd_bak
    cp initrd_new initrd_bak/
    cd initrd_bak/
    cpio -i < initrd_new
    rm -rf initrd_new
    cd ../..
    同理将squashfs-root/boot/initrd.img-5.4.96-pangum900+解压(该文件生成时COMPRESS还没改成lzma,因此还是lz4格式)。
    cp squashfs-root/boot/initrd.img-5.4.96-pangum900+ ./initrd/
    cd ./initrd
    lz4 -d initrd.img-5.4.96-pangum900+ initrd.img-5.4.96-pangum900+_new //lz4 压缩
    mkdir -p initrd_pg_bak
    mv initrd.img-5.4.96-pangum900+_new ./initrd_pg_bak
    cd ./initrd_pg_bak
    cpio -i < initrd.img-5.4.96-pangum900+_new
    cd ..
    将ubuntu原始initrd下usr/lib/modules/下目录内容删除,然后将initrd.img-5.4.96-pangum900+解压后usr/lib/modules/目录下的5.4.96-pangum900+完整拷贝到ubuntu原始initrd对应目录下。
    rm -rf ./initrd_bak/usr/lib/modules/*
    cp -rf ./initrd_pg_bak/usr/lib/modules/* ./initrd_bak/usr/lib/modules/
    接下来重新打包生成initrd:
    先打包成cpio格式(注意删除目录下解压前的cpio文件):
    cd ./initrd_bak
    find ./ |cpio -o -H newc > initrd-new.cpio
    再将cpio文件压缩为lzma格式:
    lzma initrd-new.cpio
    cd ../..
    生成的initrd-new.cpio.lzma文件即为定制内核后的initrd文件,将该文件替换到ubuntu目录中:
    root@kwephicprd24193:~/ubuntu_live# cp ./initrd/initrd_bak/initrd-new.cpio.lzma squashfs-root/boot/initrd.img-5.4.96-pangum900+
    root@kwephicprd24193:~/ubuntu_live# cp ./initrd/initrd_bak/initrd-new.cpio.lzma extract-cd/casper/initrd
  16. 重新制作并替换文件系统(在ubuntu_live目录下执行)
    1
    2
    3
    4
    rm extract-cd/casper/filesystem.manifest 
    chroot squashfs-root dpkg-query -W --showformat='${Package}${Version}\n' > extract-cd/casper/filesystem.manifest
    rm extract-cd/casper/filesystem.squashfs (若filesystem.squashfs存在需要删除)
    mksquashfs squashfs-root extract-cd/casper/filesystem.squashfs
  17. 更新iso中的md5sum(在ubuntu_live目录下执行)
    1
    2
    3
    4
    5
    rm extract-cd/md5sum.txt
    cd extract-cd && find . -type f -print0 | xargs -0 md5sum > md5sum.draft
    cd ..
    cat extract-cd/md5sum.draft | grep -v md5sum.draft | grep -v isolinux/boot.cat > extract-cd/md5sum.txt
    rm extract-cd/md5sum.draft
  18. 制作新的iso文件(在ubuntu_live目录下执行),本文档以ubuntu_customized_20.04.3.iso命令
    1
    mkisofs -r -o ubuntu_customized_20.04.3.iso extract-cd/
    生成的.iso文件即为定制完成的ISO镜像。

说明:使用U盘安装系统时,需要配置grub,所以需要提前把extract-cd/下的boot和efi文件夹拷贝出来备用。

脚本整理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/bin/bash
#############################################################################################
####################### var ######################
#############################################################################################

echo "制作ubuntu 20.4"
echo "创建2个文件夹:deb 和 ubuntu_live, deb 放所有的 deb 补丁和kernel deb"
echo "ubuntu_live 放此脚本和ubuntu-20.04.3-live-server-arm64.iso"
echo "create ubutnu 20.4 iso"
work_root=`pwd`

function delcustomerdir()
{
for dir in ./*
do
# echo $dir
if [ $dir = ./mnt ]; then

echo "del ./mnt"
rm -rf ./mnt;

fi

if [ "$dir" = "./extract-cd" ]; then

echo "del ./extract-cd";
rm -rf ./extract-cd
fi

if [ "$dir" = "./initrd" ]; then


echo "del ./initrd";
rm -rf ./initrd
fi
done
}


function step1_8()
{
mkdir mnt
mount -o loop ubuntu-20.04.3-live-server-arm64.iso mnt
mkdir extract-cd
rsync --exclude=/casper/filesystem.squashfs -a mnt/ extract-cd
unsquashfs mnt/casper/filesystem.squashfs
cp ../deb/*deb squashfs-root/home/
cp ./create_ubuntu_20.4.sh squashfs-root/home/
chroot squashfs-root/ /home/create_ubuntu_20.4.sh
}

function step9_12()
{
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devpts none /dev/pts
export HOME=/root
export LC_ALL=C
dpkg -i /home/*.deb
echo "+++++修改压缩方式为lzma++++++"
sed -i "s/COMPRESS=gzip/COMPRESS=lzma/g" /etc/initramfs-tools/initramfs.conf
echo "+++++11l++++++"
rm /home/*.deb
sed -i "s/soc_vou/uapi_panel\nsoc_vou/g" ./usr/lib/modules-load.d/ko_load.conf
echo "+++++11l++++++"
apt-get clean
rm -rf /tmp/* ~/.bash_history
rm /home/create_ubuntu_20.4.sh
umount /proc
umount /sys
umount /dev/pts
export HISTSIZE=0
exit
umount mnt
}

function step13_18()
{
echo "+++++13 制作UEFI++++++"
mount -o loop extract-cd/boot/grub/efi.img mnt
cp mnt/efi extract-cd/ -rf
umount mnt

echo "+++++14 替换内核++++++"
cp squashfs-root/boot/vmlinuz-5.4.96-pangum900 extract-cd/casper/vmlinuz

echo "+++++15 制作并替换initrd++++++"
mkdir initrd
cp extract-cd/casper/initrd ./initrd/
cd ./initrd
lz4 -d initrd initrd_new
mkdir -p initrd_bak
cp initrd_new initrd_bak/
cd initrd_bak/
cpio -i < initrd_new
rm -rf initrd_new
cd ../..

cp squashfs-root/boot/initrd.img-5.4.96-pangum900 ./initrd/
cd ./initrd
lz4 -d initrd.img-5.4.96-pangum900 initrd.img-5.4.96-pangum900_new
mkdir -p initrd_pg_bak
mv initrd.img-5.4.96-pangum900_new ./initrd_pg_bak
cd ./initrd_pg_bak
cpio -i < initrd.img-5.4.96-pangum900_new
cd ..

rm -rf ./initrd_bak/usr/lib/modules/*
cp -rf ./initrd_pg_bak/usr/lib/modules/* ./initrd_bak/usr/lib/modules/

cd ./initrd_bak
find ./ |cpio -o -H newc > initrd-new.cpio

lzma initrd-new.cpio
cd ../..


cp ./initrd/initrd_bak/initrd-new.cpio.lzma squashfs-root/boot/initrd.img-5.4.96-pangum900
cp ./initrd/initrd_bak/initrd-new.cpio.lzma extract-cd/casper/initrd


echo "+++++16 重新制作并替换文件系统++++++"

rm extract-cd/casper/filesystem.manifest
chroot squashfs-root dpkg-query -W --showformat='${Package}${Version}\n' > extract-cd/casper/filesystem.manifest
rm extract-cd/casper/filesystem.squashfs
mksquashfs squashfs-root extract-cd/casper/filesystem.squashfs

echo "+++++17 更新iso中的md5sum++++++"

rm extract-cd/md5sum.txt
cd extract-cd && find . -type f -print0 | xargs -0 md5sum > md5sum.draft
cd ..
cat extract-cd/md5sum.draft | grep -v md5sum.draft | grep -v isolinux/boot.cat > extract-cd/md5sum.txt
rm extract-cd/md5sum.draft

echo "+++++18 制作新的iso文件++++++"
mkisofs -r -o ubuntu_customized_20.04.3.iso extract-cd/
echo "sucess create the os !!! "
}




if [ "$work_root" == '/' ]; then
echo ">>>>>>>>enter custom root enviroment<<<<<<<<<<!"
step9_12
else
echo ">>>>>>>>enter server enviroment<<<<<<<<<<!"
step1_8
step13_18
fi


ISO镜像安装

准备工作

  1. 已定制好的ISO镜像(ubuntu_customized_20.04.3.iso)
  2. 依赖的硬件环境:目标板、U盘、SSD
  3. BIOS引导环境OK

制作安装U盘

  1. 使用32G以上的U盘,并格式化为vfat格式。
    参考命令:
    1
    mkfs.vfat /dev/sda
  2. 修改boot和efi
    ISO定制中已说明,需要把extract-cd/下的boot和efi文件夹拷贝出来备用。这里需要对boot/grub/grub.cfg修改,修改grub.cfg方法:从第10行“menuentry “Install Ubuntu Server” {”开始一直到最后全部删除。增加以下修改:
    1
    2
    3
    4
    5
    6
    7
    8
    menuentry "Install Ubuntu Server" {
    set gfxpayload=keep
    set rootdelay=90
    set isofile=/ubuntu_customized_20.04.3.iso
    loopback loop (hd0,msdos1)$isofile
    linux (loop)/casper/vmlinuz iso-scan/filename=$isofile ro quiet splash ---
    initrd (loop)/casper/initrd
    }
    ubuntu_customized_20.04.3.iso:定制化ISO镜像名称,根据实际情况修改;
    (hd0,msdos1):grub中读到的U盘名称,不同U盘可能名称不同。有可能是(hd0)或者其他。
  3. 修改后把boot和efi文件夹连同已定制好的ISO镜像一同拷贝到U盘根目录下。此时U盘根目录下内容如下
    1
    Boot、efi和ubuntu_customized_20.04.3.iso。

启动U盘安装

!!! 以下安装流程请在串口下进行操作

  1. 插入U盘,目标板上电,如果已设置从U盘启动,则会进入如下GRUB;如果没有设置从U盘启动,需在启动过程中按ESC后进入UEFI界面选择U盘启动。依次选择Boot Manager ->UEFI Kingston xxxxxxx进入GRUB,U盘名称请以实际识别为准。
    img not found

  2. 在grub界面确认U盘的盘符,本文为(hd0,msdos1),以下可以确认:
    img not found

  3. 执行以下命令引导ubuntu安装

    1
    2
    3
    set root=(hd0,msdos1)
    set prefix= (hd0,msdos1)/boot/grub
    normal

    img not found

  4. 选择Install Ubuntu Server进入安装流程

  5. 等待文件校验及内核启动后,界面如下:
    img not found

  6. 通过键盘上键选中[Help],进入shell中,当前lib指向usr/lib,而定制的内核挂载在rofs下,因此需要执行以下命令修改:

    1
    ln -snf rofs/lib lib

    img not found

  7. 之后执行exit退出shell,选择Continue in rich mode.

  8. 由于一些功能依赖swap和/data分区,请使用手动分区。进入到分区页面后,选择Custom Storage layout后,选择done.
    img not found
    若存在已有的逻辑设备,选择Delete删除:
    img not found
    选择Reformat将硬盘分区重置:
    img not found

  9. 以上工作完成后,开始分区操作。参考分区操作如下:
    选择Use As Boot Device将硬盘设置为Boot Device,此时会生成efi分区。
    img not found
    添加一个5G的data分区:
    img not found
    添加一个14G的swap分区:
    img not found
    以上未提到的boot分区、根分区、home分区等请自行分配。

  10. 按照提示安装完成后重启,拔出U盘即可。

Ubuntu_Desktop桌面安装

Ubuntu20.04系统安装后默认不带桌面,所以配置网络后需要安装桌面。

  1. 安装桌面根据网络情况耗时较长,请耐心等待。安装指令如下:
    1
    apt-get install ubuntu-desktop
  2. 安装完成后,需重启系统。
  3. 系统启动出现登录窗口后,输入密码正常进入系统桌面。如下图:
    img not found