Added experimental folder 'glibc-busybox' which solves the DNS issue. This works on 32bit machines. Not tested on 64bit machines. This is not at all "minimal" and needs *a lot* of RAM (256MB for now).
This commit is contained in:
parent
1ca057ee0b
commit
40fdd94157
18
src/experimental/glibc-busybox/.config
Normal file
18
src/experimental/glibc-busybox/.config
Normal file
@ -0,0 +1,18 @@
|
||||
# You can find the latest Linux kernel source bundles here:
|
||||
#
|
||||
# http://kernel.org
|
||||
#
|
||||
KERNEL_SOURCE_URL=https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.4.6.tar.xz
|
||||
|
||||
# You can find the latest GNU libc source bundles here:
|
||||
#
|
||||
# http://gnu.org/software/libc
|
||||
#
|
||||
GLIBC_SOURCE_URL=http://ftp.gnu.org/gnu/glibc/glibc-2.23.tar.bz2
|
||||
|
||||
# You can find the latest BusyBox source bundles here:
|
||||
#
|
||||
# http://busybox.net
|
||||
#
|
||||
BUSYBOX_SOURCE_URL=http://busybox.net/downloads/busybox-1.24.2.tar.bz2
|
||||
|
8
src/experimental/glibc-busybox/00_prepare.sh
Executable file
8
src/experimental/glibc-busybox/00_prepare.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf work
|
||||
mkdir work
|
||||
|
||||
# -p stops errors if the directory already exists
|
||||
mkdir -p source
|
||||
|
24
src/experimental/glibc-busybox/01_get_kernel.sh
Executable file
24
src/experimental/glibc-busybox/01_get_kernel.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Grab everything after the '=' character
|
||||
DOWNLOAD_URL=$(grep -i KERNEL_SOURCE_URL .config | cut -f2 -d'=')
|
||||
|
||||
# Grab everything after the last '/' character
|
||||
ARCHIVE_FILE=${DOWNLOAD_URL##*/}
|
||||
|
||||
cd source
|
||||
|
||||
# Downloading kernel file
|
||||
# -c option allows the download to resume
|
||||
wget -c $DOWNLOAD_URL
|
||||
|
||||
# Delete folder with previously extracted kernel
|
||||
rm -rf ../work/kernel
|
||||
mkdir ../work/kernel
|
||||
|
||||
# Extract kernel to folder 'work/kernel'
|
||||
# Full path will be something like 'work/kernel/linux-3.16.1'
|
||||
tar -xvf $ARCHIVE_FILE -C ../work/kernel
|
||||
|
||||
cd ..
|
||||
|
26
src/experimental/glibc-busybox/02_build_kernel.sh
Executable file
26
src/experimental/glibc-busybox/02_build_kernel.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/kernel
|
||||
|
||||
# Change to the first directory ls finds, e.g. 'linux-3.18.6'
|
||||
cd $(ls -d *)
|
||||
|
||||
# Cleans up the kernel sources, including configuration files
|
||||
make mrproper
|
||||
|
||||
# Create a default configuration file for the kernel
|
||||
make defconfig
|
||||
|
||||
# Changes the name of the system
|
||||
sed -i "s/.*CONFIG_DEFAULT_HOSTNAME.*/CONFIG_DEFAULT_HOSTNAME=\"minimal\"/" .config
|
||||
|
||||
# Compile the kernel with optimization for "parallel jobs" = "number of processors"
|
||||
# Good explanation of the different kernels
|
||||
# http://unix.stackexchange.com/questions/5518/what-is-the-difference-between-the-following-kernel-makefile-terms-vmlinux-vmlinux
|
||||
make bzImage -j $(grep ^processor /proc/cpuinfo | wc -l)
|
||||
|
||||
# Install kernel headers in "./usr" (this is not "/usr") which are used later.
|
||||
make headers_install
|
||||
|
||||
cd ../../..
|
||||
|
24
src/experimental/glibc-busybox/03_get_glibc.sh
Executable file
24
src/experimental/glibc-busybox/03_get_glibc.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Grab everything after the '=' character
|
||||
DOWNLOAD_URL=$(grep -i GLIBC_SOURCE_URL .config | cut -f2 -d'=')
|
||||
|
||||
# Grab everything after the last '/' character
|
||||
ARCHIVE_FILE=${DOWNLOAD_URL##*/}
|
||||
|
||||
cd source
|
||||
|
||||
# Downloading musl file
|
||||
# -c option allows the download to resume
|
||||
wget -c $DOWNLOAD_URL
|
||||
|
||||
# Delete folder with previously extracted glibc
|
||||
rm -rf ../work/glibc
|
||||
mkdir ../work/glibc
|
||||
|
||||
# Extract glibc to folder 'work/glibc'
|
||||
# Full path will be something like 'work/glibc/glibc-1.1.11'
|
||||
tar -xvf $ARCHIVE_FILE -C ../work/glibc
|
||||
|
||||
cd ..
|
||||
|
35
src/experimental/glibc-busybox/04_build_glibc.sh
Executable file
35
src/experimental/glibc-busybox/04_build_glibc.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/kernel
|
||||
cd $(ls -d *)
|
||||
WORK_KERNEL_DIR=$(pwd)
|
||||
cd ../../..
|
||||
|
||||
cd work/glibc
|
||||
|
||||
# Change to the first directory ls finds, e.g. 'glibc-2.22'
|
||||
cd $(ls -d *)
|
||||
|
||||
rm -rf ./glibc_objects
|
||||
mkdir glibc_objects
|
||||
|
||||
rm -rf ./glibc_installed
|
||||
mkdir glibc_installed
|
||||
cd glibc_installed
|
||||
GLIBC_INSTALLED=$(pwd)
|
||||
|
||||
cd ../glibc_objects
|
||||
../configure --prefix= --with-headers=$WORK_KERNEL_DIR/usr/include --disable-werror
|
||||
#../configure --prefix=$GLIBC_INSTALLED --with-headers=$WORK_KERNEL_DIR/usr/include --enable-static-ns --disable-werror
|
||||
#../configure --prefix=$GLIBC_INSTALLED --with-headers=$WORK_KERNEL_DIR/usr/include --disable-werror
|
||||
|
||||
make -j $(grep ^processor /proc/cpuinfo | wc -l)
|
||||
|
||||
#set DESTDIR=$GLIBC_INSTALLED
|
||||
#export DESTDIR
|
||||
make install DESTDIR=$GLIBC_INSTALLED -j $(grep ^processor /proc/cpuinfo | wc -l)
|
||||
|
||||
#unset DESTDIR
|
||||
|
||||
cd ../../..
|
||||
|
64
src/experimental/glibc-busybox/05_prepare_glibc.sh
Executable file
64
src/experimental/glibc-busybox/05_prepare_glibc.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/kernel
|
||||
cd $(ls -d *)
|
||||
WORK_KERNEL_DIR=$(pwd)
|
||||
cd ../../..
|
||||
|
||||
cd work/glibc
|
||||
|
||||
# Change to the first directory ls finds, e.g. 'glibc-2.22'
|
||||
cd $(ls -d *)
|
||||
|
||||
cd glibc_installed
|
||||
|
||||
mkdir -p usr
|
||||
cd usr
|
||||
|
||||
unlink include 2>/dev/null
|
||||
ln -s ../include include
|
||||
|
||||
unlink lib 2>/dev/null
|
||||
ln -s ../lib lib
|
||||
|
||||
cd ../include
|
||||
|
||||
unlink linux 2>/dev/null
|
||||
ln -s $WORK_KERNEL_DIR/usr/include/linux linux
|
||||
|
||||
unlink asm 2>/dev/null
|
||||
ln -s $WORK_KERNEL_DIR/usr/include/asm asm
|
||||
|
||||
unlink asm-generic 2>/dev/null
|
||||
ln -s $WORK_KERNEL_DIR/usr/include/asm-generic asm-generic
|
||||
|
||||
unlink mtd 2>/dev/null
|
||||
ln -s $WORK_KERNEL_DIR/usr/include/mtd mtd
|
||||
|
||||
cd ../../../..
|
||||
|
||||
exit 0
|
||||
|
||||
unlink musl-ar 2>/dev/null
|
||||
ln -s `which ar` musl-ar
|
||||
|
||||
unlink musl-strip 2>/dev/null
|
||||
ln -s `which strip` musl-strip
|
||||
|
||||
unlink linux 2>/dev/null
|
||||
ln -s /usr/include/linux linux
|
||||
|
||||
unlink mtd 2>/dev/null
|
||||
ln -s /usr/include/mtd mtd
|
||||
|
||||
if [ -d /usr/include/asm ]
|
||||
then
|
||||
unlink asm 2>/dev/null
|
||||
ln -s /usr/include/asm asm
|
||||
else
|
||||
unlink asm 2>/dev/null
|
||||
ln -s /usr/include/asm-generic asm
|
||||
fi
|
||||
|
||||
unlink asm-generic 2>/dev/null
|
||||
ln -s /usr/include/asm-generic asm-generic
|
24
src/experimental/glibc-busybox/06_get_busybox.sh
Executable file
24
src/experimental/glibc-busybox/06_get_busybox.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Grab everything after the '=' character
|
||||
DOWNLOAD_URL=$(grep -i BUSYBOX_SOURCE_URL .config | cut -f2 -d'=')
|
||||
|
||||
# Grab everything after the last '/' character
|
||||
ARCHIVE_FILE=${DOWNLOAD_URL##*/}
|
||||
|
||||
cd source
|
||||
|
||||
# Downloading busybox source
|
||||
# -c option allows the download to resume
|
||||
wget -c $DOWNLOAD_URL
|
||||
|
||||
# Delete folder with previously extracted busybox
|
||||
rm -rf ../work/busybox
|
||||
mkdir ../work/busybox
|
||||
|
||||
# Extract busybox to folder 'busybox'
|
||||
# Full path will be something like 'work/busybox/busybox-1.23.1'
|
||||
tar -xvf $ARCHIVE_FILE -C ../work/busybox
|
||||
|
||||
cd ..
|
||||
|
57
src/experimental/glibc-busybox/07_build_busybox.sh
Executable file
57
src/experimental/glibc-busybox/07_build_busybox.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/glibc
|
||||
cd $(ls -d *)
|
||||
cd glibc_installed
|
||||
GLIBC_INSTALLED=$(pwd)
|
||||
|
||||
cd ../../../..
|
||||
|
||||
cd work/busybox
|
||||
|
||||
# Change to the first directory ls finds, e.g. 'busybox-1.23.1'
|
||||
cd $(ls -d *)
|
||||
|
||||
#PATH_BACKUP=$PATH
|
||||
#PATH=$GLIBC_INSTALLED:$PATH
|
||||
|
||||
# Remove previously generated artifacts
|
||||
make distclean
|
||||
|
||||
# Create a default configuration file
|
||||
make defconfig
|
||||
|
||||
# Change the configuration, so that busybox is statically compiled
|
||||
# You could do this manually with 'make menuconfig'
|
||||
#
|
||||
# Uncomment for static build.
|
||||
#
|
||||
#sed -i "s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/" .config
|
||||
|
||||
GLIBC_INSTALLED_ESCAPED=$(echo \"$GLIBC_INSTALLED\" | sed 's/\//\\\//g')
|
||||
|
||||
#echo $GLIBC_INSTALLED_ESCAPED
|
||||
#exit 0
|
||||
|
||||
# Uncomment after some tests
|
||||
#
|
||||
sed -i "s/.*CONFIG_SYSROOT.*/CONFIG_SYSROOT=$GLIBC_INSTALLED_ESCAPED/" .config
|
||||
|
||||
#exit 0
|
||||
|
||||
#sed -i "s/.*CONFIG_CROSS_COMPILER_PREFIX.*/CONFIG_CROSS_COMPILER_PREFIX=\"uclibc-\"/" .config
|
||||
#sed -i "s/.*CONFIG_IFPLUGD.*/CONFIG_IFPLUGD=n/" .config
|
||||
sed -i "s/.*CONFIG_INETD.*/CONFIG_INETD=n/" .config
|
||||
#sed -i "s/.*CONFIG_FEATURE_WTMP.*/CONFIG_FEATURE_WTMP=n/" .config
|
||||
|
||||
# Compile busybox with optimization for "parallel jobs" = "number of processors"
|
||||
make busybox -j $(grep ^processor /proc/cpuinfo | wc -l)
|
||||
|
||||
# Create the symlinks for busybox
|
||||
# It uses the file 'busybox.links' for this
|
||||
make install
|
||||
|
||||
#PATH=$PATH_BACKUP
|
||||
|
||||
cd ../../..
|
||||
|
156
src/experimental/glibc-busybox/08_generate_rootfs.sh
Executable file
156
src/experimental/glibc-busybox/08_generate_rootfs.sh
Executable file
@ -0,0 +1,156 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/glibc
|
||||
cd $(ls -d *)
|
||||
cd glibc_installed
|
||||
GLIBC_INSTALLED=$(pwd)
|
||||
|
||||
cd ../../../..
|
||||
|
||||
cd work
|
||||
|
||||
rm -rf rootfs
|
||||
|
||||
cd busybox
|
||||
cd $(ls -d *)
|
||||
|
||||
# Copy all BusyBox generated stuff to the location of our "initramfs" folder.
|
||||
cp -R _install ../../rootfs
|
||||
cd ../../rootfs
|
||||
|
||||
# Remove "linuxrc" which is used when we boot in "RAM disk" mode.
|
||||
rm -f linuxrc
|
||||
|
||||
# Create root FS folders
|
||||
mkdir dev
|
||||
mkdir etc
|
||||
mkdir proc
|
||||
mkdir root
|
||||
mkdir src
|
||||
mkdir sys
|
||||
mkdir tmp
|
||||
|
||||
# "1" means that only the owner of a file/directory (or root) can remove it.
|
||||
chmod 1777 tmp
|
||||
|
||||
cd etc
|
||||
|
||||
# The script "/etc/bootscript.sh" is automatically executed as part of the
|
||||
# "init" proess. We suppress most kernel messages, mount all crytical file
|
||||
# systems, loop through all available network devices and we configure them
|
||||
# through DHCP.
|
||||
cat > bootscript.sh << EOF
|
||||
#!/bin/sh
|
||||
|
||||
dmesg -n 1
|
||||
mount -t devtmpfs none /dev
|
||||
mount -t proc none /proc
|
||||
mount -t sysfs none /sys
|
||||
|
||||
for DEVICE in /sys/class/net/* ; do
|
||||
ip link set \${DEVICE##*/} up
|
||||
[ \${DEVICE##*/} != lo ] && udhcpc -b -i \${DEVICE##*/} -s /etc/rc.dhcp
|
||||
done
|
||||
|
||||
EOF
|
||||
|
||||
chmod +x bootscript.sh
|
||||
|
||||
# The script "/etc/rc.dhcp" is automatically invoked for each network device.
|
||||
cat > rc.dhcp << EOF
|
||||
#!/bin/sh
|
||||
|
||||
ip addr add \$ip/\$mask dev \$interface
|
||||
|
||||
if [ "\$router" ]; then
|
||||
ip route add default via \$router dev \$interface
|
||||
fi
|
||||
|
||||
EOF
|
||||
|
||||
chmod +x rc.dhcp
|
||||
|
||||
# DNS resolving is done by using Google's public DNS servers
|
||||
cat > resolv.conf << EOF
|
||||
nameserver 8.8.8.8
|
||||
nameserver 8.8.4.4
|
||||
|
||||
EOF
|
||||
|
||||
# The file "/etc/welcome.txt" is displayed on every boot of the system in each
|
||||
# available terminal.
|
||||
cat > welcome.txt << EOF
|
||||
|
||||
#####################################
|
||||
# #
|
||||
# Welcome to "Minimal Linux Live" #
|
||||
# #
|
||||
#####################################
|
||||
|
||||
EOF
|
||||
|
||||
# The file "/etc/inittab" contains the configuration which defines how the
|
||||
# system will be initialized. Check the following URL for more details:
|
||||
# http://git.busybox.net/busybox/tree/examples/inittab
|
||||
cat > inittab << EOF
|
||||
::sysinit:/etc/bootscript.sh
|
||||
::restart:/sbin/init
|
||||
::ctrlaltdel:/sbin/reboot
|
||||
::once:cat /etc/welcome.txt
|
||||
::respawn:/bin/cttyhack /bin/sh
|
||||
tty2::once:cat /etc/welcome.txt
|
||||
tty2::respawn:/bin/sh
|
||||
tty3::once:cat /etc/welcome.txt
|
||||
tty3::respawn:/bin/sh
|
||||
tty4::once:cat /etc/welcome.txt
|
||||
tty4::respawn:/bin/sh
|
||||
|
||||
EOF
|
||||
|
||||
cat > nsswitch.conf << EOF
|
||||
passwd: db files nis
|
||||
shadow: files
|
||||
group: db files nis
|
||||
|
||||
hosts: files nisplus nis dns
|
||||
networks: nisplus [NOTFOUND=return] files
|
||||
|
||||
ethers: nisplus [NOTFOUND=return] db files
|
||||
protocols: nisplus [NOTFOUND=return] db files
|
||||
rpc: nisplus [NOTFOUND=return] db files
|
||||
services: nisplus [NOTFOUND=return] db files
|
||||
|
||||
EOF
|
||||
|
||||
cd ..
|
||||
|
||||
# The "/init" script passes the execution to "/sbin/init" which in turn looks
|
||||
# for the configuration file "/etc/inittab".
|
||||
cat > init << EOF
|
||||
#!/bin/sh
|
||||
echo "1111111111111111"
|
||||
echo "1111111111111111"
|
||||
echo "1111111111111111"
|
||||
PATH=/lib:$PATH
|
||||
export PATH
|
||||
exec /sbin/init
|
||||
|
||||
EOF
|
||||
|
||||
chmod +x init
|
||||
|
||||
# Copy all source files to "/src". Note that the scripts won't work there.
|
||||
cp ../../*.sh src
|
||||
cp ../../.config src
|
||||
cp ../../*.txt src
|
||||
chmod +rx src/*.sh
|
||||
chmod +r src/.config
|
||||
chmod +r src/*.txt
|
||||
|
||||
#cd bin
|
||||
#cp -r $GLIBC_INSTALLED/lib/* .
|
||||
#cd ..
|
||||
cp -r $GLIBC_INSTALLED/* .
|
||||
|
||||
cd ../..
|
||||
|
14
src/experimental/glibc-busybox/09_pack_rootfs.sh
Executable file
14
src/experimental/glibc-busybox/09_pack_rootfs.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work
|
||||
|
||||
# Remove the old initramfs archive if it exists.
|
||||
rm -f rootfs.cpio.gz
|
||||
|
||||
cd rootfs
|
||||
|
||||
# Packs the current folder structure in "cpio.gz" archive.
|
||||
find . | cpio -R root:root -H newc -o | gzip > ../rootfs.cpio.gz
|
||||
|
||||
cd ../..
|
||||
|
55
src/experimental/glibc-busybox/10_generate_iso.sh
Executable file
55
src/experimental/glibc-busybox/10_generate_iso.sh
Executable file
@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd work/kernel
|
||||
cd $(ls -d *)
|
||||
WORK_KERNEL_DIR=$(pwd)
|
||||
cd ../../..
|
||||
|
||||
rm -f minimal_linux_live.iso
|
||||
rm -rf work/isoimage
|
||||
|
||||
# This is the root folder of the ISO image
|
||||
mkdir work/isoimage
|
||||
cd work/isoimage
|
||||
|
||||
# Search and copy the files 'isolinux.bin' and 'ldlinux.c32'
|
||||
for i in lib lib64 share end ; do
|
||||
if [ -f /usr/$i/syslinux/isolinux.bin ]; then
|
||||
cp /usr/$i/syslinux/isolinux.bin .
|
||||
if [ -f /usr/$i/syslinux/ldlinux.c32 ]; then
|
||||
cp /usr/$i/syslinux/ldlinux.c32 .
|
||||
fi;
|
||||
break;
|
||||
fi;
|
||||
if [ $i = end ]; then exit 1; fi;
|
||||
done
|
||||
|
||||
# Now we copy the kernel
|
||||
cp $WORK_KERNEL_DIR/arch/x86/boot/bzImage ./kernel.bz
|
||||
|
||||
# Now we copy the root file system
|
||||
cp ../rootfs.cpio.gz ./rootfs.gz
|
||||
|
||||
# Copy all source files to "/src". Note that the scripts won't work there.
|
||||
mkdir src
|
||||
cp ../../*.sh src
|
||||
cp ../../.config src
|
||||
cp ../../*.txt src
|
||||
chmod +rx src/*.sh
|
||||
chmod +r src/.config
|
||||
chmod +r src/*.txt
|
||||
|
||||
# Create ISOLINUX configuration file
|
||||
echo 'default kernel.bz initrd=rootfs.gz' > ./isolinux.cfg
|
||||
|
||||
# Now we generate the ISO image file
|
||||
genisoimage -J -r -o ../minimal_linux_live.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table ./
|
||||
|
||||
# This allows the ISO image to be bootable if it is burned on USB flash drive
|
||||
isohybrid ../minimal_linux_live.iso 2>/dev/null || true
|
||||
|
||||
# Copy the ISO image to the root project folder
|
||||
cp ../minimal_linux_live.iso ../../
|
||||
|
||||
cd ../..
|
||||
|
14
src/experimental/glibc-busybox/build_minimal_linux_live.sh
Executable file
14
src/experimental/glibc-busybox/build_minimal_linux_live.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
sh 00_prepare.sh
|
||||
sh 01_get_kernel.sh
|
||||
sh 02_build_kernel.sh
|
||||
sh 03_get_musl.sh
|
||||
sh 04_build_musl.sh
|
||||
sh 05_prepare_musl.sh
|
||||
sh 06_get_busybox.sh
|
||||
sh 07_build_busybox.sh
|
||||
sh 08_generate_rootfs.sh
|
||||
sh 09_pack_rootfs.sh
|
||||
sh 10_generate_iso.sh
|
||||
|
4
src/experimental/glibc-busybox/qemu32.sh
Executable file
4
src/experimental/glibc-busybox/qemu32.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
qemu-system-i386 -m 256M -cdrom minimal_linux_live.iso
|
||||
|
4
src/experimental/glibc-busybox/qemu64.sh
Executable file
4
src/experimental/glibc-busybox/qemu64.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
qemu-system-x86_64 -cdrom minimal_linux_live.iso
|
||||
|
722
src/experimental/glibc-busybox/the_dao_of_minimal_linux_live.txt
Normal file
722
src/experimental/glibc-busybox/the_dao_of_minimal_linux_live.txt
Normal file
@ -0,0 +1,722 @@
|
||||
|
||||
The Dao of Minimal Linux Live (15-Feb-2015)
|
||||
|
||||
Author: Ivan Davidov
|
||||
Website: http://minimal.linux-bg.org
|
||||
Email: davidov (dot) i {at} gmail [dot] com
|
||||
|
||||
Redistributed by: <put your name and contact details somewhere here>
|
||||
|
||||
### ### ###
|
||||
|
||||
Contents
|
||||
|
||||
1. Preface
|
||||
2. Boot Process
|
||||
3. Inside The Shell Scripts
|
||||
4. Possible Improvements
|
||||
5. Next Steps
|
||||
6. Epilogue
|
||||
|
||||
### ### ###
|
||||
|
||||
1. Preface
|
||||
|
||||
Please feel free to redistribute this document in any form you see fit. I only ask you to
|
||||
respect my efforts and keep me as the original author. That's all I ask.
|
||||
|
||||
Note that the explanations regarding the script details are based on the "28-Jul-2014"
|
||||
version of "Minimal Linux Live". Future versions of the scripts may already include some
|
||||
of the stuff discussed in the section "Possible Improvements".
|
||||
|
||||
### ### ###
|
||||
|
||||
2. Boot Process
|
||||
|
||||
The overall boot process is quite complex but we need to know these details since we are
|
||||
talking about operating systems and to be more precise - Linux based operating systems.
|
||||
|
||||
You can find some general information here:
|
||||
|
||||
http://en.wikipedia.org/wiki/Linux_startup_process
|
||||
|
||||
When we talk about live Linux OS, the overall boot process is the following:
|
||||
|
||||
1) BIOS gives the execution control to the boot loader present on the boot media such
|
||||
as CD, DVD, USB flash or something else.
|
||||
2) In most cases the boot loader is based on Syslinux. On our boot media we should have
|
||||
two special files - the kernel file and the initramfs file.
|
||||
3) The boot media also contains a special configuration file which points to the location
|
||||
of the kernel/initramfs files.
|
||||
4) Now that Syslinux knows where the kernel file is, it loads it in the RAM and passes
|
||||
the execution control to it.
|
||||
5) The kernel detects the available hardware, loads necessary drivers and then it passes
|
||||
the execution control to the initramfs.
|
||||
6) The initramfs file is an archive which is unpacked automatically by the kernel in the
|
||||
RAM. The actual execution control is passed to the shell script file /init which must
|
||||
be present in the initramfs file.
|
||||
7) Since we are talking about minimal live CD, in theory /init is not supposed to do much.
|
||||
All we need form /init is to prepare the environment and provide the user with shell.
|
||||
In most live Linux distributions the /init script is supposed to do much more work
|
||||
but in our case for now it is enough to know that the point at which we take the control
|
||||
is exactly the /init script.
|
||||
|
||||
### ### ###
|
||||
|
||||
3. Inside The Shell Scripts
|
||||
|
||||
So far we learned that we need several pieces in order to build a live Linux OS:
|
||||
|
||||
1) boot loader - to make our media bootable.
|
||||
2) kernel file - to take care of the initial system bootstrap process.
|
||||
3) initramfs file - to prepare the necessary environment for the user.
|
||||
|
||||
This document focuses on parts (2) and (3). The reason we won't discuss (1) in details is
|
||||
because the build process that we are going to rely on later, takes care of the boot loader
|
||||
part automatically.
|
||||
|
||||
The ZIP which you have downloaded contains the following files:
|
||||
|
||||
.config
|
||||
0_prepare.sh
|
||||
1_get_kernel.sh
|
||||
2_build_kernel.sh
|
||||
3_get_busybox.sh
|
||||
4_build_busybox.sh
|
||||
5_generate_rootfs.sh
|
||||
6_pack_rootfs.sh
|
||||
7_generate_iso.sh
|
||||
build_minimal_linux_live.sh
|
||||
|
||||
If you have followed the explanation posted on http://minimal.linux-bg.org then you already
|
||||
know that you need to execute the script "build_minimal_linux_live.sh". If you open this
|
||||
file with text editor you will find out that all this script does is to execute all other
|
||||
scripts one by one.
|
||||
|
||||
From this point onwards, I encourage you to execute the script files one by one. We will
|
||||
start with "0_prepare.sh". If you take a look at the script's contents, you will find out that
|
||||
all the script does is to create an empty folder named "work". We will store our temporary
|
||||
work files there.
|
||||
|
||||
OK, let's continue with the kernel. Somehow we need to end up with fully functional kernel which
|
||||
is able to do the system initialization for us. We need to download the kernel sources, compile
|
||||
these sources and finally pack the kernel.
|
||||
|
||||
The script "1_get_kernel.sh" downloads the kernel sources and unpacks them. Here is the full
|
||||
source code of the script:
|
||||
|
||||
#/bin/sh
|
||||
|
||||
DOWNLOAD_URL=$(grep -i KERNEL_SOURCE_URL .config | cut -f2 -d'=')
|
||||
ARCHIVE_FILE=${DOWNLOAD_URL##*/}
|
||||
|
||||
cd work
|
||||
rm -f $ARCHIVE_FILE
|
||||
wget $DOWNLOAD_URL
|
||||
rm -rf kernel
|
||||
mkdir kernel
|
||||
tar -xvf $ARCHIVE_FILE -C kernel
|
||||
cd ..
|
||||
|
||||
First we read the ".config" file to find the URL for the kernel sources. The URL is stored in
|
||||
the variable "DOWNLOAD_URL". Then we get the actual name of the archive file and we store the
|
||||
name in the variable "ARCHIVE_FILE".
|
||||
|
||||
The important part of the script is the line where we get the kernel sources:
|
||||
|
||||
wget $DOWNLOAD_URL
|
||||
|
||||
The next important part of the script is the line where we unpack the kernel sources:
|
||||
|
||||
tar -xvf $ARCHIVE_FILE -C kernel
|
||||
|
||||
At this point we have downloaded and unpacked the kernel sources. So far so good. Now we need
|
||||
to compile them. We move to the next script in the chain called "2_build_kernel.sh". Here is
|
||||
the full source code that we are going to analyse:
|
||||
|
||||
#/bin/sh
|
||||
|
||||
cd work/kernel
|
||||
cd $(ls -d *)
|
||||
make clean
|
||||
make defconfig
|
||||
sed -i "s/.*CONFIG_DEFAULT_HOSTNAME.*/CONFIG_DEFAULT_HOSTNAME=\"minimal-linux-live\"/" .config
|
||||
make vmlinux
|
||||
cd ../../..
|
||||
|
||||
First we navigate to the kernel source folder. Then we execute the following commands:
|
||||
|
||||
make clean
|
||||
|
||||
The above command cleans the output from our previous kernel builds. Obviously, if this is the
|
||||
first time we go through the build process, we have nothing to clean.
|
||||
|
||||
make defconfig
|
||||
|
||||
The above command creates new ".config" file in the current folder which contains all default
|
||||
configuration parameters that we need in order to build our new kernel. Note that the defaults
|
||||
will be either 32 or 64 bit specific, depending on your Linux environment.
|
||||
|
||||
sed -i "s/.*CONFIG_DEFAULT_HOSTNAME.*/CONFIG_DEFAULT_HOSTNAME=\"minimal-linux-live\"/" .config
|
||||
|
||||
The above command searches for a specific line in the ".config" file which contains the string
|
||||
"CONFIG_DEFAULT_HOSTNAME" and replaces the whole line with the following text:
|
||||
|
||||
CONFIG_DEFAULT_HOSTNAME="minimal-linux-live"
|
||||
|
||||
Later, when you boot up your live Linux OS you can execute the command "uname -a" and you will
|
||||
see the string "minimal-linux-live" in the output. All we did was to replace the default value
|
||||
"(none)" with our custom value.
|
||||
|
||||
Now you have a sample command which you can use to search for specific configurations in the
|
||||
file ".config" and replace these configurations with your own. Obviously, you can skip this
|
||||
replacement and everything will work just fine. Like I said, the only difference will be that
|
||||
the default host name will be "minimal-linux-live" instead of "(none)".
|
||||
|
||||
Now we come to the most important and also the slowest part in the whole process. We need to
|
||||
actually create the kernel.
|
||||
|
||||
make vmlinux
|
||||
|
||||
The above command will compile the Linux kernel. This takes a lot of time, so I guess it's
|
||||
high time for a short break. The final kernel file is located here:
|
||||
|
||||
arch/x86/boot/bzImage
|
||||
|
||||
OK, at this point we should have a kernel file compiled with default options, where we have
|
||||
changed the default host name with some other value of our own. Now we move to the next
|
||||
part.
|
||||
|
||||
The kernel itself is far from enough - we also need some kind of environment with basic
|
||||
command line tools like ls, cat, mkdir, etc. This environment is called "initramfs" which
|
||||
stands for "initial RAM file system". This is what we are going to do:
|
||||
|
||||
1) We are going to download & compile BusyBox. This will give us the basic command line
|
||||
tools that we need for normal work in console mode.
|
||||
2) We will use BusyBox to provide us with some default directory/file structure which
|
||||
we will modify into our own initramfs file.
|
||||
|
||||
One by one - we need to download and unpack the BusyBox sources. Let's take a look at the
|
||||
script file "3_get_busybox.sh":
|
||||
|
||||
#/bin/sh
|
||||
|
||||
DOWNLOAD_URL=$(grep -i BUSYBOX_SOURCE_URL .config | cut -f2 -d'=')
|
||||
ARCHIVE_FILE=${DOWNLOAD_URL##*/}
|
||||
|
||||
cd work
|
||||
rm -f $ARCHIVE_FILE
|
||||
wget $DOWNLOAD_URL
|
||||
rm -rf busybox
|
||||
mkdir busybox
|
||||
tar -xvf $ARCHIVE_FILE -C busybox
|
||||
cd ..
|
||||
|
||||
The contents is almost identical to the one in "1_get_kernel.sh" which we have already
|
||||
explained above. Long story short - we get the source archive with "wget" and then we
|
||||
unpack the sources with "tar". That's it. Nothing complex at all.
|
||||
|
||||
Now that we have BusyBox sources we need to compile them. Let's take a look at the next
|
||||
script "4_build_busybox.sh" which we need to execute:
|
||||
|
||||
#/bin/sh
|
||||
|
||||
cd work/busybox
|
||||
cd $(ls -d *)
|
||||
make clean
|
||||
make defconfig
|
||||
sed -i "s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/" .config
|
||||
make busybox
|
||||
make install
|
||||
cd ../../..
|
||||
|
||||
You have probably already noticed it - we are going to execute several "make" commands
|
||||
and meanwhile we are going to change one property in the ".config" file. Let's go
|
||||
through all of these commands:
|
||||
|
||||
make clean
|
||||
|
||||
The above command ensures that we will get rid of all build artefacts, assuming this
|
||||
is not the first time we go through the BusyBox build process.
|
||||
|
||||
make defconfig
|
||||
|
||||
The above command creates new ".config" file which contains the defaults for proper
|
||||
BusyBox build process. Again, nothing extraordinary here.
|
||||
|
||||
sed -i "s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/" .config
|
||||
|
||||
The above command is very important because we inform the build process to build
|
||||
static version of BusyBox, which means that the BusyBox executable file will not
|
||||
be dependent on any external library. We cannot skip this, otherwise our OS will
|
||||
fail with "kernel panic" when we try to boot.
|
||||
|
||||
make busybox
|
||||
|
||||
The above command compiles BusyBox. Nothing interesting here. The build should be
|
||||
significantly faster compared to the kernel build.
|
||||
|
||||
make install
|
||||
|
||||
The above command creates new "_install" folder and installs BusyBox in it. We
|
||||
will use this folder as a base for our new initramfs file.
|
||||
|
||||
At this point we should have kernel compiled with default settings (yes, we changed
|
||||
one setting but it's not a big deal) and we should also have BusyBox compiled with
|
||||
static option enabled and all other default settings.
|
||||
|
||||
Now we come to the part where we create our own initramfs folder which later on we
|
||||
will pack into a file. The steps that we are going to follow are these:
|
||||
|
||||
1) Use the already created "_install" folder as base for initramfs.
|
||||
2) Create some new folders in the initramfs folder.
|
||||
3) Create some configuration files in the initramfs folder.
|
||||
|
||||
Now we come to the script "5_generate_rootfs.sh" which is responsible to generate
|
||||
proper initramfs folder with all necessary files and sub-folders in it.
|
||||
|
||||
#/bin/sh
|
||||
|
||||
cd work
|
||||
rm -rf rootfs
|
||||
cd busybox
|
||||
cd $(ls -d *)
|
||||
cp -R _install ../../rootfs
|
||||
cd ../../rootfs
|
||||
rm -f linuxrc
|
||||
mkdir dev
|
||||
mkdir etc
|
||||
mkdir proc
|
||||
mkdir src
|
||||
mkdir sys
|
||||
mkdir tmp
|
||||
cd etc
|
||||
touch welcome.txt
|
||||
echo >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' # Welcome to "Minimal Linux Live" #' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo >> welcome.txt
|
||||
cd ..
|
||||
touch init
|
||||
echo '#!/bin/sh' >> init
|
||||
echo 'dmesg -n 1' >> init
|
||||
echo 'mount -t devtmpfs none /dev' >> init
|
||||
echo 'mount -t proc none /proc' >> init
|
||||
echo 'mount -t sysfs none /sys' >> init
|
||||
echo 'cat /etc/welcome.txt' >> init
|
||||
echo 'while true' >> init
|
||||
echo 'do' >> init
|
||||
echo ' setsid cttyhack /bin/sh' >> init
|
||||
echo 'done' >> init
|
||||
echo >> init
|
||||
chmod +x init
|
||||
cp ../../*.sh src
|
||||
cp ../../.config src
|
||||
cd ../..
|
||||
|
||||
As you see, this script is much longer than the others. Let's take a look at the
|
||||
important parts one by one.
|
||||
|
||||
cd work
|
||||
rm -rf rootfs
|
||||
cd busybox
|
||||
cd $(ls -d *)
|
||||
cp -R _install ../../rootfs
|
||||
cd ../../rootfs
|
||||
|
||||
The above code snippet removes the old initramfs folder called "rootfs" and then
|
||||
copies the "_install" folder (the one created by BusyBox) with new name "rootfs".
|
||||
This folder is going to be our new initramfs focal point.
|
||||
|
||||
rm -f linuxrc
|
||||
|
||||
The folder "rootfs" contains file "linuxrc" which we don't need since we are going
|
||||
to use initramfs boot scheme. Take a look at the following Wikipedia article for
|
||||
more details:
|
||||
|
||||
http://en.wikipedia.org/wiki/Initrd
|
||||
|
||||
OK, lets go on.
|
||||
|
||||
mkdir dev
|
||||
mkdir etc
|
||||
mkdir proc
|
||||
mkdir src
|
||||
mkdir sys
|
||||
mkdir tmp
|
||||
|
||||
The above code snippet creates some basic folders which we are going to use later.
|
||||
|
||||
cd etc
|
||||
touch welcome.txt
|
||||
echo >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' # Welcome to "Minimal Linux Live" #' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo >> welcome.txt
|
||||
cd ..
|
||||
|
||||
The above code snippet creates the file "/etc/welcome.txt" and fills it with the message
|
||||
which will be displayed every time we boot up the system.
|
||||
|
||||
touch init
|
||||
echo '#!/bin/sh' >> init
|
||||
echo 'dmesg -n 1' >> init
|
||||
echo 'mount -t devtmpfs none /dev' >> init
|
||||
echo 'mount -t proc none /proc' >> init
|
||||
echo 'mount -t sysfs none /sys' >> init
|
||||
echo 'cat /etc/welcome.txt' >> init
|
||||
echo 'while true' >> init
|
||||
echo 'do' >> init
|
||||
echo ' setsid cttyhack /bin/sh' >> init
|
||||
echo 'done' >> init
|
||||
echo >> init
|
||||
|
||||
The above code snippet creates the file "/init" which is going to be invoked by our kernel
|
||||
when we boot up the system. In fact we create new shell script file. This is what our new
|
||||
"/init" script does:
|
||||
|
||||
dmesg -n 1 - We hide all kernel messages. We don't want them in our
|
||||
console. Only kernel panic messages will be displayed.
|
||||
mount -t devtmpfs none /dev - With this command we politely ask the kernel to
|
||||
populate the /dev folder with all necessary system
|
||||
devices like "console", "tty", etc. We also have nice
|
||||
names for the hardware devices like "sr0", "sda", etc.
|
||||
mount -t proc none /proc - The kernel populates the /proc folder.
|
||||
mount -t sysfs none /sys - The kernel populates the /sys folder.
|
||||
cat /etc/welcome.txt - Now we display the welcome message.
|
||||
while true - This code snippet starts shell on "tty" device and
|
||||
setsid cttyhack /bin/sh we rest assured that when we execute the "exit"
|
||||
done command new shell will be started automatically.
|
||||
|
||||
As you see, the "/init" script file doesn't do much but what it does is really essential.
|
||||
We have only one more bit of code relevant to the "/init" file:
|
||||
|
||||
chmod +x init
|
||||
|
||||
The above command ensures that our "/init" script is executable.
|
||||
|
||||
cp ../../*.sh src
|
||||
cp ../../.config src
|
||||
|
||||
The last thing we do is to copy all "Minimal Linux Live" shell scripts (including the
|
||||
configuration file) in the "/src" folder. The scripts won't do anything there. This step
|
||||
simply ensures that the live Linux ISO file which we are going to create later contains
|
||||
the build sources, just for reference.
|
||||
|
||||
OK, at this point we have "rootfs" folder which contains all necessary files and
|
||||
configurations for our initramfs file. The next step is to pack the "rootfs" folder
|
||||
into an actual initramfs file. Let's take a look at "6_pack_rootfs.sh":
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
cd work
|
||||
rm -f rootfs.cpio.gz
|
||||
cd rootfs
|
||||
find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz
|
||||
cd ../..
|
||||
|
||||
The above script removes the already existing initramfs file called "rootfs.cpio.gz"
|
||||
and then creates a new file called "rootfs.cpio.gz" based on the contents of the
|
||||
"rootfs" folder.
|
||||
|
||||
We are almost finished. At this point we have already compiled the Linux kernel and we
|
||||
have also created initramfs file based on BusyBox and our own set of configurations.
|
||||
The last thing to do is to generate bootable ISO file. Let's take a look at the last
|
||||
script "7_generate_iso.sh":
|
||||
|
||||
#/bin/sh
|
||||
|
||||
rm -f minimal_linux_live.iso
|
||||
cd work/kernel
|
||||
cd $(ls -d *)
|
||||
make isoimage FDINITRD=../../rootfs.cpio.gz
|
||||
cp arch/x86/boot/image.iso ../../../minimal_linux_live.iso
|
||||
cd ../../..
|
||||
|
||||
As usual, we first remove the already generated ISO file, assuming this is not the first
|
||||
time we go through this process. Then we navigate to the kernel's source folder and
|
||||
we execute the following command:
|
||||
|
||||
make isoimage FDINITRD=../../rootfs.cpio.gz
|
||||
|
||||
The above command generates bootable ISO based on the already compiled Linux kernel and
|
||||
it uses the initramfs file which we pass to the "make" command as additional parameter.
|
||||
The generated ISO file is then copied to the folder where we are executing our scripts.
|
||||
|
||||
### ### ###
|
||||
|
||||
4. Possible Improvements
|
||||
|
||||
Now that you have played around with your shiny new live Linux OS, you have probably
|
||||
noticed that you are logged in automatically and you have no restrictions. However,
|
||||
it only looks like you are automatically logged in. Yes, you get shell console and
|
||||
this console allows you to perform "root" operations, but this doesn't mean that you
|
||||
are logged in as "root" or any other user. In fact there are no users and groups in
|
||||
the system.
|
||||
|
||||
I'll show you the proper way to add some users and groups from within your system
|
||||
while it is still running. You can examine the final result for yourself and modify
|
||||
the "5_generate_rootfs.sh" script according to your needs.
|
||||
|
||||
OK, let's go with the "root" account!
|
||||
|
||||
touch /etc/group
|
||||
|
||||
The above command will create empty file "/etc/group" where we store the information
|
||||
for all groups.
|
||||
|
||||
addgroup -g 0 root
|
||||
|
||||
The above command will create a group "root" with group identification number "0".
|
||||
It is important to provide 0 (zero) as group identifier (gid) because this is the
|
||||
expected gid for "root".
|
||||
|
||||
touch /etc/passwd
|
||||
|
||||
The above command will create empty file "/etc/passwd" where we store the login
|
||||
information for our users.
|
||||
|
||||
adduser -h /root -G root -u 0 root
|
||||
|
||||
The above command will create user "root" with home folder "/root", assign the new
|
||||
user to the "root" group and set user identifier (uid) "0". It is important to
|
||||
provide 0 (zero) as uid because this is the expected uid for the "root" user. Add
|
||||
whatever password you want when asked. Try to remember it.
|
||||
|
||||
login
|
||||
|
||||
The above command will initiate the login process. Now you should be able to log in
|
||||
as "root" with the password which you have provided.
|
||||
|
||||
--- --- ---
|
||||
|
||||
Another possible improvement is to set appropriate "global" rights (including the 't'
|
||||
sticky flag) for the /tmp folder. You can do that by executing the following command:
|
||||
|
||||
chmod 1777 /tmp
|
||||
|
||||
The reason I haven't included this in the /init script is because in this particular
|
||||
situation it doesn't really matter. By default we get uid=0 shell console and we have
|
||||
full and unrestricted access to the /tmp folder. However, if you decide to add more
|
||||
users to the system (not just the "root" user), you may also include the above command
|
||||
in the /init script file.
|
||||
|
||||
--- --- ---
|
||||
|
||||
Probably the easiest update you can do is to re-compile the kernel with other than
|
||||
default options. This is how we do it for the kernel. First of all we need to know
|
||||
what possible options we have. Navigate to the kernel's source folder and execute the
|
||||
following command:
|
||||
|
||||
make help
|
||||
|
||||
We have several options for interactive ".config" generation. Let's go with this one:
|
||||
|
||||
make menuconfig
|
||||
|
||||
You might need to resolve one more dependency ("ncurses") if you want the above command
|
||||
to work. Once you do that you can choose any kernel configuration options you like. The
|
||||
provided menu is quite complex but we are not in hurry. Take your time and enable or
|
||||
disable any options you want. Don't forget to save your configuration. Now all we need
|
||||
is to compile the new kernel.
|
||||
|
||||
make vmlinux
|
||||
|
||||
Depending on your configuration this time the build might take longer. Obviously if
|
||||
you decide to go through manual kernel ".config" configuration you can no longer use
|
||||
the script "2_build_kernel.sh" because it will override your new configuration with
|
||||
the default configuration.
|
||||
|
||||
--- --- ---
|
||||
|
||||
Even though we haven't discussed this topic, you might have already noticed that the
|
||||
file ".config" which comes along with the other build scripts contains the URL
|
||||
locations for the kernel sources and the BusyBox sources. You can easily build live
|
||||
Linux OS based on different kernel/BusyBox versions if you provide different
|
||||
URLs in the ".config" file. Here is the content of the default ".config" file:
|
||||
|
||||
# You can find the latest Linux kernel source bundles here:
|
||||
#
|
||||
# http://kernel.org
|
||||
#
|
||||
KERNEL_SOURCE_URL=https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.15.6.tar.xz
|
||||
|
||||
# You can find the latest BusyBox source bundles here:
|
||||
#
|
||||
# http://busybox.net
|
||||
#
|
||||
BUSYBOX_SOURCE_URL=http://busybox.net/downloads/busybox-1.22.1.tar.bz2
|
||||
|
||||
Of course, once you do that you also need to go through the scripts "1_get_kernel.sh"
|
||||
and "3_get_busybox.sh" or execute the relevant commands from these scripts manually.
|
||||
|
||||
--- --- ---
|
||||
|
||||
Another very interesting improvement is to execute /sbin/init and rely on further
|
||||
configuration provided in /etc/inittab. Here is the modified version of the shell
|
||||
script "5_generate_rootfs.sh":
|
||||
|
||||
#/bin/sh
|
||||
|
||||
cd work
|
||||
rm -rf rootfs
|
||||
cd busybox
|
||||
cd $(ls -d *)
|
||||
cp -R _install ../../rootfs
|
||||
cd ../../rootfs
|
||||
rm -f linuxrc
|
||||
mkdir dev
|
||||
mkdir etc
|
||||
mkdir proc
|
||||
mkdir src
|
||||
mkdir sys
|
||||
mkdir tmp
|
||||
cd etc
|
||||
touch bootscript.sh
|
||||
echo '#!/bin/sh' >> bootscript.sh
|
||||
echo 'dmesg -n 1' >> bootscript.sh
|
||||
echo 'mount -t devtmpfs none /dev' >> bootscript.sh
|
||||
echo 'mount -t proc none /proc' >> bootscript.sh
|
||||
echo 'mount -t sysfs none /sys' >> bootscript.sh
|
||||
echo >> bootscript.sh
|
||||
chmod +x bootscript.sh
|
||||
touch welcome.txt
|
||||
echo >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' # Welcome to "Minimal Linux Live" #' >> welcome.txt
|
||||
echo ' # #' >> welcome.txt
|
||||
echo ' #####################################' >> welcome.txt
|
||||
echo >> welcome.txt
|
||||
touch inittab
|
||||
echo '::sysinit:/etc/bootscript.sh' >> inittab
|
||||
echo '::restart:/sbin/init' >> inittab
|
||||
echo '::ctrlaltdel:/sbin/reboot' >> inittab
|
||||
echo '::once:cat /etc/welcome.txt' >> inittab
|
||||
echo '::respawn:/bin/cttyhack /bin/sh' >> inittab
|
||||
echo 'tty2::once:cat /etc/welcome.txt' >> inittab
|
||||
echo 'tty2::respawn:/bin/sh' >> inittab
|
||||
echo 'tty3::once:cat /etc/welcome.txt' >> inittab
|
||||
echo 'tty3::respawn:/bin/sh' >> inittab
|
||||
echo 'tty4::once:cat /etc/welcome.txt' >> inittab
|
||||
echo 'tty4::respawn:/bin/sh' >> inittab
|
||||
echo >> inittab
|
||||
cd ..
|
||||
touch init
|
||||
echo '#!/bin/sh' >> init
|
||||
echo 'exec /sbin/init' >> init
|
||||
echo >> init
|
||||
chmod +x init
|
||||
cp ../../*.sh src
|
||||
cp ../../.config src
|
||||
cd ../..
|
||||
|
||||
The above script creates very minimal /init which executes /sbin/init. Then the
|
||||
new init process (that is /sbin/init with PID 1) reads the file /etc/inittab and
|
||||
executes all commands provided there. The script /etc/bootscript.sh takes care of
|
||||
the initial "mount" stuff. We also have 4 terminals (you can switch between them
|
||||
with "Alt + F1" to "Alt + F4") and the contents of the file /etc/welcome.txt is
|
||||
displayed before we access the shell for each of these terminals.
|
||||
|
||||
You can find more information about the supported /etc/inittab commands here:
|
||||
|
||||
http://git.busybox.net/busybox/tree/examples/inittab
|
||||
|
||||
Note that the above details are specific for BusyBox. Usually the "init" process
|
||||
supports runlevels but that's not the case with BusyBox.
|
||||
|
||||
--- --- ---
|
||||
|
||||
Most probably you use normal user (i.e. not "root") when you execute the scripts.
|
||||
One side effect is that the generated initrtamfs will keep the original ownership
|
||||
of all files and folders. However, this leads to some interesting discrepancies
|
||||
when you run the system. Some of the files/folders will have "root" ownership
|
||||
(uid=0, gid=0) but most of the files/folders will have the same uid/gid as the
|
||||
user which you used in order to build the system. This has no implications at all
|
||||
since we have unrestricted shell console but if you'd like to "fix" this you will
|
||||
have to either execute "5_generate_rootfs.sh" as "root" or manually change the
|
||||
ownership of the initramfs folder (i.e. "work/rootfs") before you execute the
|
||||
script "6_pack_rootfs.sh" with this command:
|
||||
|
||||
chown -R root:root work/rootfs
|
||||
|
||||
Note that the above command requires "root" permissions, so there is no way to
|
||||
escape from the above described discrepancies if you don't have "root" access.
|
||||
|
||||
Also note that you may need to take care of the permissions for the script files
|
||||
in the "work/rootfs/src" folder. Either delete the "src" folder before you run
|
||||
"6_pack_rootfs.sh" or make sure that all files have global "read" permissions.
|
||||
|
||||
### ### ###
|
||||
|
||||
5. Next Steps
|
||||
|
||||
OK, now we know how to build and run a basic Linux system. But that's not enough.
|
||||
Now we want to build more complex system, probably one which supports "pacman",
|
||||
"apt-get", or any other package manager.
|
||||
|
||||
Building such system requires a lot more work. A lot more! I mean it!
|
||||
|
||||
For starters, "Minimal Linux Live" lives entirely in the "initramfs" space. Simply
|
||||
said - this is the RAM space. We never really get out of there. Basically this is
|
||||
what you need if you want more functional live Linux system:
|
||||
|
||||
1) Compressed file system (SquashFS)- this is where all the real stuff will be.
|
||||
|
||||
2) GNU Coreutils - these are the real shell command line utilities (ls, cd, etc.).
|
||||
You need them because later we are going to "escape" from "initramfs" and use
|
||||
the actual file system available in the compressed file. Alternatively, you can
|
||||
overlay the whole "BusyBox" environment on top of the compressed file system but
|
||||
that's not really professional approach.
|
||||
|
||||
3) You need to "switch_root" to the actual file system (the compressed one) which
|
||||
you first need to locate, then mount and finally make it "writable" by overlaying
|
||||
virtual RAM files/folders via UnionFS/AuFS (or something similar) if the bootable
|
||||
media is not already writable. Remember that you are mounting compressed FS, which
|
||||
means that if you make any changes on files located in the original FS, they will
|
||||
not be persisted between reboots. Probably you want to handle this edge case.
|
||||
|
||||
4) You need to prepare in advance the stuff that you want to be present in the
|
||||
compressed file system. Assuming that we are building a useful live Linux OS, the
|
||||
absolute minimum is "GNU Coreutils", network management utilities and probably
|
||||
some kind of package manager, e.g. "pacman" or "apt-get". Don't forget that most
|
||||
of this additional stuff most probably relies on different kernel options that
|
||||
also need to be enabled/configured in advance.
|
||||
|
||||
5) You need to rewrite /init and make it execute all necessary steps to fulfil point 3
|
||||
from the above. Different live Linux systems use different approaches here.
|
||||
|
||||
All of the above is definitely *not* minimal but it's definitely doable if you put some
|
||||
additional efforts. It will take time but as a result you will have fully functional live
|
||||
Linux OS which you have created entirely by yourself.
|
||||
|
||||
### ### ###
|
||||
|
||||
6. Epilogue
|
||||
|
||||
That's all folks! I hope you find this tutorial useful. And remember, we are talking
|
||||
about very minimal live Linux OS here. If you want to create something bigger, I
|
||||
suggest you take a look at "Linux From Scratch" (google it, you'll find it).
|
||||
|
||||
At some point you may also find it useful to play around with other live Linux
|
||||
distributions. Don't forget that the initramfs file is compressed and in order to
|
||||
get to the actual /init script you will need to uncompress it. Then you can see
|
||||
the actual file structure of the initial root file system and examine the /init
|
||||
script file. This will give you more insight on the boot process for the
|
||||
particular live Linux distributions that you are learning from.
|
||||
|
||||
One interesting live Linux distribution is "Slax". Just download it and take a
|
||||
look at the /init script file (remember, you can uncompress the initramfs file).
|
||||
There is also a very good document which explains the internal root file system
|
||||
and the OS boot process for Slax:
|
||||
|
||||
http://slax.org/en/documentation.php#internals
|
||||
|
||||
The above URL may have changed but it is valid at the time I write this document.
|
||||
|
Loading…
x
Reference in New Issue
Block a user