Canonical Voices

Colin Ian King

3G using a Huawei E1552/E1800 (HSPA modem) on Ubuntu

So my internet service provider is rolling out a programme of speed upgrades and over the past few weeks I've suffered from various connectivity issues most probably because of infrastructure upgrades.   I lost connectivity today at 6am and was told to expect to be connected by 9pm, so I popped down town and acquired a 3G USB dongle and a suitable data plan/ contract for my needs.

Typically these USB dongles are designed to appear as USB media devices (e.g. pseudo CD-ROM) and one has to mode switch it to a USB modem.   Unfortunately I had a Huawei E1552/E1800 which required some USB mode switching magic, but to find this I first required internet connectivity.   Fortunately I had a sacrificial laptop which I installed an old version of Windows XP which allowed me to then connect to the internet using the 3G USB dongle and I was able to then track down the appropriate runes.  OK, I feel bad about installing Windows XP, but I was being pragmatic - I needed connectivity!

The procedure to get this device working on Ubuntu wasn't too bad.  First I identified the USB dongle using lsusb to get the vendor and product IDs (12d1:1446):

Bus 002 Device 013: ID 12d1:1446 Huawei Technologies Co., Ltd. E1552/E1800 (HSPA modem)

Then I added the following runes to /etc/usb_modeswitch.conf -

 DefaultVendor= 0x12d1  
 DefaultProduct=0x1446  
 TargetVendor= 0x12d1  
 TargetProductList="1001,1406,140b,140c,141b,14ac"  
 CheckSuccess=20  
 MessageContent="55534243123456780000000000000011060000000000000000000000000000"  

..this appears in many forums on the internet, kudos to whoever figured this out.

Then I ran "sudo usb_modeswitch -c /etc/usb_modeswitch.conf" and this switched the dongle into:

Bus 002 Device 012: ID 12d1:14ac Huawei Technologies Co., Ltd.

..and I was then able to simply connect using network manager.   Result!

** UPDATE **

Mathieu Trudel-Lapierre fixed this (9th Feb 2012) and now Ubuntu Precise works perfectly with the  Huawei E1552/E1800.  Thanks Mathieu!

Read more
Colin Ian King

open() using O_WRONLY | O_RDWR

One of the lesser known Linux features is that one can open a file with the flags O_WRONLY | O_RDWR.   One requires read and write permission to perform the open(), however, the flags indicate that no reading or writing is to be done on the file descriptor.   It is useful for operations such as ioctl() where we also want to ensure we don't actually do any reading or writing to a device.  A bunch of utilities such as LILO seem to use this obscure feature. 

LILO defines these flags as O_NOACCESS as follows:

 #ifdef O_ACCMODE  
 # define O_NOACCESS O_ACCMODE  
 #else  
 /* open a file for "no access" */  
 # define O_NOACCESS 3  
 #endif  

..as in this example, you may find these flags more widely known as O_NOACCESS even though they are not defined in the standard fcntl.h headers.

Below is a very simple example of the use of O_WRONLY | O_RDWR:

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
 #include <sys/ioctl.h>  
 #include <fcntl.h>  
 int main(int argc, char **argv)  
 {  
      int fd;  
      struct winsize ws;  
      if ((fd = open("/dev/tty", O_WRONLY | O_RDWR)) < 0) {  
           perror("open /dev/tty failed");  
           exit(EXIT_FAILURE);  
      }  
      if (ioctl(fd, TIOCGWINSZ, &ws) == 0)  
           printf("%d x %d\n", ws.ws_row, ws.ws_col);  
      close(fd);  
      exit(EXIT_SUCCESS);  
 }  

It is a little arcane and not portable but also an interesting feature to know about.

Read more
Colin Ian King

C ternary operator hack

Here is a simple bit of C that sets either x or y to value v depending on the value of c..

if (c)   
    x = v;  
else  
    y = v;  

..but why not "improve" this by using the C ternary operator ? : as follows:

 *(c ? &x : &y) = v;  

Now, how does this shape up when compiled on an x86 with gcc -O2 ?  Well, the first example compiles down to a test and a branch where as the second example uses a conditional move instruction (cmove) and avoids the test and branch and is faster code.  Result!

OK, so this isn't rocket science, but does show that a little bit of abuse of the ternary operator can save me a few cycles if the compiler is clued up to use cmove.

