UEFI Driver 程序框架

一、前言

前面几节着重介绍了 UEFI 应用程序的编写。在之前的介绍中 UEFI Application 通常在 UEFI Shell 中运行,特点是执行完即退出,不常驻系统且不提供服务,而是查找并使用系统中的 Protocol 服务。本节简单介绍一下 UEFI 的另一种重要的程序类型,即 UEFI Driver。有过 Linux 开发经验的朋友可以很容易理解这种设计思想,即类比于 Linux 的应用层和驱动层分离的设计思想。应用程序不能直接访问硬件,而是基于驱动程序提供的服务访问硬件数据,以实现特定功能。具体来说,UEFI Application 查找和使用 Protocol,而 UEFI Driver 定义和安装 Protocol。

二、驱动框架

在 UEFI 中,驱动的编写和使用一般遵循如下的主线框架:

复制代码
Driver: Driver加载->识别设备->绑定设备->创建Handle->安装Protocol->
Application: 查找 Protocol 并使用

大多数情况下,驱动对应的是某个硬件设备,其作用是让本来是"死"的设备"活起来",使得软件层面上能够使用该设备的功能。这个很容易理解。那么如何让我们的驱动程序与硬件设备关联起来呢,这是理解 UEFI 驱动设计思想的关键。

为了实现 Driver 与设备的绑定,UEFI 中的每个 Driver 必须实现一个核心接口:

c 复制代码
typedef struct _EFI_DRIVER_BINDING_PROTOCOL {
    EFI_DRIVER_BINDING_SUPPORTED  Supported;
    EFI_DRIVER_BINDING_START      Start;
    EFI_DRIVER_BINDING_STOP       Stop;
    UINT32                        Version;				// 驱动版本号
    EFI_HANDLE                    ImageHandle;			// 产生此驱动绑定协议实例的驱动镜像句柄
    EFI_HANDLE                    DriverBindingHandle;	// 安装此驱动绑定协议实例的句柄,通常=ImageHandle
    								// 后两个参数写为 NULL,可以使用系统填写
} EFI_DRIVER_BINDING_PROTOCOL;

其中前三个是函数指针,这三个函数都需要我们在驱动中去一一实现。

  • Supported():用于判断当前驱动是否支持某个设备(传入设备抽象的 Handle)。当驱动加载的时候,UEFI 系统会遍历所有的设备 Handle,调用该函数,以找到该驱动支持的设备。
  • Start(): 当 Supported() 函数匹配成功后,会调用此函数。Start 函数的作用是在驱动与设备匹配成功之后利用设备 Protocol 对设备进行一系列初始化,并且可以在此为这个设备 Handle 安装新的我们自己实现的 Protocol。需要注意的是,在该驱动调用前,设备 Handle 上一般会有其他基本的 Protocol。
  • Stop(): 其作用是当卸载驱动时,对驱动使用的资源进行释放,并且卸载我们自定义的 Protocol。

*在刚开始学习的时候,很容易认为 Handle 一定对应的是具体的设备。实际上 Handle 有好多种,除了设备之外,每个驱动程序,应用程序本身,还有服务本身,都有自己的 Handle。但是驱动程序的编写一般只针对设备 Handle。

1. Supported 函数

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingSupported (
    IN EFI_DRIVER_BINDING_PROTOCOL *This,
    IN EFI_HANDLE                  Controller,
    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
);
  • This: 驱动绑定协议实例指针,指向自己所属的 EFI_DRIVER_BINDING_PROTOCOL 实例,类似于 C++ 的 this 指针。
  • Controller: 待检测的设备/控制器句柄,需要判断这个控制器是否被当前驱动支持。
  • RemainingDevicePath: 剩余设备路径(可选)。用于部分驱动(如总线驱动)的子设备枚举。

示例实现:

以 PCI 设备为例:

