User:Johnburger/Demo/Boot/RAM

From OSDev Wiki
Jump to navigation Jump to search

Another piece of information needed by the Protected Mode code is just exactly how much RAM the system has - and where. At Boot time, the BIOS knows, so now would be a good time to get it and save it away for future reference.

Of course, as the PC evolved the question "How much memory is there anyway?" got harder and harder to answer, so a number of methods evolved with it. And of course, being implemented by various manufacturers, they each had their own idiosyncrasies...

I use two:

  • The first one is the original. It merely gives the top of conventional RAM (less the Extended BIOS Data Area - woohoo! I now have a value for 0009_F???h in my Memory Map!).
  • The second is the most up-to-date one. It categorises the different blocks of address space into different types (Reserved, Present, Missing, Faulty etc.)

Having gone to all that effort, however, in the rest of the Demonstrator I ignore the values for the RAM Map returned by the BIOS in the second step above. I'll leave it as an exercise for the reader...

Memory Map

After this code, the Memory Map will look like this:

Address Usage
0000_0000h Interrupt Vector Table
0000_0400h BIOS Data Area
0000_0500h Protected Mode Data
0000_0518h RAM Map from BIOS
0000_0800h Moved IDT-to-be
0000_1000h Loaded Protected Mode code
0000_2070h Available
0000_7C00h SS:SP Stack Top
0000_7C00h BIOS-loaded Boot Sector
0000_7E00h Available
0009_F###h Extended BIOS Data Area
000A_0000h Adapter / ROM Area
000B_8000h Text Video Memory
000F_0000h BIOS ROM
0010_0000h High Memory *

* Note that this memory is only accessible in Protected Mode - except for the first 64 kiB (less 16 bytes), which you can access with a Segment Register set to 0FFFFh as long as the A20 Gate is off. By the way: DON'T DO THIS!

Demo/Boot/RAM.inc

;
; Boot/RAM.inc
;

; This module uses the BIOS to determine how much RAM the system has.
; It saves the information away for the system to process after it has entered
; Protected Mode - BIOS functions aren't available then.

Boot.RAM:
                XOR             EAX,EAX           ; Zero high part of EAX
                MOV             AX,Data.Base >> 4 ; Point to global Data
                MOV             DS,AX
                MOV             ES,AX             ; With both Segments

                INT             BIOS.RAMTop.Int   ; Get size of Low RAM in kiB
                SHL             EAX,10            ; Turn into number of bytes
                MOV             [Data.RAMTop],EAX ; Top of (Real) RAM

                XOR             EBX,EBX           ; Start with beginning of RAM
                MOV             DI,Data.RAMMap    ; Store records here
.Loop:
                MOV             EAX,BIOS.RAMMap.Fn ; Function call
                MOV             CX,BIOS.RAMMap_size
                MOV             EDX,BIOS.RAMMap.Magic
                MOV             [DI+BIOS.RAMMap.Flags],BYTE BIOS.RAMMap.Flags.DontIgnore
                INT             BIOS.RAMMap.Int ; Call BIOS
                JC              .End            ; Carry? Finished

                CMP             EAX,BIOS.RAMMap.Magic ; BIOS function supported?
                JNE             .End            ; Nope.

                CMP             CL,BIOS.RAMMap.Flags ; Don't mind optional Flags DWORD
                JB              .Skip           ; Ignore if too small
                JE              .Test           ; No .Flags entry, so valid

                TEST            [DI+BIOS.RAMMap.Flags],BYTE BIOS.RAMMap.Flags.DontIgnore
                JZ              .Skip           ; Ignore if told to
.Test:
                MOV             EAX,[DI+BIOS.RAMMap.Length+0]
                OR              EAX,[DI+BIOS.RAMMap.Length+4]
                JZ              .Skip           ; Zero-length entry?

                INC     WORD    [Data.RAMMap.Num]  ; One more Map entry

                ADD             DI,BIOS.RAMMap_size ; Next record
                CMP             DI,Data.Size-BIOS.RAMMap_size ; Any more room?
                JA              .End            ; Nope. Leave
.Skip:
                TEST            EBX,EBX         ; End of sequence?
                JNZ             .Loop           ; Not yet...
.End: