"多快好省"——交叉编译构建自己的linux操作系统(2)

前言

  • 这里我们在《“多快好省”——交叉编译构建自己的linux操作系统》的基础上,使用busybox来构建initrd,在基于XFS文件系统的SATA硬盘上构建带有initrd的linux操作系统

设置编译环境

set +h
umask 022
export LJOS=~/lj-os
export LC_ALL=POSIX
export PATH=${LJOS}/cross-tools/bin:/bin:/usr/bin
unset CFLAGS
unset CXXFLAGS
export LJOS_HOST=$(echo ${MACHTYPE} | sed "s/-[^-]*/-cross/")
export LJOS_TARGET=x86_64-unknown-linux-gnu
export LJOS_CPU=k8
export LJOS_ARCH=$(echo ${LJOS_TARGET} | sed -e 's/-.*//' -e 's/i.86/i386/')
export LJOS_ENDIAN=little
export CC="${LJOS_TARGET}-gcc"
export CXX="${LJOS_TARGET}-g++"
export CPP="${LJOS_TARGET}-gcc -E"
export AR="${LJOS_TARGET}-ar"
export AS="${LJOS_TARGET}-as"
export LD="${LJOS_TARGET}-ld"
export RANLIB="${LJOS_TARGET}-ranlib"
export READELF="${LJOS_TARGET}-readelf"
export STRIP="${LJOS_TARGET}-strip"

静态编译busybox

  • 这里为了方便我配置busybox为静态编译Busybox(Settings --> Build Options --> Build BusyBox as a static binary (no shared libs)
make CROSS_COMPILE="${LJOS_TARGET}-" menuconfig
make CROSS_COMPILE="${LJOS_TARGET}-"
make CROSS_COMPILE="${LJOS_TARGET}-"  install

"多快好省"——交叉编译构建自己的linux操作系统(2)

以ko的形式编译xfs驱动

  • 配置xfs
make ARCH=${LJOS_ARCH} CROSS_COMPILE=${LJOS_TARGET}- menuconfig

"多快好省"——交叉编译构建自己的linux操作系统(2)

  • 编译驱动
make ARCH=${LJOS_ARCH} CROSS_COMPILE=${LJOS_TARGET}-

构建initramfs

"多快好省"——交叉编译构建自己的linux操作系统(2)

  • skeleton
mkdir initramfs
cp -R busybox-1.28.3/_install/* initramfs/ 
cd initramfs
mkdir dev etc lib mnt proc sys
cp -R ../busybox-1.28.3/examples/bootfloppy/etc/* etc/
  • 修改etc/inittab内容
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
  • 修改后为
::sysinit:/etc/init.d/rcS
console::respawn:-/bin/sh
  • 修改etc/fstab,增加自己的挂载操作
proc	/proc	proc	defaults 0	0
  • 创建设备文件
mknod dev/console c 5 1
mknod dev/null c 1 3
  • 重新创建init脚本
    "多快好省"——交叉编译构建自己的linux操作系统(2)
# init的内容
#!/bin/sh
#
echo "exec initramfs init"
echo "mounting proc and sys"

mount -t proc proc /proc
mount -t sysfs sysfs /sys

insmod /lib/modules/4.16.3/kernel/lib/libcrc32c.ko
insmod /lib/modules/4.16.3/kernel/fs/xfs/xfs.ko

echo "detect and export hardware info"
mdev -s


echo "Mount real rootfs to /mnt/sysroot..."
mkdir /mnt/sysroot
mount -t xfs /dev/sda2 /mnt/sysroot

echo "Switch to read rootfs..."
exec switch_root /mnt/sysroot /linuxrc
#exec switch_root /mnt/sysroot /sbin/init
  • 把xfs驱动加入到initrd
mkdir -p lib/modules/4.16.3/kernel/fs/xfs/
cp /root/ljos_tar/linux-4.16.3/fs/xfs/xfs.ko lib/modules/4.16.3/kernel/fs/xfs/
  • 制作initrd
find . |cpio -o -H newc | gzip > ../initrd.img

给SATA硬盘分区

  • 分两个区,并格式化成xfs文件系统,挂载到编译机上(/root/sda1和/root/sda2)
|/dev/sdb
|---------/dev/sdb1(用于/boot)
|---------/dev/sdb2(用于/)
  • 安装bootloarder
# 将SATA硬盘的根分区挂载到编译机的/root/sda2,boot分区挂载到编译机的/root/sda2/boot,然后安装grub2
grub2-install --root-directory=/root/sda2 /dev/sdb

配置bootloarder

  • 这里我直接复用了centos7的grub2的配置
[[email protected] sda2]# cat boot/grub2/grub.cfg 
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
set pager=1

if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/00_tuned ###
set tuned_params=""
### END /etc/grub.d/00_tuned ###

### BEGIN /etc/grub.d/01_users ###
if [ -f ${prefix}/user.cfg ]; then
  source ${prefix}/user.cfg
  if [ -n ${GRUB2_PASSWORD} ]; then
    set superusers="root"
    export superusers
    password_pbkdf2 root ${GRUB2_PASSWORD}
  fi
fi
### END /etc/grub.d/01_users ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'OS1.0a'  {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod xfs
        set root='hd0,msdos1'
        linux /vmlinuz-4.16.3 root=/dev/sda2 ro 
        initrd /initrd.img
}
  • 把制作好的initrd.img放入/root/sda2/boot(即boot分区下)

启动目标机硬盘

"多快好省"——交叉编译构建自己的linux操作系统(2)

  • 正常启动,且加载了xfs驱动
    "多快好省"——交叉编译构建自己的linux操作系统(2)