Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/sh
0002 # SPDX-License-Identifier: GPL-2.0-only
0003 
0004 # Copyright (C) 2006 Paul Mackerras, IBM Corporation <paulus@samba.org>
0005 
0006 # This script takes a kernel binary and optionally an initrd image
0007 # and/or a device-tree blob, and creates a bootable zImage for a
0008 # given platform.
0009 
0010 # Options:
0011 # -o zImage     specify output file
0012 # -p platform   specify platform (links in $platform.o)
0013 # -i initrd     specify initrd file
0014 # -d devtree    specify device-tree blob
0015 # -s tree.dts   specify device-tree source file (needs dtc installed)
0016 # -e esm_blob   specify ESM blob for secure images
0017 # -c            cache $kernel.strip.gz (use if present & newer, else make)
0018 # -C prefix     specify command prefix for cross-building tools
0019 #               (strip, objcopy, ld)
0020 # -D dir        specify directory containing data files used by script
0021 #               (default ./arch/powerpc/boot)
0022 # -W dir        specify working directory for temporary files (default .)
0023 # -z            use gzip (legacy)
0024 # -Z zsuffix    compression to use (gz, xz or none)
0025 
0026 # Stop execution if any command fails
0027 set -e
0028 
0029 export LC_ALL=C
0030 
0031 # Allow for verbose output
0032 if [ "$V" = 1 ]; then
0033     set -x
0034     map="-Map wrapper.map"
0035 fi
0036 
0037 # defaults
0038 kernel=
0039 ofile=zImage
0040 platform=of
0041 initrd=
0042 dtb=
0043 dts=
0044 esm_blob=
0045 cacheit=
0046 binary=
0047 compression=.gz
0048 uboot_comp=gzip
0049 pie=
0050 format=
0051 notext=
0052 rodynamic=
0053 
0054 # cross-compilation prefix
0055 CROSS=
0056 
0057 # mkimage wrapper script
0058 MKIMAGE=$srctree/scripts/mkuboot.sh
0059 
0060 # directory for object and other files used by this script
0061 object=arch/powerpc/boot
0062 objbin=$object
0063 dtc=scripts/dtc/dtc
0064 
0065 # directory for working files
0066 tmpdir=.
0067 
0068 usage() {
0069     echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
0070     echo '       [-d devtree] [-s tree.dts] [-e esm_blob]' >&2
0071     echo '       [-c] [-C cross-prefix] [-D datadir] [-W workingdir]' >&2
0072     echo '       [-Z (gz|xz|none)] [--no-compression] [vmlinux]' >&2
0073     exit 1
0074 }
0075 
0076 run_cmd() {
0077     if [ "$V" = 1 ]; then
0078         $* 2>&1
0079     else
0080         local msg
0081 
0082         set +e
0083         msg=$($* 2>&1)
0084 
0085         if [ $? -ne "0" ]; then
0086                 echo $msg
0087                 exit 1
0088         fi
0089         set -e
0090     fi
0091 }
0092 
0093 while [ "$#" -gt 0 ]; do
0094     case "$1" in
0095     -o)
0096         shift
0097         [ "$#" -gt 0 ] || usage
0098         ofile="$1"
0099         ;;
0100     -p)
0101         shift
0102         [ "$#" -gt 0 ] || usage
0103         platform="$1"
0104         ;;
0105     -i)
0106         shift
0107         [ "$#" -gt 0 ] || usage
0108         initrd="$1"
0109         ;;
0110     -d)
0111         shift
0112         [ "$#" -gt 0 ] || usage
0113         dtb="$1"
0114         ;;
0115     -e)
0116         shift
0117         [ "$#" -gt 0 ] || usage
0118         esm_blob="$1"
0119         ;;
0120     -s)
0121         shift
0122         [ "$#" -gt 0 ] || usage
0123         dts="$1"
0124         ;;
0125     -c)
0126         cacheit=y
0127         ;;
0128     -C)
0129         shift
0130         [ "$#" -gt 0 ] || usage
0131         CROSS="$1"
0132         ;;
0133     -D)
0134         shift
0135         [ "$#" -gt 0 ] || usage
0136         object="$1"
0137         objbin="$1"
0138         ;;
0139     -W)
0140         shift
0141         [ "$#" -gt 0 ] || usage
0142         tmpdir="$1"
0143         ;;
0144     -z)
0145         compression=.gz
0146         uboot_comp=gzip
0147         ;;
0148     -Z)
0149         shift
0150         [ "$#" -gt 0 ] || usage
0151         [ "$1" != "gz" -o "$1" != "xz" -o "$1" != "lzma" -o "$1" != "lzo" -o "$1" != "none" ] || usage
0152 
0153         compression=".$1"
0154         uboot_comp=$1
0155 
0156         if [ $compression = ".none" ]; then
0157                 compression=
0158                 uboot_comp=none
0159         fi
0160         if [ $uboot_comp = "gz" ]; then
0161                 uboot_comp=gzip
0162         fi
0163         ;;
0164     --no-gzip)
0165         # a "feature" of the wrapper script is that it can be used outside
0166         # the kernel tree. So keeping this around for backwards compatibility.
0167         compression=
0168         uboot_comp=none
0169         ;;
0170     -?)
0171         usage
0172         ;;
0173     *)
0174         [ -z "$kernel" ] || usage
0175         kernel="$1"
0176         ;;
0177     esac
0178     shift
0179 done
0180 
0181 
0182 if [ -n "$dts" ]; then
0183     if [ ! -r "$dts" -a -r "$object/dts/$dts" ]; then
0184         dts="$object/dts/$dts"
0185     fi
0186     if [ -z "$dtb" ]; then
0187         dtb="$platform.dtb"
0188     fi
0189     $dtc -O dtb -o "$dtb" -b 0 "$dts"
0190 fi
0191 
0192 if [ -z "$kernel" ]; then
0193     kernel=vmlinux
0194 fi
0195 
0196 LC_ALL=C elfformat="`${CROSS}objdump -p "$kernel" | grep 'file format' | awk '{print $4}'`"
0197 case "$elfformat" in
0198     elf64-powerpcle)    format=elf64lppc        ;;
0199     elf64-powerpc)      format=elf32ppc ;;
0200     elf32-powerpc)      format=elf32ppc ;;
0201 esac
0202 
0203 ld_version()
0204 {
0205     # Poached from scripts/ld-version.sh, but we don't want to call that because
0206     # this script (wrapper) is distributed separately from the kernel source.
0207     # Extract linker version number from stdin and turn into single number.
0208     awk '{
0209         gsub(".*\\)", "");
0210         gsub(".*version ", "");
0211         gsub("-.*", "");
0212         split($1,a, ".");
0213         print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
0214         exit
0215     }'
0216 }
0217 
0218 # Do not include PT_INTERP segment when linking pie. Non-pie linking
0219 # just ignores this option.
0220 LD_VERSION=$(${CROSS}ld --version | ld_version)
0221 LD_NO_DL_MIN_VERSION=$(echo 2.26 | ld_version)
0222 if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VERSION" ] ; then
0223         nodl="--no-dynamic-linker"
0224 fi
0225 
0226 platformo=$object/"$platform".o
0227 lds=$object/zImage.lds
0228 ext=strip
0229 objflags=-S
0230 tmp=$tmpdir/zImage.$$.o
0231 ksection=.kernel:vmlinux.strip
0232 isection=.kernel:initrd
0233 esection=.kernel:esm_blob
0234 link_address='0x400000'
0235 make_space=y
0236 
0237 
0238 if [ -n "$esm_blob" -a "$platform" != "pseries" ]; then
0239     echo "ESM blob not support on non-pseries platforms" >&2
0240     exit 1
0241 fi
0242 
0243 case "$platform" in
0244 of)
0245     platformo="$object/of.o $object/epapr.o"
0246     make_space=n
0247     ;;
0248 pseries)
0249     platformo="$object/pseries-head.o $object/of.o $object/epapr.o"
0250     link_address='0x4000000'
0251     if [ "$format" != "elf32ppc" ]; then
0252         link_address=
0253         pie=-pie
0254     fi
0255     make_space=n
0256     ;;
0257 maple)
0258     platformo="$object/of.o $object/epapr.o"
0259     link_address='0x400000'
0260     make_space=n
0261     ;;
0262 pmac|chrp)
0263     platformo="$object/of.o $object/epapr.o"
0264     make_space=n
0265     ;;
0266 coff)
0267     platformo="$object/crt0.o $object/of.o $object/epapr.o"
0268     lds=$object/zImage.coff.lds
0269     link_address='0x500000'
0270     make_space=n
0271     pie=
0272     ;;
0273 miboot|uboot*)
0274     # miboot and U-boot want just the bare bits, not an ELF binary
0275     ext=bin
0276     objflags="-O binary"
0277     tmp="$ofile"
0278     ksection=image
0279     isection=initrd
0280     ;;
0281 cuboot*)
0282     binary=y
0283     compression=
0284     case "$platform" in
0285     *-mpc866ads|*-mpc885ads|*-adder875*|*-ep88xc)
0286         platformo=$object/cuboot-8xx.o
0287         ;;
0288     *5200*|*-motionpro)
0289         platformo=$object/cuboot-52xx.o
0290         ;;
0291     *-pq2fads|*-ep8248e|*-mpc8272*|*-storcenter)
0292         platformo=$object/cuboot-pq2.o
0293         ;;
0294     *-mpc824*)
0295         platformo=$object/cuboot-824x.o
0296         ;;
0297     *-mpc83*|*-asp834x*)
0298         platformo=$object/cuboot-83xx.o
0299         ;;
0300     *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555|*-ksi8560*)
0301         platformo=$object/cuboot-85xx-cpm2.o
0302         ;;
0303     *-mpc85*|*-tqm85*)
0304         platformo=$object/cuboot-85xx.o
0305         ;;
0306     *-amigaone)
0307         link_address='0x800000'
0308         ;;
0309     esac
0310     ;;
0311 ps3)
0312     platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
0313     lds=$object/zImage.ps3.lds
0314     compression=
0315     ext=bin
0316     objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
0317     ksection=.kernel:vmlinux.bin
0318     isection=.kernel:initrd
0319     link_address=''
0320     make_space=n
0321     pie=
0322     ;;
0323 ep88xc|ep405|ep8248e)
0324     platformo="$object/fixed-head.o $object/$platform.o"
0325     binary=y
0326     ;;
0327 adder875-redboot)
0328     platformo="$object/fixed-head.o $object/redboot-8xx.o"
0329     binary=y
0330     ;;
0331 simpleboot-*)
0332     platformo="$object/fixed-head.o $object/simpleboot.o"
0333     binary=y
0334     ;;
0335 asp834x-redboot)
0336     platformo="$object/fixed-head.o $object/redboot-83xx.o"
0337     binary=y
0338     ;;
0339 xpedite52*)
0340     link_address='0x1400000'
0341     platformo=$object/cuboot-85xx.o
0342     ;;
0343 gamecube|wii)
0344     link_address='0x600000'
0345     platformo="$object/$platform-head.o $object/$platform.o"
0346     ;;
0347 microwatt)
0348     link_address='0x500000'
0349     platformo="$object/fixed-head.o $object/$platform.o"
0350     binary=y
0351     ;;
0352 treeboot-currituck)
0353     link_address='0x1000000'
0354     ;;
0355 treeboot-akebono)
0356     link_address='0x1000000'
0357     ;;
0358 treeboot-iss4xx-mpic)
0359     platformo="$object/treeboot-iss4xx.o"
0360     ;;
0361 epapr)
0362     platformo="$object/pseries-head.o $object/epapr.o $object/epapr-wrapper.o"
0363     link_address='0x20000000'
0364     pie=-pie
0365     notext='-z notext'
0366     rodynamic=$(if ${CROSS}ld -V 2>&1 | grep -q LLD ; then echo "-z rodynamic"; fi)
0367     ;;
0368 mvme5100)
0369     platformo="$object/fixed-head.o $object/mvme5100.o"
0370     binary=y
0371     ;;
0372 mvme7100)
0373     platformo="$object/motload-head.o $object/mvme7100.o"
0374     link_address='0x4000000'
0375     binary=y
0376     ;;
0377 esac
0378 
0379 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
0380 
0381 # Calculate the vmlinux.strip size
0382 ${CROSS}objcopy $objflags "$kernel" "$vmz.$$"
0383 strip_size=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" "$vmz.$$")
0384 
0385 if [ -z "$cacheit" -o ! -f "$vmz$compression" -o "$vmz$compression" -ot "$kernel" ]; then
0386     # recompress the image if we need to
0387     case $compression in
0388     .xz)
0389         xz --check=crc32 -f -6 "$vmz.$$"
0390         ;;
0391     .gz)
0392         gzip -n -f -9 "$vmz.$$"
0393         ;;
0394     .lzma)
0395         xz --format=lzma -f -6 "$vmz.$$"
0396         ;;
0397     .lzo)
0398         lzop -f -9 "$vmz.$$"
0399         ;;
0400     *)
0401         # drop the compression suffix so the stripped vmlinux is used
0402         compression=
0403         uboot_comp=none
0404         ;;
0405     esac
0406 
0407     if [ -n "$cacheit" ]; then
0408         mv -f "$vmz.$$$compression" "$vmz$compression"
0409     else
0410         vmz="$vmz.$$"
0411     fi
0412 else
0413     rm -f $vmz.$$
0414 fi
0415 
0416 vmz="$vmz$compression"
0417 
0418 if [ "$make_space" = "y" ]; then
0419         # Round the size to next higher MB limit
0420         round_size=$(((strip_size + 0xfffff) & 0xfff00000))
0421 
0422         round_size=0x$(printf "%x" $round_size)
0423         link_addr=$(printf "%d" $link_address)
0424 
0425         if [ $link_addr -lt $strip_size ]; then
0426             echo "INFO: Uncompressed kernel (size 0x$(printf "%x\n" $strip_size))" \
0427                         "overlaps the address of the wrapper($link_address)"
0428             echo "INFO: Fixing the link_address of wrapper to ($round_size)"
0429             link_address=$round_size
0430         fi
0431 fi
0432 
0433 # Extract kernel version information, some platforms want to include
0434 # it in the image header
0435 version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
0436     cut -d' ' -f3`
0437 if [ -n "$version" ]; then
0438     uboot_version="-n Linux-$version"
0439 fi
0440 
0441 # physical offset of kernel image
0442 membase=`${CROSS}objdump -p "$kernel" | grep -m 1 LOAD | awk '{print $7}'`
0443 
0444 case "$platform" in
0445 uboot)
0446     rm -f "$ofile"
0447     ${MKIMAGE} -A ppc -O linux -T kernel -C $uboot_comp -a $membase -e $membase \
0448         $uboot_version -d "$vmz" "$ofile"
0449     if [ -z "$cacheit" ]; then
0450         rm -f "$vmz"
0451     fi
0452     exit 0
0453     ;;
0454 uboot-obs600)
0455     rm -f "$ofile"
0456     # obs600 wants a multi image with an initrd, so we need to put a fake
0457     # one in even when building a "normal" image.
0458     if [ -n "$initrd" ]; then
0459         real_rd="$initrd"
0460     else
0461         real_rd=`mktemp`
0462         echo "\0" >>"$real_rd"
0463     fi
0464     ${MKIMAGE} -A ppc -O linux -T multi -C gzip -a $membase -e $membase \
0465         $uboot_version -d "$vmz":"$real_rd":"$dtb" "$ofile"
0466     if [ -z "$initrd" ]; then
0467         rm -f "$real_rd"
0468     fi
0469     if [ -z "$cacheit" ]; then
0470         rm -f "$vmz"
0471     fi
0472     exit 0
0473     ;;
0474 esac
0475 
0476 addsec() {
0477     ${CROSS}objcopy $4 $1 \
0478         --add-section=$3="$2" \
0479         --set-section-flags=$3=contents,alloc,load,readonly,data
0480 }
0481 
0482 addsec $tmp "$vmz" $ksection $object/empty.o
0483 if [ -z "$cacheit" ]; then
0484     rm -f "$vmz"
0485 fi
0486 
0487 if [ -n "$initrd" ]; then
0488     addsec $tmp "$initrd" $isection
0489 fi
0490 
0491 if [ -n "$dtb" ]; then
0492     addsec $tmp "$dtb" .kernel:dtb
0493     if [ -n "$dts" ]; then
0494         rm $dtb
0495     fi
0496 fi
0497 
0498 if [ -n "$esm_blob" ]; then
0499     addsec $tmp "$esm_blob" $esection
0500 fi
0501 
0502 if [ "$platform" != "miboot" ]; then
0503     if [ -n "$link_address" ] ; then
0504         text_start="-Ttext $link_address"
0505     fi
0506 #link everything
0507     ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $rodynamic $notext -o "$ofile" $map \
0508         $platformo $tmp $object/wrapper.a
0509     rm $tmp
0510 fi
0511 
0512 # Some platforms need the zImage's entry point and base address
0513 base=0x`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
0514 entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | cut -d' ' -f3`
0515 
0516 if [ -n "$binary" ]; then
0517     mv "$ofile" "$ofile".elf
0518     ${CROSS}objcopy -O binary "$ofile".elf "$ofile"
0519 fi
0520 
0521 # post-processing needed for some platforms
0522 case "$platform" in
0523 pseries|chrp|maple)
0524     $objbin/addnote "$ofile"
0525     ;;
0526 coff)
0527     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
0528     $objbin/hack-coff "$ofile"
0529     ;;
0530 cuboot*)
0531     gzip -n -f -9 "$ofile"
0532     ${MKIMAGE} -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
0533             $uboot_version -d "$ofile".gz "$ofile"
0534     ;;
0535 treeboot*)
0536     mv "$ofile" "$ofile.elf"
0537     $objbin/mktree "$ofile.elf" "$ofile" "$base" "$entry"
0538     if [ -z "$cacheit" ]; then
0539         rm -f "$ofile.elf"
0540     fi
0541     exit 0
0542     ;;
0543 ps3)
0544     # The ps3's loader supports loading a gzipped binary image from flash
0545     # rom to ram addr zero. The loader then enters the system reset
0546     # vector at addr 0x100.  A bootwrapper overlay is used to arrange for
0547     # a binary image of the kernel to be at addr zero, and yet have a
0548     # suitable bootwrapper entry at 0x100.  To construct the final rom
0549     # image 512 bytes from offset 0x100 is copied to the bootwrapper
0550     # place holder at symbol __system_reset_kernel.  The 512 bytes of the
0551     # bootwrapper entry code at symbol __system_reset_overlay is then
0552     # copied to offset 0x100.  At runtime the bootwrapper program copies
0553     # the data at __system_reset_kernel back to addr 0x100.
0554 
0555     system_reset_overlay=0x`${CROSS}nm "$ofile" \
0556         | grep ' __system_reset_overlay$'       \
0557         | cut -d' ' -f1`
0558     system_reset_overlay=`printf "%d" $system_reset_overlay`
0559     system_reset_kernel=0x`${CROSS}nm "$ofile" \
0560         | grep ' __system_reset_kernel$'       \
0561         | cut -d' ' -f1`
0562     system_reset_kernel=`printf "%d" $system_reset_kernel`
0563     overlay_dest="256"
0564     overlay_size="512"
0565 
0566     ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
0567 
0568     run_cmd dd if="$ofile.bin" of="$ofile.bin" conv=notrunc   \
0569         skip=$overlay_dest seek=$system_reset_kernel          \
0570         count=$overlay_size bs=1
0571 
0572     run_cmd dd if="$ofile.bin" of="$ofile.bin" conv=notrunc   \
0573         skip=$system_reset_overlay seek=$overlay_dest         \
0574         count=$overlay_size bs=1
0575 
0576     odir="$(dirname "$ofile.bin")"
0577 
0578     # The ps3's flash loader has a size limit of 16 MiB for the uncompressed
0579     # image.  If a compressed image that exceeded this limit is written to
0580     # flash the loader will decompress that image until the 16 MiB limit is
0581     # reached, then enter the system reset vector of the partially decompressed
0582     # image.  No warning is issued.
0583     rm -f "$odir"/{otheros,otheros-too-big}.bld
0584     size=$(${CROSS}nm --no-sort --radix=d "$ofile" | egrep ' _end$' | cut -d' ' -f1)
0585     bld="otheros.bld"
0586     if [ $size -gt $((0x1000000)) ]; then
0587         bld="otheros-too-big.bld"
0588     fi
0589     gzip -n --force -9 --stdout "$ofile.bin" > "$odir/$bld"
0590     ;;
0591 esac