/********************************************************************************
* I.MX6 recovery mode hacking
* 说明:
* 看一下i.MX6 Recovery模式是怎么工作的。
*
* 2017-6-12 深圳 龙华樟坑村 曾剑锋
*******************************************************************************/ 一、参考文档:
. Booting into recovery from terminal [duplicate]
https://android.stackexchange.com/questions/50366/booting-into-recovery-from-terminal
. Enter recovery mode from command line
https://android.stackexchange.com/questions/21050/enter-recovery-mode-from-command-line
. How to Support Recovery Mode for POR Reboot Based on i.MX6 Android R13.4.1
https://community.nxp.com/docs/DOC-93964 二、U-Boot Hacking /************************************************************************
*
* This is the next part if the initialization sequence: we are now
* running from RAM and have a "normal" C environment, i. e. global
* data can be written, BSS has been cleared, the stack size in not
* that critical any more, etc.
*
************************************************************************
*/ 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(); debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr); #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 > ) {
# 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") == ) {
printf(" CRC: %08X", crc32(,
(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_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 /* set up exceptions */
interrupt_init();
/* enable exceptions */
enable_interrupts(); /* Initialize from environment */
load_addr = getenv_ulong("loadaddr", , load_addr); #ifdef CONFIG_BOARD_LATE_INIT
board_late_init();
#endif #ifdef CONFIG_FSL_FASTBOOT
fastboot_setup(); ----------------------------------------------+
#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()); |
#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 = ; |
uchar memsz[]; |
|
#ifdef CONFIG_PRAM |
pram = getenv_ulong("pram", , 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) / ; |
#endif |
#endif |
sprintf((char *)memsz, "%ldk", (gd->ram_size / ) - pram); |
setenv("mem", (char *)memsz); |
} |
#endif |
|
#ifdef CONFIG_FSL_FASTBOOT |
check_fastboot(); |
#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 */ |
} |
|
void fastboot_setup(void) <------------------------------------+
{
struct tag_serialnr serialnr;
char serial[]; get_board_serial(&serialnr);
sprintf(serial, "%u%u", serialnr.high, serialnr.low);
g_dnl_set_serialnumber(serial); /*execute board relevant initilizations for preparing fastboot */
board_fastboot_setup(); /*get the fastboot dev*/
_fastboot_setup_dev(); /*check if we need to setup recovery*/
#ifdef CONFIG_ANDROID_RECOVERY
check_recovery_mode(); -----------------------+
#endif |
|
/*load partitions information for the fastboot dev*/ |
_fastboot_load_partitions(); |
|
parameters_setup(); |
} |
|
/* export to lib_arm/board.c */ |
void check_recovery_mode(void) <-------------------+
{
if (check_key_pressing()) {
puts("Fastboot: Recovery key pressing got!\n");
setup_recovery_env();
} else if (check_recovery_cmd_file()) { --------------+
puts("Fastboot: Recovery command file found!\n"); |
setup_recovery_env(); --------------*-------------------+
#ifdef CONFIG_BCB_SUPPORT | |
} else if (recovery_check_and_clean_command()) { | |
puts("Fastboot: BCB command found\n"); | |
setup_recovery_env(); | |
#endif | |
} else { | |
puts("Fastboot: Normal\n"); | |
} | |
} | |
| |
int check_recovery_cmd_file(void) <-------------------+ |
{ |
int button_pressed = ; |
int recovery_mode = ; |
|
#ifdef CONFIG_SBC7112 |
return recovery_mode || button_pressed; |
#endif |
recovery_mode = recovery_check_and_clean_flag(); -----------------------+ |
| |
/* Check Recovery Combo Button press or not. */ | |
imx_iomux_v3_setup_multiple_pads(recovery_key_pads, | |
ARRAY_SIZE(recovery_key_pads)); | |
| |
gpio_direction_input(GPIO_VOL_DN_KEY); | |
| |
if (gpio_get_value(GPIO_VOL_DN_KEY) == ) { /* VOL_DN key is low assert */ | |
button_pressed = ; | |
printf("Recovery key pressed\n"); | |
} | |
| |
return recovery_mode || button_pressed; | |
} | |
| |
int recovery_check_and_clean_flag(void) <--------------------------+ |
{ |
int flag_set = ; |
u32 reg; |
reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR); |
|
flag_set = !!(reg & ANDROID_RECOVERY_BOOT); |
printf("check_and_clean: reg %x, flag_set %d\n", reg, flag_set); |
/* clean it in case looping infinite here.... */ |
if (flag_set) { |
reg &= ~ANDROID_RECOVERY_BOOT; |
writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR); --------------------*-+
} | |
| |
return flag_set; | |
} | |
| |
void setup_recovery_env(void) <-----------------------------------+ |
{ |
board_recovery_setup(); --------+ |
} | |
| |
void board_recovery_setup(void) <------+ |
{ |
int bootdev = get_boot_device(); |
|
switch (bootdev) { |
#if defined(CONFIG_FASTBOOT_STORAGE_SATA) |
case SATA_BOOT: |
if (!getenv("bootcmd_android_recovery")) |
setenv("bootcmd_android_recovery", |
"boota sata recovery"); |
break; |
#endif /*CONFIG_FASTBOOT_STORAGE_SATA*/ |
#if defined(CONFIG_FASTBOOT_STORAGE_MMC) |
case SD2_BOOT: |
case MMC2_BOOT: |
if (!getenv("bootcmd_android_recovery")) |
setenv("bootcmd_android_recovery", |
"boota mmc0 recovery"); |
break; |
case SD3_BOOT: |
case MMC3_BOOT: |
if (!getenv("bootcmd_android_recovery")) |
setenv("bootcmd_android_recovery", |
"boota mmc1 recovery"); |
break; |
case MMC4_BOOT: |
if (!getenv("bootcmd_android_recovery")) |
setenv("bootcmd_android_recovery", |
"boota mmc2 recovery"); |
break; |
#endif /*CONFIG_FASTBOOT_STORAGE_MMC*/ |
default: |
printf("Unsupported bootup device for recovery: dev: %d\n", |
bootdev); |
return; |
} |
|
printf("setup env for recovery..\n"); |
setenv("bootcmd", "run bootcmd_android_recovery"); |
} |
|
三、Linux Kernel Hacking |
|
DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") |
/* |
* i.MX6Q/DL maps system memory at 0x10000000 (offset 256MiB), and |
* GPU has a limit on physical address that it accesses, which must |
* be below 2GiB. |
*/ |
.dma_zone_size = (SZ_2G - SZ_256M), |
.smp = smp_ops(imx_smp_ops), |
.map_io = imx6q_map_io, |
.init_irq = imx6q_init_irq, |
.init_machine = imx6q_init_machine, |
.init_late = imx6q_init_late, |
.dt_compat = imx6q_dt_compat, |
.reserve = imx6q_reserve, |
.restart = mxc_restart, ------------------+ |
MACHINE_END | |
| |
/* | |
* Reset the system. It is called by machine_restart(). | |
*/ | |
void mxc_restart(enum reboot_mode mode, const char *cmd) <-----+ |
{ |
unsigned int wcr_enable; |
|
arch_reset_special_mode(mode, cmd); -------------------------+ |
| |
if (wdog_clk) | |
clk_enable(wdog_clk); | |
| |
if (cpu_is_mx1()) | |
wcr_enable = ( << ); | |
/* | |
* Some i.MX6 boards use WDOG2 to reset external pmic in bypass mode, | |
* so do WDOG2 reset here. Do not set SRS, since we will | |
* trigger external POR later. Use WDOG1 to reset in ldo-enable | |
* mode. You can set it by "fsl,wdog-reset" in dts. | |
* For i.MX6SX we have to trigger wdog-reset to reset QSPI-NOR flash to | |
* workaround qspi-nor reboot issue whatever ldo-bypass or not. | |
*/ | |
else if ((wdog_source == && (cpu_is_imx6q() || cpu_is_imx6dl() || | |
cpu_is_imx6sl())) || cpu_is_imx6sx() || cpu_is_imx7d() | |
|| cpu_is_imx6ul()) | |
wcr_enable = 0x14; | |
else | |
wcr_enable = ( << ); | |
| |
/* Assert SRS signal */ | |
__raw_writew(wcr_enable, wdog_base); | |
/* | |
* Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be | |
* written twice), we add another two writes to ensure there must be at | |
* least two writes happen in the same one 32kHz clock period. We save | |
* the target check here, since the writes shouldn't be a huge burden | |
* for other platforms. | |
*/ | |
__raw_writew(wcr_enable, wdog_base); | |
__raw_writew(wcr_enable, wdog_base); | |
| |
/* wait for reset to assert... */ | |
mdelay(); | |
| |
pr_err("%s: Watchdog reset failed to assert reset\n", __func__); | |
| |
/* delay to allow the serial port to show the message */ | |
mdelay(); | |
| |
/* we'll take a jump through zero as a poor second */ | |
soft_restart(); | |
} | |
| |
static void arch_reset_special_mode(char mode, const char *cmd) <----------+ |
{ |
#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD |
if (cmd && strcmp(cmd, "recovery") == ) |
do_switch_recovery(); -----+ |
else if (cmd && strcmp(cmd, "bootloader") == ) | |
do_switch_fastboot(); | |
#endif | |
} | |
| |
void do_switch_recovery(void) <-------------------+ |
{ |
u32 reg; |
void *addr; |
struct clk *snvs_root; |
if(cpu_is_imx6()){ |
addr = ioremap(MX6_SNVS_BASE_ADDR, MX6_SNVS_SIZE); |
if (!addr) { |
pr_warn("SNVS ioremap failed!\n"); |
return; |
} |
reg = __raw_readl(addr + MX6_SNVS_LPGPR); <----------------------+
reg |= ANDROID_RECOVERY_BOOT;
__raw_writel(reg, (addr + MX6_SNVS_LPGPR));
}else{
snvs_root = clk_get_sys("imx-snvs.0", "snvs");
addr = ioremap(MX7_SNVS_BASE_ADDR, MX7_SNVS_SIZE);
if (!addr) {
pr_warn("SNVS ioremap failed!\n");
return;
}
clk_enable(snvs_root);
reg = __raw_readl(addr + MX7_SNVS_LPGPR);
reg |= ANDROID_RECOVERY_BOOT;
__raw_writel(reg, (addr + MX7_SNVS_LPGPR));
clk_disable(snvs_root);
}
iounmap(addr);
}

