How to build a tiny Linux MP3 Player System using Buildroot
Do you have an old spare computer that is rotting somewhere in your attic/cellar? Why not recycle it into a MP3 jukebox! 🙂
An old rig (Pentium 1/2/3-class) with 64Megs of RAM and USB connector will do!
No Harddisk required, a CDROM drive is optional in case that booting from USB doesn’t work.
We will design our (minimalistic but fully automated) Linux system so that a screen and a network interface aren’t even required.
Our very simple MP3 player system will be designed according to the following lines :
USB flash drive, with 2 partitions :
- One SYSTEM partition, EXT2 formatted.
- One data partition, labelled MYMUSIC, FAT or EXT2 formatted (preferably FAT if you want to copy files from window$ computers). The mp3 files will be stored in this partition.
We want to be able to boot directly from the USB flash drive (or with a CD if the computer can’t)
Ou Linux system will automatically mount the MYMUSIC partition (in READ ONLY mode for safety!)
The Playlist will be generated by searching mp3 files on the whole partition.
The soundcard is initialized
Playback starts.
Basically, just turn on the computer with the USB flash drive plugged in/Boot CD inserted, wait a few seconds, and enjoy your music!
Requirement for the buildroot host system
In order to create ou tiny Linux system, we need the Buildroot development suite. In this tutorial, Buildroot 2011.02 was used, on a Debian Squeeze 6.0 system.
You may want to have a look at my other how to in order to get started.
You’ll also need :
– a full development system. On Ubuntu/Debian this means the following packages : build-essential, ncurses-dev, bison, flex
– BusyBox
– syslinux/extlinux
– qemu (optional)
If you already have Buildroot installed on your host system, it is strongly advised to delete your old output directory.
PART I – Creating our tiny Linux kernel
Configuration of Buildroot before compilation/system generation :
# cd <your buildroot home> && make menuconfig
Toolchain —>
[X] Enable large file (files > 2 GB) support
[X] Enable WCHAR support
Package Selection for the target —>
Audio and video libraries and applications —>
[*] alsa-utils
ALSA utils selection —>
check everything
[*] mpg123
Hardware handling —>
[*] udev
(Without udev, soundcard support didn’t work for me)
Kernel —>
[X] Linux Kernel
Defconfig name : i386
Target filesystem options —>
[X] iso image (optional, only if you want to burn on a CD)
[X] initramfs for initial ramdisk of linux kernel
uncheck others
Linux Kernel configuration
# make linux-menuconfig
Include all the sound drivers for maximum compatibility (kernel size won’t suffer much!)
Device drivers —>
Sound card support —>
Advanced Linux Sound Architecture —>
PCI sound devices —>
<*> …
<*> Intel/SiS/nVidia/AMD/ALi AC97 Controller
<*>
(check all)
Next, we need to configure BusyBox for our embedded system, but Buildroot currently has a limitation : you must first compile the whole thing, so :
# make
then configure BusyBox
# make busybox-menuconfig
Linux System Utilities —>
[X] Support specifying devices by label or UUID
Miscellaneous Utilities —>
[X] Beep
We also need to adapt our root filesystem (the rootfs that will be included in our kernel, via initramfs) :
# cd <your buildroot home>/output/target
Create mnt/music (the mount point we will use to mount our MYMUSIC partition to)
# mkdir mnt/music
Accordingly, modify the etc/fstab file by issuing the command :
# echo "LABEL=MYMUSIC /mnt/music auto ro,noauto 0 0" >>etc/fstab
“auto” tells that the filesystem will be automatically recognized.
the “noauto” value, tells that the entry is not mounted by the mount -a command
(optional) Generate a keymap for our system (ex. for our French readers 🙂
# sudo busybox dumpkmap >etc/fr.kmap
And add the following lines to the etc/init.d/rcS (our own startup code) :
# MYMUSIC volume label MYMUSIC="MYMUSIC" # Mount point MYMUSIC_MNT="/mnt/music"
# load your keymap (optional) loadkmap </etc/fr.kmap clear
echo -e -n "\nInitializing soundcard : " # a beep will be played if alsactl init fails # TODO : add better error handling alsactl init || beep
echo -e "\nMounting Music folder... " # dirty trick here : # trying to mount the MYMUSIC partition # we have to add a delay (10 secs max should be enough) for the usb device to be available! i=1 while [ $i -le 10 ] do # if mount failed, wait 1 sec, else get out of loop (break) mount LABEL=$MYMUSIC && break echo "Waiting..." sleep 1; i=$(( $i + 1 )) done
# check if partition successfully mounted if grep -qs $MYMUSIC_MNT /proc/mounts then echo -e -n "\nMusic folder mounted (Read-only)!\nGenerating playlist : " # scan all folders for *.mp3 files on the volume and sort them alphabetically find $MYMUSIC_MNT -iname "*.mp3" | sort >/tmp/playlist.txt echo -e "OK" cd $MYMUSIC_MNT # endless loop (you may want to remove it) while true do echo -e "Starting music player (press h for help)\n" mpg123 -v -C -@ /tmp/playlist.txt clear done # never reached! echo -e "\nEnd of playlist!" else # no music partition found/mounted # play 3 beeps here to signal the failure beep beep beep echo -e "\nCouldn't mount your music folder!" echo -e "\nPlease make sure that your music partition : " echo -e " - is a valid formatted volume and is labelled $MYMUSIC" echo -e " - doesn't contain filesystem errors" echo -e "\nYou can shut down the system now or manually login and check your device." fi # to reset your system: you can use the SysRq keys : Alt+PrintScreen+b
(Optional) When generating an iso as well, you’ll have to modify the grub bootloader menu.lst file (because it would boot the first harddisk by default, not the CD!) :
# nano <buildroot>/fs/iso9660/menu.lst
default 1 timeout 3 color yellow/green white/blue
title Hard Drive (first partition) rootnoverify (hd0) chainloader +1
title Fredo's TinyLinuxMP3Player (plug your USB drive & boot CD!) kernel /kernel initrd /initrd
Ok, now it’s time to generate our tiny Linux kernel :
# cd <your buildroot home> && make
The generated kernel file (named bzImage) is well under 10Megs! And the iso is about ~14Megs.
It’s possible to test our system right away, using qemu
# qemu -kernel output/images/bzImage -soundhw all
(or with the iso)
# qemu -cdrom output/images/rootfs.iso9660 -soundhw all
Part II – Creating our bootable USB flash drive
Display all the drives to see which device is our USB drive :
# fdisk -l
Partition the drive :
WARNING! EVERYTHING ON YOUR DRIVE WILL BE LOST! AND PLEASE SELECT THE CORRECT DEVICE!
Adapt “/dev/sdX” to your own case.
# fdisk /dev/sdX
o
n
p
1
<first cylinder><enter>
<last cylinder>+16M # 16Megs should be enough, increase it if needed.
t
1
83 <Linux>
n
p
2
<first cylinder><enter>
<last cylinder><enter>
t
2
6 <FAT16> or 83 <Linux> depending on what you prefer
a
1
w
(You may unplug and plug the drive again)
Next, we format the partitions / create the filesystems with the correct volume labels :
For the SYSTEM partition
# mkfs -t ext2 -L SYSTEM /dev/sdX1
For the MYMUSIC partition
# mkfs -t vfat -n MYMUSIC /dev/sdX2
or, if you’d rather use EXT2
# mkfs -t ext2 -L MYMUSIC /dev/sdX2
Finally, let’s make the drive bootable, by installing the EXTLINUX (part of the SYSLINUX package) bootloader :
# cat /usr/lib/syslinux/mbr.bin >/dev/sdX
# mkdir /mnt/usb
# mount /dev/sdX1 /mnt/usb/
# extlinux --install /mnt/usb
# cat >/mnt/usb/extlinux.conf <<EOF
> DEFAULT linux
> PROMPT 0
> LABEL linux
> SAY TINY LINUX JUKEBOX NOW BOOTING!
> KERNEL bzImage
> APPEND quiet # comment this line for debug
> EOF
TIP :
More kernel boot options (for the APPEND line)
http://www.kernel.org/doc/Documentation/kernel-parameters.txt
Last thing, we need to copy our kernel on the drive!
# cp <your buildroot home>/output/images/bzImage /mnt/usb/
(Optional) As for the iso file (output/images/rootfs.iso9660) just burn it to a blank cdrom
Now, let’s unmount the drive :
# cd && umount /mnt/usb
PART III – Playback time!
Copy some mp3 files on the MYMUSIC partition, and boot 🙂
Press the ‘h’ key for MPG123’s help screen.
END.
IDEAS FOR IMPROVEMENTS :
– change video mode for better display (vga=xxx )
– optimize kernel size by removing unused features
PROBLEMS ENCOUNTERED :
– BusyBox’s beep command does not produce any sound
Solution : TODO
– Certain mp3 files can’t be played
Solution : your usb flash drive might be corrupted! Re-format/try another one.
– Only mp3 files are played! No OGG, no WMV, no ….
Solution : in this version, we use the MPG123 player. You’ll need to adapt the system to use another one (hint: MPLAYER).
THIS IS THE BEST HOW-TO AROUND !!!! THX A LOT MATE
Thanks for the feedback 🙂
Hi
nice but i do not see the step what i should do with my genereted rootfs.tar
Just untar it on the boot partition ?
In this howto, the rootfs is included in the initramfs (which itself is embedded into the kernel), so you only need one file : the linux kernel (bzImage) on your boot partition!
nice work with buildroot.
I use it on the kindles. appreciate teh in depth aritcles even if they don;t completely apply.
Thanks… very helpful.
I build the rootfs.iso9660 image, when i will test with virtualbox i am getting into grub prompt. Please help me
Hi,
I confirm this. Just tried with Buildroot 2013.11, booting the rootfs.iso9660 (with grub bootloader) with qemu, hangs at “Loading stage2 …”
I don’t know why. Maybe try with isolinux…
Hi,
Great tutorial, it helps me a loot, with a school project i’m doing.
I’m just having some problems, i don’t know if you could help me:
when i use qemu, i put: “qemu -hda /dev/sdb1 -hdb /dev/sdb2” cause rootfs is in the second partition, and it works fine. But when i boot the computer from the usb it only uses the first partition, right?, so i got “kernel panic” message. How could i solve this problem?
One more time, thank you for this tutorial,
Miguel
@Miguel, you should use “-hda /dev/sdb” because you want the whole drive. The booted system will handle the partitions.
i only am trying to make an old mp3 player flash a puppy install. But every iso and boot partition manager doesnt seem to work. I tried unetbootin from lubuntu, but this rca mp3 player wont be reconized…On my other flashdrives i never had trouble, im just wondering why some usb drived wont boot and ISO…
Oh if no one reads this for another 3 years, Ill totally understand, lol…