该函数用于检查控制器是否为该驱动所支持的 PCI 设备,是则返回成功,否则返回不支持,且不留下协议占用。

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingSupported (
    IN EFI_DRIVER_BINDING_PROTOCOL *This,
    IN EFI_HANDLE                  Controller,
    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
)
{
    EFI_STATUS Status;
    EFI_PCI_IO_PROTOCOL *PciIo;
    
    // 1. 如果需要处理 RemainingDevicePath(部分驱动场景)
    if (RemainingDevicePath != NULL && 
        !IsDevicePathValid(RemainingDevicePath, -1)) {
        return EFI_UNSUPPORTED;
    }
    
    // 2. 尝试打开控制器上的 PCI IO 协议
    Status = gBS->OpenProtocol(
        Controller,
        &gEfiPciIoProtocolGuid,
        (VOID **)&PciIo,
        This->DriverBindingHandle,  // 驱动镜像句柄
        Controller,
        EFI_OPEN_PROTOCOL_BY_DRIVER
    );
    
    if (EFI_ERROR(Status)) {
        return EFI_UNSUPPORTED;  // 没有 PCI IO,不支持
    }
    
    // 3. 进一步检查 PCI 配置空间(如 Vendor ID/Device ID)
    PCI_TYPE00 PciConfig;
    Status = PciIo->Pci.Read(
        PciIo,
        EfiPciIoWidthUint32,
        0,  // 偏移 0
        sizeof(PciConfig) / sizeof(UINT32),
        &PciConfig
    );
    
    if (EFI_ERROR(Status)) {
        goto CloseProtocol;
    }
    
    // 检查 VID/DID 是否匹配我的设备
    if (PciConfig.Hdr.VendorId == MY_VENDOR_ID && 
        PciConfig.Hdr.DeviceId == MY_DEVICE_ID) {
        Status = EFI_SUCCESS;
    } else {
        Status = EFI_UNSUPPORTED;
    }
    
CloseProtocol:
    // 必须关闭协议(只检查,不占用)
    gBS->CloseProtocol(
        Controller,
        &gEfiPciIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
    );
    
    return Status;
}

设备启动后,驱动的调用流程:

复制代码
系统启动 / 设备插入
    ↓
gBS->ConnectController(ControllerHandle)
    ↓
遍历所有已安装的 EFI_DRIVER_BINDING_PROTOCOL
    ↓
按 Version 排序(高版本优先)
    ↓
依次调用 Supported() 函数
    ↓
第一个返回 EFI_SUCCESS 的驱动
    ↓
调用该驱动的 Start() 函数

2. Start 函数

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingStart (
    IN EFI_DRIVER_BINDING_PROTOCOL *This,
    IN EFI_HANDLE                  Controller,
    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
);

示例实现:

该函数负责正式接管并初始化一个已被 Supported 验证通过的设备。主要的任务是 OpenProtocol 获得硬件访问能力,然后利用该能力初始化设备,随后安装自定义服务接口,暴露给上层应用。

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingStart (
    IN EFI_DRIVER_BINDING_PROTOCOL *This,
    IN EFI_HANDLE                  Controller,
    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
)
{
    EFI_STATUS Status;
    EFI_PCI_IO_PROTOCOL *PciIo;
    MY_DEVICE_PRIVATE_DATA *Private;
    
    // 1. 打开控制器上的 PCI I/O 协议(获得访问硬件的权限)
    Status = gBS->OpenProtocol(
        Controller,
        &gEfiPciIoProtocolGuid,
        (VOID **)&PciIo,
        This->DriverBindingHandle,
        Controller,
        EFI_OPEN_PROTOCOL_BY_DRIVER  // 驱动独占访问
    );
    if (EFI_ERROR(Status)) {
        return Status;
    }
    
    // 2. 为设备分配私有数据结构
    Private = (MY_DEVICE_PRIVATE_DATA *)AllocateZeroPool(
        sizeof(MY_DEVICE_PRIVATE_DATA)
    );
    if (!Private) {
        Status = EFI_OUT_OF_RESOURCES;
        goto CloseProtocol;
    }
    
    // 3. 初始化私有数据
    Private->Signature = MY_DEVICE_SIGNATURE;
    Private->PciIo = PciIo;
    Private->ControllerHandle = Controller;
    Private->DriverBindingHandle = This->DriverBindingHandle;
    
    // 4. 初始化设备硬件(通过 PciIo)
    Status = InitializeHardware(PciIo);
    if (EFI_ERROR(Status)) {
        goto FreePrivate;
    }
    
    // 5. 创建 I/O 抽象协议(供上层使用)
    Status = gBS->InstallMultipleProtocolInterfaces(
        &Controller,
        &gMyDriverIoProtocolGuid, &Private->IoProtocol,
        NULL
    );
    if (EFI_ERROR(Status)) {
        goto FreeHardware;
    }
    
    // 6. 可选:创建设备路径子节点(如果有子设备)
    if (RemainingDevicePath != NULL) {
        // 创建子控制器的逻辑
        CreateChildControllers(Controller, RemainingDevicePath);
    }
    
    return EFI_SUCCESS;
    
FreeHardware:
    // 清理硬件初始化
    CleanupHardware(PciIo);
    
FreePrivate:
    gBS->FreePool(Private);
    
CloseProtocol:
    gBS->CloseProtocol(
        Controller,
        &gEfiPciIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
    );
    
    return Status;
}

3. Stop 函数

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingStop (
    IN  EFI_DRIVER_BINDING_PROTOCOL *This,
    IN  EFI_HANDLE                  Controller,
    IN  UINTN                       NumberOfChildren,
    IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
);
  • NumberOfChildren: 子控制器的数量。
  • ChildHandleBuffer: 子控制器句柄数组(可选)。

示例实现:

该函数负责停止驱动对控制器的管理并释放所有已分配的资源。一般情况下它与 Start 函数完全对称,执行对应的清理流程。示例函数分类讨论了完全卸载整个设备驱动和保留部分子控制器两种情况。

c 复制代码
EFI_STATUS
EFIAPI
MyDriverBindingStop (
    IN  EFI_DRIVER_BINDING_PROTOCOL *This,
    IN  EFI_HANDLE                  Controller,
    IN  UINTN                       NumberOfChildren,
    IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
)
{
    EFI_STATUS Status;
    MY_DEVICE_PRIVATE_DATA *DevicePrivate;
    
    // 1. 获取设备私有数据(之前 Start 中安装的)
    Status = gBS->OpenProtocol(
        Controller,
        &gMyDriverDevicePrivateGuid,
        (VOID **)&DevicePrivate,
        This->DriverBindingHandle,
        Controller,
        EFI_OPEN_PROTOCOL_GET_PROTOCOL  // 只获取,不打开
    );
    if (EFI_ERROR(Status)) {
        return EFI_DEVICE_ERROR;
    }
    
    // 2. 根据是否有子控制器,执行不同逻辑
    if (NumberOfChildren == 0) {
        // 模式1:完全停止主控制器
        
        // 2.1 先停止并销毁所有子控制器
        while (DevicePrivate->ChildCount > 0) {
            gBS->StopController(
                DevicePrivate->ChildHandles[0],
                This->DriverBindingHandle,
                NULL  // 停止所有子控制器的子设备
            );
        }
        
        // 2.2 关闭在 Controller 上打开的所有协议
        gBS->CloseProtocol(
            Controller,
            &gEfiPciIoProtocolGuid,
            This->DriverBindingHandle,
            Controller
        );
        
        // 2.3 释放设备私有数据
        gBS->FreePool(DevicePrivate);
        
        // 2.4 从 Controller 上卸载私有数据协议(可选)
        gBS->UninstallMultipleProtocolInterfaces(
            Controller,
            &gMyDriverDevicePrivateGuid, DevicePrivate,
            NULL
        );
        
    } else {
        // 模式2:选择性停止指定的子控制器
        
        for (UINTN Index = 0; Index < NumberOfChildren; Index++) {
            EFI_HANDLE ChildHandle = ChildHandleBuffer[Index];
            MY_CHILD_PRIVATE_DATA *ChildPrivate;
            
            // 2.1 获取子设备私有数据
            Status = gBS->OpenProtocol(
                ChildHandle,
                &gMyDriverChildPrivateGuid,
                (VOID **)&ChildPrivate,
                This->DriverBindingHandle,
                Controller,
                EFI_OPEN_PROTOCOL_GET_PROTOCOL
            );
            if (EFI_ERROR(Status)) {
                continue;
            }
            
            // 2.2 清理子设备资源
            if (ChildPrivate->TimerEvent) {
                gBS->CloseEvent(ChildPrivate->TimerEvent);
            }
            
            // 2.3 关闭子设备上的协议
            gBS->CloseProtocol(
                ChildHandle,
                &gEfiDevicePathProtocolGuid,
                This->DriverBindingHandle,
                Controller
            );
            
            // 2.4 从子设备卸载私有数据
            gBS->UninstallMultipleProtocolInterfaces(
                ChildHandle,
                &gMyDriverChildPrivateGuid, ChildPrivate,
                NULL
            );
            
            // 2.5 释放子设备私有数据
            gBS->FreePool(ChildPrivate);
            
            // 2.6 从父设备的子控制器列表中移除
            RemoveChildFromList(DevicePrivate, ChildHandle);
        }
    }
    
    return EFI_SUCCESS;
}

