Difference between revisions of "Creating an Initramfs"

From CBLFS
Jump to navigationJump to search
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Package-Introduction|The mkinitramfs script creates a gzip compressed cpio archive using busybox and a simple shell init script, which can be used in place of an initrd to do such things as load kernel modules before the system boots, in order to access functionality that is not compiled into the kernel, and therefore must be loaded, such as usb disks, scsi disks, etc. This is different than loading modules automatically at boot time, because those are loaded after the root disk is mounted, fsck'd etc, and typically an initrd contains modules which are loaded into the kernel before anything else, to fascilitate mounting the root fs. IE kernel doesn't have reiserfs support compiled in, but your root fs is formatted reiserfs}}
+
{{Package-Introduction|The mkinitramfs script creates a gzip compressed cpio archive using busybox and a simple shell init script, which can be used in place of an initrd to do such things as load kernel modules before the system boots, in order to access functionality that is not compiled into the kernel, and therefore must be loaded, such as usb disks, scsi disks, etc. This is different than loading modules automatically at boot time, because those are loaded after the root disk is mounted, fsck'd etc, and typically an initrd contains modules which are loaded into the kernel before anything else, to fascilitate mounting the root fs. IE kernel doesn't have reiserfs support compiled in, but your root disk is formatted reiserfs}}
 
== Dependencies ==
 
== Dependencies ==
  
Line 12: Line 12:
 
  #!/bin/bash
 
  #!/bin/bash
 
  errmsg(){
 
  errmsg(){
cat << EOT
+
  cat << EOT
 
   [ERROR] $@
 
   [ERROR] $@
 
  EOT
 
  EOT
 
  }
 
  }
 
  killme(){
 
  killme(){
errmsg "$@"
+
  errmsg "$@"
errmsg "Exiting ..."
+
  errmsg "Exiting ..."
exit 1
+
  exit 1
 
  }
 
  }
 
  helpme(){
 
  helpme(){
cat << EOT
+
  cat << EOT
 
   $(basename ${0}) is a script to automagically make
 
   $(basename ${0}) is a script to automagically make
 
   a gzip compressed cpio archive containsing busybox
 
   a gzip compressed cpio archive containsing busybox
 
   which can act as an initrd.
 
   which can act as an initrd.
 
   
 
   
  -c - remove initramfs-tree before creating the
+
-c             - remove initramfs-tree before creating the
  initramfs
+
                  initramfs
 
   
 
   
  -v|--verbose - use verbose messages
+
-v|--verbose   - use verbose messages
 
   
 
   
  -k <version> - use modules from kernel <version>
+
-k <version>   - use modules from kernel <version>
 
   
 
   
  -m <arg1,arg2> - comma separated list of additional modules
+
-m <arg1,arg2> - comma separated list of additional modules
  besides the ones contained in the file
+
                  besides the ones contained in the file
  /etc/sysconfig/mkinitramfs.modules to add
+
                  /etc/sysconfig/mkinitramfs.modules to add
  to the initramfs archive
+
                  to the initramfs archive
 
   
 
   
  -o <arg> - output finished archive to <arg> instead
+
-o <arg>       - output finished archive to <arg> instead
  of /boot/initramfs.igz
+
                  of /boot/initramfs.igz
 
   
 
   
  -r|--rootfs - use device as root device
+
-r|--rootfs     - use device as root device
 
  -f|--rootfstype - use filesystem type for root device
 
 
   
 
   
 
  Example:
 
  Example:
Line 50: Line 48:
 
  }
 
  }
 
  usage(){
 
  usage(){
cat << EOT
+
  cat << EOT
   $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 -f ext3
+
   $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 -o /boot/initramfs.igz-2.6.30.2
 
  EOT
 
  EOT
 
  }
 
  }
 
  vrbmsg(){
 
  vrbmsg(){
if [ "${initramfs_use_verbose}" ]; then
+
  if [ "${initramfs_use_verbose}" ]; then
cat << EOT
+
    cat << EOT
 
  $@
 
  $@
 
  EOT
 
  EOT
fi
+
  fi
 
  }
 
  }
 
  fnd_mod(){
 
  fnd_mod(){
module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko)"
+
  module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko)"
