使用者工具

網站工具


uefi_learning

差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

Both sides previous revision 前次修改
下次修改
前次修改
uefi_learning [2024/04/07 11:17]
don
uefi_learning [2024/04/30 08:27] (目前版本)
don
行 1: 行 1:
 ====== UEFI 學習 ====== ====== UEFI 學習 ======
 +
 +[[https://uefi.org/specifications | UEFI specification download]]
 +
  
 {{:uefi_flow1.png|}} {{:uefi_flow1.png|}}
行 28: 行 31:
 |[PatchPcd]| 列出的Pcd 變量僅本模塊可用| |[PatchPcd]| 列出的Pcd 變量僅本模塊可用|
  
-1.[Defines]: +[[http://guidgen.com|GUID 的生成]] 
-性定义语法: + 
-性名 = 性值+1、[Defines]: 
 +性定義語法:\\ 
 +性名 = 性值 
 <code> <code>
 [Defines] [Defines]
行 41: 行 47:
   ENTRY_POINT                    = DxeMain    //必须,模块的入口函数   ENTRY_POINT                    = DxeMain    //必须,模块的入口函数
 </code> </code>
 +
 +
 +2、[Sources]塊:
 +此塊下的每一行表示一個檔,檔使用相對路徑
 +
 <code> <code>
 [Sources]    //一般情况下不指定特定编译项时,使用这个即可,适用于任何体系结构 [Sources]    //一般情况下不指定特定编译项时,使用这个即可,适用于任何体系结构
行 54: 行 65:
 TimerWin.c | MSFT    //指定编译器有效 TimerWin.c | MSFT    //指定编译器有效
 TimerLinux.c | GCC    //指定编译器有效 TimerLinux.c | GCC    //指定编译器有效
 +</code>
  
-[BuildOptions+3、[Packages]塊: 
-  # Enable STDARG for variable arguments +此塊下面列出了模組所引用到的所有包的聲明檔dec檔。如果在Sources塊內列出了原始檔案,在此塊下必須列出MdePkg/MePkg.dec,並放在此塊的首行
-  *_*_*_CC_FLAGS = -DHAVE_STDARG_H+
  
-  # Override MSFT build option to remove /Oi and /GL +4、[LibraryClasses]塊: 
-  MSFT:*_*_*_CC_FLAGS          = /GL- +此塊內列出了模組所要連結的所有庫模組(使用了庫的庫函數就要列出來)。庫定義在包的dsc檔中
-  INTEL:*_*_*_CC_FLAGS         = /Oi-+
  
-  # Oniguruma: potentially uninitialized local variable used +5、[BuildOptions]塊:\\ 
-  MSFT:*_*_*_CC_FLAGS /wd4701 /wd4703+5-1、語法: 
 +     [BuildOptions] 
 +     [編譯器家族] [$ (Target)][Tool_CHAIN_TAG][$ (Arch)]_[CC | DLINK]_FLAGS [= |==]選項
  
-  # Oniguruma: intrinsic function not declared +5-2、編譯器家族 
-  MSFT:*_*_*_CC_FLAGS /wd4164+     可以是MSFT(Visual Studio編譯器家族)、INTEL(Intel編譯器家族)、GCC(Gcc編譯器家族) 
 +     和 RVCT(ARM編譯器家族)中的一個 
 +     Target是DEBUG、RELEASE和*中的一個,*是萬用字元 
 +     TOOL_CHAIN_TAG是編譯器的名字,編譯器定義在Conf/tools_def.txt檔中,*表示對指定編譯器家族內的所有編譯器都有效 
 +     Arch是體系結構,可以是IA32、X64、IPF、EBC或ARM,*是萬用字元 
 +     CC表示編譯選項, 
 +     DLINK表示連結選項 
 +     =表示選項附加到預設選項後面, 
 +     ==表示僅使用所定義的選項,不用預設選項。它們後面是編譯選項或連接選項
  
-  # Oniguruma: old style declaration in st.c 
-  MSFT:*_*_*_CC_FLAGS = /wd4131 
  
-  # Oniguruma: 'type cast' : truncation from 'OnigUChar *' to 'unsigned int' +==== inf檔編譯運行 ====
-  MSFT:*_*_*_CC_FLAGS /wd4305 /wd4306+
  
-  # Oniguruma: nameless union declared in regparse.h +原始檔案,inf工程檔完成,想要編譯運行這個模組,需要將inf工程檔添加到dsc的[Components]部分,然後就可以使用build工具編譯\\ 
-  MSFT:*_*_*_CC_FLAGS = /wd4201+模組應用程式是如何被編譯成.efi文件的:\\ 
 +1、.c源碼檔先被編譯成目的檔案.obj\\ 
 +2、連接器將目的檔案*.obj和其他的庫連接成*.dll\\ 
 +3、GenFw工具將*.dll轉化成*.efi\\ 
 +這些過程都由build命令自動完成\\
  
-  # Oniguruma: 'type cast' : "int" to "OnigUChar", function pointer to "void *" +標準應用程式載入過程(efi檔載入)\\ 
-  MSFT:*_*_*_CC_FLAGS = /wd4244 /wd4054+1、將efi檔載入到記憶體\\ 
 +efi模組檔————gBS ->LoadImage()將efi檔載入到記憶體中生成image物件————gBS->StartImage(Image)啟動Image物件\\ 
 + 
 +  gBS 指向啟動服務表 global Boot Servers\\ 
 +  * gST 指向系統表 global System Table\\ 
 +  gRT 指向運行時服務表 global Running Time\\ 
 +  * gImageHandle 指向正在執行的驅動或應用程式\\ 
 + 
 +<code> 
 +EFI_STATUS 
 +LoadDriver( 
 +  IN CONST CHAR16   *FileName, 
 +  IN CONST BOOLEAN  Connect 
 +  ) 
 +
 +  EFI_HANDLE                    LoadedDriverHandle; 
 +  EFI_STATUS                    Status; 
 +  EFI_DEVICE_PATH_PROTOCOL      *FilePath; 
 +  EFI_LOADED_IMAGE_PROTOCOL     *LoadedDriverImage;
  
-  # Oniguruma: previous local declaration +  LoadedDriverImage   = NULL; 
-  MSFT:*_*_*_CC_FLAGS /wd4456+  FilePath            = NULL; 
 +  LoadedDriverHandle  = NULL; 
 +  Status              EFI_SUCCESS;
  
-  # Oniguruma: signed and unsigned mismatch/cast +*************************************
-  MSFT:*_*_*_CC_FLAGS = /wd4018 /wd4245 /wd4389+
  
-  # Oniguruma: tag_end in parse_callout_of_name +  // 
-  GCC:*_*_*_CC_FLAGS = -Wno-error=maybe-uninitialized+  // Use LoadImage to get it into memory 
 +  // 
 +  Status gBS->LoadImage( 
 +    FALSE, 
 +    gImageHandle, 
 +    FilePath, 
 +    NULL, 
 +    0, 
 +    &LoadedDriverHandle);
  
-  # Oniguruma: implicit conversion from 'UINTN' (aka 'unsigned long long') to 'long' +**********************************************
-  GCC:*_CLANG9_*_CC_FLAGS = -Wno-error=constant-conversion+
  
-  # Not add -Wno-error=maybe-uninitialized option for XCODE +    // 
-  # XCODE doesn't know this option +    // Make sure it is a driver image 
-  XCODE:*_*_*_CC_FLAGS =+    // 
 +    Status gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);
  
 + *************************************************
 + /*
 + * 找出可执行的程序镜像Image的入口函数并执行找到的入口函数, gBS->StartImage是个函数指针,实际指向CoreStartImage函数
 + */
 +    Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);
 +    if (EFI_ERROR(Status)) {
 +      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);
 +    } else {
 +      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);
 +    }
 +  }
 +**********************************************************
 +  return (Status);
 +}
 </code> </code>
  
 +2、進入鏡像image的入口函數
 +CoreStartImage的主要作用是調用鏡像的入口函數,在這裡面SetIump/LongJumps是為應用程式提供了一種錯誤處理機制。gBS->StartImage的核心是EntryPoint函數,它就是這個應用程式的入口函數,就是_ModuleEntryPoint函數,進入到這裡,代碼執行的控制權才轉交給我們的應用程式efi
  
 +<code>
 +EFI_STATUS
 +EFIAPI
 +CoreStartImage (
 +  IN EFI_HANDLE  ImageHandle,
 +  OUT UINTN      *ExitDataSize,
 +  OUT CHAR16     **ExitData  OPTIONAL
 +  )
 +{
 +  EFI_STATUS                    Status;
 +  LOADED_IMAGE_PRIVATE_DATA     *Image;
 +  LOADED_IMAGE_PRIVATE_DATA     *LastImage;
 +  UINT64                        HandleDatabaseKey;
 +  UINTN                         SetJumpFlag;
 +  EFI_HANDLE                    Handle;
 +
 +**************************************************************
 +  //
 +  // Set long jump for Exit() support
 +  // JumpContext must be aligned on a CPU specific boundary.
 +  // Overallocate the buffer and force the required alignment
 +  //
 +  Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
 +  if (Image->JumpBuffer == NULL) {
 +    //
 +    // Image may be unloaded after return with failure,
 +    // then ImageHandle may be invalid, so use NULL handle to record perf log.
 +    //
 +    PERF_START_IMAGE_END (NULL);
 +
 +    //
 +    // Pop the current start image context
 +    //
 +    mCurrentImage = LastImage;
 +
 +    return EFI_OUT_OF_RESOURCES;
 +  }
 +  Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
 +
 +  SetJumpFlag = SetJump (Image->JumpContext);
 +  //
 +  // The initial call to SetJump() must always return 0.
 +  // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
 +  //
 +  if (SetJumpFlag == 0) {
 +    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
 +    //
 +    // Call the image's entry point 核心
 +    //
 +    Image->Started = TRUE;
 +    Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
 +
 +******************************************************************
 +
 +  //
 +  // UEFI Specification - StartImage() - EFI 1.10 Extension
 +  // To maintain compatibility with UEFI drivers that are written to the EFI
 +  // 1.02 Specification, StartImage() must monitor the handle database before
 +  // and after each image is started. If any handles are created or modified
 +  // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must
 +  // be called with the Recursive parameter set to TRUE for each of the newly
 +  // created or modified handles before StartImage() returns.
 +  //
 +
 +**********************************************************************
 +
 +  //
 +  // Save the Status because Image will get destroyed if it is unloaded.
 +  //
 +  Status = Image->Status;
 +
 +**************************************************************************
 +  //
 +  // Done
 +  //
 +  PERF_START_IMAGE_END (Handle);
 +  return Status;
 +}
 +
 +_ModuleEntryPoint函数:
 +
 +EFI_STATUS
 +EFIAPI
 +_ModuleEntryPoint (
 +  IN EFI_PEI_FILE_HANDLE       FileHandle,
 +  IN CONST EFI_PEI_SERVICES    **PeiServices
 +  )
 +{
 +  if (_gPeimRevision != 0) {
 +    //
 +    // Make sure that the PEI spec revision of the platform is >= PEI spec revision of the driver
 +    //
 +    ASSERT ((*PeiServices)->Hdr.Revision >= _gPeimRevision);
 +  }
 +
 +  //
 +  // Call constructor for all libraries
 +  //
 +  ProcessLibraryConstructorList (FileHandle, PeiServices);
 +
 +  //
 +  // Call the driver entry point
 +  //
 +  return ProcessModuleEntryPointList (FileHandle, PeiServices);
 +}
 +</code>
 +
 +3、進入模組的入口函數
 +在_ModuleEntryPoint中,調用了ProcessModuleEntryPointList ,然後在build過程中,會解析inf檔,生成AutoGen.c檔,裡面查看ProcessModuleEntryPointList ,它調用了應用程式工程模組的真正入口函數,就是inf檔中指定的那個入口函數
 +
 +<code>
 +EFI_STATUS
 +EFIAPI
 +ProcessModuleEntryPointList (
 +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
 +  IN CONST EFI_PEI_SERVICES     **PeiServices
 +  )
 +
 +{
 +  return PcdPeimInit (FileHandle, PeiServices);
 +}
 +</code>
 +標準應用程式工程模組入口函式呼叫過程:\\
 +efi——LoadImage——StartImage——_ModuleEntryPoint——ProcessModuleEntryPointList ——inf中指定的入口函数\\
 +原文連結:https://blog.csdn.net/wangyongh/article/details/105345077
 +
 +
 +===== DSC 文件 =====
 +.inf 用于编译一个模块, 而.dsc 文件用于编译一个Package, 它包含了[Defines]、
 +[LibraryClasses]、[Components] 几个必需部分以及[PCD]、[BuildOptions] 等几个可选部分。
 +
 +
 +===== DEC 文件 =====
 +.dec 文件定义了公开的数据和接口,供其他模块使用。它包含了必需区块[Defines] 以及可选区块[Includes]、[LibraryClasses]、[Guids]、[Protocols]、[Ppis] 和[PCD] 几个部分。
 +.dec文件需要被调用模块.inf文件所包含。
  
  
行 154: 行 353:
 |FatPkg, FatBinPkg|FAT支持包。| \\                     |FatPkg, FatBinPkg|FAT支持包。| \\                    
 原文連結:https://blog.csdn.net/u011057409/article/details/117636656 原文連結:https://blog.csdn.net/u011057409/article/details/117636656
 +
 +
 +===== Build 參數 =====
 +
 +^ 命令參數縮寫 ^ 命令參數全稱 ^ 描述 ^
 +|-h |--help |show this help message and exit顯示説明資訊。|
 +|-a TARGETARCH |--arch=TARGETARCH|選擇目標平臺架構,該選項被指定會取代Conf/target.txt中的TARGET_ARCH。|
 +|-p PLATFORMFILE |--platform=PLATFORMFILE|通過指定.dsc檔指定要編譯的package,該選項將會Conf/target.txt文件ACTIVE_PLATFORM。|
 +|-m MODULEFILE| --module=MODULEFILE|Build the module specified by the INF file name argument。|
 +|-b BUILDTARGET| --buildtarget=BUILDTARGET |選擇編譯成DEBUG還是RELEASE。指定該選項後會取代target.txt文件中TARGET。|
 +|-t TOOLCHAIN| --tagname=TOOLCHAIN|選擇tools_def.txt中定義的編譯工具,例如VS2012:-t vs2012|
 +|-n THREADNUMBER| |編譯器使用的執行緒數量,指定後取代target.txt檔中MAX_CONCURRENT_THREAD_NUMBER指定的執行緒數量。 Less than 2 will disable multi-thread builds.小於2就禁止多執行緒編譯。|
 +|-u| --skip-autogen | Skip AutoGen step.跳過AutoGen這一步。|
 +|-c| --case-insensitive | Don't check case of file name.檔案名不區分大小寫。|
 +|-w| --warning-as-error | Treat warning in tools as error.將警告做錯誤處理。|
 +|-j LOGFILE| --log=LOGFILE| Put log in specified file as well as on console.將編譯資訊輸出到檔。|
 +|-s| --silent| Make use of silent mode of (n)make.使用沉默模式執行make或nmake。|
 +|-q| --quiet| Disable all messages except FATAL ERRORS.編譯過程中只顯示嚴重錯誤資訊。|
 +|-d DEBUG| --debug=DEBUG| Enable debug messages at specified level.在指定的級別啟用調試消息。|
 +|-D MACROS| --define=MACROS| Macro: "Name [= Value]".定義宏。|
 +| | ---version| show program's version number and exit。|
 +
  
 ===== UEFI API ===== ===== UEFI API =====
行 164: 行 385:
 ==== PcdGetPtr() ==== ==== PcdGetPtr() ====
 PcdGetPtr(PcdHelloWorldPrintString) 讀取在PcdHelloWorldPrintString 的字串。 PcdGetPtr(PcdHelloWorldPrintString) 讀取在PcdHelloWorldPrintString 的字串。
 +
 +==== AMI VEB ====
 +AMI VEB 基本上就是一堆 .CIF 檔案的集合
 +
 + 
uefi_learning.1712459822.txt.gz · 上一次變更: 2024/04/07 11:17 由 don