Read more
Colin Ian King

Part of my focus this cycle is to see where we can make power saving improvements for Ubuntu Precise 12.04 LTS. There has been a lot of anecdotal evidence of specific machines or power saving features behaving poorly over the past few cycles.   So, armed with a 6.5 digit precision multimeter from Fluke I've been measuring the power consumption on various laptops in different test scenarios to try and answer some outstanding questions:

* Is it safe to enable Matthew Garrett's PCIe ASPM fix?
* Are the power savings suggested by PowerTop useful and can we reliably enabled any of these in pm-utils?
* How accurate are the ACPI battery readings to estimate power consumption?
* Do the existing pm-utils power.d scripts still make sense?
* Which is better for power saving: i386, i386-pae or amd64?
* How much power does the laptop backlight really use?
* Does halving the mouse input rate really save that much more power?
* Should we re-enable Aggressive Link Power Management (ALPM)?
* Are there any misbehaving applications that are consuming too much power?
* What are the root causes of HDD wake-ups
* Which applications and daemons are creating unnecessary wake events?
* How much does the MSR_IA32_ENERGY_PERF_BIAS save us?

..and many more besides!

From some of the analysis and "crowd sourcing" tests it is clear that the PCIe ASPM fix works well, so we've already incorporated that into Precise.

Aggressive Link Power Management (ALPM) is a mechanism where a SATA AHCI controller can put the SATA link that connects to the disk into a very low power mode during periods of zero I/O activity and into an active power state when work needs to be done. Tests show that this can save around 0.5-1.5 Watts of power on a typical system. However, it has been known in the past to not work on some devices, so I've put a call for testing of ALPM out to the community so we can get a better understanding of the power savings vs reliability.

Some of the PowerTop analysis has shown we can save another 1-2 Watts of power by putting USB and PCI controllers of devices like Webcams, SD card controllers, Wireless, Ethernet and Bluetooth  into a lower power state.  Again, we would like to understand the range of power savings across a large set of hardware and to see how reliable this is, so another crowd sourced call for testing has been also set up.

So, if you want to contribute to the testing, please visit the above links and spend just a few tens of minutes to see we can extend the battery life of your laptop or netbook.  And periodically visit https://wiki.ubuntu.com/Kernel/PowerManagement to see if there any new tests you can participate in.

[UPDATE]

I've written some brief notes on power saving tweaks and also some simple recommendations for application developers to follow too.

The thread continues here (part 2)

Read more
Colin Ian King

Last month I wrote about the investigations being undertaken to identify any suitable power savings for Ubuntu Precise 12.04 LTS.  Armed with a suitably accurate 6.5 digit precision Fluke digital multimeter I worked my way through the Kernel Team Power Management Blueprint measuring many numerous configurations and ways to possibly save power.

A broad range of areas were examined, from kernel tweaks, hardware settings to disk wake-ups and application wakeup events.

Quite a handful of misbehaving applications have been identified ranging from frequent unnecessary wake-ups on poll() and select() calls to rather verbose logging of debug messages that stop the disk from going into power saving states.

We also managed to identify and remove pm-utils power.d scripts that didn't actually save any power and even consumed more power on newer Solid State Drives.    By carefully analysing all the PowerTop recommendations we also identified a subset of device power management savings that are shown to be useful and save power across a wide range of machines.   After crowd-source testing these tweaks we have now added them into pm-utils for Ubuntu Precise 12.04 LTS by default.  I'm very grateful to the Ubuntu community for participating in the testing and feedback.

I've written a brief summary of all the test results, however, the full results can be found in the various subdirectories here.   I've also written a very simple set of recommendations to help application developers avoid mistakes that lead to power wasting applications.

We've also set up a Power Management Wiki page that has links to the following:

* Identifying Power Sucking Applications
* Aggressive Link Power Management call for testing
* PCIe Active State Power Management call for testing (now complete)
* Updates to pm utils scripts call for testing (now complete)

..and probably the most useful:

* Power Saving Tweaks

The Power Saving Tweaks page lists a selection of tweaks that can be employed to save power on various machines.  Unfortunately with some hardware these tweaks cause lock-ups or rendering bugs, so they cannot be rolled out by default unless we can find either a definitive list of the broken hardware or a large enough whitelist to enable these on a useful set of working hardware.  Some of the tweaks cannot be rolled out for all machines as users want specific functionality enabled by default, for example, we need to enable Bluetooth for users with bluetooth keyboards and so it is up to the user to chose to disable Bluetooth to save 1-2 Watts of power.

