PEI là gì trong UEFI?
PEI là phase chuẩn bị nền tảng trước DXE trong UEFI, chịu trách nhiệm memory init, PPI và HOB để hệ thống có thể tiếp tục boot.
PEI (Pre-EFI Initialization) là phase firmware chạy sau SEC và trước DXE. Nhiệm vụ chính là chuẩn bị những điều kiện tối thiểu để hệ thống có thể chuyển sang DXE: khởi tạo memory, chạy các PEIM cần thiết, publish PPI và tạo HOB list để bàn giao thông tin cho DXE.
Temporary environment
Thiết lập môi trường tối thiểu ban đầu, thường trước khi DRAM dùng được.
Memory + PPI + HOB
Khởi tạo nền tảng, publish PPI, tạo HOB list để bàn giao cho DXE.
Driver environment
Đọc HOB, dựng service đầy đủ hơn và bắt đầu dispatch DXE driver.
PEI làm những việc gì?
PEI chạy trong giai đoạn rất sớm, khi hệ thống chưa có đầy đủ service như DXE. Code trong PEI thường ngắn gọn, tập trung chuẩn bị nền tảng thay vì xử lý logic phức tạp.
| Mục | Giá trị | Ghi chú |
|---|---|---|
| CPU initialization | Cấu hình CPU cơ bản | Cache, microcode update, MSR cần thiết. SEC đã làm tối thiểu, PEI hoàn thiện thêm. |
| Memory initialization | Khởi tạo DRAM - permanent memory | Nhiệm vụ quan trọng nhất. SEC dùng CAR (Cache-As-RAM) làm RAM tạm. PEI mới thật sự khởi tạo DRAM. |
| Hardware initialization tối thiểu | Chipset, clock, power domain cần thiết | Chỉ những gì cần thiết để hệ thống có thể chạy tiếp. Hardware phức tạp hơn để DXE driver xử lý. |
| PEIM dispatch | Load và chạy các PEI Module | PEI Core dispatch PEIM theo thứ tự dependency PPI. Dependency thường được khai báo trong section [Depex] của file .inf. |
| PPI management | Publish và locate PPI giữa các PEIM | PEIM publish PPI khi sẵn sàng, PEIM khác locate PPI để gọi service. Tương tự Protocol nhưng trong PEI. |
| HOB | Dữ liệu bàn giao sang DXE | PEI tạo HOB list để DXE biết memory, resource, firmware volume và boot mode ban đầu. |
| Boot mode | Xác định kiểu boot | Normal boot, recovery, S3/S4 resume. PEI đọc hardware state và set boot mode vào HOB. |
| DXE IPL | Kết thúc PEI, chuyển sang DXE | PEI kết thúc bằng cách gọi DXE IPL PPI - load DXE Core và chuyển quyền điều khiển sang DXE. |
Môi trường PEI khác DXE ở điểm nào?
Ở PEI, hầu hết service đều đến từ một nơi duy nhất: PEI Services Table (EFI_PEI_SERVICES). Không có handle database và gBS như trong DXE; PEI không dùng UEFI Protocol trên handle database mà dùng PPI. Các PEI service cốt lõi được truy cập qua pointer **PeiServices được truyền vào entry point, hoặc qua wrapper từ PeiServicesLib.
EFI_STATUS EFIAPI
MyPeimEntryPoint (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices // ← PEI Services Table
)
{
// ...
}
Đây là điểm người mới hay bị lạ: không có gBS->... hay gRT->... như ở DXE. Thay vào đó là (*PeiServices)->... hoặc dùng wrapper từ PeiServicesLib.
PEI Core và PEIM là gì?
Đây là điểm hay bị bỏ qua khi đọc tài liệu - “PEI” thực ra gồm hai thành phần khác nhau.
PEI Core là firmware do UEFI PI spec định nghĩa, chịu trách nhiệm:
- Nhận quyền điều khiển từ SEC
- Quản lý PPI database
- Dispatch các PEIM theo đúng thứ tự dependency
- Gọi DXE IPL khi PEI hoàn tất
PEIM (PEI Module) là các module riêng biệt do platform cung cấp, ví dụ memory init PEIM, chipset init PEIM, platform config PEIM. Mỗi PEIM khai báo dependency trong file .inf:
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND
gEfiPeiMasterBootModePpiGuid
PEI Core đọc [Depex] của từng PEIM và chỉ dispatch PEIM đó khi tất cả PPI dependency đã được install. Đây là cơ chế đảm bảo thứ tự init đúng - memory PEIM phải chạy trước PEIM nào cần memory, chipset PEIM phải chạy trước PEIM cần access hardware.
Nếu một PEIM không được dispatch dù build pass, hãy kiểm tra [Depex] trong .inf - có thể PPI mà nó chờ chưa được install bởi PEIM nào đó.
PEI kết thúc như thế nào?
PEI không tự “nhảy” sang DXE. Khi tất cả PEIM cần thiết đã chạy xong và HOB list đã được tạo, PEI Core gọi DXE IPL PPI (EFI_DXE_IPL_PPI). DXE IPL là PEIM đặc biệt chịu trách nhiệm:
- Locate DXE Core trong firmware volume
- Load DXE Core vào memory
- Chuyển quyền điều khiển sang DXE Core entry point kèm HOB list pointer
Từ đây PEI kết thúc - không có return. DXE Core tiếp nhận HOB list và bắt đầu dựng môi trường DXE.
PEI Services thường dùng
PeiServicesLib cung cấp wrapper cho nhiều PEI Services thường dùng, giúp code gọn hơn mà không cần truyền **PeiServices qua từng hàm.
Cài đặt và locate PPI:
#include <Library/PeiServicesLib.h>
// Publish một PPI để PEIM khác dùng
EFI_PEI_PPI_DESCRIPTOR mMyPpiDescriptor = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gMyPpiGuid,
&mMyPpi
};
PeiServicesInstallPpi(&mMyPpiDescriptor);
// Locate PPI do PEIM khác đã publish
MY_PPI_PROTOCOL *MyPpi;
Status = PeiServicesLocatePpi(
&gMyPpiGuid,
0, // instance index
NULL, // descriptor output, thường không cần
(VOID **)&MyPpi
);
if (EFI_ERROR(Status)) {
// PPI chưa có - producer chưa chạy, hoặc GUID sai
return Status;
}
Allocate memory:
Trong PEI, allocation phụ thuộc trạng thái memory hiện tại. Trước khi permanent memory usable, môi trường còn rất hạn chế; sau khi permanent memory usable và quá trình migration phù hợp đã hoàn tất, PEIM có thể dùng các service cấp phát bộ nhớ an toàn hơn.
VOID *Buffer;
// Chỉ dùng sau khi permanent memory đã usable
Status = PeiServicesAllocatePool(sizeof(MY_STRUCT), &Buffer);
Chi tiết về giai đoạn trước/sau memory migration và AllocatePages nên được tách thành một note riêng về PEI memory allocation.
Tạo HOB để bàn giao dữ liệu cho DXE:
#include <Library/HobLib.h>
// Resource HOB - thông báo vùng system memory sau DRAM init
BuildResourceDescriptorHob(
EFI_RESOURCE_SYSTEM_MEMORY,
EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED,
DramBase,
DramSize
);
// GUID HOB - truyền dữ liệu platform-specific sang DXE
MY_PLATFORM_INFO *Info = BuildGuidHob(
&gMyPlatformInfoGuid,
sizeof(MY_PLATFORM_INFO)
);
if (Info != NULL) {
Info->BoardId = DetectedBoardId;
Info->FeatureFlags = DetectedFeatures;
}
Set boot mode:
// PEI đọc hardware state rồi set boot mode vào HOB
// DXE và BDS đọc lại qua GetBootModeHob()
Status = PeiServicesSetBootMode(BOOT_WITH_FULL_CONFIGURATION);
// hoặc: BOOT_ON_S4_RESUME, BOOT_IN_RECOVERY_MODE, v.v.
Truy cập PCI config hoặc I/O sớm:
Trong PEI, nếu cần đọc/ghi PCI config space trước DXE, PEIM thường locate EFI_PEI_PCI_CFG2_PPI thay vì dùng PciIo Protocol như ở DXE. Chi tiết cách dùng nên được tách thành một note riêng về EFI_PEI_PCI_CFG2_PPI.
HOB trong PEI là gì?
PEI tạo HOB list để bàn giao toàn bộ trạng thái platform cho DXE - memory, resource, firmware volume và boot mode. DXE Core đọc HOB list này ngay khi bắt đầu chạy.
Chi tiết các loại HOB, API đọc và debug: HOB là gì?
Vì sao lỗi DXE đôi khi bắt nguồn từ PEI?
Nếu dữ liệu DXE cần được PEI bàn giao qua HOB, thì PEI sai sẽ chỉ lộ ra khi DXE bắt đầu chạy.
Ví dụ thường gặp:
- DXE không thấy vùng memory đúng → Resource Descriptor HOB từ PEI sai.
- DXE driver trong FV phụ không được dispatch → PEI chưa tạo FV HOB cho FV đó.
- BDS xử lý sai boot mode → Boot mode PEI set không đúng tình huống thực tế.
Nói cách khác: PEI không chỉ là “phase trước DXE”. Nó là phase chuẩn bị trạng thái ban đầu của platform - nếu trạng thái đó sai, lỗi sẽ theo vào DXE.
Khi nào cần quan tâm đến PEI?
Nếu bạn chỉ viết DXE driver độc lập, consume protocol bình thường và không đụng tới dữ liệu từ PEI, có thể chưa cần đào sâu PEI ngay. Nhưng khi lỗi xảy ra rất sớm trong boot flow - đặc biệt trước hoặc ngay lúc chuyển sang DXE - PEI là nơi đầu tiên cần nhìn vào.
Các dấu hiệu cần kiểm tra PEI:
- Máy reset loop trước khi DXE log xuất hiện.
- POST code dừng ở vùng PEI.
- Memory training fail hoặc DRAM không usable.
- DXE Core không khởi động được.
- DXE thiếu thông tin memory, resource hoặc FV phụ.
- Boot mode sai khi vào BDS.
Checklist khi debug PEI
Lỗi hiểu nhầm hay gặp
SEC có CAR, PEI mới khởi tạo DRAM thật sự. SEC dùng Cache-As-RAM (CAR) - cache của CPU được dùng như RAM tạm khi DRAM chưa sẵn sàng. Đây không phải DRAM thật. PEI mới là phase thật sự khởi tạo DRAM. Vì vậy không thể allocate memory thoải mái ở đầu PEI - phải chờ memory init PEIM chạy xong trước.
PEI có C runtime đầy đủ hơn SEC, nhưng vẫn hạn chế hơn DXE nhiều. SEC thường viết bằng assembly hoặc C rất hạn chế (không có stack đủ lớn, không có global data). PEI có môi trường C dễ dùng hơn SEC, đặc biệt sau khi permanent memory usable. Nhưng so với DXE thì PEI vẫn thiếu nhiều service: không có handle database, không có gBS, không dùng UEFI Protocol trên handle database.
PEI không phải chỉ là “khúc trước DXE”. PEI là phase có kiến trúc riêng - PEI Core, PEIM, PPI, HOB, DXE IPL. Không phải vài dòng init tạm thời.
Không thể bê tư duy DXE driver sang PEIM. gBS chưa tồn tại, memory có thể chưa đầy đủ ở đầu PEI. PEIM viết theo tư duy DXE driver rất dễ fail hoặc làm sai trạng thái hệ thống.
Lỗi DXE không phải lúc nào cũng do DXE. Nếu dữ liệu cần được PEI bàn giao qua HOB, sai từ PEI sẽ chỉ lộ ra khi DXE bắt đầu đọc.
PPI không phải Protocol. PPI thuộc PEI, Protocol thuộc DXE. Nhầm hai khái niệm này sẽ khiến việc đọc EDK II source khó hơn nhiều.
Câu hỏi tự kiểm tra
- PEI nằm giữa hai phase nào trong boot flow UEFI?
- SEC dùng CAR để làm gì? PEI khởi tạo gì mà SEC chưa làm?
- PEI Core và PEIM khác nhau ở điểm nào?
- PEIM được dispatch theo cơ chế gì - khai báo ở đâu trong source?
- PPI dùng để làm gì trong PEI?
- HOB giúp PEI bàn giao dữ liệu gì cho DXE?
- PEI kết thúc bằng cách nào - DXE IPL làm gì?
- Nếu DXE thiếu FV phụ hoặc memory map sai, vì sao cần kiểm tra lại PEI?
Bài liên quan
Nguồn tham khảo public
- UEFI PI Specification 1.9 - Volume 1: PEI Core Interface
- EDK II MdePkg - PeiServicesLib
- EDK II - PeiServicesTablePointerLib.h
- EDK II MdePkg - HobLib
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.
HOB là gì trong UEFI?
HOB là dữ liệu PEI bàn giao cho DXE trong boot flow UEFI, giúp DXE biết memory, resource và firmware volume ban đầu.
PPI là gì trong UEFI?
PPI là cơ chế interface giữa các PEIM trong PEI phase, thay thế cho Protocol khi DXE chưa sẵn sàng. Hiểu PPI giúp debug dispatch order và lỗi PEIM không chạy.
PEI Fail Checklist
Quicknote checklist debug lỗi trong PEI phase.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.