UEFI在高通平臺實現
UEFI(Unified extensible firmware interface)統一的可擴充套件韌體介面,是一種詳細描述型別介面的標準。
可擴充套件韌體介面(Extensible Firmware Interface,EFI)是 Intel 為 PC 韌體的體系結構、介面和服務提出的建議標準。其主要目的是為了提供一組在 OS 載入之前(啟動前)在所有平臺上一致的、正確指定的啟動服務,被看做是有近20多年曆史的 BIOS 的繼任者。
既然UEFI是為了取代BIOS的,自然有他自己的優勢。
BIOS是彙編實現的,採用的是16bit 真實模式定址方式,最大支援的記憶體只有1M,程式碼易讀性以及實現的功能都受到限制,而且移植起來不方便。
UEFI克服了上述的所有缺點,採用C語言實現,分層,模組化設計,實現了CPU以及驅動的無關性。UEFI可以理解為一個完整的系統,包含了上電時序,驅動實現,os環境建立(這個os可以理解為UEFI執行獨有的os,非linux,windows),應用程式。其中應用程式支援網路配置,類shell環境,fastboot,linux loader等。
其中UEFI中涉及的名詞縮寫:
Unified extensible firmware interface (UEFI)
SEC:security
PEI:pre EFI initialization
DXE
BDS:Boot Dev Select
TSL:Transient System Load
RT: runtime
AL:after life
GUID:Globally Unique Identifier
CSM : Compatibility Support Module
TCG:Trusted Computing Group
PE:portable executable
COFF:Common object file format
FV:Firmware Volume
對於高通的平臺UEFI的實現分成了兩部分:
1. XBL
2. ABL包含了晶片無關的應用,比如fastboot和linuxloader
UEFI程式碼中大量使用了protocol概念,這個protocol其實指的是驅動,包含了驅動函式指標和資料。以rampatition為例:
boot_images/QcomPkg/Include/Protocol/EFIRamPartition.h中聲明瞭了rampatition protocol:
typedef
EFI_STATUS
(EFIAPI *EFI_RAMPARTITION_GETRAMPARTITIONS)(
INEFI_RAMPARTITION_PROTOCOL* This,
OUTRamPartitionEntry *RamPartitions,
IN OUT UINT32 *NumPartition
);struct_EFI_RAMPARTITION_PROTOCOL {
UINT64 Revision;
EFI_RAMPARTITION_GETRAMPARTITIONVERSION GetRamPartitionVersion;
EFI_RAMPARTITION_GETHIGHESTBANKBIT GetHighestBankBit;
EFI_RAMPARTITION_GETRAMPARTITIONS GetRamPartitions;
};
在boot_images/QcomPkg/Drivers/EnvDxe/EnvDxe.c中實現了該協議
STATIC EFI_RAMPARTITION_PROTOCOL RamPartitionProtocol =
{
EFI_RAMPARTITION_PROTOCOL_REVISION,
EFI_GetRamPartitionVersion,
EFI_GetHighestBankBit,
EFI_GetRamPartitions
};
在XBL中實現了protocol,也就是驅動,在ABL中可以直接使用。
UEFI啟動流程:
對於高通平臺啟動過程依次為PBL->XBL->ABL.
一般使用者定製化主要集中在ABL中,這部分程式碼樹如下:
Andrioid程式碼路徑bootable/bootloader/edk2/QcomModulePkg
├── Application
│ └── LinuxLoader
│ ├── LinuxLoader.c
│ └── LinuxLoader.inf
├── Include
│ ├── Library
│ │ ├──BoardCustom.h
│ │ ├── Board.h
│ │ ├──BootImage.h
│ │ ├──BootLinux.h
│ │ ├──BootStats.h
│ │ ├──Decompress.h
│ │ ├──DeviceInfo.h
│ │ ├── DrawUI.h
│ │ ├──FastbootMenu.h
│ │ ├── Fonts.h
│ │ ├── KeyPad.h
│ │ ├──LinuxLoaderLib.h
│ │ ├── list.h
│ │ ├──LocateDeviceTree.h
│ │ ├──MenuKeysDetection.h
│ │ ├──PartitionTableUpdate.h
│ │ ├── Recovery.h
│ │ ├── Reg.h
│ │ ├──ShutdownServices.h
│ │ ├──StackCanary.h
│ │ ├──UnlockMenu.h
│ │ ├──UpdateCmdLine.h
│ │ ├──UpdateDeviceTree.h
│ │ └──VerifiedBootMenu.h
│ └── Protocol
│ ├── EFICardInfo.h
│ ├── EFIChargerEx.h
│ ├── EFIChipInfo.h
│ ├── EFIChipInfoTypes.h
│ ├── EFIEraseBlock.h
│ ├── EFILimits.h
│ ├── EFIMdtp.h
│ ├── EFIPlatformInfo.h
│ ├── EFIPlatformInfoTypes.h
│ ├── EFIPmicPon.h
│ ├── EFIPmicVersion.h
│ ├── EFIQseecom.h
│ ├── EFIRamPartition.h
│ ├── EFIResetReason.h
│ ├── EFIRng.h
│ ├── EFIScmModeSwitch.h
│ ├── EFIUsbDevice.h
│ ├── EFIUsbEx.h
│ ├── EFIVerifiedBoot.h
│ └── UsbEx.h
├── Library
│ ├── BootLib
│ │ ├── Board.c
│ │ ├──BootLib.inf
│ │ ├──BootLinux.c
│ │ ├──BootStats.c
│ │ ├──Decompress.c
│ │ ├──DeviceInfo.c
│ │ ├── DrawUI.c
│ │ ├──FastbootMenu.c
│ │ ├── KeyPad.c
│ │ ├──LinuxLoaderLib.c
│ │ ├──LocateDeviceTree.c
│ │ ├──MenuKeysDetection.c
│ │ ├──PartitionTableUpdate.c
│ │ ├── Recovery.c
│ │ ├──ShutdownServices.c
│ │ ├──UnlockMenu.c
│ │ ├──UpdateCmdLine.c
│ │ ├──UpdateDeviceTree.c
│ │ └──VerifiedBootMenu.c
│ ├── FastbootLib
│ │ ├──FastbootCmds.c
│ │ ├──FastbootCmds.h
│ │ ├──FastbootLib.inf
│ │ ├──FastbootMain.c
│ │ ├──FastbootMain.h
│ │ ├──MetaFormat.h
│ │ ├──SparseFormat.h
│ │ ├──UsbDescriptors.c
│ │ └──UsbDescriptors.h
│ ├── StackCanary
│ │ ├──StackCanary.c
│ │ └──StackCanary.inf
│ └── zlib
│ ├── adler32.c
│ ├── inffast.c
│ ├── inffast.h
│ ├── inffixed.h
│ ├── inflate.c
│ ├── inflate.h
│ ├── inftrees.c
│ ├── inftrees.h
│ ├── zconf.h
│ ├── zlib.h
│ ├── zlib.inf
│ ├── zutil.c
│ └── zutil.h
├──QcomModulePkg.dec
├──QcomModulePkg.dsc
├──QcomModulePkg.fdf
└── Tools
├── app_path_set.cmm
├── check_paths.cmm
├── debug_app.cmm
├── elf_tools.py
├── image_header.py
├── load_uefi_dump.cmm
├── log_save.cmm
├── symbol_Load.cmm
└── uefi_core_path_set.cmm
這部分裡面主要是支援linuxloader 用來載入linux,以及fastboot。使用者修改主要集中在這兩個部分,入口函式LinuxLoaderEntry。
UEFI中用到幾種字尾格式的檔案說明:
fdf:flash definitionfile,描述flash分割槽地址範圍
dec:package declarationfile,定義了不同模組的GUID資訊
dsc:description file,主要包含需要用到的所有inf檔案
inf:單個模組的編譯資訊,類似makefile
efi :最終編譯生成的UEFI可執行檔案