There's always time to play

Wednesday, December 23, 2009

Convert PDF to ... PDF

I keep running into people having issues with PDF files. Most of the times there's a very easy solution to fix their issues: convert the PDF to a PDF.

The following ghostscript command will successfully convert a PDF to a new PDF without any restrictions, suitable for printing, editing with PDF editors or whatever you want:
gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPassThroughJPEGImages=true -sOutputFile=out_file.pdf in_file.pdf.

Sunday, October 25, 2009

When something's broken...

I've spent a large amount of today figuring out how to get some MP4 files playing on my TV (Samsung LE37B650T2, with DLNA support). Turned out that my TV doesn't like a MP4 file with the video track before the audio track, so I now add the audio tracks first. That at least got one movie playing, I guess I can get more to play this way.

Sunday, September 20, 2009

Moving files in Banshee library

I moved most of my music to the localized music folder (yay for localized name fail). Of course Banshee didn't know I moved them, so I had to tell it they were moved. I knew Banshee uses sqlite, so I just had to find the db and do the replacement. Banshee's database can be found in ~/.config/banshee-1/banshee.db. The following block highlights all you need to do to change the path for your files:

$ sqlite3 ~/.config/banshee-1/banshee.db
SQLite version 3.6.10
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> UPDATE CoreTracks SET Uri = replace(Uri, '/home/mycroes/Music/', '/home/mycroes/Muziek/') WHERE Uri LIKE 'file:///home/mycroes/Music/%';

Of course you need to pass in the correct arguments to 'replace', but that should be an easy one.

Sunday, June 28, 2009

Watching TV with mplayer

Occassionally I want to watch something on my computer, and currently I'm using mplayer to do so. When I finally was able to play video and sound at the same time, I decided I wanted to have a bit easier way to watch tv then constantly searching for my mplayer command. So I made a small shell script, and while I was at it I added in the channel list so I can just start watching without searching frequencies too, so here it is:

FILTER="-vf pp=lb,crop=672:420"
OUTPUT="-vo gl -ao pulse"


TV="-tv outfmt=i420:chanlist=europe-west:width=720:height=576:amode=1:alsa:adevice=hw.2,0:forceaudio:immediatemode=0:channels=$CHANNELS"

mplayer $OPTS $FILTER $OUTPUT $TV tv://$1

As you can see I'm using the first argument as channel, so you can invoke this script with a channel number to immediately select a channel on startup, but leaving out the argument will just start mplayer on the first channel.

Last but not least, you can switch channels by binding keys to tv_step_channel 1 and tv_step_channel -1, in Ubuntu these are bound to h and l by default, and I suspect this to be the upstream default.

Tuesday, April 14, 2009

Magic comments

So you're writing some code, and there seems to be an error somewhere. As a real programmer, you're going to use printf or echo to debug your code. I happen to be writing a lot of PHP lately, so I also debug with var_dump. Not that it really matters, because after all it boils down to eliminating lines with errors, and as long as you use a programming language that supports // for single line comments and /* ... */ for multiline comments you can use magic comments.

Honestly, there's no magic involved, just a bit of logic. Let's say there's some code consisting of 3 blocks of lines:
[block 1]

[block 2]

[block 3]

If I want to comment one block, I could simply put /*, */ around it like this:
[block 1]

[block 2]

[block 3]

However, soon enough I figure I needed to comment block 2 for a while. Because I'm lazy, I try to type no more than needed, so it becomes this:
[block 1]
[block 2]

[block 3]

I'm almost happy now, but it seems I need to switch back to having block 1 commented again instead of block 2... Of course I can remove the added characters, or I can just add a few more:
[block 1]

[block 2]

[block 3]

Now if I decide that I need to comment block 2 again, I only need to edit one character:
[block 1]
[block 2]

[block 3]

And it's actually possible to chain these by using a /*/ between 2 blocks. If the block in front was commented, the next block won't be commented. If the block in front however was not commented, this block will be commented. And there you go, boolean logic with comments, it's almost magic.

