UEFI与固件程序设计 Tel:69589584 Email:wang.box@163.com 同济大学软件学院 Agenda EFI Driver Development EFI Application Development EFI Drivers EFI Driver Model Supports complex bus hierarchies – Follows the organization of physical/electrical architecture of the machine Driver Binding Protocol provides flexibility – Function to match drivers to devices – Driver version management – Hot-plug and unload support Drivers not tied to FLASH – Can be loaded from EFI System Partition Extensible – Able to extend to future bus and device types EFI Drivers Driver Design Steps Determine Driver Type Identify Consumed I/O Protocols Identify Produced I/O Protocols Identify EFI Driver Model Protocols Identify Additional Driver Features Identify Target Platforms – x86 – x64 – Itanium Processor Family – EFI Byte Code (EBC) EFI Drivers What Type of Driver is Being Designed? EFI Images Drivers Service Drivers EFI Driver Model Initializing Drivers Root Bridge Drivers Device BusBus Hybrid Device Drivers Drivers Drivers Drivers Drivers EFI 1.02 Drivers Applications OS Loaders EFI Drivers Drivers Service Drivers Device Drivers EFI Driver Model Initializing Drivers Root Bridge Drivers Manages a Controller or Peripheral Device Start() Does Not Create Any Child Handles Start() Produces One or More I/O Protocols – Installed onto the Device’s Controller Handle Examples: PCI Video Adapters USB Host Controllers USB Keyboards / USB Mice PS/2 Keyboards / PS/2 Mice Bus Drivers Hybrid Drivers Device Drivers EFI Drivers Drivers Service Drivers Bus Drivers EFI Driver Model Initializing Drivers Root Bridge Drivers Manages and Enumerates a Bus Controller Start() Creates One or More Child Handles Start() Produces Bus Specific I/O Protocols – Installed onto the Bus’s Child Handles Examples: PCI Network Interface Controllers Serial UART Controllers Bus Drivers Hybrid Drivers Device Drivers EFI Drivers Drivers Service Drivers Hybrid Drivers EFI Driver Model Initializing Drivers Root Bridge Drivers Bus Drivers Manages and Enumerates a Bus Controller Start() Creates One or More Child Handles Start() Produces Bus Specific I/O Protocols – Installed onto the Bus’s Controller Handle – Installed onto Bus’s Child Handles Examples: PCI SCSI Host Controllers PCI Fiber Channel Controllers Hybrid Drivers Device Drivers EFI Drivers Drivers Service Drivers Service Drivers EFI Driver Model Initializing Drivers Root Bridge Drivers Bus Drivers Does Not Manage Hardware Provides Services to other Drivers Does not support Driver Binding Protocol Typically installs protocols in driver entry point Creates One or More Service Handles Produces Service Specific Protocols – Installed onto Service Handles Examples: EFI Decompress Protocol EFI Byte Code Virtual Machine Boot Integrity Services (BIS) Hybrid Drivers Device Drivers EFI Drivers Drivers Service Drivers Initializing Drivers Initializing Drivers Typically Touches Hardware Performs One Time Initialization Operations Does Not Create Any Handles Does Not Produce Any Protocols Unloaded When Finished Examples: None EFI Driver Model Root Bridge Drivers Bus Drivers Hybrid Drivers Device Drivers EFI Drivers Drivers Service Drivers Root Bridge Drivers Initializing Drivers Typically Manages Part of Core Chipset Directly Touches Hardware Creates One or More Root Bridge Handles Produces Root Bridge I/O Protocols Installed onto new Root a Bridge Handles Examples: PCI Host Bridge EFI Driver Model Root Bridge Drivers Bus Drivers Hybrid Drivers Device Drivers EFI Drivers What I/O Protocols are Consumed? FLASH USB Peripherals USB I/O Protocol Device Path Protocol PCI Adapters PCI I/O Protocol Device Path Protocol EFI Drivers What I/O Protocols are Produced? FLASH SCSI Pass Thru Protocol and Block I/O Protocol SCSI SCSI RAID Fiber Channel EFI Drivers What I/O Protocols are Produced? FLASH UNDI and Network Interface Identifier Protocol Network Interface Controller (NIC) EFI Drivers Driver Design Checklist EFI Drivers Running EFI drivers ConnectController() Called from Boot Manager or during load Precedence rules are applied Context override Platform override Bus override Version number Order of which drivers are installed into handle database is not deterministic DisconnectController() Must test and implement Stop() EFI Drivers Implement, Test & Debug See Backup Slides for Details Required for IHVs Optional for OEM/ODMs Test Functions with EFI Shell Commands Check for Leaks with EFI Shell Commands Install EFI Compliant Operating System Boot EFI Compliant Operating System Debug Macros Identify Critical Failures Use Same Techniques on all CPU Types x86, x64, Itanium Processor Family, EBC Driver Guidelines Driver Guidelines Don’t touch hardware in Driver Entry Keep Supported() small and simple Move complex I/O into Start() and Stop() Start() / Stop() mirror each other InstallProtocolInterface() UninstallProtocolInterface() OpenProtocol() CloseProtocol AllocatePages() FreePages() AllocatePool() FreePool() Driver Entry / Unload() mirror each other Driver Guidelines PCI Device Drivers Always Call PciIo->Attributes() Advertises Dual Address Cycle Capability Save and Enable Attributes in Start() Disable Attributes in Stop() DMA – Bus Master Write Operations Must call PciIo->Flush() DMA – Setting Up with PciIo->Map() Do Not Use Returned DeviceAddress Not all chipsets have 1:1 bus/system mappings Driver Guidelines PCI Device Drivers – Start() Status = PciIo->Attributes( PciIo, EfiPciIoAttributeOperationGet, 0, &ControllerContext->OriginalPciIoAttributes ); if (EFI_ERROR (Status)) { // Error Handling } Status = PciIo->Attributes( PciIo, EfiPciIoAttributeOperationEnable, (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE), 0, NULL ); if (EFI_ERROR (Status)) { // Error Handling } Save Original and Enable Driver Guidelines PCI Device Drivers – Stop() Status = PciIo->Attributes( PciIo, EfiPciIoAttributeOperationSet, &ControllerContext->OriginalPciIoAttributes NULL ); if (EFI_ERROR (Status)) { // Error Handling } Restore Original Driver Guidelines Preventing Alignment Faults VOID ScsiDeviceNodeInit ( IN OUT SCSI_DEVICE_PATH *ScsiDeviceNode, IN UINT16 Pun, IN UINT16 Lun ) { ScsiDeviceNode->Scsi.Header.Type = MESSAGING_DEVICE_PATH; ScsiDeviceNode->Scsi.Header.SubType = MSG_SCSI_DP; SetDevicePathNodeLength (&ScsiDeviceNode->Scsi.Header, sizeof(SCSI_DEVICE_PATH)); ScsiDeviceNode->Scsi.Pun = Pun; ScsiDeviceNode->Scsi.Lun = Lun; } BAD ScsiDeviceNode may not be aligned Driver Guidelines Preventing Alignment Faults VOID ScsiDeviceNodeInit ( IN OUT SCSI_DEVICE_PATH *ScsiDeviceNode, IN UINT16 Pun, IN UINT16 Lun ) { SCSI_DEVICE_PATH MyDeviceNode; GOOD MyDeviceNode.Scsi.Header.Type = MESSAGING_DEVICE_PATH; MyDeviceNode.Scsi.Header.SubType = MSG_SCSI_DP; SetDevicePathNodeLength (&MyDeviceNode.Scsi.Header, sizeof(SCSI_DEVICE_PATH)); MyDeviceNode.Scsi.Pun = Pun; MyDeviceNode.Scsi.Lun = Lun; gBS->CopyMem (ScsiDeviceNode, &MyDeviceNode, sizeof(SCSI_DEVICE_PATH)); } gBS->CopyMem() handles all alignments MyDeviceNode is aligned Driver Guidelines Use EFI Driver Library Functions CHILD_DEVICE Child; OK Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (CHILD_DEVICE), &Child ); if (EFI_ERROR (Status)) { return Status; } gBS->SetMem (Child, sizeof (CHILD_DEVICE), 0); CHILD_DEVICE Child; GOOD Child = EfiLibAllocateZeroPool (sizeof (CHILD_DEVICE)); if (Child == NULL) { return EFI_OUT_OF_RESOURCES; } Library Functions Simplify Source Code Library Functions May Reduce Size Driver Guidelines EFI Device Paths EFI_DRIVER_BINDING.Start() Child->DevicePath = EfiAppendDevicePathNode ( ControllerDevicePath, ChildDevicePathNode ); if (Child->DevicePath == NULL) { return(EFI_OUT_OF_RESOURCES); } EFI_DRIVER_BINDING.Stop() gBS->FreePool (Child->DevicePath); Parent Device Path is Opaque Not Parsed by Bus Drivers Driver Guidelines Bus Walk Tips Use LocateHandleBuffer(Bus I/O Protocol) Do not scan PCI configuration space Implement support for RemainingDevicePath Highly recommended for all bus drivers (i.e. SCSI, Fibre Channel, etc.) Allows bus driver to bypass full enumeration. Reduces boot time Driver Guidelines Component Name Protocol Limit Lengths of Names to 40 Unicode Characters Include Driver Name and Version Number UNDI Driver (Network Interface Controller) Typically the Name of the PCI Controller MAC Node Produced by an UNDI Driver Identify Location of Physical Connector on NIC PCI Slots Identify Physical Location of PCI Slots in the System SCSI / SCSI RAID / Fiber Channel Controller - Typically name of the PCI Controller Channel - Identify Physical Location of the SCSI Channel Disk - Use Results from INQUIRY Command Driver Guidelines Option ROM Size Reduction Use EFI Compression Compile with EFI Byte Code Compiler Single Binary for x86, x64 and Itanium Smaller than Itanium Binaries Comparable to x86 Binaries Compresses Well ~ 50% Driver Guidelines How To Improve Portability Do Not Assume Max Number of Children Do Not Use Fixed Memory Addresses Do Not Use Assembly Do Not Use Floating Point Arithmetic Some Minor EBC Porting Considerations Bus Drivers Should Support Producing 1 Child at a time if possible (improves boot performance) Driver Guidelines Improve Portability Driver Writer’s Guide EFI Driver Writer’s Guide Captures Practical Experiences Use as a Recipe Book Must Read for all EFI Driver Developers Living Document Content Based on Industry Feedback Updated as Techniques are Refined Updated as New Technologies are Introduced Driver Writer’s Guide General Topics Overview of EFI Concepts EFI Services Commonly Used by EFI Drivers Rarely Used by EFI Drivers Should Not Be Used by EFI Drivers General Driver Design Guidelines Classes of EFI Drivers Driver Entry Point Private Context Data Structures EFI Driver Model Protocols Driver Writer’s Guide Platform Specific Topics PCI Driver Guidelines USB Driver Design Guidelines SCSI Driver Design Guidelines Size Optimizations Speed Optimizations Itanium Processor Family Considerations EFI Byte Code Considerations Building/Testing/Debugging EFI Drivers Driver Writer’s Guide Benefits of following EFI Driver Guidelines Following EFI Driver Guidelines Improves Portability, Quality, and Interoperability Reduces Implementation Effort May Increase Performance May Reduce FLASH Overhead EFI Driver Writer’s Guide Helps Improve EFI Drivers Summary Good Designs Save Time and Money Many Tools Available to Test and Debug Using Driver Guidelines Improves Portability Compile in EBC to have one driver image to support x86, x64 and Itanium. Further Information http://developer.intel.com/technology/EFI EFI Web site for information, IDF presentations and EFI Driver Writer’s Guide http://www.uefi.org Website for Unified EFI Forum Back up Required Materials for IHVs Optional Materials for OEMs Agenda Introduction EFI Shell EFI Toolkit 3rd Party Libraries What are EFI Applications? EFI Applications extend firmware No hardware dependence No OS dependence Portable across platforms IA-32, Intel® 64, IA-64 Enables rapid application development What is an EFI Application? An EFI Loadable Image Loaded by EFI loader just like drivers Does not register protocols like drivers do Consumes protocols Typically user driven (exits when task completed) Same set of interfaces available as drivers have Can be used for Platform diagnostics Factory diagnostics Utilities Driver prototyping ‘Platform’ applications EFI Shell An EFI Application Interactive Console Interface Application Launch Load EFI Drivers Scripting Capability Automatic execution of startup script file Console redirection to files Open Source located on http://efi-shell.tianocore.org project EFI Toolkit Components Utilities C Library Network Stack Platform Management Compression Database Source Included Useful tools for EFI application development Open Source located on http://efi-toolkit.tianocore.org project Programming Models Native EFI Model Uses only EFI constructs Access to all EFI constructs Smaller code size Portability Model Familiar programming interfaces Easier to port ANSI/POSIX based programs Larger binary image A single program can use both EFI Toolkit Integration Database Hardware Management Compress Network C Library Utilities EFI EFI API C Library FreeBSD Port ANSI/POSIX compliant System I/O - open(), read(), write(), close(), stat() Standard I/O - fopen(), printf(), gets(), … String/Char - strcmp(), isascii(), atoi(), … Memory - malloc(), free(), realloc(), … Time/Date - time(), asctime(), ctime(), … Math - sqrt(), pow(), sin(), log(), … EFI Library “Lite Weight” C Library like functions String Functions Memory Support Functions CRC Support Functions Text I/O Functions Math Functions Spin Lock Functions Specific EFI functions Handle and Protocol Support Functions Device Path Support Functions Network Components Port of FreeBSD TCP/IP stack Supports standard protocols IPv4, ICMP, ARP, UDP, TCP Socket library interface Implemented as an EFI protocol Miscellaneous SMBIOS Library Library routines for parsing SMBIOS tables Database btree Hashing Compression General purpose compression/decompression Gzip functionality Utilities Network utilities FTP client and server, ping Text editor Scripting interpreter (Python) Sample applications EFI Hello.c #include "efi.h" EFI_STATUS InitializeHelloApplication ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { UINTN Index; SystemTable->ConOut->OutputString(SystemTable->ConOut, L”Hello application started\n"); SystemTable->ConOut->OutputString(SystemTable->ConOut, L"\n\r\n\r\n\rHit any key to exit this image\n\r"); SystemTable->BootServices->WaitForEvent( 1, &(SystemTable->ConIn->WaitForKey), &Index); SystemTable->ConOut->OutputString(SystemTable->ConOut, L"\n\r\n\r"); return EFI_SUCCESS; } EFI Library Hello.c #include "efi.h" #include "efilib.h" EFI_STATUS InitializeHelloLibApplication ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { InitializeLib (ImageHandle, SystemTable); Print(L"\n\n\nHelloLib application started\n\n\n"); Print(L"\nHit any key to exit this image\n"); WaitForSingleEvent(ST->ConIn->WaitForKey,0); ST->ConOut->OutputString (ST->ConOut, L"\n\r\n\r"); return EFI_SUCCESS; } C Library Hello.c #include <atk_libc.h> #include <stdio.h> EFI_STATUS InitializeHelloLibCApplication ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { InitializeLib(ImageHandle, SystemTable); printf("Hello LibC application started\n\n\n"); printf("Hit C/R to exit this image\n"); return( getchar() ); } C Library Hello.c #include <atk_libc.h> #include <stdio.h> int main (int argc, char **argv ) { printf("Hello LibC application started\n\n\n"); printf("Hit C/R to exit this image\n"); return( getchar() ); } C++ Support No direct support No Global constructors and destructors New and Delete can be mapped to malloc/free Portable Embedded Graphics Portable Embedded Graphics Portable graphics library for EFI Similar windowing components (widgets) Dialog boxes Progress bars, scroll bars Text boxes Window Management Fonts Bitmaps, JPEG, … Contact Swell Software http://www.swellsoftware.com PEG Components Summary EFI Applications extend firmware Provides system independence in the pre-boot space Hardware Operating System Platform IA-32, Intel® 64, and IA-64 Large library support EFI Shell provides convenient launch point Further Information https://efi-toolkit.tianocore.org/ EFI Web site for EFI Toolkit download https://www.TianoCore.org Website for EFI open source resources EFI Developer Kit (EDK) Nt32 emulation environment EFI Shell Source http://www.swellsoftware.com Portable Embedded Graphics toolkit http:/uefi.org UEFI Specification