Page 1 of 1

What Happens If I Won't Enable A20 line in PM ?

Posted: Tue Jun 13, 2017 10:48 am
by elad
When I try to access memory address that are higher than 0xFFFFF without enabling A20 line not a lot happens..
So what does happen when tring to access memory ranges with bits 20+ set without enabling the A20 line?
does address bits 20+ are cleared in the memory bus?
Or when entering Protected Mode address bits 20 - 31 are enabled anyway ( regardless if A20 controllers bits are set or not ) ?

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Tue Jun 13, 2017 11:08 am
by BenLunt
Hi,

The A20 line is just that, just the A20 line. All other bits (lines) are still intact. So, if you write to a memory address above 1 Meg, all writes will be to that address with bit 20 zero'd. If you are writing to an even meg address, you are fine. If you write to an odd meg address, you will actually write to the even meg address before it.

A20 = off
write to address 0x00E01234 = a write to address 0x00E01234
write to address 0x00F01234 = a write to address 0x00E01234

It is highly recommended that you make sure the A20 line is active before you use any address after the first Meg. Most machines, if not all new ones, will already have the A20 active, but it is wise to check to make sure.

To make sure, use this knowledge that if you write to an odd meg address with the A20 line off, the even meg address before it will be modified.

The bad thing about the A20 line, being a thing of the past, it was activated in different ways on different hardware. You have to have numerous techniques written into your code to activate it.

Hope this helps,
Ben
http://www.fysnet.net/the_universal_serial_bus.htm

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Tue Jun 13, 2017 12:10 pm
by BrightLight
BenLunt wrote:You have to have numerous techniques written into your code to activate it.
Just to clarify for the OP, the A20 enabling sequence should be something like this, in this order as it starts with the least-risky option first.

1. Check if A20 is enabled, by writing a value to an odd megabyte address (i.e. 0x100000) and reading back a value from the same address with bit 20 cleared (i.e. 0x000000 for this example.) If the values are not equal (i.e. A20 is enabled) return from the function and don't do anything. Else, continue with step 2.
2. Enable A20 using BIOS INT 0x15 function 0x2401. It will return zero on success. If it succeeds, jump to step 4. If the function is not supported or failed, continue with step 3.
3. Enable A20 using the PS/2 controller method. This is described in the Wiki article about A20.
4. Check if A20 is enabled, with the same technique in step 1. If it is enabled, return from the function. Else, continue with step 5.
5. Enable A20 using the FAST method. Read a byte from I/O port 0x92, set bit 1, clear bit 0 and write it back to the same I/O port. A small delay (i.e. NOP or PAUSE in a loop) is useful here.
6. Check if A20 is enabled again, with the same technique in step 1. If it is enabled, return from the function. Else, display an error message, as there is apparently no way to enable A20 on this machine.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Tue Jun 13, 2017 12:48 pm
by Octocontrabass
elad wrote:So what does happen when tring to access memory ranges with bits 20+ set without enabling the A20 line?
It depends.

On 386 and lower, there's a circuit between the CPU and the RAM that forcibly sets A20 to 0 whenever the CPU tries to access memory between 1MB and 2MB (0x100000 - 0x1FFFFF becomes 0x000000 - 0x0FFFFF). On addresses below 1MB, it has no effect. On addresses above 2MB, the effect depends on how that circuit was designed. On some computers, the circuit forces A20 to always be 0, no matter what address the CPU requests. On other computers, the circuit only forces A20 to be 0 when the address is between 1MB and 2MB. (It might actually be more complicated than that; I've only ever checked to see if the BIOS ROM was still accessible with the A20 line disabled.)

On 486 and higher, the CPU has an input (either a physical pin or a series of bus cycles) that controls A20 behavior. The behavior of disabling A20 is only documented in real mode, and I recall reading at least one manual that explicitly states that it's undefined in all other modes. With my 486 in unreal mode, it behaves as if A20 is always forced to 0. I've never tested it in protected mode, nor have I tried anything newer than that, so there's no guarantee this is a typical result.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Tue Jun 13, 2017 1:20 pm
by Brendan
Hi,

Note that A20 affects the entire physical address space, not just the first few MiB. For example, if you try to write to physical address 0x12345678 with A20 disabled then the write would actually go to physical address "0x12345678 & 0xFFEFFFFF = 0x12245678".

