Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 #
0003 # This file is subject to the terms and conditions of the GNU General Public
0004 # License.  See the file "COPYING" in the main directory of this archive
0005 # for more details.
0006 #
0007 # Copyright (C) 2017 by Changbin Du <changbin.du@intel.com>
0008 #
0009 # Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others
0010 #
0011 # "make fdimage/fdimage144/fdimage288/hdimage/isoimage"
0012 # script for x86 architecture
0013 #
0014 # Arguments:
0015 #   $1  - fdimage format
0016 #   $2  - target image file
0017 #   $3  - kernel bzImage file
0018 #   $4  - mtools configuration file
0019 #   $5  - kernel cmdline
0020 #   $6+ - initrd image file(s)
0021 #
0022 # This script requires:
0023 #   bash
0024 #   syslinux
0025 #   mtools (for fdimage* and hdimage)
0026 #   edk2/OVMF (for hdimage)
0027 #
0028 # Otherwise try to stick to POSIX shell commands...
0029 #
0030 
0031 # Use "make V=1" to debug this script
0032 case "${KBUILD_VERBOSE}" in
0033 *1*)
0034         set -x
0035         ;;
0036 esac
0037 
0038 # Exit the top-level shell with an error
0039 topshell=$$
0040 trap 'exit 1' USR1
0041 die() {
0042         echo ""        1>&2
0043         echo " *** $*" 1>&2
0044         echo ""        1>&2
0045         kill -USR1 $topshell
0046 }
0047 
0048 # Verify the existence and readability of a file
0049 verify() {
0050         if [ ! -f "$1" -o ! -r "$1" ]; then
0051                 die "Missing file: $1"
0052         fi
0053 }
0054 
0055 diskfmt="$1"
0056 FIMAGE="$2"
0057 FBZIMAGE="$3"
0058 MTOOLSRC="$4"
0059 KCMDLINE="$5"
0060 shift 5                         # Remaining arguments = initrd files
0061 
0062 export MTOOLSRC
0063 
0064 # common options for dd
0065 dd='dd iflag=fullblock'
0066 
0067 # Make sure the files actually exist
0068 verify "$FBZIMAGE"
0069 
0070 declare -a FDINITRDS
0071 irdpfx=' initrd='
0072 initrdopts_syslinux=''
0073 initrdopts_efi=''
0074 for f in "$@"; do
0075         if [ -f "$f" -a -r "$f" ]; then
0076             FDINITRDS=("${FDINITRDS[@]}" "$f")
0077             fname="$(basename "$f")"
0078             initrdopts_syslinux="${initrdopts_syslinux}${irdpfx}${fname}"
0079             irdpfx=,
0080             initrdopts_efi="${initrdopts_efi} initrd=${fname}"
0081         fi
0082 done
0083 
0084 # Read a $3-byte littleendian unsigned value at offset $2 from file $1
0085 le() {
0086         local n=0
0087         local m=1
0088         for b in $(od -A n -v -j $2 -N $3 -t u1 "$1"); do
0089                 n=$((n + b*m))
0090                 m=$((m * 256))
0091         done
0092         echo $n
0093 }
0094 
0095 # Get the EFI architecture name such that boot{name}.efi is the default
0096 # boot file name. Returns false with no output if the file is not an
0097 # EFI image or otherwise unknown.
0098 efiarch() {
0099         [ -f "$1" ] || return
0100         [ $(le "$1" 0 2) -eq 23117 ] || return          # MZ magic
0101         peoffs=$(le "$1" 60 4)                          # PE header offset
0102         [ $peoffs -ge 64 ] || return
0103         [ $(le "$1" $peoffs 4) -eq 17744 ] || return    # PE magic
0104         case $(le "$1" $((peoffs+4+20)) 2) in           # PE type
0105                 267)    ;;                              # PE32
0106                 523)    ;;                              # PE32+
0107                 *) return 1 ;;                          # Invalid
0108         esac
0109         [ $(le "$1" $((peoffs+4+20+68)) 2) -eq 10 ] || return # EFI app
0110         case $(le "$1" $((peoffs+4)) 2) in              # Machine type
0111                  332)   echo i386       ;;
0112                  450)   echo arm        ;;
0113                  512)   echo ia64       ;;
0114                 20530)  echo riscv32    ;;
0115                 20580)  echo riscv64    ;;
0116                 20776)  echo riscv128   ;;
0117                 34404)  echo x64        ;;
0118                 43620)  echo aa64       ;;
0119         esac
0120 }
0121 
0122 # Get the combined sizes in bytes of the files given, counting sparse
0123 # files as full length, and padding each file to cluster size
0124 cluster=16384
0125 filesizes() {
0126         local t=0
0127         local s
0128         for s in $(ls -lnL "$@" 2>/dev/null | awk '/^-/{ print $5; }'); do
0129                 t=$((t + ((s+cluster-1)/cluster)*cluster))
0130         done
0131         echo $t
0132 }
0133 
0134 # Expand directory names which should be in /usr/share into a list
0135 # of possible alternatives
0136 sharedirs() {
0137         local dir file
0138         for dir in /usr/share /usr/lib64 /usr/lib; do
0139                 for file; do
0140                         echo "$dir/$file"
0141                         echo "$dir/${file^^}"
0142                 done
0143         done
0144 }
0145 efidirs() {
0146         local dir file
0147         for dir in /usr/share /boot /usr/lib64 /usr/lib; do
0148                 for file; do
0149                         echo "$dir/$file"
0150                         echo "$dir/${file^^}"
0151                 done
0152         done
0153 }
0154 
0155 findsyslinux() {
0156         local f="$(find -L $(sharedirs syslinux isolinux) \
0157                     -name "$1" -readable -type f -print -quit 2>/dev/null)"
0158         if [ ! -f "$f" ]; then
0159                 die "Need a $1 file, please install syslinux/isolinux."
0160         fi
0161         echo "$f"
0162         return 0
0163 }
0164 
0165 findovmf() {
0166         local arch="$1"
0167         shift
0168         local -a names=(-false)
0169         local name f
0170         for name; do
0171                 names=("${names[@]}" -or -iname "$name")
0172         done
0173         for f in $(find -L $(efidirs edk2 ovmf) \
0174                         \( "${names[@]}" \) -readable -type f \
0175                         -print 2>/dev/null); do
0176                 if [ "$(efiarch "$f")" = "$arch" ]; then
0177                         echo "$f"
0178                         return 0
0179                 fi
0180         done
0181         die "Need a $1 file for $arch, please install EDK2/OVMF."
0182 }
0183 
0184 do_mcopy() {
0185         if [ ${#FDINITRDS[@]} -gt 0 ]; then
0186                 mcopy "${FDINITRDS[@]}" "$1"
0187         fi
0188         if [ -n "$efishell" ]; then
0189                 mmd "$1"EFI "$1"EFI/Boot
0190                 mcopy "$efishell" "$1"EFI/Boot/boot${kefiarch}.efi
0191         fi
0192         if [ -n "$kefiarch" ]; then
0193                 echo linux "$KCMDLINE$initrdopts_efi" | \
0194                         mcopy - "$1"startup.nsh
0195         fi
0196         echo default linux "$KCMDLINE$initrdopts_syslinux" | \
0197                 mcopy - "$1"syslinux.cfg
0198         mcopy "$FBZIMAGE" "$1"linux
0199 }
0200 
0201 genbzdisk() {
0202         verify "$MTOOLSRC"
0203         mformat -v 'LINUX_BOOT' a:
0204         syslinux "$FIMAGE"
0205         do_mcopy a:
0206 }
0207 
0208 genfdimage144() {
0209         verify "$MTOOLSRC"
0210         $dd if=/dev/zero of="$FIMAGE" bs=1024 count=1440 2>/dev/null
0211         mformat -v 'LINUX_BOOT' v:
0212         syslinux "$FIMAGE"
0213         do_mcopy v:
0214 }
0215 
0216 genfdimage288() {
0217         verify "$MTOOLSRC"
0218         $dd if=/dev/zero of="$FIMAGE" bs=1024 count=2880 2>/dev/null
0219         mformat -v 'LINUX_BOOT' w:
0220         syslinux "$FIMAGE"
0221         do_mcopy w:
0222 }
0223 
0224 genhdimage() {
0225         verify "$MTOOLSRC"
0226         mbr="$(findsyslinux mbr.bin)"
0227         kefiarch="$(efiarch "$FBZIMAGE")"
0228         if [ -n "$kefiarch" ]; then
0229                 # The efishell provides command line handling
0230                 efishell="$(findovmf $kefiarch shell.efi shell${kefiarch}.efi)"
0231                 ptype='-T 0xef' # EFI system partition, no GPT
0232         fi
0233         sizes=$(filesizes "$FBZIMAGE" "${FDINITRDS[@]}" "$efishell")
0234         # Allow 1% + 2 MiB for filesystem and partition table overhead,
0235         # syslinux, and config files; this is probably excessive...
0236         megs=$(((sizes + sizes/100 + 2*1024*1024 - 1)/(1024*1024)))
0237         $dd if=/dev/zero of="$FIMAGE" bs=$((1024*1024)) count=$megs 2>/dev/null
0238         mpartition -I -c -s 32 -h 64 $ptype -b 64 -a p:
0239         $dd if="$mbr" of="$FIMAGE" bs=440 count=1 conv=notrunc 2>/dev/null
0240         mformat -v 'LINUX_BOOT' -s 32 -h 64 -c $((cluster/512)) -t $megs h:
0241         syslinux --offset $((64*512)) "$FIMAGE"
0242         do_mcopy h:
0243 }
0244 
0245 geniso() {
0246         tmp_dir="$(dirname "$FIMAGE")/isoimage"
0247         rm -rf "$tmp_dir"
0248         mkdir "$tmp_dir"
0249         isolinux=$(findsyslinux isolinux.bin)
0250         ldlinux=$(findsyslinux  ldlinux.c32)
0251         cp "$isolinux" "$ldlinux" "$tmp_dir"
0252         cp "$FBZIMAGE" "$tmp_dir"/linux
0253         echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg
0254         cp "${FDINITRDS[@]}" "$tmp_dir"/
0255         genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \
0256                     -quiet -o "$FIMAGE" -b isolinux.bin \
0257                     -c boot.cat -no-emul-boot -boot-load-size 4 \
0258                     -boot-info-table "$tmp_dir"
0259         isohybrid "$FIMAGE" 2>/dev/null || true
0260         rm -rf "$tmp_dir"
0261 }
0262 
0263 rm -f "$FIMAGE"
0264 
0265 case "$diskfmt" in
0266         bzdisk)     genbzdisk;;
0267         fdimage144) genfdimage144;;
0268         fdimage288) genfdimage288;;
0269         hdimage)    genhdimage;;
0270         isoimage)   geniso;;
0271         *)          die "Unknown image format: $diskfmt";;
0272 esac