[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH V3 3/6] Add utils/gen-hd-image



gen-hd-image creates partitioned harddisk images from a directory
tree and optionally installs a bootloader into the image. Supported
target filesystems are fat16, fat32 and ext2.

Its main use is building bootable images for armhf/armel/arm64
systems which use u-boot as their system firmware.  U-boot
requires the boot device to have an MBR-style partition table,
therefore booting from "superfloppy" style images (like they
are built by d-i for i386/amd64 systems) does not work there.
---
 build/util/gen-hd-image | 380 ++++++++++++++++++++++++++++++++++++++++++++++++
 debian/changelog        |   2 +
 debian/control          |   9 +-
 debian/copyright        |   5 +
 4 files changed, 394 insertions(+), 2 deletions(-)
 create mode 100755 build/util/gen-hd-image

diff --git a/build/util/gen-hd-image b/build/util/gen-hd-image
new file mode 100755
index 0000000..13913f0
--- /dev/null
+++ b/build/util/gen-hd-image
@@ -0,0 +1,380 @@
+#!/bin/sh
+#
+# gen-hd-image V1.01
+# Copyright 2014,2015 by Karsten Merker <merker@debian.org>
+#
+# This file is dual-licensed. It is provided under (at your option)
+# either the terms of the GPL2+ or the terms of the X11 license as
+# described below.  Note that this dual licensing only applies to this
+# file, and not this project as a whole.
+#
+# License options:
+#
+# - Option "GPL2+":
+#
+#   This program is free software; you can redistribute it and/or
+#   modify it under the terms of the GNU General Public License as
+#   published by the Free Software Foundation; either version 2 of the
+#   License, or (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public
+#   License along with this program; if not, write to the Free
+#   Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+#   MA 02110-1301 USA
+#
+#   On Debian systems, the full text of the GPL version 2 is
+#   available in the file /usr/share/common-licenses/GPL-2.
+#
+# - or, alternatively, option "X11":
+#
+#   Permission is hereby granted, free of charge, to any person
+#   obtaining a copy of this software and associated documentation
+#   files (the "Software"), to deal in the Software without
+#   restriction, including without limitation the rights to use,
+#   copy, modify, merge, publish, distribute, sublicense, and/or
+#   sell copies of the Software, and to permit persons to whom the
+#   Software is furnished to do so, subject to the following
+#   conditions:
+#
+#   The above copyright notice and this permission notice shall be
+#   included in all copies or substantial portions of the Software.
+#
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+#   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+#   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+#   OTHER DEALINGS IN THE SOFTWARE.
+
+PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin"
+export PATH
+
+FSTYPE="fat32"
+PARTID="0x0c"
+FATSIZE="32"
+BUILDTYPE="complete"
+SOURCEDIR="."
+PARTOFFSET="2048"
+DEFAULT_IMAGESIZE="976560" # default d-i FLOPPY_SIZE for hd-media images
+IMAGESIZE="${DEFAULT_IMAGESIZE}"
+COMPRESS="none"
+COMPRESS_OPTS=""
+VERBOSITY="0"
+PREREQUISITES="fmt sfdisk"
+PREREQUISITES_MISSING=""
+
+log()
+{
+  if [ "${VERBOSITY}" -gt 0 ]; then
+    echo "$(basename $0): $1"
+  fi
+}
+
+error()
+{
+  echo "$(basename $0): $1" 1>&2
+}
+
+clean_tempfiles()
+{
+  [ -f "${TEMP_FS_IMAGEFILE}" ] && rm -f "${TEMP_FS_IMAGEFILE}"
+  [ -f "${TEMP_HD_IMAGEFILE}" ] && rm -f "${TEMP_HD_IMAGEFILE}"
+}
+
+check_prerequisites()
+{
+  for TOOL in $1
+  do
+    which >/dev/null ${TOOL}
+    if [ ! "$?" -eq 0 ]; then
+      PREREQUISITES_MISSING="${PREREQUISITES_MISSING}${TOOL} "
+    fi
+  done
+  if [ -n "${PREREQUISITES_MISSING}" ]; then
+    error "ERROR: The following programs are unavailable, but required"
+    error "ERROR: for the selected options: ${PREREQUISITES_MISSING}"
+    error "ERROR: Exiting."
+    exit 1
+  fi
+}
+
+usage()
+{
+  fmt -w 75 -s <<EOF
+
+$(basename $0) - bootable harddisk image generator
+
+SYNOPSIS:
+
+$(basename $0) -o output_image_name [-s image_size] [-i sourcedir] [-t fstype] [-p partition_offset] [-b build_type] [-z|-j|-J] [-h] [[bootloader_image bootloader_offset] ...]
+
+DESCRIPTION:
+
+$(basename $0) generates harddisk images with a partition table and a
+single primary partition from a directory tree without requiring root
+privileges.  It optionally also installs firmware/bootloader
+binaries (usually u-boot) in the image area between the MBR and the
+first partition and allows to generate concatenateable partial images
+(only the MBR+firmware area or only the partition area).
+
+OPTIONS
+
+  -b build_type
+
+       Specify the type of image to build. Valid options are:
+
+       - complete:   complete harddisk image (MBR/firmware + partition)
+       - firmware:   only MBR/firmware/bootloader image
+       - partition:  only partition image
+
+       The default is building a complete harddisk image.
+
+  -h
+
+       Display this help text and exit.
+
+  -i sourcedir
+
+       Specify the source directory from which the filesystem in
+       the image should be generated.  The default is the current
+       directory.
+
+  -j
+
+       Compress the image with bzip2.
+
+  -J
+
+       Compress the image with xz.
+
+  -o output_image_name
+
+       Specify the name of the generated image. If one of the
+       compression options (-z/-j/-J) is selected, the according
+       suffix (.gz/.bz2/.xz) will be appended to the supplied
+       file name.
+
+  -p partition_offset
+
+       Specify the partition offset from the beginning of the
+       device in blocks of 512 Bytes.  The default is 2048, i.e.
+       the partition starts at an offset of 1 MB.
+
+  -s image_size
+
+       Specify the size of the complete harddisk image in kB.
+       When building partial images, the size of the parts is
+       calculated accordingly, so that the sum of the parts is
+       the specified image size.  The default image size is
+       ${DEFAULT_IMAGESIZE} kB.
+
+  -t fstype
+
+       Type of the filesystem to create in the harddisk image.
+       Available options are fat32 (default), fat16 and ext2.
+       Generating large ext2 images can be very slow (ca. 5
+       minutes for a 1GB image on a 1GHz Cortex-A7).
+
+  -v
+
+       Verbose output.
+
+  -z
+
+       Compress the image with gzip.
+
+The bootloader_image and bootloader_offset parameters specify which
+bootloader image should be installed at which offset (in blocks of 512
+Bytes) from the start of the harddisk image.  This parameter set can be
+used multiple times to install multi-part bootloader images (e.g.  to
+install u-boot versions with separate SPL images).
+
+EOF
+}
+
+# Parse parameters:
+# -h help
+# -i input directory
+# -o output filename
+# -s size of disk image
+# -t type of filesystem (fat16/fat32/ext2)
+# -p partition offset
+# -b build type (complete/firmware/partition)
+# -z/-j/-J gzip/bzip2/xz compression
+# -v verbose
+
+while getopts "hi:o:s:t:p:b:zjJv" option; do
+  case ${option} in
+    h)
+      usage
+      exit 0
+      ;;
+    i)
+      SOURCEDIR="${OPTARG}"
+      ;;
+    o)
+      IMAGEFILE="${OPTARG}"
+      ;;
+    s)
+      IMAGESIZE="${OPTARG}"
+      ;;
+    t)
+      FSTYPE="${OPTARG}"
+      case "${FSTYPE}" in
+        fat16)
+          PARTID="0x0e"
+          FATSIZE="16"
+          ;;
+        fat32)
+          PARTID="0x0c"
+          FATSIZE="32"
+          ;;
+        ext2)
+          PARTID="0x83"
+          ;;
+        *)
+          echo "$(basename $0): Invalid filesystem type \"${FSTYPE}\". Use fat16, fat32 or ext2."
+          exit 1
+          ;;
+      esac
+      ;;
+    p)
+      PARTOFFSET="${OPTARG}"
+      ;;
+    b)
+      BUILDTYPE="${OPTARG}"
+      case "${BUILDTYPE}" in
+        complete|firmware|partition)
+          ;;
+        *)
+          echo "$(basename $0): Invalid build type \"${BUILDTYPE}\". Use complete, firmware or partition."
+          exit 1
+          ;;
+      esac
+      ;;
+    z)
+      COMPRESS="gzip"
+      COMPRESS_OPTS="-n"
+      PREREQUISITES="${PREREQUISITES} gzip"
+      ;;
+    j)
+      COMPRESS="bzip2"
+      PREREQUISITES="${PREREQUISITES} bzip2"
+      ;;
+    J)
+      COMPRESS="xz"
+      PREREQUISITES="${PREREQUISITES} xz"
+      ;;
+    v)
+      VERBOSITY="1"
+      ;;
+  esac
+done
+
+shift $((${OPTIND}-1))
+
+case "${FSTYPE}" in
+  fat16|fat32)
+    PREREQUISITES="${PREREQUISITES} mkfs.msdos mcopy"
+    ;;
+  ext2)
+    PREREQUISITES="${PREREQUISITES} genext2fs"
+    ;;
+esac
+
+check_prerequisites "${PREREQUISITES}"
+
+FS_SIZE=$((${IMAGESIZE}-${PARTOFFSET}/2))
+if [ ${FS_SIZE} -lt 34816 ] && [ "${FSTYPE}" = "fat32" ]; then
+  error "INFO: Image size too small for FAT32, using FAT16."
+  FSTYPE="fat16"
+  PARTID="0x0e"
+  FATSIZE="16"
+fi
+if [ ${FS_SIZE} -gt 2097152 ] && [ "${FSTYPE}" = "fat16" ]; then
+  error "INFO: Image size too big for FAT16, using FAT32."
+  FSTYPE="fat32"
+  PARTID="0x0c"
+  FATSIZE="32"
+fi
+
+log "Starting to generate image ${IMAGEFILE} ..."
+
+case "${BUILDTYPE}" in
+  complete|firmware)
+    log "Building partition table ..."
+    TEMP_HD_IMAGEFILE=$(mktemp)
+    dd 2>/dev/null if=/dev/zero bs=1k of="${TEMP_HD_IMAGEFILE}" seek=$((${IMAGESIZE}-1)) count=1
+    sfdisk --force -u S "${TEMP_HD_IMAGEFILE}" 1>/dev/null 2>/dev/null <<EOF
+${PARTOFFSET}, ,${PARTID},*,
+EOF
+    while [ "$#" -ge "2" ]
+    do
+      if [ -n "$1" ]; then
+        BOOTLOADER_IMAGE="$1"
+        BOOTLOADER_OFFSET="$2"
+        log "Installing ${BOOTLOADER_IMAGE} at sector ${BOOTLOADER_OFFSET} ..."
+        dd 2>/dev/null if="${BOOTLOADER_IMAGE}" of="${TEMP_HD_IMAGEFILE}" bs=512 seek="${BOOTLOADER_OFFSET}" conv=notrunc
+      fi
+      shift 2
+    done
+    if [ "$#" -eq 1 ]; then
+      error "ERROR: Firmware/bootloader image name or offset missing. Exiting."
+      clean_tempfiles
+      exit 1
+    fi
+    ;;
+esac
+
+case "${BUILDTYPE}" in
+  complete|partition)
+    log "Building filesystem ..."
+    TEMP_FS_IMAGEFILE=$(mktemp)
+    TEMP_FS_IMAGESIZE=$((${IMAGESIZE}-${PARTOFFSET}/2)) # fs size in kB
+    dd 2>/dev/null if=/dev/zero bs=1k of="${TEMP_FS_IMAGEFILE}" seek=$((${TEMP_FS_IMAGESIZE}-1)) count=1
+    case "${FSTYPE}" in
+      fat16|fat32)
+        mkfs.msdos >/dev/null -F "${FATSIZE}" "${TEMP_FS_IMAGEFILE}" "${TEMP_FS_IMAGESIZE}"
+        mcopy -s -i "${TEMP_FS_IMAGEFILE}" ${SOURCEDIR}// ::
+        # The trailing // is necessary to make mcopy copy the contents
+        # of ${SOURCEDIR} but not ${SOURCEDIR} itself. Using ${SOURCEDIR}/*
+        # would omit dotfiles and ${SOURCEDIR}/. does not work with mcopy.
+        ;;
+      ext2)
+        genext2fs -z -U -d "${SOURCEDIR}" -b "${TEMP_FS_IMAGESIZE}" "${TEMP_FS_IMAGEFILE}"
+        ;;
+    esac
+    ;;
+esac
+
+case "${BUILDTYPE}" in
+  firmware)
+    dd 2>/dev/null if="${TEMP_HD_IMAGEFILE}" bs=512 count="${PARTOFFSET}" of="${IMAGEFILE}"
+    ;;
+  complete)
+    dd 2>/dev/null if="${TEMP_HD_IMAGEFILE}" bs=512 count="${PARTOFFSET}" of="${IMAGEFILE}"
+    cat "${TEMP_FS_IMAGEFILE}" >> "${IMAGEFILE}"
+    ;;
+  partition)
+    mv "${TEMP_FS_IMAGEFILE}" "${IMAGEFILE}"
+    ;;
+esac
+
+if [ ! "${COMPRESS}" = "none" ];
+then
+  log "Compressing image ..."
+  "${COMPRESS}" ${COMPRESS_OPTS} -f "${IMAGEFILE}"
+fi
+
+clean_tempfiles
+
+log "Image finished."
+
+exit 0
diff --git a/debian/changelog b/debian/changelog
index d81210a..4fafb44 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,8 @@ debian-installer (201410XX) UNRELEASED; urgency=medium
   * Add boot/arm/u-boot-image-config (a list of u-boot components and their
     offsets on disk, needed to create bootable images for arm-based systems).
   * Provide u-boot binaries for armhf systems without u-boot in flash.
