TPL và Event trong UEFI là gì?
TPL kiểm soát mức ưu tiên callback trong UEFI. Event là cơ chế notify/signal/wait. Hiểu TPL giúp debug deadlock, callback sai thời điểm và timer không fire.
Event là cơ chế callback và notification trong UEFI - driver tạo event, đăng ký callback, rồi signal hoặc wait trên event đó. TPL (Task Priority Level) quyết định khi nào callback được chạy và thao tác nào bị trì hoãn.
Nếu chỉ viết DXE driver đơn giản, TPL có vẻ xa lạ. Nhưng khi debug deadlock, callback chạy sai thời điểm, hoặc event không fire như mong đợi - TPL là chi tiết đầu tiên cần nhìn vào.
Bốn mức TPL
| Mục | Giá trị | Ghi chú |
|---|---|---|
| TPL_APPLICATION (4) | Mức thấp nhất | Code ứng dụng, vòng lặp chính, WaitForEvent. Hầu hết driver chạy ở đây khi không đang xử lý event. |
| TPL_CALLBACK (8) | Event notify callback | Thường dùng cho callback nhẹ. Có thể gọi nhiều Boot Services, nhưng vẫn phải tránh wait dài, reentrancy và service không phù hợp với TPL hiện tại. |
| TPL_NOTIFY (16) | Critical section nhẹ | Dùng cho critical section ngắn để bảo vệ shared data khỏi callback TPL_CALLBACK. Không nên gọi service phức tạp hoặc có thể block. |
| TPL_HIGH_LEVEL (31) | Mức cao nhất | Dùng cho mức rất cao/nội bộ firmware. Driver thông thường không nên raise lên mức này. |
Khi code đang chạy ở TPL cao hơn, event có notify TPL thấp hơn sẽ bị defer đến khi TPL giảm xuống.
Event callback trong UEFI không phải interrupt handler kiểu OS. Callback chỉ chạy khi firmware có cơ hội dispatch notify theo TPL rule - nếu raise TPL quá lâu hoặc không restore TPL, callback có thể bị defer mãi.
Hai loại event chính
EVT_NOTIFY_SIGNAL - callback tự động khi event được signal:
EFI_EVENT Event;
// Callback được dispatch khi Event được signal và TPL cho phép
gBS->CreateEvent(
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK, // TPL của callback khi chạy
MyNotifyCallback, // hàm callback
NULL, // context truyền vào callback
&Event
);
// Signal event → notify callback sẽ chạy khi TPL cho phép
gBS->SignalEvent(Event);
EVT_NOTIFY_WAIT - notify callback được gọi khi firmware kiểm tra event trong WaitForEvent() hoặc CheckEvent(), nếu event chưa được signal. Callback thường poll trạng thái thiết bị, rồi signal event khi data đã sẵn sàng để WaitForEvent() thoát:
// Notify callback có thể được gọi khi WaitForEvent/CheckEvent kiểm tra event
// Callback poll status, rồi signal event nếu data đã sẵn sàng
gBS->CreateEvent(
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
MyCheckStatusCallback,
NULL,
&Event
);
UINTN Index;
gBS->WaitForEvent(1, &Event, &Index);
Nếu callback chỉ poll mà không bao giờ signal event khi điều kiện thỏa, WaitForEvent có thể bị kẹt hoặc chờ mãi. Vì vậy callback phải kiểm tra đúng condition và signal event khi data đã sẵn sàng.
Timer Event
Timer event cho phép callback chạy định kỳ:
EFI_EVENT TimerEvent;
gBS->CreateEvent(
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
MyTimerCallback,
NULL,
&TimerEvent
);
// Periodic: timer event được signal mỗi khoảng 1 giây (đơn vị 100ns), callback chạy khi TPL cho phép
gBS->SetTimer(TimerEvent, TimerPeriodic, 10000000);
// One-shot: callback sau 500ms
gBS->SetTimer(TimerEvent, TimerRelative, 5000000);
// Tắt timer
gBS->SetTimer(TimerEvent, TimerCancel, 0);
// Cleanup khi không cần
gBS->CloseEvent(TimerEvent);
RaiseTPL và RestoreTPL
Đây là cơ chế tạo critical section ngắn - raise TPL để block callback thấp hơn, xử lý shared resource, rồi restore:
EFI_TPL OldTpl;
// Raise: block tất cả callback TPL_CALLBACK và thấp hơn
OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
// --- Critical section ---
// Thao tác shared resource an toàn ở đây
// Tránh gọi: AllocatePool, LocateProtocol, WaitForEvent, hoặc Boot Service phức tạp
// --- End critical section ---
// Restore: unlock callback bị defer
gBS->RestoreTPL(OldTpl);
Event Group
Event group (CreateEventEx) là cơ chế gom nhiều event theo cùng một GUID. Khi firmware signal event group đó, tất cả event đã đăng ký với group GUID tương ứng sẽ được notify. Thường dùng cho lifecycle event như ExitBootServices và SetVirtualAddressMap:
// Đăng ký handler cho ExitBootServices event group
EFI_EVENT ExitEvent;
gBS->CreateEventEx(
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
MyExitBootServicesHandler,
NULL,
&gEfiEventExitBootServicesGuid, // GUID của event group
&ExitEvent
);
Đây là cách runtime driver đăng ký cleanup handler - khi OS gọi ExitBootServices(), firmware signal event group này và tất cả handler được gọi.
Handler của ExitBootServices event group chạy rất muộn trong boot flow, nên chỉ cleanup dependency vào Boot Services, disable timer/event cần thiết, và tránh allocate/wait.
Quy tắc quan trọng
| Mục | Giá trị | Ghi chú |
|---|---|---|
| Luôn CloseEvent khi xong | Tránh leak event handle | Trong driver/application, nên CloseEvent khi không còn dùng. Nếu quên, event handle có thể leak và timer/callback có thể còn được signal ngoài ý muốn. |
| Không WaitForEvent ở TPL > APPLICATION | Spec trả EFI_UNSUPPORTED, thực tế có thể deadlock | Spec yêu cầu WaitForEvent ở TPL_APPLICATION; ở TPL cao hơn có thể trả EFI_UNSUPPORTED. Nếu cố chờ trong callback/TPL cao, flow có thể deadlock. |
| RaiseTPL phải đi kèm RestoreTPL | Không raise mà không restore | Nếu return trước RestoreTPL (ví dụ trong error path), callback bị block vĩnh viễn. |
| Callback nên ngắn | Tránh làm việc nặng trong callback | Callback chạy ở TPL cao. Mọi thao tác phức tạp nên defer sang context thấp hơn. |
Checklist TPL/Event
Câu hỏi tự kiểm tra
EVT_NOTIFY_SIGNALvàEVT_NOTIFY_WAITkhác nhau thế nào?- Callback chạy ở
TPL_NOTIFYcó thể gọiAllocatePoolkhông? Tại sao? RaiseTPLnếu không cóRestoreTPLtương ứng thì xảy ra gì?- Timer Periodic và Timer Relative khác nhau ở điểm nào?
CreateEventExdùng để làm gì khác so vớiCreateEvent?- Tại sao không được gọi
WaitForEventở TPL cao hơnTPL_APPLICATION?
Bài liên quan
Nguồn tham khảo public
- UEFI Specification 2.11 - Event, Timer, and Task Priority Services
- EDK II MdePkg - UefiBootServicesTableLib.h
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.
Boot Services là gì?
Boot Services là nhóm API của UEFI chỉ hợp lệ trong boot time. Bao gồm memory, protocol, event, image và controller services - tất cả truy cập qua gBS.
DXE là gì trong UEFI?
DXE là phase firmware sau PEI, nơi driver được dispatch, protocol được install và Boot Services trở nên đầy đủ. DXE xây dựng môi trường để BDS có thể chọn và khởi động OS.
UEFI System Table là gì?
UEFI System Table là bảng trung tâm firmware truyền vào mọi UEFI image. Từ đây có thể đến Boot Services, Runtime Services, console và Configuration Table.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.