WHDD Live ISO Boot CD

From richud.com
Jump to navigation Jump to search


WHDD is created by Andrey Utkin. This is a small 'Live' image to run standalone.

Prebuilt WHDD Live ISO

For people who just want it without building themselves

Prebuilt ISO 2.1-10

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.

i386 uClibc toolchain

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

WHDD screenshot 1.gif

Main menu

WHDD screenshot 3.gif

Show hard drive SMART data

WHDD screenshot 2.gif

Running the 'read test' should produce something like this after a couple of seconds;

WHDD screenshot.gif

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