Friday, July 31, 2009

Booting Linux live from mobile phone

== If you had landed here thinking this is about booting Linux on your mobile phone, "NO". This is about booting Linux on a comp/laptop from a mobile phone ==

The concept of booting and using Linux without having to install it on hard disk (aka Live CD) has been there for years (at least 10?). Thanks to Knoppix -- the pioneer in this approach. This later evolved to booting a live CD from media other than just CDs, like pen drives etc., With the later BIOS, supporting USB devices in the boot list, this had become pretty handy. I was a big fan of Damn Small Linux (DSL), which is really a damn small linux (with just a 50MB foot print) and goes almost invisible on your pen drive. I used to happily carry around DSL on my pen drive 2-3 years back.

But hold on. Why do I need to carry a bootable linux on my pen drive?? Anyways I need a comp to boot it; and the comp would anyway have an OS installed. Then why? True, but it is handy. I primarily see this useful for 2 purposes:

1. To use it as a recovery tool if something terribly goes wrong with my comp -- I do backup my master-boot-record (MBR) and the partition table (pretty easy to backup/restore from linux) etc., so I can recover my PC if something goes wrong at that level. This is also useful to analyze any comp for that matter if that fails to boot.

2. I can carry a set of applications along with me. If I have a comp infront of me, I would like to have a C/C++ compiler on it, maybe python interpreter and sometimes Office suite (MS office or open office). I cannot expect this everywhere I need it. Well, my own personal comp in my home town (one of the powerful ones I had during my Engineering with 64MB RAM and 500MHz processor :D) now barely has anything useful in it. It does not have most of the applications that I would need for today; and some times it does not even boot when I need it to :) No photoshop, python, games etc., Carrying a linux satisfies all (at least, most of) these requirements.

This being so useful, the major setback is the necessity to carry around that pen drive all the time; this drawback supersedes and suppresses all its advantages, and I mostly did not have my pen drive with me when I needed it ; And at some point, I forgot which of my 'n' pen-drives had the Linux live installed -- and that was the end to my use of this approach.

Recently, this thought struck my mind -- Why shouldn't I use my mobile phone as a pen drive, as I carry it all the time. And now that I have a Windows Mobile phone, I was really interested to see my "Windows" phone striving hard to help me in booting Linux on my comp :). But, I wasn't sure if that would work, without having to have a dedicated memory card. I was very clear that this is useful only if I can use the memory card for any other use on my mobile, like earlier. I tried various flavors including Fedora, DSL and Knoppix. My first choice was DSL -- it being so small, but that failed to boot off any pen drive on my laptop and my desktop (Gave up! maybe it does not support a variety of hardware?). Fedora 11 was the next choice. I used this live USB Creator, but that failed to boot too -- I didn't spend much time on it. I thought I would try out the legend Knoppix and it just worked effortlessly. The only important thing to notice in this project is, that we need to boot Linux off a FAT16 drive. The knoppix live CD comes with the isolinux boot loader that operates off an ISO -- but that wouldn't help us here. Thankfully, syslinux is a boot loader that does this job for us.

So, here is what you need to do if you need to boot Linux from your pendrive or Windows Mobile or any other mobile that supports Mass-storage mode.

On Windows: (TRY AT YOUR OWN RISK!!!)