if [ ! -n "${module}" ]; then
+
  if [ ! -n "${module}" ]; then
module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko.gz)"
+
    module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko.gz)"
fi
+
  fi
cat << EOT
+
  cat << EOT
 
  ${module}
 
  ${module}
 
  EOT
 
  EOT
unset module
+
  unset module
 
  }
 
  }
 
  initramfs_use_kernel="$(uname -r)"
 
  initramfs_use_kernel="$(uname -r)"
Line 76: Line 74:
 
  initramfs_use_rootfstype="ext3"
 
  initramfs_use_rootfstype="ext3"
 
  until [ -z "${1}" ]; do
 
  until [ -z "${1}" ]; do
case "${1}" in
+
  case "${1}" in
-c)
+
    -c)
rm -rf /boot/initramfs-tree
+
      rm -rf /boot/initramfs-tree
;;
+
      ;;
-v|--verbose)
+
    -v|--verbose)
initramfs_use_verbose='true'
+
      initramfs_use_verbose='true'
;;
+
      ;;
-k)
+
    -k)
initramfs_use_kernel="${2}"
+
      initramfs_use_kernel="${2}"
shift
+
      shift
;;
+
      ;;
-m)
+
    -m)
initramfs_use_modules="${2}"
+
      initramfs_use_modules="${2}"
shift
+
      shift
;;
+
      ;;
-o)
+
    -o)
initramfs_output="${2}"
+
      initramfs_output="${2}"
shift
+
      shift
;;
+
      ;;
-r|--rootfs)
+
    -r|--rootfs)
initramfs_use_rootfs="${2}"
+
      initramfs_use_rootfs="${2}"
shift
+
      shift
;;
+
      ;;
-f|--rootfstype)
+
    -h|--help)
initramfs_use_rootfstype="${2}"
+
      helpme
shift
+
      usage
;;
+
      exit 0
-h|--help)
+
      ;;
helpme
+
    -u|--usage)
usage
+
      usage
exit 0
+
      exit 0
;;
+
      ;;
-u|--usage)
+
  esac
usage
+
  shift
exit 0
 
;;
 
esac
 
shift
 
 
  done
 
  done
 
  for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do
 
  for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do
if [ ! -x "${mkinitramfs_tool}" ]; then
+
  if [ ! -x "${mkinitramfs_tool}" ]; then
killme "Required tool ${mkinitramfs_tool} missing!"
+
    killme "Required tool ${mkinitramfs_tool} missing!"
fi
+
  fi
 
  done
 
  done
 
  if [ ! -d "$(dirname ${initramfs_output})" ]; then
 
  if [ ! -d "$(dirname ${initramfs_output})" ]; then
killme "Can not create ${initramfs_output}"
+
  killme "Can not create ${initramfs_output}"
 
  fi
 
  fi
 
  if [ ! -d '/boot/initramfs-tree' ]; then
 
  if [ ! -d '/boot/initramfs-tree' ]; then
mkdir /boot/initramfs-tree
+
  mkdir /boot/initramfs-tree
mkdir /boot/initramfs-tree/{bin,sbin,lib,etc,proc}
+
  mkdir /boot/initramfs-tree/{bin,sbin,lib,etc,proc,root,sys,mnt}
mkdir /boot/initramfs-tree/{lib/modules,root,sys,mnt}
+
  mkdir /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}
ln -s . /boot/initramfs-tree/usr
+
  ln -s . /boot/initramfs-tree/usr
 
  fi
 
  fi
 
  if [ -f /etc/sysconfig/initramfs.modules ]; then
 
  if [ -f /etc/sysconfig/initramfs.modules ]; then
cat /etc/sysconfig/initramfs.modules | while read line; do
+
  cat /etc/sysconfig/initramfs.modules | while read line; do
