更改第三方手机检测到的CPU厂商型号,在kernel\arch\arm\mach-msm下面对应的Board-*.c文件里更改,比如我们是8226的CPU,就要在Board-8226.c里将DT_MACHINE_START(MSM8226_DT, "Qualcomm MSM 8226 (Flattened Device Tree)")  这里的8226改成客户指定的型号,比如要改成8926,就要这么改:
DT_MACHINE_START(MSM8226_DT, "Qualcomm MSM 8926 (Flattened Device Tree)"),这里修改的值,实际上是 proc/cpuinfo这个文件里的值. 网上有的人说是要改ro.boot.hardware这个属性值,改这个值,确实是改变了CPU的厂商信息,具体到代码,也就是改了CPU的hardware信息,但是这样改的话,是会导致手机找不到对应的init.hardware.rc文件,比如我们8226的芯片,如果你把hardware改成了8926,那么开机时会找不到init.8926.rc这个文件,而导致开不了机。第三方检测工具,比如安兔兔,都是直接读的cpuinfo这个文件的内容, 具体的和CPU厂商名,即cpu的hardware相关的开机流程梳理下,就会明白了。
我们手机开机时,加载完linux内核后,会马上调用用户空间的第一个程序:init.在init程序的主函数main里,我们只需要关注下面三个函数:
    property_init();
    get_hardware_name(hardware, &revision);
    process_kernel_cmdline();
 其中property_init主要是为属性分配一些存储空间,该函数并不是核心。不过当我们查看init.rc文件时会发现该文件开始部分用一些import语句导入了其他的配置文件,例如,/init.usb.rc。大多数配置文件都直接使用了确定的文件名,只有如下的代码使用了一个变量(${ro.hardware})执行了配置文件名的一部分。那么这个变量值是从哪获得的呢?


import /init.${ro.hardware}.rc


     首先要了解init.${ro.hardware}.rc配置文件的内容通常与当前的硬件有关。    现在我们先来关注get_hardware_name函数,代码如下:

[cpp] view plaincopy  

 void get_hardware_name(char *hardware, unsigned int *revision)   

 {   

     char data[1024];   

     int fd, n;   

     char *x, *hw, *rev;   

    

     /* 如果hardware已经有值了,说明hardware通过内核命令行提供,直接返回 */   

     if (hardware[0])   

         return;   

     //  打开/proc/cpuinfo文件   

     fd = open("/proc/cpuinfo", O_RDONLY);   

     if (fd < 0) return;   

     //  读取/proc/cpuinfo文件的内容   

     n = read(fd, data, 1023);   

     close(fd);   

     if (n < 0) return;   

    

     data[n] = 0;   

     //  从/proc/cpuinfo文件中获取Hardware字段的值   

     hw = strstr(data, "\nHardware");   

     rev = strstr(data, "\nRevision");   

     //  成功获取Hardware字段的值   

     if (hw) {   

         x = strstr(hw, ": ");   

         if (x) {   

             x += 2;   

             n = 0;   

             while (*x && *x != '\n') {   

                 if (!isspace(*x))   

                     //  将Hardware字段的值都转换为小写,并更新hardware参数的值   

                     //  hardware也就是在init.c文件中定义的hardware数组   

                     hardware[n++] = tolower(*x);   

                 x++;   

                 if (n == 31) break;   

             }   

             hardware[n] = 0;   

         }   

     }   

    

     if (rev) {   

         x = strstr(rev, ": ");   

         if (x) {   

             *revision = strtoul(x + 2, 0, 16);   

         }   

     }   

 }




      从get_hardware_name方法的代码可以得知,该方法主要用于确定hardware和revision的变量的值。Revision这里先不讨论,只要研究hardware。获取hardware的来源是从Linux内核命令行或/proc/cpuinfo文件中的内容。Linux内核命令行暂且先不讨论(因为很少传递该值),先看看/proc/cpuinfo,该文件是虚拟文件(内存文件),执行cat /proc/cpuinfo命令会看到该文件中的内容。我们现在8226的手机,输入这命令后显示的信息为:Hardware : Qualcomm MSM 8926 (Flattened Device Tree), 如果程序就到此为止的话,那么与硬件相关的配置文件名就是:init.QualcommMSM8926(FlattenedDeviceT.rc,于与中间为什么是“QualcommMSM8926(FlattenedDeviceT”,大伙可以自己看下get_hardware_name这个函数是怎么定义的就知道了。 
      现在我们的这套高通的代码,在执行完get_hardware_name函数后面又调用了process_kernel_cmdline函数,代码如下:


[cpp] view plaincopy  

 static void process_kernel_cmdline(void)   

 {   

     /* don't expose the raw commandline to nonpriv processes */   

     chmod("/proc/cmdline", 0440);   

    

     //  导入内核命令行参数   

     import_kernel_cmdline(0, import_kernel_nv);   

     if (qemu[0])   

         import_kernel_cmdline(1, import_kernel_nv);   

    

     //  用属性值设置内核变量   

     export_kernel_boot_props();   

 }


 在process_kernel_cmdline函数中除了使用import_kernel_cmdline函数导入内核变量外,主要的功能就是调用export_kernel_boot_props函数通过属性设置内核变量,例如,通过ro.boot.hardware属性设置hardware变量,也就是说可以通过ro.boot.hardware属性值可以修改get_hardware_name函数中从/proc/cpuinfo文件中得到的hardware字段值。下面看一下export_kernel_boot_props函数的代码。

[cpp] view plaincopy  

 static void export_kernel_boot_props(void)   

 {   

     char tmp[PROP_VALUE_MAX];   

     const char *pval;   

     unsigned i;   

     struct {   

         const char *src_prop;   

         const char *dest_prop;   

         const char *def_val;   

     } prop_map[] = {   

         { "ro.boot.serialno", "ro.serialno", "", },   

         { "ro.boot.mode", "ro.bootmode", "unknown", },   

         { "ro.boot.baseband", "ro.baseband", "unknown", },   

         { "ro.boot.bootloader", "ro.bootloader", "unknown", },   

     };   

     //  通过内核的属性设置应用层配置文件的属性   

     for (i = 0; i < ARRAY_SIZE(prop_map); i++) {   

         pval = property_get(prop_map[i].src_prop);   

         property_set(prop_map[i].dest_prop, pval ?: prop_map[i].def_val);   

     }   

     //  根据ro.boot.console属性的值设置console变量   

     pval = property_get("ro.boot.console");   

     if (pval)   

         strlcpy(console, pval, sizeof(console));   

    

     /* save a copy for init's usage during boot */   

     strlcpy(bootmode, property_get("ro.bootmode"), sizeof(bootmode));   

    

     /* if this was given on kernel command line, override what we read  

      * before (e.g. from /proc/cpuinfo), if anything */   

     //  获取ro.boot.hardware属性的值   

     pval = property_get("ro.boot.hardware");   

     if (pval)   

         // 这里通过ro.boot.hardware属性再次改变hardware变量的值   

         strlcpy(hardware, pval, sizeof(hardware));   

     //  利用hardware变量的值设置设置ro.hardware属性   

     //  这个属性就是前面提到的设置初始化文件名的属性,实际上是通过hardware变量设置的   

     property_set("ro.hardware", hardware);   

    

     snprintf(tmp, PROP_VALUE_MAX, "%d", revision);   

     property_set("ro.revision", tmp);   

    

     /* TODO: these are obsolete. We should delete them */   

     if (!strcmp(bootmode,"factory"))   

         property_set("ro.factorytest", "1");   

     else if (!strcmp(bootmode,"factory2"))   

         property_set("ro.factorytest", "2");   

     else   

         property_set("ro.factorytest", "0");   

 }



      从export_kernel_boot_props函数的代码可以看出,该函数实际上就是来回设置一些属性值,并且利用某些属性值修改console、hardware等变量。其中hardware变量(就是一个长度为32的字符数组)在get_hardware_name函数中已经从/proc/cpuinfo文件中获得过一次值了,在export_kernel_boot_props函数中又通过ro.boot.hardware属性设置了一次值,最后用hardware变量设置ro.hardware属性,我们8226的代码里的这个值性值ro.boot.hardware为:qcom,所以最后的初始化文件名为init.qcom.rc。到此就分析完了。至于如何查看ro.boot.hardware的值,可以用adb命令,进入到/dev/socket目录后,输入getprop命令,即可以查看所有的属性值