android4.4 恢复出厂设置,Android4.4.2恢复出厂设置(四)

u-Boot启动部分

U-Boot启动到Linux的流程图如下所示:

5d4e5316b9d7?tdsourcetag=s_pctim_aiomsg

U-Boot启动Linux流程

board_init_r

U-Boot首先从u-bootarch/arm/lib/crt0.S调用u-boot/arch/arm/lib/board.c中的board_init_r开始启动,函数board_init_r的实现如下所示:

void board_init_r(gd_t *id, ulong dest_addr)

{

ulong malloc_start;

#if !defined(CONFIG_SYS_NO_FLASH)

ulong flash_size;

#endif

gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */

bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");

monitor_flash_len = (ulong)&__rel_dyn_end - (ulong)_start;

/* Enable caches */

enable_caches();

debug("monitor flash len: %08lX\n", monitor_flash_len);

board_init(); /* Setup chipselects */

/*

* TODO: printing of the clock inforamtion of the board is now

* implemented as part of bdinfo command. Currently only support for

* davinci SOC's is added. Remove this check once all the board

* implement this.

*/

#ifdef CONFIG_CLOCKS

set_cpu_clk_info(); /* Setup clock information */

#endif

serial_initialize();

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);

#else

debug("Now running in RAM - U-Boot at: %08lx\n", CONFIG_SYS_SDRAM_BASE);

#endif

#ifdef CONFIG_LOGBUFFER

logbuff_init_ptrs();

#endif

#ifdef CONFIG_POST

post_output_backlog();

#endif

/* The Malloc area is immediately below the monitor copy in DRAM */

malloc_start = dest_addr - TOTAL_MALLOC_LEN;

mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);

#ifdef CONFIG_ARCH_EARLY_INIT_R

arch_early_init_r();

#endif

power_init_board();

#if !defined(CONFIG_SYS_NO_FLASH)

puts("Flash: ");

flash_size = flash_init();

if (flash_size > 0) {

# ifdef CONFIG_SYS_FLASH_CHECKSUM

print_size(flash_size, "");

/*

* Compute and print flash CRC if flashchecksum is set to 'y'

*

* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX

*/

if (getenv_yesno("flashchecksum") == 1) {

printf(" CRC: %08X", crc32(0,

(const unsigned char *) CONFIG_SYS_FLASH_BASE,

flash_size));

}

putc('\n');

# else /* !CONFIG_SYS_FLASH_CHECKSUM */

print_size(flash_size, "\n");

# endif /* CONFIG_SYS_FLASH_CHECKSUM */

} else {

puts(failed);

hang();

}

#endif

#if defined(CONFIG_CMD_NAND)

puts("NAND: ");

nand_init(); /* go init the NAND */

#endif

#if defined(CONFIG_CMD_ONENAND)

onenand_init();

#endif

#ifdef CONFIG_GENERIC_MMC

puts("MMC: ");

mmc_initialize(gd->bd);

#endif

#ifdef CONFIG_ROCKCHIP

board_storage_init();

#endif

#ifdef CONFIG_CMD_SCSI

puts("SCSI: ");

scsi_init();

#endif

#ifdef CONFIG_HAS_DATAFLASH

AT91F_DataflashInit();

dataflash_print_info();

#endif

/* initialize environment */

if (should_load_env())

env_relocate();

else

set_default_env(NULL);

#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)

arm_pci_init();

#endif

stdio_init(); /* get the devices list going. */

jumptable_init();

#if defined(CONFIG_API)

/* Initialize API */

api_init();

#endif

console_init_r(); /* fully init console as a device */

#ifdef CONFIG_DISPLAY_BOARDINFO_LATE

# ifdef CONFIG_OF_CONTROL

/* Put this here so it appears on the LCD, now it is ready */

display_fdt_model(gd->fdt_blob);

# else

checkboard();

# endif

#endif

#if defined(CONFIG_ARCH_MISC_INIT)

/* miscellaneous arch dependent initialisations */

arch_misc_init();

#endif