if [ -n "${line}" -a "$(head -c1 <<<${line})" != "#" ]; then
+
    if [ -n "${line}" -a "$(head -c1 <<<${line})" != "#" ]; then
module="$(fnd_mod ${line})"
+
      module="$(fnd_mod ${line})"
if [ -n "${module}" ]; then
+
      if [ -n "${module}" ]; then
vrbmsg "Found ${module}"
+
        vrbmsg "Found ${module}"
case "${module}" in
+
        case "${module}" in
*.ko)
+
          *.ko)
cat ${module} > /boot/initramfs-tree/lib/modules/$(basename ${module})
+
            cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module})
;;
+
            ;;
*.ko.gz)
+
          *.ko.gz)
gzip -dc ${module} > /boot/initramfs-tree/lib/modules/$(basename ${module} .gz)
+
            gzip -dc ${module} > /boot/initramfs-tree/lib/modules${initramfs_use_kernel}/$(basename ${module} .gz)
;;
+
            :;
esac
+
        esac
else
+
      else
errmsg "Couldn't find ${line}"
+
        errmsg "Couldn't find ${line}"
fi
+
      fi
fi
+
    fi
done
+
  done
 
  fi
 
  fi
 
  if [ -n "${initramfs_use_modules}" ]; then
 
  if [ -n "${initramfs_use_modules}" ]; then
for line in ${initramfs_use_modules//,/ }; do
+
  for line in ${initramfs_use_modules//,/ }; do
module="$(fnd_mod ${line})"
+
    module="$(fnd_mod ${line})"
if [ -n "${module}" ]; then
+
    if [ -n "${module}" ]; then
vrbmsg "Found ${module}"
+
      vrbmsg "Found ${module}"
case "${module}" in
+
      case "${module}" in
*.ko)
+
        *.ko)
cat ${module} > /boot/initramfs-tree/lib/modules/$(basename ${module})
+
          cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module})
echo "$(basename ${module} .ko)" >> /boot/initramfs-tree/etc/modules
+
          echo "$(basename ${module} .ko)" >> /boot/initramfs-tree/etc/modules
;;
+
          ;;
*.ko.gz)
+
        *.ko.gz)
gzip -dc ${module} > /boot/initramfs-tree/lib/modules/$(basename ${module} .gz)
+
          gzip -dc ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module} .gz)
echo "$(basename ${module} .ko.gz)" >> /boot/initramfs-tree/etc/modules
+
          echo "$(basename ${module} .ko.gz)" >> /boot/initramfs-tree/etc/modules
;;
+
          ;;
esac
+
      esac
else
+
    else
errmsg "Couldn't find ${line}"
+
      errmsg "Couldn't find ${line}"
fi
+
    fi
done
+
  done
 
  fi
 
  fi
 
  cat /bin/busybox > /boot/initramfs-tree/bin/busybox
 
  cat /bin/busybox > /boot/initramfs-tree/bin/busybox
Line 182: Line 176:
 
  /bin/busybox clear
 
  /bin/busybox clear
 
  /bin/busybox cat << END
 
  /bin/busybox cat << END
   This system is uses Community Beyond Linux From Scratch
+
   This system uses Community Beyond Linux From Scratch
 
   <http://cblfs.cross-lfs.org/>
 
   <http://cblfs.cross-lfs.org/>
 
  END
 
  END
Line 206: Line 200:
 
  # would return "/sbin/init"
 
  # would return "/sbin/init"
 
  get_opt() {
 
  get_opt() {
echo "\$@" | /bin/busybox cut -d "=" -f 2
+
  echo "\$@" | /bin/busybox cut -d "=" -f 2
 
  }
 
  }
 
  # Defaults
 
  # Defaults
Line 213: Line 207:
 
  runlevel="3"
 
  runlevel="3"
 
  for i in \$(cat /proc/cmdline); do
 
  for i in \$(cat /proc/cmdline); do
case \${i} in
+
  case \${i} in
root\=*)
+
    root\=*)
root=\$(get_opt \${i})
+
      root=\$(get_opt \${i})