I've also set-up a PPA with a few tools to help measure power and track down misbehaving wake-up events and CPU intensive applications.  These tools don't replace tools like PowerTop and top, but do allow me to track trends on a system over a long running period.   You may find these useful too.

We also have a Ubuntu Power Consumption Project set up to help us track bugs related to power consumption issues and regressions.  

Last, but no way least,  I'd like to thank Steve Langasek and Martin Pitt for all their help with the pm-utils and various fixes to power sucking applications.

Read more
Colin Ian King

Commodore 64 is 30

The C64 boot screen (running in vice)
30 years ago this week Commodore unveiled the Commodore 64 (C64) - a MOS 6510 based 8 bit microcomputer with a 64K of RAM. I was given a C64 and 1530 C2N cassette deck for Christmas when I was 15 years old and I eventually acquired a 1541 floppy drive. The C64's VIC II graphics chip was a powerful device that had various graphics modes, 8 pixels of smooth scrolling and 8 21x24 pixel sprites. The Sound chip (SID) sported 3 voices with 4 different waveform generators and fine control of the amplitude envelopes as well as filtering and tricks like ring modulation and synchronization.

The lack of a powerful BASIC interpreter directed my attention to learning 6502 assembler so I could start writing 3D wire frame vector graphics. I learned how to write cycle accurate timing code to drive the VIC II to make side borders disappear and with raster interrupts to make the the top and bottom borders disappear too. I also wedged in my own BASIC tokenizer and interpreter to extend the BASIC to provide better structured programming (while/wend, procedures, repeat/until) and sound, graphics and disk support - all this taught me how to structure large projects in assembler and how to write compact and efficient code.

I spent hours pouring over the disassembled C64 BASIC and Kernal ROMs and learned the art of reverse engineering from the object code. I figured out the tape format, analyzed the read/write characteristics of the tape drive head and re-wrote my own tape turbo loaders.
With the aid of an annotated ROM disassembly of the 1541 floppy drive I figured out how to write disk turbos and I hacked up my own fast formatting tools and my own file system.

By the time I was 17 I had acquired the the Super C Compiler and I learned how to write C on a system that had a 15 minute edit-compile-link-run turnaround cycle(!).

Elite on the C64.
All this 1MHz 8 bit goodness taught me valuable lessons in programming efficient code and the trade-off between compact code and fast code. I learned how to twiddle hardware, bit bang data down wires and push a system to squeeze a little more performance out of it.







I was fortunate to have the time and energy and the right hardware available in my formative years, so I am grateful for Commodore for producing the quirky and hackable C64.

See also  http://www.reghardware.com/2012/01/02/commodore_64_30_birthday

Read more
Colin Ian King

Monitoring /proc/timer_stats

The /proc/timer_stats interface allows one to check on timer usage in a Linux system and hence detect any misuse of timers that can cause excessive wake up events (and also waste power).  /proc/timer_stats reports the process id (pid) of a task that initialised the timer, the name of the task, the name of the function that initialised the timer and the name of the timer callback function.  To enable timer sampling, write "1\n" to /proc/timer_stats and to disable write "0\n".

While this interface is simple to use, collecting multiple samples over a long period of time to monitor overall system behaviour takes a little more effort.   To help with this, I've written a very simple tool called eventstat that calculates the rate of events per second and can dump the data in a .csv (comma separated values) format for importing into a spreadsheet such as LibreOffice for further analysis (such as graphing).

In its basic form, eventstat will run ad infinitum and can be halted by control-C. One can also specify the sample period and number of samples to gather, for example:

 sudo eventstat 10 60  

.. this gathers samples every 10 seconds for 60 samples (which equates to 10 minutes).

The -t option specifies an events/second threshold to discard events less than this threshold, for example:  sudo cpustat -t 10 will show events running at 10Hz or higher.

To dump the samples into a .csv file, use the -r option followed by the name of the .csv file.  If you just want to collect just the samples into a .csv file and not see the statistics during the run, use also the -q option, e.g.

 sudo eventstat -q -r event-report.csv


