Page 2 of 3

Re: How is MOVSD supposed to work?

Posted: Sun Jun 12, 2016 1:08 am
by RobbieE
@neon

Would checking for a wrap-around be a definitive test?

Something along the lines of:

Code: Select all

GateA20Test:
Write X to 0x0
Write X to 0x100000
if ([0x0] == [0x100000])
  goto GateA20Open;
else
  useNextA20EnablingFunction;
  goto GateA20Test

Re: How is MOVSD supposed to work?

Posted: Sun Jun 12, 2016 1:22 am
by SpyderTL
Yea, this would work. It's even mentioned on the A20 wiki page.

However, memory address 0x00 may be used by something, like the real mode interrupt table. So you might not want to change that particular value.

The wiki page suggests changing the boot loader signature value, since you know exactly where it is, and you know it's not being used by anything.

Re: How is MOVSD supposed to work?

Posted: Sun Jun 12, 2016 1:41 am
by alexfru
SpyderTL wrote:However, memory address 0x00 may be used by something, like the real mode interrupt table. So you might not want to change that particular value.
Address of the system-wide division overflow (/by 0) handler. If you have none of your own and do not intend to cause and handle division overflows, chances are, this is a rather useless one and whether it's restored to its original value or left corrupted, the handler won't be able to do anything meaningful (return, causing an infinite loop, reset the CPU, etc) anyway.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 12:20 pm
by ~
MOVSD moves 4 bytes.

You can use REP with a counter in ECX instead of a software loop using JNZ.

The source buffer is in DS:ESI.

The destination buffer is in ES:EDI.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 2:38 pm
by iansjack
I think you can take it that the OP already knew that. (That's exactly how they used the instruction.)

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 4:18 pm
by neon
You can use int 15h function 2403h and int 15h function 2402h to check for A20. Modern systems should support these.

You don't have to use 0 and 1MB. Testing using the boot loader signature (as was suggested above) and compare address 0:7dfe with ffff:7e0e, if they are the same, then you know A20 is not enabled. This is the safest route.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 6:32 pm
by ~
neon wrote:You can use int 15h function 2403h and int 15h function 2402h to check for A20. Modern systems should support these.

You don't have to use 0 and 1MB. Testing using the boot loader signature (as was suggested above) and compare address 0:7dfe with ffff:7e0e, if they are the same, then you know A20 is not enabled. This is the safest route.
An even safer route would involve using VM86 mode.

What we would do is to launch a V86-mode task that is different than the main task.

Then we can test the INT 15h functions 2402h and 2403h.

In some ancient 386DX machines, these functions, as well as the functions to retrieve the motherboard's memory map, make the whole system crash. I don't know if there are laptops or pocket x86 PCs that could fail in similar ways.

So, with a V86 task, these functions will either have no effect, crash the whole system (in this case only crash the V86 task), or succeed.

In any case, if they fail to enable the A20 or to retrieve the memory map, we will be able to terminate the secondary V86 task even if it's crashed, and we will have the chance to test an alternate method without failing.

But this is already a system prepared to run in widely nonstandard hardware. I guess it's always good to eventually add that support as long as you really need it in practice, so you can understand how it really works closely.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 8:34 pm
by Octocontrabass
~ wrote:In some ancient 386DX machines, these functions, as well as the functions to retrieve the motherboard's memory map, make the whole system crash.
Do you have any examples of such systems? (Ideally, I'd like a copy of the BIOS ROM so I can examine it.)

I have found two systems where memory map functions cause crashes. One crashes when calling int 0x15 function 0xe881, but that function isn't valid in real mode. The other crashes when calling int 0x15 function 0x8a, but that can be avoided by calling better functions first and only using it as a fallback when no better functions are available.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 10:32 pm
by Kazinsal
When fiddling with A20, do not poke the keyboard controller unless you know for sure it's there. If it's not there, at best, you'll get nothing back. More likely, you'll hang or reset the system.

Best thing to do is ask the BIOS to do it for you, and if you really feel the need to do it yourself, you need to go through the ACPI tables and see if there's a keyboard controller present (you're looking for the IA-PC boot architecture flag word in the Fixed ACPI Description Table.)

Welcome to the rabbit hole that is operating systems development.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 10:51 pm
by ~
Kazinsal wrote:When fiddling with A20, do not poke the keyboard controller unless you know for sure it's there. If it's not there, at best, you'll get nothing back. More likely, you'll hang or reset the system.

Best thing to do is ask the BIOS to do it for you, and if you really feel the need to do it yourself, you need to go through the ACPI tables and see if there's a keyboard controller present (you're looking for the IA-PC boot architecture flag word in the Fixed ACPI Description Table.)

Welcome to the rabbit hole that is operating systems development.
If you reset the system, the KBC is more likely there. That's another of its functions, and if you aren't careful you can reset the system at the same time that you're trying to enable the A20.

There's no way to hang the system, unless you use an infinite loop and a specific, real machine model that is known for not having a KBC. Also, at this point no other modern peripherals would use I/O ports or memory regions of legacy devices. It would make things much more dirty regardless of whether they are still there or not.

