前言:
我们在项目工作中对Uboot启动流程熟悉后,会非常有帮助,例如:工作中再做一些关于secure boot、loader模式下做一些操作、启动阶段拉高电平操作外设等。
一、u-boot基本介绍
1.1 u-boot起源
u-boot(Universal Boot Loader),是Wolfgang Denk (德国人)在sourceforge.net的发起的开源项目用于嵌入式soc开发,支持ARM,MIPS,PowerPC,x86等处理器架构,
同时支持linux,VxWorks,NetBSD,QNX等操作系统,逐渐被众多厂商采用成为BootLoader标准之一。
1.2 RK使用的u-boot
u-boot 一共有两个版本v2014旧版本和v2017新版本:
- 基于开源的 UBoot v2014.10 正式版中切出来:
支持芯片:rk3288、rk3036、rk312x、rk3368、rk322x、rk3366、rk3399 等;
rk3399: # strings uboot.img |grep 2023
U-Boot 2014.10-RK3399-06 (Sep 20 2023 - 09:31:37)
- 基于开源的 U-Boot v2017.09 正式版中切出来:
支持目前RK所有主流在售芯片:
rk3588: # strings uboot.img |grep 2023
U-Boot 2017.09 (Jun 02 2023 - 19:43:33 +0800)
1.2 v2017.09 支持的功能主要有
-
支持 RK Android 固件启动;
-
支持 Android AOSP 固件启动;
-
支持 Linux Distro 固件启动;
-
支持 Rockchip miniloader 和 SPL/TPL 两种 Pre-loader 引导;
-
支持 LVDS、EDP、MIPI、HDMI、CVBS、RGB 等显示设备;
-
支持 eMMC、Nand Flash、SPI Nand flash、SPI NOR flash、SD 卡、 U 盘等存储设备启动;
-
支持 FAT、EXT2、EXT4 文件系统;
-
支持 GPT、RK parameter 分区表;
-
支持开机 LOGO、充电动画、低电管理、电源管理;
-
支持 I2C、PMIC、CHARGE、FUEL GUAGE、USB、GPIO、PWM、GMAC、eMMC、NAND、Interrupt 等;
-
支持 Vendor storage 保存用户的数据和配置;
-
支持 RockUSB 和 Google Fastboot 两种 USB gadget 烧写 eMMC;
-
支持 Mass storage、ethernet、HID 等 USB 设备;
-
支持通过硬件状态动态选择 kernel DTB.
1.3 u-boot的代码结构
以卫士通rk3399的uboot-v2014为例:
├── api #存放uboot提供的syscall 的api函数例如:system (reset, platform info), devices (enumerate all, open, close, read, write)等├── arch #存放SOC相关的代码平台文件 包括重要的 start.S load armboot to ram、设置栈等
├── board #存放板级的代码,例如rk的fastboot、loader模式检测等
├── common #通用函数的实现 ,包含进入uboot命令行模式后的实现run_command();比如我们常用的tftp 、nand/memory测试等命令,还有board_f 、board_r 初始化的board_init_f和board_init_r
├── disk #磁盘分区相关代码
├── drivers #设备驱动的代码storage、spi nor/nand、emmc、pcie、网卡等
├── dts #存放设备树(与kernel共用,这个里面基本上没有用)
├── fs #文件系统格式的支持 ext2、ext4、fat的代码
├── include #头文件和平台宏控的默认文件.h 例如:串口的波特率、默认打印的串口NUM等
├── net #网络协议的代码,例如arp、tftp、ping等
├── post #上电自检代码检测,例如:CPU cache、memory、watchdog、uart等
├── scripts #脚本存放位置 例如:cleanpatch等工具
├── tools #用于编译和检查uboot目标文件mkimage工具
二、u-boot启动流程
2.1 RK启动方式
RK平台根据前级Loader代码是否开源,目前有两套启动方式:
// 前级loader闭源
BOOTROM => ddr bin => Miniloader => TRUST => U-BOOT => KERNEL
// 前级loader开源
BOOTROM => TPL(Tiny Program Loader) => SPL (Secondary Program Loade)Miniloader => TRUST => U-BOOT => KERNEL
TPL(Tiny Program Loader)和 SPL(Secondary Program Loader)是比 U-Boot 更早阶段的 Loader:
TPL:运行在 sram 中,负责完成 ddr 初始化;
SPL:运行在 ddr 中,负责完成系统的 lowlevel 初始化、后级固件加载(trust.img 和 uboot.img);
U-Boot proper:运行在ddr中,即我们通常所说的"U-Boot",它负责引导kernel;
2.1.1 BootRom与SRAM在RK3399数据手册的规格:

2.1.2 BootRom引导过程流程
例如 RK3399支持从内部bootrom启动,重映射由 SGRF_PMU_CON0[15] 控制。当 remap 设置为 0 时,0xFFFF0000 地址被映射到 bootrom。当 remapis 设置为 1 时,0xFFFF0000 地址被映射到 INTMEM0。
其中cortex-A53的core0作为第一个启动的核心,执行0xffff0000处的Bootrom loader程序。

引导过程流程流程图:
·
2.1.3 u-boot 启动过程
-
链接脚本文件u-boot.lds uboot的入口函数
uboot编译完成后会在根目录生成这个文件
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") OUTPUT_ARCH(aarch64) ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(8); .text : { *(.__image_copy_start) arch/arm/cpu/armv8/start.o (.text*) *(.text*) } -
arch/arm/cpu/armv8/start.S_start:
.globl _start _start: nop b reset3. reset:
reset: #ifdef CONFIG_ROCKCHIP /* * check loader tag */ ldr x0, =__loader_tag ldr w1, [x0] ldr x0, =LoaderTagCheck ldr w2, [x0] cmp w1, w2 b.eq checkok ret /* return to maskrom or miniloader */ checkok: #endif /* * Could be EL3/EL2/EL1, Initial State: * Little Endian, MMU Disabled, i/dCache Disabled */ adr x0, vectors switch_el x1, 3f, 2f, 1f 3: msr vbar_el3, x0 mrs x0, scr_el3 orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */ msr scr_el3, x0 msr cptr_el3, xzr /* Enable FP/SIMD */ ldr x0, =COUNTER_FREQUENCY msr cntfrq_el0, x0 /* Initialize CNTFRQ */ #ifdef CONFIG_ROCKCHIP msr cntvoff_el2, xzr /* clear cntvoff_el2 for kernel */ #endif b 0f 2: msr vbar_el2, x0 mov x0, #0x33ff msr cptr_el2, x0 /* Enable FP/SIMD */ b 0f 1: msr vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */ 0: bl lowlevel_init |
4. lowlevel_init: u-boot/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
ENTRY(lowlevel_init) mov x29, lr /* Save LR */ ldr x0, =secondary_boot_func bl secondary_switch_to_el2 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1 bl secondary_switch_to_el1 #endif |
在ARMv8架构中改用执行等级(Execution Level,EL)EL0~EL3来定义ARM核的运行等级,其中EL0~EL2等级分为安全态和非安全态。ARMv8架构与ARMv7架构中ARM核运行权限的对应关系如下图:

EL3 负责负责安全监测和安全模式切换通过设定SCR寄存器中的安全状态位(NS bit)来实现的,通过触发安全监控模式调用(smc)切换到Monitor模式或EL3,
并通过共享内存的方式将数据发送给安全世界状态来进行处理;
root@linux :/data/develop/root/android/rk/00_wst/u-boot# strings tools/rk_tools/bin/rk33/rk3399_bl31_v1.31.elf |grep arm_smc
arm_smccc_res
参考函数reset:
switch_el x1, 3f, 2f, 1f
EL2 主要提供虚拟化支持;
EL1 能够执行一些特权指令,用于运行各类操作系统,在安全模式则是Trusted OS;
EL0 (Normal World) 用户的APP进程等;
5. _main: arch/arm/lib/crt0_64.S
ENTRY(_main)
/*
* Set up initial C runtime environment and call board_init_f(0).
*/
ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
sub x0, x0, #GD_SIZE /* allocate one GD above SP */
bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
mov x18, sp /* GD is above SP */
mov x0, #0
bl board_init_f
..................
/* call board_init_r(gd_t *id, ulong dest_addr) */
mov x0, x18 /* gd_t */
ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */
b board_init_r |
2.1.4 board_init_f
u-boot/lib/hang.c
void hang(void)
{
bootstage_error(BOOTSTAGE_ID_NEED_RESET);
for (;;)
;
} |
u-boot/lib/initcall.c
int initcall_run_list(const init_fnc_t init_sequence[])
{
const init_fnc_t *init_fnc_ptr;
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
unsigned long reloc_ofs = 0;
int ret;
if (gd->flags & GD_FLG_RELOC)
reloc_ofs = gd->reloc_off;
debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs);
if (gd->flags & GD_FLG_RELOC)
debug(" (relocated to %p)\n", (char *)*init_fnc_ptr);
else
debug("\n");
ret = (*init_fnc_ptr)();
if (ret) {
printf("initcall sequence %p failed at call %p (err=%d)\n",
init_sequence,
(char *)*init_fnc_ptr - reloc_ofs, ret);
return -1;
}
}
return 0;
}
|
u-boot/common/board_f.c
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = 0;
if (initcall_run_list(init_sequence_f))
hang();
}
/* 通过 hung() for 循环调用init_sequence_f 的函数指针 */
static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_SANDBOX
setup_ram_buf,
#endif
setup_mon_len, /* 设置 monitor 长度 */
setup_fdt,
#ifdef CONFIG_TRACE
trace_early_init,
#endif
initf_malloc,
arch_cpu_init, /* basic arch cpu dependent setup */
#endif
mark_bootstage,
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
initf_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
/* TODO: can any of this go into arch_cpu_init()? */
#if defined(CONFIG_PPC) && !defined(CONFIG_8xx_CPUCLK_DEFAULT)
get_clocks, /* get CPU and bus clocks (etc.) */
#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
&& !defined(CONFIG_TQM885D)
adjust_sdram_tbs_8xx,
#endif
/* TODO: can we rename this to timer_init()? */
init_timebase,
#endif
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_BLACKFIN)
timer_init, /* initialize timer */
#endif
#ifdef CONFIG_SYS_ALLOC_DPRAM
#if !defined(CONFIG_CPM2)
dpram_init,
#endif
#endif
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /* initialize environment */
#if defined(CONFIG_8xx_CPUCLK_DEFAULT)
/* get CPU and bus clocks according to the environment variable */
get_clocks_866,
/* adjust sdram refresh rate according to the new clock */
sdram_adjust_866,
init_timebase,
#endif
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
#ifdef CONFIG_SANDBOX
sandbox_early_getopt_check,
#endif
#ifdef CONFIG_OF_CONTROL
fdtdec_prepare_fdt,
#endif
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
#if defined(CONFIG_MPC8260)
prt_8260_rsr,
prt_8260_clks,
#endif /* CONFIG_MPC8260 */
#if defined(CONFIG_MPC83xx)
prt_83xx_rsr,
#endif
#ifdef CONFIG_PPC
checkcpu,
#endif
print_cpuinfo, /* display cpu info (and speed) */
#if defined(CONFIG_MPC5xxx)
prt_mpc5xxx_clks,
#endif /* CONFIG_MPC5xxx */
#if defined(CONFIG_DISPLAY_BOARDINFO)
show_board_info,
#endif
INIT_FUNC_WATCHDOG_INIT
#if defined(CONFIG_MISC_INIT_F)
misc_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
init_func_i2c,
#endif
#if defined(CONFIG_HARD_SPI)
init_func_spi,
#endif
#ifdef CONFIG_X86
dram_init_f, /* configure available RAM banks */
calculate_relocation_address,
#endif
announce_dram_init,
/* TODO: unify all these dram functions? */
#ifdef CONFIG_ARM
dram_init, /* configure available RAM banks */
#endif
#if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
init_func_ram,
#endif
#ifdef CONFIG_POST
post_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_SYS_DRAM_TEST)
testdram,
#endif /* CONFIG_SYS_DRAM_TEST */
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_POST
init_post,
#endif
INIT_FUNC_WATCHDOG_RESET
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - area that won't get touched by U-Boot and Linux (optional)
* - kernel log buffer
* - protected RAM
* - LCD framebuffer
* - monitor code
* - board info struct
*/
setup_dest_addr,
#if defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
/* Blackfin u-boot monitor should be on top of the ram */
reserve_uboot,
#endif
#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR)
reserve_logbuffer,
#endif
#ifdef CONFIG_PRAM
reserve_pram,
#endif
reserve_round_4k,
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \
defined(CONFIG_ARM)
reserve_mmu,
#endif
#if defined(CONFIG_LCD) || defined(CONFIG_ROCKCHIP_DISPLAY)
reserve_lcd,
#endif
#ifdef CONFIG_ROCKCHIP
reserve_global_buffers,
#endif
reserve_trace,
/* TODO: Why the dependency on CONFIG_8xx? */
#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
!defined(CONFIG_BLACKFIN)
reserve_video,
#endif
#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_NIOS2)
reserve_uboot,
#endif
#ifndef CONFIG_SPL_BUILD
reserve_malloc,
reserve_board,
#endif
setup_machine,
reserve_global_data,
reserve_fdt,
reserve_stacks,
setup_dram_config,
show_dram_config,
#ifdef CONFIG_PPC
setup_board_part1,
INIT_FUNC_WATCHDOG_RESET
setup_board_part2,
#endif
display_new_sp,
#ifdef CONFIG_SYS_EXTBDINFO
setup_board_extra,
#endif
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
setup_reloc,
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
jump_to_copy,
#endif
NULL,
};
|
2.1.5 board_init_r
u-boot/common/board_r.c
void board_init_r(gd_t *new_gd, ulong dest_addr)
{
if (initcall_run_list(init_sequence_r))
hang();
}
init_fnc_t init_sequence_r[] = {
initr_trace,
initr_reloc,
/* TODO: could x86/PPC have this also perhaps? */
#ifdef CONFIG_ARM
initr_caches,
#endif
initr_reloc_global_data,
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
initr_unlock_ram_in_cache,
#endif
initr_barrier,
initr_malloc,
bootstage_relocate,
#ifdef CONFIG_DM
initr_dm,
#endif
#ifdef CONFIG_ARM
board_init, /* Setup chipselects */
#endif
/*
* 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
stdio_init_tables,
initr_serial,
initr_announce,
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_PPC
initr_trap,
#endif
#ifdef CONFIG_ADDR_MAP
initr_addr_map,
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_R)
board_early_init_r,
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_LOGBUFFER
initr_logbuffer,
#endif
#ifdef CONFIG_POST
initr_post_backlog,
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_SYS_DELAYED_ICACHE
initr_icache_enable,
#endif
#if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do early PCI configuration _before_ the flash gets initialised,
* because PCU ressources are crucial for flash access on some boards.
*/
initr_pci,
#endif
#ifdef CONFIG_PPC
initr_spi,
#endif
#ifdef CONFIG_CMD_NAND
initr_nand,
#endif
#ifdef CONFIG_CMD_ONENAND
initr_onenand,
#endif
#ifdef CONFIG_GENERIC_MMC
initr_mmc,
#endif
#ifdef CONFIG_HAS_DATAFLASH
initr_dataflash,
#endif
#ifdef CONFIG_ROCKCHIP
initr_rk_storage,
#endif
initr_env,
INIT_FUNC_WATCHDOG_RESET
initr_secondary_cpu,
#ifdef CONFIG_HERMES
initr_hermes,
#endif
#if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
mac_read_from_eeprom,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do pci configuration
*/
initr_pci,
#endif
stdio_add_devices,
initr_jumptable,
#ifdef CONFIG_API
initr_api,
#endif
console_init_r, /* fully init console as a device */
#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
show_board_info,
#endif
#ifdef CONFIG_ARCH_MISC_INIT
arch_misc_init, /* miscellaneous arch-dependent init */
#endif
#ifdef CONFIG_MISC_INIT_R
misc_init_r, /* miscellaneous platform-dependent init */
#endif
#ifdef CONFIG_HERMES
initr_hermes_start,
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_CMD_KGDB
initr_kgdb,
#endif
#ifdef CONFIG_X86
board_early_init_r,
#endif
interrupt_init,
#if defined(CONFIG_ARM) || defined(CONFIG_x86)
initr_enable_interrupts,
#endif
#ifdef CONFIG_X86
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
initr_status_led,
#endif
/* PPC has a udelay(20) here dating from 2002. Why? */
#ifdef CONFIG_CMD_NET
initr_ethaddr,
#endif
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
#ifdef CONFIG_CMD_SCSI
INIT_FUNC_WATCHDOG_RESET
initr_scsi,
#endif
#ifdef CONFIG_CMD_DOC
INIT_FUNC_WATCHDOG_RESET
initr_doc,
#endif
#ifdef CONFIG_BITBANGMII
initr_bbmii,
#endif
#ifdef CONFIG_CMD_NET
INIT_FUNC_WATCHDOG_RESET
initr_net,
#endif
#ifdef CONFIG_POST
initr_post,
#endif
#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE)
initr_pcmcia,
#endif
#if defined(CONFIG_CMD_IDE)
initr_ide,
#endif
#ifdef CONFIG_LAST_STAGE_INIT
INIT_FUNC_WATCHDOG_RESET
/*
* Some parts can be only initialized if all others (like
* Interrupts) are up and running (i.e. the PC-style ISA
* keyboard).
*/
last_stage_init,
#endif
#ifdef CONFIG_CMD_BEDBUG
INIT_FUNC_WATCHDOG_RESET
initr_bedbug,
#endif
#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
initr_mem,
#endif
#ifdef CONFIG_ROCKCHIP
rk_initr_serial, /* YQ Add for serial-MM Boot */
#endif
#ifdef CONFIG_PS2KBD
initr_kbd,
#endif
run_main_loop,
}; |
root@chroot:~/android/rk/00_wst/u-boot# grep -rn rk_initr_serial
匹配到二进制文件 u-boot
System.map:495:0000000000216878 t rk_initr_serial
串口抓的启动log:

