diff --git a/bootfiles/build b/bootfiles/build
new file mode 100644
index 0000000..7074793
--- /dev/null
+++ b/bootfiles/build
@@ -0,0 +1,231 @@
+#!/bin/bash
+
+# Linux Live Kit Improved v1.0
+# Original version: Linux Live Kit version 7
+# Modified/improved by: @johndah4x0r [terencedoesmc12 AT gmail DOT com]
+
+# Environment path
+export PATH="${PATH}:.:./tools:../tools"
+source ./.config || exit 1
+source ./livekitlib || exit 1
+
+# only root can continue, because only root can read all files from your system
+allow_only_root
+
+# Change directory to build environment
+CHANGEDIR="$(dirname $0)"
+echo "Changing current directory to $CHANGEDIR"
+CWD="$(pwd)"
+cd "$CHANGEDIR"
+
+
+# It's building time!
+clear
+
+echo_sign "BUILD SCRIPT"
+echo_livekit_msg "build: Doing a self-check..."
+
+# Start with 0 errors
+ERRS=0
+
+# Check if mksquashfs supports XZ compression
+if [ -z "$(mksquashfs 2>&1 | grep "Xdict-size")" ]; then
+ echo_err "build: 'mksquashfs': not-avail / not-supported"
+ (( ERRS+=1 ))
+else
+ echo_livekit_msg "build: 'mksquashfs': avail + supported"
+fi
+
+# Check if either 'mkisofs' or 'genisoimage' exists
+MKISOFS="$(which mkisofs 2>/dev/null || \
+which genisoimage 2>/dev/null)"
+if [ -z "$MKISOFS" ]; then
+ echo_err "build: 'mkisofs' / 'genisoimage': not-avail"
+
+ # Hahaha! 'false'?!?!?
+ MKISOFS="false"
+else
+ echo_livekit_msg "build: '$(basename $MKISOFS)': avail"
+fi
+
+# Check if we have 'zip'
+ZIP_CMD="$(which zip 2>/dev/null)"
+if [ -z "$ZIP_CMD" ]; then
+ # since a ZIP archive is the core, we have to go to fatal mode!
+ echo_fatal "build: 'zip': not-avail"
+ echo_fatal "build: 'zip': Critically needed!"
+ (( ERRS+= 2 ))
+else
+ echo_livekit_msg "build: 'zip': avail"
+fi
+
+
+if [ $ERRS -eq 0 ]; then
+ echo_livekit_msg "build: Problems found: $ERRS"
+ echo_livekit_msg "build: Self-check passed."
+else
+ echo_err "build: Problems found: $ERRS"
+ echo_err "build: Self-check failed!"
+ echo_err "build: Please make sure that you have all needed packages installed!"
+ exit 1
+fi
+
+echo_livekit_msg "build: Preparing to build..."
+clear
+
+echo " ==========================================="
+echo " Linux Live Kit version 2.0 (improved)"
+echo " ==========================================="
+echo " Live Kit information:"
+echo " > Kernel version: $KERNEL"
+echo " > Architecture: $ARCH"
+echo " > Live Kit name: $LIVEKITNAME"
+echo " > Bundle extension: '.$BEXT'"
+
+read -p "Press Enter to continue or press Ctrl-C to cancel... " junk
+
+# It's time to rock 'n roll!
+clear
+
+# Generate initramfs image (cpio-xz archive)
+echo_livekit_msg "build: Generating initramfs CPIO-XZ image..."
+
+cd initramfs
+INITRAMFS="$(./gen-initramfs "$LIVEKITNAME")"
+cd ..
+
+# Prepare the Live Kit archive
+rm -Rf "$LIVEKITDATA"
+echo_livekit_msg "build: Preparing boot files..."
+BOOT="$LIVEKITDATA"/"$LIVEKITNAME"/boot
+mkdir -p "$BOOT"
+mkdir -p "$BOOT"/../changes
+mkdir -p "$BOOT"/../bundles
+mv "$INITRAMFS" $BOOT/initramfs.img
+cp bootfiles/* $BOOT
+
+# do substitution
+cat bootfiles/syslinux.cfg | sed -r "s:/boot/:/$LIVEKITNAME/boot/:" | \
+sed -r "s:MyLinux:$LIVEKITNAME:" > $BOOT/syslinux.cfg
+
+echo_livekit_msg "build: BootInstall.*: Replacing 'MyLinux' with '$LIVEKITNAME'..."
+cat bootfiles/BootInstall.bat | sed -r "s:/boot/:/$LIVEKITNAME/boot/:" | \
+ sed -r "s:\\\\boot\\\\:\\\\$LIVEKITNAME\\\\boot\\\\:" | fgrep -iv "rem" | \
+ sed -r "s:MyLinux:$LIVEKITNAME:" > $BOOT/BootInstall.bat
+cat bootfiles/BootInstall.sh | sed -r "s:MyLinux:$LIVEKITNAME:" > $BOOT/BootInstall.sh
+
+echo_livekit_msg "build: Copying kernel..."
+cp $VMLINUZ $BOOT/
+
+# Copy files from include_bund/, but
+# do not skip bundle creation
+#
+if [ -n "$(ls -A include_bund/ | grep ".$BEXT")" ]; then
+ echo_livekit_msg "build: Copying bundles from include_bund/ ..."
+ ls -A include_bund/ | grep ".$BEXT" | \
+ while read BUND; do
+ cp $BUND "$LIVEKITDATA"/"$LIVEKITNAME"/bundles/
+ done
+fi
+
+# create compressed bundles
+for i in $MKMOD; do
+ CMDOPT="$(get_exclude "$EXCLUDE" $i)"
+ echolog "CMDOPT = $CMDOPT" >&2
+ mkbund /$i $LIVEKITDATA/$LIVEKITNAME/00-main-$i.$BEXT \
+ -keep-as-directory $CMDOPT
+done
+
+# copy rootcopy folder
+if [ -d rootcopy/ ]; then
+ echo_livekit_msg "build: Copying contents of rootcopy/..."
+ cp -a rootcopy/ $LIVEKITDATA/$LIVEKITNAME/
+fi
+
+TARGET=/mnt/z
+if [ ! -d $TARGET ]; then
+ TARGET=/tmp/livekit-build/
+fi
+
+if [ ! -d $TARGET ]; then
+ mkdir -p $TARGET &>/dev/null
+fi
+
+# Output file
+OUT_FILE="$LIVEKITNAME-$ARCH-$PID"
+
+# Checksum file
+SUM_FILE="$TARGET/CHECKSUMS-${OUT_FILE}.TXT"
+
+# Go to Live Kit build data
+cd "$LIVEKITDATA"
+
+# Create ISO image
+echo_livekit_msg "build: Creating ISO file for CD boot..."
+
+# How the F@-- can it be more compact than this!?!?
+"$MKISOFS" -o "$TARGET/$OUT_FILE.iso" -v -J \
+-R -D -A "$LIVEKITNAME" -V "$LIVEKITNAME" \
+-no-emul-boot -boot-info-table -boot-load-size 4 \
+-b "$LIVEKITNAME"/boot/isolinux.bin -c \
+"$LIVEKITNAME"/boot/isolinux.boot . &>/dev/null
+if [ $? -ne 0 ]; then
+ echo_warn "build: Failed to generate ISO image!"
+ SCAN=
+else
+ echo_livekit_msg "build: ISO image: $OUT_FILE.iso"
+ SCAN=1
+fi
+
+# Substitute 'mylinux' with $LIVEKITNAME
+cat "$CWD/bootinfo.txt" | fgrep -v "#" | \
+ sed -r "s/mylinux/$LIVEKITNAME/" | sed -r "s/\$//" > readme.txt
+
+# Create ZIP archive for "universal" use
+echo_livekit_msg "build: Creating ZIP for USB boot..."
+rm -f "$TARGET/$OUT_FILE.zip"
+zip -0 -r "$TARGET/$OUT_FILE.zip" * &>/dev/null
+echo_livekit_msg "build: Output file: $OUT_FILE.zip"
+
+echo_livekit_msg "build: Cleaning up..."
+cd ..
+rm -Rf "$LIVEKITDATA"
+
+# just for aesthetics
+echo_livekit_msg "build: Process ID: $PID - Your results is in $TARGET"
+
+# Generate checksum(s)
+echo_livekit_msg "build: Generating MD5 checksums: Please wait..."
+
+if [ "$SCAN" ]; then
+ MD5_ISO="$(md5sum $TARGET/$OUT_FILE.iso 2>/dev/null | cut -d ' ' -f 1)"
+else
+ MD5_ISO="< FAILED TO GENERATE ISO IMAGE! >"
+fi
+
+MD5_ZIP="$(md5sum $TARGET/$OUT_FILE.zip 2>/dev/null | cut -d ' ' -f 1)"
+
+cat >"$SUM_FILE" <
+# Modified by: 'JohnDaH4x0r' [terencedoesmc12 AT gmail DOT com]
+
+source ../.config
+
+INITRAMFS=/tmp/$LIVEKITNAME-initramfs-$PID
+
+# copy file to initramfs tree, including
+# all library dependencies (as shown by ldd)
+# $1 = file to copy (full path)
+copy_including_deps()
+{
+ # if source doesn't exist or target exists, do nothing
+ if [ ! -e "$1" -o -e "$INITRAMFS"/"$1" ]; then
+ return
+ fi
+
+ cp -R --parents "$1" "$INITRAMFS"
+ if [ -L "$1" ]; then
+ DIR="$(dirname "$1")"
+ LNK="$(readlink "$1")"
+ copy_including_deps "$(cd "$DIR"; realpath -s "$LNK")"
+ fi
+
+ ldd "$1" 2>/dev/null | sed -r "s/.*=>|[(].*//g" | sed -r "s/^\\s+|\\s+\$//" \
+ | while read LIB; do
+ copy_including_deps "$LIB"
+ done
+
+ for MOD in $(find "$1" -type f | grep .ko); do
+ for DEP in $(cat /$LMK/modules.dep | fgrep /$(basename $MOD):); do
+ copy_including_deps "/$LMK/$DEP"
+ done
+ done
+
+ shift
+ if [ "$1" != "" ]; then
+ copy_including_deps "$@"
+ fi
+}
+
+rm -Rf $INITRAMFS
+mkdir -p $INITRAMFS/{bin,dev,etc,lib,lib64,mnt,proc,root,run,sys,tmp,usr,var/log}
+ln -s bin $INITRAMFS/sbin
+
+cd static
+./update
+cd ..
+
+cp static/{busybox,mount.dynfilefs,mount.ntfs-3g,eject} $INITRAMFS/bin
+chmod a+x $INITRAMFS/bin/{busybox,mount.*,eject}
+
+$INITRAMFS/bin/busybox | grep , | grep -v Copyright | tr "," " " | while read LINE; do
+ for TOOL in $LINE; do
+ if [ ! -e $INITRAMFS/bin/$TOOL ]; then
+ ln -s busybox $INITRAMFS/bin/$TOOL
+ fi
+ done
+done
+rm -f $INITRAMFS/{s,}bin/init
+
+mknod $INITRAMFS/dev/console c 5 1
+mknod $INITRAMFS/dev/null c 1 3
+mknod $INITRAMFS/dev/ram0 b 1 0
+mknod $INITRAMFS/dev/tty1 c 4 1
+mknod $INITRAMFS/dev/tty2 c 4 2
+mknod $INITRAMFS/dev/tty3 c 4 3
+mknod $INITRAMFS/dev/tty4 c 4 4
+
+#copy_including_deps /usr/bin/strace
+#copy_including_deps /usr/bin/lsof
+
+copy_including_deps /$LMK/kernel/fs # all filesystems
+copy_including_deps /$LMK/kernel/drivers/staging/zsmalloc # needed by zram
+copy_including_deps /$LMK/kernel/drivers/block/zram
+copy_including_deps /$LMK/kernel/drivers/block/loop.*
+
+# usb drivers
+copy_including_deps /$LMK/kernel/drivers/usb/storage/usb-storage.*
+copy_including_deps /$LMK/kernel/drivers/usb/host
+copy_including_deps /$LMK/kernel/drivers/usb/common
+copy_including_deps /$LMK/kernel/drivers/usb/core
+copy_including_deps /$LMK/kernel/drivers/hid/usbhid
+copy_including_deps /$LMK/kernel/drivers/hid/hid.*
+copy_including_deps /$LMK/kernel/drivers/hid/uhid.*
+copy_including_deps /$LMK/kernel/drivers/hid/hid-generic.*
+
+# disk and cdrom drivers
+copy_including_deps /$LMK/kernel/drivers/cdrom
+copy_including_deps /$LMK/kernel/drivers/scsi/sr_mod.*
+copy_including_deps /$LMK/kernel/drivers/scsi/sd_mod.*
+copy_including_deps /$LMK/kernel/drivers/scsi/scsi_mod.*
+copy_including_deps /$LMK/kernel/drivers/scsi/sg.*
+copy_including_deps /$LMK/kernel/drivers/ata
+
+# copy all custom-built modules
+copy_including_deps /$LMK/updates
+
+copy_including_deps /$LMK/modules.*
+
+
+find $INITRAMFS -name "*.ko.gz" -exec gunzip {} \;
+
+# trim modules.order file. Perhaps we could remove it entirely
+MODULEORDER="$(cd "$INITRAMFS/$LMK/"; find -name "*.ko" | sed -r "s:^./::g" | tr "\n" "|" | sed -r "s:[.]:.:g")"
+cat $INITRAMFS/$LMK/modules.order | sed -r "s/.ko.gz\$/.ko/" | grep -E "$MODULEORDER"/foo/bar > $INITRAMFS/$LMK/_
+mv $INITRAMFS/$LMK/_ $INITRAMFS/$LMK/modules.order
+
+depmod -b $INITRAMFS $KERNEL
+
+echo "root::0:0::/root:/bin/bash" >$INITRAMFS/etc/passwd
+touch $INITRAMFS/etc/{m,fs}tab
+
+cp init $INITRAMFS
+chmod a+x $INITRAMFS/init
+cp cleanup $INITRAMFS/lib
+chmod a+x $INITRAMFS/lib/cleanup
+ln -s ../init $INITRAMFS/bin/init
+cp ../livekitlib $INITRAMFS/lib/
+cp ../.config $INITRAMFS/lib/
+
+cd $INITRAMFS
+find . -print | cpio -o -H newc 2>/dev/null | xz -f --extreme --check=crc32 >$INITRAMFS.img
+echo $INITRAMFS.img
+
+cd ..
+rm -Rf $INITRAMFS
+#mv $INITRAMFS.img /tmp/initrfs.img
diff --git a/bootfiles/initramfs/init b/bootfiles/initramfs/init
new file mode 100644
index 0000000..2c96b56
--- /dev/null
+++ b/bootfiles/initramfs/init
@@ -0,0 +1,93 @@
+#!/bin/sh
+# Initial script for Linux Live Kit / Linux Live Kit Improved
+# Modifier: "JohnDaH4x0r"
+
+# Modify and export/declare new PATH
+export PATH=.:/:/usr/sbin:/usr/bin:/sbin:/bin
+
+# Source Live Kit library script
+. /lib/.config
+. /lib/livekitlib
+
+# Declare start of 'init' state
+clear
+echo_sign "INIT START"
+
+# Run switch_root: initramfs -> tmpfs
+transfer_initramfs
+
+# Directory variables pointing to /memory
+MEMORY=/memory
+CHANGES=$MEMORY/changes
+UNION=$MEMORY/union
+DATAMNT=$MEMORY/data
+BUNDLES=$MEMORY/bundles
+
+# Initliaise /proc, /sys and such
+init_proc_sysfs
+
+# Initialise debugging if requested
+debug_start
+dbg_shell_start
+
+# 1st debug shell interval
+debug_shell
+
+# Initialise important kernel modules
+init_devs
+init_aufs
+init_zram
+
+# Then, modprobe everything
+modprobe_everything
+
+# Find data dir with filesystem bundles
+# NEW:
+# Only 15 seconds before timeout, to minimize the
+# pain of waiting a "whole" minute.
+#
+DATA="$(find_data 15 "$DATAMNT")"
+
+# 2nd debug shell interval
+debug_shell
+
+# Setup persistent changes
+persistent_changes "$DATA" "$CHANGES"
+
+# 3rd debug shell interval
+debug_shell
+
+# Copy data to RAM if requested by user
+DATA="$(copy_to_ram "$DATA" "$CHANGES")"
+
+# Setup an empty union
+init_union "$CHANGES" "$UNION"
+
+# 4th debug shell interval
+debug_shell
+
+# Append bundles to union
+union_append_bundles "$DATA" "$BUNDLES" "$UNION"
+
+# 5th debug shell interval
+debug_shell
+
+# Copy contents of 'rootcopy/'
+copy_rootcopy_content "$DATA" "$UNION"
+
+# Generate a basic 'fstab' with the core filesystems
+fstab_create "$UNION"
+
+# 6th and final debug shell interval
+debug_shell
+
+# Declare the end of first 'init' state
+clear
+echo_sign "INIT END"
+
+# Change root to main OS and let the 'init' in the
+# main OS do the rest...
+change_root "$UNION"
+
+# < ======== NOTHING SHOULD GO OVER THIS LINE! ======== >
+fatal "Unknown error!"
diff --git a/bootfiles/livekitlib b/bootfiles/livekitlib
new file mode 100644
index 0000000..4d8396e
--- /dev/null
+++ b/bootfiles/livekitlib
@@ -0,0 +1,784 @@
+#!/bin/sh
+
+# Functions library :: for Linux Live Kit scripts
+# Original author: Tomas M.
+# Modified by: 'JohnDaH4x0r'
+
+# related to build script
+# get_exclude: Generate exclude arguments for 'mksquashfs'
+# $1: the exclude list ("$EXCLUDE", if you use .config)
+
+get_exclude()
+{
+ EXCLUDE_LIST="$1"
+ PARENT_DIR="$(echo "$2" | tr -s "/")"
+
+ if [ -z "$PARENT_DIR" ]; then
+ return 1
+ elif [ "$PARENT_DIR" = "/" ]; then
+ return 1
+ fi
+
+ echo "$EXCLUDE_LIST" | tr " " "\n" | grep "$PARENT_DIR" \
+ | while read KEY; do
+ echo -n "-e $KEY "
+ done
+}
+
+# NOTE: DO NOT TOUCH THE ESCAPE CHARACTERS!
+BLUE="[1;34m"
+YELLOW="[1;33m"
+ORANGE="[0;33m"
+GREEN="[1;32m"
+BOLD="[0;1m"
+RED="[1;31m"
+NC="[0m"
+
+# debug related
+debug_start()
+{
+ if grep -q 'debug' /proc/cmdline; then
+ DEBUG_IS_ENABLED=1
+ else
+ DEBUG_IS_ENABLED=
+ fi
+}
+
+dbg_shell_start()
+{
+ if grep -q 'dbg_shell' /proc/cmdline; then
+ DBG_SHELL=1
+ else
+ DBG_SHELL=
+ fi
+}
+
+debug_log()
+{
+ if [ "$DEBUG_IS_ENABLED" ]; then
+ echo "[${GREEN}"' debug '"${NC}]: $@" >&2
+ log "debug_log: $*"
+ fi
+}
+
+# echo related functions
+
+# echo fatal tag
+# $1 = text to show
+echo_fatal()
+{
+ echo "[${RED}"' fatal '"${NC}] $@" >&2
+}
+
+# echo bold
+# $1 = text to show
+#
+echo_bold()
+{
+ echo "$BOLD""$@""$NC"
+}
+
+# echo livekit tag
+echo_livekit()
+{
+ echo "[${BLUE}"'livekit'"${NC}] "
+}
+
+echo_livekit_msg()
+{
+ echo "[${BLUE}"'livekit'"${NC}] $@"
+}
+
+# echo error
+echo_err()
+{
+ echo "[${RED}"' error '"${NC}] $@" >&2
+}
+
+# echo warn
+echo_warn()
+{
+ echo "[${YELLOW}"' warn! '"${NC}] $@" >&2
+}
+
+# echo signature
+echo_sign()
+{
+ echo "${BOLD}"' Linux Live Kit Improved v1.0 - '"$* ${NC}"
+}
+
+# log - store given text in /var/log/livedbg
+log()
+{
+ echo "$@" 2>/dev/null >>/var/log/livekit-log
+}
+
+echolog()
+{
+ echo "$@"
+ log "echolog: $@"
+}
+
+# show information about the debug shell
+show_debug_banner()
+{
+ echo_sign "DEBUGGING MODE"
+ echo "The root shell is prepared for you!" >&2
+ echo "Type your desired commands or press Ctrl-D to continue booting." >&2
+ echo >&2
+}
+
+# debug_shell
+# executed when debug boot parameter is present
+#
+debug_shell()
+{
+ if [ "$DBG_SHELL" ]; then
+ show_debug_banner
+ setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1'
+ echo
+ fi
+}
+
+fatal()
+{
+ log "FatalError: $@"
+ echo_fatal "$@"
+ echo_sign "EMERGENCY MODE" >&2
+ echo_bold "Please consult /var/log/livekit-log for more info." >&2
+ setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1'
+}
+
+
+# test if the script is started by root user. If not, exit
+#
+allow_only_root()
+{
+ if [ "0$UID" -ne 0 ]; then
+ echo_err "Only root can run $(basename $0)"; exit 1
+ fi
+}
+
+# Make bundle
+# call mksquashfs with apropriate arguments
+# $1 = directory which will be compressed to squashfs bundle
+# $2 = output file
+# $3..$9 = optional arguments like -keep-as-directory or -b 123456789
+#
+mkbund()
+{
+ debug_log "mkbund" "$*"
+
+ if [ -e "$2" ]; then
+ echo_warn "mkbund: $(basename $2): File already exists!"
+ echo_warn "mkbund: $(basename $2): Deleting file..."
+ rm -f "$2"
+ else
+ echo_livekit_msg "mkbund: $(basename $2): Making new bundle..."
+ fi
+
+ echo_livekit_msg "mkbund: SquashFS compression: 1024k - XZ" >&2
+ echo_livekit_msg "mkbund: $(basename $2): Compressing bundle..." >&2
+ mksquashfs "$1" "$2" -comp xz -b 1024k $3 $4 $5 $6 $7 $8 $9 >/dev/null || \
+ (echo_err "mkbund: Failed to make bundle!" && exit 1)
+}
+
+# Now, for the Live Kit system-related stuff
+
+# get value of kernel cmdline parameter $1
+# $1 = parameter to search for
+#
+cmdline_value()
+{
+ cat /proc/cmdline | egrep -o "(^|[[:space:]])$1=[^[:space:]]+" | \
+ tr -d " " | cut -d "=" -f 2- | tail -n 1
+}
+
+
+# Move entire initramfs tree to tmpfs mount.
+# It's a bit tricky but is necessray to enable pivot_root
+# even for initramfs boot image
+#
+transfer_initramfs()
+{
+ if [ ! -r /lib/esc_initramfs.sgn ]; then
+ echo_livekit >&2
+ echo "Switching root from initramfs to tmpfs..." >&2
+ SWITCH=/m # one letter directory
+ mkdir -p $SWITCH
+ mount -t tmpfs -o size="100%" tmpfs "$SWITCH"
+ cp -a /??* "$SWITCH" 2>/dev/null # only copy two-and-more-letter directories
+ cd $SWITCH
+ echo "This file indicates that we successfully escaped initramfs" >"$SWITCH"/lib/esc_initramfs.sgn
+ exec switch_root -c /dev/console . "$0"
+ fi
+}
+
+# mount virtual filesystems like proc, sys and such
+#
+init_proc_sysfs()
+{
+ debug_log "init_proc_sysfs" "$*"
+ mkdir -p /proc /sys /etc "$MEMORY"
+ mount -n -t proc proc /proc
+ echo "0" >/proc/sys/kernel/printk
+ mount -n -t sysfs sysfs /sys
+ mount -n -o remount,rw rootfs /
+ ln -sf /proc/mounts /etc/mtab
+}
+
+
+# modprobe all modules found in initial ramdisk
+modprobe_everything()
+{
+ debug_log "modprobe_everything" "$*"
+
+ echo_livekit_msg "Probing for hardware..." >&2
+
+ find /lib/modules/ | fgrep '.ko' | xargs -n 1 modprobe 2>/dev/null
+ refresh_devs
+}
+
+
+refresh_devs()
+{
+ debug_log "refresh_devs" "$*"
+ if [ -r /proc/sys/kernel/hotplug ]; then
+ echo /sbin/mdev > /proc/sys/kernel/hotplug
+ fi
+ mdev -s
+}
+
+# make sure some devices are there
+init_devs()
+{
+ debug_log "init_devs" "$*"
+ modprobe zram 2>/dev/null
+ modprobe loop 2>/dev/null
+ modprobe squashfs 2>/dev/null
+ modprobe fuse 2>/dev/null
+ refresh_devs
+}
+
+# Activate zram (auto-compression of RAM)
+# Compressed RAM consumes 1/2 or even 1/4 of original size
+# Setup static size of 500MB
+#
+init_zram()
+{
+ debug_log "init_zram" "$*"
+ echo_livekit_msg "Setting up ZRAM as swap if available..."
+ if [ -r /sys/block/zram0/disksize ]; then
+ echo 536870912 > /sys/block/zram0/disksize # 512MB
+ mkswap /dev/zram0 >/dev/null
+ swapon /dev/zram0 -p 32767
+ echo 100 > /proc/sys/vm/swappiness
+ fi
+}
+
+# load the AUFS kernel module if needed
+#
+init_aufs()
+{
+ debug_log "init_aufs" "$*"
+
+ # Prepare for error messages
+ echo >>/var/log/livkekit-log
+
+ modprobe aufs 2>/var/log/livekit-log
+
+ # If aufs module failed to load, panic immidiately
+ if [ $? -ne 0 ]; then
+ fatal "Failed to load AUFS module!"
+ fi
+
+ # finally, refresh all devices
+ refresh_devs
+}
+
+# Setup empty union
+# $1 = changes directory (ramfs or persistent changes)
+# $2 = union directory where to mount the union
+#
+init_union()
+{
+ debug_log "init_union" "$*"
+
+ echo_livekit_msg "Initialising AUFS union..."
+ mkdir -p "$1"
+ mkdir -p "$2"
+
+ # Prepare for error messages
+ echo >>/var/log/livekit-log
+
+ mount -t aufs -o xino="/.xino",trunc_xino,br="$1" aufs "$2" >/var/log/livekit-log 2>&1
+
+ # If failed to init union, panic
+ if [ $? -ne 0 ]; then
+ fatal "Failed to initialise AUFS union!"
+ fi
+}
+
+# Return device mounted for given directory
+# $1 = directory
+#
+mounted_device()
+{
+ debug_log "mounted_device" "$*"
+
+ local MNT TARGET
+ MNT="$1"
+ while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do
+ TARGET="$(grep -F " $MNT " /proc/mounts | cut -d " " -f 1)"
+ if [ "$TARGET" != "" ]; then
+ echo "$TARGET"
+ return
+ fi
+ MNT="$(dirname "$MNT")"
+ done
+}
+
+# Return mounted dir for given directory
+# $1 = directory
+#
+mounted_dir()
+{
+ debug_log "mounted_dir" "$*"
+
+ local MNT
+ MNT="$1"
+ while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do
+ if mountpoint -q "$MNT" 2>/dev/null; then
+ echo "$MNT"
+ return
+ fi
+ MNT="$(dirname "$MNT")"
+ done
+}
+
+# Make sure to mount FAT12/16/32 using vfat
+# in order to support long filenames
+# $1 = device
+#
+device_bestfs()
+{
+ debug_log "device_bestfs" "$*"
+ local FS
+
+ FS="$(blkid "$1" | sed -r "s/.*TYPE=//" | tr -d '"' | \
+ tr "[A-Z]" "[a-z]" | cut -d ' ' -f 1)"
+ if [ "$FS" = "msdos" -o "$FS" = "fat" ]; then
+ FS="vfat"
+ elif [ "$FS" = "ntfs" ]; then
+ FS="ntfs-3g"
+ else
+ FS="$FS"
+ fi
+ echo "-t $FS"
+}
+
+# Filesystem options for mount
+# $1 = filesystem or '-t filesystem'
+#
+fs_options()
+{
+ debug_log "fs_options" "$*"
+
+ if [ "$1" = "-t" ]; then
+ shift
+ fi
+ if [ "$1" = "vfat" ]; then
+ echo "-o check=s,shortname=mixed,iocharset=utf8"
+ fi
+}
+
+
+# Modprobe network kernel modules until a working driver is found.
+# These drivers are (or used to be) probed in Slackware's initrd.
+# The function returns the first device found, yet it doesn't have
+# to be a working one, eg. if the computer has two network interfaces
+# and ethernet cable is plugged only to one of them.
+#
+init_network_dev()
+{
+ debug_log "init_network_dev" "$*"
+ echo_livekit_msg "Preparing networking device(s)..." >&2
+ local MODULE ETH
+
+ for MODULE in 3c59x acenic de4x5 e1000 e1000e e100 epic100 hp100 \
+ ne2k-pci pcnet32 8139too 8139cp tulip via-rhine r8169 atl1e yellowfin \
+ tg3 dl2k ns83820 atl1 b44 bnx2 skge sky2 tulip depca 3c501 3c503 \
+ 3c505 3c507 3c509 3c515 ac3200 at1700 cosa cs89x0 de600 de620 e2100 \
+ eepro eexpress eth16i ewrk3 forcedeth hostess_sv11 hp-plus hp ni52 \
+ ni65 sb1000 sealevel smc-ultra sis900 smc9194 wd; do
+ modprobe $MODULE 2>/dev/null
+ ETH="$(cat /proc/net/dev | grep : | grep -v lo: | cut -d : -f 1 | tr -d " " | head -n 1)"
+ if [ "$ETH" != "" ]; then
+ echo "$ETH"
+ return 0
+ fi
+ rmmod $MODULE 2>/dev/null
+ done
+
+ # If we are here, none of the above specified modules worked.
+ # As a last chance, try to modprobe everything.
+ echo_warn "No networking kernel module found!"
+ modprobe_everything
+ cat /proc/net/dev | grep ':' | grep -v 'lo:' | cut -d : -f 1 | tr -d " " | head -n 1
+}
+
+
+# Download data from tftp
+# $1 = target (store downloaded files there)
+#
+download_data_pxe()
+{
+ debug_log "download_data_pxe" "$*"
+ local CMD CLIENT SERVER GW MASK PORT ETH PROTOCOL
+
+ mkdir -p "$1/$LIVEKITNAME"
+
+ cmdline_value ip | while IFS=":" read CLIENT SERVER GW MASK PORT; do
+ echo_livekit_msg "Downloading files from ${SERVER}..." >&2
+
+ ETH=$(init_network_dev)
+ if [ "$PORT" = "" ]; then
+ PORT="7529"
+ fi
+
+ # set IP address as given by boot paramter
+ if [ -n "$CLIENT" ] && [ -n "$MASK" ]; then
+ ifconfig $ETH "$CLIENT" netmask "$MASK"
+ route add default gw "$GW"
+ else
+ # if client ip is unknown, try to get a DHCP lease
+ udhcpc -i $ETH -f -q
+ fi
+
+ # well known IP address of Google public DNS service
+ echo nameserver 8.8.8.8 >> /etc/resolv.conf
+
+ PROTOCOL=http
+ wget -q -O "$1/PXEFILELIST" "http://$SERVER:$PORT/PXEFILELIST?$(uname -r):$(uname -m)"
+ if [ $? -ne 0 ]; then
+ echo_warn "Failed to download from http://${SERVER}:${PORT}!" >&2
+ echo_livekit_msg 'Downloading with TFTP protocol...' >&2
+ PROTOCOL=tftp
+ tftp -g -r PXEFILELIST -l "$1/PXEFILELIST" $SERVER
+ fi
+
+ cat "$1/PXEFILELIST" | while read FILE; do
+ if [ "$PROTOCOL" = "http" ]; then
+ echo_livekit_msg "PXE-HTTP: Downloading ${FILE}..." >&2
+ wget -O "$1/$LIVEKITNAME/$FILE" "http://$SERVER:$PORT/$FILE"
+ elif [ "$PROTOCOL" = "tftp" ]; then
+ echo_livekit_msg "PXE-TFTP: Downloading ${FILE}..." >&2
+ tftp -g -r $FILE -l "$1/$LIVEKITNAME/$FILE" $SERVER
+ fi
+ done
+ done
+
+ echo "$1/$LIVEKITNAME"
+}
+
+# Find LIVEKIT data by mounting all devices
+# If found, keep mounted, else unmount
+# $1 = data directory target (mount here)
+# $2 = data directory which contains compressed bundles
+#
+find_data_try()
+{
+ debug_log "find_data_try" "$*"
+
+ local DEVICE FS FROM OPTIONS
+
+ mkdir -p "$1"
+ blkid | sort | cut -d: -f 1 | grep -E -v "/loop|/ram|/zram" | while read DEVICE; do
+ FROM="$2"
+ FS="$(device_bestfs "$DEVICE")"
+ OPTIONS="$(fs_options $FS)"
+ mount -r "$DEVICE" "$1" $FS $OPTIONS 2>/dev/null
+
+ # if the FROM parameter is actual file, mount it again as loop (eg. iso)
+ if [ -f "$1/$FROM" ]; then
+ mount -o remount,rw "$DEVICE" "$1" 2>/dev/null
+ mkdir -p "$1/../file"
+ mount -o loop,ro "$1/$FROM" "$1/../file" 2>/dev/null
+ FROM="../file/$LIVEKITNAME"
+ fi
+
+ # search for bundles in the mounted directory
+ if [ "$(find "$1/$FROM" -maxdepth 1 -name "*.$BEXT" 2>/dev/null)" != "" ]; then
+ # we found at least one bundle/module here
+ mount -o remount,rw "$DEVICE" "$1" 2>/dev/null
+ echo "$1/$FROM" | tr -s "/" | sed -r "s:/[^/]+/[.][.]/:/:g"
+ return
+ fi
+
+ # unmount twice, since there could be mounted ISO as loop too. If not, it doesn't hurt
+ umount "$1" 2>/dev/null
+ umount "$1" 2>/dev/null
+ done
+}
+
+# Retry finding LIVEKIT data several times,
+# until timeouted or until data is found
+# $1 = timeout
+# $2 = data directory target (mount here)
+#
+find_data()
+{
+ debug_log "find_data" "$*"
+
+ local DATA FROM
+
+ if [ "$(cmdline_value ip)" != "" ]; then
+ download_data_pxe "$2"
+ return
+ fi
+
+ FROM="$(cmdline_value from)"
+ if [ "$FROM" = "" ]; then FROM="$LIVEKITNAME"; fi
+ echo_livekit >&2
+ echo "Looking for $LIVEKITNAME data in /$FROM .." | tr -s "/" >&2
+ for timeout in $(seq 1 $1); do
+ echo -n "." >&2
+ refresh_devs
+ DATA="$(find_data_try "$2" "$FROM")"
+
+ # This "was" a bug!
+ echo "" >&2
+
+ if [ "$DATA" != "" ]; then
+ echo_livekit_msg "$LIVEKITNAME data found on $(mounted_device "$2")" >&2
+ echo "$DATA"
+ return
+ fi
+ sleep 1
+ done
+ echo "" >&2
+
+ if [ "$DATA" = "" ]; then
+ fatal "$LIVEKITNAME data not found"
+ fi
+
+}
+
+# Activate persistent changes
+# $1 = data directory
+# $2 = target changes directory
+#
+persistent_changes()
+{
+ debug_log "persistent_changes" "$*"
+
+ local CHANGES T1 T2
+
+ CHANGES="$1/$(basename "$2")"
+ T1="$CHANGES/.perch-test.dat"
+ T2="${T1}-clone.dat"
+
+ # Setup the directory anyway, it will be used in all cases
+ mkdir -p "$2"
+
+ # If persistent changes are not requested, end here
+ if grep -vq 'perch' /proc/cmdline; then
+ return
+ fi
+
+ # check if changes directory exists and is writable
+ touch "$T1" 2>/dev/null && rm -f "$T1" 2>/dev/null
+
+ # if not, simply return back
+ if [ $? -ne 0 ]; then
+ echo_warn "Persistent changes not writable or not used."
+ return
+ fi
+ echo_livekit_msg "Testing persistent changes for POSIX compatibility..." >&2
+ touch "$T1" && ln -sf "$T1" "$T2" 2>/dev/null && \
+ chmod +x "$T1" 2>/dev/null && test -x "$T1" && \
+ chmod -x "$T1" 2>/dev/null && test ! -x "$T1" && \
+ rm "$T1" "$T2" 2>/dev/null
+
+ if [ $? -ne 0 ]; then
+ echo_warn "File system is not POSIX-compatible!" >&2
+ echo_livekit_msg "Activating DynFileFS persistent changes..." >&2
+ rm "$T1" "$T2" 2>/dev/null
+
+ mount.dynfilefs "$CHANGES/changes.dat" 4000 "$2"
+ if [ "$(device_bestfs "$2/loop.fs" | tr -d " ")" = "-t" ]; then
+ mke2fs -F "$2/loop.fs" >/dev/null
+ fi
+ mount -o loop,sync "$2/loop.fs" "$2"
+ rmdir "$2/lost+found" 2>/dev/null
+ else
+ echo_livekit_msg "Activating native persistent changes..." >&2
+ mount --bind "$CHANGES" "$2"
+ fi
+}
+
+# Copy content of rootcopy directory to union
+# $1 = data directory
+# $2 = union directory
+copy_rootcopy_content()
+{
+ debug_log "copy_rootcopy_content" "$*"
+
+ if [ "$(ls -1 "$1/rootcopy/" 2>/dev/null)" != "" ]; then
+ echo_livekit
+ echo "Copying content of rootcopy directory..."
+ cp -a "$1"/rootcopy/* "$2"
+ fi
+}
+
+# Copy data to RAM if requested
+# $1 = live data directory
+# $2 = changes directory
+#
+copy_to_ram()
+{
+ debug_log "copy_to_ram" "$*"
+
+ local MDIR MDEV RAM CHANGES
+
+ if grep -vq 'copy2ram' /proc/cmdline; then
+ echo "$1"
+ return
+ fi
+
+ echo_livekit_msg "Copying $LIVEKITNAME data to RAM..." >&2
+ RAM="$(dirname "$2")"/copy_to_ram
+ mkdir -p "$RAM"
+ cp -a "$1"/* "$RAM"
+ echo "$RAM"
+
+ MDIR="$(mounted_dir "$1")"
+ MDEV="$(mounted_device "$1")"
+ MDEV="$(losetup $MDEV 2>/dev/null | cut -d " " -f 3)"
+ umount "$MDIR" 2>/dev/null
+
+ if [ "$MDEV" ]; then # iso was mounted here, try to unmount the FS it resides on too
+ MDEV="$(mounted_device "$MDEV")"
+ umount "$MDEV" 2>/dev/null
+ fi
+}
+
+# load filter
+#
+filter_load()
+{
+ local FILTER
+ FILTER=$(cmdline_value load)
+ if [ "$FILTER" = "" ]; then
+ cat -
+ else
+ cat - | egrep "$FILTER"
+ fi
+}
+
+# noload filter
+#
+filter_noload()
+{
+ local FILTER
+ FILTER=$(cmdline_value noload)
+ if [ "$FILTER" = "" ]; then
+ cat -
+ else
+ cat - | egrep -v "$FILTER"
+ fi
+}
+
+# sort modules by number even if they are in subdirectory
+#
+sortmod()
+{
+ cat - | sed -r "s,(.*/(.*)),\\2:\\1," | sort -n | cut -d : -f 2-
+}
+
+# Mount squashfs filesystem bundles
+# and add them to union
+# $1 = directory where to search for bundles
+# $2 = directory where to mount bundles
+# $3 = directory where union is mounted
+#
+union_append_bundles()
+{
+ debug_log "union_append_bundles" "$*"
+
+ local BUN
+
+ echo_livekit >&2
+ echo "Appending bundles to union..." >&2
+
+ # Just tell me why! Why be compact?!?
+ ( ls -1 "$1" | sort -n ; cd "$1" ; find modules/ 2>/dev/null | \
+ sortmod | filter_load) | grep '[.]'$BEXT'$' |\
+ filter_noload | \
+ while read BUNDLE; do
+ echo_livekit_msg "Appending: $BUNDLE" >&2
+
+ BUN="$(basename "$BUNDLE")"
+ mkdir -p "$2/$BUN"
+
+ # It now depends on your kernel!
+ mount -o loop -t squashfs "$1/$BUNDLE" "$2/$BUN"
+ mount -o remount,add:1:"$2/$BUN" aufs "$3"
+ done
+}
+
+# Create empty fstab properly
+# $1 = root directory
+#
+fstab_create()
+{
+ debug_log "fstab_create" "$*"
+
+ local FSTAB
+ FSTAB="$1/etc/fstab"
+ echo aufs / aufs defaults 0 0 > $FSTAB
+ echo proc /proc proc defaults 0 0 >> $FSTAB
+ echo sysfs /sys sysfs defaults 0 0 >> $FSTAB
+ echo devpts /dev/pts devpts gid=5,mode=620 0 0 >> $FSTAB
+ echo tmpfs /dev/shm tmpfs defaults 0 0 >> $FSTAB
+}
+
+
+# Change root and execute init
+# $1 = where to change root
+#
+change_root()
+{
+ debug_log "change_root" "$*"
+ echo_livekit_msg "Changing root..." >&2
+ umount /proc
+ umount /sys
+
+ cd "$1"
+
+ # make sure important device files and directories are in union
+ mkdir -p boot dev proc sys tmp mnt run
+ chmod 1777 tmp
+ if [ ! -e dev/console ]; then mknod dev/console c 5 1; fi
+ if [ ! -e dev/tty ]; then mknod dev/tty c 5 0; fi
+ if [ ! -e dev/tty0 ]; then mknod dev/tty0 c 4 0; fi
+ if [ ! -e dev/tty1 ]; then mknod dev/tty1 c 4 1; fi
+ if [ ! -e dev/null ]; then mknod dev/null c 1 3; fi
+ if [ ! -e sbin/fsck.aufs ]; then ln -s /bin/true sbin/fsck.aufs; fi
+
+ # find chroot and init
+ if [ -x bin/chroot -o -L bin/chroot ]; then CHROOT=bin/chroot; fi
+ if [ -x sbin/chroot -o -L sbin/chroot ]; then CHROOT=sbin/chroot; fi
+ if [ -x usr/bin/chroot -o -L usr/bin/chroot ]; then CHROOT=usr/bin/chroot; fi
+ if [ -x usr/sbin/chroot -o -L usr/sbin/chroot ]; then CHROOT=usr/sbin/chroot; fi
+ if [ "$CHROOT" = "" ]; then fatal "chroot: Executable not found!"; fi
+
+ if [ -x bin/init -o -L bin/init ]; then INIT=bin/init; fi
+ if [ -x sbin/init -o -L sbin/init ]; then INIT=sbin/init; fi
+ if [ "$INIT" = "" ]; then fatal "init: Executable not found!"; fi
+
+ mkdir -p mnt/live
+ mount -n -o remount,ro aufs .
+ pivot_root . mnt/live
+ exec $CHROOT . $INIT < dev/console > dev/console 2>&1
+}