fastboot啓動初始化流程--基於MT6765

概述

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 ([email protected]), 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 ([email protected]), 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 ([email protected]), 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 ([email protected]), 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)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MaMx9fkz-1592622951755)(E8AD552599B642BD841CD41F0A3D4753)]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章