AndroidLinux Kernel and driver


  • Android system overview
  • Bootloader--EDK2 UEFI boot
  • Linux Kenel init flow
  • Linux driver

1.  Android 系统框架

 1)应用程序层
2)应用程序框架层
3)系统运行库层
    a)系统库
    b)Android运行时
4)Linux内核层


Android 系统启动过程


Power on Sequence

  • Power button is pressed and this launches the ROM code on the RPM
  • SBL1 code runs on RPM processor 
  • Bootloader on main apps processor runs  (LK or EDK2 UEFI boot)
  • Apps bootloader launches the HLOS (Android)
  • Initial startup code on HLOS launches other processors: Riva (wifi), DSPs, etc.

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)
 

猜你喜欢

转载自blog.csdn.net/weixin_41820883/article/details/80895166