[問題] 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