Stop 函数与 Start 函数的对应关系:

复制代码
Start() 执行的操作              Stop() 必须执行的反向操作
OpenProtocol()          →     CloseProtocol()
AllocatePool()          →     FreePool()
CreateEvent()           →     CloseEvent()
InstallProtocol()       →     UninstallProtocol()
CreateChildHandle()     →     DestroyChildHandle()  // 通过 DisconnectController

4. 入口函数

我们前面介绍了驱动绑定协议,入口函数在驱动被加载时由固件调用,主要任务是注册我们定义好的驱动绑定协议,也就是通过 InstallMultipleProtocolInterfaces 将驱动绑定协议安装到该驱动的 ImageHandle 句柄上,使 UEFI 驱动模型能够识别并调用该驱动的 Supported/Start/Stop 接口。

c 复制代码
// 驱动全局变量
EFI_DRIVER_BINDING_PROTOCOL gMyDriverBinding = {
    MyDriverBindingSupported,
    MyDriverBindingStart,
    MyDriverBindingStop,
    0x10,                          // 驱动版本
    NULL,                          // 可选的镜像句柄
    NULL                           // 可选的驱动绑定句柄
};

// 驱动入口函数
EFI_STATUS
EFIAPI
MyDriverEntryPoint (
    IN EFI_HANDLE           ImageHandle,
    IN EFI_SYSTEM_TABLE     *SystemTable
)
{
    EFI_STATUS  Status;
    
    // 1. 保存系统表指针(供驱动其他地方使用)
    gST = SystemTable;
    gBS = SystemTable->BootServices;
    gImageHandle = ImageHandle;
    
    // 2. 初始化驱动绑定协议
    gMyDriverBinding.ImageHandle = ImageHandle;
    gMyDriverBinding.DriverBindingHandle = ImageHandle;
    
    // 3. 安装驱动绑定协议到镜像句柄
    Status = gBS->InstallMultipleProtocolInterfaces(
        &gMyDriverBinding.DriverBindingHandle,
        &gEfiDriverBindingProtocolGuid, &gMyDriverBinding,
        NULL
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((EFI_D_ERROR, "Failed to install Driver Binding Protocol: %r\n", Status));
        return Status;
    }
    
    // 4. 可选:安装组件名称协议(用于显示驱动名称)
    Status = gBS->InstallMultipleProtocolInterfaces(
        &gMyDriverBinding.DriverBindingHandle,
        &gEfiComponentNameProtocolGuid,  &gMyComponentName,
        &gEfiComponentName2ProtocolGuid, &gMyComponentName2,
        NULL
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((EFI_D_WARN, "Failed to install Component Name Protocol: %r\n", Status));
        // 不致命,继续执行
    }
    
    // 5. 驱动加载成功
    DEBUG((EFI_D_INFO, "MyDriver loaded successfully\n"));
    
    return EFI_SUCCESS;
}

