1. Android 系统框架
1)应用程序层
2)应用程序框架层
3)系统运行库层
a)系统库
b)Android运行时
4)Linux内核层
Android 系统启动过程
Power on Sequence
2. Bootloader--EDK2 UEFI boot
2.1 UEFI boot flow-Sec阶段
SEC(Security Phase)阶段是平台初始化的第一个阶段,计算机系统加电后进入这个阶段。
1)接收并处理系统启动和重启信号
2)初始化临时存储区域
3)作为可信系统的根
4)传递系统参数给下一阶段(即PEI)
代码路径:
EDK2/ArmPlatformPkg/Sec/Arm/SecEntryPoint.S JMPT to Sec C code( CEntryPoint)
EDK2/ArmPlatformPkg/Sec/Sec.c (CEntryPoint)
EDK2/CoreBootModulePkg/SecCore/SecMain.c (SecStartup() ->
SecStartupPhase2 ->
FindAndReportEntryPoint( … ,&PeiCoreEntryPoint)
(*PeiCoreEntryPoint) (SecCoreData, …)
2.2 UEFI boot flow-PEI阶段
PEI执行流程
PEI(Pre-EFI Initialization)阶段资源仍然十分有限,内存到了PEI后期才被初始化,其主要功能是为DXE准备执行环境,将需要传递到DXE的信息组成HOB(Handoff Block)列表,最终将控制权转交到DXE手中。
代码路径
EDK2/Mdepkg/Library/PeiCoreEntryPoint/ PeiCoreEntryPoint.inf / .c
EDK2/MdeModulePkg/Core/Pei/PeiMain/PeiMian.c ---PeiCore() ->
LeadDxe IPL PPI—>
PeiServiceLocatePpt(&EfiDxeIplPpiGuid, 0,Null, (Void **)&TempPtr.DxeIpl);
EDK2/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
PeimInitializeDxeIpl() - >
DxeLoadCore()
2.3 DXE执行流程
DXE(Driver Execution Environment)阶段执行大部分系统初始化工作,进入此阶段时,内存已经可以被完全使用,因而此阶段可以进行大量的复杂工作。从程序设计的角度讲,DXE阶段与PEI阶段相似,执行流程如图
代码路径:
EDK2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c DxeMain()
2.4 BDS阶段
BDS(Boot Device Selection)的主要功能是执行启动策略,其主要功能包括:
初始化控制台设备。
加载必要的设备驱动。
根据系统设置加载和执行启动项。
如果加载启动项失败,系统将重新执行DXE dispatcher以加载更多的驱动,然后重新尝试加载启动项。
用户选中某个启动项(或系统进入默认的启动项)后,OS Loader启动,系统进入TSL阶段。
EDK2/ArmPlatformPkg/Bds/Bds.c
EDK2/Universal/BdsDxe/BdsEntry.c
EDK2/ArmPlatformPkg/Bds/BootOption.c
EDK2/ArmPlatformPkg/Bds/BootLinux.c
bootloader/edk2/ArmPkg/Application/LinuxLoader/Arm/LinuxStarter.c
bootloader/edk2/ArmPkg/Application/LinuxLoader/AArch64/LinuxStarter.c ---
StartLinux()--> LinuxKernel(...KernelParamasAddress)
2.5 TSL –RT--AL阶段
TSL阶段
TSL(Transient System Load)是操作系统加载器(OS Loader)执行的第一阶段,在这一阶段OS Loader作为一个UEFI应用程序运行,系统资源仍然由UEFI内核控制。当启动服务的ExitBootServices()服务被调用后,系统进入Run Time阶段。
UEFI Shell是这个临时系统的人机交互界面。正常情况下,系统不会进入UEFI Shell,而是直接执行操作系统加载器
RT阶段
系统进入RT(Run Time)阶段后,系统的控制权从UEFI内核转交到OS Loader手中,UEFI占用的各种资源被回收到OS Loader,仅有UEFI运行时服务保留给OS Loader和OS使用。随着OS Loader的执行,OS最终取得对系统的控制权。
AL阶段
在RT阶段,如果系统(硬件或软件)遇到灾难性错误,系统固件需要提供错误处理和灾难恢复机制,这种机制运行在AL(After Life)阶段。UEFI和UEFI PI标准都没有定义此阶段的行为和规范。
3. Linux Kenel init flow
Start_Kernel:
kernel/init/main.c --start_kernel()
-> rest_init()
-> kernel_init()
-> kernel_init_freeable();
-> do_basic_setup() ,load_default_modules()
-> driver_init(), do_initcalls()
-> do_initcall_level()
-> do_one_initcall(fn)
----do_init_module() -> do_one_initcall(mod->init)
kernel/kernel/module.c----- load_module()
module_init:
module_init() defined in include\/linux/\module.h
fn是module_init的参数,fn是一个函数指针(函数名)。
module_init(fn)---> __initcall(fn) ---> device_initcall(fn) ---> __define_initcall(fn, 6)
所以当我们写module_init(fn)最终我们可以简化成以下内容(假设module_init的参数为test_init)
module_init(test_init) ---> __define_initcall(test_init, 6)
4. Linux driver
4.1 linux系统将设备分类
linux系统将设备分为3类:字符设备、块设备、网络设备。使用驱动程序
字符设备:
鼠标,键盘,串口,控制台,LED设备等。
块设备:
硬盘,磁盘,SD卡,U盘。
网络接口设备:WIFI,蓝牙等
Linux driver structure
Linux 字符驱动模型
STRUCT 定义文件路径
Kernel/include/linux/cdev.h define struct cdev , cdev_init, cdev_add, cdev_del, cdev_put
Kernel/include/linux/kobject.h define struct kobject ,kobject_init, kobject_add,kobject_del,
Kernel/include/linux/kdev.h
Kernel/include/linux/file.h define struct fd,
Kernel/include/linux/fs.h define stuct file_oprations ,inode_oprations, file (line915).
Kernel/include/linux/module.h define struct module,
Kernel/include/linux/device.h define device(line778), device_driver,
Kernel/include/linux/types.h typedef __u32 _kernel_dev_t, devt_t.
Module driver定义
Module_driver() ---defined in kernel /include/linux/device.h -> module_init(), module_exit()
Module_hid_drver() –defined in kenrel/include/linux/hid.h
Module_init() --defined in kenrel/include/linux/module.h
Linux字符驱动HID-LED驱动
路径:Kernel/drivers/hid/hid-led.c
static struct hid_driver hidled_driver = {
.name = "hid-led",
.probe = hidled_probe,
.id_table = hidled_table,
};
module_hid_driver(hidled_driver);
static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
ldev = devm_kzalloc(&hdev->dev, sizeof(*ldev), GFP_KERNEL);
ldev->buf = devm_kmalloc(&hdev->dev, MAX_REPORT_SIZE, GFP_KERNEL);
ret = hid_parse(hdev);
ldev->hdev = hdev;
mutex_init(&ldev->lock);
ret = hidled_init_rgb(&ldev->rgb[i], minor);
hid_info(hdev, "%s initialized\n", ldev->config->name);
...
return 0;
}
Platform driver-
kernel/include/linux/platform_device.h
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
Module driver define:
kernel/include/linux/device.h
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
I2C driver—
kernel/include/linux/i2c.h
#define module_i2c_driver(__i2c_driver) \ module_driver(__i2c_driver, i2c_add_driver,\
i2c_del_driver)
SPI driver define
kernel/include/linux/spi/spi.h
struct spi_driver {
const struct spi_device_id *id_table;
Int (*probe)(struct spi_device *spi);
Int (*remove)(struct spi_device *spi);
Void (*shutdown)(struct spi_device *spi);
Int (*suspend)(struct spi_device *spi, pm_message_t mesg);
Int (*resume)(struct spi_device *spi);
struct device_driver driver;
};
#define module_spi_driver(__spi_driver) \
module_driver(__spi_driver, spi_register_driver, \
spi_unregister_driver)