bootloaderandroid
‘壹’ android bootloader lk阶段能读取文件吗
1.主要功能,红色部分是android特有的一些功能,如fastboot,recovery模式等:
* Variety of nand devices for bootup
* USB driver to enable upgrading images over usb ring development
* Keypad driver to enable developers enter ‘fastboot’ mode for image upgrades
* Display driver for debugging and splash screen
* Enable Android recovery image and image upgrades
2.配置dram内存大小,供linux kernel使用
The memory tags can be customized inlk/target/<target_name>/atags.c
3.fastboot模式,可以自行打开或者关闭
如,在boot中关闭按键或者usb 驱动,都可以达到此目的
相关文件
k/app/aboot/fastboot.c
lk/app/aboot/aboot.c
4.MTD block setting
可以配置各个mtd image 分区在如下 文件中
lk\target\tcc8900_evm\init.c
static struct ptentry board_part_list[]
5.打开或者关闭splash screen in the bootloader
DISPLAY_SPLASH_SCREEN功能可以来打开关闭
开机时候,boot会从’splash’ MTD分区中读取原始的文件到framebuffer中显示,所以也需要加载display 的驱动
入口函数在 kernel/main.c 中的 kmain(), 以下就来读读这一段 code.
void kmain(void)
{
// get us into some sort of thread context
thread_init_early();
// early arch stuff
arch_early_init();
// do any super early platform initialization
platform_early_init();
// do any super early target initialization
target_early_init();
dprintf(INFO, "welcome to lk/n/n");
// deal with any static constructors
dprintf(SPEW, "calling constructors/n");
call_constructors();
// bring up the kernel heap
dprintf(SPEW, "initializing heap/n");
heap_init();
// initialize the threading system
dprintf(SPEW, "initializing threads/n");
thread_init();
// initialize the dpc system
dprintf(SPEW, "initializing dpc/n");
dpc_init();
// initialize kernel timers
dprintf(SPEW, "initializing timers/n");
timer_init();
#if (!ENABLE_NANDWRITE)
// create a thread to complete system initialization
dprintf(SPEW, "creating bootstrap completion thread/n");
thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
// enable interrupts
exit_critical_section();
// become the idle thread
thread_become_idle();
#else
bootstrap_nandwrite();
#endif
}
In include/debug.h: 我们可以看到 dprintf 的第一个参数是代表 debug level.
/* debug levels */
#define CRITICAL 0
#define ALWAYS 0
#define INFO 1
#define SPEW 2
In include/debug.h:
view plainprint?
#define dprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dprintf(x); } } while (0)
所以 dprintf 会依 DEBUGLEVEL 来判断是否输出信息.
来看第一个 call 的函数: thread_init_early, define in thread.c
view plainprint?
void thread_init_early(void)
{
int i;
/* initialize the run queues */
for (i=0; i < NUM_PRIORITIES; i++)
list_initialize(&run_queue[i]);
/* initialize the thread list */
list_initialize(&thread_list);
/* create a thread to cover the current running state */
thread_t *t = &bootstrap_thread;
init_thread_struct(t, "bootstrap");
/* half construct this thread, since we're already running */
t->priority = HIGHEST_PRIORITY;
t->state = THREAD_RUNNING;
t->saved_critical_section_count = 1;
list_add_head(&thread_list, &t->thread_list_node);
current_thread = t;
}
#define NUM_PRIORITIES 32 in include/kernel/thread.h
list_initialize() defined in include/list.h: initialized a list
view plainprint?
static inline void list_initialize(struct list_node *list)
{
list->prev = list->next = list;
}
run_queue 是 static struct list_node run_queue[NUM_PRIORITIES]
thread_list 是 static struct list_node thread_list
再来要 call 的函数是: arch_early_init() defined in arch/arm/arch.c
view plainprint?
void arch_early_init(void)
{
/* turn off the cache */
arch_disable_cache(UCACHE);
/* set the vector base to our exception vectors so we dont need to double map at 0 */
#if ARM_CPU_CORTEX_A8
set_vector_base(MEMBASE);
#endif
#if ARM_WITH_MMU
arm_mmu_init();
platform_init_mmu_mappings();
#endif
/* turn the cache back on */
arch_enable_cache(UCACHE);
#if ARM_WITH_NEON
/* enable cp10 and cp11 */
uint32_t val;
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val));
val |= (3<<22)|(3<<20);
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val));
/* set enable bit in fpexc */
val = (1<<30);
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val));
#endif
}
现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit,
内存管理单元)提供支持。
CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地
址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PA
MMU将VA映射到PA是以页(Page)为单位的,32位处理器的页尺寸通常是4KB。例如,MMU可以通过一个映射项将VA的一页
0xb7001000~0xb7001fff映射到PA的一页0x2000~0x2fff,如果CPU执行单元要访问虚拟地址0xb7001008,则实际访问到的物理地
址是0x2008。物理内存中的页称为物理页面或者页帧(Page Frame)。虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页
表(Page Table)来描述的,页表保存在物理内存中,MMU会查找页表来确定一个VA应该映射到什么PA。
操作系统和MMU是这样配合的:
1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中
的什么位置。
2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令
控制MMU去做。
MMU除了做地址转换之外,还提供内存保护机制。各种体系结构都有用户模式(User Mode)和特权模式(Privileged Mode)之分,
操作系统可以在页表中设置每个内存页面的访问权限,有些页面不允许访问,有些页面只有在CPU处于特权模式时才允许访问,有些页面
在用户模式和特权模式都可以访问,访问权限又分为可读、可写和可执行三种。这样设定好之后,当CPU要访问一个VA时,MMU会检查
CPU当前处于用户模式还是特权模式,访问内存的目的是读数据、写数据还是取指令,如果和操作系统设定的页面权限相符,就允许访
问,把它转换成PA,否则不允许访问,产生一个异常(Exception)
常见的 segmentation fault 产生的原因:
用户程序要访问一段 VA, 经 MMU 检查后无权访问, MMU 会产生异常, CPU 从用户模式切换到特权模式, 跳转到内核代码中执行异常服务程序.
内核就会把这个异常解释为 segmentation fault, 将引发异常的程序终止.
‘贰’ 安卓系统上的解锁bl,BL是什么意思
BL锁即BootLoader,就是在操作系统内核运行之前运行的一段小程序,它负责在开机时加载硬件的初始化程序,并启动系统进程,就像电脑的bios一样。、
BootLoader对于手机很重要,如果BootLoader不能正常加载,手机就无法正常启动和使用。这也就是为什么BootLoader被锁的手机必须要破解,如果不破解BootLoader,就无法初始化手机硬件,手机也就无法使用。
(2)bootloaderandroid扩展阅读
手机两种启动模式下bootloader的作用:
1、自启动模式
在这种模式下,bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。
2、交互模式
在这种模式下,目标机上的bootloader将通过串口或网络等通行手段,从开发主机(Host)上下载内核映像等到RAM中。可以被bootloader写到目标机上的固态存储媒质,或者直接进入系统的引导,也可以通过串口接收用户的命令。