;;
+
      ;;
init\=*)
+
    init\=*)
init=\$(get_opt \${i})
+
      init=\$(get_opt \${i})
;;
+
      ;;
runlevel\=*)
+
    runlevel\=*)
runlevel=\$(get_opt \${i})
+
      runlevel=\$(get_opt \${i})
;;
+
      ;;
esac
+
  esac
 
  done
 
  done
 
  # Mount the root device
 
  # Mount the root device
  mount -o ro -t ${initramfs_use_rootfstype} "\${root}" /root
+
  mount -o ro "\${root}" /root
  if [ -f /root/lfs-root.img ]; then
+
  # Below is an example of how to use the initramfs
  BNROOT=\$(/bin/busybox basename "\${root}")
+
# to load clfs or lfs from a disk image
  umount root
+
#if [ -f /root/lfs-root.img ]; then
  mkdir -p /mnt/"\${BNROOT}" &&
+
BNROOT=\$(/bin/busybox basename "\${root}")
  mount "\${root}" /mnt/"\${BNROOT}" &&
+
umount root
  mount -o loop /mnt/"\${BNROOT}"/lfs-root.img /root &&
+
mkdir -p /mnt/"\${BNROOT}" &&
  mkdir -p /root/mnt/"\${BNROOT}" &&
+
mount "\${root}" /mnt/"\${BNROOT}" &&
  mount /mnt/"\${BNROOT}" /root/mnt/"\${BNROOT}"
+
mount -o loop /mnt/"\${BNROOT}"/lfs-root.img /root &&
  unset BNROOT
+
mkdir -p /root/mnt/"\${BNROOT}" &&
  fi
+
mount /mnt/"\${BNROOT}" /root/mnt/"\${BNROOT}"
  if [[ -x "/root/\${init}" ]]; then
+
unset BNROOT
# Unmount all other mounts so that the ram used by
+
  #fi
# the initramfs can be cleared after switch_root
+
  if [ -x "/root/\${init}" ]; then
umount /sys /proc
+
  # Unmount all other mounts so that the ram used by
  # Switch to the new root and execute the init at
+
  # the initramfs can be cleared after switch_root
# the specified runlevel
+
  umount /sys /proc
exec switch_root /root "\${init}" "\${runlevel}"
+
  # Switch to the new root and execute the init at
 +
  # the specified runlevel
 +
  exec switch_root /root "\${init}" "\${runlevel}"
 
  fi
 
  fi
 
  echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'"
 
  echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'"
Line 249: Line 245:
 
  EOT
 
  EOT
 
  chmod 755 /boot/initramfs-tree/init
 
  chmod 755 /boot/initramfs-tree/init
 +
( cd /boot/initramfs-tree
 +
  find . | cpio -H newc -o | gzip -9c > ${initramfs_output}
 +
) || exit 1
 
  EOF
 
  EOF
 
  chmod 755 /usr/sbin/mkinitramfs
 
  chmod 755 /usr/sbin/mkinitramfs

Latest revision as of 21:55, 30 October 2009

Introduction to Creating an Initramfs

The mkinitramfs script creates a gzip compressed cpio archive using busybox and a simple shell init script, which can be used in place of an initrd to do such things as load kernel modules before the system boots, in order to access functionality that is not compiled into the kernel, and therefore must be loaded, such as usb disks, scsi disks, etc. This is different than loading modules automatically at boot time, because those are loaded after the root disk is mounted, fsck'd etc, and typically an initrd contains modules which are loaded into the kernel before anything else, to fascilitate mounting the root fs. IE kernel doesn't have reiserfs support compiled in, but your root disk is formatted reiserfs

Project Homepage: Unknown

Dependencies

Required

Caution.png

Note

The init script created for the initramfs will drop to the shell in busybox if there is an error, while only a few things are actually needed for the init to function, while compiling busybox you might want to keep in mind that it may need additional functionality to be able to work properly if the initramfs drops to the shell. Also this assumes that busybox is compiled statically linked, if that is not the case, additional libraries will be required to be added to the initramfs-tree. To test this run 'file /bin/busybox'. If file reports it as dynamically linked, running 'ldd /bin/busybox' should help you determine what libraries may be needed.

