如何从独立环境关闭计算机?
我正在制作一个基于 Intel x86 架构的保护模式操作系统,并且正在寻找一些有关如何通过汇编代码或类似代码关闭计算机电源的信息。你能帮我解决这个问题吗?
I'm making a protected-mode OS based on Intel's x86 architecture, and was looking for some information on how to power off the computer via assembly code, or something like that. Could you help me with this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
来自 http://forum.osdev.org/viewtopic.php?t=16990
ACPI 关闭从技术上来说是一件非常简单的事情,所需要的只是一个 outw(PM1a_CNT, SLP_TYPa | SLP_EN );并且计算机已关闭。
问题在于这些值的收集,特别是因为 SLP_TYPa 位于 DSDT 中的 _S5 对象中,因此是 AML 编码的。
下面是一个简单的“地图”,显示了在哪里可以找到这些字段。
要导出
\_S5
对象,通常会使用 AML 解释器,但考虑到我们正在构建一个业余爱好操作系统,这显然不是一种选择。简单的解决方案是手动扫描 DSDT。 AML 语言指定 _... 对象仅定义一次,这使得查找\_S5
对象变得非常简单,因为简单的memcmp()
就足够了。一旦找到,
SLP_TYPx
值就会被提取。信息的收集最好在操作系统初始化时执行,因为之后您可以重复使用 RAM,而无需担心损坏它。
现在只剩下
outw(PM1a_CNT, SLP_TYPa | SLP_EN );
了。如果
PM1b_CNT != 0
您需要用b重复它。如果这有点太抽象了,这里有一些代码可供查看。
有关更多信息,请阅读 ACPI 1.0a 规范的相应部分。
这适用于我所有的机器 bochs 和 qemu。
但我注意到无需启用 ACPI 即可让电脑断电。虽然我不知道情况是否总是如此。
如果你只是想玩一点。
对于 bochs 和 qemu,它是
outw( 0xB004, 0x0 | 0x2000 );
from http://forum.osdev.org/viewtopic.php?t=16990
The ACPI shutdown is technically a really simple thing all that is needed is a outw(PM1a_CNT, SLP_TYPa | SLP_EN ); and the computer is powered off.
The problem lies in the gathering of these values especially since the SLP_TYPa is in the _S5 object which is in the DSDT and therefore AML encoded.
Below is a simple "map" of where to find these fields.
To export the
\_S5
object one would normally use an AML interpreter but that's obviously not an option considering we're building a hobby OS. The simple solution is to scan the DSDT manually. The AML language specifies that _... objects are defined only once which makes it very simple to find the\_S5
object since a simplememcmp()
is enough.Once found the
SLP_TYPx
values are extracted.The gathering of the information is best performed at OS initialization because after that you can reuse the ram and don't need to worry about corrupting it.
Now all that remains is
outw(PM1a_CNT, SLP_TYPa | SLP_EN );
and you're gone.If
PM1b_CNT != 0
you need to repeat it with b.If that was a little too abstract here is some code to look at
For further information read the corresponding sections of the ACPI 1.0a specification
This works on all of my machines bochs and qemu.
but I noticed that one needn't enable ACPI for the pc to power down. Though i don't know if this is always the case.
If you just want to play a little.
For bochs and qemu it's
outw( 0xB004, 0x0 | 0x2000 );
APM
https://en.wikipedia.org/wiki/Advanced_Power_Management
在
qemu-system-i386
2.0.0 Ubuntu 14.04 上测试的方法:有关 QEMU 上的确切编译和运行步骤,查看此存储库
osdev.org 文章:http://wiki.osdev.org/Shutdown , http:// wiki.osdev.org/APM
ACPI 是更新、更好的方法。
APM
https://en.wikipedia.org/wiki/Advanced_Power_Management
Method tested on
qemu-system-i386
2.0.0 Ubuntu 14.04:For the exact compilation and running steps on QEMU, see this repo
osdev.org articles: http://wiki.osdev.org/Shutdown , http://wiki.osdev.org/APM
ACPI is the newer, better method.