概述
lk最主要的工作就是加载kernel和ramdisk,然后跳转到kernel中去执行。
同时有几个比较重要工作也是在lk中执行:
- a.初始化LCD,加载并显示开机logo。
- b.对启动模式判断,meta模式,recovery模式,power off charging模式,fastboot模式等等。
- c.fastboot也是在lk中实现的,主要作用就是下载我们手机镜像。
检测启动模式软件流程
platform/mt6765/platform.c
:- static int bootstrap2(void *arg)
- void platform_init(void)
- if (g_boot_mode == FASTBOOT) video_printf(" => FASTBOOT mode…\n");打印fastboot字符
- boot_mode_select(); 按键检测,模式选择
- apps_init(); fastboot模式启动初始化,后续会讲
- 按键选择代码如下:
platform/mt6765/boot_mode.c:
6 // global variable for specifying boot mode (default = NORMAL)
47 BOOTMODE g_boot_mode = NORMAL_BOOT;
boot_mode_select();
120 #if defined(HAVE_LK_TEXT_MENU) || defined(MTK_FASTBOOT_SUPPORT)
121 /*Check RTC to know if system want to reboot to Fastboot*/
122 if (Check_RTC_PDN1_bit13()) {
123 g_boot_mode = FASTBOOT;
124 Set_Clr_RTC_PDN1_bit13(false);
125 }
126
127 /*Check RGU to know if system want to reboot to Fastboot*/
128 #ifdef MTK_ENTER_FASTBOOT_VIA_RGU
129 if (mtk_wdt_fastboot_check()) {
130 g_boot_mode = FASTBOOT;
131 mtk_wdt_fastboot_set(0); // clear RGU fastboot mode bit
132 }
133 #endif
134
135 if (g_boot_mode == FASTBOOT) {
136 dprintf(CRITICAL, "[FASTBOOT] reboot to boot loader\n");
137 return;
138 }
139 #endif
141 #if defined (HAVE_LK_TEXT_MENU) //wugn lk的选择目录
142 /*If forbidden mode is factory, cacel the factory key detection*/
143 if (g_boot_arg->sec_limit.magic_num == 0x4C4C4C4C) {
144 if (g_boot_arg->sec_limit.forbid_mode == F_FACTORY_MODE) {
145 //Forbid to enter factory mode
146 dprintf(CRITICAL, "%s Forbidden\n",MODULE_NAME);
147 factory_forbidden=1;
148 }
149 }
150 // forbid_mode = g_boot_arg->boot_mode &= 0x000000FF;
151 /*If boot reason is power key + volumn down, then
152 disable factory mode dectection*/
153 if (mtk_detect_pmic_just_rst()) {
154 factory_forbidden=1;
155 }
156 /*Check RTC to know if system want to reboot to Recovery*/
157 if (Check_RTC_Recovery_Mode()) {
158 g_boot_mode = RECOVERY_BOOT;
159 return;
160 }
161 /*If MISC Write has not completed in recovery mode
162 before system reboot, go to recovery mode to
163 finish remain tasks*/
164 if (unshield_recovery_detection()) {
165 return;
166 }
167 ulong begin = get_timer(0);
168
169 /*we put key dectection here to detect key which is pressed*/
170 dprintf(INFO, "eng build\n");
171 while (get_timer(begin)<50) {
172
173
174 if (!factory_forbidden) {
175 if (mtk_detect_key(MT65XX_FACTORY_KEY)) {
176 dprintf(CRITICAL, "%s Detect key\n",MODULE_NAME);
177 dprintf(CRITICAL, "%s Enable factory mode\n",MODULE_NAME);
178 g_boot_mode = FACTORY_BOOT;
179 //video_printf("%s : detect factory mode !\n",MODULE_NAME);
180 return;
181 }
182 }
183
184 if (mtk_detect_key(MT65XX_BOOT_MENU_KEY)) {
185 dprintf(CRITICAL, "\n%s Check boot menu\n",MODULE_NAME);
186 dprintf(CRITICAL, "%s Wait 50ms for special keys\n",MODULE_NAME);
187 mtk_wdt_disable();
188 /*************************/
189 mt65xx_backlight_on();
190 /*************************/
191 boot_mode_menu_select();
192 mtk_wdt_init();
193 return;
194 }
195 #ifdef MT65XX_RECOVERY_KEY
196 if (mtk_detect_key(MT65XX_RECOVERY_KEY)) {
197 dprintf(CRITICAL, "%s Detect cal key\n",MODULE_NAME);
198 dprintf(CRITICAL, "%s Enable recovery mode\n",MODULE_NAME);
199 g_boot_mode = RECOVERY_BOOT;
200 //video_printf("%s : detect recovery mode !\n",MODULE_NAME);
201 return;
202 }
203 #endif
204 }
205 #else
...略...
由以上可知,通过不同按键选择设置对应全局变量g_boot_mode进入不同模式,进入fastboot一般有两种方式。
- 一是通过开机并按键进入。
- 二是通过adb reboot bootloader命令进入。
1.通过adb命令进入,运行adb reboot bootloader系统会重启,下次开机会自动进入fastboot模式。其原理是执行adb reboot bootloader后,系统是会写一个fastboot标志位到RTC寄存器,下次开机运行到lk中,会在boot_mode_select函数中调用Check_RTC_PDN1_bit13()来检测是否进入fastboot模式。
2.按键进入就是开机过程中通过按某个键来进入fastboot模式,这个按键是需要在lk配置的,目前MT6765项目是没有配置的。
- 需要把之前boot menu相关的删除,power和音量+键进入fastboot,具体配置方法如下:
while (get_timer(begin)<50) {
if (!factory_forbidden) {
if (mtk_detect_key(MT65XX_FACTORY_KEY)) {
dprintf(CRITICAL, "%s Detect key\n",MODULE_NAME);
dprintf(CRITICAL, "%s Enable factory mode\n",MODULE_NAME);
g_boot_mode = FACTORY_BOOT;
//video_printf("%s : detect factory mode !\n",MODULE_NAME);
return;
}
}
//[BUGFIX]-Mod-BEGIN by (wugangnan@paxsz.com), 2020/06/19, for fastboot bootup by volumeup
/*
if (mtk_detect_key(MT65XX_BOOT_MENU_KEY)) {
dprintf(CRITICAL, "\n%s Check boot menu\n",MODULE_NAME);
dprintf(CRITICAL, "%s Wait 50ms for special keys\n",MODULE_NAME);
mtk_wdt_disable();
mt65xx_backlight_on();
boot_mode_menu_select();
mtk_wdt_init();
return;
}
#ifdef MT65XX_RECOVERY_KEY
if (mtk_detect_key(MT65XX_RECOVERY_KEY)) {
dprintf(CRITICAL, "%s Detect cal key\n",MODULE_NAME);
dprintf(CRITICAL, "%s Enable recovery mode\n",MODULE_NAME);
g_boot_mode = RECOVERY_BOOT;
//video_printf("%s : detect recovery mode !\n",MODULE_NAME);
return;
}
#endif
*/
#ifdef MT65XX_FASTBOOT_KEY
if (mtk_detect_key(MT65XX_RECOVERY_KEY)) {
dprintf(CRITICAL, "%s Detect cal key\n",MODULE_NAME);
dprintf(CRITICAL, "%s Enable FASTBOOT mode\n",MODULE_NAME);
g_boot_mode = FASTBOOT;
//video_printf("%s : detect FASTBOOT mode !\n",MODULE_NAME);
return;
}
#endif
//[BUGFIX]-Mod-END by (wugangnan@paxsz.com), 2020/06/19, for fastboot bootup by volumeup
}
- META模式进入是通过获取环境变量REBOOT_META_FLAG来进入,主要由工具设定,代码如下
platform/mt6765/boot_mode.c
:
if (meta_detection()) {
return;
}
meta_value = get_env(REBOOT_META_FLAG);
if (meta_value != NULL) {
if (strncmp(meta_value, REBOOT_META_FLAG_VALUE, strlen(REBOOT_META_FLAG_VALUE)+1) == 0) {
g_boot_mode = META_BOOT;
if (set_env(REBOOT_META_FLAG, "0") != 0)
dprintf(INFO, "REBOOT_META_FLAG set failed!\n");
return;
}
}
第一行是通过检测g_boot_arg->boot_mode来判断:
extern BOOT_ARGUMENT *g_boot_arg;
static int meta_detection(void)
{
int boot_mode;
#ifdef DEFAULT_META
boot_mode = 1;
return boot_mode;
#endif
boot_mode = 0;
if (g_boot_arg->boot_mode != NORMAL_BOOT)
boot_mode = 1;
dprintf(CRITICAL, "Meta mode: %d, boot_mode: %d\n", boot_mode, g_boot_arg->boot_mode);
return boot_mode;
}
/* boot type definitions */
typedef enum {
NORMAL_BOOT = 0,
META_BOOT = 1,
RECOVERY_BOOT = 2,
SW_REBOOT = 3,
FACTORY_BOOT = 4,
ADVMETA_BOOT = 5,
ATE_FACTORY_BOOT = 6,
ALARM_BOOT = 7,
KERNEL_POWER_OFF_CHARGING_BOOT = 8,
LOW_POWER_OFF_CHARGING_BOOT = 9,
FASTBOOT = 99,
DOWNLOAD_BOOT = 100,
UNKNOWN_BOOT
} BOOTMODE;
这个应该是工具给设定的,log打印:
(200609_09:47:00.903)BOOT_MODE: 0
fastboot模式初始化过程
- bootstrap2(void *arg)
- apps_init();
- app->init(app);
- mt_boot_init(const struct app_descriptor *app) app/mt_boot/mt_boot.c
- if (g_boot_mode == FASTBOOT)
- goto fastboot;
- fastboot_init(target_get_scratch_address(), sz);app/mt_boot/fastboot.c
fastboot_init(target_get_scratch_address(), sz)
*790 fastboot_register("getvar:", cmd_getvar, TRUE, FALSE);
791 fastboot_publish("version", "0.5");
792 fastboot_publish("version-preloader", g_boot_arg->pl_version);
793 fastboot_publish("version-bootloader", LK_VER_TAG);
794 update_radio_version();
795 fastboot_publish("version-baseband", (const char *)radio_version);
796 publish_ab_variables();
797 fastboot_publish("is-userspace", "no");
798 fastboot_register("signature", cmd_install_sig, FALSE, TRUE);
799
800 #if (defined(MTK_EMMC_SUPPORT) || defined(MTK_UFS_SUPPORT)) && defined(MTK_SPI_NOR_SUPPORT)
801 dprintf(ALWAYS,"Init EMMC device in fastboot mode\n");
802 mmc_legacy_init(1);
803 #endif
804 fastboot_register("flash:", cmd_flash_mmc, TRUE, TRUE);
805 fastboot_register("erase:", cmd_erase_mmc, TRUE, TRUE);
806
807 fastboot_register("oem printk-ratelimit", cmd_printk_ratelimit, TRUE, FALSE);
808 fastboot_register("continue", cmd_continue, FALSE, FALSE);
809 fastboot_register("reboot", cmd_reboot, TRUE, FALSE);
810 fastboot_register("reboot-bootloader", cmd_reboot_bootloader, TRUE, FALSE);
811 fastboot_register("reboot-recovery",cmd_reboot_recovery, TRUE, FALSE);
812 fastboot_register("reboot-fastboot",cmd_reboot_fastboot, TRUE, FALSE);
thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
- thread的callback函数是
fastboot_handler
:
static int fastboot_handler(void *arg)
{
for (;;) {
event_wait(&usb_online);
fastboot_command_loop();
}
return 0;
}
- 这个函数是循环,如果usb接收到命令,就调用fastboot_command_loop来解析命令并调用命令的执行函数
static void fastboot_command_loop(void)
{
struct fastboot_cmd *cmd;
int r;
dprintf(INFO,"fastboot: processing commands\n");
again:
while (fastboot_state != STATE_ERROR) {
memset(buffer, 0, sizeof(buffer));
r = usb_read(buffer, MAX_RSP_SIZE);
if (r < 0) break; //no input command
buffer[r] = 0;
dprintf(ALWAYS,"[fastboot: command buf]-[%s]-[len=%d]\n", buffer, r);
dprintf(ALWAYS,"[fastboot]-[download_base:0x%x]-[download_size:0x%x]\n",(unsigned int)download_base,(unsigned int)download_size);
/*Pick up matched command and handle it*/
for (cmd = cmdlist; cmd; cmd = cmd->next) {
fastboot_state = STATE_COMMAND;
if (memcmp(buffer, cmd->prefix, cmd->prefix_len)) {
continue;
}
dprintf(ALWAYS,"[Cmd process]-[buf:%s]-[lenBuf:%s]\n", buffer, buffer + cmd->prefix_len);
//[FEATURE]-Add-BEGIN by (wugangnan@paxsz.com), 2020/6/19,for PayDroid Tool
#ifdef MTK_SEC_FASTBOOT_UNLOCK_SUPPORT
if ((strcmp(buffer + cmd->prefix_len, "boot") == 0) && (0 == get_unlocked_status()))
{
r = fastboot_oem_unlock_chk();
if (r != 0) break;
dprintf(ALWAYS, "fastboot_oem_unlock_chk\n");
}
#endif
//[FEATURE]-Add-END by (wugangnan@paxsz.com), 2020/6/19,for PayDroid Tool
#ifdef MTK_SECURITY_SW_SUPPORT
extern unsigned int seclib_sec_boot_enabled(unsigned int);
//if security boot enable, check cmd allowed
if ( !(sec_usbdl_enabled() || seclib_sec_boot_enabled(1)) || cmd->allowed_when_security_on )
if ((!cmd->forbidden_when_lock_on) || (0 != get_unlocked_status()))
#endif
{
cmd->handle((const char*) buffer + cmd->prefix_len, (void*) download_base, download_size);
}
}
fastboot_state = STATE_OFFLINE;
dprintf(INFO,"fastboot: oops!\n");
}
所有的命令都在cmdlist 这个列表中,调用memcmp来比较pc发的命令和fastboot的命令是否相等,如果相等就调用handle处理,
也就是我们fastboot_register时候的第二个参数
- 在fastboot中我们一般通过fastboot_register来注册命令,下面就是下载和擦除命令:
fastboot_register("flash:", cmd_flash_mmc, TRUE, TRUE);
fastboot_register("erase:", cmd_erase_mmc, TRUE, TRUE);
以擦除命令为例,emmc烧写调用流程如下:
- void cmd_flash_mmc(const char *arg, void *data, unsigned sz) app/mt_boot/dl_command.cs
- flash_storage(arg, data, sz);
- cmd_flash_mmc_standard(arg, data, sz);
- cmd_flash_mmc_img(arg, data, sz);
- cmd_flash_mmc_sparse_img(const char* arg, void* data, unsigned sz)
- emmc_write(ptn , (unsigned int *)data, sz)