mknet.sh.in 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #!/bin/sh
  2. #
  3. # vim: set ts=4 sw=4 et:
  4. #
  5. #-
  6. # Copyright (c) 2009-2015 Juan Romero Pardines.
  7. # All rights reserved.
  8. #
  9. # Redistribution and use in source and binary forms, with or without
  10. # modification, are permitted provided that the following conditions
  11. # are met:
  12. # 1. Redistributions of source code must retain the above copyright
  13. # notice, this list of conditions and the following disclaimer.
  14. # 2. Redistributions in binary form must reproduce the above copyright
  15. # notice, this list of conditions and the following disclaimer in the
  16. # documentation and/or other materials provided with the distribution.
  17. #
  18. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20. # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23. # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. #-
  29. readonly PROGNAME=$(basename "$0")
  30. readonly REQTOOLS="xbps-install tar"
  31. # This script needs to jump around, so we'll remember where we started
  32. # so that we can get back here
  33. readonly CURDIR="$(pwd)"
  34. # This source pulls in all the functions from lib.sh. This set of
  35. # functions makes it much easier to work with chroots and abstracts
  36. # away all the problems with running binaries with QEMU.
  37. # shellcheck source=./lib.sh
  38. . ./lib.sh
  39. # Die is a function provided in lib.sh which handles the cleanup of
  40. # the mounts and removal of temporary directories if the running
  41. # program exists unexpectedly.
  42. trap 'die "An unchecked exception has occured!"' INT TERM
  43. usage() {
  44. cat <<_EOF
  45. Usage: $PROGNAME [options] <rootfs>
  46. Options:
  47. -r <repo-url> Use this XBPS repository (may be specified multiple times).
  48. -c <cachedir> Use this XBPS cache directory.
  49. -i <lz4|gzip|bzip2|xz> Compression type for the initramfs image (lz4 if unset).
  50. -o <file> Output file name for the netboot tarball (auto if unset).
  51. -C "cmdline args" Add additional kernel command line arguments.
  52. -T "title" Modify the bootloader title.
  53. -S "splash image" Set a custom splash image for the bootloader
  54. The $PROGNAME script generates a network-bootable tarball of Void Linux
  55. _EOF
  56. exit 1
  57. }
  58. # ########################################
  59. # SCRIPT EXECUTION STARTS HERE
  60. # ########################################
  61. while getopts "r:c:C:T:i:o:h" opt; do
  62. case $opt in
  63. r) XBPS_REPOSITORY="--repository=$OPTARG $XBPS_REPOSITORY";;
  64. c) XBPS_CACHEDIR="--cachedir=$OPTARG";;
  65. i) INITRAMFS_COMPRESSION="$OPTARG";;
  66. o) OUTPUT_FILE="$OPTARG";;
  67. C) BOOT_CMDLINE="$OPTARG";;
  68. T) BOOT_TITLE="$OPTARG";;
  69. S) SPLASH_IMAGE="OPTARG";;
  70. h) usage;;
  71. esac
  72. done
  73. shift $((OPTIND - 1))
  74. BASE_TARBALL="$1"
  75. # We need to infer the target architecture from the filename. All
  76. # other scripts are able to get this from the platforms map because a
  77. # platform is manually specified. Since the netboot tarballs target
  78. # only architectures, its necessary to pull this information from the
  79. # filename.
  80. XBPS_TARGET_ARCH=${BASE_TARBALL%%-ROOTFS*}
  81. XBPS_TARGET_ARCH=${XBPS_TARGET_ARCH##void-}
  82. # Knowing the target arch, we can set the cache up if it hasn't
  83. # already been set
  84. set_cachedir
  85. # This is an aweful hack since the script isn't using privesc
  86. # mechanisms selectively. This is a TODO item.
  87. if [ "$(id -u)" -ne 0 ]; then
  88. die "need root perms to continue, exiting."
  89. fi
  90. # Before going any further, check that the tools that are needed are
  91. # present. If we delayed this we could check for the QEMU binary, but
  92. # its a reasonable tradeoff to just bail out now.
  93. check_tools
  94. # We need to operate on a tempdir, if this fails to create, it is
  95. # absolutely crucial to bail out so that we don't hose the system that
  96. # is running the script.
  97. ROOTFS=$(mktemp -d) || die "failed to create ROOTFS tempdir, exiting..."
  98. BOOT_DIR=$(mktemp -d) || die "failed to create BOOT_DIR tempdir, exiting..."
  99. PXELINUX_DIR="$BOOT_DIR/pxelinux.cfg"
  100. # Now that we have a directory for the ROOTFS, we can expand the
  101. # existing base filesystem into the directory
  102. info_msg "Expanding base tarball $BASE_TARBALL into $ROOTFS for $PLATFORM build."
  103. tar xf "$BASE_TARBALL" -C "$ROOTFS"
  104. info_msg "Install additional dracut modules"
  105. # This section sets up the dracut modules that need to be present on
  106. # the ROOTFS to build the PXE tarball. This includes the netmenu
  107. # module and the autoinstaller
  108. mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/05netmenu"
  109. cp dracut/netmenu/* "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/"
  110. # The netmenu can directly launch the manual installer from the
  111. # initrd. This is the same installer that's on the live media with
  112. # all its quirks, oddities, and wierdness. It's included here for
  113. # places where you might have a lab network and need to run manual
  114. # installs from the network.
  115. cp installer.sh "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/"
  116. # Of course with a PXE environment unattended installs are the norm.
  117. # The autoinstaller is loaded as a very high priority dracut module
  118. # and will fail the build if it can't be installed.
  119. mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller"
  120. cp dracut/autoinstaller/* "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller/"
  121. info_msg "Install kernel and additional required netboot packages"
  122. # The rootfs has no kernel in it, so it needs to have at the very
  123. # least dracut, syslinux, and linux installed. binutils provides
  124. # /usr/bin/strip which lets us shrink down the size of the initrd
  125. # dracut-network provides the in-initrd network stack
  126. # dialog is needed by the install environment
  127. # ${INITRAMFS_COMPRESSION} is the name of the compressor we want to use (lz4 by default)
  128. run_cmd_target "xbps-install $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -Sy linux dracut syslinux binutils dracut-network dialog ${INITRAMFS_COMPRESSION-lz4}"
  129. run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a"
  130. # Dracut needs to know the kernel version that will be using this
  131. # initrd so that it can install the kernel drivers in it. Normally
  132. # this check is quite complex, but since this is a clean rootfs and we
  133. # just installed exactly one kernel, this check can get by with a
  134. # really niave command to figure out the kernel version
  135. KERNELVERSION=$(ls "$ROOTFS/usr/lib/modules/")
  136. # Now that things are setup, we can call dracut and build the initrd.
  137. # This will pretty much step through the normal process to build
  138. # initrd with the exception that the autoinstaller and netmenu are
  139. # force added since no module depends on them.
  140. info_msg "Building initrd for kernel version $KERNELVERSION"
  141. run_cmd_chroot "$ROOTFS" "env -i /usr/bin/dracut \
  142. -N \
  143. --${INITRAMFS_COMPRESSION-lz4} \
  144. --add-drivers ahci \
  145. --force-add 'autoinstaller netmenu' \
  146. --omit systemd \
  147. /boot/initrd \
  148. $KERNELVERSION"
  149. [ $? -ne 0 ] && die "Failed to generate the initramfs"
  150. info_msg "Collect netboot components"
  151. # The whole point of this endeavor is to get the files needed for PXE.
  152. # Now that they have been generated, we copy them out of the doomed
  153. # ROOTFS and into the $BOOT_DIR where we're staging the rest of the
  154. # tarball
  155. mv -v "$ROOTFS/boot/initrd" "$BOOT_DIR"
  156. cp -v "$ROOTFS/boot/vmlinuz-$KERNELVERSION" "$BOOT_DIR/vmlinuz"
  157. # The initrd has *very* restrictive permissions by default. To
  158. # prevent some SysAdmin down the road having a very frustrating time
  159. # debugging this, we just fix this here and now.
  160. chmod 0644 "$BOOT_DIR/initrd"
  161. # Now we need to grab the rest of the files that go in the tarball.
  162. # Some of these are always required, some of these are canonical, and
  163. # some of this list is from trial and error. Either way, this is the
  164. # minimum needed to get Void up and booting on metal from the network.
  165. for prog in pxelinux.0 ldlinux.c32 libcom32.c32 vesamenu.c32 libutil.c32 chain.c32 ; do
  166. cp -v "$ROOTFS/usr/share/syslinux/$prog" "$BOOT_DIR"
  167. done
  168. # Lastly we need the default pxelinux config and the splash image.
  169. # This is user configurable, but if that isn't set then we'll use the
  170. # one from data/splash.png instead
  171. mkdir -p "$PXELINUX_DIR"
  172. cp -f pxelinux.cfg/pxelinux.cfg.in "$PXELINUX_DIR/default"
  173. cp -f "${SPLASH_IMAGE-data/splash.png}" "$BOOT_DIR"
  174. # This sets all the variables in the default config file
  175. info_msg "Configuring pxelinux.0 default boot menu"
  176. sed -i -e "s|@@SPLASHIMAGE@@|$(basename "${SPLASH_IMAGE}")|" \
  177. -e "s|@@KERNVER@@|${KERNELVERSION}|" \
  178. -e "s|@@KEYMAP@@|${KEYMAP}|" \
  179. -e "s|@@ARCH@@|$BASE_ARCH|" \
  180. -e "s|@@LOCALE@@|${LOCALE}|" \
  181. -e "s|@@BOOT_TITLE@@|${BOOT_TITLE}|" \
  182. -e "s|@@BOOT_CMDLINE@@|${BOOT_CMDLINE}|" \
  183. "$PXELINUX_DIR/default"
  184. # Default output file format
  185. OUTPUT_FILE="void-netboot-${XBPS_TARGET_ARCH}-${KERNELVERSION}-$(date +%Y%m%d)"
  186. info_msg "Compressing results to $OUTPUT_FILE.tar.gz"
  187. cd "$BOOT_DIR" || die "Could not enter image dir"
  188. tar -zcvf "$CURDIR/$OUTPUT_FILE.tar.gz" .
  189. cd "$CURDIR" || die "Could not return to working directory"
  190. # As a final cleanup step, remove the ROOTFS and the expanded BOOT_DIR
  191. info_msg "Cleaning up and removing build directories"
  192. cleanup_chroot
  193. [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
  194. [ -d "$BOOT_DIR" ] && rm -rf "$BOOT_DIR"