Essentially, every "odd MiB" of the physical address space can't be accessed and you'd access the preceding "even MiB' instead.

As a fun fault tolerance feature (which isn't necessarily practical beyond demonstration purposes); if my OS fails to enable A20 it continues to boot anyway - the physical memory manager just marks "odd MiBs" of RAM as unusable so that those pages aren't allocated. The real problem is for firmware tables and memory mapped PCI devices, which can be partially or completely inaccessible without A20 enabled.


Cheers,

Brendan

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Wed Jun 14, 2017 3:48 am
by onlyonemac
You'll be unable to access every second megabyte of physical memory. Instead, it will map to the previous megabyte.

So for example if you try to access address 0x380000, which is halfway through the 4th megabyte of memory, it will be the same as accessing address 0x280000 (both for reading and writing).

Of course, this is what should happen in theory. In reality, leaving A20 disabled when accessing higher memory addresses should be considered undefined behaviour and what really happens may vary between different motherboards and at different addresses. This behaviour should not be relied upon.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Wed Jun 14, 2017 10:25 am
by elad
thank you for the answers O:)

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Wed Jun 14, 2017 12:08 pm
by ~
If you find unable to enable the line A20 in a particular machine, you would probably do much better if you investigated why by writing test snippets and adding specific tricks later to your operating system code library.

The A20 gate is also supposed to be implemented as an OR gate array with a single output into the enabling of address bit 20, so if you enable it with more than one method, you will probably need to disable it again with those same methods.

And newer machines seem to always have it enabled by default, specially if they were designed when Windows Vista and 7 already existed and started to be very common.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Thu Jun 15, 2017 10:46 am
by bluemoon
omarrx024 wrote:
BenLunt wrote:You have to have numerous techniques written into your code to activate it.
Just to clarify for the OP, the A20 enabling sequence should be something like this, in this order as it starts with the least-risky option first.

1. Check if A20 is enabled, by writing a value to an odd megabyte address (i.e. 0x100000) and reading back a value from the same address with bit 20 cleared (i.e. 0x000000 for this example.) If the values are not equal (i.e. A20 is enabled) return from the function and don't do anything. Else, continue with step 2.
2. Enable A20 using BIOS INT 0x15 function 0x2401. It will return zero on success. If it succeeds, jump to step 4. If the function is not supported or failed, continue with step 3.
3. Enable A20 using the PS/2 controller method. This is described in the Wiki article about A20.
4. Check if A20 is enabled, with the same technique in step 1. If it is enabled, return from the function. Else, continue with step 5.
5. Enable A20 using the FAST method. Read a byte from I/O port 0x92, set bit 1, clear bit 0 and write it back to the same I/O port. A small delay (i.e. NOP or PAUSE in a loop) is useful here.
6. Check if A20 is enabled again, with the same technique in step 1. If it is enabled, return from the function. Else, display an error message, as there is apparently no way to enable A20 on this machine.
If you attempt to mess with PS/2 controller on a mac machine it just hangs. You want to check if PS/2 controller exists.
http://wiki.osdev.org/%228042%22_PS/2_C ... ler_Exists

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Thu Jun 15, 2017 2:00 pm
by iocoder
elad wrote:When I try to access memory address that are higher than 0xFFFFF without enabling A20 line not a lot happens..
So what does happen when tring to access memory ranges with bits 20+ set without enabling the A20 line?
does address bits 20+ are cleared in the memory bus?
Or when entering Protected Mode address bits 20 - 31 are enabled anyway ( regardless if A20 controllers bits are set or not ) ?
You don't enable/disable the A20 line. Your code actually enables a circuitry that we call 'A20 gate' which controls the A20 line in IBM-compatible machines. There are no such 'gates' for other address lines. It was added in the original IBM AT design for compatibility purposes (as the article on the wiki explains). The circuit simply looked like this:

Image

