c-如何在LattePanda上启用ACPI(用于关闭电源)



我编写此代码是为了使用ACPI通过从64位UEFI启动的程序关闭计算机。

(很抱歉代码太长,但我认为所有部件都是必需的(

#include <stdint.h>
#define in8(data, port) __asm__ __volatile__ 
("xor %%eax, %%eaxntin %%dx, %%alnt" : "=a"(data) : "d"(port))
#define in16(data, port) __asm__ __volatile__ 
("xor %%eax, %%eaxntin %%dx, %%axnt" : "=a"(data) : "d"(port))
#define out8(data, port) __asm__ __volatile__ 
("out %%al, %%dxnt" : : "a"(data), "d"(port))
#define out16(data, port) __asm__ __volatile__ 
("out %%ax, %%dxnt" : : "a"(data), "d"(port))
void initSerialPort(void) {
/* set speed to 115200bps */
out8(0x83, 0x03FB); /* enable LSB/MSB register */
out8(0x00, 0x03F9); /* MSB */
out8(0x01, 0x03F8); /* LSB */
/* set line info */
out8(0x03, 0x03FB); /* disable LSB/MSB register, no parity, no 2-bit stop, 8-bit data */
/* set modem info */
out8(0x03, 0x03FC); /* no loopback, no interrupt, RTS on, DTR on */
/* enable FIFO */
out8(0x07, 0x03FA); /* interrupt at 1 byte, clear TX, clear RX, enable */
/* disable interrupt */
out8(0x00, 0x03F9);
}
void printChar(int c) {
int status;
/* wait until TX buffer is empty */
do {
in8(status, 0x03FD);
} while (!(status & 0x20));
/* put data to send */
out8(c, 0x03F8);
}
void printString(const char* str) {
while (*str != '') printChar((unsigned char)*(str++));
}
void printInt(uint64_t value, int radix) {
char vStr[128] = "";
char* pStr = vStr + 120;
do {
*(pStr--) = "0123456789ABCDEF"[value % radix];
value /= radix;
} while (value > 0);
printString(pStr + 1);
}
void stop(void) {
__asm__ __volatile__(
"clint"
"1:nt"
"hltnt"
"jmp 1bnt"
);
}
char* searchPuttern(char* text, uint64_t textSize, const char* puttern, uint64_t putternSize) {
uint64_t i, j;
if (textSize < putternSize) return 0;
for (i = 0; i <= textSize - putternSize; i++) {
int ok = 1;
for (j = 0; j < putternSize; j++) {
if (text[i + j] != puttern[j]) {
ok = 0;
break;
}
}
if (ok) return text + i;
}
return 0;
}
void entry(void* unused, uint64_t* table) {
uint64_t* guidTable;
uint64_t guidTableNumElements;
uint64_t i;
uint64_t* rsdp;
uint32_t* rsdt, *xsdt;
uint32_t* fadt_from_rsdt, *fadt, *dsdt;
uint64_t xsdtNumElements;
uint32_t smi_cmd, acpi_enable, pm1a_cnt_blk, pm1b_cnt_blk;
uint32_t amlLength;
char* aml, *s5;
int pm1a_value, pm1b_value;
int status;
int printLimit;
(void)unused;
initSerialPort();
/* parse things to get required values */
printString("argument table = 0x"); printInt((uint64_t)table, 16); printChar('n');
guidTable = (uint64_t*)table[14];
guidTableNumElements = table[13];
printString("GUID table = 0x"); printInt((uint64_t)guidTable, 16); printChar('n');
printString("GUID table size = "); printInt(guidTableNumElements, 10); printChar('n');
rsdp = 0;
for (i = 0; i < guidTableNumElements; i++) {
if (guidTable[i * 3 + 0] == UINT64_C(0x11D3E4F18868E871) &&
guidTable[i * 3 + 1] == UINT64_C(0x81883CC7800022BC)) {
rsdp = (uint64_t*)guidTable[i * 3 + 2];
break;
}
}
if (rsdp == 0) {
printString("RSDP not foundn");
stop();
}
printString("RSDP = 0x"); printInt((uint64_t)rsdp, 16); printChar('n');
printString("RSDP signature = 0x"); printInt(rsdp[0], 16); printChar('n');
rsdt = (uint32_t*)(rsdp[2] & UINT64_C(0xffffffff));
xsdt = (uint32_t*)rsdp[3];
printString("RSDT = 0x"); printInt((uint64_t)rsdt, 16); printChar('n');
fadt_from_rsdt = 0;
if (rsdt != 0) {
uint64_t rsdtNumElements;
printString("RSDT signature = 0x"); printInt(rsdt[0], 16); printChar('n');
printString("RSDT length = "); printInt(rsdt[1], 10); printChar('n');
rsdtNumElements = (rsdt[1] - 36) / 4;
fadt = 0;
for (i = 0; i < rsdtNumElements; i++) {
uint32_t* addr = (uint32_t*)(uint64_t)rsdt[9 + i];
printString("*0x"); printInt((uint64_t)addr, 16);
printString(" = 0x"); printInt(addr[0], 16);
printChar('n');
if ((addr[0] & UINT64_C(0xffffffff)) == UINT64_C(0x50434146)) {
fadt_from_rsdt = addr;
}
}
}
printString("XSDT = 0x"); printInt((uint64_t)xsdt, 16); printChar('n');
if (xsdt == 0) {
printString("XSDT not foundn");
stop();
}
printString("XSDT signature = 0x"); printInt(xsdt[0], 16); printChar('n');
printString("XSDT length = "); printInt(xsdt[1], 10); printChar('n');
xsdtNumElements = (xsdt[1] - 36) / 8;
fadt = 0;
for (i = 0; i < xsdtNumElements; i++) {
uint32_t* addr = (uint32_t*)((uint64_t*)&xsdt[9])[i];
printString("*0x"); printInt((uint64_t)addr, 16);
printString(" = 0x"); printInt(addr[0], 16);
printChar('n');
if ((addr[0] & UINT64_C(0xffffffff)) == UINT64_C(0x50434146)) {
fadt = addr;
}
}
printString("FADT from RSDT = 0x"); printInt((uint64_t)fadt_from_rsdt, 16); printChar('n');
printString("FADT from XSDT = 0x"); printInt((uint64_t)fadt, 16); printChar('n');
if (fadt == 0) fadt = fadt_from_rsdt;
if (fadt == 0) {
printString("FADT not foundn");
stop();
}
printString("FADT = 0x"); printInt((uint64_t)fadt, 16); printChar('n');
printString("FADT signature = 0x"); printInt(fadt[0], 16); printChar('n');
printString("FADT length = "); printInt(fadt[1], 10); printChar('n');
dsdt = (uint32_t*)(uint64_t)fadt[10];
smi_cmd = fadt[12];
acpi_enable = fadt[13] & 0xff;
pm1a_cnt_blk = fadt[16];
pm1b_cnt_blk = fadt[17];
printString("DSDT = 0x"); printInt((uint64_t)dsdt, 16); printChar('n');
printString("SMI_CMD = 0x"); printInt(smi_cmd, 16); printChar('n');
printString("ACPI_ENABLE = 0x"); printInt(acpi_enable, 16); printChar('n');
printString("PM1a_CNT_BLK = 0x"); printInt(pm1a_cnt_blk, 16); printChar('n');
printString("PM1b_CNT_BLK = 0x"); printInt(pm1b_cnt_blk, 16); printChar('n');
printString("PM1_CNT_LEN = "); printInt((fadt[22] >> 8) & 0xff, 10); printChar('n');
if (fadt[1] >= 148) {
printString("X_DSDT = 0x");
printInt(fadt[35] | ((uint64_t)fadt[36] << 32), 16);
printChar('n');
}
if (fadt[1] >= 184) {
printString("X_PM1a_CNT_BLK = 0x"); printInt(fadt[43], 16);
printString(" 0x"); printInt(fadt[44], 16);
printString(" 0x"); printInt(fadt[45], 16);
printChar('n');
}
if (fadt[1] >= 196) {
printString("X_PM1b_CNT_BLK = 0x"); printInt(fadt[46], 16);
printString(" 0x"); printInt(fadt[47], 16);
printString(" 0x"); printInt(fadt[48], 16);
printChar('n');
}
printString("DSDT signature = 0x"); printInt(dsdt[0], 16); printChar('n');
printString("DSDT length = "); printInt(dsdt[1], 10); printChar('n');
if (dsdt[1] < 36) {
printString("DSDT too shortn");
stop();
}
amlLength = dsdt[1] - 36;
aml = (char*)&dsdt[9];
s5 = searchPuttern(aml, amlLength, "x08_S5_x12", 6);
if (s5 == 0) {
printString("_S5_ not foundn");
stop();
}
printString("_S5_ dump:n");
for (i = 0; i < 16; i++) {
if (i > 0) printChar(' ');
printString("0x"); printInt((unsigned char)s5[i], 16);
}
printChar('n');
if (s5[8] == 0) {
pm1a_value = 0;
if (s5[9] == 0) pm1b_value = 0; else pm1b_value = (unsigned char)s5[10];
} else {
pm1a_value = (unsigned char)s5[9];
if (s5[10] == 0) pm1b_value = 0; else pm1b_value = (unsigned char)s5[11];
}
printString("value for PM1a_CNT.SLP_TYP = 0x"); printInt(pm1a_value, 16); printChar('n');
printString("value for PM1b_CNT.SLP_TYP = 0x"); printInt(pm1b_value, 16); printChar('n');
/* enable ACPI for powering off */
in16(status, pm1a_cnt_blk);
printString("status = 0x"); printInt(status, 16); printChar('n');
if (!(status & 1)) {
printString("sending ACPI_ENABLE to SMI_CMDn");
out8(acpi_enable, smi_cmd);
printLimit = 10;
do {
in16(status, pm1a_cnt_blk);
if (printLimit-- > 0) {
printString("status = 0x"); printInt(status, 16); printChar('n');
}
} while (!(status & 1));
}
/* power off */
printString("switching staten");
in16(status, pm1a_cnt_blk);
out16((status & ~(7 << 10)) | ((pm1a_value & 7) << 10) | (1 << 13), pm1a_cnt_blk);
if (pm1b_cnt_blk != 0) {
in16(status, pm1b_cnt_blk);
out16((status & ~(7 << 10)) | ((pm1b_value & 7) << 10) | (1 << 13), pm1b_cnt_blk);
}
printString("state switch sentn");
stop();
}

我用TDM-GCC(gcc (tdm64-1) 9.2.0(编译了这个。

编译命令为:

C:MyInstalledAppsTDM-GCC-64bingcc -Wall -Wextra -nostdlib -e entry -m64 -Wl,--subsystem=10 acpi_test.c -o bootx64.efi

它不会给我任何警告或错误信息。

我在我的LattePanda(有2G RAM和32G eMMC(上尝试了这个代码,但它没能关闭。查看跟踪,似乎无法通过将ACPI_ENABLE发送到端口SMI_CMD来启用ACPI。我的意思是PM1a_CNT_BLK寄存器中的SCI_EN位似乎没有设置。

我也在QEMU和VirtualBox上尝试过这个代码,并成功地关闭了电源,但它看起来没有帮助,因为这些VM软件中似乎已经启用了ACPI。

我的QEMU版本是QEMU emulator version 5.1.92 (v5.2.0-rc2-11843-gf571c4ffb5-dirty)并使用GitHub-BlankOn/ofmf-blobs:BIOS.bin作为qemu的BIOS来支持UEFI。

根据对串行端口的输出,ACPI_ENABLESMI_CMD的值看起来是合理的。(我不知道它们是否真的正确(

我是不是忽略了什么?我应该怎么做才能在LattePanda上启用ACPI,并从UEFI启动的程序中关闭电源?

LattePanda的串行端口输出:

argument table = 0x7BA13F18
GUID table = 0x7BA12E18
GUID table size = 13
RSDP = 0x7B12E000
RSDP signature = 0x2052545020445352
RSDT = 0x7B12E028
RSDT signature = 0x54445352
RSDT length = 124
*0x7B12E188 = 0x50434146
*0x7B14AB40 = 0x43495041
*0x7B14ABC8 = 0x54445046
*0x7B14AC10 = 0x54444946
*0x7B14ACB0 = 0x4D44534D
*0x7B14AD08 = 0x4746434D
*0x7B14AD48 = 0x54445353
*0x7B14EEC0 = 0x54445353
*0x7B14F518 = 0x54445353
*0x7B14F570 = 0x49464555
*0x7B14F5B8 = 0x54445353
*0x7B14F828 = 0x54455048
*0x7B14F860 = 0x54445353
*0x7B14FFC8 = 0x54445353
*0x7B150258 = 0x54445353
*0x7B1503D8 = 0x5449504C
*0x7B1504E0 = 0x47464342
*0x7B150620 = 0x4D415250
*0x7B150650 = 0x54524742
*0x7B150688 = 0x324D5054
*0x7B1506C0 = 0x54525343
*0x7B150810 = 0x54414457
XSDT = 0x7B12E0A8
XSDT signature = 0x54445358
XSDT length = 212
*0x7B14AA30 = 0x50434146
*0x7B14AB40 = 0x43495041
*0x7B14ABC8 = 0x54445046
*0x7B14AC10 = 0x54444946
*0x7B14ACB0 = 0x4D44534D
*0x7B14AD08 = 0x4746434D
*0x7B14AD48 = 0x54445353
*0x7B14EEC0 = 0x54445353
*0x7B14F518 = 0x54445353
*0x7B14F570 = 0x49464555
*0x7B14F5B8 = 0x54445353
*0x7B14F828 = 0x54455048
*0x7B14F860 = 0x54445353
*0x7B14FFC8 = 0x54445353
*0x7B150258 = 0x54445353
*0x7B1503D8 = 0x5449504C
*0x7B1504E0 = 0x47464342
*0x7B150620 = 0x4D415250
*0x7B150650 = 0x54524742
*0x7B150688 = 0x324D5054
*0x7B1506C0 = 0x54525343
*0x7B150810 = 0x54414457
FADT from RSDT = 0x7B12E188
FADT from XSDT = 0x7B14AA30
FADT = 0x7B14AA30
FADT signature = 0x50434146
FADT length = 268
DSDT = 0x7B12E210
SMI_CMD = 0xB2
ACPI_ENABLE = 0xA0
PM1a_CNT_BLK = 0x404
PM1b_CNT_BLK = 0x0
PM1_CNT_LEN = 2
X_DSDT = 0x7B12E210
X_PM1a_CNT_BLK = 0x2001001 0x404 0x0
X_PM1b_CNT_BLK = 0x1 0x0 0x0
DSDT signature = 0x54445344
DSDT length = 116766
_S5_ dump:
0x8 0x5F 0x53 0x35 0x5F 0x12 0x7 0x4 0xA 0x7 0x0 0x0 0x0 0x14 0x1E 0x5F
value for PM1a_CNT.SLP_TYP = 0x7
value for PM1b_CNT.SLP_TYP = 0x0
status = 0x0
sending ACPI_ENABLE to SMI_CMD
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0
status = 0x0

QEMU的串行端口输出:

argument table = 0x7EED018
GUID table = 0x7EED0D8
GUID table size = 9
RSDP = 0x7EF9014
RSDP signature = 0x2052545020445352
RSDT = 0x7EF8074
RSDT signature = 0x54445352
RSDT length = 52
*0x7EF5000 = 0x50434146
*0x7EF4000 = 0x43495041
*0x7EF3000 = 0x54455048
*0x7EF2000 = 0x54454157
XSDT = 0x7EF80E8
XSDT signature = 0x54445358
XSDT length = 68
*0x7EF5000 = 0x50434146
*0x7EF4000 = 0x43495041
*0x7EF3000 = 0x54455048
*0x7EF2000 = 0x54454157
FADT from RSDT = 0x7EF5000
FADT from XSDT = 0x7EF5000
FADT = 0x7EF5000
FADT signature = 0x50434146
FADT length = 116
DSDT = 0x7EF6000
SMI_CMD = 0xB2
ACPI_ENABLE = 0xF1
PM1a_CNT_BLK = 0xB004
PM1b_CNT_BLK = 0x0
PM1_CNT_LEN = 2
DSDT signature = 0x54445344
DSDT length = 5060
_S5_ dump:
0x8 0x5F 0x53 0x35 0x5F 0x12 0x6 0x4 0x0 0x0 0x0 0x0 0x10 0x3B 0x5C 0x2E
value for PM1a_CNT.SLP_TYP = 0x0
value for PM1b_CNT.SLP_TYP = 0x0
status = 0x1
switching state
state switch sent

VirtualBox 6.1.18 r142142的串行端口输出(Qt5.6.2(:

argument table = 0x6FEE018
GUID table = 0x6FEEC98
GUID table size = 10
RSDP = 0x6FFA014
RSDP signature = 0x2052545020445352
RSDT = 0x6FF9074
RSDT signature = 0x54445352
RSDT length = 52
*0x6FF7000 = 0x50434146
*0x6FF8000 = 0x43495041
*0x6FF3000 = 0x54445353
*0x5E39000 = 0x54524742
XSDT = 0x6FF90E8
XSDT signature = 0x54445358
XSDT length = 68
*0x6FF7000 = 0x50434146
*0x6FF8000 = 0x43495041
*0x6FF3000 = 0x54445353
*0x5E39000 = 0x54524742
FADT from RSDT = 0x6FF7000
FADT from XSDT = 0x6FF7000
FADT = 0x6FF7000
FADT signature = 0x50434146
FADT length = 244
DSDT = 0x6FF4000
SMI_CMD = 0x442E
ACPI_ENABLE = 0xA1
PM1a_CNT_BLK = 0xB004
PM1b_CNT_BLK = 0x0
PM1_CNT_LEN = 2
X_DSDT = 0x6FF4000
X_PM1a_CNT_BLK = 0x2001001 0xB004 0x0
X_PM1b_CNT_BLK = 0x0 0x0 0x0
DSDT signature = 0x54445344
DSDT length = 8997
_S5_ dump:
0x8 0x5F 0x53 0x35 0x5F 0x12 0x6 0x2 0xA 0x5 0xA 0x5 0x14 0x23 0x5F 0x50
value for PM1a_CNT.SLP_TYP = 0x5
value for PM1b_CNT.SLP_TYP = 0x5
status = 0x1
switching state

LattePanda环境:

BIOS Information
BIOS Vendor              American Megatrends
Core Version             5.011
Compliancy               UEFI 2.4; PI 1.3
Project Version          S70CR200 3.06 x64
Build Date and Time      03/30/2018 14:41:43

根据@user3840170的建议,I

  • 从Super Grub2磁盘下载super_grub2_disk_standalone_x86_64_efi_2.04s1.EFI
  • 把它放在我的U盘根上
  • 通过内置UEFI Shell在我的LattePanda上推出
  • 按下菜单上的c进入命令行模式
  • 键入以下命令:
serial --speed=115200
terminal_output --append serial
set debug=acpi
halt

然后,我得到了下面的日志,我的LattePanda关机了

grub> halt
commands/acpihalt.c:403: rsdp1=0x7b12e000
commands/acpihalt.c:423: PM1a port=404
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 24
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 2e
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 34
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 3c
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 43
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 4d
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 55
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 5d
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 64
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 6b
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 75
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 7d
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 87
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 8f
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 99
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell a3
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell a9
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell af
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell b5
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell bb
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell c1
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell c7
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell cd
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell d3
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell d9
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell e1
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell eb
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell f5
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell fc
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 103
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 10a
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 111
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 118
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 11f
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 125
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 12b
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 131
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 137
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 13d
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 143
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 149
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 153
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 15d
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 167
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 171
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 177
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 17d
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 187
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 191
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 19b
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 1a5
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 1ab
commands/acpihalt.c:107: data type = 0xa
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 1b2
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x5b
commands/acpihalt.c:242: Tell 1bc
commands/acpihalt.c:188: Extended opcode: 0x80
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x5b
commands/acpihalt.c:242: Tell 1cb
commands/acpihalt.c:188: Extended opcode: 0x81
commands/acpihalt.c:241: Opcode 0x14
commands/acpihalt.c:242: Tell 84f
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 858
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 862
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 868
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 86e
commands/acpihalt.c:107: data type = 0x0
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 874
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 87a
commands/acpihalt.c:107: data type = 0xb
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 882
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 88c
commands/acpihalt.c:107: data type = 0xc
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 896
commands/acpihalt.c:107: data type = 0x1
commands/acpihalt.c:241: Opcode 0x10
commands/acpihalt.c:242: Tell 89c
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 8a3
commands/acpihalt.c:107: data type = 0x11
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8b2
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8bb
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8c4
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8cd
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8d6
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8df
commands/acpihalt.c:241: Opcode 0x6
commands/acpihalt.c:242: Tell 8e8
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 8f1
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell a42
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell b65
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell b9f
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell bd1
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell c0b
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell c3d
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell c77
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell ca9
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell ce3
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x10
commands/acpihalt.c:242: Tell d15
commands/acpihalt.c:241: Opcode 0x5b
commands/acpihalt.c:242: Tell d1d
commands/acpihalt.c:188: Extended opcode: 0x82
commands/acpihalt.c:241: Opcode 0x10
commands/acpihalt.c:242: Tell 207b
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 2081
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 208d
commands/acpihalt.c:107: data type = 0x12
commands/acpihalt.c:241: Opcode 0x8
commands/acpihalt.c:242: Tell 209a
commands/acpihalt.c:269: S5 found
commands/acpihalt.c:444: SLP_TYP = 7, port = 0x404

RSDP地址、PM1a端口和SLP_TYP看起来与我的程序获得的相同。

我不知道这是否真的会有帮助,但我注意到与GRUB中的ACPI断电实现有一些不同(正如询问者所报告的,它确实有效(:

  1. GRUB不需要向SMI端口发送任何东西。GRUB只有一次执行任何端口I/O,那就是写入PM1A寄存器。(PM1B也不麻烦。(grub-core/commands/acpihalt.c中的所有其他代码都只是用于定位和解析ACPI表。是的,grub_acpi_halt似乎是在没有任何先前ACPI初始化调用的情况下冷调用的。不过,它似乎确实提前释放了EFI资源,如grub-core/lib/efi/halt.cgrub-core/kern/i386/efi/init.c所示,并最终释放了grub-core/kern/efi/init.c(但并没有终止EFI引导服务(。

  2. GRUB不保留"未使用"的PM1A寄存器位。询问者的代码首先读取PM1A寄存器,以便仔细屏蔽它不想修改的位字段。GRUB并不在意,它只是把零放在那里。从询问者的代码翻译成名字,似乎可以进行

    out16((1 << 13) | (pm1a_value << 10), pm1a_cnt_blk);
    

因此,首先我建议完全删除ACPI_ENABLE位,然后调整对PM1A端口的写入。ACPI 6.0规范的文本表明,只有当您真正希望接收和处理SCI中断时,才需要前者;如果你只想关闭系统,你可能会跳过它。

最新更新