I.MX6 recovery mode hacking的更多相关文章

  1. I.MX6 mfgtool2-android-mx6q-sabresd-emmc.vbs hacking

    /******************************************************************** * I.MX6 mfgtool2-android-mx6q- ...

  2. I.MX6 gpio-keys driver hacking

    /**************************************************************************** * I.MX6 gpio-keys driv ...

  3. I.MX6 bq27441 driver hacking

    /************************************************************************* * I.MX6 bq27441 driver ha ...

  4. I.MX6 U-boot PWM hacking

    /******************************************************************************* * I.MX6 U-boot PWM ...

  5. I.MX6 U-boot GPIO hacking

    /******************************************************************************* * I.MX6 U-boot GPIO ...

  6. I.MX6 U-Boot mkconfig hacking

    /**************************************************************************** * I.MX6 U-Boot mkconfi ...

  7. I.MX6 MAC Address hacking

    /************************************************************************** * I.MX6 MAC Address hack ...

  8. I.MX6 mkuserimg.sh hacking

    /*********************************************************************** * I.MX6 mkuserimg.sh hackin ...

  9. I.MX6 天嵌 E9 U-boot menu hacking

    /************************************************************************************ * I.MX6 天嵌 E9 ...

随机推荐

  1. linux centos7 安装zookeeper

    linux 系统下 zookeeper 安装教程 1.下载安装包 1)进入安装目录 cd /home/install/ 2)下载 wget http://mirror.bit.edu.cn/apach ...

  2. phpword使用

    composer 安装 https://packagist.org/packages/phpoffice/phpword 开发文档:http://phpword.readthedocs.io/en/l ...

  3. xaml可扩展应用程序标记语言

    xaml 类似于 html,但不是html,它是基于xml语言的:’html可以呈现在浏览器中而xaml 可以现实 3d动画等特效. xaml  是强类型语言,  是解释性语言,虽然他可以被编译.

  4. 20145201《Java程序设计》第九周学习总结

    20145201 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行操作,开发人员无须接触底层 ...

  5. menubar下面的选项不可以输入中文

    这是一个QT5的bug. 1.不用中文,使用英文: 2.先输入中文,然后在属性Action里面的text里改成中文.

  6. gradle-rn-app工程运行须知

    singwhatiwanna edited this page 16 days ago · 5 revisions  Pages 7 Home Demo 工程运行须知 VirtualAPK API 概 ...

  7. [BZOJ2017][Usaco2009 Nov]硬币游戏

    Description 农夫约翰的奶牛喜欢玩硬币游戏,因此他发明了一种称为“Xoinc”的两人硬币游戏. 初始时,一个有N(5 <= N <= 2,000)枚硬币的堆栈放在地上,从堆顶数起 ...

  8. Java 正则表达式 Pattern & Matcher

    通常会有这种需求: 在文档中搜索有规律的字符串,然后进行统计或者替换.Java.util.regex包下的Pattern和Matcher这两个类提供了通过正则表达式来匹配查询,甚至替换的功能.那么我们 ...

  9. java 使用反射

    java程序中的对象在运行时会出现两种类型:编译时类型和运行时类型.例如List list  = new ArrayList().其中变量list的编译时类型是List,运行时类型是ArrayList ...

  10. ZC_03_创建对象

    1. 正如 上一篇文章中所见,反射创建 类实例的方式,主要为2类: (1).Class对象.newInstance() 这是使用 默认的无参构造函数 创建对象 (2).Constructor对象.ne ...