三、示例程序

此示例是一个简化的 UEFI DXE 阶段 USB 设备驱动示例程序,它遵循 UEFI 驱动模型标准,通过实现驱动绑定协议中的 SupportedStartStop 三个核心函数来管理 USB 设备。程序从 SimpleUsbDriverEntryPoint 入口函数开始执行,首先将包含这三个函数指针的 EFI_DRIVER_BINDING_PROTOCOL 实例安装到当前驱动的镜像句柄上,从而向 UEFI 固件注册该驱动。当系统枚举到新的 USB 设备时,固件会调用 SimpleUsbDriverSupported 函数,该函数通过尝试以 BY_DRIVER 方式打开控制器上的 EFI_USB_IO_PROTOCOL 来验证设备是否为 USB 设备,检查完毕后立即关闭协议以避免占用。一旦确认支持,固件随即调用 SimpleUsbDriverStart 函数正式接管设备,在此阶段驱动会分配并初始化设备私有上下文结构体 SIMPLE_USB_DEVICE,长期打开 EFI_USB_IO_PROTOCOL 以获得硬件访问权,并通过该协议读取 USB 设备描述符,将设备的厂商标识、产品标识及类别等信息打印到调试输出中。最后,当驱动需要被卸载或设备被移除时,SimpleUsbDriverStop 函数会被触发,负责关闭已打开的 USB I/O 协议并释放之前分配的所有内存资源,完成整个驱动的退出流程。

c 复制代码
/** @file
 最简单的DXE阶段USB驱动示例
 演示如何绑定USB设备并安装协议
**/

#include <Uefi.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>

// USB相关协议头文件
#include <Protocol/UsbIo.h>
#include <Protocol/DevicePath.h>

// 驱动私有上下文结构
typedef struct {
    EFI_HANDLE              ControllerHandle;    // 绑定的USB控制器句柄
    EFI_USB_IO_PROTOCOL     *UsbIo;              // USB I/O协议指针
    EFI_DEVICE_PATH_PROTOCOL *DevicePath;        // 设备路径
} SIMPLE_USB_DEVICE;

// 全局变量:驱动绑定协议实例
EFI_DRIVER_BINDING_PROTOCOL gSimpleUsbDriverBinding = {
    SimpleUsbDriverSupported,
    SimpleUsbDriverStart,
    SimpleUsbDriverStop,
    0x10,        // 驱动版本号
    NULL,        // 不需要ImageHandle
    NULL         // 不需要DeviceHandle
};

/**
  检查驱动是否支持该USB设备
**/
EFI_STATUS
EFIAPI
SimpleUsbDriverSupported (
    IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    IN EFI_HANDLE                   Controller,
    IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    )
{
    EFI_STATUS          Status;
    EFI_USB_IO_PROTOCOL *UsbIo;
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Supported() called for Controller: %p\n", Controller));
    
    // 1. 尝试打开USB I/O协议
    Status = gBS->OpenProtocol(
        Controller,
        &gEfiUsbIoProtocolGuid,
        (VOID **)&UsbIo,
        This->DriverBindingHandle,
        Controller,
        EFI_OPEN_PROTOCOL_BY_DRIVER
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] No USB I/O protocol, Status: %r\n", Status));
        return Status;
    }
    
    // 2. 可以进一步检查USB设备类型(Class/SubClass/Protocol)
    // 这里简化处理:只要有USB I/O协议就认为支持
    
    // 3. 关闭协议(Supported()不能占用协议)
    gBS->CloseProtocol(
        Controller,
        &gEfiUsbIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
    );
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Device is supported!\n"));
    return EFI_SUCCESS;
}

