Almost a year ago, I volunteered to help set up a couple of IPCop boxes for the purpose of basic firewalling, VPN, and QOS between two sites. I am always leery of building Linux based systems to do the work of embedded devices, since computers (unless you spend extra for them) tend to be less reliable in my experience. One also considers power and moving parts. The end goal was to be able to take any computer with two ethernet ports, and capable of booting from a USB "thumb drive", and turn it into an instant firewall. I struggled much more than I should have, mostly due to my own poor understanding of Linux boot issues, but have finally prevailed. Here is the results of that effort.
IPCop on USB Howto:
Overview:
1. Follow the existing instructions for making a flash based IPCop System
2. Create a custom initrd to preload the necessary USB modules.
3. Modify grub.conf to use your custom initrd.
4. Reboot (test)
Details:
The first task is to install IPCop on a hard disk. There is plenty of instructions out there on how to do this, so no additional details are provided here.
The very first thing to do is follow the execellent instructions in Appendix C of the IPCOP manual (http://www.ipcop.org/1.4.0/en/install/html/mkflash.html). Follow the instructions carefully, as this will generate our base system. Choose a working directory (I used /root), and stay in that directory for the duration of this tutorial.
The next step is to make our custom initrd. The default installation contains mkinitrd, and we'll need to instruct it to preload some modules as well. (Note that the order of the --preload arguments is important!)
root@ipcop: # mkinitrd --preload usbcore --preload scsi_mod --preload usb-storage --preload usb-uhci --preload ehci-hcd --preload sd_mod CustomInitrd.gz `uname -r`
You now have a shiny new initrd to work with. It's a gzipped cpio archive, so we'll need to mount it to do our editing:
root@ipcop: # mkdir tmp
root@ipcop: # gunzip CustomInitrd.gz
root@ipcop: # mount -o loop CustomInitrd tmp
Now we need to (ever so slightly) modify the linuxrc file (which is run in the first stage ramdisk) to give the usb modules time to do their detection before completing the first stage boot:
root@ipcop: # vi tmp/linuxrc
Find the line for mounting the /proc filesystem, it looks likes this:
echo Mounting /proc filesystem
mount -t proc /proc /proc
And right after this, insert the wait:
echo "Waiting for USB devices to come online"
sleep 8
Save and close the file. We need to repack the initrd and put it in the boot partition now:
root@ipcop: # umount tmp
root@ipcop: # gzip -9 CustomInitrd.gz
Let's mount the first partition of the USB which contains the boot information we created when we followed the Flash Based IPCop Systems tutorial, followed by putting the new initrd in place. Assuming your USB stick was recognized as /dev/sda, this looks like this:
root@ipcop: # mount /dev/sda1 tmp
root@ipcop: # mv CustomInitrd.gz tmp
Now we edit the grub boot menu to use the new USB.
root@ipcop: # vi tmp/grub/grub.conf
Near the beginning of this file, find the line that starts with "default", and make sure it reads "default 0". Now ... delete all of the lines starting with the first one that starts with "title", and add your new boot configuration:
title USBBoot
root(hd0,0)
kernel /vmlinuz root=/dev/sda4 acpi=off ro ide=nodma ramdisk_size=655536
initrd /CustomInitrd.gz
savedefault
Save and close grub.conf.
We also (may? I needed to do this, you may not) need to change the device.map, since in a USB boot situation, the USB thumb drive will always be assigned (by grub) as hd0. Note that this is my understanding, and may not reflect reality :).
vi tmp/grub/device.map
You only really need to make sure you have hd0 mapped correctly. There should be only one lines that starts with (hd0), and it should read:
(hd0) /dev/sda
Save and close.
We only have a little bit of cleanup to do, and we'll be ready to go:
root@ipcop: # umount tmp
root@ipcop: # rmdir tmp
Your USB stick should be ready to go. Reboot your IPCop box (optionally removing the staging hard drive before restarting it). You may need to go into BIOS to enable USB booting. When it starts up, just run setup, and get to work!
This was a frustrating but fulfilling endeavour, and I was unable to find a good reference from Google on how to do this. I hope it has been helpful.
- Joshua Radke
Comments
Problem with activation
Hi there, I dont know if I am writing in a proper board but I have got a problem with activation, link i receive in email is not working... http://www.radkeland.org/?9312ad325d2edae8c8601c6b62e,
Activation
Dear Guest,
I get many spam sign-ups per day, and am not as careful as I should be with making sure the person applying for an account is not someone I know. Please follow the sign up directions (use a sensible user name (Real name encouraged)), and send me (webmaster) an email when you sign up, so I know not to delete the application.
Best,
Josh
excellent page - adding comments
Thank you for an excellent writeup. Yours is the most comprehensive I've found for installing IPCop on a USB flash. I have several additions or comments:
- Be careful uploading mkflash, settings.8139, and logrotate.conf to the root directory. settings.8139 will be used during mkflash if it's here, and could confuse your system into not booting ethernet ports if it doesn't match your configuration. I think the logrotate.conf is intended to rotate logs on a daily basis instead of weekly. I think it needs to be copied to the etc directory to work. I'm not sure yet if it's necessary.
- The line 'gzip -9 CustomInitrd.gz' should read 'gzip -9 CustomInitrd'
- When modifying grub.conf, there are too many 5s in the line ...'ramdisk_size=655536'. I think it should be ramdisk_size=65536'. I don't think there's enough space on a 512 MB computer for a 655536 KB ramdisk. The operating system will probably shrink it to the maximum size, but I'm not certain what it will do.
- As you said above, the map information appears to be in grubbatch. I had to modify /dev/hda to /dev/sda.
- I definitely needed to create the initrd directory in the root of the fourth drive image (in my case /dev/sda4). I don't know why grub won't boot without it. The result is the kernel panic described, and the system gives no explanation as to why the boot failed. That one took lots of time and aggravation to figure out. I should have read your comments section more thoroughly to begin with.
- I had to modify /etc/fstab in the /dev/sda4 image. This and the above step can be done by 'mount /dev/sda4 tmp'. Edit the fstab file, changing harddisk1, harddisk2, and harddisk4 to the proper device designations. In my case they are sda1, sda2, and sda4. Instead, it's possible to just modify the symbolic links. harddisk1, 2, and 4 are initially set up as symbolic links to /dev/hda1, 2, 4.
- Once you get all this figured out, you might want to make a copy of the USB image in case the stick fails. I think you could plug it into a linux system and do something like the following:
dd if=/dev/ of=filename.img
This should probably be done in a separate system, not in the IPCop system while it is running.
Having IPCop on USB flash definitely adds to its usefulness. I'm surprised IPCop isn't distributed with a USB image or thorough instructions in the distribution. Thanks again!
Winston
kernel panic
First of all, great guide. I've been trying to install ipcop to my pendrive using this guide, but I've had a few things that didn't work for me.
I couldn't use 'uname -r' while making the custom initrd, so I just entered uname -r in the console, and used the resulting kernel version instead.
Also I had to use [ mount -t ext3 /dev/sda1 tmp ] to mount my usb stick, but those are just minor issues. The thing I'm struggling with now is that the system crashes into a kernel panic while booting (kernel panic: no init found. Try passing init= option to kernel).
I couldn't find the device.map file mentioned at the end of this guide, and I think this is causing the kernel panic.
I've tried creating a device.map file with just the [ (hd0) /dev/sda ] statement in it, but to no avail. I'm using Ipcop version 1.4.20
Do you have any ideas on how to solve this problem?
Troubleshooting Kernel Panic
Ok ... I think I kind of understand your current state, so I'll do my best.
If you're using grub, device.map should be in the /boot directory of the USB image.
I can't tell from your description (or perhaps this was long enough ago that I've forgotten) whether you've successfully loaded stage1 or not. Perhaps the easiest way would be to edit the linuxrc file above, and make the first line something like:
echo "Processing linuxrc"
Then, rezip, recopy, and restart. If you don't get to the 'processing linuxrc' echoed on your screen, then you have been unable to start the stage1 kernel, which should be in the boot directory of the image you're working on (tmp/boot). The file name will be something like 'CustomInitrc.gz', and this needs to match exactly the "initrd /CustomInitrd.gz" line in grub.conf.
If you _do_ get to the echo line above, it means that you may need more drivers to mount the usb stick (root partition). I would encourage you to get ahold of nash, and use that to make an intractive session during the boot, so you can play around with 'lsmod', 'modprobe', 'mount', etc. These modules can be coped to the boot image from the basic IPCop install.
I hope this help!
Josh
Troubleshooting Kernel Panic
I've manually searched all 3 partitions (sda 1,2 & 3) of the usb stick to find the device.map file, but it's nowhere to be found in any directory. It's just the basic ipcop flash image from the guide, and it's using grub afaik. Maybe they changed some things around. I haven't modded anything myself, just a fresh install and the steps from the guide.
I've now tried to add the echo "Processing linuxrc" line to linuxrc, but the text zips by too fast to be seen I think. I did notice I can see the echo "waiting for USB devices to get online" line, which I also had to add to linuxrc. Does this indicate stage 1 is loading? I can also see the usb stick being detected, with correct brand and size, and I also see the lines:
sda: write protect is off
sda: sda1 sda2 sda4
I can also see the line: Mounting root filesystem
After that things seem to be going wrong.
The following lines appear:
pivotroot: pivot_root(/sysroot,/sysrootinitrd) failed: 2
umount /initrd/proc failed: 2
Freeing unused kernel memory: 92k freed
Kernel panic: No Init found. etc.
Maybe this gives a little more info about the problem?
Meanwhile I had also tried some other things. In the grub folder from the boot partition of the stick, there is a file named grubbatch. I have opened it using vi and noticed there was a line in it saying: "device (hd0) /dev/hdc, but changing hdc into sda didn't help me unfortunately.
Also I tried modifying the mkflash script to allow sda to be used (./mkflash 2gb sda), and tried to make an image this way, but this image gave me thesame panic.
I'm pretty new to linux (this is my first project using it), and so far this trouble has been a huge learning experience, since it forced me to learn alot. I'm not sure what you mean by using nash and modprobe etc, but I'll try to read up on that. If I'm getting this right, you're basically saying that ipcop doesn't have the right drivers for my usb stick? I can mount the stick, while using the staging harddisk, so doesn't that mean it should have the right drivers?
Thanks for helping me a little further. I really appreciate it alot! If you think of anything new... that would be awesome
I fixt it! I'm so happy, it
I fixt it! I'm so happy, it turned out to be a very simple, yet nearly untraceble problem. I needed to make a Initrd folder in the root of the image, which can be found at sda4.
I used the following:
root: # mount -t ext3 /dev/sda4 tmp
root: # cd tmp
root: # mkdir initrd
Just to be sure I also made thesame dir in the root directory found there:
Still being in the tmp folder I used:
root: # cd root
root: # mkdir initrd
After this the system booted like a charm.
As you said, a very frustrating, but fulfillinf endeavor!
Almost There!
Wow, I'm pretty sure you're almost there! Your stage 1 ramdisk is definitely online, grats!
I screwed up with the nash suggestion; nash is the shell that is executing your linuxrc file currently. What I was trying to suggest was busybox. Google around for a busybox comipled for your kernel version (or something close). Copy it in to /bin on your ramdisk image, and call it from the linuxrc, right before the problem. That will give you a basic shell in your first stage ramdisk. You would call it in your linuxrc script with something like:
/bin/busybox sh
From there you can 'ls', 'modprobe', 'mkdir', 'cat', etc. (provided the binary you download has those commands enabled).
After some googling, it appears that this can happen if the /initrd directory is missing in the ramdisk image. Check that.
It may be that ext3 support is not on the ramdisk? ... if this is the case, you may need to add --preload ext3 to the initial 'mkinitrd' command.
If you get to needing to use busybox, and find some sequence of commands that allow the boot to finish (start by just trying to do what the linuxrc has in it), remember that you'll need to edit the linuxrc on the compressed ramdisk, then copy it back to the thumb drive.
If stuff is zipping by too fast in the linuxrc, just do this:
echo "Hi, I'm a useless notification!"
sleep 10
That will make it do nothing for 10 seconds after the echo.
Ok, it looks like IPCop 1.4.1 changed the boot stuff a bit, 'grubbatch' seems to be the same as 'system.map'. If you do the above busybox interruption, you should be able to see which device your USB is being detected as (should be /dev/sda). I believe that needs to be in the grubbatch file (and make sure you save/rezip/recopy to the stick after changes).
(hd0) /dev/sda
Let me know if any of these suggestions work.
BTW, I'm very encouraged with your effort, and excitement! I love to see new gnu/linux users enjoy the customizability that a free operating system offers! You've also taken up a non-trivial project. My guide from earlier this year is the first I was able to find that attempted to put it all together.
Josh