LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (http://www.linuxquestions.org/questions/slackware-14/)
-   -   Slackware 13.37 Running from USB (Done with qemu) (http://www.linuxquestions.org/questions/slackware-14/slackware-13-37-running-from-usb-done-with-qemu-889168/)

ljones0 06-30-2011 07:57 AM

Slackware 13.37 Running from USB (Done with qemu)
 
Hello all! :)

I've finally managed to get slackware 13.37 (32 bit) to run from a USB stick. Note, actually run as opposed to running the installer.

By and large it is a modification of the instructions found here.

To do this, I used the following;

* A copy of slackware 13.37 32 bit from DVD
* A compaq CQ60 64-bit laptop running slackware 13.37 from the hard drive
* A copy of the latest version of qemu installed on the compaq laptop's hard drive (version 0.14.50).
* An 8GB SD Card (could also be a USB stick if you don't want to use a SD card).
* Syslinux (the default version in slackware 13.37).

Before you begin....
This procedure will need to be done on a reasonably new PC that is fast enough and can boot from USB properly (not all systems can). Also even some newer systems might not work, for example the laptop I was using (a 64-bit Compaq CQ60) works fine (as does an older Asus EEEPC 904HD), whereas my normal desktop PC (using a M3A78EM motherboard) would not boot properly and would hang, for reasons unknown :-( .

Instructions

Before you begin, you'll need this file (must be named init) -
Code:

#!/bin/ash
#
# /init:  init script to load kernel modules from an initramfs
#        This requires that your kernel supports initramfs!!!
#
# Copyright 2004  Slackware Linux, Inc., Concord, CA, USA
# Copyright 2007, 2008, 2009, 2010  Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


# With a generic kernel, you need to load the modules needed to mount the
# root partition.  This might mean a SCSI, RAID, or other drive controller
# module, as well as the module to support the root filesystem.  Once the
# root partition is mounted all the other modules will be available so you
# don't need to load them here.
#
# Config files used by this script:
#
# /rootdev        Contains the name of the root device, such as: /dev/hda1
#
# /rootfs        Contains the root filesystem type, such as: xfs
#
# /initrd-name    Contains the name of the initrd file.
#
# /resumedev      Contains the name of the device to resume from hibernation.
#
# /luksdev        Contains colon separated list of luks encrypted devices to
#                be unlocked.
#
# /lukskey        Contains the path to a LUKS key-file for automatic unlock
#                Format: LABEL=<partition_label>:/path/to/file
#                        UUID=<partition_uuid>:/path/to/file
#
# /wait-for-root  Contains a number - the init script will wait this amount
#                of seconds before creating device nodes.
#
# /keymap        Contains the name for a custom keyboard map
#
# Optional:
#
# /load_kernel_modules
#                A script that uses modprobe to load the desired modules.
#
#                There's an example in here.  To actually use it, you'll
#                need to make it executable: 
#
#                    chmod 755 load_kernel_modules

INITRD=$(cat /initrd-name)
#ROOTDEV=$(cat /rootdev)
#ROOTFS=$(cat /rootfs)
LUKSDEV=$(cat /luksdev)
LUKSKEY=$(cat /lukskey)
RESUMEDEV=$(cat /resumedev)
WAIT=$(cat /wait-for-root)
KEYMAP=$(cat /keymap)
INIT=/sbin/init

PATH="/sbin:/bin:/usr/sbin:/usr/bin"

# Mount /proc and /sys:
mount -n proc /proc -t proc
mount -n sysfs /sys -t sysfs

if grep devtmpfs /proc/filesystems 1>/dev/null 2>/dev/null ; then
  DEVTMPFS=1
  mount -n devtmpfs /dev -t devtmpfs
fi       

# NEW - Added label and uuid *) below.
# Parse command line
for ARG in $(cat /proc/cmdline); do
  case $ARG in
    0|1|2|3|4|5|6|S|s|single)
      RUNLEVEL=$ARG
    ;;
    label=*)
      LABEL_FOR_ROOT=`echo $ARG | cut -f2 -d=`
    ;;
    uuid=*)
      UUID_FOR_ROOT=`echo $ARG | cut -f2 -d=`
    ;;
    install)
      RESCUE=2
    ;;
    init=*)
      INIT=$(echo $ARG | cut -f2 -d=)
    ;;
    luksdev=/dev/*)
      LUKSDEV=$(echo $ARG | cut -f2 -d=)
    ;;
    lukskey=*)
      LUKSKEY=$(echo $ARG | cut -f2- -d=)
    ;;
    rescue)
      RESCUE=1
    ;;
    resume=*)
      RESUMEDEV=$(echo $ARG | cut -f2 -d=)
    ;;
    root=/dev/*)
      ROOTDEV=$(echo $ARG | cut -f2 -d=)
    ;;
    root=LABEL=*)
      ROOTDEV=$(echo $ARG | cut -f2- -d=)
    ;;
    root=UUID=*)
      ROOTDEV=$(echo $ARG | cut -f2- -d=)
    ;;
    rootfs=*)
      ROOTFS=$(echo $ARG | cut -f2 -d=)
    ;;
    waitforroot=*)
      WAIT=$(echo $ARG | cut -f2 -d=)
    ;;
  esac
done

# Load kernel modules:
if [ ! -d /lib/modules/$(uname -r) ]; then
  echo "No kernel modules found for Linux $(uname -r)."
elif [ -x ./load_kernel_modules ]; then # use load_kernel_modules script:
  echo "${INITRD}:  Loading kernel modules from initrd image:"
  . ./load_kernel_modules
else # load modules (if any) in order:
  if ls /lib/modules/$(uname -r)/*.*o 1> /dev/null 2> /dev/null ; then
    echo "${INITRD}:  Loading kernel modules from initrd image:"
    for module in /lib/modules/$(uname -r)/*.*o ; do
      /sbin/modprobe $module
    done
    unset module
  fi
fi

# Sometimes the devices need extra time to be available.
# A root filesystem on USB is a good example of that.
sleep $WAIT

# If udevd is available, use it to generate block devices
# else use mdev to read sysfs and generate the needed devices
if [ -x /sbin/udevd -a -x /sbin/udevadm ]; then
  /sbin/udevd --daemon --resolve-names=never
  /sbin/udevadm trigger --subsystem-match=block --action=add
  /sbin/udevadm settle --timeout=10
else
  [ "$DEVTMPFS" != "1" ] && mdev -s
fi

# Load a custom keyboard mapping:
if [ -n "$KEYMAP" ]; then
  echo "${INITRD}:  Loading '$KEYMAP' keyboard mapping:"
  tar xzOf /etc/keymaps.tar.gz ${KEYMAP}.bmap | loadkmap
fi

if [ "$RESCUE" = "" ]; then
  # Initialize RAID:
  if [ -x /sbin/mdadm ]; then
    /sbin/mdadm -E -s >/etc/mdadm.conf
    /sbin/mdadm -S -s
    /sbin/mdadm -A -s
    # This seems to make the kernel see partitions more reliably:
    fdisk -l /dev/md* 1> /dev/null 2> /dev/null
  fi

echo "1"
/bin/blkid
read key1

# NEW
 if [ "$ROOTDEV" = "" ]; then
  echo "Waiting 10 seconds ...."
  sleep 10
  echo "LABEL_FOR_ROOT=" $LABEL_FOR_ROOT
  while [ "$ROOTDEV" = "" ]
  do
    PARTITIONS=`cat /proc/partitions`
    BLKID=`/bin/blkid -c /dev/null`
    echo $BLKID
    echo $PARTITIONS
   
    if [ ! "$LABEL_FOR_ROOT" = "" ]; then
      BLKID_ROOT=`/bin/blkid -c /dev/null -s TYPE -t LABEL=$LABEL_FOR_ROOT`
    else
      BLKID_ROOT=`/bin/blkid -c /dev/null -s TYPE -t UUID=$UUID_FOR_ROOT`
    fi
    echo "Found: "$BLKID_ROOT
    ROOTDEV=`echo $BLKID_ROOT | awk 'BEGIN{FS=":"}{print $1}'`
    ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($2);print substr($2,2,l-2)}'`
   
    done
  fi
# NEW-END

echo "2"

  # Unlock any encrypted partitions necessary to access the
  # root filesystem, such as encrypted LVM Physical volumes, disk
  # partitions or mdadm arrays.
  # Unavailable devices such as LVM Logical Volumes will need to be
  # deferred until they become available after the vgscan.

  if [ -x /sbin/cryptsetup ]; then

echo "3"

    # Determine if we have to use a LUKS keyfile:
    if [ ! -z "$LUKSKEY" ]; then
      mkdir  /mountkey
      KEYPART=$(echo $LUKSKEY |cut -f1 -d:)
      LUKSPATH="/mountkey$(echo $LUKSKEY |cut -f2 -d:)"
      # Catch possible mount failure:
      if blkid -t TYPE=vfat $KEYPART 1>/dev/null 2>&1 ; then
        MOUNTOPTS="-t vfat -o shortname=mixed"
      else
        MOUNTOPTS="-t auto"
      fi
      mount $MOUNTOPTS $(findfs $KEYPART) /mountkey 2>/dev/null
      # Check if we can actually use this file:
      if [ ! -f $LUKSPATH ]; then
        LUKSKEY=""
      else
        echo ">>> Using LUKS key file: '$LUKSKEY'"
        LUKSKEY="-d $LUKSPATH"
      fi
    fi

echo "4"

    LUKSLIST_DEFERRED=""
    LUKSLIST=$(echo $LUKSDEV | tr -s ':' ' ')
    for LUKSDEV in $LUKSLIST ; do
      if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
        if echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
          CRYPTDEV="luks$(basename $LUKSDEV)"
        elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
          CRYPTDEV="$ROOTDEV"
        else
          CRYPTDEV="luks$(basename $LUKSDEV)"
        fi
        echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
        /sbin/cryptsetup ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
        if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
          ROOTDEV="/dev/mapper/$CRYPTDEV"
        fi
      else
        LUKSLIST_DEFERRED="${LUKSLIST_DEFERRED} ${LUKSDEV}"
      fi
    done
  fi

echo "5"

  # Initialize LVM:
  if [ -x /sbin/vgchange ]; then
    /sbin/vgchange -ay --ignorelockingfailure
  fi
 
echo "6"

  # Unlock any LUKS encrypted devices that were deferred above but have now
  # become available due to the vgscan (i.e. filesystems on LVM Logical Volumes)

  if [ -x /sbin/cryptsetup -a -n "${LUKSLIST_DEFERRED}" ]; then
    for LUKSDEV in ${LUKSLIST_DEFERRED} ; do
      if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
        if echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
          CRYPTDEV="luks$(basename $LUKSDEV)"
        elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
          CRYPTDEV="$ROOTDEV"
        else
          CRYPTDEV="luks$(basename $LUKSDEV)"
        fi
        echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
        /sbin/cryptsetup ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
        if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
          ROOTDEV="/dev/mapper/$CRYPTDEV"
        fi
      else
        echo "LUKS device '${LUKSDEV}' unavailable for unlocking!"
      fi
    done
  fi

echo "7"

  # Find root device if a label or UUID was given:
  if echo $ROOTDEV | grep -q "LABEL=" || \
    echo $ROOTDEV | grep -q "UUID=" ; then
    ROOTDEV=$(findfs $ROOTDEV)
  fi

echo "8"

  # Clean up after LUKS unlock using a keyfile:
  if grep -q mountkey /proc/mounts 2>/dev/null ; then
    umount -l /mountkey
    rmdir /mountkey 2>/dev/null
  fi

echo "9"

  # Resume state from swap
  if [ "$RESUMEDEV" != "" ]; then
    if ls -l $RESUMEDEV | grep -q "^l" ; then
      RESUMEDEV=$(ls -l $RESUMEDEV | awk '{ print $NF }')
    fi
    echo "Trying to resume from $RESUMEDEV"
    RESMAJMIN=$(ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }')
    echo $RESMAJMIN > /sys/power/resume
  fi
 
echo "10"
 
  # Switch to real root partition:
  echo 0x0100 > /proc/sys/kernel/real-root-dev
 
  echo "rootfs is "$ROOTFS
  echo "rootdev is "$ROOTDEV
 
  mount -o ro -t $ROOTFS $ROOTDEV /mnt
 
  if [ ! -r /mnt/sbin/init ]; then
    echo "ERROR:  No /sbin/init found on rootdev (or not mounted).  Trouble ahead."
    echo "        You can try to fix it. Type 'exit' when things are done."
    echo
    /bin/sh
  fi
else
  echo
  echo "RESCUE mode"
  echo
  echo "        You can try to fix or rescue your system now. If you want"
  echo "        to boot into your fixed system, mount your root filesystem"
  echo "        read-only under /mnt:"
  echo
  echo "            # mount -o ro -t filesystem root_device /mnt"
  echo
  echo "        Type 'exit' when things are done."
  echo
  /bin/sh
fi

echo "11"

if pgrep udevd >/dev/null ; then
  /sbin/udevadm settle --timeout=30
  pkill udevd
fi

echo "12"

unset ERR
echo "13"
mount -o move /proc /mnt/proc
echo "14"
mount -o move /sys /mnt/sys
[ "$DEVTMPFS" = "1" ] && mount -o move /dev /mnt/dev
echo "15"
echo "${INITRD}:  exiting"
exec switch_root /mnt $INIT $RUNLEVEL

Note
In the above init file there are 3 lines;
Code:

echo "1"
/bin/blkid
read key1

You can omit the "read key1" line I simpy put this in a test to see what was happening inside the script when modifying it.

1. Open a terminal (e.g. konsole) and insert the SD card or USB stick.

2. Find out the sd/USB device name by running dmesg as root. (Mine appeared as sdb).

3. Type exit (no longer root).

4. Boot the slackware DVD by using qemu; (Note, /dev/sdb is the sd/USB device!).
Code:

qemu -boot d -cdrom /dev/sr0 -hda /dev/sdb
5. Let the DVD boot normally in qemu then create two partitions with cfdisk with the first partition as w95fat32 (type B), the second linux, e.g.
Code:

Name      Flags          Part Type    Fs Type              [label]              Size(MB)
 sda1      Boot          Primary      W95 FAT32                                98.71 
 sda2                    Primary      Linux                                    7849.51*

Note that the SD/USB device will appear as /dev/sda in qemu, so the dos partition from within qemu will be /dev/sda1, with the linux partition as /dev/sda2.

6. Continue to do a normal slackware install. As a test, just install A, AP and Y. From memory, the linux partition was formatted with slackware 13.37's default, ext4.

7. Let the installer continue as normal but don't install Lilo, just its package!.

8. Once the installer finishes, exit and let qemu restart. Then when qemu restarts and boots the slackware DVD at the boot prompt type;
Code:

boot: hugesmp.s root=/dev/sda2 rdinit= ro
9. This should now boot you into the newly installed system. Let it boot.

10. From the newly installed system, type;
Code:

mkdosfs /dev/sda1
11. Now type the following;
Code:

mkdir /tmp/0
mount /dev/sda1 /tmp/0
cd /boot
mkinitrd

12. And now these;
Code:

cd initrd-tree

rm bin/awk
rm bin/cut

cp /lib/libblkid.so.1 lib/
cp /lib/libext2fs.so.2 lib/
cp /lib/libc.so.6 lib/
cp /lib/libuuid.so.1 lib/
cp /lib/libcom_err.so.2 lib/
cp /lib/ld-linux.so.2 lib/
cp /lib/libpthread.so.0 lib/
cp /lib/libdl.so.2 lib/
cp /lib/libm.so.6 lib/

cp /usr/bin/awk bin/
cp /sbin/blkid bin/
cp /bin/cut bin/

cd ..

mount /dev/dvd /mnt/dvd
installpkg -root /boot/initrd-tree /mnt/dvd/slackware/a/devs*

13. Copy the init file above from whereever you stored it and then copy it into /boot/initrd-tree.

14. Then run these commands;
Code:

cd /boot
mkinitrd

15. Next modify the newly installed systems' /etc/fstab. With a text editor (e.g. jed) change the first line of /etc/fstab from
Code:

/dev/sda2          /        ext4    defaults 1 1
to
Code:

/dev/root          /        ext4    defaults 1 1
16. Next label the second partition on the SD/USB device by typing;
Code:

e2label /dev/sda2 TEST
17. Copy the files needed to boot from the SD/USB device onto the dos partition (e.g. /dev/sda1) and make the directory - we'll use SYSLINUX to boot with.
Code:

mkdir /tmp/0/syslinux
cp /boot/vmlinuz /tmp/0/syslinux
cp /boot/initrd.gz /tmp/0/syslinux

18. Next create the syslinux.cfg file for syslinux - it needs to be placed into the dos partition - /syslinux/syslinux.cfg (eg /tmp/0/syslinux/syslinux.cfg);
Code:

default vmlinuz initrd=initrd.gz label="TEST"
Note that the word label must be in lower case, it dosen't seem to work in upperase.

19. Now type;
Code:

cd /tmp/0
syslinux -s /dev/sda1

20 And then create an MBR for linux on the SD/USB device;
Code:

lilo -M /dev/sda
Finally,
Code:

umount /tmp/0
Unmount any other mounted devices, type sync, wait for any devices to finish writing, reboot and hope it works!

Hopefully I didn't forget anything above :-) !

ljones

linus72 06-30-2011 08:24 AM

liones0

you may also be interested in this
http://www.linuxquestions.org/questi...ml#post3969567

see here for some premade ones though the slack one is not there anymore but easy to make
http://multidistro.com/downloads/por...portables.html

andrewthomas 07-20-2011 10:27 AM

Using qemu is unnecessary, in my opinion.

I just installed from the slackware-current DVD directly to a USB drive,

used UUID's in my fstab,

installed grub2 to the MBR of my USB-stick and I am up and running.

the_zone 04-06-2013 07:49 AM

I know this an old thread, but i can not get it working.

I followed the instructions to the letter.

I get the following error :

mount: mounting /dev/sda2 on /mnt failed: No such file or directory
ERROR: No /sbin/init found on rootdev (or not mounted). Trouble ahead.


What I have noticed is that the init script is overwritten while running mkinitrd the second time.
I fail to understand why it is necessary to run mkinitrd twice and without any parameters.

any suggestions ?

grtz

ST

the_zone 04-07-2013 03:28 AM

One step further.

executing :

mkinitrd --with-usb -c -k 2.6.33.4-smp -f ext4 -r /dev/sda2

solved the previous error.
I see echo "1" scrolling by. So at least it is initing.

The next issue is that it keeps printing the output from blkid.
Like it is in some sort of loop.

grtz

ST

the_zone 05-18-2013 02:58 PM

Sort of solved it.

I mananaged to install slackware via the above mentioned QEMU method on one usb-stick only.

The second one did not work.
It seemed that the USB device was not initialized in time.
Finally I solved it by installing slackware 14.0 directly on a USB stick and booting via the DVD with rootdelay=10.

jtsn 05-18-2013 08:09 PM

It should be mentioned that USB thumb-drives or SD memory cards formatted with ext4 may not last very long due to hefty write amplification caused by ext4's 4K blocksize and metadata journaling. The cheap flash drives are usually designed around FAT's 32K block size and may do read-modify-write cycles at the 512K or 1024K erase-block level.

AUFS-based turnkey solutions like SLAX already exist for exact this scenario - including persistence on USB drives without introducing wear & tear. So I would recommend using them instead.

Of course you can still install Slackware to a regular USB hard-drive and boot it with LILO. As long as you use a suitable initrd and UUIDs for your partitions you don't need special measures beside that. Unlike Windows Linux supports booting from USB storage out of the box.

the_zone 05-20-2013 07:57 AM

@jtsn

Thanks for your comments.I will have a look at SLAX and aufs.
I preferably stay with slackware itself since I have been using it a long time and know my way.

Would it matter to use ext2 ?

I also found this :

http://www.cyrius.com/debian/nslu2/linux-on-flash/

jtsn 05-20-2013 11:37 AM

Quote:

Originally Posted by the_zone (Post 4954830)
Thanks for your comments.I will have a look at SLAX and aufs.
I preferably stay with slackware itself since I have been using it a long time and know my way.

SLAX is Slackware customized to run from CD-ROM and USB thumbdrives.

Quote:

Would it matter to use ext2 ?
At least you want to have something like F2FS. It's available on Linux 3.8 and later.


All times are GMT -5. The time now is 04:34 AM.