/**
  启动驱动,初始化USB设备
**/
EFI_STATUS
EFIAPI
SimpleUsbDriverStart (
    IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    IN EFI_HANDLE                   Controller,
    IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    )
{
    EFI_STATUS               Status;
    SIMPLE_USB_DEVICE        *Device;
    EFI_USB_IO_PROTOCOL      *UsbIo;
    EFI_DEVICE_PATH_PROTOCOL *DevicePath;
    EFI_USB_DEVICE_DESCRIPTOR UsbDeviceDesc;
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Start() called for Controller: %p\n", Controller));
    
    // 1. 分配设备私有数据结构
    Device = AllocateZeroPool(sizeof(SIMPLE_USB_DEVICE));
    if (Device == NULL) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] Failed to allocate device context\n"));
        return EFI_OUT_OF_RESOURCES;
    }
    
    // 2. 打开USB I/O协议
    Status = gBS->OpenProtocol(
        Controller,
        &gEfiUsbIoProtocolGuid,
        (VOID **)&UsbIo,
        This->DriverBindingHandle,
        Controller,
        EFI_OPEN_PROTOCOL_BY_DRIVER
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] Failed to open USB I/O, Status: %r\n", Status));
        goto ErrorFreeDevice;
    }
    
    // 3. 获取设备路径
    Status = gBS->OpenProtocol(
        Controller,
        &gEfiDevicePathProtocolGuid,
        (VOID **)&DevicePath,
        This->DriverBindingHandle,
        Controller,
        EFI_OPEN_PROTOCOL_GET_PROTOCOL
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] Failed to get device path, Status: %r\n", Status));
        goto ErrorCloseProtocol;
    }
    
    // 4. 读取USB设备描述符(标准USB操作示例)
    Status = UsbIo->UsbGetDeviceDescriptor(UsbIo, &UsbDeviceDesc);
    if (EFI_ERROR(Status)) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] Failed to get device descriptor, Status: %r\n", Status));
        goto ErrorCloseProtocol;
    }
    
    // 5. 打印设备信息
    DEBUG((DEBUG_INFO, "[SimpleUSB] USB Device Info:\n"));
    DEBUG((DEBUG_INFO, "  Vendor ID  : 0x%04X\n", UsbDeviceDesc.IdVendor));
    DEBUG((DEBUG_INFO, "  Product ID : 0x%04X\n", UsbDeviceDesc.IdProduct));
    DEBUG((DEBUG_INFO, "  Class      : 0x%02X\n", UsbDeviceDesc.DeviceClass));
    DEBUG((DEBUG_INFO, "  SubClass   : 0x%02X\n", UsbDeviceDesc.DeviceSubClass));
    DEBUG((DEBUG_INFO, "  Protocol   : 0x%02X\n", UsbDeviceDesc.DeviceProtocol));
    DEBUG((DEBUG_INFO, "  MaxPacket0 : %d\n", UsbDeviceDesc.MaxPacketSize0));
    
    // 6. 保存设备上下文
    Device->ControllerHandle = Controller;
    Device->UsbIo = UsbIo;
    Device->DevicePath = DevicePath;
    
    // 7. 安装自定义协议(表示驱动已成功启动)
    // 注意:你需要先定义自己的协议GUID
    // Status = gBS->InstallProtocolInterface(
    //     &Controller,
    //     &gSimpleUsbDeviceProtocolGuid,
    //     EFI_NATIVE_INTERFACE,
    //     Device
    // );
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Driver started successfully!\n"));
    return EFI_SUCCESS;
    
ErrorCloseProtocol:
    gBS->CloseProtocol(
        Controller,
        &gEfiUsbIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
    );
    
ErrorFreeDevice:
    FreePool(Device);
    return Status;
}