With eventstat you can quickly identify rouge processes that cause a high frequency of wake ups.   Arguably one can do this with tools such as PowerTop, but eventstat was written to allow one to collect the event statistics over a very long period of time and then help to analyse or graph the data in tools such as Libre Office spreadsheet.


The source is available in the following git repository:  git://kernel.ubuntu.com/cking/eventstat.git and in my power management tools PPA: https://launchpad.net/~colin-king/+archive/powermanagement

In an ideal world, application developers should check their code with tools like eventstat or PowerTop to ensure that the application is not misbehaving and causing excessive wake ups especially because abuse of timers could be happening in the supporting libraries that applications may be using.

Read more
Colin Ian King

Google's _nomap SSID madness

Now, I try to write positive comments on my blog, but now and again things really irk me and I need to comment about them.  

Google is using wireless access point SSIDs to construct a database to enable devices to determine their location using wireless and hence not relying on GPS.   If you want to opt out of this database, Google is suggesting that one should simply append _nomap to the SSID.   Google also hopes that this will become a standard SSID opt-out for any location service database.

This basically means that if you want your desired SSID you get opted into Google's database (so much for privacy), otherwise you have to put up with some utterly stupid name that Google mandates.  Thanks for the choice Google.  And there is nothing to stop other location service providers either suggesting a different naming scheme to make it impossible to opt out of one or more schemes.

Now, if the UK government mandated that all SSIDs needed to be named in a specific way to opt out of their special database, there would be uproar.  However, Google just ploughs ahead with more of their data gathering and nobody seems to complain.

Read more
Colin Ian King

UEFI  Compatibility Support Module (CSM) provides compatibility support for traditional legacy BIOS.  This allows allows the booting an operating system that requires a traditional option ROM support, such as BIOS Int 10h video calls.

While looking at boot and runtime misbehaviour on UEFI systems I would like to know if CSM is enabled or not, but the question is how does one detect CSM support?   Well, making the assumption that CSM is generally enabled to support Int 10h video calls, we look for any video option ROMs and see if the real mode Int 10h vector is set to jump to a handler in one of the ROMs.  

Option ROMs are found in the region 0xc0000 to 0xe0000 and normally the video option ROM is found at 0xc0000.  Option ROMs are found on 512 byte boundaries with a header bytes containing 0x55, 0xaa and ROM length (divided by 512) so we just mmap in 0xc0000..xe0000 and then scan the memory for headers to locate option ROM images.  

My assumption for CSM being enabled is that Int 10h vectors into one of these option ROMs, and we can assume it is a video option ROM if it contains the string "VGA" somewhere in the ROM image.  Yes, it is a hack, but it seems to work on the range of UEFI enabled systems I've so far used.

For reference, I've put the code in my debug-code git repository and available for anyone to use.


Read more
Colin Ian King

UEFI Secure Boot and Linux

There has been a lot of (heated) discussion in the past weeks concerning UEFI Secure Boot and how this can impact on the ability of a user to install their operating system of choice.

To address this, today has seen no less than two papers published to address this hot topic.  Canonical along with Red Hat have published a white paper that describes how UEFI Secure Boot will impact users and manufactures.   The paper also provides recommendations on the implementation of UEFI Secure Boot in way that allows users to be in control of their own PC hardware.

Meanwhile the Linux Foundation has also published a paper giving technical guidance on how to implement UEFI Secure Boot to allow operating systems other than Windows 8 to operate on new Windows 8 PCs.

So lots to read and good technical guidance all round.  Let's  hope that these constructive set of papers will push the argument into a positive outcome.


Read more
Colin Ian King

C vararg macros are very useful and I've generally used them a lot for wrapping C vararg functions.  However, at times it would be very useful to be able to determine the number of arguments being passed into the the vararg macro and this is not as straight forward as it first seems.

Anyhow, this problem has been asked many times on the usenet and internet, and I stumbled on a very creative solution by Laurent Deniau posted on comp.std.c back in 2006.

 #define PP_NARG(...) \  
      PP_NARG_(__VA_ARGS__,PP_RSEQ_N())  
 #define PP_NARG_(...) \  
      PP_ARG_N(__VA_ARGS__)  
 #define PP_ARG_N( \  
      _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \  
      _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \  
      _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \  
      _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \  
      _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \  
      _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \  
      _61,_62,_63,N,...) N  
 #define PP_RSEQ_N() \  
      63,62,61,60,          \  
      59,58,57,56,55,54,53,52,51,50, \  
      49,48,47,46,45,44,43,42,41,40, \  
      39,38,37,36,35,34,33,32,31,30, \  
      29,28,27,26,25,24,23,22,21,20, \  
      19,18,17,16,15,14,13,12,11,10, \  
      9,8,7,6,5,4,3,2,1,0  
   
 /* Some test cases */  
 PP_NARG(A) -> 1  
 PP_NARG(A,B) -> 2  
 PP_NARG(A,B,C) -> 3  
 PP_NARG(A,B,C,D) -> 4  
 PP_NARG(A,B,C,D,E) -> 5   

