We have one working and simple filesystem working. It is time to take a look on the /dev directory, and see which options do we have.

File devices are a special kind of files, usually found under /dev. If you want to write  to your serial port, open /dev/ttyS0, if you want to access the first framebuffer, go to /dev/fb0, etc. You can also setup permissions, for example, to protect the serial port to be abused from users, or to make a device readonly. And we can create symlinks, so we know that /dev/logitech will point to the correct webcam device.

How we create all this stuff?

The first option  is to use mknod for each device. This is very odd and hard to maintain, but if you are looking for some quick config, or a very fast boot, or a small kernel, you can choose this. With mknod, you specify a pair of magic numbers (driver specific) to create the device. So, you must know all thre devices that are present or that will be present in the future, and the magic numbers. That is quite a mess.

Busybox has a file with all the devices that you want to create when you make the final image. Check  system / device_table.txt . It has the device name, major/minor numbers, and permissions. For example, you can create the serial port and give it permissions to everybody. You can create more things like symlinks, dirs, etc, not only devices…

Tee most sophisticated way, and the usual one that you will find in your distro, is udev. This is not ‘unix traditional’, but it is the standard now in Linux. It works in userspace (safer) and for example, it will trigger actions when you plug devices (and you can create symlinks, etc). But if you have an embedded device, maybe this one is too much.

Nowadays, the kernel uses devtmpfs to handle device files. It will populate  /dev with the default devices and with default permissions (root 0600). It will mount it very early, so, you can do things like init=/bin/sh, and you can create even smaller images.

There were something similar before called devfs, but it had many issues and it is now obsolete. The new version (about 2009) is like ‘devfs done right’.

Busybox has a project called mdev. It is like a micro udev. It will handle things like load kernel modules when you plug an usb camera, etc.

You dont need devtmpfs to run mdev. Calling mdev -s will check /sys and will create the correct devices (slow). If you dont use devtmpfs, you need to call mdev -s in your /bin/init script to populate /dev

So, when the kernel detects a new device, it calls  /proc/sys/kernel/hotplug. To enable mdev :

echo /sbin/mdev > /proc/sys/kernel/hotplug

with some time, I will write a simple mdev.conf with same permissions, and some scripts to automount usb devices under /media

 

I am playing with my a13 olinuxino micro. It is running and I really love it! It is time to connect it to the LAN. The idea of this howto is to have a, more or less, clear idea of all the steps that you need to connect your wifi card, step by step.

This device hasnt any network card (it cost 35 euros), but fortunately I got an old usb wifi card, an Ovislink evo-w300usb, that internally comes with a chip from ralink, the 2870.  The current driver is the rt2800usb. So, if you compile the kernel by yourself, enable the driver here:

Device Drivers  --->
[*] Network device support  --->
[*]   Wireless LAN  ---> 
  <M> Ralink driver support  --->
   <M> Ralink rt2500 (USB) support
    <M> Ralink rt2501/rt73 (USB) support
    <M> Ralink rt27xx/rt28xx/rt30xx (USB) support
    [*] rt2800usb - Include support for rt33xx devices
    [ ] rt2800usb - Include support for unknown (USB) devices
    [*] Ralink debug output

Also, remember to enable all the obvious things, like network support, tcp support, etc.

The next step is to bring the interface up. This device has a proprietary firmware that must be uploaded when you setup the interface. The system will upload the firmware to the device automatically. But with our small system, this is not so easy, because the kernel must have some access to the filesystem.

For an embedded device there are some ways to do it. Busybox has a system called mdev to dinamically update the list of devices. Before you can tell to the kernel that you will use mdev as your device manager, you must mount the sysfs, and setup the kernel ‘hotplugger’ :

# mount -t proc proc /proc
# mount -t sysfs sysfs /sys
# sysctl -w kernel.hotplug=/sbin/mdev
# mdev -s

ok, now, copy the latest firmware to /lib/firmware, and setup the interface

to enable the driver, type

# modprobe rt2800usb

tocheck that your device exists:

# iw list

to bring the device up

# ip link set wlan0 up

if your hotplugger is not correctly configured, the system will hang up for a while… check that /dev is correctly populated and your filesystem is mounted, etc.

ok, now you have a working wireless network card. You can see more info with:

# iw phy phy0 info

to list the available networks, type:

# iw dev wlan0 scan

to check if we are connected to the access point (we are not) :

# iw dev wlan0 link

Now it is time to associate our wireless card to the access point. I assume your router is using WPA2 for encryption. We need the package wpa_supplicant that will stay resident while our interface is connected. We will configure a /etc/wpa_suppliant.conf with all the networks and passwords that we use.

# cat /etc/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant

network={
ssid="MYSSDI"
psk=9f85448469740f8194ccd055cab3109251774aba3f1a788d50ed93a403afd1d5
scan_ssid=1
proto=WPA RSN
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
}

wpa_passphrase is a simple command that will generate the key for authentication.this will genreate something like:

# wpa_passphrase test_ssid supersecret
network={
ssid="test_ssid"
#psk="supersecret"
psk=9574610e6e0032abd916be445cca3b5ab932ec450be3f8066ddfc372229ce238
}

we copy and paste the psk key to our configuration.

At this point, we have a link between our wifi card and the access point. You can see it like that you plugged the cable on the switch. The next step is to include the ip address, etc, and tell the system to use wpa_supplicant when we need it.

# cat /etc/network/interfaces
iface wlan0 inet static
address 192.168.1.15
netmask 255.255.255.0
wireless-essid MYSSID
gateway 192.168.1.5
pre-up wpa_supplicant -B -Dwext -iwlan0 -c/etc/wpa_supplicant.conf
post-down killall -q wpa_supplicant

To setup the interface, type:

# iface wlan0 up

and try the network sending a ping to the gateway:

# ping 192.168.1.5

Please, if you think that I missed something, drop a comment here 🙂

This is one of the first things that I change on the first login, right after I install a new server.

Long time ago, people didnt have access to Internet. We used the console, alone at home, with some txt that we could get on a diskette, or on the CD ROM that came with some magazine. Even that, X Org was even worse than today, and we had like 128Mb of ram or so…

For that, we used the console. I mean, the VGA console, because old cards have a fast video mode called ‘text mode’ that could display only chars. Most of the time, we used the direct console to work.

To make multitasking easy, you could open several consoles, and move between them using Atl+Fn. This was very useful on that time.

But that was almost 20 years ago.

Now, it has no sense. We keep that only for historical reasons. You dont have a monitor, you dont have a console. So, dont spawn many consoles, wasting resources for nothing.

This is so old, that you have to edit /etc/inittab, something that came from unix, and comment those lines:

#1:2345:respawn:/sbin/getty 38400 tty1
#2:23:respawn:/sbin/getty 38400 tty2
#3:23:respawn:/sbin/getty 38400 tty3
#4:23:respawn:/sbin/getty 38400 tty4
#5:23:respawn:/sbin/getty 38400 tty5
#6:23:respawn:/sbin/getty 38400 tty6

if you have the server at home, you could keep the first one in case of emergency, but you can also boot in single mode and fix your computer.

And to apply this change, you have to use a very rare and arcane command:

telinit q

I was writing an script last night, and I found a problem.

I have a mysql server with some database and some stuff that I have to query sometimes. So, to make make life easier, I simply tunnel the tcp connection using ssh.

$ ssh -L 12345:localhost:3306 -N -f myserver.com

This starts listening on the port 12345 of my machine, and forwards everything to the port 3306 at myserver.com. It works pretty well, and it is quite secure and easy to setup.

But the thing is that, if you run it twice, it will ‘fail’, but the ssh is still running. So, if you have a cron file, you will end up with lots of ssh sessions in background.

Wat?

I tried to figure out how I can check if the port is already used on my machine, to dont launch ssh in that case.

And I found that, surprisingly, bash has built-in functions for network support!! everything goes through /dev/tcp/<addr>/<port> , it is a “hidden file” where you can read and write.

$ exec 3<>/dev/tcp/www.google.com/80
$ echo "GET /" >&3
$ cat <&3

This will connect to google (a popular website that sysadmins use to check availability) , and get some page. It created a file descriptor, number 3, where you can send or read data.

You can, for example, write a simple port scanner:

$port = 1; while [$port -lt 1024];do echo > /dev/tcp/<TARG_IP>/$port;
 [$? == 0] && echo $port "is open" >> /tmp/ports.txt; port = 'expr 
$port + 1'; done;

Ok, now my script seems very easy:

#!/bin/bash

LOCALPORT=3333
FD=6exec ${FD}<>/dev/tcp/127.0.0.1/${LOCALPORT} 2>/dev/null && exit
ssh -L 12345:localhost:3306 -N -f myserver.com

In my last post, I was talking about the idea of using an ARM machine to build my image. That sounds really slow and painful, sure, but at least it could be done without problems.

Well, I posted the blog entry on twitter, and fortunately, TheVaw, a good friend from Galicia, point me about using qemu. I knew qemu, but honestly, i never use it before.

To install qemu, on debian (or similars) you can follow this simple guide on the debian wiki. Basically, i installed:

apt-get install qemu binfmt-support qemu-user-static

With this package, you can cross compile a binary using the toolchain (apt-get install gcc-4.7-arm-linux-gnueabihf in my case), and run the arm binary in your x64 machine. It works.

So, I built the required binaries and they worked.. great! Then I continue compiling things, and dependencies, downloading repos, etc.

