定制 Ubuntu 18.04 UEFI 启动盘初探(1)

5 篇文章 0 订阅
4 篇文章 0 订阅

  工作中需要制作定制化的Ubuntu启动盘,之前有用 buildroot 做过,但是在安装工具方面还是没有Ubuntu灵活方便,所以还是准备基于Ubuntu来制作。

  网上的文章大部分是基于Ubuntu 安装盘来制作,server版本约1GB大小,desktop版本约需要1.9GB。它有以下优点和缺点,即修改目标。

优点:

  • 使用 squash 文件系统,和initramrd相比,不需要全部加载进内存,对内存需求较低
  • 有完整的启动脚本,很多改动需求只要修改这些脚本的配置参数就可以达成

缺点:

  • 镜像太大无法满足频繁改动升级的需要
  • 不需要安装功能,考虑剪除
  • 不是所有应用都需要安装,考虑剪除
  • 需要为不同项目灵活更换配套驱动及工具,需要另行安装
  • 启动界面应按项目内容显示提示菜单

首先研究 boot/grub/grub.cfg中的启动参数,其中 boot=casper 将影响 init脚本中的 BOOT参数值。

menuentry "Try Ubuntu without installing" {
    set gfxpayload=keep
    linux    /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash ---
    initrd    /casper/initrd.lz

然后研究 casper/initrd.lz,它负责加载squash文件系统。注意“. /scripts/${BOOT}”会提供“mountroot()”函数。

. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mount_top
mount_premount
mountroot

 以下是“mountroot()”函数及其注释,看得出来,大部分casper启动功能都在这里完成。

执行下面3个脚本,都可不予支持

    run_scripts /scripts/casper-premount
10driver_updates
只有带启动参数 debian-installer/driver-update=*
才会真正执行(去找启动盘上的 /cdrom/ubuntu-drivers/$(uname -r)下的驱动更新)
 
20iso_scan
只有带启动参数 iso-scan/filename=* 才会真正执行
 
30custom_installation
只有带启动参数 debian-installer/custom-installation=* 才会真正执行
 
     if [ ! -z "${NETBOOT}" ]; then

如果网络引导,可不予支持,不过支持这个功能调试比较方便

        if do_netmount ; then
             livefs_root="${mountpoint}"
         else
             panic "Unable to find a live file system on the network"
         fi
     else
本地引导        # Scan local devices for the image
         i=0

尝试60次,每次间隔1秒

        while [ "$i" -lt 60 ]; do
 》参考 find_livefs 的实现《            livefs_root=$(find_livefs $i)
搜索启动盘,优先搜启动参数live-media=*指定的设备,
如果没有指定或没能搜到,会在合适时机遍历所有设备搜索
            if [ "${livefs_root}" ]; then
其中 /bin/fstype 查看磁盘文件格式的功能不错,值得注意                break
             fi
             sleep 1
             i="$(($i + 1))"
         done
     fi
  
     if [ -z "${livefs_root}" ]; then
         panic "Unable to find a medium containing a live file system"
     fi
  
如果启动参数指定 toram    if [ "${TORAM}" ]; then
  则将文件系统加载在内存        live_dest="ram"
如果启动参数指定 todisk=*    elif [ "${TODISK}" ]; then
  则将文件系统加载在磁盘        live_dest="${TODISK}"
     fi
     if [ "${live_dest}" ]; then
         log_begin_msg "Copying live_media to ${live_dest}"
 》参考 copy_live_to 的实现《        copy_live_to "${livefs_root}" "${live_dest}"
         log_end_msg
     fi
  
挂载镜像到目录,会调用setup_unionfs()
 会从/cdrom/casper/下匹配 "ext2" "squashfs" "dir" 后缀的文件或文件夹,并挂载
    mount_images_in_directory "${livefs_root}" "${rootmnt}"
  
     # initialize the /var/crash directory in overlayfs so that inotify for
crash处理机制,并不理解实际工作机制。    # /var/crash works and update-notifier will notify of crashes
     touch /root/var/crash/crash.init
     rm /root/var/crash/crash.init
  
     log_end_msg
  
     # Allow to override USERNAME and HOST based on media information
从initrd的/etc/casper.conf提取到FLAVOUR变量    # make it skipable by setting FLAVOUR= in casper.conf
如果FLAVOUR为空,从启动盘的/.disk/info提取    if [ -f /cdrom/.disk/info ] && [ -z "$FLAVOUR" ]; then
它将影响 HOST,USERNAME,USERFULLNAME,BUILD_SYSTEM        FLAVOUR="$(cut -d' ' -f1 "/cdrom/.disk/info" 2>/dev/null | tr '[A-Z]' '[a-z]')" || FLAVOUR=
/etc/casper.conf里的值是        if [ -n "$FLAVOUR" ]; then
export USERNAME="ubuntu"            HOST=$FLAVOUR
export USERFULLNAME="Live session user"            USERNAME=$FLAVOUR
export HOST="ubuntu"            export HOST USERNAME
export BUILD_SYSTEM="Ubuntu"            sed -i "s,USERNAME=.*,USERNAME=\"$FLAVOUR\",g; s,HOST=.*,HOST=\"$FLAVOUR\",g" /etc/casper.conf
         fi
     fi
  
     # Apply command lines override of HOST, USERNAME and USERFULLNAME
如果命令行有传参设置,
则优先使用其设置 HOST,USERNAME,USERFULLNAME
    [ -n "$CMD_HOST" ] && HOST=$CMD_HOST && export HOST
     [ -n "$CMD_USERNAME" ] && USERNAME=$CMD_USERNAME && export USERNAME
     [ -n "$CMD_USERFULLNAME" ] && USERFULLNAME=$CMD_USERFULLNAME && export USERFULLNAME
     if [ -n "$CMD_HOST" ] || [ -n "$CMD_USERNAME" ] || [ -n "$CMD_USERFULLNAME" ]; then
         sed -i "s,USERNAME=.*,USERNAME=\"$USERNAME\",g; s,USERFULLNAME=.*,USERFULLNAME=\"$USERFULLNAME\",g; s,HOST=.*,HOST=\"$HOST\",g" /etc/casper.conf
     fi
  
     # unionfs-fuse needs /dev to be bind-mounted for the duration of
     # casper-bottom; udev's init script will take care of things after that
如果是unionfs-fuse文件系统,    if [ "${UNIONFS}" = unionfs-fuse ]; then
用“mount -n -o bind ...”挂载/dev设备目录        mount -n -o bind /dev "${rootmnt}/dev"
     fi
  
     # Open up two fifo's fd's for debconf-communicate to use. Speeds up
     # the Casper process considerably.
     log_begin_msg "Creating debconf-communicate fifo mechanism"
用 fifo 加速casper过程    mkfifo /tmp/debconf-in.fifo
结束前这些fifo会被释放删除    mkfifo /tmp/debconf-out.fifo
  
     # Make the template database read-only, so that passthrough debconf
     # instances can write to it directly; otherwise templates are only
     # passed through when necessary.  Use temporary config databases as
     # well; we'll copy their contents back at the end.
     DEBCONF_TMPDIR="$(chroot /root mktemp -dt debconf.XXXXXX)"
     cp -a /root/var/cache/debconf/config.dat "/root$DEBCONF_TMPDIR/"
     cp -a /root/var/cache/debconf/passwords.dat "/root$DEBCONF_TMPDIR/"
     sed "s,^Filename: /var/cache/debconf/\(config\|passwords\).dat$,Filename: $DEBCONF_TMPDIR/\1.dat,; /^Name: templatedb/a\
 Readonly: true" /root/etc/debconf.conf >"/root$DEBCONF_TMPDIR/debconf.conf"
  
     DEBCONF_SYSTEMRC="$DEBCONF_TMPDIR/debconf.conf" chroot /root debconf-communicate -fnoninteractive casper > /tmp/debconf-out.fifo < /tmp/debconf-in.fifo &
     debconfpid="$!"
  
     if [ ! -p /tmp/debconf-in.fifo ] || [ ! -p /tmp/debconf-out.fifo ]; then
         log_warning_msg "failed to setup debconf-communicate channel"
     fi
     log_end_msg
  
     # Order matters!
     # These file descriptors must stay open until we're finished with
     # debconf-communicate.
     exec 4</tmp/debconf-out.fifo 3>/tmp/debconf-in.fifo
  
     maybe_break casper-bottom
     [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/casper-bottom"
  
》参考对应脚本《    run_scripts /scripts/casper-bottom
     [ "$quiet" != "y" ] && log_end_msg
  
     if [ "${UNIONFS}" = unionfs-fuse ]; then
         umount "${rootmnt}/dev"
     fi
  
     # Close the fd's associated with debconf-communicate.
     exec 3>&- 4<&-
     rm -f /tmp/debconf-in.fifo
     rm -f /tmp/debconf-out.fifo
     wait $debconfpid
  
     # Copy config database changes back to the master files.
     chroot /root debconf-copydb tmpdb config \
         --config=Name:tmpdb --config=Driver:File \
         --config="Filename:$DEBCONF_TMPDIR/config.dat"
     chroot /root debconf-copydb tmpdb passwords \
         --config=Name:tmpdb --config=Driver:File \
         --config="Filename:$DEBCONF_TMPDIR/passwords.dat"
     rm -rf "$DEBCONF_TMPDIR"
  
     exec 1>&6 6>&-
     exec 2>&7 7>&-
     kill "$tailpid"
     cp casper.log "${rootmnt}/var/log/"
     if [ -f /etc/casper.conf ]; then
         cp /etc/casper.conf "${rootmnt}/etc/"
     fi

要修改 casper/initrd.lz, 先了解怎么解压和重新打包

# 解压 initrd.lz

mkdir initrd-dir
cd initrd-dir
cp  ../initrd.lz initrd.lzma
unlzma -d initrd.lzma
cpio -id < initrd
rm  initrd

# 重新打包为 initrd2.lz
cd initrd-dir
find . | cpio --quiet --dereference -o -H newc > ../initrd2
cd ..
lzma -7 initrd2
mv initrd2.lzma  initrd2.lz

这样我们可以做一些改动,比如升级busybox。

/scripts/casper会解析启动参数 live-media-path,我们可以通过指定该值来改变 squashfs文件的搜索路径$LIVE_MEDIA_PATH。

            live-media-path=*)
                LIVE_MEDIA_PATH="${x#live-media-path=}"
                export LIVE_MEDIA_PATH
                echo "export LIVE_MEDIA_PATH=\"$LIVE_MEDIA_PATH\"" >> /etc/casper.conf ;;

 

下一节尝试 用cubic 工具定制启动盘,因为使用这个工具可以将注意力集中在配置软件上。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值