Page 3 of 3
Posted: Tue Nov 20, 2007 11:13 am
by Dex
LordMage wrote:
Code: Select all
bits 32
Stage3:
;-------------------------------;
; Set registers ;
;-------------------------------;
mov ax, 0x10 ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov esp, 90000h ; stack begins from 90000h
;HERE IN YOU CODE DO THIS
call TestRam
push [ExtMemorySize]
push [TotalMemoryMB]
Add these function to you code
Code: Select all
;----------------------------------------------------;
; TestRam ;
;----------------------------------------------------;
TestRam:
pushad
mov eax,dword[TotalMemoryMB]
rol eax,8
push eax
push eax
shr al,4
call hexget
mov byte [fs:0xB8090], al
pop eax
call hexget
mov byte [fs:0xB8092], al
pop eax
rol eax,8
push eax
push eax
shr al,4
call hexget
mov byte [fs:0xB8094], al
pop eax
call hexget
mov byte [fs:0xB8096], al
pop eax
rol eax,8
push eax
push eax
shr al,4
call hexget
mov byte [fs:0xB8098], al
pop eax
call hexget
mov byte [fs:0xB809A], al
pop eax
rol eax,8
push eax
push eax
shr al,4
call hexget
mov byte [fs:0xB809C], al
pop eax
call hexget
mov byte [fs:0xB809E], al
pop eax
popad
ret
;----------------------------------------------------;
; hexget ;
;----------------------------------------------------;
hexget:
and eax,0x0000000f
or eax,0x00000030
cmp eax,0x39
ja add7
ret
add7: add eax,7
ret
This should print a hex number in the top right hand corner, report back what it prints.
If you have 32mb of ram, it should print 20 .
Posted: Tue Nov 20, 2007 6:15 pm
by bewing
LordMage wrote:okay, I tried to push the contents like he suggested but I got the same answer, I must be doing something wrong but I really don't know what. is there anything else wrong with my code? Can I actually make something in my stage2 bootloader globally available so that my kernel can see it also?
Of course you can. I would very much suggest it, in fact. It's much harder to move a stack properly, than it is to use a table at an absolute address.
One thing that is
absolutely guaranteed on all PCs is that "low" memory, from 0x500 to 0x9ffdf is completely available. There cannot be any holes, any hardware remappings, or anything at all except pure plain vanilla RAM. All of that memory (almost 639K) is available for passing data in absolute (known) memory locations. All you need to do is have your bootloader create a table there, and have your kernel pick it back up. Of course, this is PHYSICAL memory, so if you wait until virtual page mapping is turned on, you may need to unmap it.
Code: Select all
TotMem equ 0x1000
... middle of bootloader code ...
call get_RAMsize ; returns total amt of ram in EAX
mov [TotMem], EAX ; Intel (not at&t) syntax
... bootloader boots kernel written in C
... in kernel code somewhere
#define TotMem 0x1000
unsigned long ram_from_bios;
ram_from_bios= *((unsigned long *) TotMem);
But, of course, as Brendan is saying -- in the end you won't just be passing one 32bit value, you will have an entire
table stored at some KNOWN absolute physical address in low mem.
Posted: Tue Nov 20, 2007 8:12 pm
by LordMage
I went the shorter route and took Bewings advice, it worked!!!!
I do appreciate the hex routine though Dex. I was wanting one of those and will use it. The good news though is that I am seeing 32 now which is the correct amount of ram so now I can modify and calculate to give me what I need for my plans. Thanks again
Posted: Wed Nov 21, 2007 12:10 am
by Brendan
Hi,
bewing wrote:One thing that is absolutely guaranteed on all PCs is that "low" memory, from 0x500 to 0x9ffdf is completely available.
That is not guaranteed. Do a web search for "EBDA too big" and see how many hits you get because some LILO programmer made the same assumption...
The 512 KB area from 0x00000000 to 0x00080000 is guaranteed to be nice, contiguous, usable RAM though.
bewing wrote:There cannot be any holes, any hardware remappings, or anything at all except pure plain vanilla RAM.
Strange you should say "holes". Take a look at the datasheets for Intel 945 chipsets - it actually does support a hole from 0x00080000 to 0x000A0000. I doubt any motherboards actually use this hole, but the chipset supports it.
Also, the PXE specification (for booting from network) says the BIOS/ROM/etherboot networking code can freely use the area from 0x00080000 to the start of the EBDA, so it's good to leave this area untouched while your booting.
Cheers,
Brendan
Posted: Wed Nov 21, 2007 4:33 pm
by bewing
Brendan wrote:
Do a web search for "EBDA too big" and see how many hits you get
OK, I'll do that -- OK, the answer is only 4000 on google; I knew that there might be a little space at the end of page 9 used by BIOS; multiple K for the EBDA is completely excessive (low memory is precious during bootup, and people would have to be idiots to f*ck it up with a damned table like this); and it would be really nice if someone would write a wiki entry about this stupid "feature" somewhere -- since there are no obvious search results, and the OSDev wiki has unfulfilled references to the EBDA.
Brendan wrote:
The 512 KB area from 0x00000000 to 0x00080000 is guaranteed to be nice, contiguous, usable RAM though.
Except that the real mode IDT takes up the first K, and you don't really want to lose that -- and the BIOS trashes bytes in the next 0x100 bytes every 18th of a second.
Brendan wrote:
Also, the PXE specification (for booting from network) says the BIOS/ROM/etherboot networking code can freely use the area from 0x00080000 to the start of the EBDA, so it's good to leave this area untouched while your booting.
But then you're booting off an entirely different bootloader anyway.
If a disk-based bootloader knows that it is booting itself, it already knows you are not booting off a network.
Posted: Thu Nov 22, 2007 4:28 am
by Brendan
Hi,
bewing wrote:Brendan wrote:Do a web search for "EBDA too big" and see how many hits you get
OK, I'll do that -- OK, the answer is only 4000 on google; I knew that there might be a little space at the end of page 9 used by BIOS; multiple K for the EBDA is completely excessive (low memory is precious during bootup, and people would have to be idiots to f*ck it up with a damned table like this); and it would be really nice if someone would write a wiki entry about this stupid "feature" somewhere -- since there are no obvious search results, and the OSDev wiki has unfulfilled references to the EBDA.
Try to imagine writing code that handles as much as a modern BIOS does with less than 5 KB of ".bss", where most of that space must match code written over 20 years ago (before there were things like PCI BIOS, Multiprocessor specification, ACPI, SMM, Plug & Play, DMTF/SMBIOS, boot from CD/USB and floppy/had disk emulation, etc).
There is no complete reference for the EBDA that every BIOS complies with, just like there's no complete reference for kernel data that all OS's comply with.
bewing wrote:Brendan wrote:The 512 KB area from 0x00000000 to 0x00080000 is guaranteed to be nice, contiguous, usable RAM though.
Except that the real mode IDT takes up the first K, and you don't really want to lose that -- and the BIOS trashes bytes in the next 0x100 bytes every 18th of a second.
It's still usable RAM, even if it is temporarily unusable before the switch to protected mode.
bewing wrote:Brendan wrote:Also, the PXE specification (for booting from network) says the BIOS/ROM/etherboot networking code can freely use the area from 0x00080000 to the start of the EBDA, so it's good to leave this area untouched while your booting.
But then you're booting off an entirely different bootloader anyway.
If a disk-based bootloader knows that it is booting itself, it already knows you are not booting off a network.
Not necessarily. From
this web site:
MEMDISK simulates a disk by claiming a chunk of high memory for the
disk and a (very small - 2K typical) chunk of low (DOS) memory for the
driver itself, then hooking the INT 13h (disk driver) and INT 15h
(memory query) BIOS interrupts.
Just because your OS booted from a floppy, doesn't mean it didn't boot from an emulated floppy (where the floppy emulation code runs on top of etherboot/netboot to access a floppy image on a remote machine).
Cheers,
Brendan
Posted: Fri Nov 23, 2007 4:34 pm
by bewing
Brendan wrote:
Try to imagine writing code that handles as much as a modern BIOS does with less than 5 KB of ".bss"
Well, the BIOS tests (and therefore can access) upper memory -- so it's stupid for it to put stuff in low mem. Also, if the BIOS didn't lock the 128k below 1M, it would have plenty of ram to play with there.
Brendan wrote:
There is no complete reference for the EBDA
Ugh. I'd think they'd have learned their lesson over the years about the concept of "standards". Guess not.
Brendan wrote:
It's still usable RAM, even if it is temporarily unusable before the switch to protected mode.
Yes, but precisely the same comment could be applied to the EBDA itself, too.
Posted: Sat Nov 24, 2007 7:58 am
by Brendan
Hi,
bewing wrote:Brendan wrote:There is no complete reference for the EBDA
Ugh. I'd think they'd have learned their lesson over the years about the concept of "standards". Guess not.
Can you find any standard that says the OS can use more than 512 KB of memory below 1 MB (or a standard that says the BIOS can't have a large EBDA from 0x00080000 to 0x0009FFFF)? I'd think OS developers would have learned their lesson over the years about the concept of "standards" (e.g. the standard BIOS "Int 0x12" function). I'd guess they haven't (although LILO did fix their bug when they realised they were relying on assumptions, and I doubt they'll be making the same mistake again soon).
bewing wrote:Brendan wrote:It's still usable RAM, even if it is temporarily unusable before the switch to protected mode.
Yes, but precisely the same comment could be applied to the EBDA itself, too.
No it can't - data in the EBDA may be used by SMM code regardless of what mode the CPU/OS was using (and can also be used by the BIOS to co-ordinate SMM code, real mode APM code and ACPI code).
Cheers,
Brendan
Posted: Sat Nov 24, 2007 2:07 pm
by bewing
Brendan wrote:
Can you find any standard that says the OS can use more than 512 KB of memory below 1 MB (or a standard that says the BIOS can't have a large EBDA from 0x00080000 to 0x0009FFFF)?
In fact, I think the standard that said just that is called MSDOS ver 3 through 5 and/or Windows 1.0 through 3.11.
And doesn't an OS have complete control over preventing the system from entering SMM?
Posted: Sat Nov 24, 2007 6:25 pm
by Brendan
Hi,
bewing wrote:Brendan wrote:Can you find any standard that says the OS can use more than 512 KB of memory below 1 MB (or a standard that says the BIOS can't have a large EBDA from 0x00080000 to 0x0009FFFF)?
In fact, I think the standard that said just that is called MSDOS ver 3 through 5 and/or Windows 1.0 through 3.11.
The word "standard" is probably a bit inaccurate - the original 8086 XT machine had "BIOS Int 0x12", and all other 80x86 computers still have it for backward compatability.
bewing wrote:And doesn't an OS have complete control over preventing the system from entering SMM?
SMM is (and AFAIK was always intended to be) completely hidden from the OS and normal software.
If the OS enables "ACPI mode" then some things will cause an SCI (which is handled by the OS's AML interpretter) instead of causing an SMI (which is handled by the BIOS's SMM code).
If the OS supports USB properly, then some things that were emulated by the BIOS's SMM code aren't (e.g. BIOSs make a USB keyboard look like a PS/2 keyboard using SMM until the OS disables it in the USB device).
However, even with full ACPI and USB support there can be other things the BIOS uses SMM for. One of the things that's mentioned in the documentation for some Intel chipsets is "RAM scrubbing" (which I assume is something that attempts to correct or recover from temporary RAM errors).
For some chipsets you might be able to avoid and/or disable all of the causes of SMI, but without studying each motherboard (chipset and BIOS) you won't know how much SMM does or how much SMM you can avoid. There isn't really any limit to the number of things the BIOS could use SMM for, and there definately isn't a generic way to disable all SMM.
Cheers,
Brendan
Posted: Sun Nov 25, 2007 10:17 pm
by Dandee Yuyo
Me I just plainly forget about what's below 1MB. I just use it to load the second stage loader and to map some tables at boot time while I can still use the BIOS to get some valuable system information, and plan to use it only for DMA buffers in the future; and maybe, MAYBE, some kernel tables.
To determine the amount of RAM I do int 15 with eax e820h, e801h and 8800h in that order. If e820h fails, I fill an e820h-like memory map with the results of e801h or 8800h that the kernel uses to initialize the page frame allocator.
I asume that if e820h didn't work there won't be any ACPI present mapping its I/O in upper RAM. Is this bad?
If 8800h fails, then I just show a message and jmp $.. Hey update your hardware!
Probing memory is bad, probing is evil. DON'T.