However, passing no arguments to this macro yields 1, which is not as we expect. So last night I tweaked the macro to fix this problem by checking the length of the stringified macro arguments and adjusting the return value for a empty __VA_ARGS__  - as follows:

 #define PP_NARG(...)  (PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) - \  
     (sizeof(#__VA_ARGS__) == 1))  
 #define PP_NARG_(...)  PP_ARG_N(__VA_ARGS__)  
   
 #define PP_ARG_N( \  
    _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \  
   _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \  
   _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \  
   _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \  
   _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \  
   _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \  
   _61,_62,_63, N, ...) N  
   
 #define PP_RSEQ_N() \  
     63,62,61,60,          \  
     59,58,57,56,55,54,53,52,51,50, \  
     49,48,47,46,45,44,43,42,41,40, \  
     39,38,37,36,35,34,33,32,31,30, \  
     29,28,27,26,25,24,23,22,21,20, \  
     19,18,17,16,15,14,13,12,11,10, \  
     9,8,7,6,5,4,3,2,1,0  

The purists may point out that PP_NARG() only handles 64 arguments.  For just integer arguments, a better solution for any number of arguments has been proposed by user qrdl on stackoverflow:

 #define NUMARGS(...) (int)(sizeof((int[]){0, ##__VA_ARGS__})/sizeof(int)-1)

..which is appealing as it is more immediately understandable than the PP_NARG() macro, however it is less generic since it only works for ints.

Anyhow, it's great to find such novel solutions even if they may be at first a little bit non-intuitive.


Read more
Colin Ian King

Forcing a CMOS reset from userspace

Resetting CMOS memory on x86 platforms is normally achieved by either removing the CMOS battery or by setting a CMOS clear motherboard jumper in the appropriate position.  However, both these methods require access to the motherboard which is time consuming especially when dealing with a laptop or netbook.

An alternative method is to twiddle specific bits in the CMOS memory so that the checksum is no longer valid and on the next boot the BIOS detects this and this generally forces a complete CMOS reset.

I've read several ways to do this, however the CMOS memory layout varies from machine to machine so some suggested solutions may be unreliable across all platforms.  Apart from the Real Time Clock (which writing to won't affect a CMOS reset), the only CMOS addresses to be consistently used across most machines are 0x10 (Floppy Drive Type), 0x2e (CMOS checksum high byte) and 0x2f (CMOS checksum low byte).  With this in mind, it seems that the best way to force a CMOS reset is to corrupt the checksum bytes, so my suggested solution is to totally invert each bit of the checksum bytes.

To be able to read the contents of CMOS memory we need to write the address of the memory to port 0x70 then delay a small amount of time and then read the contents by reading port 0x71.    To write to CMOS memory we again write the address to port 0x70, delay a little, and then write the value to port 0x71.   A small delay of 1 microsecond (independent of CPU speed)  can be achieved by writing to port 0x80 (the Power-On-Self-Test (POST) code debug port).

 static inline uint8_t cmos_read(uint8_t addr)  
 {  
     outb(addr, 0x70);    /* specify address to read */  
     outb(0, 0x80);       /* tiny delay */  
     return inb(0x71);    /* read value */  
 }  
   
 static inline void cmos_write(uint8_t addr, uint8_t val)  
 {  
     outb(addr, 0x70);    /* specify address to write */  
     outb(0, 0x80);       /* tiny delay */  
     outb(val, 0x71);     /* write value */  
 }  

And hence inverting CMOS memory at a specified address is thus:

 static inline void cmos_invert(uint8_t addr)  
 {  
     cmos_write(addr, 255 ^ cmos_read(addr));  
 }  

