Firmware Debug Overview: debug BIOS/UEFI nên bắt đầu từ đâu?
Tổng quan cách debug BIOS/UEFI theo phase: reset, SEC, PEI, DXE, BDS, TSL, runtime, log, POST code, shell và checklist root cause.
Debug BIOS/UEFI khó không phải vì không có log, mà vì log thường xuất hiện ở phase sau, còn root cause có thể nằm ở phase trước. Một lỗi boot nhìn như BDS fail có thể bắt đầu từ PEI memory HOB. Một lỗi Shell không thấy fs0: có thể do driver chưa bind ở DXE. Một lỗi OS không thấy UEFI variable có thể do attribute thiếu RUNTIME_ACCESS.
Nói ngắn gọn: debug firmware phải debug theo phase, theo dữ liệu handoff và theo boundary, không debug theo triệu chứng bề mặt.
Nếu bạn chỉ nhìn dòng cuối cùng trong log, bạn sẽ rất dễ sửa sai chỗ.
Ví dụ:
Triệu chứng: LoadImage -> EFI_NOT_FOUND
Có thể do:
- File thật sự không tồn tại
- Boot#### Device Path stale
- Device chưa connect
- Filesystem driver chưa bind
- FV/driver thiếu từ DXE
- BootOrder trỏ entry cũ
Debug firmware nên bắt đầu từ câu hỏi nào?
Trước khi mở source hoặc thêm log, hãy trả lời ba câu hỏi:
- Hệ thống chết ở phase nào?
- Phase đó phụ thuộc dữ liệu nào từ phase trước?
- Signal debug nào đáng tin ở phase đó?
Debug firmware theo phase
Firmware Debug
├─ Reset Vector
│ ├─ CPU có fetch firmware không?
│ └─ POST code / trace / SPI
├─ SEC
│ ├─ Temporary memory có sẵn chưa?
│ └─ SEC có handoff sang PEI không?
├─ PEI
│ ├─ Memory init OK không?
│ ├─ HOB list đúng không?
│ └─ DXE IPL có chạy không?
├─ DXE
│ ├─ DXE Core vào chưa?
│ ├─ Dispatcher có thấy driver không?
│ └─ DriverBinding có bind controller không?
├─ BDS
│ ├─ BootOrder / Boot#### đúng không?
│ ├─ Device Path connect được không?
│ └─ LoadImage / StartImage status gì?
├─ TSL
│ ├─ Loader load kernel/config được không?
│ └─ ExitBootServices có success không?
└─ Runtime
├─ Runtime Services có hoạt động không?
├─ Variable attributes đúng không?
└─ ACPI / SMM / capsule path có lỗi không? Firmware debug flow tổng quát
Nhìn triệu chứng
Boot fail, no display, no fs0, variable missing, OS crash.
Xác định phase
Reset, SEC, PEI, DXE, BDS, TSL hay Runtime.
Kiểm tra boundary
Handoff giữa phase trước và phase hiện tại.
Kiểm tra dữ liệu
HOB, protocol, Device Path, variable, memory map.
Chọn debug signal
POST, serial log, Shell command, OS log, trace.
Chứng minh root cause
Không sửa khi chưa chứng minh tầng lỗi.
Bảng chọn hướng debug nhanh
| Triệu chứng | Phase nghi ngờ | Debug đầu tiên |
|---|---|---|
| Không có log nào | Reset/SEC | Power, reset, SPI fetch, POST code |
| Có POST đầu nhưng không vào PEI | SEC | Temporary RAM, SEC handoff, PEI FV |
| PEI memory init fail | PEI | Memory PEIM, silicon policy, training log |
| PEI xong nhưng không có DXE | PEI to DXE | DXE IPL, HOB list, FV HOB |
| DXE vào nhưng driver không chạy | DXE Dispatcher | FV discovery, DEPEX, driver entry |
| Driver entry chạy nhưng device không có | Driver Binding | Supported, Start, OpenProtocol |
| Có BlockIo nhưng không có fs0 | DXE/FS chain | Partition driver, FAT driver, SimpleFileSystem |
| BootOrder đúng nhưng không boot | BDS | Boot#### Device Path, LoadImage status |
| LoadImage SECURITY_VIOLATION | BDS/security | Secure Boot, db/dbx, image signature |
| StartImage return error | TSL | Bootloader ExitData, config/kernel path |
| ExitBootServices INVALID_PARAMETER | TSL handoff | GetMemoryMap, MapKey stale |
| OS không thấy variable | Runtime | Variable attributes, RT access, runtime mapping |
Debug theo phase: Reset Vector
Ở reset vector, hệ thống rất nghèo tài nguyên. Serial có thể chưa có, DRAM chưa sẵn sàng, stack bình thường chưa tồn tại.
| Câu hỏi | Signal tốt | Không nên làm |
|---|---|---|
| CPU có fetch firmware không? | SPI analyzer, trace, POST đầu | Chờ DXE log |
| Reset vector bytes đúng không? | Disassemble flash region | Sửa BDS |
| Board có reset loop không? | Reset reason, scope | Đoán do OS |
| Flash image đúng SKU không? | Build map, flash dump | Assume source là image |
| Boot block corrupt không? | SPI dump, compare image | Thêm log DXE |
| Security early chặn không? | Platform security status nếu có | Tắt policy bừa |
| CPU mode setup đúng không? | Trace/register | Dùng printf phức tạp |
| POST đầu có chạy không? | POST code | Kết luận chết vì không serial |
Debug theo phase: SEC
SEC dựng temporary environment để vào PEI. Lỗi ở đây thường làm hệ thống chết rất sớm.
| Vấn đề | Triệu chứng | Debug |
|---|---|---|
| Temporary RAM/CAR lỗi | Crash trước PEI | POST temp memory ready |
| Stack tạm sai | Crash khi gọi function | Check stack base/size |
| SEC không tìm PEI Core | Không có PEI entry | PEI FV base/header |
| SEC handoff args sai | PEI vào rồi crash | Handoff structure |
| Early serial sai | Không log nhưng POST chạy | UART base/clock/pinmux |
| Security early fail | Reset/recovery rất sớm | Verified boot policy |
| Image layout đổi | Không vào PEI sau FDF change | FD/FV map |
| Watchdog reset | Reset theo chu kỳ | Reset reason/watchdog |
Debug theo phase: PEI
PEI tạo memory, HOB, boot mode và thông tin handoff cho DXE. PEI bug hay lộ muộn ở DXE/BDS.
| Cần kiểm tra | Vì sao quan trọng | Triệu chứng nếu sai |
|---|---|---|
| Memory init | DXE cần permanent memory | Không vào DXE hoặc crash sớm |
| HOB list | DXE đọc platform state từ HOB | DXE hiểu sai memory/FV/resource |
| FV HOB | DXE thấy DXE Core/driver FV | Driver không dispatch |
| Boot Mode HOB | DXE/BDS chọn flow | Vào recovery/setup nhầm |
| Resource HOB | MMIO/IO/resource map | PCI/resource lỗi |
| CPU HOB | Address width/capability | Memory map sai |
| DXE IPL | Cửa vào DXE Core | PEI xong nhưng không vào DXE |
| PEIM dependency | PEIM dispatch order | Memory/silicon init thiếu |
Debug theo phase: DXE
DXE là phase debug phong phú nhất vì có serial log, protocol database, Shell commands và driver model rõ ràng.
| Tầng | Câu hỏi | Tool/log |
|---|---|---|
| DXE Core | DXE Core đã vào chưa? | DXE first log, POST |
| FV discovery | DXE thấy FV chứa driver không? | HOB dump, build report |
| Dispatcher | Driver entry có chạy không? | DEBUG entry, dispatcher log |
| DEPEX | Dependency thỏa chưa? | Protocol log, dh -p |
| Driver Binding | Supported/Start có chạy không? | drivers, connect, Start log |
| Protocol output | Protocol expected có install không? | dh -p ProtocolName |
| Device tree | Child handles có tạo không? | devtree |
| Filesystem | Có SimpleFileSystem không? | map -r, dh -p SimpleFileSystem |
Debug theo phase: BDS
BDS là nơi boot policy hoạt động. BDS đọc BootOrder, BootNext, Boot####, connect device path, LoadImage và StartImage.
| Object/API | Debug gì | Signal |
|---|---|---|
| BootOrder | Thứ tự boot option | dmpstore BootOrder |
| BootNext | One-time boot | dmpstore BootNext |
| Boot#### | EFI_LOAD_OPTION | dmpstore/bcfg boot dump |
| Device Path | Disk/partition/file path | DevicePathToText, map -r |
| ConnectDevicePath | Device path có connect được không | Connect status |
| LoadImage | Bootloader load được không | EFI_STATUS |
| StartImage | Bootloader chạy và return gì | Status, ExitData |
| Fallback path | Removable/recovery boot | \EFI\BOOT\BOOTX64.EFI |
Debug theo phase: TSL
TSL là lúc bootloader chạy. Nếu StartImage() đã gọi bootloader, lỗi sau đó có thể là loader-specific.
| Vấn đề | Có thể do | Debug |
|---|---|---|
| StartImage return error | Bootloader tự fail | ExitData, loader log |
| Kernel/config not found | Path/options sai | LoadOptions, file check |
| GOP missing | Graphics protocol không có | dh -p GraphicsOutput |
| ACPI table issue | DXE publish table sai | acpidump/source |
| GetMemoryMap BUFFER_TOO_SMALL | Query-size pattern | Expected nếu xử lý đúng |
| ExitBootServices INVALID_PARAMETER | MapKey stale | GetMemoryMap lại |
| No log after exit | Boot Services gone hoặc OS early issue | OS early log |
| Kernel panic | OS/kernel/initrd/ACPI | OS log |
Debug theo phase: Runtime
Runtime debug thường bắt đầu từ OS log, efivar, acpidump, dmidecode, capsule status hoặc SMM trace.
| Triệu chứng | Khả năng | Debug |
|---|---|---|
| OS không thấy variable | Thiếu RUNTIME_ACCESS | Attributes, efivar |
| SetVariable fail | Policy/auth/store full | EFI_STATUS |
| Runtime call page fault | SetVirtualAddressMap/ConvertPointer bug | Runtime descriptors |
| ResetSystem lỗi | Runtime reset implementation | OS log/reset reason |
| Capsule update fail | Capsule/SMM/flash policy | ESRT, capsule status |
| ACPI device không bind | ACPI table/method sai | acpidump |
| Sleep/resume lỗi | ACPI NVS/SMM/runtime state | Memory type, SMM |
| SMI latency cao | SMM handler issue | SMM trace/perf |
Debug signal nên dùng theo phase
| Phase | Signal tốt | Ghi chú |
|---|---|---|
| Reset | POST code, SPI trace, JTAG | Serial thường chưa có |
| SEC | POST code, early serial, trace | Log càng ít càng tốt |
| PEI | PEI log, HOB dump, POST | Memory init và HOB là trọng tâm |
| DXE | DEBUG log, Shell commands | Protocol/driver state rõ nhất |
| BDS | Boot variable dump, LoadImage status | Log Device Path rất quan trọng |
| TSL | Loader log, ExitData, GetMemoryMap log | Phân biệt firmware và loader |
| Runtime | OS log, efivar, acpidump, SMM trace | Không còn Boot Services |
| Field issue | Minimal checkpoint, persistent log | Đừng phụ thuộc lab-only tool |
Debug Diary: không thấy fs0:
Triệu chứng:
UEFI Shell vào được
map -r không có fs0:
Đừng kết luận USB/SSD hỏng ngay. fs0: cần cả một chain.
Checklist không thấy fs0
Debug Diary: BootOrder đúng nhưng boot fail
Triệu chứng:
BootOrder có entry đúng
Boot0001 nhìn đúng tên
Nhưng máy boot vào Setup
Checklist BootOrder đúng nhưng boot fail
Debug Diary: PEI xong nhưng DXE mất driver
Triệu chứng:
PEI memory init OK
DXE Core chạy
Nhưng một nhóm driver không bao giờ entry
Checklist DXE mất driver sau PEI
Debug Diary: OS không thấy variable nhưng Shell thấy
Triệu chứng:
Shell dmpstore thấy MyVar
Linux/Windows runtime không thấy MyVar
Checklist Shell thấy variable nhưng OS không thấy
Anti-pattern firmware debug
| Anti-pattern | Vì sao sai | Cách sửa |
|---|---|---|
| Sửa theo dòng log cuối | Root cause có thể ở phase trước | Trace data handoff |
| Thêm log quá nhiều ở SEC | Stack/temp memory hạn chế | Dùng POST nhỏ |
| Coi driver có trong source là đã chạy | Có thể không vào image/FV | Check build report |
| Coi driver dispatch là device ready | Chưa chắc bind controller | Check DriverBinding |
| Coi fs0 là identity ổn định | fsX mapping có thể đổi | Dùng Device Path |
| Coi BootOrder đúng là boot được | Boot#### có thể stale | Dump EFI_LOAD_OPTION |
| Tắt Secure Boot để né lỗi | Che root cause security | Debug signature/db/dbx |
| Gọi Boot Services sau exit | Không còn hợp lệ | Chia rõ TSL/runtime |
Instrumentation nên có trong firmware
| Vị trí | Nên log/checkpoint | Mục tiêu |
|---|---|---|
| Reset/SEC | POST reset, SEC entry, temp memory ready | Biết sống tới đâu |
| PEI | Memory init start/done, HOB summary | Debug memory/HOB |
| PEI to DXE | DXE IPL entry, DXE Core found | Debug handoff |
| DXE | Driver discovered, DEPEX, entry status | Debug dispatcher |
| DriverBinding | Supported/Start/Stop status | Debug connect |
| BDS | Boot####, Device Path, LoadImage/StartImage | Debug boot fail |
| TSL | GetMemoryMap, ExitBootServices | Debug loader handoff |
| Runtime | Runtime variable/status, VA change | Debug OS runtime |
Firmware debug playbook
Firmware debug playbook
Security checklist khi debug firmware
Security checklist khi debug firmware
Khi đọc source nên tìm gì?
| Muốn debug | Tìm gì trong source | Câu hỏi |
|---|---|---|
| Reset/SEC | ResetVector, SecCore, TempRam | CPU vào firmware và SEC thế nào? |
| PEI | PEIM, PPI, HOB build | PEI tạo dữ liệu gì cho DXE? |
| DXE handoff | DxeIpl, DXE Core locate | DXE Core được gọi thế nào? |
| DXE dispatch | DEPEX, dispatcher, FV discovery | Driver được dispatch vì sao? |
| DriverBinding | Supported/Start/Stop | Driver bind controller ra sao? |
| BDS | Boot manager, LoadImage/StartImage | Boot option được chọn/chạy thế nào? |
| TSL | Loader GetMemoryMap/ExitBootServices | Loader handoff OS thế nào? |
| Runtime | Runtime driver, VA change, variable service | OS gọi firmware runtime ra sao? |
| ACPI | ACPI table publish/source | OS nhìn hardware qua table nào? |
| SMM | SMM communication/lock | SMM policy/runtime path nào còn active? |
Câu hỏi tự kiểm tra
Tự kiểm tra sau khi đọc note này
Blog seeds
- Firmware Debug Overview: debug BIOS/UEFI nên bắt đầu từ đâu?
- Không có log DXE, có nên debug DXE không?
- Từ POST code tới root cause trong early boot
- Driver có trong source nhưng không chạy, debug thế nào?
- BootOrder đúng nhưng boot fail, debug theo tầng
Bài liên quan
- Firmware Flow Overview là gì?
- Reset Vector là gì?
- SEC Phase là gì?
- PEI to DXE Handoff là gì?
- DXE Dispatcher là gì?
- Driver Binding Flow là gì?
- BDS to TSL Handoff là gì?
- TSL là gì?
- Runtime Phase là gì?
- EFI_STATUS là gì?
- UEFI Shell là gì?
Nguồn tham khảo public
Bài viết này hữu ích với bạn?
Bạn có thể chia sẻ cho người đang học firmware, BIOS/UEFI, embedded systems hoặc ủng hộ tác giả.
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.
Firmware Flow Overview là gì?
Tổng quan firmware flow trong BIOS/UEFI: reset vector, SEC, PEI, DXE, BDS, ExitBootServices, runtime và cách debug theo phase.
DXE Phase: Driver, Protocol và cách đọc log khi mọi thứ không chạy
Deep dive vào DXE phase: dispatcher, DEPEX, Driver Binding, protocol database, kèm cách dùng serial log, POST code và UEFI Shell để debug thực tế.
UEFI Boot Flow: từ Reset Vector đến ExitBootServices
Không phải học để thuộc tên phase. Học boot flow để biết máy đang chết ở đâu, và debug theo hướng nào: từ SEC đến Runtime.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.