The programmer chooses whether to enable the AND gate or disable it (by controlling the so-called 'A20 GATE' output pin of the micro-controller that was mainly used as a keyboard controller). If the AND gate is disabled, the value of the A20 line will always be zero. This is necessary for IBM AT to stay compatible with old DOS programs that made use of memory wrap around behavior of the original 8086.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Thu Jun 15, 2017 2:55 pm
by ~
Just note that if a motherboard implement more than one method to enable the A20 line, all those methods are implemented as circuits apart, and all of them end up in a final OR gate (just expand the same previous schematic with an array of A20-enabling circuits that go into an OR).

So if you enable more than one of those circuits, then the A20 will be kept enabled by more than one source, and then if you want to disable it again you will have to disable all of those sources. I haven't tested it because I barely need to enable the A20 line (it seems to always be already enabled on any machine with SATA ports or with 64-bit-capable CPU), and I don't want risking locking the machine if the A20 gate is already enabled by an unknown source before loading a boot sector.

Known sources are the KBC, the Fast A20, and the BIOS services could use some of those means, more commonly the KBC.

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Thu Jun 15, 2017 3:06 pm
by Brendan
Hi,
bluemoon wrote:
omarrx024 wrote:Just to clarify for the OP, the A20 enabling sequence should be something like this, in this order as it starts with the least-risky option first.

1. Check if A20 is enabled, by writing a value to an odd megabyte address (i.e. 0x100000) and reading back a value from the same address with bit 20 cleared (i.e. 0x000000 for this example.) If the values are not equal (i.e. A20 is enabled) return from the function and don't do anything. Else, continue with step 2.
2. Enable A20 using BIOS INT 0x15 function 0x2401. It will return zero on success. If it succeeds, jump to step 4. If the function is not supported or failed, continue with step 3.
3. Enable A20 using the PS/2 controller method. This is described in the Wiki article about A20.
4. Check if A20 is enabled, with the same technique in step 1. If it is enabled, return from the function. Else, continue with step 5.
5. Enable A20 using the FAST method. Read a byte from I/O port 0x92, set bit 1, clear bit 0 and write it back to the same I/O port. A small delay (i.e. NOP or PAUSE in a loop) is useful here.
6. Check if A20 is enabled again, with the same technique in step 1. If it is enabled, return from the function. Else, display an error message, as there is apparently no way to enable A20 on this machine.
If you attempt to mess with PS/2 controller on a mac machine it just hangs. You want to check if PS/2 controller exists.
http://wiki.osdev.org/%228042%22_PS/2_C ... ler_Exists
No. Usually the ACPI tables are placed near the "end of RAM below 4 GiB", which is almost always an "odd MiB", which means that you need to enable A20 before you can access the ACPI tables, which means that you can't use ACPI tables to determine if the PS/2 controller exists until after A20 is enabled.

Fortunately; for BIOS (including an 80x86 Apple Mac running "Boot Camp"), the sequence above usually stops at "step 1" or "step 2". It's mostly only very old computers (Pentium or older?) that might not support the BIOS function, and very old computers always have a PS/2 controller, so (without checking if the PS/2 controller exists beforehand) you can be "extremely confident" that you'll never have a problem at "step 3".

For EFI/UEFI (including 80x86 Apple Mac without "Boot Camp"); A20 is always "enabled by default" and may not exist, so you wouldn't do any of steps listed above.


Cheers,

Brendan

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Thu Jun 15, 2017 11:30 pm
by elad
I enabled the A20 line this way:

1)in real mode code I put :
mov ax,0x2401
int 15h

2)after jumping to Protected mode (EIP points to even megabyte) I checked if A20 is enabled using:

;original code btw:)

is_a20_on?:
pushad
mov edi,0x112345
mov esi,0x012345
mov [esi],esi
mov [edi],edi
cmpsd
popad
jne a20_on
ret

a20_on:

3)if that doesn't work ,I tried to enable A20 using the ps/2 keyboard controller:

call a20wait
mov al,0xad ;disable the ps/2 keyboard
out 0x64,al
call a20wait
mov al,0xdd ;enable A20 line command
out 0x64,al

call a20wait
mov al,0xae ; enable the ps/2 keyboard
out 0x64,al
call a20wait

(a20wait:
in al,0x64
test al,2
jnz a20wait
ret)

4) check if A20 is enabled using Step 2's code.


3)if even that doesn't work ,I tried to enable A20 using the 0x92 port:


in al,0x92
or al,2
and al,0xfe
out 0x92,al