Sunday, March 15, 2009

Creating a bootable USB flash drive formatted as NTFS

Next in the series of bootable flash drives: NTFS support.

I don't really care what filesystem my devices are, as long as I can read and write them. So FAT32 would be a decent choice, right? No. FAT32 has a file size limit of only 4G and I tend to store larger stuff on my Corsair Flash Survivor. I came up with two different solutions:
1. Create two separate partitions, one with stuff GRUB needs access to, one with large stuff like the filesystem images and my data,
2. Create a NTFS partition and boot from that.

Of course I first came up with solution 2, but I couldn't find much information about grub and ntfs, except for total lack of support for ntfs. I was thinking about solution 1 and then decided it sucks if you're forced to use two partitions while you don't really want to, so I went on looking for booting from ntfs drives.

After a while I came upon grub4dos. I can't say I really love it (without spending any time investigating it seems it's more of a hack than an enhancement to grub), but it's grub and it boots from ntfs formatted drives. Once I had that figured out, it was time to start doing some work.

First, partition the flash drive so there's a large ntfs partition (in my case the whole 16G). In my case there was already a partition there, if there's not you can skip deletion of the partition.
# fdisk /dev/sdx

Command (m for help): d
Selected partition 1

Command (m for help): n
Command action
e extended
p primary partition (1-4)
Partition number (1-4): 1
First cylinder (1-125, default 1): [return]
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-125, default 125): [return]
Using default value 125

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 7
Changed system type of partition 1 to 7 (HPFS/NTFS)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

Now it's time to create a filesystem on the flash drive, since we've chosen ntfs we'll need ntfsprogs, your linux distribution probably has it in it's repositories. Enter the following command to format the drive:
# mkfs.ntfs -L label -Q /dev/sdxY
Cluster size has been automatically set to 4096 bytes.
Creating NTFS volume structures.
mkntfs completed successfully. Have a nice day.

This shouldn't have been hard, if I actually needed to explain those steps to you at all, so let's continue with the serious part. The next few steps need a grub4dos archive. You can find one at their downloads page, I took Extract this and open a command line in the directory where the extracted files are. Now enter the following command:
# ./ /dev/sdx

Disk geometry calculated according to the partition table:

Sectors per track = 63, Number of heads = 255


If it says Success or something similar, then grub4dos is on your flash drive. You can actually boot from it, however for grub4dos to be useful it needs some files. Copy grldr to your flash drive (of course you need to mount it for that). It should be in the root of the drive. Now create a menu.lst in the root of the drive too (yes, this differs from grub behaviour). Edit the menu.lst file so it resembles a usable grub menu.lst and you're done.

The following block is my menu.lst, if there's any interest in the files and layout I used then just leave a comment and I'll be sure to answer any questions about it.
default 0
timeout 60

title Ubuntu Jaunty Alternate Install AMD64
kernel /ubuntu/jaunty/vmlinuz
initrd /ubuntu/jaunty/initrd.gz

title Gentoo Minimal X86
kernel /gentoo/x86/gentoo root=/dev/ram0 init=/linuxrc looptype=squashfs loop=/gentoo/x86/image.squashfs cdroot
initrd /gentoo/x86/gentoo.igz

title Gentoo Minimal AMD64
kernel /gentoo/amd64/gentoo root=/dev/ram0 init=/linuxrc looptype=squashfs loop=/gentoo/amd64/image.squashfs cdroot
initrd /gentoo/amd64/gentoo.igz

title GParted
kernel /gparted/vmlinuz boot=live union=aufs noswap vga=791 ip=frommedia nolocales live-media-path=gparted
initrd /gparted/initrd1.img

title Memtest 86+
kernel /memtest86/memtest86-3.5

title Boot first harddisk
rootnoverify (hd1)
chainloader +1

title Reboot

title Shut down

