2

APM shutdown has been covered at X86 instructions to power off computer in real mode?

How to reboot instead of shutting down the computer? Please quote and explain the relevant documentation / standard in your answer.

I've understood that APM and ACPI are the two main methods, and I'm interested in both. Let me know if there are others.

I have found the ACPI spec is at http://uefi.org/specifications but it's taking too much brainpower to parse it that I found it worthy of a question.

I could not find the URL for the APM spec, only a Google cache of a Microsoft RTF here.

If you need a way to test your answer, this minimal APM shutdown boot sector example may be a good starting point. The goal is to convert it to a reboot example instead.

I have read the Linux kernel 4.2 code at arch/x86/realmode/rm/reboot.S but I don't understand how it works, since I can't find the difference between those commands and my working shutdown example.

Related more generic on superuser: https://superuser.com/questions/294681/how-does-a-computer-restart-itself

Related question for protected mode: Rebooting in Protected Mode

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985

2 Answers2

3

I use the following code in a floppy-disk boot image to reset the pc if the kernel files aren't present on the boot media.

Reboot:
    db 0x0ea 
    dw 0x0000 
    dw 0xffff 

Which essentially assembles to the following instruction:

jmp     far ptr 0FFFFh:0 

I think it's a warm-reboot, i.e equivalent to hitting Ctrl-Alt-Delete, as opposed to hitting the reset button on the front of the machine.

enhzflep
  • 12,927
  • 2
  • 32
  • 51
  • That worked! GAS syntax: `ljmpw $0xFFFF, $0x0000`. [Working minimal example](https://github.com/cirosantilli/x86-bare-metal-examples/blob/6606a2647d44bc14e6fd695c0ea2b6b7a5f04ca3/reboot.S). Linux kernel is doing `ljmpw $0xf000, $0xfff0` on the linked file, which also works. But *why* does it work? Where is it documented? – Ciro Santilli OurBigBook.com Sep 21 '15 at 07:50
  • 1
    Brilliant. According to the answer here: http://stackoverflow.com/questions/31296422/weird-assembly-in-bootloader-causes-computer-to-reboot and the contained link, here: https://en.wikipedia.org/wiki/Reset_vector it's because the address 0xFFFF0 is the address of the reset-vector, or the address of the first instruction the cpu should execute when it begins operation. I guess that means it has to be a warm-boot - the RAM still contains the data that was already in it. – enhzflep Sep 21 '15 at 13:14
  • If you are using `ljmpw $0xFFFF, $0x0000` be aware that this is fine if your target CPU is an 8088/8086. On a 286 it was recommended to `ljmpw $0xF000, $0xFFF0` . Although this looks the same, most 386+ now boot in unreal mode with CS segment descriptor 0xF000 pointing at the physical address at the REAL top area of memory where special firmware often resides (not necessarily region <1mb). It use to be advised that enabling the A20 was a good idea before such a far jmp. For what its worth the entry point for the BIOS is `0xf000:0xe05b` which is why some versions of Linux jump there instead. – Michael Petch Sep 21 '15 at 16:04
  • 1
    And if one wants to be pedantic about this prior to jumping to `0xF000:0xFFF0` you can always consider writing to the `BDA` at `0x0000:0x0472`.If you store the word `0x1234` @ that location a warm boot should be done when you `jmp to 0xF000:0xFFF0`.Typically if you store the word `0x0000` @ `0x0000:0x0472` it should cold reboot when you jmp to the BIOS.Jumping to the BIOS like this isn't guaranteed to work so if ACPI is present issuing the reboot that way is preferred, if that fails drop back to the method of resetting via keyboard controller (just like on the 286). If that fails then try BIOS – Michael Petch Sep 21 '15 at 16:51
  • Is rebooting a PC easy?Not according to Linux Developer Matthew Garrett.I discovered He wrote this [blog](http://mjg59.livejournal.com/137313.html) on the subject.He also wrote this [email](https://lkml.org/lkml/2011/4/6/113) about how Windows certified machines get rebooted by a Windows OS and how even Linux will often hang a PC during reboot.The 286 KBD reset discussed is document on [OSDev](http://wiki.osdev.org/Reboot). If you review all the [reboot.c code](http://lxr.free-electrons.com/source/arch/x86/kernel/reboot.c) you find they resort to specific methods depending on computer model – Michael Petch Sep 21 '15 at 19:03
  • @MichaelPetch please put those comments in an answer and get rep! :-) – Ciro Santilli OurBigBook.com Sep 25 '15 at 08:38
0

Works on my old pc 8086:

mov ds, ax
mov ax,0000
mov [0472], ax
jmp FFFF:000
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
chris_cx
  • 55
  • 11
  • 1
    Where did you get this from? Why do each operation? – Ciro Santilli OurBigBook.com Feb 02 '16 at 15:24
  • 3
    I believe that a warm reboot should be set by moving `0x1234` to 0x0000:0x0472. You should be setting _DS_ to 0, and putting 0x1234 into memory location DS:0x0472. I also believe that you meant 0472h not 0472 (which is decimal) – Michael Petch Feb 03 '16 at 19:40
  • I used debug. com to compile it, no need 0472h in that case source: http://computer-programming-forum.com/46-asm/92f051fd8d60ee50.htm – chris_cx Feb 04 '16 at 11:14
  • 2
    Even if the decimal value 0472 wasn't a problem (because of the use of DEBUG.COM) you should clearly state what is the value in `AX` that you move into the `DS` register. – Fifoernik Feb 04 '16 at 11:28
  • ok. but I have no issue, I just answered the question, on real 8086 hardware, that code works fine – chris_cx Feb 04 '16 at 17:35