#if defined(CONFIG_MISC_INIT_R)

/* miscellaneous platform dependent initialisations */

misc_init_r();

#endif

#ifndef CONFIG_ROCKCHIP

/* set up exceptions */

interrupt_init();

/* enable exceptions */

enable_interrupts();

#endif

/* Initialize from environment */

load_addr = getenv_ulong("loadaddr", 16, load_addr);

#ifdef CONFIG_BOARD_LATE_INIT

board_late_init();

#endif

#ifdef CONFIG_BITBANGMII

bb_miiphy_init();

#endif

#if defined(CONFIG_CMD_NET)

puts("Net: ");

eth_initialize(gd->bd);

#if defined(CONFIG_RESET_PHY_R)

debug("Reset Ethernet PHY\n");

reset_phy();

#endif

#endif

#ifdef CONFIG_POST

post_run(NULL, POST_RAM | post_bootmode_get(0));

#endif

#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)

/*

* Export available size of memory for Linux,

* taking into account the protected RAM at top of memory

*/

{

ulong pram = 0;

uchar memsz[32];

#ifdef CONFIG_PRAM

pram = getenv_ulong("pram", 10, CONFIG_PRAM);

#endif

#ifdef CONFIG_LOGBUFFER

#ifndef CONFIG_ALT_LB_ADDR

/* Also take the logbuffer into account (pram is in kB) */

pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;

#endif

#endif

sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram);

setenv("mem", (char *)memsz);

}

#endif

/* main_loop() can return to retry autoboot, if so just run it again. */

for (;;) {

main_loop();

}

/* NOTREACHED - no way out of command loop except booting */

}

函数board_init_r事实上为初始化序列的第二部分,此时从内存启动并具有一个正常的C运行环境。如全局数据可以写入,BSS已被清除等,在其中最重要的部分就是调用函数board_late_init准备启动Linux系统的环境变量。

board_late_init

函数board_late_init实现在文件u-boot/board/rockchip/rk32xx/rk32xx.c中:

extern char bootloader_ver[24];

int board_late_init(void)

{

debug("board_late_init\n");

#if (CONFIG_BOOTDELAY > 0)

setenv("bootdelay", simple_itoa(CONFIG_BOOTDELAY));

#endif

setenv("bootcmd", CONFIG_BOOTCOMMAND);

load_disk_partitions();

rkimage_prepare_fdt();

key_init();

#ifdef CONFIG_POWER_RK

pmic_init(0);

fg_init(0); /*fuel gauge init*/

#endif

//TODO:set those buffers in a better way, and use malloc?

rkidb_setup_space(gd->arch.rk_global_buf_addr);

/* after setup space, get id block data first */

rkidb_get_idblk_data();

/* Secure boot check after idb data get */

SecureBootCheck();

if (rkidb_get_bootloader_ver() == 0) {

printf("\n#Boot ver: %s\n", bootloader_ver);

}

char tmp_buf[32];

/* rk sn size 30bytes, zero buff */

memset(tmp_buf, 0, 32);

if (rkidb_get_sn(tmp_buf)) {

setenv("fbt_sn#", tmp_buf);

}

board_fbt_preboot();

return 0;

}

这里其实是在准备Linux系统的启动环境变量,其中核心的部分在于调用board_fbt_preboot进入fastboot启动模式。

board_fbt_preboot

函数board_fbt_preboot实现在文件u-boot/board/rockchip/common/rkboot/fastboot.c中:

void board_fbt_preboot(void)