Creating the mkinitramfs script

cat > /usr/sbin/mkinitramfs << "EOF"
#!/bin/bash
errmsg(){
  cat << EOT
 [ERROR] $@
EOT
}
killme(){
  errmsg "$@"
  errmsg "Exiting ..."
  exit 1
}
helpme(){
  cat << EOT
 $(basename ${0}) is a script to automagically make
 a gzip compressed cpio archive containsing busybox
 which can act as an initrd.

-c              - remove initramfs-tree before creating the
                  initramfs

-v|--verbose    - use verbose messages

-k <version>    - use modules from kernel <version>

-m <arg1,arg2>  - comma separated list of additional modules
                  besides the ones contained in the file
                  /etc/sysconfig/mkinitramfs.modules to add
                  to the initramfs archive

-o <arg>        - output finished archive to <arg> instead
                  of /boot/initramfs.igz

-r|--rootfs     - use device as root device

Example:
EOT
}
usage(){
  cat << EOT
 $(basename ${0}) -c -k 2.6.30.2 -m ext3 -r /dev/hda3 -o /boot/initramfs.igz-2.6.30.2
EOT
}
vrbmsg(){
  if [ "${initramfs_use_verbose}" ]; then
    cat << EOT
$@
EOT
  fi
}
fnd_mod(){
  module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko)"
  if [ ! -n "${module}" ]; then
    module="$(find /lib/modules/${initramfs_use_kernel} -name ${1}.ko.gz)"
  fi
  cat << EOT
${module}
EOT
  unset module
}
initramfs_use_kernel="$(uname -r)"
initramfs_output="/boot/initramfs.igz"
initramfs_use_rootfs="/dev/hda2"
initramfs_use_rootfstype="ext3"
until [ -z "${1}" ]; do
  case "${1}" in
    -c)
     rm -rf /boot/initramfs-tree
     ;;
    -v|--verbose)
     initramfs_use_verbose='true'
     ;;
    -k)
     initramfs_use_kernel="${2}"
     shift
     ;;
    -m)
     initramfs_use_modules="${2}"
     shift
     ;;
    -o)
     initramfs_output="${2}"
     shift
     ;;
    -r|--rootfs)
     initramfs_use_rootfs="${2}"
     shift
     ;;
    -h|--help)
     helpme
     usage
     exit 0
     ;;
    -u|--usage)
     usage
     exit 0
     ;;
  esac
  shift
done
for mkinitramfs_tool in /bin/busybox /usr/bin/cpio /bin/gzip; do
  if [ ! -x "${mkinitramfs_tool}" ]; then
    killme "Required tool ${mkinitramfs_tool} missing!"
  fi
done
if [ ! -d "$(dirname ${initramfs_output})" ]; then
  killme "Can not create ${initramfs_output}"
fi
if [ ! -d '/boot/initramfs-tree' ]; then
  mkdir /boot/initramfs-tree
  mkdir /boot/initramfs-tree/{bin,sbin,lib,etc,proc,root,sys,mnt}
  mkdir /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}
  ln -s . /boot/initramfs-tree/usr
fi
if [ -f /etc/sysconfig/initramfs.modules ]; then
  cat /etc/sysconfig/initramfs.modules | while read line; do
    if [ -n "${line}" -a "$(head -c1 <<<${line})" != "#" ]; then
      module="$(fnd_mod ${line})"
      if [ -n "${module}" ]; then
        vrbmsg "Found ${module}"
        case "${module}" in
          *.ko)
           cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module})
           ;;
          *.ko.gz)
           gzip -dc ${module} > /boot/initramfs-tree/lib/modules${initramfs_use_kernel}/$(basename ${module} .gz)
           :;
        esac
      else
        errmsg "Couldn't find ${line}"
      fi
    fi
  done