Tuesday, March 10, 2009

How not to fix an issue in an ebuild

As seen on Comment #2 From Christian Hoffmann 2008-06-08 13:59:44:
cherokee ships a patched version of lighty's spawn-fcgi. We could try to make
spawn-fcgi an independent package again and patch in the additional features of
cherokee based on a USE flag. Or we could introduce a "spawn-fcgi" USE flag for
both lighty and cherokee and die in the ebuild if the other web server was
installed with USE=spawn-fcgi as well. Any ideas?

Yes dude, you totally understood it. I bet mister Hoffman likes to tell portage (or whatever package manager he uses) to continue after every second ebuild because there's a check halfway in the ebuild instead of a real solution...

What if the check fails? Well, then package install fails of course. And what then? Well if you were just rebuilding world then you can fix the issue and start over again, or continue and know that you still have to fix it...

Sunday, March 1, 2009

Playing videos on a second display using mplayer

I decided I didn't need my home theatre pc anymore, because I don't record that much anymore (and that's the thing I liked most about it). I do however still have the need to play stuff on my tv and watch it from my bed, so I started by using mplayer to play videos to my already connected tv. I'm not covering the display setup here, just the needed information. My tv is display :0.1, I have multiple sound cards (my desktop speakers feature an internal soundcard), and the one my tv is plugged into is hw:1.0 (alsa). Putting this together with stuff lyign around on the web you get this:
DISPLAY=:0.1 mplayer -vo xv -ao alsa:device=hw=1.0 -fs /path/to/file

Using the above I have audio and video from my tv, so when I'm done watching I can turn the tv off and go to sleep... Now all I need is a remote!

Wednesday, February 11, 2009

Fallback kernels using GRUB (or safe rebooting of remote machines)

If you can't reach a certain computer (like a server that's colocated), but need to reboot it anyway, it's better to do it in a safe way. GRUB allows the use of the "fallback" command to specify a kernel to boot if it can't boot the kernel specified by default, but what if it can boot the default kernel but the kernel dies at some point? Well GRUB will be happy, it did boot a kernel.

The solution is in the "savedefault" option. When using "default saved" in the GRUB config file, GRUB will boot the kernel that was saved as default. Very easy to understand. But how can we use this to our advantage? Well let's assume we have a new kernel and an old kernel, named new and old, the config will probably look something like this:
default 0
fallback 1
timeout 5

title New
kernel /new root=/dev/sda1

title Old
kernel /old root=/dev/sda1

There's two things that need to be changed here. First the kernel needs to know what to do when it panics. Because there's one reasonable thing to do, it's implemented by means of a kernel commandline argument. Append "panic=5" to the kernel command line in the GRUB config and the system will reboot five seconds after the kernel panics.

The second change is that we need to tell GRUB that it needs to boot the second kernel if the first fails. We can't easily tell GRUB to boot the second only if the first has failed, but we can reliably tell GRUB to make the second default whenever the first boots. The changes will result in the following config (menu.lst):
default saved
fallback 1
timeout 5

title New
kernel /new root=/dev/sda1 panic=5
savedefault 1

title Old
kernel /old root=/dev/sda1

This config will instruct GRUB to set Old as the default kernel whenever New gets booted, and the "default saved" line will tell GRUB to boot the kernel saved as default. This can be chained to have multiple fallback kernels, but that's all up to you.

There's one issue left, if you want to reboot the system but the new kernel did work out, GRUB will still (correctly) assume it has to boot the old kernel. However there's a linux userspace utity that will allow you to change the default:
# grub-set-default 0

This will reset the default to 0. Of course if the system boots you can edit the menu.lst file by hand, setting the default to 0, but if you want to use it again you had better reset the default beforehand.

Creating a multiboot USB flash drive using GRUB

So I am currently booting my system from a USB flash drive, and probably will be for quite some time. One thing that annoyed me about syslinux is that it's really nothing more than a very simple boot loader, but sometimes you want more.

