Saturday, December 27, 2008

building jaunty using git



Day 1:

Yesterday, I re-visited the task of building the kernel for ubuntu-jaunty. Obtaining the source using git is covered here. Compiling the source is covered here.

Snag1:
I was on Hardy (not Intrepid) and Hardy repositories do not have a needed utility makedumpfile. After a few hours of compiling, the build failed as it couldn't find makedumpfile. You can save yourself the trouble and manually install the package from here. Once you download the makedumpfile package, you can install it like so:

dpkg -i /path/to/file/makedumpfile_1.2.9-0ubuntu3_i386.deb

So I'm now starting a build again, but this time, to save some time, I will build just the generic flavor, like so:

AUTOBUILD=1 NOEXTRAS=1 fakeroot debian/rules binary-generic

I'm also removing the source directory and cloning the repository fresh. This is to
make sure that there are no conflicts with any files left over from the previous
build.

Day 2:
So today I got the build to go all the way. It generated two debs - the linux image
and headers respectively. I installed the image like so:

dpkg -i linux-image-2.6.28-4-generic_2.6.28-4.5_i386.deb

Since I had modified the /boot/grub/menu.1st file, this gave me the option of overwriting
it or keeping the old. I kept the old file as there were entries to all my
kernel versions I wanted to keep. Later I manually added the stanza
for the new kernel to /boot/grub/menu.1st like so:

title Ubuntu 8.04.1, git kernel 2.6.28-4-generic
root (hd0,0)
kernel /vmlinuz-2.6.28-4-generic root=UUID=b79346d4-7799-43ae-a033-99d70b6784be ro quiet splash
initrd /initrd.img-2.6.28-4-generic
quiet

Snag 2:
Then I tried installing the headers like so:

dpkg -i linux-headers-2.6.28-4-generic_2.6.28-4.5_i386.deb

But this failed as there was a dependency on linux-headers-2.6.28-4 which was not
present on the system. I found it here. I installed it like so:

dpkg -i linux-headers-2.6.28-4_2.6.28-4.5_all.deb

After that, I could successfully install the headers.

After which, I could reboot into the new kernel.

Wireless:

However my wireless connection did not work. Looking at the dmesg output I found these:

thushara@gini-sisila:~$ dmesg | grep acx
[ 12.782440] acx: Loaded combined PCI/USB driver, firmware_ver=default
[ 12.782450] acx: compiled to use 32bit I/O access. I/O timing issues might occur, such as non-working firmware upload. Report them
[ 12.782532] acx_pci 0000:00:0b.0: PCI INT A -> Link[LNKD] -> GSI 10 (level, low) -> IRQ 10
[ 12.782758] acx: found ACX111-based wireless network card at 0000:00:0b.0, irq:10, phymem1:0xE2020000, phymem2:0xE2000000, mem1:0xe0edc000, mem1_size:8192, mem2:0xe08c0000, mem2_size:131072
[ 12.783790] acx: loading firmware for acx1111 chipset with radio ID 16
[ 12.783801] acx_pci 0000:00:0b.0: firmware: requesting acx/1.2.1.34/tiacx111c16
[ 20.290162] acx: firmware image 'acx/1.2.1.34/tiacx111c16' was not provided. Check your hotplug scripts
[ 20.290177] acx_pci 0000:00:0b.0: firmware: requesting acx/1.2.1.34/tiacx111
[ 20.772774] acx: firmware image 'acx/1.2.1.34/tiacx111' was not provided. Check your hotplug scripts
[ 20.772786] acx: reset_dev() FAILED
[ 20.772840] acx_pci 0000:00:0b.0: PCI INT A disabled
[ 20.788119] acx_pci: probe of 0000:00:0b.0 failed with error -5
[ 20.788361] usbcore: registered new interface driver acx_usb

So it looked like the firmware files were missing. Doing a quick `locate tiacx` listed
that the firmware files were available on my previous kernel lib path but not on
the current kernel firmware path.

So I created the firmware directory for the acx driver under the directory for
the new kernel and copied just the single file mentioned by the dmesg to that
location, like so:

sudo cp /lib/firmware/2.6.24-19-generic/acx/1.2.1.34/tiacx111c16 /lib/firmware/`uname -r`/acx/1.2.1.34

After this, I could reboot into the new kernel and the wireless worked.

Tuesday, December 16, 2008

Java has no unsigned types



I came across this today as I need to create a hash that maps a tuple to an object. The tuple comprises of two keys. Each key is in reality an unsigned integer (32 bit). I was hoping to construct a key for the hash by shifting one key 32 bits and ORing them together to make a 64bit key.

A good article on this can be found here.

The problem with not being able to use an unsigned type supported by the language is the introduction of subtle bugs.

Here's an example:

int x = 0x865a672b;
long y = (0x12345678<<32) | x

1) you can shift an integer (32 bit value) a maximum of 31 bits. in fact if you were to do:

val << shift, where val is an integer, java internally does val << (shift%32)
Thus in this case, 0x12345678 is not shifted at all.

2) so the 0x12345678 never gets promoted to a 64-bit long. Thus we expected 0x1234567800000000, but we have 0x12345678.

3) 0x865a672b is a negative number (as it is an integer). So the 64-bit representation would be 0xffffffff865a672b

4) so we're in fact performing 0x12345678 | 0xffffffff865a672b = 0xffffffff967e777b

So how about this? (We're using longs now)

long x = 0x865a672b;
long y = (0x12345678L<<32) | x;

This gives us 0xffffffff865a672b which is still not what we want, but close. So what is happening here is that even though we declared x to be a long, 0x865a672b is treated as an integer, and java converts that negative integer to a long and in the process keeps the sign (-ve). So x is really 0xffffffff865a672b. So when we OR this to 0x1234567800000000, the high order 32 bits are lost.

Ok, last try:

long x = 0x865a672bL;
long y = (0x12345678L<<32) | x;

Notice we're coercing 0x865a672bL to be a long (the L at the end). This works, giving us 0x12345678865a672b. Enough already!

So if you want to work with unsigned 32-bit values in java, always work in long data type and convert any literal to long with an L at the end.