To ensure we are the only process accessing the CMOS memory we should also turn off interrupts, so we use iopl(3) and asm("cli") to do this and then asm("sti") and iopl(0) to undo this.   We also need to use ioperm() to get access to ports 0x70, 0x71 and 0x80 for cmos_read() and cmos_write() to work and we need to run the program with root privileges.  The final program is as follows:

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <stdint.h>  
 #include <unistd.h>  
 #include <sys/io.h>  
   
 #define CMOS_CHECKSUM_HI (0x2e)  
 #define CMOS_CHECKSUM_LO (0x2f)  
   
 static inline uint8_t cmos_read(uint8_t addr)  
 {  
     outb(addr, 0x70);    /* specify address to read */  
     outb(0, 0x80);       /* tiny delay */  
     return inb(0x71);    /* read value */  
 }  
   
 static inline void cmos_write(uint8_t addr, uint8_t val)  
 {  
     outb(addr, 0x70);    /* specify address to write */  
     outb(0, 0x80);       /* tiny delay */  
     outb(val, 0x71);     /* write value */  
 }  
   
 static inline void cmos_invert(uint8_t addr)  
 {  
     cmos_write(addr, 255 ^ cmos_read(addr));  
 }  
   
 int main(int argc, char **argv)  
 {  
     if (ioperm(0x70, 2, 1) < 0) {  
         fprintf(stderr, "ioperm failed on ports 0x70 and 0x71\n");  
         exit(1);  
     }  
     if (ioperm(0x80, 1, 1) < 0) {  
         fprintf(stderr, "ioperm failed on port 0x80\n");  
         exit(1);  
     }  
     if (iopl(3) < 0) {  
         fprintf(stderr, "iopl failed\n");  
         exit(1);  
     }  
   
     asm("cli");  
     /* Invert CMOS checksum, high and low bytes*/  
     cmos_invert(CMOS_CHECKSUM_HI);  
     cmos_invert(CMOS_CHECKSUM_LO);  
     asm("sti");  
   
     (void)iopl(0);  
     (void)ioperm(0x80, 1, 0);  
     (void)ioperm(0x70, 2, 0);  
   
     exit(0);  
 }  

You can find this source in by debug code git repo.

Before you run this program, make sure you know which key should be pressed to jump into the BIOS settings on reboot (such as F2, delete, backspace,ESC, etc.) as some machines may just display a warning message on reboot and need you to press this key to progress further.

So to reset, simple run the program with sudo and reboot.  Easy.  (Just don't complain to me if your machine isn't easily bootable after running this!)


Read more
Colin Ian King

Some problems are a little challenging to debug and require sometimes a bit of lateral thinking to solve.   One particular issue is when suspend/resume locks up and one has no idea where or why because the console has is suspended and any debug messages just don't appear.

In the past I've had to use techniques like flashing keyboard LEDs, making the PC speaker beep or even forcible rebooting the machine at known points to be able to get some idea of roughly where a hang has occurred.   This is fine, but it is tedious since we can only emit a few bits of state per iteration.   Saving state is difficult since when a machine locks up one has to reboot it and one looses debug state.   One technique is to squirrel away debug state in the real time clock (RTC) which allows one to store twenty or so bits of state, which is still quite tough going.

One project I've been working on is to use the power of system tap to instrument the entire suspend/resume code paths - every time a function is entered a hash of the name is generated and stored in the RTC.  If the machine hangs, one can then grab this hash out of the RTC can compare this to the known function names in /proc/kallsyms, and hopefully this will give some idea of where we got to before the machine hung.

However, what would be really useful is the ability to print out more debug state during suspend/resume in real time.   Normally I approach this by using a USB/serial cable and capturing console messages via this mechanism.  However, once USB is suspended, this provides no more information.

One solution I'm now using is with Kamal Mostafa's minimodem.  This wonderful tool is an implementation of a software modem and can send and receive data by emulating a Bell-type or RTTY FSK modem.  It allows me to transmit characters at 110 to 300 baud over a standard PC speaker and reliably receive them on a host machine.  If the wind is in the right direction, one can transmit at higher speeds with an audio cable plugged in the headphone jack of the transmitter and into the microphone socket on the receiver if hardware allows.