I've always used GRUB. GRUB has support for splash images so it looks nice. I also think the editing features of GRUB are great. Mistyped the kernel name after updating? Edit it in the menu. I also really like GRUB's default feature, which allows for some nice tricks, but that's for another post.

All in all, I wanted to get booting using GRUB. I've always installed GRUB 'by hand'. I've noticed the existance of grub-install, but the first time I ever read about it, I read about some issue with it. It was probably not important, but since I knew GRUB's setup commands by hand I didn't need it anyway. Turns out that if you run linux, GRUB will just map your USB flash drive as another harddrive (or at least it did for me with two different drives).

To install GRUB, it expects some files to be present. It also expects a filesystem to be present too if you install the same way I do. Because I like my USB flash drives easily accessible on multiple platforms, I format them as FAT32. I must say I only used them in linux so far, so if you're just like me you might as well format them ext2. In typable commands:
# mkdosfs -F 32 -n [somename] /dev/sdxy
# mke2fs -L [somename] /dev/sdxy

Of course sdxy refers to the partition on the flash drive you want to use, in my case it's /dev/sde1. You don't have to use labels (-n and -L options respectively), but I prefer to label my filesystems.

I also prefer to have my filesystems clean, so I try to keep all this bootable stuff contained in a folder. Mount your flash drive, and create a folder boot:
# mount /dev/sdxy /mnt
# mkdir /mnt/boot

I will be using the folder boot to store my kernels, initramfs's and the GRUB folder with GRUB files. GRUB needs just three (3) files to get installed: stage1, stage2 and the appropiate stage1_5. Easiest way to get these is from an existing install, if that's not possible for you, ask google for another solution (i.e.: "compile grub"). When using a FAT32 formatted flash drive you need to copy fat_stage1_5, when using ext2 or ext3 you should use e2fs_stage1_5.
# mkdir /mnt/boot/grub
# cp /boot/grub/stage{1,2} /mnt/boot/grub
# cp /boot/grub/fat_stage1_5 /mnt/boot/grub

GRUB now has all the files it needs, so let's install it:
# grub
grub> device (hd7) /dev/sdx

grub> root (hd7,z)
Filesystem type is fat, partition type 0xb

grub> setup (hd7)
Checking if "/boot/grub/stage1" exists... yes
Checking if "/boot/grub/stage2" exists... yes
Checking if "/boot/grub/fat_stage1_5" exists... yes
Running "embed /boot/grub/fat_stage1_5 (hd7)"... 16 sectors are embedded.
Running "install /boot/grub/stage1 (hd7) (hd7)1+16 p (hd7,0)/boot/grub/stage2
/boot/grub/menu.lst"... succeeded

grub> quit

this maps (hd7) to /dev/sdx, the root line needs to be changed to match z = y - 1, in other words if you're using partition 1, enter a 0 for z, increment both equally for other partitions. You should now be able to boot from the USB flash drive, but we're not done yet. I like to have a config too, and I included a nice menu background, so I copied splash.xpm.gz over to /mnt/boot/grub. As for the config, here's mine for a gentoo 2008.0 minimal livecd squashfs image on my flash drive:
default 0
timeout 30

title Gentoo Minimal LiveCD 2008.0
kernel /boot/kernel-2008.0.img root=/dev/ram0 init=/linuxrc dokeymap looptype=squashfs loop=/minimal-2008.0.squashfs cdroot vga=791
initrd /boot/initrd-2008.0.igz

Name the file menu.lst and GRUB should be able to find it. If you now boot from the flash drive, you should see the menu. And as another bonus, booting entries seems to be way faster than it is with syslinux!

Sunday, February 8, 2009

Migrating from single disk to 3-disk RAID 5 (on Gentoo)

When following this guide a disk crash before the final step might still result in data loss, so if your data *is* important, back it up!

