UEFI Variable là gì?
UEFI Variable lưu cấu hình firmware theo dạng Name + VendorGuid + Attributes + Data. Hiểu variable giúp debug boot option mất, Secure Boot fail và NVRAM đầy.
UEFI Variable là cơ chế lưu trạng thái và cấu hình firmware theo dạng Name + VendorGuid + Attributes + Data.
Một phần variable có attribute NV (non-volatile) nên vẫn còn sau khi tắt máy - boot option, Secure Boot key, setup policy đều đi qua cơ chế này.
Điểm quan trọng: variable không phải key-value đơn giản.
Cùng tên nhưng khác VendorGuid là hai variable hoàn toàn khác nhau.
Cùng data nhưng khác attribute thì quyền truy cập và lifetime cũng khác.
Cấu trúc một variable
| Mục | Giá trị | Ghi chú |
|---|---|---|
| Name | BootOrder, SecureBoot, ... | Unicode string. Phân biệt hoa thường. |
| VendorGuid | gEfiGlobalVariableGuid, ... | Namespace. Cùng Name khác GUID = hai variable khác nhau. |
| Attributes | NV | BS | RT | Auth | Quy định lifetime và quyền truy cập. Xem chi tiết: Variable Attribute là gì? |
| Data | Binary payload | Format tùy variable - UINT16 array cho BootOrder, UINT8 cho SecureBoot, ... |
GetVariable - đọc variable
Ví dụ dưới đây là boot-time pattern, nên còn dùng gBS để allocate buffer.
Nếu gọi variable service trong runtime path sau ExitBootServices(), không được dùng gBS.
UINT32 Attributes;
UINTN DataSize = 0;
VOID *Buffer = NULL;
// Lần 1: lấy size
Status = gRT->GetVariable(
L"BootOrder",
&gEfiGlobalVariableGuid,
&Attributes,
&DataSize,
NULL
);
if (Status == EFI_BUFFER_TOO_SMALL) {
// Boot-time: còn được dùng gBS để allocate buffer
Status = gBS->AllocatePool(EfiBootServicesData, DataSize, &Buffer);
if (EFI_ERROR(Status)) {
return Status;
}
// Lần 2: đọc thật sự
Status = gRT->GetVariable(
L"BootOrder",
&gEfiGlobalVariableGuid,
&Attributes,
&DataSize,
Buffer
);
// Sau khi dùng xong, nhớ gBS->FreePool(Buffer) trong boot-time code
}
if (Status == EFI_NOT_FOUND) {
// Kiểm tra cả tên biến VÀ VendorGuid - sai một trong hai thì EFI_NOT_FOUND
}
SetVariable - ghi variable
UINT16 BootOrder[] = { 0x0001, 0x0000, 0x0002 };
Status = gRT->SetVariable(
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(BootOrder),
BootOrder
);
if (Status == EFI_OUT_OF_RESOURCES) {
// Variable store đầy hoặc không reclaim được đủ space
// Cần giảm size, xóa variable không cần, hoặc kiểm tra reclaim/GC của firmware
}
if (Status == EFI_SECURITY_VIOLATION) {
// Payload/quyền ghi không thỏa yêu cầu bảo vệ của variable
}
// Với variable thông thường, DataSize = 0 thường dùng để delete variable.
// Protected/authenticated variable có thể yêu cầu rule riêng khi delete.
Status = gRT->SetVariable(L"MyVar", &MyGuid, Attributes, 0, NULL);
Namespace isolation
VendorGuid là cơ chế namespace - hai vendor có thể dùng cùng tên variable mà không conflict:
"CustomConfig" + {VENDOR-A-GUID} ← variable của Vendor A
"CustomConfig" + {VENDOR-B-GUID} ← variable hoàn toàn khác
Đây là lý do khi đọc variable của platform vendor, phải biết đúng GUID của họ - không có GUID thì không tìm được dù tên đúng.
Authenticated variable
Một số variable quan trọng - đặc biệt Secure Boot keys như PK, KEK, db, dbx - yêu cầu authenticated write.
Vẫn ghi qua SetVariable(), nhưng Data payload phải có authenticated header/signature đúng theo rule của firmware và trạng thái Secure Boot hiện tại.
Nếu ghi payload thường, firmware có thể trả EFI_SECURITY_VIOLATION.
QueryVariableInfo - kiểm tra variable store
Trước khi ghi variable lớn, có thể hỏi firmware còn bao nhiêu dung lượng:
UINT64 MaxVariableStorageSize;
UINT64 RemainingVariableStorageSize;
UINT64 MaxVariableSize;
Status = gRT->QueryVariableInfo(
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
&MaxVariableStorageSize,
&RemainingVariableStorageSize,
&MaxVariableSize
);
Nếu RemainingVariableStorageSize thấp, SetVariable() có thể fail với EFI_OUT_OF_RESOURCES dù data không quá lớn.
Checklist khi làm việc với UEFI Variable
Câu hỏi tự kiểm tra
- UEFI Variable được xác định bởi những thành phần nào?
- Vì sao cùng
Namenhưng khácVendorGuidlại là hai variable khác nhau? GetVariablethường được gọi hai lần để làm gì?EFI_BUFFER_TOO_SMALLtrongGetVariablecó nghĩa là gì?EFI_NOT_FOUNDkhi đọc variable thường cần kiểm tra những gì?DataSize = 0trongSetVariablethường dùng để làm gì?EFI_SECURITY_VIOLATIONkhi ghi Secure Boot variable thường gợi ý điều gì?QueryVariableInfodùng để kiểm tra gì?
Bài liên quan
- Variable Attribute là gì?
- UEFI Variable Store là gì?
- Runtime Services là gì?
- Boot####, BootOrder và BootNext là gì?
- GUID là gì?
Nguồn tham khảo public
- UEFI Specification 2.11 - Variable Services
- EDK II MdePkg - UefiRuntimeServicesTableLib.h
- EDK II MdeModulePkg - Variable driver
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.
Runtime Services là gì?
Runtime Services là nhóm API UEFI còn hợp lệ sau ExitBootServices. Bao gồm variable, time, reset và virtual address mapping - truy cập qua gRT.
Authenticated Variable là gì?
Quicknote giải thích authenticated variable trong UEFI.
Runtime phase là gì?
Giải thích giai đoạn runtime sau ExitBootServices và vì sao UEFI Runtime Services vẫn còn quan trọng khi OS đã chạy.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.