UEFI Service Driver là gì?

UEFI Service Driver install protocol lên service handle, không cần Driver Binding. Hiểu service handle pattern, khi nào dùng thay vì driver binding, và cách trace service protocol.

Cập nhật 6 phút đọc
Driver Types cover

UEFI Service Driver là driver install protocol cung cấp dịch vụ cho các driver hoặc module khác - mà không cần EFI_DRIVER_BINDING_PROTOCOL. Nó không bind vào controller, không có Supported()/Start()/Stop(). Nó chỉ làm một việc: install protocol lên một handle để consumer locate và dùng.

Đây là loại driver đơn giản nhất về cấu trúc, nhưng dễ bị viết sai về ownership, lifetime, và khi nào nên dùng service handle mới thay vì install lên handle có sẵn.

Service driver vs Driver Binding driver

Mục Giá trị Ghi chú
Driver Binding driver Bind vào controller Cần Supported()/Start()/Stop(). Bind vào hardware handle. Protocol phụ thuộc vào hardware present.
Service driver Install service protocol Không Supported()/Start()/Stop(). Install lên service handle mới hoặc handle có sẵn. Protocol available sau khi driver dispatch và InstallProtocolInterface() thành công.
Khi nào dùng service driver Service không cần bind controller cụ thể HII database, variable policy, crypto service, platform info, custom platform service - không cần bind trực tiếp vào một controller cụ thể.

Entry point - install và xong

Service driver entry point đơn giản nhất trong UEFI:

EFI_STATUS EFIAPI
MyServiceDriverEntryPoint (
    IN EFI_HANDLE        ImageHandle,
    IN EFI_SYSTEM_TABLE  *SystemTable
    )
{
    EFI_STATUS       Status;
    MY_SERVICE_DATA  *ServiceData;

    // Allocate service context
    Status = gBS->AllocatePool(
        EfiBootServicesData,
        sizeof(MY_SERVICE_DATA),
        (VOID **)&ServiceData
    );
    if (EFI_ERROR(Status)) return Status;

    // Init service context
    InitMyService(ServiceData);

    // Install protocol lên handle mới (NULL → firmware tạo handle)
    EFI_HANDLE ServiceHandle = NULL;
    Status = gBS->InstallProtocolInterface(
        &ServiceHandle,
        &gMyServiceProtocolGuid,
        EFI_NATIVE_INTERFACE,
        &ServiceData->Protocol
    );
    if (EFI_ERROR(Status)) {
        gBS->FreePool(ServiceData);
        return Status;
    }

    // Lưu handle để có thể uninstall sau nếu cần
    ServiceData->ServiceHandle = ServiceHandle;

    // Service handle tồn tại - consumer có thể LocateProtocol ngay bây giờ
    return EFI_SUCCESS;
}

Không có ConnectController(). Không có DisconnectController(). Không có Stop(). Driver init xong là service available.

Service driver là boot-time DXE driver. Protocol của nó tồn tại trong handle database và được dùng trước ExitBootServices(). Nếu service phải được OS gọi sau EBS, đó là runtime driver/runtime service design khác - xem UEFI Runtime Driver là gì?.

Service handle - tạo mới hay install lên handle có sẵn

Có hai cách install service protocol:

// Cách 1: Install lên handle MỚI
// Dùng khi service là độc lập, không liên quan handle nào khác
EFI_HANDLE ServiceHandle = NULL;  // NULL → firmware tạo handle mới
gBS->InstallProtocolInterface(
    &ServiceHandle,
    &gMyServiceProtocolGuid,
    EFI_NATIVE_INTERFACE,
    &ServiceData->Protocol
);
// ServiceHandle bây giờ có giá trị - lưu lại nếu cần uninstall sau
// Cách 2: Install lên handle CÓ SẴN (ví dụ: ImageHandle)
// Dùng khi muốn associate service với module cụ thể
gBS->InstallProtocolInterface(
    &ImageHandle,   // handle đã tồn tại
    &gMyServiceProtocolGuid,
    EFI_NATIVE_INTERFACE,
    &ServiceData->Protocol
);
Mục Giá trị Ghi chú
Handle mới (NULL) Service handle độc lập Consumer dùng LocateProtocol để tìm. Phù hợp với global service không gắn với module cụ thể.
ImageHandle Gắn với driver image Phù hợp khi service lifetime gắn với driver image. Nếu driver hỗ trợ unload, unload handler phải uninstall protocol và free context đúng cách.
Handle khác Gắn với entity khác Ví dụ: install thêm protocol lên controller handle để augment capability. Cần cẩn thận ownership.

Consumer locate service - LocateProtocol