As my 1TB harddrive was filling up I was considering the ways I could expand storage. I hate usb drives, just for the simple fact that they're slow. I also don't like external storage at all, unless it's network storage. However, network storage would be slow for me too unless I at least spend some money to buy a decent gigabit switch instead of my 10/100 switch.

The option I liked most turned out to be to add another internal drive. I was already using LVM, so extending the volume group to span another disk wouldn't be hard, but that had it's serious downsides too. I'm not someone who does regular backups, I actually just don't do them at all unless something is really broken or I really feel I need to. Last time either of those happened is longer than a year ago I think, so a lot has changed since then. Now there's a lot of stuff I just don't need to backup, for the simple fact that it's someone else's service. I only use IMAP mail accounts and that's about the most important thing I could lose...

Because I don't do regular backups, I hope my harddisks will stay alive. Starting with a little bit of data and a new harddisk I can survive a near-instant crash. However when I would extend my 1TB lvm volume group with another drive, the risk of losing all data would immediately become twice as high. That's something I'm not willing to risk, because there's ways in which I simply don't have to risk it.

The solution I came up with was to buy 2 extra drives and create a RAID 5 array on top of them. A RAID 5 array requires at least 3 block devices, best to use 3 different disks for that, and will allow recovery of all data if at most one drive fails. It's possible to start with 3 drives and later expand to more while keeping all data on the disks. Another advantage is that data will be spread across disks, so reads and writes will also be spread across disks, so they will both be faster (the processing overhead for RAID 5 is very low).

When I made up my mind I had to figure out how to transition from my single disk to the RAID array, without having to use yet another disk to temporarily store my current data. A while ago I found some pages that pointed out that it's possible to create a 'degraded' RAID array. A degraded array means that on drive fail you might lose data, but when I still have all data on the old disk that won't be an issue. After having all the data on the degraded array, the old drive can be added to the array to fix the array integrity again.

So to summarize all of the above this is what I had to do:
- Add the drives to the system
- Create a degraded RAID 5 array on the 2 new drives
- Copy all data to the degraded RAID array
- Clean the old disk and add it to the array

Of course in reality I also had to compile a kernel with linux software raid support, because it was not there yet.

And here's what I typed with some additional explanation:
# paludis -i mdadm

Install mdadm, the linux software raid utility

# fdisk /dev/sda
# fdisk /dev/sdc

Partition the disks, in my case it just meant creating a full size partition with type fd (linux raid autodetect). Yes, my new disks are sda and sdc, I might have switched cables somewhere...

# mdadm --create -f /dev/md0 --level=5 --raid-devices=3 /dev/sda1 /dev/sdc1 missing

Create the degraded RAID 5 array with a missing drive.

# mdadm --examine --scan >> /etc/mdadm/mdadm.conf

Create a usable config file. Don't know when I would need it, but hey, it's there when I need it...

# pvcreate /dev/md0

Initialize a physical volume for lvm.

# vgcreate vg /dev/md0

Create the volume group 'vg' on the RAID array. Keep in mind that it needs to be different from the volume group name you was already using, if you were already using one...

# lvcreate -L30G -nroot vg
# lvcreate -L1200G -nhome vg

Create logical volumes for the root and home partition (that's all I use).

# mkfs.ext4 -L root /dev/vg/root
# mkfs.ext4 -L home /dev/vg/home

Create a filesystem, why not use ext4 immediately? Especially nice with biggish files.

At this point it's time to copy over all files, everyone has their own opinions about how this should be done, I just cped them over from the live install, leaving out /dev, /proc, /sys and creating them afterwards, copied /dev/null and /dev/console (copying all of /dev isn't really feasible, and those are all you need in gentoo) and I was done copying.

