[DESCRIPTION]
在加载lcm driver的时候,根据预先写在nvram里面的特定标示,来选择性的加载对应的lcm driver,实现lcm兼容。
[KEYWORD]
nvram、pro_info、preloader、lk、boot argument。
[THEORY]
原理说明:
1、nvram的pro_info分区里面,可以开辟一段特定的结构块,通过meta工具进行写入数据,然后在preloader里面去读取这个数据,传递给lk。lk解析参数,在加载lcm driver的时候根据参数来选择驱动。Kernel阶段接受lk传递的lcm name进行加载驱动。
2、在lk和kernel阶段,加载lcm driver的流程基本不变。在disp_drv_get_lcm_driver()函数里面,不在根据compare_id的结果来加载驱动,而是直接匹配lcm name加载驱动。
3、为什么要preloader读取nvram,传递参数这么复杂,何不在lk里面读取nvram然后根据读取结果加载驱动?
----这是因为lk阶段最开始就要加载lcm driver,这时候nvram还没有初始化,无法读取,而且不适合修改lk的流程。
[SOLUTION]
一、如何添加lcm name成员到pro_info?
1. 确认打开 MTK_PRODUCT_INFO_SUPPORT
修改alps/mediatek/config/$project/ProjectConfig.mk: MTK_PRODUCT_INFO_SUPPORT=yes
MTK_PRODUCT_INFO_SUPPORT也必须存在于 AUTO_ADD_GLOBAL_DEFINE_BY_NAME中
2. 在alps\mediatek\custom\[$project]\cgen\cfgfileinc\CFG_PRODUCT_INFO_File.h中,
将新定义的数据加入到 PRODUCT_INFO 中:
typedef struct
{
unsigned char barcode[64];
nvram_ef_imei_imeisv_struct IMEI[4]; //pro_info一般会存放board code和EMEI
unsigned char lcm_name[16]; //用来做唯一标示的成员按照需要自己定义
unsigned char reseerved[1024-64-40-16]; //pro_info结构体长度固定
} PRODUCT_INFO;
二、如何向pro_info里面写入lcm name?
1、通过USB线,用meta工具连接手机,选择AP NVRAM Editor,在弹出来的窗口点击“read from NVRAM”,然后会有小窗口,请选择:
注释:如果之前没有编译bin档,那么先选择Cgen.exe,生成一个DxDesigner文件。
2、找到pro_info分区和里面的lcm name,写入数据,然后点击“save to NVRAM”。整个写的过程如下:
三、preloader里面如何读取pro_info,如何传递参数?
1、在alps\mediatek\platform\[$mt65xx]\preloader\src\core\main.c文件中,
在main()函数里面的bldr_pre_process()后,bldr_post_process()前,添加读取pro_info里面的lcm name的操作,参考代码如下:
char lcm_name[16];
void bldr_read_proinfo()
{
char *name = PART_PRO_INFO;
part_t *part = part_get(name);
if (NULL == part) {
print("%s %s partition not found\n", MOD, name);
return -1;
}
int ret = 0;
u32 offset = 0;
blkdev_t *bdev;
bdev = bootdev;
/* specify the read offset */
u64 src = part->startblk * bdev->blksz + offset;
u32 ms;
u8 buf[200];
u8 i =0;
blkdev_read(bdev, src, sizeof(buf), buf);
/*i=0;
while( i < sizeof(buf))
{
print("[zxd]%x %x %x %x %x %x %x %x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
i += 8;
}*/
//memcpy(lcm_name, &buf[104], 32);
for(i=0;i<LCM_FLAG_BITS;i++)
{
*(lcm_name+i) = buf[104+i];
}
//*(lcm_name+i) = '\0';
}
2、在mediatek/platform/[$mt65xx]/preloader/src/drivers/inc/platform.h中的boot_arg_t,添加一个参数,用来存放lcm name。参考代码如下:
typedef struct {
u32 magic;
boot_mode_t mode;
u32 e_flag;
u32 log_port;
u32 log_baudrate;
u8 log_enable;
u8 reserved[3];
u32 dram_rank_num;
u32 dram_rank_size[4];
u32 boot_reason;
u32 meta_com_type;
u32 meta_com_id;
u32 boot_time;
da_info_t da_info;
SEC_LIMIT sec_limit;
#if(1)
u8 flag[LCM_FLAG_BITS];//存放preloader传递的lcm name信息
#endif
} boot_arg_t;
3、在alps\mediatek\platform\[$mt65xx]\preloader\src\drivers\platform.c的platform_post_init()函数里面,对传递的参数bootarg进行赋值.参考代码如下:
void platform_post_init(void)
{
······
#if(1)
int i=0;
while(i<LCM_FLAG_BITS)
{
*(bootarg->flag+i)= *(lcm_name+i);
i++;
}
#endif
······
}
四、lk阶段如何解析参数?
1、在alps\bootable\bootloader\lk\kernel\main.c中,对preloader传递过来的参数进行解析,获取lcm id。
在kmain()函数的最开始,添加如下参考代码:
u8 lcm_name2[LCM_FLAG_BITS+1];
void kmain(void)
{
#if(1)
g_boot_arg = &boot_addr;
memcpy(g_boot_arg, BOOT_ARGUMENT_LOCATION, sizeof(BOOT_ARGUMENT));
//strncpy(lcm_name2,g_boot_arg->flag,LCM_FLAG_BITS);
int i=0;
while(i<LCM_FLAG_BITS)
{
*(lcm_name2+i) = *((g_boot_arg->flag) + i);
i++;
}
*(lcm_name2+i) = '\0';
#endif
·····
}
2、在alps\mediatek\platform\[$mt65xx]\lk\disp_drv.c文件中的disp_drv_get_lcm_driver()函数中,根据参数lcm_name2来加载驱动。