Consumer locate service protocol qua LocateProtocol() - không cần biết handle cụ thể:

MY_SERVICE_PROTOCOL *MyService;

Status = gBS->LocateProtocol(
    &gMyServiceProtocolGuid,
    NULL,
    (VOID **)&MyService
);
if (EFI_ERROR(Status)) {
    // Service chưa available - có thể driver publish service chưa dispatch
    // Hoặc có thể register notify khi protocol được install
    return Status;
}

// Dùng service
MyService->DoSomething(MyService, ...);

Nếu consumer cần biết khi service available, có thể dùng RegisterProtocolNotify():

// Phải tạo event trước khi register notify
EFI_EVENT NotifyEvent;
VOID      *Registration;

Status = gBS->CreateEvent(
    EVT_NOTIFY_SIGNAL,
    TPL_CALLBACK,
    MyServiceNotifyHandler,
    NULL,
    &NotifyEvent
);
if (EFI_ERROR(Status)) return Status;

// Register để được notify khi service protocol được install
Status = gBS->RegisterProtocolNotify(
    &gMyServiceProtocolGuid,
    NotifyEvent,
    &Registration
);

Ví dụ service driver trong EDK II

Mục Giá trị Ghi chú
HII Database Driver edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ Install EFI_HII_DATABASE_PROTOCOL, EFI_HII_FONT_PROTOCOL, v.v. lên service handle. BIOS Setup UI, string package, form package đều dùng đây.
Variable Policy Driver edk2/MdeModulePkg/Universal/Variable/ Publish policy protocol để DXE/platform code đăng ký variable policy trong boot phase; thường bị lock ở EndOfDxe/SmmReadyToLock tùy platform. Không phải runtime variable service.
Security Manager edk2/MdeModulePkg/Universal/SecurityStubDxe/ Install EFI_SECURITY_ARCH_PROTOCOL lên service handle. Được hook trong LoadImage path.
Platform Info Driver Platform package Publish board ID, hardware config, silicon policy. Consumer DXE driver LocateProtocol để đọc.

Failure pattern - service không available khi consumer cần

LocateProtocol fail - service chưa dispatch:

  • Consumer DXE driver dispatch trước service driver
  • DEPEX của consumer phải khai báo GUID của service protocol:
[Depex]
  gMyServiceProtocolGuid   # ← GUID này, không phải Driver Binding GUID

Nếu thiếu DEPEX, consumer có thể dispatch trước khi service available.

Service install nhưng GUID sai:

# UEFI Shell: kiểm tra service protocol có trên handle nào không
Shell> dh -p <protocol_GUID>
# Không thấy → service driver chưa dispatch, hoặc GUID mismatch
Shell> dh -v    # tìm handle có gMyServiceProtocolGuid

Service context bị free sớm:

  • Protocol vẫn còn trong handle database nhưng interface trỏ tới memory đã free
  • Consumer LocateProtocol() thành công nhưng gọi function pointer thì crash
  • Xảy ra khi error path FreePool context trước khi UninstallProtocolInterface

Trace khi service protocol không available

# UEFI Shell: kiểm tra protocol có trong handle database không
Shell> dh -p EFI_HII_DATABASE_PROTOCOL  # hoặc GUID của service cần tìm

# Nếu không thấy: service driver chưa dispatch
# Nguyên nhân thường gặp:
# 1. FDF thiếu service driver
# 2. DEPEX của service driver chưa thỏa (protocol required chưa install)
# 3. Service driver dispatch thành công nhưng install fail im lặng

# Tìm trong build map (path tùy platform/toolchain)
grep "MyServiceDriver" Build/*/*/FV/*.map

# EDK II - service driver pattern
grep -r "InstallProtocolInterface\|LocateProtocol" \
    edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ --include="*.c" | head -10

Checklist Service Driver

Câu hỏi tự kiểm tra

  1. Service driver khác Driver Binding driver ở điểm cốt lõi nào?
  2. Tại sao consumer cần khai báo service protocol GUID trong DEPEX?
  3. Service handle mới (NULL) và ImageHandle khác nhau về lifetime thế nào?
  4. Nếu LocateProtocol() fail, nguyên nhân phổ biến nhất là gì?
  5. Khi nào service driver cần chủ động UninstallProtocolInterface()?

Bài liên quan

Nguồn tham khảo public

Thấy nội dung này hữu ích?

Lưu lại hoặc chia sẻ cho người cũng đang học firmware, BIOS/UEFI và embedded systems.

Nội dung liên quan

Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.

Biến note thành bài viết hoàn chỉnh

Notes là nơi ghi nhanh khái niệm.