EFI_ERROR là gì?
Quicknote EFI_ERROR là gì?
EFI_ERROR(Status) là macro dùng để kiểm tra một EFI_STATUS có thuộc nhóm lỗi hay không. Nó giúp code đọc rõ hơn so với việc tự so sánh từng status code.
Nhưng trong debug thực tế, điều quan trọng không chỉ là “có lỗi hay không”. Điều quan trọng hơn là lỗi này có được phép xảy ra trong flow hiện tại không.
Status = gRT->GetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
&Attributes,
&Size,
BootOrder
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "GetVariable(BootOrder) failed: %r\n", Status));
return Status;
}
EFI_ERROR giải quyết vấn đề gì?
Nếu không có macro này, code sẽ dễ rơi vào kiểu:
if (Status != EFI_SUCCESS) {
return Status;
}
Cách này đôi khi quá thô. Một số API dùng status khác EFI_SUCCESS như một tín hiệu hợp lệ. Ví dụ EFI_BUFFER_TOO_SMALL thường là bước đầu để caller biết cần allocate bao nhiêu byte.
Nhận status
Một API trả về EFI_STATUS sau khi được gọi.
EFI_ERROR(Status)
Kiểm tra status có thuộc nhóm lỗi hay không.
Phân loại ngữ cảnh
Lỗi thật, trạng thái retry, dependency chưa sẵn sàng hay flow bình thường?
Xử lý đúng nhánh
Return, retry, allocate lại, fallback hoặc log thêm context.
Debug Diary: EFI_ERROR đúng nhưng xử lý sai
Một lỗi khá dễ gặp:
Status = gRT->GetVariable (..., &Size, NULL);
if (EFI_ERROR (Status)) {
return Status;
}
Với GetVariable(), caller có thể cố tình truyền NULL để lấy size trước. Khi đó EFI_BUFFER_TOO_SMALL không phải lỗi cần return ngay, mà là tín hiệu để allocate buffer.
Cách đúng hơn:
Status = gRT->GetVariable (Name, Guid, &Attributes, &Size, NULL);
if (Status == EFI_BUFFER_TOO_SMALL) {
Buffer = AllocateZeroPool (Size);
Status = gRT->GetVariable (Name, Guid, &Attributes, &Size, Buffer);
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "GetVariable failed: %r\n", Status));
return Status;
}
| Mục | Giá trị | Ghi chú |
|---|---|---|
| Return ngay | Lỗi không thể phục hồi | Ví dụ input sai, security violation, không có dependency bắt buộc. |
| Retry | Flow có thể phục hồi | Ví dụ buffer thiếu, protocol chưa sẵn sàng trong một số flow. |
| Fallback | Có đường thay thế | Ví dụ boot option fail thì thử option kế tiếp. |
| Ignore có kiểm soát | Status bình thường trong enumerate | Ví dụ driver không support controller này. |
Common Pitfall
Sai lầm lớn nhất là dùng EFI_ERROR() như một cái búa: cứ có lỗi là return. Firmware thường cần phân biệt lỗi nghiêm trọng với trạng thái điều khiển flow. Nếu không phân biệt, boot manager có thể bỏ qua fallback, driver có thể ngừng enumerate quá sớm, hoặc setup có thể không hiển thị dữ liệu dù chỉ thiếu buffer tạm thời.
Checklist khi viết nhánh EFI_ERROR
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.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.