Showing posts with label Xperia. Show all posts
Showing posts with label Xperia. Show all posts

Thursday, August 9, 2012

Android native C programs | hello, world ! ARM LINUX | Dynamic Linking

Well, there are a lot of websites online that tell you how to write a android program. But they all are written in java and are compiled to a dalvik executable. Lets get to the basics and write one that runs over your processor rather than the dalvik virtual machine. First of all you need a toolchain. CodeSourcery has a lite edition that is available for free download (linux link, There is a windows version available too). After you download the toolchain (Make sure you have downloaded ARM/GNU Linux version). Untar it, Install it or do whatever you have to get it running (I suggest you to just download the tarball instead of installer). This must give you a folder arm-20xx.xx. We need to copy the libraries required. Decide on your workspace. Create a folder to hold all your work call it /exp. Copy the tool chain to the same folder. Now connect your phone to the computer open shell, command prompt, whichever you are using to access adb and pull /system/lib from it to some new folder in /exp say /exp/lib.

$ adb pull /system/lib /exp/lib

This must pull all the libraries to that folder. Now write your first code hello.c in the root of /exp

#include<stdio.h>
int main()
{
         printf("hello, world! \n ");
         return 0;
}



Now is the time to compile it. Compile it with arm-none-linux-gnueabi-gcc

$./arm-2011.03/bin/arm-none-linux-gnueabi-gcc -c hello.c

This should output a file hello.o, this is our compiled file. But is still not a executable. So now as to get a executable we need to link the file (dynamically) to the libraries. We have already copied libraries to the file /lib. So let us run the loader with required flags to get our executable. What flags do we require???. We need one to tell our program where to start running on execution --entry flag takes care of that. We also need to tell the program where the dynamic linker is when being executed on your phone so we use --dynamic-linker flag. -nostdlib is required so that the compiler doesn't include the standard libraries of linux (The ones in android are quite different). Its is also required to give the path the program should search for its libraries while running on the phone, so the first -rpath. The second one does the work of pointing the linker to the library files as to where the files are stored now (the ones you copied from phone), this is to help the loaded libraries to search for its dependencies. -L, this specifies the path where our library is stored in the computer, the library that is specified by the -l option. -o gives the file name of the output executable. And hello.o is the input file.


$./arm-2011.03/bin/arm-none-linux-gnueabi-ld --entry=main --dynamic-linker /system/bin/linker -nostdlib -rpath /system/lib -rpath ~/exp/lib -L ~/exp/lib -l c -o hello hello.o 

Now we only need to push the file into the phone and execute it.


We can observer that there is a problem in this program. It doesn't exit like the normal programs we used to work with. Instead it has to be terminated manually. How to overcome this defect??. This occurs because we have not asked the program to exit at all. Let us do that now by creating another function that exits the program. We modify the program


#include<stdio.h>
#include<stdlib.h>
int main()
{
         printf("hello, world! \n ");
         return 0;
}

void _close()
{
        exit(main());
}


Now we need to start the program from the _close point so that it calls the main program and then exits it. so compile it same way. But while linking it use --entry flag for _close. 

./arm-2011.03/bin/arm-none-linux-gnueabi-ld --entry=_close --dynamic-linker /system/bin/linker -nostdlib -rpath /system/lib -rpath ~/exp/lib -L ~/exp/lib -l c -o hello hello.o 

Now push this the same way into the phone and execute it


Now the program should exit normally. Cheers!!!

Wednesday, July 25, 2012

Android | Linux "Sysfs" interface in kernel [Xperia X10]

Before reading this, make sure you have read this post and this one.
Sysfs is a virtual file system provided by the linux kernel. It is exports information about devices and drivers, and is also used for configuration. We used this in previous post to set scaling_governor and scaling_max_freq. All those files are part of Sysfs interface. This post will outline on creating a new file in the same old cpufreq folder to display all possible frequencies that the cpu can run on. This was done on Xperia X10, and I have good reasons to believe that The interface files are created from the source in /drivers folder of the /kernel. This particular one we are searching for must be in /cpufreq. Inside the folder we find the source files. Open up cpufreq.c. 



Go to that part of the code that says sysfs interface. And find suitable place to create our file. As you can see I found mine.



Now that you have added a function to display the frequencies. Its time to create the file in the interface that would display them


They can be created by adding a line to the descriptors that create a file. Just add

define_one_ro(scaling_available_frequencies);


We need to add a line to the attributes structure also. Add

&scaling_available_frequencies.attr,


to the lines.


Now the driver file is ready. But if you have observed, we have made use of an external function by name


acpuclock_get_available_frequencies_str


This is not defined in acpuclock file. So we need to head over to the file


../kernel/arch/arm/mach-msm/acpuclock-8x50.c


and add this function to output the value of frequencies as a string buffer.


The function plainly alters the string in *buf to hold the values of the frequencies. This completes the work. Now compile the kernel and load it to the phone, and discover your own new interface that shows all the possible frequency values.


Tuesday, July 24, 2012

Android kernel overclock [QSD8250] [Xperia X10]

Playing Temple Run is great on my phone [Xperia X10]. But I was irritated by its constant lagging gameplay on my phone. One of awesome things about linux is that it allows for dynamic frequency scaling (???). That means changing the frequency at which the board is running on the go. I just remembered that, So connected the phone to the computer and established adb link. Then I went to the cpufreq folder. It was easy to find, I found it in sys/devices/system/cpu/cpu0. In this folder we find a lot of files that we can write to and control the freq of the board. A ls command would reveal all of them
$ls
  cpuinfo_min_freq
  cpuinfo_max_freq
  scaling_min_freq
  cpuinfo_max_freq
  affected_cpus
  related_cpus
  scaling_governor
  scaling_driver
  scaling_available_governors
  scaling_setspeed
  scaling_cur_freq
  stats
  ondemand