{

enum fbt_reboot_type frt;

#ifdef CONFIG_CMD_FASTBOOT

/* need to init this ASAP so we know the unlocked state */

fbt_fastboot_init();

#endif

frt = board_fbt_get_reboot_type();

if ((frt == FASTBOOT_REBOOT_UNKNOWN) || (frt == FASTBOOT_REBOOT_NORMAL)) {

FBTDBG("\n%s: no spec reboot type, check key press.\n", __func__);

frt = board_fbt_key_pressed();

} else {

//clear reboot type.

board_fbt_set_reboot_type(FASTBOOT_REBOOT_NORMAL);

}

#ifdef CONFIG_POWER_RK

board_fbt_low_power_check();

#endif

int logo_on = 0;

#ifdef CONFIG_LCD

if (gd->fdt_blob) {

int node = fdt_path_offset(gd->fdt_blob, "/fb");

logo_on = fdtdec_get_int(gd->fdt_blob, node, "rockchip,uboot-logo-on", 0);

}

printf("read logo_on switch from dts [%d]\n", logo_on);

if ((frt != FASTBOOT_REBOOT_MINIKERNEL || (is_power_low() && !is_charging())) && logo_on) {

drv_lcd_init(); //move backlight enable to board_init_r, for don't show logo in rockusb

}

#endif

#ifdef CONFIG_POWER_RK

board_fbt_low_power_off();

#endif

#ifdef CONFIG_UBOOT_CHARGE

//check charge mode when no key pressed.

int cold_boot = board_fbt_is_cold_boot();

if ((cold_boot && board_fbt_is_charging())

|| frt == FASTBOOT_REBOOT_CHARGE) {

#ifdef CONFIG_CMD_CHARGE_ANIM

char *charge[] = { "charge" };

if (logo_on && do_charge(NULL, 0, ARRAY_SIZE(charge), charge)) {

//boot from charge animation.

frt = FASTBOOT_REBOOT_NORMAL;

}

#else

return fbt_run_charge();

#endif

}

#endif //CONFIG_UBOOT_CHARGE

powerOn();

#ifdef CONFIG_LCD

if (frt != FASTBOOT_REBOOT_MINIKERNEL && logo_on) {

lcd_enable_logo(true);

lcd_standby(0);

mdelay(100);

rk_backlight_ctrl(-1); /*use defaut brightness in dts*/

}

#endif

#ifdef CONFIG_RK_PWM_REMOTE

if ((frt == FASTBOOT_REBOOT_UNKNOWN) || (frt == FASTBOOT_REBOOT_NORMAL)) {

frt = board_fbt_key_pressed();

}

RemotectlDeInit();

#endif

if (frt == FASTBOOT_REBOOT_RECOVERY) {

FBTDBG("\n%s: starting recovery img because of reboot flag\n", __func__);

return board_fbt_run_recovery();

} else if (frt == FASTBOOT_REBOOT_RECOVERY_WIPE_DATA) {

FBTDBG("\n%s: starting recovery img to wipe data "

"because of reboot flag\n", __func__);

/* we've not initialized most of our state so don't

* save env in this case

*/

return board_fbt_run_recovery_wipe_data();

}

#ifdef CONFIG_CMD_FASTBOOT

else if (frt == FASTBOOT_REBOOT_FASTBOOT) {

FBTDBG("\n%s: starting fastboot because of reboot flag\n", __func__);

board_fbt_request_start_fastboot();

}

#endif

else if (frt == FASTBOOT_REBOOT_MINIKERNEL) {

FBTDBG("\n%s: starting mini kernel because of reboot flag\n", __func__);

printf("mini kernel\n");

do_mini_kernel();

}

else {

FBTDBG("\n%s: check misc command.\n", __func__);

/* unknown reboot cause (typically because of a cold boot).

* check if we had misc command to boot recovery.

*/

rkloader_run_misc_cmd();

}

}

在该函数中,判断通过文件kernel/arch/arm/mach-rockchip/rk3288.c中的函数rk3288_restart调用writel_relaxed写入寄存器RK3288_PMU_SYS_REG0中的值来判断启动类型,对于recovery模式来说,最终调用到函数board_fbt_run_recovery。

board_fbt_run_recovery

函数board_fbt_run_recovery实现在文件u-boot/board/rockchip/common/rkboot/fastboot.c中:

static void board_fbt_run_recovery(void)

{

#ifdef CONFIG_CMD_BOOTRK

char *const boot_recovery_cmd[] = {"bootrk", "recovery"};

do_bootrk(NULL, 0, ARRAY_SIZE(boot_recovery_cmd), boot_recovery_cmd);

#endif

/* returns if recovery.img is bad */

FBTERR("\nfastboot: Error: Invalid recovery img\n");

}