/**
  停止驱动,清理资源
**/
EFI_STATUS
EFIAPI
SimpleUsbDriverStop (
    IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    IN EFI_HANDLE                   Controller,
    IN UINTN                        NumberOfChildren,
    IN EFI_HANDLE                   *ChildHandleBuffer
    )
{
    EFI_STATUS Status;
    SIMPLE_USB_DEVICE *Device = NULL;
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Stop() called for Controller: %p\n", Controller));
    
    // 1. 获取设备私有数据(如果你安装了自定义协议)
    // Status = gBS->OpenProtocol(
    //     Controller,
    //     &gSimpleUsbDeviceProtocolGuid,
    //     (VOID **)&Device,
    //     This->DriverBindingHandle,
    //     Controller,
    //     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    // );
    
    // 2. 关闭USB I/O协议
    Status = gBS->CloseProtocol(
        Controller,
        &gEfiUsbIoProtocolGuid,
        This->DriverBindingHandle,
        Controller
    );
    
    // 3. 释放设备上下文
    if (Device != NULL) {
        FreePool(Device);
    }
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Driver stopped\n"));
    return EFI_SUCCESS;
}

/**
  驱动入口点
**/
EFI_STATUS
EFIAPI
SimpleUsbDriverEntryPoint (
    IN EFI_HANDLE        ImageHandle,
    IN EFI_SYSTEM_TABLE  *SystemTable
    )
{
    EFI_STATUS Status;
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Driver Entry Point\n"));
    
    // 1. 设置驱动绑定协议的句柄
    gSimpleUsbDriverBinding.DriverBindingHandle = ImageHandle;
    gSimpleUsbDriverBinding.ImageHandle = ImageHandle;
    
    // 2. 安装驱动绑定协议到ImageHandle
    Status = gBS->InstallMultipleProtocolInterfaces(
        &ImageHandle,
        &gEfiDriverBindingProtocolGuid,
        &gSimpleUsbDriverBinding,
        NULL
    );
    
    if (EFI_ERROR(Status)) {
        DEBUG((DEBUG_ERROR, "[SimpleUSB] Failed to install Driver Binding Protocol, Status: %r\n", Status));
        return Status;
    }
    
    DEBUG((DEBUG_INFO, "[SimpleUSB] Driver Binding Protocol installed successfully\n"));
    DEBUG((DEBUG_INFO, "[SimpleUSB] Waiting for USB devices...\n"));
    
    return EFI_SUCCESS;
}

示例代码 AI 生成后整理。


Steady Progress!

相关推荐
波特率11520010 小时前
单片机启动流程以STM32举例
stm32·单片机·嵌入式硬件·嵌入式·嵌入式软件
lularible11 小时前
PTP协议精讲(2.17):追踪光速的脚步——White Rabbit与亚纳秒同步
网络·网络协议·开源·嵌入式·ptp
嵌入式小企鹅1 天前
国产大模型与芯片加速融合,RISC-V生态多点开花,AI编程工具迈入自动化新纪元
人工智能·学习·ai·嵌入式·算力·risc-v·半导体
CinzWS1 天前
A53多核协同(上):核间通信与缓存一致性协议——ARM多核的“心灵感应“
arm开发·嵌入式·芯片验证·原型验证·a53
WeeJot嵌入式1 天前
【串口】初始串口-轮询模式
stm32·单片机·嵌入式
三万棵雪松1 天前
【嵌入式刷题硬件设计基础(一)】
fpga开发·嵌入式·硬件基础
CinzWS1 天前
A53多核协同(下):一致性内存模型与内存屏障——ARM多核的“时间魔法“
arm开发·嵌入式·原型验证·a53
WeeJot嵌入式1 天前
【中断】初识中断以及外部中断的使用
c语言·stm32·单片机·嵌入式硬件·嵌入式
阿源-2 天前
如何在EDKII中编译UNIX风格C语言
嵌入式·uefi·edk2