fi
if [ -n "${initramfs_use_modules}" ]; then
  for line in ${initramfs_use_modules//,/ }; do
    module="$(fnd_mod ${line})"
    if [ -n "${module}" ]; then
      vrbmsg "Found ${module}"
      case "${module}" in
        *.ko)
         cat ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module})
         echo "$(basename ${module} .ko)" >> /boot/initramfs-tree/etc/modules
         ;;
        *.ko.gz)
         gzip -dc ${module} > /boot/initramfs-tree/lib/modules/${initramfs_use_kernel}/$(basename ${module} .gz)
         echo "$(basename ${module} .ko.gz)" >> /boot/initramfs-tree/etc/modules
         ;;
      esac
    else
      errmsg "Couldn't find ${line}"
    fi
  done
fi
cat /bin/busybox > /boot/initramfs-tree/bin/busybox
chmod 755 /boot/initramfs-tree/bin/busybox
cat > /boot/initramfs-tree/init << EOT
#!/bin/busybox sh
# Mount things which are needed by this script
/bin/busybox mount -t proc proc /proc
/bin/busybox mount -t sysfs sysfs /sys
# Disable kernel messages from popping up on
# the screen
/bin/busybox echo 0 > /proc/sys/kernel/printk
# Clear the screen
/bin/busybox clear
/bin/busybox cat << END
 This system uses Community Beyond Linux From Scratch
 <http://cblfs.cross-lfs.org/>
END
# Create the symlinks to busybox
/bin/busybox --install -s
# Create device nodes
/bin/busybox mknod /dev/null c 1 3
/bin/busybox mknod /dev/tty c 5 0
# Check for modules
if [ -f /etc/modules ]; then
  /bin/busybox depmod /lib/modules
  /bin/busybox cat /etc/modules | while read line; do
    if [ -n "\${line}" ]; then
      /bin/busybox modprobe \${line/.ko/}
    fi
  done
fi
# Sleep for devices to connect, like USB
/bin/busybox sleep 5
/bin/busybox mdev -s
# Function for parsing command line options with
# '=' in them. Ex. get_opt("init=/sbin/init")
# would return "/sbin/init"
get_opt() {
  echo "\$@" | /bin/busybox cut -d "=" -f 2
}
# Defaults
init="/sbin/init"
root="${initramfs_use_rootfs}"
runlevel="3"
for i in \$(cat /proc/cmdline); do
  case \${i} in
    root\=*)
     root=\$(get_opt \${i})
     ;;
    init\=*)
     init=\$(get_opt \${i})
     ;;
    runlevel\=*)
     runlevel=\$(get_opt \${i})
     ;;
  esac
done
# Mount the root device
mount -o ro "\${root}" /root
# Below is an example of how to use the initramfs
# to load clfs or lfs from a disk image
#if [ -f /root/lfs-root.img ]; then
#  BNROOT=\$(/bin/busybox basename "\${root}")
#  umount root
#  mkdir -p /mnt/"\${BNROOT}" &&
#  mount "\${root}" /mnt/"\${BNROOT}" &&
#  mount -o loop /mnt/"\${BNROOT}"/lfs-root.img /root &&
#  mkdir -p /root/mnt/"\${BNROOT}" &&
#  mount /mnt/"\${BNROOT}" /root/mnt/"\${BNROOT}"
#  unset BNROOT
#fi
if [ -x "/root/\${init}" ]; then
  # Unmount all other mounts so that the ram used by
  # the initramfs can be cleared after switch_root
  umount /sys /proc
  # Switch to the new root and execute the init at
  # the specified runlevel
  exec switch_root /root "\${init}" "\${runlevel}"
fi
echo "Failed 'exec switch_root /root \\"\${init}\\" \\"\${runlevel}\\"'"
exec sh
EOT
chmod 755 /boot/initramfs-tree/init
( cd /boot/initramfs-tree
  find . | cpio -H newc -o | gzip -9c > ${initramfs_output}
) || exit 1
EOF
chmod 755 /usr/sbin/mkinitramfs