But after a while, I realized that this is totally insane! I have to patch some makefiles, I got errors with static libc libraries, blah blah, and I am tired of waste my time reinventing the wheel.

Looking for a better solution, i found the buildroot package. It seems to do everything that I am doing here, compile the kernel, make a minimum root filesystem, make an sdcard image, etc. I tested it, and it works!!

And even better, on the last version from git, all the projects binaries for sunxi are included!! the cubieboard is supported, and it has the tools for the boot loader. It builds the kernel 3.4 with the sunxi  modifications. And it compiles everything.

Also, I found another great candy, a custom buildroot in github. It seems based on buildroot, but with many modifications. I am reading the logs, trying to understand the differences, etc. You can read more on the linux-sunxi wiki.

Then, at this point, My idea is continue working on buildroot. As the target is to make my own board, I forked the buildroot git repo, and created my own version on github. To do so :

touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:derethor/buildroot.git
git push -u origin master
git remote add buildroot git://git.buildroot.net/buildroot
git fetch buildroot
git merge buildroot/master
git push -u origin master

Then, you can update the buildroot repo to your local repo (it will be buildroot/master), and rebase (if you dare to do so)

This is the github repo, if you want to followmy progress  (i dont promiss any commit 🙂

 

Well, after some days of research, i found that cross compile things on my PC wont be easy. Not at all. Some binaries are impossible to cross compile, because they build an executable to actually generate files. The cross compiler can build the tool, but not run it. And it doesnt work.

So, that is the thing, i have to use an ARM machine to build things. And I have only an A13, without network, and a rpi.

The thing is that If i cross compile something on the pc (linux mint 14), and then, I copy it to the rpi, it crases. I use armhf arch, but it seems that I need to enable something, etc.

So, to make my life easier. I will compile everything on the rpi. The kernel will take hours, i am sure, but it will work (i guess). Maybe on the furure, i can buy an A31 as a build machine for images, but it is ok, i dont have to build everything all the time.

Later, i will investigate how to cross compile the kernel here, using the same architecture than the rpi. I am sure that there are losts of tutorials on internet about it.

Puff

 

 

20130620_040154

 

You can see, the A13 Olinuxino Micro, connected with USB (only 500 mA, so, dont connect a touch screen, etc). I upload the image with the sony card reader, using a microsd adapter to sdcard (quite a pain to plug/unplug each time), and my lovely bus pirate (a logic analyzer for 20 euros). The Bus pirate works with the 3.3v serial port.

The Bus pirate can works like a simple sniffer (no sense), or you can use it like a normal terminal. It captures also i2c and SPI.

 

I downloaded this config from github, and reverted the script.bin to the original one from olinuxino… and using a very simple busybox env, I can boot and run a console!!!

This is the ps output

# ps
PID USER VSZ STAT COMMAND
1 0 872 S /bin/busybox init
2 0 0 SW [kthreadd]
3 0 0 SW [ksoftirqd/0]
4 0 0 SW [kworker/0:0]
5 0 0 SW [kworker/u:0]
6 0 0 SW< [cpuset]
7 0 0 SW< [khelper]
8 0 0 SW [kdevtmpfs]
9 0 0 SW< [netns]
10 0 0 SW [sync_supers]
11 0 0 SW [bdi-default]
12 0 0 SW< [kintegrityd]
13 0 0 SW< [kblockd]
14 0 0 SW [khubd]
15 0 0 SW< [md]
16 0 0 SW [kworker/0:1]
17 0 0 SW< [cfg80211]
18 0 0 SW< [rpciod]
19 0 0 SW [khungtaskd]
20 0 0 SW [kswapd0]
21 0 0 SWN [ksmd]
22 0 0 SW [fsnotify_mark]
23 0 0 SW< [nfsiod]
24 0 0 SW< [cifsiod]
25 0 0 SW< [crypto]
38 0 0 SW< [kmpathd]
39 0 0 SW< [kmpath_handlerd]
41 0 0 SW< [deferwq]
42 0 0 SW [mmcqd/0]
43 0 0 SW [kworker/u:2]
44 0 0 SW< [ext4-dio-unwrit]
52 0 872 S -/bin/sh
53 0 872 S /bin/busybox init
54 0 872 S /bin/busybox init
55 0 872 S /bin/busybox init
56 0 0 SW [flush-179:0]
59 0 876 R ps
The A13 is really hot. I guess because I am still trying to boot, and the clock is running at max freq all the time

quick heat dissipation

The A13 is really hot. I guess that it is because I am still builing the root image, and the kernel is running at fullspeed (1Ghz). I have some small heatsilk to cooldown a little bit the micro, but it is still hot (i didnt measure it, but you can touch it without problems… for a while)