+  * Add utils/gen-hd-image (a script to create partitioned harddisk images
+    from a directory and optionally install a bootloader into the image).
 
   [ Aurelien Jarno ]
   * Add scsi-modules to the cdrom flavour on ppc64el to be able to access
diff --git a/debian/control b/debian/control
index fbdb166..bf3a66d 100644
--- a/debian/control
+++ b/debian/control
@@ -68,11 +68,12 @@ Build-Depends:
 #		default.)
 	hfsutils [powerpc],
 #		For making bootable HFS USB sticks for powerpc.
-	dosfstools [i386 ia64 m68k amd64 arm64],
+	dosfstools [i386 ia64 m68k amd64 armhf arm64],
 #		For creating FAT filesystems with mkfs.msdos.
 #		Of course i386/amd64 use this for floppies, CDs etc.
 #		ia64 uses it for floppies (?)
 #		m68k uses it for atari floppies
+#		armhf uses it for building bootable SD card images
 	cpio,
 #		For creating initramfs images.
 	xz-utils,
@@ -133,12 +134,16 @@ Build-Depends:
 #		Used to make EFI bootable images
 	grub-ieee1275-bin [ppc64el],
 #		IEEE1275 bootloader support.
+	u-boot-imx [armhf],
+	u-boot-omap [armhf],
+	u-boot-sunxi [armhf],
+#		U-boot binaries, needed to build bootable SD card images.
 # 
 # Architecture specific build dependencies:
 	tofrodos [i386 amd64 kfreebsd-i386 kfreebsd-amd64],
 #		For todos, used on files that need to be accessible from
 #		DOS.
-	mtools [i386 ia64 m68k amd64 arm64 kfreebsd-i386 kfreebsd-amd64 hurd-i386],
+	mtools [i386 ia64 m68k amd64 armhf arm64 kfreebsd-i386 kfreebsd-amd64 hurd-i386],
 #		mcopy is used to put files onto FAT filesystems w/o
 #		mounting them.
 # 
diff --git a/debian/copyright b/debian/copyright
index a9bca6c..a733f34 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -25,3 +25,8 @@ a rebuilt-from-scratch "debian" word.
     build/boot/hurd/pics/joy-hurd.{svg,png}
     build/boot/kfreebsd/pics/joy-kbsd.{svg,png}
     build/boot/x86/pics/joy.{svg,png}
+
+The gen-hd-image tool, used to build bootable partitioned disk images, is
+Copyright 2014,2015 Karsten Merker <merker@debian.org> and is dual-licensed.
+It is provided under the terms of the GNU GPL version 2 or any later
+version, or alternatively under the terms of the X11 license.
-- 
2.1.4


Reply to: