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.

Cập nhật 5 phút đọc
BIOS Terms cover

Boot Services là tập hợp các API của UEFI chỉ hợp lệ trong boot time - trước khi OS loader gọi ExitBootServices(). Toàn bộ Boot Services được truy cập qua con trỏ toàn cục gBS (EFI_BOOT_SERVICES *).

DXE driver, UEFI application, và BDS đều dùng Boot Services để làm mọi việc: allocate memory, install/locate protocol, tạo event, load image và connect controller.

Boot Services rất tiện, nhưng có hạn sử dụng. Sau ExitBootServices(), gBS không còn hợp lệ - mọi code dùng Boot Services sau điểm này là undefined behavior.

Các nhóm API chính

Mục Giá trị Ghi chú
Memory Services AllocatePool, AllocatePages, FreePool, FreePages Cấp phát và giải phóng memory trong boot time. Memory type ảnh hưởng đến lifetime.
Protocol Services InstallProtocolInterface, LocateProtocol, OpenProtocol, CloseProtocol Xương sống của DXE driver model. Tất cả driver binding đều đi qua đây.
Event & Timer CreateEvent, SetTimer, SignalEvent, WaitForEvent, CloseEvent Dùng cho callback, notify khi protocol xuất hiện, timer-based polling.
Image Services LoadImage, StartImage, Exit, UnloadImage BDS dùng LoadImage/StartImage để chạy OS loader và UEFI application.
Controller Services ConnectController, DisconnectController Trigger Driver Binding - bind/unbind driver với controller.
Misc Services Stall, SetWatchdogTimer, GetMemoryMap, LocateHandleBuffer Delay, watchdog, lấy memory map trước ExitBootServices, tìm handle theo protocol.

Memory type và lifetime

Khi allocate memory bằng Boot Services, memory type quyết định lifetime của vùng đó:

VOID *Buffer;

// EfiBootServicesData - chỉ tồn tại đến ExitBootServices()
gBS->AllocatePool(EfiBootServicesData, Size, &Buffer);

// EfiRuntimeServicesData - cần tồn tại sau ExitBootServices()
// Runtime driver dùng type này để OS không reclaim
gBS->AllocatePool(EfiRuntimeServicesData, Size, &Buffer);

Lỗi phổ biến nhất là allocate với EfiBootServicesData rồi lưu pointer vào structure dùng ở runtime path. Sau ExitBootServices(), vùng memory boot services có thể bị OS reclaim.

EfiRuntimeServicesData chỉ nên dùng cho dữ liệu thật sự thuộc runtime service hoặc runtime driver. Không nên dùng runtime memory type chỉ vì muốn “giữ pointer lâu hơn” - vùng này sẽ xuất hiện trong memory map và ảnh hưởng đến OS. Memory này cũng có thể liên quan đến SetVirtualAddressMap() nếu runtime code giữ pointer sau khi OS chuyển sang virtual address mode.

Event và TPL

Boot Services có cơ chế Event để xử lý callback và async notification. Mọi event chạy ở một TPL (Task Priority Level) nhất định:

EFI_EVENT Event;

// Tạo event sẽ signal khi protocol mới xuất hiện
gBS->CreateEvent(
       EVT_NOTIFY_SIGNAL,
       TPL_CALLBACK,          // TPL của callback
       MyNotifyFunction,
       NULL,
       &Event
     );

// Đăng ký với một protocol GUID
VOID *Registration;
gBS->RegisterProtocolNotify(&gEfiBlockIoProtocolGuid, Event, &Registration);

// Cleanup khi không cần
gBS->CloseEvent(Event);

TPL quan trọng để hiểu thứ tự xử lý và reentrancy:

Mục Giá trị Ghi chú
TPL_APPLICATION (4) Mức thấp nhất Code ứng dụng thông thường chạy ở đây.
TPL_CALLBACK (8) Event notify/callback Hầu hết event callback chạy ở TPL_CALLBACK.
TPL_NOTIFY (16) Critical section nhẹ Dùng khi cần block TPL_CALLBACK trong một đoạn code ngắn.
TPL_HIGH_LEVEL (31) Mức cao nhất Dùng nội bộ bởi firmware. Không dùng trong driver thông thường.

Khi code đang chạy ở TPL cao hơn, event ở TPL thấp hơn sẽ bị defer đến khi TPL giảm xuống.

Ở TPL cao, callback nên chạy ngắn và tránh làm việc nặng. Không nên wait lâu, polling phức tạp, hoặc gọi các Boot Services không phù hợp với TPL hiện tại. Nếu cần xử lý nhiều, nên defer sang ngữ cảnh TPL thấp hơn.

Boot Services và các bài đã học

Boot Services là nền tảng kết nối tất cả những gì đã học:

Protocol Services  → gBS->InstallProtocolInterface / LocateProtocol / OpenProtocol
Handle Database    → gBS->LocateHandleBuffer / ProtocolsPerHandle / OpenProtocolInformation
Driver Binding     → gBS->ConnectController / DisconnectController
DXE Dispatcher     → load/dispatch driver trong môi trường DXE nơi Boot Services đã sẵn sàng

Mọi thao tác với handle database, protocol install/locate, driver binding đều đi qua gBS. Đây là lý do tại sao hiểu Boot Services là hiểu DXE.

Phân biệt Boot Services và Runtime Services

Boot Services (gBS)Runtime Services (gRT)
Hợp lệ khiTrước ExitBootServices()Trước và sau ExitBootServices()
Dùng choDriver, BDS, OS loaderVariable, time, reset, runtime firmware services
Memory typeEfiBootServicesData/CodeEfiRuntimeServicesData/Code
Ví dụAllocatePool, LocateProtocolGetVariable, ResetSystem

Khi nào cần quan tâm đến Boot Services?

Hầu như mọi DXE driver đều dùng Boot Services - không thể tránh. Nhưng có một số tình huống cụ thể cần chú ý đặc biệt:

  • Runtime driver phải tránh gBS sau ExitBootServices()
  • OS loader phải lấy memory map rồi gọi ExitBootServices() đúng cách
  • Driver leak event hay memory nếu không CloseEventFreePool khi cleanup
  • Code dùng EfiBootServicesData nhưng pointer được giữ lâu hơn boot time

Checklist Boot Services

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

  1. Boot Services được truy cập qua pointer nào?
  2. Điểm nào đánh dấu kết thúc validity của Boot Services?
  3. EfiBootServicesDataEfiRuntimeServicesData khác nhau ở lifetime thế nào?
  4. TPL dùng để làm gì trong Event model?
  5. Tại sao runtime driver không được gọi gBS->LocateProtocol()?
  6. Driver có thể dùng Boot Services trong Stop() không?
  7. Nếu event notify bị leak, debug như thế nào?

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.