Now there's some additional stuff to worry about. I'm using gentoo, so I have to worry about being able to start from my RAID array too. Because I wanted to use the full disks for my RAID array I'm going to have to boot from another device, like a usb flash drive. So I started by copying my kernel with RAID and lvm support to my usb drive, created the entry in my syslinux config and created an initrd with
genkernel --lvm --mdadm initrd
. This created a nice initrd, with the helpful message that to use the lvm stuff I also had to pass dolvm on my kernel commandline. Now it was time to see if it all worked, and... fail... My RAID array was not detected, so all I could use was my old disk. After a while I found that for mdadm support you also need to pass 'domdadm' on the kernel commandline, and that solved all of my issues with booting, now let's hope that gets documented somewhere too.

I was now able to boot using my new lvm logical volumes on my new RAID 5 array. I actually started copying my home volume when I was able to boot, because that would take quite some time. All in all there was just one thing left to do, and that was adding the old drive to the RAID array (after changing the partition layout of course):

# mdadm /dev/md0 --add /dev/sdb1

Add sdb1 to the raid array.

Immediately the raid array will be resynced. This will take quite a while, because the RAID array itself has no knowledge about the data on it, so the entire disks are being synced.

While this all happens and after this all happens you can
$ cat /proc/mdstat
to see the status of the RAID array.

Now you should have a working RAID 5 array, just make sure you don't delete your data because a RAID array won't protect you from being stupid.

For a more detailed guide on just setting up the RAID array with a missing drive see Linux Software RAID 101 -- Part 3: creating an array with a missing drive, the guide I used to create my RAID array (you will notice all the mdadm commands are directly copied from that page).

Issues with syslinux

A small followup to my post about a syslinux bootable usb stick, I'm writing down the current issues I have ran into.
1. syslinux is not your average bootloader
2. syslinux on a fat32 usb drive doesn't like to get recognized as USB-FDD

Point 1 is easy to understand. Syslinux is made to be useful in the special cases, not to be useful in about any case. Want to boot to a different kernel? Edit the config file. I think grub is far more userfriendly than syslinux will ever be, so I'm definately doing that grub bootable usb drive soon.

Point 2 is something different... I don't know if grub will work when the system tries to boot from the usb device as if it's a floppy drive. I don't know what's going wrong for syslinux either, but I would not be amazed if either the system or syslinux decides that it can't read beyound 2.88M (or 1.44, but I guess it would at least support large floppy disks). If it's the system, then grub probably won't make any difference at all... So now you might ask, why would you want to boot with usb floppy drive emulation? Well, I don't want to, but it seems some machines have no other option depending on the kind of usb device you use...

Expect a grub multiboot usb drive howto soon.

Tuesday, January 13, 2009

Kernel Mode-Setting on Intel hardware

Today I was going to try kernel modesetting, or kms in short, on my machines with intel graphic chipsets. First I was going to try it on was my 'old' laptop with an intel 915 chipset. I configured a 2.6.29-rc1 kernel and tried it, but as soon as it wanted to change mode my screen would turn black and only show something as soon as X was started again. One time it did seem to have working consoles again after X was started, but that didn't seem reproducible.

I decided to move to the next victim, my MSI Wind with intel 945 chipset. I was hoping a newer chipset would work better, so I took the same route again and rebooted, and it worked! The only thing that didn't work was X, but I knew I had to get something near version 2.6 of the intel Xorg driver to have that working with kms again.

So while I installed new drivers I went looking for the differences between the kernel configurations of both machines. I started at the framebuffer section, because I knew I had the uvesafb driver compiled in on my 'old' laptop and I had intelfb compiled in on both laptops, so my first guess was to disable the uvesafb driver and try what happens. Immediate success, I had native 1680x1050 on the console on my 'old' laptop, and X would even start. I didn't have recent intel Xorg drivers however, so switching between X and consoles was still as slows as it had always been. But having the consoles at native resolution is already so much of an improvement, that you shouldn't really care.

