summaryrefslogtreecommitdiff
path: root/mkinitramfs
blob: e7d79438b8f1d58bb73f9b54e00b953685fed45e (plain)
    1 #!/usr/bin/env bash
    2 #
    3 # Mkinitramfs creates a basic init ram fs with encryption support.
    4 # Copyright (C)  2016  Aaron Ball <nullspoon@oper.io>
    5 #
    6 # This program is free software: you can redistribute it and/or modify
    7 # it under the terms of the GNU General Public License as published by
    8 # the Free Software Foundation, either version 3 of the License, or
    9 # (at your option) any later version.
   10 #
   11 # This program is distributed in the hope that it will be useful,
   12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 # GNU General Public License for more details.
   15 #
   16 # You should have received a copy of the GNU General Public License
   17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
   18 #
   19 
   20 
   21 # Hash of fully-qualified binaries
   22 declare -a fqbins
   23 
   24 
   25 #
   26 # Searches PATH for all binaries listed as function arguments. Each found
   27 # binary is then put into the global "bins" array.
   28 #
   29 # This function also serves to ensure all specified binaries are present and
   30 # in PATH. It will exit code 1 with an error message if any binaries are not
   31 # found.
   32 #
   33 # Note: To use this function, insert "declare -a fqbins" at top of script).
   34 #
   35 # @param bins All function arguments are the names of binaries to locate.
   36 #
   37 function resolve_bins {
   38   local args=${@}
   39 
   40   for i in ${args[@]}; do
   41     local path=$(which ${i} 2>/dev/null)
   42 
   43     if [[ $? -gt 0 ]]; then
   44       echo "Could not find binary ${i}. Is it installed?"
   45       exit 1
   46     fi
   47 
   48     echo "Located ${i} at ${path}"
   49     fqbins+=("${path}")
   50   done
   51 }
   52 
   53 
   54 #
   55 # Gets first path locatable in a string
   56 #
   57 function get_first_path {
   58   local str=${1}
   59 
   60   local out=''
   61   local cursor=''
   62 
   63   for ((i=0; i<${#str}; i++)); do
   64     if [[ ${str:$i:1} == '/' ]]; then
   65       cursor=${i}
   66       break
   67     fi
   68   done
   69 
   70   # Exit if no path found
   71   [[ ${cursor} == '' ]] && return
   72 
   73   while [[ ${str:$cursor:1} != ' ' ]] && [[ ${cursor} -lt ${#str} ]]; do
   74     out="${out}${str:$cursor:1}"
   75     cursor=$((${cursor} + 1))
   76   done
   77 
   78   echo "${out}"
   79 }
   80 
   81 
   82 function get_deps {
   83   local bin=${1}
   84 
   85   for dep in $(ldd ${bin}); do
   86      get_first_path "${dep}"
   87   done
   88 }
   89 
   90 
   91 #
   92 # Creates cpio file for specified initrd cache directory.
   93 # Outputs to /boot/initrd-${version}.
   94 #
   95 # @param cache   Path to the uncompressed source directory to be archived
   96 # @param version Version of initrd archive
   97 #
   98 function mkcpio {
   99   [[ -z ${1} ]] && echo "Initramfs cache path required." && exit 1
  100   [[ -z ${2} ]] && echo "Kernel version required." && exit 1
  101 
  102   local cache=${1}
  103   local version=${2}
  104 
  105   cd ${cache}
  106   fspath="/boot/initrd-${version}"
  107 
  108   # Notify user of initrd overwriting
  109   [[ -f ${fspath} ]] && echo -e "\n\n${fspath} exists. Overwriting.\n"
  110 
  111   # Create the initrd
  112   find . -print0 | cpio --null -ov --format=newc | xz -C crc32 -v -9 -c > ${fspath}
  113 }
  114 
  115 
  116 #
  117 # Sets up cache dir for later writing to an archive (via cpio).
  118 # Performs simple operations like creating a basic directory structure, 
  119 #
  120 # @param cache Path to the cache directory. Will be created if not exists
  121 #
  122 function cache_dir_setup {
  123   [[ -z ${1} ]] && echo "Please specify a cache dir." && exit 1
  124   local cache=${1}
  125 
  126   # Clean the cache so we start fresh
  127   rm -rf ${cache} && mkdir ${cache}
  128 
  129   local dirs=(
  130     bin
  131     dev
  132     dev/disk
  133     dev/disk/by-uuid
  134     etc
  135     lib
  136     lib32
  137     lib64
  138     mnt/root
  139     proc
  140     root
  141     run
  142     sbin
  143     sys
  144     usr/lib
  145     usr/lib64
  146     usr/lib32
  147     usr/bin
  148     usr/sbin
  149   )
  150 
  151   # Create the temporary directory structure
  152   for i in ${dirs[*]}; do
  153     mkdir -p ${cache}/${i}
  154   done
  155 }
  156 
  157 
  158 #
  159 # Checks installed kernel modules for the specified version to see if the
  160 # corresponding kernel has encryption support statically compiled in.
  161 #
  162 # @param version Version of kernel modules to check
  163 #
  164 function check_crypto_support {
  165   [[ -z ${1} ]] && echo "Kernel version required." && exit 1
  166   local version=${1}
  167 
  168   builtinpath=/lib/modules/${version}/modules.builtin
  169   
  170   # Check for encryption support
  171   if [[ ! $(grep dm-crypt ${builtinpath}) ]]; then
  172     echo -e "\n\nWarning: Static encryption support not found."
  173     echo "         Module dm-crypt not found in modules.builtin."
  174     echo "Press enter to continue, or Ctrl+c to exit and resolve."
  175     read
  176   fi
  177 }
  178 
  179 
  180 #
  181 # Checks to see if kernel modules for the specified version have been
  182 # installed.
  183 #
  184 # @param version Version to check for installation status
  185 #
  186 function check_kernel_version {
  187   [[ -z ${1} ]] && echo "Kernel version required." && exit 1
  188   local version=${1}
  189 
  190   modulespath=/lib/modules/${version}
  191   if [[ ! -d ${modulespath} ]]; then
  192     echo "Error: Could not find ${modulespath}."
  193     echo "Has kernel version ${version} been comiled?"
  194     exit 1
  195   fi
  196 }
  197 
  198 
  199 function main {
  200   [[ -z ${1} ]] && echo "Please specify a kernel version" && exit 1
  201 
  202   local version=${1}
  203 
  204   check_kernel_version ${version}
  205 
  206   local cache='/tmp/initrd'
  207   local res_path=/usr/share/mkinitramfs/
  208 
  209   # List of binaries to exist in the new initramfs
  210   resolve_bins \
  211     bash cat echo ls cryptsetup chmod chown mount sleep umount clear cut \
  212     grep less tr which blkid shutdown switch_root
  213 
  214 
  215   # Set up the archive source dir.
  216   cache_dir_setup ${cache}
  217 
  218   # Ensure static crypto support exists in kernel
  219   check_crypto_support ${version}
  220 
  221   # Copy binary and dependencies to cache dir
  222   for bin in ${fqbins[@]}; do
  223     bindirname=$(dirname ${bin})
  224     # Copy the binary of interest
  225     cp -u ${bin} "${cache}/${bindirname}/"
  226 
  227     deps=$(get_deps ${bin})
  228     # Copy each of the binary's deps
  229     for dep in ${deps[@]}; do
  230       local depdirname=$(dirname ${dep})
  231       cp -u ${dep} "${cache}/${depdirname}/"
  232       if [[ $? -gt 0 ]]; then
  233         echo "Error: Problem copying ${dep} into ${cache}."
  234 	      exit 1
  235       fi
  236     done
  237   done
  238 
  239   # Copy in init script and add execute
  240   cp ${res_path}/init ${cache}/init && chmod +x ${cache}/init
  241   # Copy in message file
  242   cp ${res_path}/msg ${cache}/etc/msg
  243 
  244   # Create archive image
  245   mkcpio ${cache} ${version}
  246 }
  247 
  248 
  249 main ${@}

Generated by cgit