toybox/scripts/mkroot.sh
<<
>>
Prefs
   1#!/bin/bash
   2
   3# Clear environment variables by restarting script w/bare minimum passed through
   4[ -z "$NOCLEAR" ] &&
   5  exec env -i NOCLEAR=1 HOME="$HOME" PATH="$PATH" LINUX="$LINUX" \
   6    CROSS_COMPILE="$CROSS_COMPILE" CROSS_SHORT="$CROSS_SHORT" "$0" "$@"
   7
   8# assign command line NAME=VALUE args to env vars
   9while [ $# -ne 0 ]
  10do
  11  X="${1/=*/}"
  12  Y="${1#*=}"
  13  [ "${1/=/}" != "$1" ] && eval "export $X=\"\$Y\"" || echo "unknown $i"
  14  shift
  15done
  16
  17# If we're cross compiling, set appropriate environment variables.
  18if [ -z "$CROSS_COMPILE" ]
  19then
  20  echo "Building natively"
  21  if ! cc --static -xc - -o /dev/null <<< "int main(void) {return 0;}"
  22  then
  23    echo "Warning: host compiler can't create static binaries." >&2
  24    sleep 3
  25  fi
  26else
  27  CROSS_PATH="$(dirname "$(which "${CROSS_COMPILE}cc")")"
  28  CROSS_BASE="$(basename "$CROSS_COMPILE")"
  29  [ -z "$CROSS_SHORT" ] && CROSS_SHORT="${CROSS_BASE/-*/}"
  30  echo "Cross compiling to $CROSS_SHORT"
  31  if [ -z "$CROSS_PATH" ]
  32  then
  33    echo "no ${CROSS_COMPILE}cc in path" >&2
  34    exit 1
  35  fi
  36fi
  37
  38# set up directories (can override most of these paths on cmdline)
  39TOP="$PWD/root"
  40[ -z "$BUILD" ] && BUILD="$TOP/build"
  41[ -z "$AIRLOCK" ] && AIRLOCK="$TOP/airlock"
  42[ -z "$OUTPUT" ] && OUTPUT="$TOP/${CROSS_SHORT:-host}"
  43[ -z "$ROOT" ] && ROOT="$OUTPUT/${CROSS_BASE}fs" && rm -rf "$ROOT"
  44MYBUILD="$BUILD/${CROSS_BASE:-host-}tmp"
  45rm -rf "$MYBUILD" && mkdir -p "$MYBUILD" || exit 1
  46
  47# Stabilize cross compiling by providing known $PATH contents
  48if [ ! -z "$CROSS_COMPILE" ]
  49then
  50  if [ ! -e "$AIRLOCK/toybox" ]
  51  then
  52    echo === Create airlock dir
  53
  54    PREFIX="$AIRLOCK" KCONFIG_CONFIG="$TOP"/.airlock CROSS_COMPILE= \
  55      make clean defconfig toybox install_airlock &&
  56    rm "$TOP"/.airlock || exit 1
  57  fi
  58  export PATH="$CROSS_PATH:$AIRLOCK"
  59fi
  60
  61### Create files and directories
  62mkdir -p "$ROOT"/{etc,tmp,proc,sys,dev,home,mnt,root,usr/{bin,sbin,lib},var} &&
  63chmod a+rwxt "$ROOT"/tmp && ln -s usr/{bin,sbin,lib} "$ROOT" || exit 1
  64
  65# init script. Runs as pid 1 from initramfs to set up and hand off system.
  66cat > "$ROOT"/init << 'EOF' &&
  67#!/bin/sh
  68
  69export HOME=/home
  70export PATH=/bin:/sbin
  71
  72mountpoint -q proc || mount -t proc proc proc
  73mountpoint -q sys || mount -t sysfs sys sys
  74if ! mountpoint -q dev
  75then
  76  mount -t devtmpfs dev dev || mdev -s
  77  mkdir -p dev/pts
  78  mountpoint -q dev/pts || mount -t devpts dev/pts dev/pts
  79fi
  80
  81if [ $$ -eq 1 ]
  82then
  83  # Setup networking for QEMU (needs /proc)
  84  ifconfig eth0 10.0.2.15
  85  route add default gw 10.0.2.2
  86  [ "$(date +%s)" -lt 1000 ] && rdate 10.0.2.2 # or time-b.nist.gov
  87  [ "$(date +%s)" -lt 10000000 ] && ntpd -nq -p north-america.pool.ntp.org
  88
  89  [ -z "$CONSOLE" ] &&
  90    CONSOLE="$(sed -n 's@.* console=\(/dev/\)*\([^ ]*\).*@\2@p' /proc/cmdline)"
  91
  92  [ -z "$HANDOFF" ] && HANDOFF=/bin/sh && echo Type exit when done.
  93  [ -z "$CONSOLE" ] && CONSOLE=console
  94  exec /sbin/oneit -c /dev/"$CONSOLE" $HANDOFF
  95else
  96  /bin/sh
  97  umount /dev/pts /dev /sys /proc
  98fi
  99EOF
 100chmod +x "$ROOT"/init &&
 101
 102# /etc/passwd with both kernel special accounts (root and nobody) + guest user
 103cat > "$ROOT"/etc/passwd << 'EOF' &&
 104root::0:0:root:/home/root:/bin/sh
 105guest:x:500:500:guest:/home/guest:/bin/sh
 106nobody:x:65534:65534:nobody:/proc/self:/dev/null
 107EOF
 108
 109# /etc/group with groups corresponding to each /etc/passwd user
 110cat > "$ROOT"/etc/group << 'EOF' &&
 111root:x:0:
 112guest:x:500:
 113nobody:x:65534:
 114EOF
 115
 116# /etc/resolv.conf using Google's public nameserver. (We could use QEMU's
 117# 10.0.2.2 forwarder here, but this way works in both chroot and QEMU.)
 118echo "nameserver 8.8.8.8" > "$ROOT"/etc/resolv.conf || exit 1
 119
 120# Build toybox
 121
 122make clean
 123if [ -z .config ]
 124then
 125  make defconfig
 126  # Work around musl-libc design flaw.
 127  [ "${CROSS_BASE/fdpic//}" != "$CROSS_BASE" ] &&
 128    sed -i 's/.*\(CONFIG_TOYBOX_MUSL_NOMMU_IS_BROKEN\).*/\1=y/' .config
 129else
 130  make silentoldconfig
 131fi
 132LDFLAGS=--static PREFIX="$ROOT" make toybox install || exit 1
 133
 134# Abort early if no kernel source specified
 135if [ -z "$LINUX" ] || [ ! -d "$LINUX/kernel" ]
 136then
 137  echo 'No $LINUX directory, kernel build skipped.'
 138  rmdir "$MYBUILD" "$BUILD" 2>/dev/null
 139  exit 0
 140fi
 141
 142# Which architecture are we building a kernel for?
 143[ -z "$TARGET" ] && TARGET="${CROSS_BASE/-*/}"
 144[ -z "$TARGET" ] && TARGET="$(uname -m)"
 145
 146# Target-specific info in an (alphabetical order) if/else staircase
 147# Each target needs board config, serial console, RTC, ethernet, block device.
 148
 149if [ "$TARGET" == armv5l ]
 150then
 151
 152  # This could use the same VIRT board as armv7, but let's demonstrate a
 153  # different one requiring a separate device tree binary.
 154  QEMU="qemu-system-arm -M versatilepb -net nic,model=rtl8139 -net user"
 155  KARCH=arm
 156  KARGS="console=ttyAMA0"
 157  VMLINUX=arch/arm/boot/zImage
 158  KERNEL_CONFIG="
 159CONFIG_CPU_ARM926T=y
 160CONFIG_MMU=y
 161CONFIG_VFP=y
 162CONFIG_ARM_THUMB=y
 163CONFIG_AEABI=y
 164CONFIG_ARCH_VERSATILE=y
 165
 166# The switch to device-tree-only added this mess
 167CONFIG_ATAGS=y
 168CONFIG_DEPRECATED_PARAM_STRUCT=y
 169CONFIG_ARM_ATAG_DTB_COMPAT=y
 170CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
 171
 172CONFIG_SERIAL_AMBA_PL011=y
 173CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 174
 175CONFIG_RTC_CLASS=y
 176CONFIG_RTC_DRV_PL031=y
 177CONFIG_RTC_HCTOSYS=y
 178
 179CONFIG_PCI=y
 180CONFIG_PCI_VERSATILE=y
 181CONFIG_BLK_DEV_SD=y
 182CONFIG_SCSI=y
 183CONFIG_SCSI_LOWLEVEL=y
 184CONFIG_SCSI_SYM53C8XX_2=y
 185CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 186CONFIG_SCSI_SYM53C8XX_MMIO=y
 187
 188CONFIG_NET_VENDOR_REALTEK=y
 189CONFIG_8139CP=y
 190"
 191  DTB=arch/arm/boot/dts/versatile-pb.dtb
 192elif [ "$TARGET" == armv7l ] || [ "$TARGET" == aarch64 ]
 193then
 194  if [ "$TARGET" == aarch64 ]
 195  then
 196    QEMU="qemu-system-aarch64 -M virt -cpu cortex-a57"
 197    KARCH=arm64
 198    VMLINUX=arch/arm64/boot/Image
 199  else
 200    QEMU="qemu-system-arm -M virt"
 201    KARCH=arm
 202    VMLINUX=arch/arm/boot/zImage
 203  fi
 204  KARGS="console=ttyAMA0"
 205  KERNEL_CONFIG="
 206CONFIG_MMU=y
 207CONFIG_ARCH_MULTI_V7=y
 208CONFIG_ARCH_VIRT=y
 209CONFIG_SOC_DRA7XX=y
 210CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
 211CONFIG_ARCH_ALPINE=y
 212CONFIG_ARM_THUMB=y
 213CONFIG_VDSO=y
 214CONFIG_CPU_IDLE=y
 215CONFIG_ARM_CPUIDLE=y
 216CONFIG_KERNEL_MODE_NEON=y
 217
 218CONFIG_SERIAL_AMBA_PL011=y
 219CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 220
 221CONFIG_RTC_CLASS=y
 222CONFIG_RTC_HCTOSYS=y
 223CONFIG_RTC_DRV_PL031=y
 224
 225CONFIG_NET_CORE=y
 226CONFIG_VIRTIO_MENU=y
 227CONFIG_VIRTIO_NET=y
 228
 229CONFIG_PCI=y
 230CONFIG_PCI_HOST_GENERIC=y
 231CONFIG_VIRTIO_BLK=y
 232CONFIG_VIRTIO_PCI=y
 233CONFIG_VIRTIO_MMIO=y
 234
 235CONFIG_ATA=y
 236CONFIG_ATA_SFF=y
 237CONFIG_ATA_BMDMA=y
 238CONFIG_ATA_PIIX=y
 239
 240CONFIG_PATA_PLATFORM=y
 241CONFIG_PATA_OF_PLATFORM=y
 242CONFIG_ATA_GENERIC=y
 243"
 244elif [ "$TARGET" == i486 ] || [ "$TARGET" == i686 ] ||
 245     [ "$TARGET" == x86_64 ] || [ "$TARGET" == x32 ]
 246then
 247  if [ "$TARGET" == i486 ]
 248  then
 249    QEMU="qemu-system-i386 -cpu 486 -global fw_cfg.dma_enabled=false"
 250    KERNEL_CONFIG="CONFIG_M486=y"
 251  elif [ "$TARGET" == i686 ]
 252  then
 253    QEMU="qemu-system-i386 -cpu pentium3"
 254    KERNEL_CONFIG="CONFIG_MPENTIUMII=y"
 255  else
 256    QEMU=qemu-system-x86_64
 257    KERNEL_CONFIG="CONFIG_64BIT=y"
 258    [ "$TARGET" == x32 ] && KERNEL_CONFIG="$KERNEL_CONFIG
 259CONFIG_X86_X32=y"
 260  fi
 261  KARCH=x86
 262  KARGS="console=ttyS0"
 263  VMLINUX=arch/x86/boot/bzImage
 264  CONFIG_MPENTIUMII=y
 265  KERNEL_CONFIG="
 266$KERNEL_CONFIG
 267
 268CONFIG_UNWINDER_FRAME_POINTER=y
 269
 270CONFIG_PCI=y
 271CONFIG_BLK_DEV_SD=y
 272CONFIG_ATA=y
 273CONFIG_ATA_SFF=y
 274CONFIG_ATA_BMDMA=y
 275CONFIG_ATA_PIIX=y
 276
 277CONFIG_NET_VENDOR_INTEL=y
 278CONFIG_E1000=y
 279CONFIG_SERIAL_8250=y
 280CONFIG_SERIAL_8250_CONSOLE=y
 281CONFIG_RTC_CLASS=y
 282"
 283elif [ "$TARGET" == mips ] || [ "$TARGET" == mipsel ]
 284then
 285  QEMU="qemu-system-mips -M malta"
 286  KARCH=mips
 287  KARGS="console=ttyS0"
 288  VMLINUX=vmlinux
 289  KERNEL_CONFIG="
 290CONFIG_MIPS_MALTA=y
 291CONFIG_CPU_MIPS32_R2=y
 292CONFIG_SERIAL_8250=y
 293CONFIG_SERIAL_8250_CONSOLE=y
 294
 295CONFIG_PCI=y
 296CONFIG_BLK_DEV_SD=y
 297CONFIG_ATA=y
 298CONFIG_ATA_SFF=y
 299CONFIG_ATA_BMDMA=y
 300CONFIG_ATA_PIIX=y
 301
 302CONFIG_NET_VENDOR_AMD=y
 303CONFIG_PCNET32=y
 304
 305CONFIG_POWER_RESET=y
 306CONFIG_POWER_RESET_SYSCON=y
 307"
 308  [ "$TARGET" == mipsel ] &&
 309    KERNEL_CONFIG="${KERNEL_CONFIG}CONFIG_CPU_LITTLE_ENDIAN=y" &&
 310    QEMU="qemu-system-mipsel -M malta"
 311elif [ "$TARGET" == powerpc ]
 312then
 313  KARCH=powerpc
 314  QEMU="qemu-system-ppc -M g3beige"
 315  KARGS="console=ttyS0"
 316  VMLINUX=vmlinux
 317  KERNEL_CONFIG="
 318CONFIG_ALTIVEC=y
 319CONFIG_PPC_PMAC=y
 320CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
 321
 322CONFIG_IDE=y
 323CONFIG_IDE_GD=y
 324CONFIG_IDE_GD_ATA=y
 325CONFIG_BLK_DEV_IDE_PMAC=y
 326CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 327
 328CONFIG_MACINTOSH_DRIVERS=y
 329CONFIG_ADB=y
 330CONFIG_ADB_CUDA=y
 331
 332CONFIG_NET_VENDOR_NATSEMI=y
 333CONFIG_NET_VENDOR_8390=y
 334CONFIG_NE2K_PCI=y
 335
 336CONFIG_SERIO=y
 337CONFIG_SERIAL_PMACZILOG=y
 338CONFIG_SERIAL_PMACZILOG_TTYS=y
 339CONFIG_SERIAL_PMACZILOG_CONSOLE=y
 340CONFIG_BOOTX_TEXT=y
 341"
 342elif [ "$TARGET" == powerpc64le ]
 343then
 344  KARCH=powerpc
 345  QEMU="qemu-system-ppc64 -M pseries -vga none"
 346  KARGS="console=/dev/hvc0"
 347  VMLINUX=vmlinux
 348  KERNEL_CONFIG="CONFIG_PPC64=y
 349CONFIG_PPC_PSERIES=y
 350CONFIG_CPU_LITTLE_ENDIAN=y
 351CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
 352
 353CONFIG_BLK_DEV_SD=y
 354CONFIG_SCSI_LOWLEVEL=y
 355CONFIG_SCSI_IBMVSCSI=y
 356CONFIG_ATA=y
 357
 358CONFIG_NET_VENDOR_IBM=y
 359CONFIG_IBMVETH=y
 360CONFIG_HVC_CONSOLE=y
 361
 362# None of this should be necessary
 363CONFIG_PPC_TRANSACTIONAL_MEM=y
 364CONFIG_PPC_DISABLE_WERROR=y
 365CONFIG_SECTION_MISMATCH_WARN_ONLY=y
 366"
 367elif [ "$TARGET" = s390x ]
 368then
 369  QEMU="qemu-system-s390x"
 370  KARCH=s390
 371  VMLINUX=arch/s390/boot/bzImage
 372  KERNEL_CONFIG="
 373CONFIG_MARCH_Z900=y
 374CONFIG_PACK_STACK=y
 375CONFIG_NET_CORE=y
 376CONFIG_VIRTIO_NET=y
 377CONFIG_VIRTIO_BLK=y
 378CONFIG_SCLP_TTY=y
 379CONFIG_SCLP_CONSOLE=y
 380CONFIG_SCLP_VT220_TTY=y
 381CONFIG_SCLP_VT220_CONSOLE=y
 382CONFIG_S390_GUEST=y
 383"
 384elif [ "$TARGET" == sh4 ]
 385then
 386  QEMU="qemu-system-sh4 -M r2d -serial null -serial mon:stdio"
 387  KARCH=sh
 388  KARGS="console=ttySC1 noiotrap"
 389  VMLINUX=arch/sh/boot/zImage
 390  KERNEL_CONFIG="
 391CONFIG_CPU_SUBTYPE_SH7751R=y
 392CONFIG_MMU=y
 393CONFIG_MEMORY_START=0x0c000000
 394CONFIG_VSYSCALL=y
 395CONFIG_SH_FPU=y
 396CONFIG_SH_RTS7751R2D=y
 397CONFIG_RTS7751R2D_PLUS=y
 398CONFIG_SERIAL_SH_SCI=y
 399CONFIG_SERIAL_SH_SCI_CONSOLE=y
 400
 401CONFIG_PCI=y
 402CONFIG_NET_VENDOR_REALTEK=y
 403CONFIG_8139CP=y
 404
 405CONFIG_PCI=y
 406CONFIG_BLK_DEV_SD=y
 407CONFIG_ATA=y
 408CONFIG_ATA_SFF=y
 409CONFIG_ATA_BMDMA=y
 410CONFIG_PATA_PLATFORM=y
 411
 412CONFIG_BINFMT_ELF_FDPIC=y
 413CONFIG_BINFMT_FLAT=y
 414
 415#CONFIG_SPI=y
 416#CONFIG_SPI_SH_SCI=y
 417#CONFIG_MFD_SM501=y
 418
 419#CONFIG_RTC_CLASS=y
 420#CONFIG_RTC_DRV_R9701=y
 421#CONFIG_RTC_DRV_SH=y
 422#CONFIG_RTC_HCTOSYS=y
 423"
 424else
 425  echo "Unknown \$TARGET"
 426  exit 1
 427fi
 428
 429# Write the miniconfig file
 430{
 431  echo "# make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=$TARGET.miniconf"
 432  echo "# make ARCH=$KARCH -j \$(nproc)"
 433  echo "# boot $VMLINUX"
 434  echo
 435  echo "$KERNEL_CONFIG"
 436
 437  # Generic options for all targets
 438
 439  echo "
 440# CONFIG_EMBEDDED is not set
 441CONFIG_EARLY_PRINTK=y
 442CONFIG_BINFMT_ELF=y
 443CONFIG_BINFMT_SCRIPT=y
 444CONFIG_NO_HZ=y
 445CONFIG_HIGH_RES_TIMERS=y
 446
 447CONFIG_BLK_DEV=y
 448CONFIG_BLK_DEV_INITRD=y
 449CONFIG_RD_GZIP=y
 450
 451CONFIG_BLK_DEV_LOOP=y
 452CONFIG_EXT4_FS=y
 453CONFIG_EXT4_USE_FOR_EXT2=y
 454CONFIG_VFAT_FS=y
 455CONFIG_FAT_DEFAULT_UTF8=y
 456CONFIG_MISC_FILESYSTEMS=y
 457CONFIG_SQUASHFS=y
 458CONFIG_SQUASHFS_XATTR=y
 459CONFIG_SQUASHFS_ZLIB=y
 460CONFIG_DEVTMPFS=y
 461CONFIG_DEVTMPFS_MOUNT=y
 462CONFIG_TMPFS=y
 463CONFIG_TMPFS_POSIX_ACL=y
 464
 465CONFIG_NET=y
 466CONFIG_PACKET=y
 467CONFIG_UNIX=y
 468CONFIG_INET=y
 469CONFIG_IPV6=y
 470CONFIG_NETDEVICES=y
 471#CONFIG_NET_CORE=y
 472#CONFIG_NETCONSOLE=y
 473CONFIG_ETHERNET=y
 474"
 475} > "$OUTPUT/miniconfig-$TARGET"
 476
 477# Write the qemu launch script
 478echo "$QEMU -nographic -no-reboot -m 256" \
 479     "-append \"panic=1 HOST=$TARGET $KARGS\"" \
 480     "-kernel $(basename "$VMLINUX") -initrd ${CROSS_BASE}root.cpio.gz" \
 481     ${DTB:+-dtb "$(basename "$DTB")"} '"$@"' \
 482     > "$OUTPUT/qemu-$TARGET.sh" &&
 483chmod +x "$OUTPUT/qemu-$TARGET.sh" &&
 484
 485echo "Build linux for $KARCH"
 486
 487# Snapshot Linux source dir and clean it
 488cp -sfR "$LINUX" "$MYBUILD/linux" && pushd "$MYBUILD/linux" > /dev/null ||
 489  exit 1
 490
 491# Build kernel
 492make distclean &&
 493make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTPUT/miniconfig-$TARGET" &&
 494make ARCH=$KARCH CROSS_COMPILE="$CROSS_COMPILE" -j $(nproc) || exit 1
 495
 496# If we have a device tree binary, save it for QEMU.
 497if [ ! -z "$DTB" ]
 498then
 499  cp "$DTB" "$OUTPUT/$(basename "$DTB")" || exit 1
 500fi
 501
 502cp "$VMLINUX" "$OUTPUT/$(basename "$VMLINUX")" && cd .. && rm -rf linux &&
 503  popd || exit 1
 504rmdir "$MYBUILD" "$BUILD" 2>/dev/null
 505
 506# package root filesystem for initramfs.
 507# we do it here so module install can add files (not implemented yet)
 508echo === create "${CROSS_BASE}root.cpio.gz"
 509
 510(cd "$ROOT" && find . | cpio -o -H newc | gzip) > \
 511  "$OUTPUT/${CROSS_BASE}root.cpio.gz"
 512