ACPI là gì: tại sao firmware không nên tắt máy bằng cách toggle GPIO
Tại sao firmware không nên dùng GPIO trực tiếp để tắt máy? ACPI là hợp đồng firmware viết, OS đọc: table, AML, power state và cách debug sleep/wake sai.
Câu hỏi ban đầu: tại sao firmware không nên tắt máy bằng cách toggle GPIO?
Tôi nhớ lúc mới bắt đầu làm quen với SMM, có một lần cần implement logic tắt máy khẩn cấp khi nhiệt độ vượt ngưỡng, loại feature hay có trên POS terminal đặt trong môi trường nóng. Suy nghĩ đầu tiên rất tự nhiên: SMM chạy ở privilege rất cao, không có OS nào can thiệp được, vậy chỉ cần toggle GPIO pin tắt nguồn là xong.
Đồng nghiệp nhìn draft code, hỏi một câu: “GPIO nào? Board nào cũng khác nhau, mày định hardcode à?”
Câu hỏi đó mở ra một chuỗi giải thích mà tôi muốn viết lại ở đây: tại sao firmware không nên tắt máy bằng cách toggle GPIO, và ACPI fill vào khoảng trống đó như thế nào.
Câu trả lời ngắn: GPIO pin nào liên quan đến power là thứ platform-specific. Nếu hardcode vào SMM hoặc firmware handler, code sẽ bị dính chặt vào một board cụ thể. Quan trọng hơn, trong flow shutdown bình thường, power transition không phải quyết định riêng của SMM. Nó là một phần của ACPI và OS power management.
Câu trả lời dài hơn cần một bước lùi để hiểu firmware và OS phân chia quyền kiểm soát phần cứng như thế nào, và đó chính là lý do ACPI tồn tại.
Firmware và OS nhìn phần cứng khác nhau
Sau khi ExitBootServices() được gọi, OS nắm quyền platform. Nhưng OS không biết chi tiết phần cứng theo nghĩa hardware-specific: GPIO pin nào là power button, EC register nào điều khiển fan, rail nào phải tắt theo thứ tự nào khi sleep.
Firmware biết tất cả những điều đó, vì firmware mới là thứ init hardware từ đầu. Nhưng firmware không thể chỉ “giải thích bằng miệng” cho OS. Nó phải để lại một bản mô tả chuẩn hóa.
ACPI là bản mô tả đó.
Firmware init hardware
Firmware cấu hình chipset, device, policy và platform resource
Publish ACPI tables
Firmware install DSDT, SSDT, FADT, MADT và các table liên quan
ExitBootServices
Firmware bàn giao quyền điều khiển boot-time cho OS
OS đọc ACPI
OS walk từ RSDP, đọc DSDT/SSDT, interpret AML
OS gọi ACPI method
Device probe, sleep, wake, power button đều đi qua ACPI model
ACPI không phải API kiểu function call trực tiếp giữa OS và firmware. Nó là một hợp đồng dữ liệu và control method: firmware publish table và AML, OS đọc table rồi thực thi AML method khi cần. Mọi thao tác power management sau khi OS lên đều đi qua hợp đồng này.
Quay lại câu hỏi: tại sao không toggle GPIO trong SMM?
Trong SMM, về mặt kỹ thuật bạn có thể truy cập hardware register trực tiếp. Nhưng dùng cách đó để tắt nguồn trong flow bình thường sẽ gây nhiều vấn đề.
Thứ nhất, nó bypass ACPI power sequence. OS không có cơ hội flush disk, close file handle, notify driver cleanup hoặc chuẩn bị device trước khi mất nguồn. Kết quả có thể là filesystem corruption hoặc device rơi vào trạng thái undefined sau khi bật lại.
Thứ hai, nó không portable. GPIO pin nào, register nào, EC command nào liên quan đến power là board-specific và silicon-specific. Hardcode vào SMM handler nghĩa là firmware bị gắn chặt vào một platform.
Thứ ba, nó sai ownership. SMM sinh ra để xử lý service nhỏ, bảo vệ resource và thực thi security policy. Nó không nên thay OS làm power management vĩ mô. Trong shutdown bình thường, OS/OSPM là bên điều phối power transition.
Trong flow ACPI bình thường, firmware không phải là bên tự ý tắt máy sau khi OS đã chạy. Firmware cung cấp ACPI tables, trong đó có FADT, DSDT/SSDT và _S5. OS/OSPM đọc thông tin này, chuẩn bị device, flush filesystem, gọi các ACPI method cần thiết, rồi mới yêu cầu chipset vào S5 bằng SLP_TYP và SLP_EN.
Nói cách khác: firmware viết hợp đồng, OS đọc hợp đồng và điều khiển power transition.
Publish ACPI tables
FADT, DSDT/SSDT, _S5, _PTS, _WAK và device methods
Đọc ACPI
OS hiểu device, resource, wake source và sleep state
Chuẩn bị power transition
Flush I/O, notify driver, chạy ACPI method cần thiết
SLP_TYP + SLP_EN
OS yêu cầu chipset vào sleep/off state theo ACPI spec
Power transition
Platform chuyển sang S5 theo đúng ACPI flow
Nếu đây là thermal emergency thật sự, platform có thể có đường bảo vệ phần cứng riêng như EC, PMIC, chipset thermal trip hoặc board-specific safety logic. Nhưng đó là cơ chế bảo vệ khẩn cấp, không phải flow OS-controlled shutdown bình thường. Không nên trộn emergency hardware protection với shutdown ACPI thông thường.
ACPI là gì: nhìn từ firmware engineer
ACPI (Advanced Configuration and Power Interface) không chỉ là “bảng cấu hình”. Nó gồm hai phần chính.
1. Static tables, dữ liệu firmware publish lúc boot.
2. AML code, bytecode mà OS interpreter thực thi ở runtime khi cần hỏi platform “làm gì bây giờ”.
Đây là điểm nhiều người bỏ qua: ACPI không chỉ đọc một lần khi boot. OS liên tục gọi các ACPI method trong suốt quá trình chạy, khi device được probe, khi system sleep, khi device mất điện, khi user nhấn power button.
Cấu trúc ACPI tables
Firmware publish một cây bảng. OS tìm điểm vào qua RSDP (Root System Description Pointer), từ đó walk sang các bảng khác:
RSDP → XSDT
├─ FADT → DSDT (AML chính)
├─ SSDT (AML bổ sung)
├─ MADT (interrupt controller)
├─ MCFG (PCIe ECAM base)
└─ ... (các table khác tùy platform)
Các bảng quan trọng nhất với firmware engineer:
| Table | Tên đầy đủ | Vai trò khi debug |
|---|---|---|
| FADT | Fixed ACPI Description Table | Chứa PM register info, ACPI flags và pointer tới DSDT |
| DSDT | Differentiated System Description Table | AML chính của platform, chứa device namespace và control methods như _STA, _CRS, _PS0, _PRW |
| SSDT | Secondary System Description Table | Bổ sung namespace theo CPU, device, SKU hoặc Setup option |
| MADT | Multiple APIC Description Table | Mô tả APIC và interrupt routing, sai ở đây thường gây lỗi SMP hoặc interrupt |
| MCFG | PCI ECAM Table | Cho OS biết base address để access PCI config space qua ECAM |
AML: ngôn ngữ chạy trong OS
Phần hay nhất, và cũng phức tạp nhất, của ACPI là AML, ACPI Machine Language.
Firmware viết ACPI Source Language (ASL), compiler dịch sang AML binary, AML được nhúng vào DSDT/SSDT. OS có một interpreter chạy AML này ở runtime.
// ASL source, firmware engineer viết cái này
Device (PWRB) { // Power Button device
Name (_HID, "PNP0C0C")
Method (_STA, 0) {
Return (0x0F) // Present, enabled, visible, functioning
}
}
Device (SLPB) { // Sleep Button
Name (_HID, "PNP0C0E")
Method (_PRW, 0) { // Power Resource for Wake
Return (Package() { 0x1D, 0x04 }) // GPE 0x1D, wakes from S4
}
}
Khi OS muốn biết power button có hoạt động không, nó gọi _STA. Khi OS muốn biết sleep button có thể wake từ S4 không, nó gọi _PRW. Firmware không cần biết OS sẽ hỏi lúc nào, nó chỉ cần viết đúng các method này.
Power state: ACPI định nghĩa, OS quyết định, firmware mô tả
ACPI định nghĩa các Global System States từ S0 đến S5:
| State | Ý nghĩa | Ghi chú khi debug |
|---|---|---|
| S0 | Working, hệ thống đang chạy | S0ix / Modern Standby cũng nằm trong S0 |
| S3 | Suspend to RAM | DRAM giữ dữ liệu, device/rail tắt, resume nhanh |
| S4 | Hibernate | State lưu xuống storage, hệ thống gần như tắt hoàn toàn |
| S5 | Soft Off | Tắt mềm, chỉ còn logic wake và power button |
| G3 | Mechanical Off | Mất nguồn hoàn toàn, không phải S-state trong cùng nghĩa với S0-S5 |
Khi OS muốn sleep, ví dụ vào S3, nó không chỉ tắt màn hình. Nó cần một chuỗi chuẩn bị:
- Gọi
_PTS(Prepare To Sleep), firmware chuẩn bị platform - Tắt device từng cái theo
_PS3của mỗi device - Gọi method tắt power resource nếu platform có mô tả
- Ghi vào PM Control Register để chipset vào sleep state
- Khi có wake event, firmware chạy lại một phần khởi động
- OS gọi
_WAK, firmware restore state cần thiết - Device được bật lại theo
_PS0
Đây là lý do firmware không nên “tắt máy trực tiếp” bằng một GPIO riêng lẻ trong flow bình thường. Mỗi bước trong ACPI power transition đều có lý do. Nếu bỏ qua _PS3 của một device, device đó có thể ở trạng thái undefined sau khi bật lại. Nếu bỏ qua _PTS, EC có thể không được thông báo về sleep state sắp xảy ra.
Firmware viết ACPI ở đâu trong boot flow?
ACPI tables được tạo và publish trong DXE phase, trước khi BDS load OS:
Platform DXE module
Đọc Setup option, board config, SKU và policy
Patch DSDT/SSDT
Tạo hoặc chỉnh ACPI table theo config thực tế
InstallAcpiTable()
Gọi EFI_ACPI_TABLE_PROTOCOL->InstallAcpiTable()
Load OS
BDS load OS loader
Read ACPI
OS đọc tables qua RSDP và interpret AML
Điều quan trọng: ACPI table phản ánh Setup option. Nếu user tắt một feature trong BIOS Setup, firmware có thể patch _STA của device tương ứng để trả 0x00, device biến mất khỏi OS dù phần cứng vẫn có trên board.
Đây là nguồn gốc của nhiều bug khó giải thích: device không có trong Device Manager dù đo điện thì vẫn có điện. Không phải driver OS sai, là _STA đang trả 0x00 vì một Setup option nào đó đang tắt nó.
Kịch bản thực tế: sleep/wake sai sau khi thay BIOS
Một pattern rất hay gặp khi làm BIOS:
Triệu chứng: máy sleep OK, nhưng sau resume touchpad/USB mất
Cách debug đúng không phải cài lại driver OS. Mà là đi theo ACPI.
Bước 1: Xác định device nào mất sau resume
Device Manager hoặc lspci, lsusb, dmesg trên Linux có thể giúp xác định device nào có warning hoặc không quay lại sau resume.
Bước 2: Dump ACPI tables
# Linux
sudo acpidump -o acpi.dat
acpixtract acpi.dat
iasl -d DSDT.dat SSDT*.dat
Bước 3: Tìm method liên quan device đó
Tìm _PS0 và _PS3 của device trong AML đã decompile. Kiểm tra:
- Power sequence có đúng không: rail → delay → clock → reset
- GPIO state sau resume có được restore không
- EC command có được gửi lại không
Bước 4: Kiểm tra _PRW của device
// _PRW không đúng có thể gây instant wake
Method (_PRW, 0) {
Return (Package() { 0x1D, 0x03 }) // GPE, sleep state
}
Nếu GPE trong _PRW bị active trước khi sleep, máy sẽ wake ngay lập tức sau khi vừa sleep.
Checklist debug sleep/wake và ACPI
SMM và ACPI: hai tầng khác nhau, không phải đối thủ
Để kết lại câu hỏi ban đầu: SMM và ACPI không cạnh tranh nhau. Chúng có vai trò khác nhau.
SMM xử lý service bảo mật nhỏ, bảo vệ resource, xử lý event mà OS không nên biết. Nó chạy nhanh và không nên làm những việc lớn như quản lý power state bình thường.
ACPI là hợp đồng giữa firmware và OS về toàn bộ hardware description và power management. Mọi thứ liên quan đến power state, device enumerate, sleep/wake đều phải đi qua ACPI model.
Trong shutdown bình thường, OS/OSPM là bên đọc _S5, chuẩn bị hệ thống, rồi yêu cầu chipset vào S5 bằng SLP_TYP và SLP_EN.
Nếu là thermal emergency thật sự, platform thường dùng đường bảo vệ riêng như EC, PMIC, chipset thermal trip hoặc board-specific safety logic. Đó là cơ chế bảo vệ khẩn cấp, không phải flow shutdown ACPI bình thường.
Tóm tắt
- ACPI là hợp đồng firmware viết, OS đọc, mô tả hardware, power state, và control method
- AML là bytecode trong DSDT/SSDT, OS interpreter chạy ở runtime khi cần
- Power state (S0-S5) được ACPI định nghĩa, OS quyết định, firmware mô tả và hỗ trợ bằng table/method
- Firmware không nên toggle GPIO để tắt máy vì bypass power sequence, không portable, và sai ownership trong flow bình thường
- Debug device mất hoặc sleep/wake sai nên bắt đầu từ ACPI, dump table, decompile AML, kiểm tra method
Tài liệu tham khảo
- ACPI Specification, uefi.org, spec chính thức của ACPI, free download
- iasl compiler, acpica.org, tool decompile AML sang ASL, cross-platform
- ACPICA Project, GitHub, reference interpreter và tools, open source
- EDK II ACPI modules, GitHub, ACPI DXE driver reference
- AMI Aptio 5.x Status Codes, POST code reference
Đọc tiếp
- ACPI Table Types cần biết
- ACPI Method là gì?
- Power State S0-S5 là gì?
- Power Sequence là gì?
- SMM Architecture Overview
- DXE Phase: Driver, Protocol và cách đọc log
- SMM trong UEFI: System Management Mode từ góc debug
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.
DSDT vs SSDT khác nhau thế nào?
Quicknote phân biệt DSDT và SSDT trong ACPI.
AML là gì?
Quicknote giải thích ACPI Machine Language.
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ế.
Đọc thêm về BIOS/UEFI
Khám phá các bài viết về BIOS/UEFI, embedded firmware, debugging và system-level thinking.