In any case, encapsulating the critical initialization tasks in snippets running under V86 tasks, there's no way to hang or crash the system, just that particular task. We just need to check whether the task finishes the initialization successfully after a normal and short period of time, or else terminate it, assume it crashed or failed, and try another way. In this way it's warrantied that we will always find the right way to initialize the system.

The key is to use V86 tasks to call critical BIOS code through INT instructions at the time that it will protect us from any failure and then we will be able to actually complete the initialization of the system without letting it crash or hang by running extremely critical stuff directly in a vulnerable Real Mode environment.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 11:08 pm
by Kazinsal
~ wrote:If you reset the system, the KBC is more likely there. That's another of its functions, and if you aren't careful you can reset the system at the same time that you're trying to enable the A20.
If the system resets or hangs when you frob the A20 line or the keyboard status port then you don't have a keyboard controller. Simple as that.
There's no way to hang the system, unless you use an infinite loop and a specific, real machine model that is known for not having a KBC. Also, at this point no other modern peripherals would use I/O ports or memory regions of legacy devices. It would make things much more dirty regardless of whether they are still there or not.
False. You can definitely hang a system that has no keyboard controller just by attempting to read from or write to it once, no loops involved. See all x86 Macs.

Re: How is MOVSD supposed to work?

Posted: Tue Jun 14, 2016 11:57 pm
by Brendan
Hi,
~ wrote:The key is to use V86 tasks to call critical BIOS code through INT instructions at the time that it will protect us from any failure and then we will be able to actually complete the initialization of the system without letting it crash or hang by running extremely critical stuff directly in a vulnerable Real Mode environment directly.[/b]
The added complexity/hassle of v86 mode crud is far more likely to cause problems/bugs that wouldn't have existed otherwise than it is to successfully work-around bugs that only exist in extremely rare cases. For a simple example, there's at least one "PXE ROM" implementation that hooks "int 0x15" (to steal/reserve memory that it uses) that also switches to/from protected mode (partly to access the NIC's memory mapped registers and partly because I suspect it's mostly written in 32-bit C) where attempting to use v86 mode will cause it to crash (because you can't expect to re-enable protected mode in CR0 when you're in v86 mode).

For A20, test if it's already enabled, and if it's not then use the BIOS function and test again. If A20 is disabled after that, then it's an ancient computer and you can safely assume the KBC exists. Most (all?) 80x86 computers that don't have a PS/2 controller use UEFI (where A20 is never disabled) anyway.

For getting memory map; do it in "best first" order (e.g. starting with "int 0x15, eax=0xE820") and skip "int 0x15, eax=0xE881". Note: I do have a 75 MHz Pentium machine which locks up when "int 0x15, eax=0xE881" is called (which would probably lock up exactly the same if you used v86).


Cheers,

Brendan

Re: How is MOVSD supposed to work?

Posted: Wed Jun 15, 2016 12:09 am
by Octocontrabass
Brendan wrote:Note: I do have a 75 MHz Pentium machine which locks up when "int 0x15, eax=0xE881" is called (which would probably lock up exactly the same if you used v86).
That's because int 0x15 function 0xe881 is designed to be called from 32-bit protected mode; of course it won't work if you call it in real mode or v86 mode. It probably works on that computer, if you can figure out how to call it properly!

Re: How is MOVSD supposed to work?

Posted: Wed Jun 15, 2016 12:38 am
by Brendan
Hi,
Octocontrabass wrote:
Brendan wrote:Note: I do have a 75 MHz Pentium machine which locks up when "int 0x15, eax=0xE881" is called (which would probably lock up exactly the same if you used v86).
That's because int 0x15 function 0xe881 is designed to be called from 32-bit protected mode; of course it won't work if you call it in real mode or v86 mode. It probably works on that computer, if you can figure out how to call it properly!
It's NOT designed to be called from protected mode. That doesn't even make any sense.

Protected mode needs a completely different interrupt descriptor table (IDT with 8-byte entries and not IVT with 4-byte entries), and a GDT or LDT with defined descriptors. To make something usable in protected mode would require (at a minimum) well defined "code and data segment descriptor details" and entry point (e.g. like the protected mode interface/s VBE provides); and not "int 0x15".


Cheers,

Brendan

Re: How is MOVSD supposed to work?

Posted: Wed Jun 15, 2016 1:07 am
by Octocontrabass
Brendan wrote:It's NOT designed to be called from protected mode. That doesn't even make any sense.
I only use the "int 0x15" name because it's handled by the int 0x15 dispatcher; I have no idea how you're actually supposed to call it.

I've disassembled one BIOS that supports int 0x15 function 0xe881. Its int 0x15 dispatcher explicitly avoids using any instructions that would differ between 16- and 32-bit mode before the branch to the function 0xe881 handler. The function 0xe881 handler disassembles to nonsense in 16-bit mode, but in 32-bit mode it disassembles to a function that loads EAX, EBX, ECX, and EDX to the expected values and then returns. It returns the same values as int 0x15 function 0xe801.

It's obviously meant to be called in the same way as the 32-bit EISA BIOS functions (int 0x15 functions 0xd880-0xd8ff), which are handled similarly by this BIOS. Unfortunately, I haven't found any real documentation on how those were supposed to be called, either. RBIL only mentions them briefly on the 16-bit equivalents (int 0x15 functions 0xd800-0xd87f).