The files are self explanatory. For example doing

$cat cpuinfo_max_freq
998400

We get to know that the maximum freq of the cpu is 998400. The freq of the board is constantly changed to minimize the power consumption of the device. This change is done by a program known as governor. Many governors are found in a linux system. Typically five are found in any linux system.
  1. powersave
  2. performance
  3. userspace
  4. ondemand
  5. conservative 

But in my case (X10) there are only two

$cat scaling_available_governors
ondemand performance

Performance runs the cpu in fastest mode always and ondemand allows the freq to be controlled by superuser or root.

I did change my governor to performance. 

$su
#echo performance > scaling_governor
echo performance > scaling_governor

But I was still not satisfied with the results. Xperia X10 is officially a 1GHz phone, as announced on Gsmarena

But a little help of google shows that it can run upto 1.2GHz. A lot of developers have created overclocked kernels. I decided to create my own (uff... So much for Temple Run). Rest of the post shows how that was achieved. 

Try this at your own risk. I am not responsible for whatever the hell happens to your phone.

Basically we need a Linux environment to compile kernel. Oh I will not take the liberty of explaining the way in which we can compile the kernel. There is already a tutorial online on how to do so by an awesome guy (lol). And as usual we need the phone to be rooted and bootloader unlocked. And the source code for the Xperia X10 kernel can be found here. The link in the tutorial leads you to the latest kernel source, which surprisingly hasn't been configured for xperia x10. 

Ohk get into the kernel folder of the source. The clock is controlled using the code in a file by name of acpuclock-{model}.c. In our case the file would be acpuclock-8x50.c. You will find the file in ../../kernel/arch/arm/mach-msm folder. Open the file in a editor. A chipset can only run at certain frequencies. The possible frequencies are therefore tabulated and required freq selected from it in our case we must find the table somewhere inside this file. We find that there is a structure that holds all the possible freq values for the board

struct clkctl_acpu_speed acpu_freq_tbl_998[]

You can ignore the other struct as the max freq in that is less than X10's. The struct is just defined above the table   

We find that the first value is a integer depicting weather the freq is to be used for scaling or not.

 Now let us add our own frequencies to this table. Let us add just two frequencies after 998400KHz entry. Add

{ 1, 1000000, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x1B, 1300},
{ 1, 1228800, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x1C, 1300},

to the table. This must create us two scalable frequencies 1GHz and 1.2288GHz.


Now that we have created two extra frequencies, but the kernel is still not ready to be compiled. We need to edit the structure that creates this table on runtime

#ifdef CONFIG_CPU_FREQ_MSM
static struct cpufreq_frequency_table freq_table[20];


This creates an array of twenty structures of those frequency values, which was just sufficient for the initial table. But now that we have extra two values let us increase this to say 23


This takes care of the array. But there is another function by name

static void __init acpu_freq_tbl_fixup(void)

This thing fixes back the cpu frequency to normal values if it finds that the frequency has exceeded the fixed value. It does this by using a case statement

switch (tcsr_spare2 & 0xF0) {
case 0x70:
acpu_freq_tbl = acpu_freq_tbl_768;
max_acpu_khz = 768000;
break;
case 0x30:
case 0x00:
max_acpu_khz = 998400;
break;
case 0x10:
max_acpu_khz = 1267200;
break;
default:
pr_warning("Invalid efuse data (%x) on Max ACPU freq!\n",
tcsr_spare2);
goto skip_efuse_fixup;
}


Now change the value of case 0x00: max_acpu_khz to 1228800.



switch (tcsr_spare2 & 0xF0) {
case 0x70:
acpu_freq_tbl = acpu_freq_tbl_768;
max_acpu_khz = 768000;
break;
case 0x30:
case 0x00:
max_acpu_khz = 1228800;
break;
case 0x10:
max_acpu_khz = 1267200;
break;
default:
pr_warning("Invalid efuse data (%x) on Max ACPU freq!\n",
tcsr_spare2);
goto skip_efuse_fixup;
}

Ok that takes care of everything. Now just compile the kernel, and load it to your phone. And If you get this error during the compile time


Go to the Makefile in /kernel folder. And edit the KBUILD_CFLAGS in it, Just remove -Werror\ line.


That flag makes the compiler check for warnings and terminates the compile process in case of small warnings. On removal of the flag these are ignored. Any other problems you encounter just leave a comment at the end. I will try to rectify. Now to check out the build. After you load it to your phone connect it in USB debugging mode and open the shell. Now check for the maximum frequency. The best way to run the cpu in maximum freq is to run performance governor. So I changed the governor to performance and then updated the scaling_max_freq.


And voila the Temple Run was running awesome on the phone. And don't put it in that state for too long, it drains battery fast. And enjoy the new awesomeness of Xperia X10. We can create custom governors like smartass minmax .,etc. And run the phone more efficiently. We can also port the  2.6.32 kernel of newest xperia phones to Xperia X10. But that is for another day. Enjoy with this for now. Or there are a lot of custom kernels available online download them. Try creating more entries to the table and run the cpu on different frequencies and feel the awesomeness of your X10. Incase you don't own a X10 the case must be similar with whatever phone you own. But make sure it is overclockable, cause some phones already run at the highest freq supported by the board. And any tweak to the kernel will not work. That will not spoil the phone though, but try it at your own risk.