[问题] UEFI的Driver-Model Driver

楼主: devcc (游侠)   2023-03-23 11:22:51
开发平台(Platform): (Ex: Win10, Linux, ...)
编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出)
VScode
额外使用到的函数库(Library Used): (Ex: OpenGL, ...)
问题(Question):
我自己创一个驱动程序模型来驱动程序,它作用是提供一个协议来读取 PCI 设备。
首先我其实只是在用一个新的协议来包PciIo(不确定自己这样写的架构对不对)
测试过后 Supported跟Start似乎都正常,
我另外写一个app.c的来呼叫我新的协议也可以呼叫(只是呼叫出来的东西好像不太理想)
但在disconnect地方出现问题,他无法断开连结是什么原因?
程式码(Code):(请善用置底文网页, 记得排版,禁止使用图档)
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/ComponentName2.h>
#include <Protocol/PciIo.h>
#define LANGUAGE_CODE_ENGLISH "en"
// ==========================================================
// define My Pci device
EFI_GUID gMyPciProtocolGuid = {0xa1bd7202, 0xd040, 0x46ed, {0xb0, 0xcd, 0xf5,
0x2f, 0xa3, 0xad, 0xe7, 0xa6}};
typedef struct _MY_PROTOCOL MY_PROTOCOL;
typedef EFI_STATUS (EFIAPI *MY_PROTOCOL_FUNCTION) (
IN MY_PROTOCOL *This,
IN EFI_PCI_IO_PROTOCOL *PciIo
);
struct _MY_PROTOCOL {
MY_PROTOCOL_FUNCTION Function;
EFI_PCI_IO_PROTOCOL *PciIo;
};
EFI_STATUS
EFIAPI
MyProtocolFunction (
IN MY_PROTOCOL *This,
IN EFI_PCI_IO_PROTOCOL *PciIo
)
{
UINT32 Data;
// Call the PciIo function
return PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
1,
&Data
);
}
// ==========================================================
// Function Prototypes for Driver Binding Protocol Interface
EFI_STATUS
EFIAPI
Supported(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
Start(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
Stop(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
EFI_STATUS
EFIAPI
GetDriverName(
IN EFI_COMPONENT_NAME2_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
GetControllerName(
IN EFI_COMPONENT_NAME2_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
// ==========================================================
// EFI Driver Binding Protocol Instance
EFI_DRIVER_BINDING_PROTOCOL gMyPciDriverBinding = {
Supported, //Supported
Start, //Start,
Stop, //Stop,
0xa, //Version,
NULL, //Image Handle,
NULL //DriverBindingHandle,
};
EFI_COMPONENT_NAME2_PROTOCOL gMyPciDriverComponentName2 = {
GetDriverName,
GetControllerName,
LANGUAGE_CODE_ENGLISH
};
// ==========================================================
// Functions for Driver Binding Protocol Interface
EFI_STATUS
EFIAPI
Supported(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
Print(L"driver-model driver Pci Driver Supported\n");
EFI_STATUS Status;
UINT16 VendorId;
EFI_PCI_IO_PROTOCOL *PciIo;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
// Read the Vendor ID of the PCI device
Status = PciIo->Pci.Read(
PciIo,
EfiPciIoWidthUint16,
0x00,
1,
&VendorId
);
if (EFI_ERROR(Status)) {
return Status;
}
gBS->CloseProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
if (VendorId == 0x8086) {
Print(L"VendorId: %x\n", VendorId);
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Start(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
Print(L"driver-model driver Pci Driver Start\n");
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
MY_PROTOCOL myProtocol = {MyProtocolFunction,NULL};
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
myProtocol.Function = MyProtocolFunction;
myProtocol.PciIo = PciIo;
// Install the protocol on the handle for the specified PCI device
Status = gBS->InstallMultipleProtocolInterfaces(
&ControllerHandle,
&gMyPciProtocolGuid, myProtocol,
NULL
);
Print(L"install protocol(gMyPciProtocolGuid): %r\n", Status);
if (EFI_ERROR(Status)) {
Print(L"Failed to install protocol: %r\n", Status);
return Status;
}
gBS->CloseProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return Status;
}
EFI_STATUS
EFIAPI
Stop(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
Print(L"driver-model driver Pci Driver Stop\n");
EFI_STATUS Status;
MY_PROTOCOL *myProtocol;
Status = gBS->OpenProtocol(
ControllerHandle,
&gMyPciProtocolGuid,
(VOID**)&myProtocol,
ControllerHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
return Status;
}
Status = gBS->UninstallMultipleProtocolInterfaces (
ControllerHandle,
&gMyPciProtocolGuid, myProtocol,
NULL
);
if (EFI_ERROR (Status)) {
Print(L"Failed to Uninstall protocol: %r\n", Status);
return Status;
}
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
Print(L"Protocol has been Uninstalled : %r.\n", Status);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
GetDriverName(
IN EFI_COMPONENT_NAME2_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
Print(L"driver-model driver Pci Driver Name Get Driver Name\n");
//Supports only English
if (Language == NULL ||
AsciiStrCmp( Language, LANGUAGE_CODE_ENGLISH) == 0) {
StrCpyS (*DriverName,
StrSize(L"My PCI Driver"),
L"My PCI Driver");
return EFI_SUCCESS;
} else {
return EFI_UNSUPPORTED;
}
}
EFI_STATUS
EFIAPI
GetControllerName(
IN EFI_COMPONENT_NAME2_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}
// ==========================================================
// Pci Protocol Functions Implementation
EFI_STATUS
EFIAPI
MyPciDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
// Install driver model protocol(s).
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gMyPciDriverBinding,
ImageHandle,
NULL,
&gMyPciDriverComponentName2
);
if (EFI_ERROR(Status)) {
Print(L"Failed to install protocol: %r\n", Status);
return Status;
}
return Status;
}
补充说明(Supplement):
作者: ssdoz2sk (眷恋着提拉米苏的风采~)   2023-03-26 01:19:00
Disconnect 出现问题是指你 unload driver image 时候,出现 Unsupported? 看起来是没有 UNLOAD_IMAGE 的 funcinf 也要有相对应的设定,可以参考MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe
作者: lchbird (新手上路)   2023-04-04 21:19:00
两个问题。第一个是Start中的myProtocil是local variable,会出事。第二个是在Start中PciIo被close了,这不用close,Stop中才需要close。

Links booklink

Contact Us: admin [ a t ] ucptt.com