EFI_ERROR là gì?

Quicknote EFI_ERROR là gì?

3 phút đọc
Đọc bằng Tiếng Việt English 日本語
Debug / Shell / Driver Terms cover

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.

01 STATUS

Nhận status

Một API trả về EFI_STATUS sau khi được gọi.

02 CHECK

EFI_ERROR(Status)

Kiểm tra status có thuộc nhóm lỗi hay không.

03 CLASSIFY

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?

04 ACTION

Xử lý đúng nhánh

Return, retry, allocate lại, fallback hoặc log thêm context.

Không phải mọi nhánh EFI_ERROR đều nên xử lý giống nhau.

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.