Meanwhile, my MSI Wind had finished installing newer intel Xorg drivers and I was ready to start X, success again. Switching between X and consoles is simply amazingly fast. I have however noticed a small issue here, somehow gdm thinks the vertical resolution is about twice what it really is, so I only see the top half of the screen and thus no login box. Once I'm logged in the issue seems to persist and my cursor is invisible, but my terminal keyboard shortcut works and the terminal is completely visible, so I can live with that for now.

Next machine is my Asus EEEpc 701/4G surf, which features an intel 915 chipset again. I compiled a 2.6.29-rc1 kernel again, using the config I made last week when I created my bootable usb stick. Copied the kernel to my usb stick, booted and... failure. Same kind of problem as on my 'old' laptop, screen turns black. Because I use the gentoo minimal image I never get to a X server either, so it stays black. Back to the kernel config, what went wrong? Somehow console framebuffer support was turned off, and I also had some other options turned off like low level display driver support. I don't think the latter really matters, but the first was an issue. After that it booted fine, except for the fact that I now used the in-kernel squashfs support which was at version 4.0 already, while the patch I previously used to patch my kernel sources was at version 3.4. Seems like the disk-format changed in between, so I can't mount the image, but I can get the fancy native resolution console.

Everything seems to work now, except for one thing, my 'old' laptop refuses to start X after updating to one of the 2.6 beta intel graphic drivers. Seems to get a hard lock, so I'll have to dig into that. I might have some newer packages installed on my msi wind, so I'll start by comparing versions and then I'll see. So far I'm happy.

Other issues I noticed are that on all the machines I seem to get some output from the drm driver that something is going wrong, including occasional call traces where something apparently went terribly wrong, but almost everything works. I also noticed that after a while the screen blanks, even though I think it shouldn't. Even worse, pressing a key won't turn it back on again, but switching to console, pressing a key does. After that I can switch back to X again and it works.

So now I only have one thing left to do, and that's check if it also works on the MacBook me and my girlfriend use together, but I guess I'll have to do some more work on my bootable usb stick before that's going to work.

Wednesday, January 7, 2009

Creating a multiboot USB-stick using syslinux

Since I have an eeepc-701, I need a way to boot it from external media so I can mess with it. I have a Corsair Flash Survivor (16GB), so I'm going to use that for rescue-goodness. I'll give step by step instructions on how to create a similar boot disk. In these instructions I'll assume that /dev/sdc is the usb drive, /dev/sdc1 is the partition we're using for the filesystem. Further mine will be mounted at /media/Corsair and I'll also assume you can find the appropiate packages if you haven't gotten them yet (dosfstools and syslinux in gentoo). Last but not least most of these commands will need root permissions, so prepend them with sudo if that's your thing, or become root and do it all as root.

Format the usb drive as fat 32
Of course there are other options than fat 32 to create a bootable usb drive, but syslinux needs a FAT filesystem to work.
# mkdosfs -F 32 -n Corsair /dev/sdc1

Mount the usb drive
Unplugging and replugging will work for me as I use Gnome with automount support, should probably work for most people using a larger desktop environment. If not:
# mkdir -p /media/Corsair
# mount /dev/sdc1 /media/Corsair

Create a syslinux directory
Syslinux needs somewhere to store its files, I prefer doing that in a directory so I don't get a cluttered view every time I look at the files on my usb drive.
$ mkdir /media/Corsair/syslinux

Unmount and install syslinux
Unmount in whatever way suits you, just don't unplug yet. The -d option tells syslinux to use our directory 'syslinux' to store its files, just make sure the directory is there before running syslinux.
# umount /media/Corsair
# syslinux -d syslinux /dev/sdc1

Mount again
Remount the device to put more on it than just syslinux.
# mount /dev/sdc1 /media/Corsair

There's only two things left to do now:
1. Move images to the usb drive
2. Create the syslinux.cfg file

