Analysis of Aboot startup process

Location:
bootloader/lk/app/aboot/aboot.c
At the end of the file is the following code:

APP_START(aboot)
	.init = aboot_init,
APP_END

Take a look at the definition of macro app "start"

#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,
#define APP_END };

Expand the above result to:

struct app_descriptor _app_aboot = {
.name = aboot,
.init = aboot_init,
}

So where is about init called?
bootable/bootloader/lk/kernel/main.c

static int bootstrap2(void *arg){
···
apps_init();
···
}

Here we mainly look at the order of calls. For the detailed procedure, see the code: bootable/bootloader/lk/app/app.c

void apps_init(void)
{
	/* call all the init routines */
	for (app = &__apps_start; app != &__apps_end; app++) {
		if (app->init)
			app->init(app);//Run the about? Init function here.
	}
}

A brief introduction to the function about init

void aboot_init(const struct app_descriptor *app)
{
	/* Setup page size information for nv storage */
	//Read the register and check whether the device is started from emmc
	if (target_is_emmc_boot())
	{
		page_size = mmc_page_size();
		page_mask = page_size - 1;
		dprintf(CRITICAL,"liyang emmc boot\n");
	}
	//Read the properties of the device from the devinfo/aboot partition
	read_device_info(&device);
	read_allow_oem_unlock(&device);

	/* Display splash screen if enabled */
#if DISPLAY_SPLASH_SCREEN
#if NO_ALARM_DISPLAY
	if (!check_alarm_boot()) {
#endif
		//Initialize the display module, where the data in the splash partition is read and displayed.
		//This place hasn't been opened yet, so it hasn't been shown
		dprintf(CRITICAL, "Display Init: liyang Start %s\n", device.display_panel);
		target_display_init(device.display_panel);
		dprintf(CRITICAL, "Display Init: liyang Done\n");
#if NO_ALARM_DISPLAY
	}
#endif
#endif
	//Read the serial number of the device
	target_serialno((unsigned char *) sn_buf);
	//Open the device display here, and you can see the boot logo read from splash above
	qpnp_wled_set_level(gwled, QPNP_WLED_MAX_BR_LEVEL);
	memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);

	/*
	 * Check power off reason if user force reset,
	 * if yes phone will do normal boot.
	 */
	if (is_user_force_reset())
		goto normal_boot;
	//The next step is to test the buttons, and enter the upgrade or ELoad mode (tile changing) according to different combinations
	/* Check if we should do something other than booting up */
	if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_BACK))
	{
    //Add by Skysoft start 
    }else if (keys_get_state(KEY_VOLUMEDOWN) && keys_get_state(KEY_BACK))
    {
    //Add by Skysoft end
	}else{
	}
normal_boot:
	if (!boot_into_fastboot)//Enter the normal startup process
	{
		if (target_is_emmc_boot())
		{
			if(emmc_recovery_init())
				dprintf(CRITICAL," liyang error in emmc_recovery_init\n");
			if(target_use_signed_kernel())
			{
				if((device.is_unlocked) || (device.is_tampered))
				{
				#ifdef TZ_TAMPER_FUSE
					set_tamper_fuse_cmd();
				#endif
				#if USE_PCOM_SECBOOT
					set_tamper_flag(device.is_tampered);
				#endif
				}
			}
			boot_linux_from_mmc();
			dprintf(CRITICAL, "liyang after boot_linux_from_mmc\n");
		}
		else//If the upgrade process fails, it will enter this branch.
		{
			dprintf(CRITICAL, "liyang recovery_init\n");
			recovery_init();//Get the upgrade status to decide whether to enter recovery/boot
	#if USE_PCOM_SECBOOT
		if((device.is_unlocked) || (device.is_tampered))
			set_tamper_flag(device.is_tampered);
	#endif
			boot_linux_from_flash();//Enter recovery/boot according to recovery init
		}
	}else//Enter fastboot mode
	/* We are here means regular boot did not happen. Start fastboot. */
	/* register aboot specific fastboot commands */
	aboot_fastboot_register_commands();//Register the command in fastboot. You can also add the fastboot command from here. That is, the command is stored in a linked list of type struct fastboot? Var.
	/* dump partition table for debug info */
	partition_dump();//Read out the partition information of the device

	/* initialize and start fastboot */
	fastboot_init(target_get_scratch_address(), target_get_max_flash_size());//Initialize fastboot. Including the initialization of usb.
#if FBCON_DISPLAY_MSG
	display_fastboot_menu();//Show fastboot menu
#endif
}

Let's take a look at the FastBoot init function, which is mainly to register some events, initialize USB, and open a Thread to detect these events.

int fastboot_init(void *base, unsigned size){
	thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
}

static int fastboot_handler(void *arg)
{
	for (;;) {
		event_wait(&usb_online);
		fastboot_command_loop();
	}
	return 0;
}

static void fastboot_command_loop(void)
{
	//Apply for a cache
	uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));

again:
	while (fastboot_state != STATE_ERROR) {//Start to read the data in USB, and call the previously registered processing function.

		r = usb_if.usb_read(buffer, MAX_RSP_SIZE);

		fastboot_state = STATE_COMMAND;

		for (cmd = cmdlist; cmd; cmd = cmd->next) {
			if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
				continue;
			cmd->handle((const char*) buffer + cmd->prefix_len,
				    (void*) download_base, download_size);//cmd has been registered in the linked list in the previous introduction. The registered function is called here.
			if (fastboot_state == STATE_COMMAND)
				fastboot_fail("unknown reason");
			goto again;
		}

		fastboot_fail("unknown command");

	}
	fastboot_state = STATE_OFFLINE;
	dprintf(INFO,"fastboot: oops!\n");
	free(buffer);
}

This is the boot process.

Posted by amrigo on Mon, 23 Dec 2019 08:51:10 -0800