The 8254 Programmable Interval-timer on a PC can be used to generate a square wave at a predefined frequency and can be connected to the PC speaker to emit a beep.  Sending data using the speaker to minimodem is a case of sending a 500ms leader tone, then emitting characters.  Each character has a 1 baud space tone, followed by 8 bits (least significant bit first) with a zero being a 1 baud space tone and a 1 being represented by a 1 baud mark tone, and the a trailing bunch of stop bits.

So using a prototype driver written by Kamal, I tweaked the code and put it into my suspend/resume SystemTap script and now I can dump out messages over the PC speaker and decode them using minimodem.  300 baud may not be speedy, but I am able to now instrument and trace through the entire suspend/resume path.

The SystemTap scripts are "work-in-progress" (i.e. if it breaks you keep the pieces), but can be found in my pmdebug git repo git://kernel.ubuntu.com/cking/pmdebug.git.  The README file gives a quick run down of how to use this script and I have written up a full set of instructions.

The caveat to this is that one requires a PC where one can beep the PC speaker using the PIT.  Lots of modern machines seem to either have this disabled, or the volume somehow under the control of the Intel HDA audio driver.  Anyhow, kudos to Kamal for providing minimodem and giving me the prototype kernel driver to allow me to plug this into a SystemTap scrip.


Read more
Colin Ian King

UEFI EDK II Revisited

My colleague Manoj Iyer has written up a guide on how to download EDK II and build the UEFI firmware for QEMU.   This requires older versions of gcc found in Natty (since the newer Oneiric version is more pedantic and uses -Werror=unused-but-set-variable by default).

With a chroot I was able get it downloaded, built and tested in less than 40 minutes.   Here is a sample UEFI helloworld application running in QEMU using the firmware using Manoj's instructions.


Now I can rig up some tests to exercise Ubuntu and the Firmware Test Suite without the need for any real UEFI hardware..


Read more
Colin Ian King

PCI Interrupt Routing

Understanding PCI Interrupt Routing on the x86 platform is a not entirely straight forward.  The underlining principle is determining which interrupt is being asserted when a PCI interrupt signal occurs. Unfortunately this is generally platform specific and so firmware tables of various types have been used over the many years to describe the routing configuration.

While looking into the legacy PCI interrupt routing tables I found an excellent article by FreeBSD kernel hacker John Baldwin that explains PCI interrupt routing in a clear an succinct manner.   Although written for FreeBSD, this article is contains a lot of Linux relevant information.


Read more
Colin Ian King

Dennis Ritchie, R.I.P.

Dennis Ritchie has passed away. He gave us C and UNIX and much more beside. My tribute to Dennis Ritchie is as follows:

 #include <stdio.h>  
 #include <stdlib.h>  
 #define K continue  
 #define t /*|+$-*/9  
 #define _l /*+$*/25  
 #define s/*&|+*/0xD  
 #define _/*&|+*/0xC  
 #define _o/*|+$-*/2  
 #define _1/*|+$-*/3  
 #define _0/*|+$*/16  
 #define J/*&|*/case  
 char typedef signed   
  B;typedef H;H main(  
  ){B I['F'],V=0,E[]=  
   {s,0,s,31,t,1,s,111  
   ,_,t,-3,_,s,50,_l,-  
    1,t,1,s,0x48>>2,_l,  
    -2,_,_1,5,_o,s,0,_1  
     ,-8,s,0,s,-65,t,75,  
     s,100,_,t,8,_,_1,-5  
      ,s,82,t,32,s,111,s,  
      20,_l,-2,t,7,_,_1,5  
       ,_o,s,0,_1,-8,s,0,\  
      _0,};B*P=E;while(P)  
      {B L=*P,l=*(P+1),U=  
     I[V-1],A=(L>>2)&1,C  
     =(V-(1-A)),i;switch  
    (L)while(0){J _l:i=  
    l>0?U>>l:U<<-l;K;J\  
   t:i=U+l;K;J _:i=U;  
   K;J s:i=l;K;J _o:  
  putchar(U);K;J _1:  
  P+=U?0:l;K;J _0:e\  
 xit(0);}C[I]=(L&8)?  
 i:I[C];P+=(L&1)+1;V  
 +=A-((L&2)>>1);}re\  
 turn/*c.i.king*/0;}  

You can download the source here.


Read more
Colin Ian King

Today my colleague Chris Van Hoof pointed me to a Gource visualization of the work I've been doing on the Firmware Test Suite.  Gource animates the software development sources as a tree with the root in the centre of the display and directories as branches and source files as leaves.