很明显,这里调用的函数为do_bootrk(NULL, 0, 2, {"bootrk", "recovery"}),

do_bootrk

函数do_bootrk的实现在文件u-boot/common/cmd_bootrk.c中:

int do_bootrk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

{

char *boot_source = "boot";

rk_boot_img_hdr *hdr = NULL;

const disk_partition_t* ptn = NULL;

bootm_headers_t images;

bool charge = false;

if (argc >= 2) {

if (!strcmp(argv[1], "charge")) {

charge = true;

} else {

boot_source = argv[1];

}

}

memset(&images, 0, sizeof(images));

if (rk_bootrk_start(&images)) { /*it returns 1 when failed.*/

puts("bootrk: failed to setup lmb!\n");

goto fail;

}

ptn = get_disk_partition(boot_source);

if (ptn) {

hdr = rk_load_image_from_storage(ptn, &images);

if (hdr == NULL) {

goto fail;

}

} else {

hdr = rk_load_image_from_ram(boot_source, &images);

if (hdr == NULL) {

goto fail;

}

}

#ifdef CONFIG_SECUREBOOT_CRYPTO

if ((SecureMode != SBOOT_MODE_NS) && (SecureBootCheckOK == 0)) {

puts("Not allow to boot no secure sign image!");

while(1);

}

#endif /* CONFIG_SECUREBOOT_CRYPTO */

rk_commandline_setenv(boot_source, hdr, charge);

#if defined(CONFIG_UBOOT_CHARGE) && defined(CONFIG_POWER_FG_ADC)

fg_adc_storage_flag_store(0);

fg_adc_storage_store(0);

#endif

rk_module_deinit();

/* Secure boot state will set drm, sn and others information in the nanc ram,

* so, after set, PLS notice do not read/write nand flash.

*/

SecureBootSecureState2Kernel(SecureBootCheckOK);

/* after here, make sure no read/write storate */

bootimg_print_image_hdr(hdr);

printf("kernel @ 0x%08x (0x%08x)\n", hdr->kernel_addr, hdr->kernel_size);

printf("ramdisk @ 0x%08x (0x%08x)\n", hdr->ramdisk_addr, hdr->ramdisk_size);

images.ep = hdr->kernel_addr;

images.rd_start = hdr->ramdisk_addr;

images.rd_end = hdr->ramdisk_addr + hdr->ramdisk_size;

#ifdef CONFIG_IMPRECISE_ABORTS_CHECK

puts("enable imprecise aborts check.");

enable_imprecise_aborts();

#endif

#ifdef CONFIG_BOOTM_LINUX

puts("bootrk: do_bootm_linux...\n");

do_bootm_linux(0, 0, NULL, &images);

#endif /* CONFIG_BOOTM_LINUX */

fail:

board_fbt_boot_failed(boot_source);

puts("bootrk: Control returned to monitor - resetting...\n");

do_reset(cmdtp, flag, argc, argv);

return 1;

}

这里的主要任务就是确认了所要加载的镜像的位置,然后通过函数do_bootm_linux(0, 0, NULL, &images)启动对应的镜像,对于recovery模式来说,就是镜像recovery.img了。

do_bootm_linux

函数do_bootm_linux(0, 0, NULL, &images)来实现在文件u-boot/arch/arm/lib/bootm.c中:

int do_bootm_linux(int flag, int argc, char * const argv[],

bootm_headers_t *images)

{

/* No need for those on ARM */

if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)

return -1;

if (flag & BOOTM_STATE_OS_PREP) {

boot_prep_linux(images);

return 0;

}

if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {

boot_jump_linux(images, flag);

return 0;

}

boot_prep_linux(images);

boot_jump_linux(images, flag);

return 0;

}

最终到这里,通过boot_prep_linux设置参数,并以boot_jump_linux来启动linux内核。接下来的任务,就是Linux系统启动的事情了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值