2.1.6 main_loop
static int run_main_loop(void)
{
/* main_loop() can return to retry autoboot, if so just run it again */
for (;;)
main_loop();
return 0;
}
void main_loop(void)
{
const char *s;
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
#ifndef CONFIG_SYS_GENERIC_BOARD
puts("Warning: Your board does not use generic board. Please read\n");
puts("doc/README.generic-board and take action. Boards not\n");
puts("upgraded by the late 2014 may break or be removed.\n");
#endif
modem_init();
#ifdef CONFIG_VERSION_VARIABLE
setenv("ver", version_string); /* set version variable */
#endif /* CONFIG_VERSION_VARIABLE */
cli_init();
run_preboot_environment_command();
#if defined(CONFIG_UPDATE_TFTP)
update_tftp(0UL);
#endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process();
if (cli_process_fdt(&s))
cli_secure_boot_cmd(s);
autoboot_command(s);
cli_loop();
} |
U_BOOT_CMD:

U_BOOT_CMD(
tftpboot, 3, 1, do_tftpb,
"boot image via network using TFTP protocol",
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
2.1.7 reboot loader
kernel :
arch/arm64/boot/dts/rockchip/rk3399.dtsi
最后更新到寄存器中

uboot: board/rockchip/common/rkboot/fastboot.c
board_late_init()
board_fbt_preboot()
board_fbt_get_reboot_type()
enum fbt_reboot_type board_fbt_get_reboot_type(void)
{
enum fbt_reboot_type frt = FASTBOOT_REBOOT_UNKNOWN;
uint32_t loader_flag = IReadLoaderFlag();
int reboot_mode = loader_flag ? (loader_flag & 0xFF) : BOOT_NORMAL;
/* Feedback reboot mode to the kernel. */
ISetLoaderFlag(SYS_KERNRL_REBOOT_FLAG | reboot_mode);
if (SYS_LOADER_ERR_FLAG == loader_flag) {
loader_flag = SYS_LOADER_REBOOT_FLAG | BOOT_LOADER;
reboot_mode = BOOT_LOADER;
}
if ((loader_flag & 0xFFFFFF00) == SYS_LOADER_REBOOT_FLAG) {
switch (reboot_mode) {
case BOOT_NORMAL:
printf("reboot normal.\n");
frt = FASTBOOT_REBOOT_NORMAL;
break;
case BOOT_LOADER:
#ifdef CONFIG_CMD_ROCKUSB
printf("reboot rockusb.\n");
do_rockusb(NULL, 0, 0, NULL);
#endif
break;
#ifdef CONFIG_CMD_FASTBOOT
case BOOT_FASTBOOT:
printf("reboot fastboot.\n");
frt = FASTBOOT_REBOOT_FASTBOOT;
break;
#endif
case BOOT_NORECOVER:
printf("reboot no recover.\n");
frt = FASTBOOT_REBOOT_NORECOVER;
break;
case BOOT_RECOVER:
printf("reboot recover.\n");
frt = FASTBOOT_REBOOT_RECOVERY;
break;
case BOOT_WIPEDATA:
case BOOT_WIPEALL:
printf("reboot wipe data.\n");
frt = FASTBOOT_REBOOT_RECOVERY_WIPE_DATA;
break;
case BOOT_CHARGING:
printf("reboot charge.\n");
frt = FASTBOOT_REBOOT_CHARGE;
break;
default:
printf("unsupport reboot type %d\n", reboot_mode);
break;
}
} else {
printf("normal boot.\n");
}
/* Normal boot mode */
if (reboot_mode == BOOT_NORMAL) {
#ifdef CONFIG_RK_SDCARD_BOOT_EN
if (StorageSDCardUpdateMode()) {
/* detect sd card update, audo entern recovery */
frt = FASTBOOT_REBOOT_RECOVERY;
}
#endif
#ifdef CONFIG_RK_UMS_BOOT_EN
if (StorageUMSUpdateMode()) {
/* detect ums update, audo entern recovery */
frt = FASTBOOT_REBOOT_RECOVERY;
}
#endif
}
return frt;
} |

1524

被折叠的 条评论
为什么被折叠?



