1. 程式人生 > >AndroidLinux Kernel and driver

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_driverdriver;
 };
  #define module_spi_driver(__spi_driver) \
  module_driver(__spi_driver, spi_register_driver, \
  spi_unregister_driver)