5)same as Step 4.


6)enable A20 line using port 0xee:

in al,0xee

7)same as Step 4.


last but not least ) if all that doesn't work, halt the system using:

cli
halt:
hlt
jmp halt

Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Fri Jun 16, 2017 1:11 am
by ~
See my public domain BOOTCFG project. I have mastered detecting the state of the A20 line and enabling/disabling it via KBC/Fast A20/BIOS to a fair degree:
http://f.osdev.org/viewtopic.php?p=276636

Look at the root directory of the source code, there is a fully 16-bit program called "01_64_rm.asm" that is able to detect whether the A20 line is enabled or not, solely by manipulating memory in the first Megabyte+65536-16 area, so it's safe to use even under very old machines, in pure 16-bit mode without Unreal Mode, very important to avoid locking up under, say, a 286, or dealing unnecessarily with A20 enabling circuits to detect, enable or disable.

Here is the current version of that program at this time. You can find the rest of A20 enabling option snippets in the project's ZIP file:

Code: Select all

_01_64_RM:
bits 16
org 100h



cld


;Compare:
;
;DS:SI==0000:0000 (phys. 000000-00FFF0)
;ES:DI==FFFF:0010 (phys. 100000-10FFF0)
;
;(Those are 65536-16 bytes to test).
;If they are different, then A20 is currently enabled.
;
;They are potentially the same address in a contiguous
;even/odd Megabyte pair, if A20 is disabled.
;;

push ds
push es


push word 0
pop ds
xor si,si


push word 0xFFFF
pop es
mov di,16


mov cx,65536-16



;Use the LOOP instruction to give
;these memory regions more time
;to become more altered which
;will help to differentiate them
;even more (remember that the LOOP
;instruction is extremely slow even in
;the newest CPUs):
;;
.loop1:
 cmpsb
 jne .loop1_END
loop .loop1
.loop1_END:

pop es
pop ds

test cx,cx
jnz .A20On




;If CX is 0, then the A20 line
;is disabled because the first and second
;Megabytes were identical despite being
;tested for differences in the first 65536-16 bytes
;via the CMPSB instruction:
;;
 mov ah,9
 mov dx,strA20Off
 int 21h

 mov al,0  ;Return code==enabled FALSE






jmp .END
.A20On:






mov ah,9
mov dx,strA20On
int 21h

mov al,1  ;Return code==enabled TRUE







.END:

;Exit to DOS:
;;
 mov ah,4Ch
 int 21h






strAppName db "01_64_RM.COM: $"

strA20On  db "01_64_RM.COM: A20 detected enabled from pure 16-bit Real Mode...",13,10,"$"
strA20Off db "01_64_RM.COM: A20 detected disabled from pure 16-bit Real Mode...",13,10,"$"






;EOF


Re: What Happens If I Won't Enable A20 line in PM ?

Posted: Fri Jun 16, 2017 2:32 am
by onlyonemac
elad wrote:If you're interted ,I enabled the A20 line this way:
Does it work?

The only thing I might consider adding is checking if A20 is enabled before you begin, avoiding the (possibly unimplemented) BIOS call if it is. Although this might be awkward if you're checking in protected mode and using a real-mode interrupt to enable it - you'll need a way to check if it is enabled using real mode, such as using the code below (copied from the wiki):

Code: Select all

check_a20:
    pushf
    push ds
    push es
    push di
    push si
 
    cli
 
    xor ax, ax ; ax = 0
    mov es, ax
 
    not ax ; ax = 0xFFFF
    mov ds, ax
 
    mov di, 0x0500
    mov si, 0x0510
 
    mov al, byte [es:di]
    push ax
 
    mov al, byte [ds:si]
    push ax
 
    mov byte [es:di], 0x00
    mov byte [ds:si], 0xFF
 
    cmp byte [es:di], 0xFF
 
    pop ax
    mov byte [ds:si], al
 
    pop ax
    mov byte [es:di], al
 
    mov ax, 0
    je check_a20__exit
 
    mov ax, 1
 
check_a20__exit:
    pop si
    pop di
    pop es
    pop ds
    popf
 
    ret
This uses the fact that you can read a little way into the second megabyte of memory from real mode, by setting the segment register to FFFF and then using an offset on top of that.