Move images to the usb drive
I create two directories to start with: gentoo and gparted. Inside the gentoo directory I put the kernel, initrd and squashfs from the minimal install cd and renamed them to include the release number in the files. At first I named my kernel just 'kernel-2008.0', but that seems to confuse syslinux so I renamed it to kernel-2008.0.img in the end. Better extensions suggestions for the kernel are welcome. I also copied all the .msg files from the gentoo cd to the syslinux directory I created on the root of the filesystem, so I can press F1-F6 and see irrelevant gentoo messages, however, changing these is easy and will be done when I have more time. It also seems gentoo needs a file called 'livecd' on the root, else it won't find the media as the fs media. It's cluttering the drive, but removing the file will just cause gentoo not to find a valid root fs. Last but not least I compiled a kernel that has support for most of the hardware in my eeepc 701/4G surf, and named that 'kernel-eee' straight on the root of the USB drive. I needed at least 2.6.28 so I could have support for the onboard network card, whatever way I'm installing it I'm gonna want network support. The kernel is monolithic (no modules and no module loading support) and works fine with the gentoo 2008.0 squashfs.

Inside the gparted directory I again put the kernel, initrd and squashfs files. I just took them from the livecd, left names as they were.

Create the syslinux.cfg file
I took most of this file straight out of the isolinux.cfg that came on the gentoo cd and customized where necessary.
default gentoo
timeout 150
prompt 1
display boot.msg
F1 kernels.msg
F2 F2.msg
F3 F3.msg
F4 F4.msg
F5 F5.msg
F6 F6.msg
F7 F7.msg

label eee
kernel /kernel-eee
append root=/dev/ram0 init=/linuxrc dokeymap looptype=squashfs loop=/gentoo/minimal-2008.0.squashfs cdroot initrd=/gentoo/initrd-2008.0.igz

label gentoo
kernel /gentoo/kernel-2008.0.img
append root=/dev/ram0 init=/linuxrc dokeymap looptype=squashfs loop=/gentoo/minimal-2008.0.squashfs cdroot initrd=/gentoo/initrd-2008.0.igz vga=791

label gentoo-nofb
kernel /gentoo/kernel-2008.0.img
append root=/dev/ram0 init=/linuxrc dokeymap looptype=squashfs loop=/gentoo/minimal-2008.0.squashfs cdroot initrd=/gentoo/initrd-2008.0.igz

label gparted
kernel /gparted/vmlinuz
append initrd=/gparted/initrd1.img boot=live union=aufs noswap vga=791 ip=frommedia nolocales live-media-path=gparted

label memtest86
kernel memtest86

Syslinux uses relative paths by default, so if you use no '/' syslinux will look for the files inside the dir syslinux is. The solution is simple, use absolute paths for the kernel and initrd and it's all OK. Most important change made to this file is the append lines. For gentoo, the loop parameter needs to point to the squashs image, so I changed that to /gentoo/minimal-2008.0.squashfs (name of the image in my case). I added a line for my eeepc kernel, which just boots into a gentoo minimal cd.

Next was gparted. Gparted supports a 'live-media-path=' parameter, this needs to be used when the gparted squashfs image is not directly in the root of the filesystem on the usb drive. Other than that gparted just looks for any file with name *.{squashfs,ext2,ext3,jffs2} so the name doesn't really matter as long as the extension hasn't changed.

I also left the memtest line in place, added the memtest image to the root of the drive and my rescue-drive is mostly done.

It should also be possible to do the same thing using grub, except for the F1-F6 messages and the default message (or can grub do that too?). I'm definately gonna add grub to it, probably replacing syslinux with grub. Using grub might also allow for use of other filesystems on the drive, which might end up being a big plus too. Come back again to read about that, once I've tried it myself.

Sunday, January 4, 2009

Configuring a linux kernel for another architecture than host

On my 64 bit gentoo installation I wanted to compile a kernel for 32 bit machines (specifically my eee pc 701), but somehow menuconfig was as smart to notice I was running a 64 bit machine and so showed me stuff to build a 64 bit kernel. After a quick search I found the solution:
make ARCH=i386 (oldconfig|menuconfig|)