Static pictures do this no justice. I've uploaded an mp4 video of the entire software development history of fwts so you can see Gource in action.

To generate the video, the following incantation was used:

 gource -s 0.03 --auto-skip-seconds 0.1 --file-idle-time 500 \  
 --multi-sampling -1280x720 --stop-at-end \  
 --output-ppm-stream - | ffmpeg -y -r 24 \  
 -f image2pipe -vcodec ppm -i - -b 2048K fwts.mp4  

..kudos to Chris for this rune.


Read more
Colin Ian King

Exponential Growth of Patents

The United States Patent and Trademark Office (USPTO) recently publish an interesting article about the millions of patents issued by the United States of America.  Using the current numbering system, patent #1 was issued in 1836 and patent #8,000,000 was recently issued in August this year.   I plotted issue date against patent number and lo and behold we get exponential growth of patents since the turn of the 20th century:

At this rate, we will see 8 million more patents issued by the end of 2016.  Intellectual property is abundant, perhaps too much so.  Are all these patents totally valid?  Is there any kind of quality control being applied?  Personally, I doubt it.  I don't want to be alarmist, but I really think this is getting totally out of control.

Patents are used as trading tokens as big businesses wage war against each other.  Companies are loading their war-chests with patent portfolios to block rivals from bringing to market innovative new products which leads to a product monoculture.   More perversely, patents are being used so sue users of technology rather than manufacturers.  Ultimately the consumer is the loser and patent lawyers and big business are the winners -  that's the price for patents protecting innovation.


Read more
Colin Ian King

More interesting uses for SystemTap

Now and again while debugging systems I would like to be able to evaluate an ACPI method or object and see what it returns.    To solve this problem in a generic way I put a little bit of effort today in developing a short SystemTap script that allows me to run acpi_evaluate_object() on a given named object and to dump out any returned data.

I've wrapped the gory details up into a small wrapper function called which is passed just the name of the object to evaluate and if necessary an acpi_object_list containing the arguments to be passed into a method call.   For methods that don't require arguments, we end up with a simple call like the  following:

                acpi_eval("_BIF", NULL);

..and for more complex examples, with arguments, we have:

        struct acpi_object_list arg_list;
        union acpi_object args[1];

        args[0].type = ACPI_TYPE_INTEGER;
        args[0].integer.value = 1; 
        arg_list.count = 1;
        arg_list.pointer = args; 
        acpi_eval("_WAK", &arg_list);

The script is designed to allow one to hack away and add in the calls to the objects that one requires to be evaluated, quick-n-dirty, but it does the job.

It was surprisingly easy to get this up and running with SystemTap once I had figured how to dump out the evalated objects to the tty - the script is fairly compact and the main bulk of the code is a terse error message table.

The script can be found it my SystemTap git repo: git://kernel.ubuntu.com/cking/systemtap-scripts.git


Read more
Colin Ian King

Proprietary Code - Where do we draw the line?

I can't help being amused when users say they chose not to use a specific Open Source distribution because it contains binary drivers and hence is not totally free.  I too really care that we have software freedom and try to work towards a totally free Operating System but where do we draw the line?

Some users state that they won't touch a specific brand of hardware such as Wireless or Video because one has to use a binary driver or that it contains firmware that is not Open Source.  While this is an admirable philosophical stance it has its blind-spots. For example,  laptops contain Embedded Controllers to do a variety of hardware interfacing tasks - do we refuse to use these laptops because the firmware in the Embedded Controllers are not Open Source?  Or how about the ACPI AML code that appears in the DSDT and SSDTs - so should we boot the machine with ACPI disabled because this code is not Open Source?

Taking it further, what about the Microcode inside the processor?  This binary blob is loaded by BIOS updated by the Operating System to fix subtle features in Microprocessors post-release.  So, should we stop using this because Intel won't supply us the source?

So at what point do we stop using a system because it is not fully Open Source?  OK, so I've taking the argument to its logical conclusion to stretch the point.   I fully understand that it is totally desirable to avoid using Closed Source binary blobs where possible and trying to keep a system totally Open Source keeps us honest.  However, sometimes I find the purest viewpoint rather blinkered if it refuses to use a specific distribution when their machine is riddled with Closed Source binary firmware blobs.  Perhaps they should start working on the BIOS vendors and Intel to release their code..


Read more