WHDD Live ISO Boot CD
WHDD is created by Andrey Utkin. This is a small 'Live' image to run standalone.
Contents
Prebuilt WHDD Live ISO
For people who just want it without building themselves
Boot from Syslinux/PXELinux
Label WHDD V2 LINUX /memdisk iso INITRD /whdd-live.iso
or separate (not in ISO)
Label WHDD V2 LINUX /bzImage INITRD /initramfs
Build it yourself
Download Toolchain
This uses uClibc to create smaller C library files and hence a smaller output.
Create folders
Create directory structure somewhere;
mkdir -p patch source custom
Download Sources
cd source git clone https://github.com/krieger-od/whdd git clone git://git.busybox.net/busybox curl https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.02.tar.xz | tar -Jx svn co http://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools smartmontools curl https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.5.tar.xz | tar -Jx curl http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz | tar -zx curl http://invisible-island.net/datafiles/release/dialog.tar.gz | tar -zx
Dir structures
Initially you should just have folders custom, patch, source and the Makefile.
(Ignore other folders for the moment, this is after it has been built to give you an idea how it should look)
├── custom │ ├── inittab │ └── rcS ├── destdir │ ├── bin │ ├── etc │ ├── include │ ├── lib │ ├── linuxrc -> bin/busybox │ ├── sbin │ ├── share │ └── usr ├── initrd │ ├── bin │ ├── dev │ ├── etc │ ├── home │ ├── init -> bin/busybox │ ├── lib │ ├── mnt │ ├── opt │ ├── proc │ ├── sbin │ ├── sys │ ├── tmp │ ├── usr │ └── var ├── Makefile ├── output │ ├── bzImage │ ├── initramfs │ └── isolinux ├── patch │ └── xxxxxxxxxxxx.patch ├── source │ ├── busybox │ ├── dialog-1.2-20140219 │ ├── linux-3.14 │ ├── ncurses-5.9 │ ├── smartmontools-code-3887-trunk │ ├── syslinux │ └── whdd ├── whdd-live.iso └── whdd.qcow
Patches
Patches have been pushed to master so none needed with current version at time of writing (v 2.2)
Makefile
This should be one level below the folder structure's created, see the dir layout
- Change TCHAIN to where your toolchain is, buildroot ones have hard coded paths, x-tools (crosstools-ng doesn't?)
#####################################################
#
# Makefile -- Top level WHDD Live Makefile #####
#
# 2014 Richud.com #####
#
#####################################################
### REMEMBER TOOLCHAIN IS HARDCODED PATHS! ###
## sudo apt-get install byacc flex texinfo groff mklibs ##
########################
#0) Root path of system
########################
ROOT := $(shell pwd)
##################################################
#1) source path, all the extracted program sources
##################################################
SOURCE := $(ROOT)/source
##########################################################
#2) DESTDIR path for build process, makes 'install' target
##########################################################
DESTDIR := $(ROOT)/destdir
##################################################
#3) folder to create stripped/cleaned initrd image
##################################################
INITRD := $(ROOT)/initrd
##############################################################
#4) custom folder for initial run file and misc component bits
##############################################################
CUST := $(ROOT)/custom
PATCH = $(ROOT)/patch
######################################################################################
#5) custom folder for output of kernel and ramdisk images (bzImage/initramfs)
######################################################################################
OUTPUT := $(ROOT)/output
############################
#6) toolchain and compiler
############################
TCHAIN = /home/rich/x-tools/i386-unknown-linux-uclibc/bin
HOST = i386-unknown-linux-uclibc
#compiler
export CC = $(HOST)-gcc
#stripper
STRIP := $(TCHAIN)/$(HOST)-strip
#path
export PATH+=:$(TCHAIN)
#work out source locations
SOURCEDIRS := $(foreach d, $(wildcard $(SOURCE)/*), echo $(notdir $(d)))
#programs to make, if not here they wont build at all as they are referenced below to find their path
PROGS = ncurses busybox dialog smartmontools whdd
#auto create variables for paths e.g. var generated pigz = pigz-2.3.1
$(foreach d, $(PROGS) linux, $(eval $(subst -,,$(d))_PATH = $(filter $(d)%,$(SOURCEDIRS))))
#FLAGS
export CFLAGS = -D_GNU_SOURCE -O3 -m32 -march=i386
export CXXFLAGS = -D_GNU_SOURCE -O3 -m32 -march=i386
export LDFLAGS = -L$(SOURCE)/$(ncurses_PATH)/lib -L$(SOURCE)/$(dialog_PATH) -Wl,-rpath,/lib -Wl,--as-needed
export CPPFLAGS = -I$(SOURCE)/$(ncurses_PATH)/include
#laying down filesystem structure for initrd image
DIRS = \
dev/shm dev/pts \
etc/opt etc/init.d \
home \
mnt \
opt \
proc \
sys \
tmp \
usr/root usr/local usr/share/terminfo/l \
var/tmp var/run var/opt var/cache var/lib/misc var/lib/nfs var/local var/log
###################################
## END OF GENERAL CONFIG SECTION ##
###################################
all: progs linux system iso
progs: $(PROGS)
busybox :
cd "$(SOURCE)/$(busybox_PATH)/" ;\
make defconfig ;\
sed -i \
-e "/# Archival Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Debian Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Finding Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Linux Ext2 FS Progs/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Linux Module Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Filesystem\/Volume identification/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Miscellaneous Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Networking Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Common options for /,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Print Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Mail Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Process Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# System Logging Utilities/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_SHA/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_SETSID/s/# \([A-Z0-9_]*\) is not set/\1=y/" \
.config ;\
yes "" | make oldconfig ;\
make CFLAGS="$(CFLAGS) $(CPPFLAGS)" CROSS_COMPILE=$(HOST)- CONFIG_PREFIX=$(DESTDIR) -j4 install
dialog :
cd "$(SOURCE)/$(dialog_PATH)" ;\
./configure --host=$(HOST) --prefix= --with-shared --with-ncursesw --enable-widec --disable-rc-file --with-curses-dir="$(SOURCE)/$(ncurses_PATH)" ;\
make -j4 && make DESTDIR=$(DESTDIR) install
linux :
cd "$(SOURCE)/$(linux_PATH)" ;\
make mrproper && make i386_defconfig ;\
sed -i \
-e "/# IO Schedulers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Power management/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PCI host controller drivers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PC-card bridges/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Networking options/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Core Netfilter/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Xtables/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# IP: Netfilter/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# IPv6: Netfilter/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Queueing/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Classification/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Network testing/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Packet Radio protocols/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Misc devices/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# IEEE 1394/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Distributed Switch/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# MII PHY device drivers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# USB Network Adapters/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Enable WiMAX/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Serial drivers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Non-8250 serial/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PCMCIA character/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PC SMBus host/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Enable PHYLIB/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# ACPI drivers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Texas Instruments/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Watchdog/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# USB-based Watchdog/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PPS support/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PTP clock/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Enable PHYLIB/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Sonics Silicon/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Multifunction/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Frame buffer hardware/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# LED/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# iptables/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Microsoft/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# PHY Subsystem/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Firmware/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# File systems/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# CD-ROM/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Memory Debugging/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Debug Lockups/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Lock Debugging/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# RCU Debugging/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Runtime Testing/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Security options/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Crypto core/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Authenticated Encryption/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Block modes/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Hash modes/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Digest/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Ciphers/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/# Random Number/,/^$$/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_QUOTA/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_.*NOTIFY/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_LOGO/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_AGP/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_DRM/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_FB/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_SND/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_SOUND/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_INPUT_JOYSTICK/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_INPUT_TABLET/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_INPUT_TOUCHSCREEN/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_INPUT_MISC/s/\([A-Z0-9_]*\)=.*/# \1 is not set/" \
-e "/CONFIG_SATA/s/# \([A-Z0-9_]*\) is not set/\1=y/" \
-e "/CONFIG_ACPI/s/# \(CONFIG_ACPI\) is not set/\1=y/" \
-e "/CONFIG_PATA/s/# \([A-Z0-9_]*\) is not set/\1=y/" \
-e "s/CONFIG_DEFAULT_HOSTNAME=\"(none)\"/CONFIG_DEFAULT_HOSTNAME=\"WHDD Live\"/" \
.config ;\
yes "" | make oldconfig ;\
make CFLAGS="$(CFLAGS) $(CPPFLAGS)" CROSS_COMPILE=$(HOST)- ARCH=i386 -j8 all ;\
cp "arch/x86/boot/bzImage" $(OUTPUT)
ncurses :
cd "$(SOURCE)/$(ncurses_PATH)" ;\
./configure --host=$(HOST) --prefix= --datadir=/usr/share --with-termlib=tinfo --enable-widec --with-shared \
--without-gpm --without-manpages --without-progs ;\
make -j4 && make DESTDIR=$(DESTDIR) install
smartmontools :
#using SVN
cd "$(SOURCE)/$(smartmontools_PATH)/smartmontools" ;\
./autogen.sh ;\
./configure --host=$(HOST) --prefix= ;\
make -j4 && make DESTDIR=$(DESTDIR) install
whdd :
cd "$(SOURCE)/$(whdd_PATH)" ;\
cmake \
-DCMAKE_C_COMPILER="$(TCHAIN)/$(HOST)-gcc" \
-DCMAKE_CXX_COMPILER="$(TCHAIN)/$(HOST)-g++" \
-DCMAKE_PREFIX_PATH="$(SOURCE)/$(dialog_PATH);$(SOURCE)/$(ncurses_PATH)" \
-DCMAKE_SYSTEM_NAME="Linux" \
-DCLI=ON \
-DCMAKE_INSTALL_PREFIX:PATH= . \
&& make && make DESTDIR="$(DESTDIR)" install
clean :
for i in $$(ls -d $(SOURCE)/*); do cd "$$i"; make clean; done
rm -rf $(DESTDIR)
distclean :
for i in $$(ls -d $(SOURCE)/*); do cd "$$i"; make distclean; done
rm -rf $(DESTDIR)
system :
#delete initrd build folder
$(shell rm -rf "$(INITRD)")
#(re)create folder structure
$(foreach d,$(DIRS),$(shell mkdir -p $(INITRD)/$(d)))
#copy ALL files over
cp -aR $(DESTDIR)/. $(INITRD)/
#copy custom bits
cp -a $(CUST)/* $(INITRD)/etc/
mv $(INITRD)/etc/rcS $(INITRD)/etc/init.d/
###############
#cleanup/shrink
###############
#uneeded terminals
rm -rf "$(INITRD)/usr/share/terminfo" && mkdir -p "$(INITRD)/usr/share/terminfo/l"
cp -a "$(DESTDIR)/usr/share/terminfo/l/linux" "$(INITRD)/usr/share/terminfo/l/"
#undeeded executables
rm -rf "$(INITRD)/sbin/smartd" "$(INITRD)/bin/dialog"
#minimalise target libs linker - ld- needs fixing!! 21 stripped
cd "$(TCHAIN)/../i386-unknown-linux-uclibc/lib" ;\
mklibs -d $(INITRD)/lib -D \
-L "$(SOURCE)/$(ncurses_PATH)/lib" -L "$(SOURCE)/$(dialog_PATH)" -L "$(TCHAIN)/../i386-unknown-linux-uclibc/lib" \
--ldlib ld-uClibc.so.0 --target $(HOST) $$(find "$(DESTDIR)/bin" "$(DESTDIR)/sbin" -type f -perm /a+x)
mv "$(INITRD)/ld-uClibc.so.0" "$(INITRD)/lib"
#fix initd default to initramfs default
mv $(INITRD)/linuxrc $(INITRD)/init
#link wipe
ln -s /etc/wipe.sh $(INITRD)/wipe.sh
#make sure these user customisable files are executable
cd $(INITRD) && chmod 755 etc/*.sh etc/inittab etc/init.d/rcS
#cleanup unneeded files
cd $(INITRD) && rm -rf man share include info lib/*.a lib/*.la
#strip Executable and Linkable Format files, but not kernel modules if present
find $(INITRD) -type f ! -iname "*.ko" -exec $(STRIP) {} \; 2> /dev/null
#reset ownership, cpio archive it and lzma compress initramfs
cd "$(INITRD)" && find ./ -print | cpio --owner 0.0 --quiet -H newc -o | lzma -9 -z -k -c > $(OUTPUT)/initramfs
iso :
#generate ISO
mkdir -p "$(OUTPUT)/isolinux"
echo "DEFAULT WHDD \n\
LABEL WHDD \n\
LINUX /bzImage \n\
INITRD /initramfs" > "$(OUTPUT)/isolinux/isolinux.cfg"
find "$(SOURCE)" -name ldlinux.c32 -o -name isolinux.bin -exec cp -a {} "$(OUTPUT)/isolinux" \;
mkisofs -o "whdd-live.iso" \
-b "isolinux/isolinux.bin" -c "isolinux/boot.cat" \
-no-emul-boot -boot-load-size 4 -boot-info-table -R -J -l -V "WHDD Live" "$(OUTPUT)"
/custom folder contents
inittab
::sysinit:/etc/init.d/rcS ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r tty1::respawn:/bin/sh tty2::respawn:/bin/sh
rcS
#!/bin/sh #####################set # WHDD Live # # Richud.com 2014 # ##################### #mount system virtual file systems mount -t proc proc /proc mount -t sysfs none /sys #UNIX98 pseudoterminal support mount -t devpts devpts /dev/pts #hotplug support with bb mdev mdev -s echo /sbin/mdev > /proc/sys/kernel/hotplug #stop all but EMERG kernel messages to console echo 1 4 1 7 > /proc/sys/kernel/printk #set LANG so ncurses displays all ACSII codes. #this needs controlling terminal set below to work OR need to patch busybox/shell/ash.c with LANG variable. export LANG=en_US.UTF-8 #startup whdd with a controlling terminal else no SIGNALS will work like ctrl-c OR patch kernel drivers/char/tty_io.c setsid sh -c 'exec "/sbin/whdd" </dev/tty1 >/dev/tty1 2>&1'
Build It
Assuming you have all the files extracted and laid out correctly, just run 'make'.
- make = build everything i.e. create kernel 'bzImage', programs and system archive 'initramfs' , iso
- make xxxxx = build program xxxxx (to 'destdir/')
- make linux = just build (compile) kernel ('output/bzImage')
- make progs = just build (compile) all the progs ('destdir/')
- make system = clean/strip/cpio archive programs ('output/initramfs')
- make iso = create ISO from bzImage and initramfs
Test It (with QEmu)
- create a 50Mb test 'hard drive' image
qemu-img create -f qcow whdd.qcow 50M
- fire it up
qemu-system-x86_64 -kernel output/bzImage -initrd output/initramfs -hda whdd.qcow
Selecting the QEMU disk
Main menu
Show hard drive SMART data
Running the 'read test' should produce something like this after a couple of seconds;
UTF.8 Support
Remeber you need ncurses, a terminfo database, patched ash.c or specifying LANG in the running shell. Additionally, but not in this example, a correct console font such as Lat15-Fixed16.psf or cyr-sun16.psfu (Thanks Lavrentiy Ivanov)
Comments
blog comments powered by Disqus