1. Download Knoppix Live CD ISO image.
2. Download syslinux.
3. If mobile, put your Mobile in USB Mass-storage mode and connect it to your PC (else connect your pendrive to your PC).
4. Extract the Knoppix ISO to a folder say C:\MyFolder (Many software could do this including WinZip, 7Z etc.,)
5. Copy all the files from the C:\MyFolder\boot folder to C:\MyFolder\ (ie., bring the files inside boot folder to the parent directory).
6. Rename C:\MyFolder\isolinux.cfg to C:\MyFolder\syslinux.cfg (thankfully the config files are similar between isolinux and syslinux).
7. Delete the isolinux.bin file from C:\MyFolder\ (we don't need this).
8. Now copy all the files from C:\MyFolder to your mass-storage folder (say G:). Note: Directory structure should be such that all files in the C:\MyFolder should be in the root directory of your mass-storage drive.
9. IMPORTANT: Be very careful at this step. If you give a wrong drive letter, you may spoil your computer from booting. Open up a command prompt. CD to the folder where you have syslinux and run 'win32\syslinux.exe -ma G:' (I assume G: is your mass-storage drive).

You are all set. Make sure you have USB removable device / USB HDD in the boot list (with priority ahead of your HDD) of your computer. If all done well, connect your mobile/pendrive to your comp and reboot; you should see Knoppix booting off it.

Here is my Lenovo T400 Laptop booting Knoppix from my Windows Mobile ASUS P320: (The video is little long, please feel free to forward if you feel bored; but I want to provide even granular details for the interested, so didn't strip it down).

Have fun!

Friday, July 24, 2009

Windows Mobile Mass-storage drains battery

I recently discovered that my Windows Mobile (ASUS P320) phone drains battery if the USB connection setting is set to 'Mass storage'. In fact it terribly drains; almost half its usual time. It drains battery even if the phone is not connected over USB to any host and even if the phone is in sleep mode. Horrible and unexpected!!

So, in case you have a Windows Mobile phone and suffer with pretty poor battery performance (less than 1.5 days) check if you had changed the USB setting to 'mass-storage' (Start->Settings->Connections->USB). Set it to 'activesync turbo mode'. Change to mass-storage only when required and change it back. It is quite likely that this problem is specific to Windows Mobile 6.1, but I would not be surprised if this issue exists in other versions.

Also, many people complain about WinMo phones switching off much earlier than the battery becoming totally empty. It is important to understand that phone switching off itself on low battery is for your own benefit; if a WinMo runs totally out of battery, it is as good as a hard reset (you lose everything in your phone memory including applications (on phone mem), messages, contacts etc.,). Ideally it switches off when charge in the battery goes below 10% and you can still boot it back again in emergency (it tries to switch off again); I've even made calls at those times. Also, even if the phone is switched off, it still uses battery to keep the memory contents alive; so the remaining 6-10% is reserved to preserve your data until you get to a charger. So it is better not to force boot. I think, usually there is also a small internal backup battery, to support changing of phone batteries without losing data, but that's not going to last long.

Thursday, July 16, 2009

TVProgramGuide -- developer's view - #2

This is a follow up of my previous post on developer's view on my TVProgramGuide application.

There were 2 APIs identified : InitIR and GetIRCode

The next step is to identify the return types, calling convention, parameter list and types of these two. Let me explain how I discovered them for one of those APIs (GetIRcode - the difficult one) by reverse-engineering their disassembly.

Disassembly of ThatDll!GetIRCode

10001190 83ec0c sub esp,0Ch
10001193 8d442400 lea eax,[esp]
10001197 53 push ebx
10001198 8d4c2408 lea ecx,[esp+8]
1000119c 33db xor ebx,ebx
1000119e 50 push eax
1000119f 51 push ecx
100011a0 c6442410c0 mov byte ptr [esp+10h],0C0h
100011a5 c644241102 mov byte ptr [esp+11h],2
100011aa 885c2412 mov byte ptr [esp+12h],bl
100011ae 885c2413 mov byte ptr [esp+13h],bl
100011b2 885c2414 mov byte ptr [esp+14h],bl
100011b6 885c2415 mov byte ptr [esp+15h],bl
100011ba c644241601 mov byte ptr [esp+16h],1
100011bf 885c2417 mov byte ptr [esp+17h],bl
100011c3 c744240c08000000 mov dword ptr [esp+0Ch],8
100011cb e870ffffff call ThatDll!SendVendorCmd (10001140)
100011d0 3bc3 cmp eax,ebx
100011d2 5b pop ebx
100011d3 8b542410 mov edx,dword ptr [esp+10h]
100011d7 750c jne ThatDll!GetIRCode+0x55 (100011e5)
100011d9 8a4c2404 mov cl,byte ptr [esp+4]
100011dd 880a mov byte ptr [edx],cl
100011df 83c40c add esp,0Ch
100011e2 c20400 ret 4
100011e5 c602ff mov byte ptr [edx],0FFh
100011e8 83c40c add esp,0Ch
100011eb c20400 ret 4

Calling convention:
An easy technique to identify the calling convention is to look for the 'ret' statement @25,28 (I would also advise to double check with the caller's next instruction disassembly to make sure he doesn't play with the stack pointer). In stdcall calling convention the callee is supposed to free the stack space for arguments. I think here we are debating only over stdcall and cdecl calling conventions. So, if the 'ret' statement has any value given as operand (no. of bytes to free up on stack), then the calling convention should be 'stdcall'. In most cases, DLLs are stdcalls -- and this observation ensures that for this dll.

Return type (and out params):
In this case, we had already discovered that the technical return type is an int (and was returning 0x0 on keypress and 0xff on no keypress). However, we are still lacking the keycode when a key was pressed. If you look at the epilogue of the function, there are two branchings (clearly two rets @25,28). Please note the "mov byte ptr [edx],0FFh" @26. This looks like an error case, when SendVendorCmd failed (@21). A close look at the diassembly (@18,21) reveals that this code flow occurs when the return value of SendVendorCmd is non-zero (!=ebx); it should also be noted that the return value of GetIRCode is the same as the return value of SendVendorCmd (note that there is no change in eax after the call to SendVendorCmd). If you look at the success path(@22,23), an out parameter of SendVendorCmd (@[esp+4]) is copied on to the address in edx (note the byte ptr mov -- the out param value is so an unsigned char).

Argument list and types:
We are almost done. The only missing piece is to figure out what is edx pointing to. This is a crucial and challenging part. Please bear with me. The statement 'mov edx, dword ptr[esp+10h]'@20, means that the address of the parameter is on the stack. The return statement denotes a 4 byte cleanup on the stack; so it is likely that the fucntion takes only one parameter and that is a pointer to a byte (unsigned char*). However, it is not clear if the [esp+10h] belongs to the local stack variable in this function or is really a argument pushed by the caller -- use of ebp might have been much clearer, but we don't have a choice here. Looking at the disassembly of SendVendorCmd (ret 8) tells me that it uses 8 bytes on stack for arguments. So after the call to SendVendorCmd, the esp will be less by 8 bytes. Now if you carefully account for all the push and pop instructions in this function before [esp+10h]@20, you would find out that the [esp+10h] is indeed pointing to [esp_0+4h] if esp_0 is the esp at the time of entry of the function. [esp+4h] at the entry point clearly skips the return address and lands on the first argument to the function.

And hence the function is 'int (__stdcall *ThatDll!GetIRCode)(unsigned char*)'

I believe I don't have to mention about the InitIR API. But that was pretty simple; the prototype turned out to be 'void (__stdcall *InitIR)(void)' :D.

Now, how to I use ths info to dynamically hook onto the existing TV tuner application is the only critical missing part. Stay tuned!

Sunday, July 12, 2009

TVProgramGuide -- developer's view

=== this post is for educational purposes only. please do not apply these concepts to hack into or do illegal stuff ===

As promised earlier, here is my post on what's behind my TVProgramGuide application.

For the ones who do not have the background on the topic and for the ones who did not read my post on my application -- I had a TV tuner hardware and an application that works with it. I could use my TV tuner remote to control the TV. Now I need to find a way to hook into this design and capture the TV remote key presses, so I can use it in my own applications (important: without affecting the TV app's functionality). I'm keen in mentioning only the critical and difficult portions of this app.

The whole issue can be split into multiple major issues:

1. Finding out the DLL and the APIs that the current app uses to read the remote key presses.
2. Reverse-engineer the APIs and find out their calling convention, return types and parameter lists (and types) -- you would definitely need if you are going to hook into the APIs.
3. Find a means to hook/patch the functionality to allow both the TV app and my app to capture the strokes -- multiple options available. Read on.
4. Decipher the codes to match the real keys on remote -- if 1-3 are complete, this shouldn't be difficult.

Let me talk about each one of them in detail.

Finding out the DLL and APIs:

The TV application and the tuner hardware are from different vendors. This have me the hope that there might mostly like be a dll which provides the set of APIs to talk between the two. Using dependency-walker I found the list of modules that the TV tuner application was depending on. I filtered a set of non-system DLLs that got installed along with the TV tuner application. Then listed down the "exports" table from each of those DLLs and looked for any reasonably named API that relates to this. In one of those DLLs (I'm not disclosing the name of the DLL to keep this hack anonymous), there was an API named 'GetIRCode' -- having known that remotes work on Infra-Red (IR), this was suspicious. There were other APIs named 'InitIR', 'GetOneButtonStatus' etc., which seemed more and more closer towards the functionality I was looking at. I was almost sure.

Here's the export table of that identified DLL :

To make sure if these are indeed the APIs that I was looking for: I attached the debugger (windbg) to the TV tuner application and added breakpoints to all APIs in that DLL. As the application starts, I got a breakpoint hit in Dll!InitIR. Makes sense. Then, I could see breakpoints continuously being hit on Dll!GetIRCode (yes, continuously). I just realized that there was no callback mechanism, and the application continuously polls for keypresses by calling GetIRCode (ahem!, waste of CPU). But is it really what I think? Just to make sure that this API was doing something useful on a key press, I looked at the return code of GetIRCode after each invocation. It returned 0xff (likely a -1 in signed byte) most times. I set a conditional breakpoint on the return statement of this function to break if the return value is != 0xff (ie., break if register eax != 0xff). I realized from my testing that, whenever I pressed a key on my TV remote, this break point was hit and the return value was 0 -- hmmm, almost there, but where is the key code??? hack isn't that easy :). A good news was that, during the runtime (when I tested with remote key presses), the TV tuner application did not call any other API on this DLL.

So, at the end of this step, I have discovered the DLL and two APIs that I might need to hook into. And also that GetIRCode returns 0 once after a key was pressed (note: I still do not know how to identify the key, just hoping that this API would help) -- no idea about the calling convention, return types, the parameters I need to pass in to these APIs and their types. Way to go!!

Step 2 for reverse-engineering those APIs for calling convention, parameter list/types is a long topic, stay tuned!