Can a bootloder use memory under 0x7C00 ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
JessyV
Posts: 4
Joined: Thu Mar 01, 2012 9:56 am

Can a bootloder use memory under 0x7C00 ?

Post by JessyV »

My Bootloader is loaded by the BIOS at 0x7C00, but I need to use memory from 0x6000 to 0x9000 in order to load an extension of the bootloader (as it is limited to one sector - 512 Bytes).

So here is my question : is there any obstacle that forbids me to use this memory ?
If there's any, I simply need a contiguous space which is 0x3000 long under 0x9000.

NOTE: This applies only to a 16-Bits (Real Mode) Context.

Thanx, Jessy V.
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Can a bootloder use memory under 0x7C00 ?

Post by ~ »

This is the normal procedure (to use memory other than the boot one); there's no problem, but only certain ranges (below) are truly free for your use.

OSDev Wiki: Memory Map (x86) - Overview

Remember that under 1 Megabyte you can use the following 3 memory ranges without hassle:

0x500 to 0x7BFF (if you count the boot you can use up to 0x7DFF)
0x7E00 to 0x7FFFF
0x80000 to 0x9FBFF

Image
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Can a bootloder use memory under 0x7C00 ?

Post by Schol-R-LEA »

The one caveat I would make is that you want o avoid overwriting the boot sector at 0x7C00-0x7DFF, or at least the section of it doing the loading, which if you meant to use 0x6000 to 0x9000, means you would need to relocate part of the boot sector somewhere else before loading.

If you don't mind me asking, why does it have to be below 0x9000? You normally have quite a bit more space available above 0x7DFF (up to 0x7FFFF), which your requirement fits quite nicely into.

Alternately, you could load the second stage anywhere between 0x500 and 0x4FFF, and have sufficient memory available. Remember, you havwe most of memory available to you, and few limits on what you can do with it. The system is wide open to you at boot time, and you can use it in whatever way you see fit, so long as you stick to the areas not used by the BIOS, the device memory, or the IVT.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
JessyV
Posts: 4
Joined: Thu Mar 01, 2012 9:56 am

Re: Can a bootloder use memory under 0x7C00 ?

Post by JessyV »

Thanks to you for replying, I must confess that I first thought my question was stubborn :oops: .

My loading scheme iss in fact to have the bootloader from 0x7C00 to 0x7E00, as the BIOS loads it. It would then load a larger 16-Bits program (that I call pre-kernel or Kernel.16), which would make all the necessary initializations (Video modes and other BIOS calls) which didn't feet at all in the 512 bytes limit of the bootloader. at 0x6000 so it can be very large while not overwritting the original bootloader, as it shares some of it's routines to avoid code repetition. Then, it would load the definitive, 32-Bits kernel at 0x9000 and pass it control.

The pre-kernel should not, however, overwritten then as my OS will return to it times by times using virtual 8086 mode to, for example, change the video mode or other BIOS things. This is the reason for which it should be so big ;)

Sorry, I just didn't notice the existance of the Memory Map page :oops:
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: Can a bootloder use memory under 0x7C00 ?

Post by turdus »

JessyV wrote:...it can be very large while not overwritting the original bootloader, as it shares some of it's routines to avoid code repetition.
Not a good idea imho. You introduce restrictions on stage 2 (unusable bytes at the middle, complicated load), with almost no benefit (you could spare only a few bytes of code, not much). If I were you, I would go with the relocation beneath 0x6000.
The pre-kernel should not, however, overwritten then as my OS will return to it times by times
It does not worth it. That means your kernel would depend on a specific stage 2 code.
On the other hand, you can load your 16 bit BIOS glue code with the rest of your kernel, which is a far more elegant way. Almost every assembler supports mixed mode code (nasm, gas, fasm, tasm, masm etc.) that can be statically linked with your 32 bit kernel. Or, as a last chance, you can include 16 bit code (as char array, using bytes from preceding assembly) into your kernel's initialized data section, if your linker does not like mixed code.
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Can a bootloder use memory under 0x7C00 ?

Post by ~ »

JessyV wrote:Thanks to you for replying, I must confess that I first thought my question was stubborn :oops: .

My loading scheme iss in fact to have the bootloader from 0x7C00 to 0x7E00, as the BIOS loads it. It would then load a larger 16-Bits program (that I call pre-kernel or Kernel.16), which would make all the necessary initializations (Video modes and other BIOS calls) which didn't feet at all in the 512 bytes limit of the bootloader. at 0x6000 so it can be very large while not overwritting the original bootloader, as it shares some of it's routines to avoid code repetition. Then, it would load the definitive, 32-Bits kernel at 0x9000 and pass it control.
What I do for a second stage is to have a "pre-kernel" image that spans as much memory as it needs. Now the clever part is that the boot code checks for every sector it copies, that it isn't in the way of the boot code (if(pointer==0x7B00)pointer=0x7F00;else copy_next_sector();) and if so it skips copying it and advances beyond it. Meanwhile, in the "pre-kernel" image, I assume that the base address is simply 0x500 and when it reaches the address that would correspond to the boot code in memory, I just pad it with 0 (anyway the boot code will take care not to overwrite itself with this 1024-byte block, just add 0x200 to 0x500 until you reach 0x7B00 and then the need to skip 0x7D00 at the middle of the boot code and finally to 0x7F00, beyond the boot code, becomes more clear).

With that tiny precaution I could probably load an image all the way from 0x500 to 0x9FBFF if I needed to --see how 0x500-0x7BFF/0x7DFF, 0x7E00-0x7FFFF and 0x80000-0x9FBFF-- are in reality a contiguous block of memory, with just 1 KB of padding (but the assembling/compilation becomes just a little more difficult because you need to check that the first part spans just before the boot code, and then 1024 bytes of padding, and then the rest of the code up to a valid address).

Once you figure out how to build such a skeleton, then reimplementing it becomes very easy (it could take you a while; if you want more specific information, which can require the use of extern or global keywords for C/Assembler, and probably a LD script, unless you are comfortable with manually tracking the structure of the binary, or help about it, just ask).

And I wouldn't mind repeating routines in the second stage and in the kernel. It is normal/standard, and it is better to have all useful functions that make sense, of the second stage in the kernel itself (it allows for the kernel to be really autonomous).

JessyV wrote:The pre-kernel should not, however, overwritten then as my OS will return to it times by times using virtual 8086 mode to, for example, change the video mode or other BIOS things. This is the reason for which it should be so big ;)

Sorry, I just didn't notice the existance of the Memory Map page :oops:
There's no need to worry since it's very basic stuff.

I think it is OK to design a kernel in this way if it allows you to learn in the first milestone. BIOS services in Protected Mode are almost useful only for setting VESA modes (standard VGA modes can be programmed in the kernel because they are very well known).

Just don't forget to better use code emulation (look for x86emu in the wiki for source code of this type, although it's not so basic) or virtual 8086 mode from your kernel instead of returning to Real Mode for some future milestone.

I would only use code emulation because virtual 8086 mode doesn't work for 64-bit Long Mode, from what I have learned.

You could have a similar functionality in the kernel, reimplementing specific software interrupts or using an "exports table" that other rudimentary binaries can be "linked" to the kernel, which in turn could internally have the kernel emulate the BIOS code you need.
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: Can a bootloder use memory under 0x7C00 ?

Post by turdus »

@~: I agree, plus
don't forget that not every machine ships BIOS. Many (and more and more in the future) use UEFI. Your kernel has to support both, because by the time your OS will be something that's worth showing, most probably BIOS and 16 bit will die. Not to mention architectures that do not have 16 bit mode or UEFI at all (think about your Android phone or the Raspberry Pi).

What I do is a well-defined architecture interface, implemented in assembly (a low level hardware abstraction layer). It's loaded as a part of the kernel, which is architecture specific anyway. When my 64 bit kernel gains control, nothing left from real mode stage 2 in memory except one data structure at 0x500-0x600, so every BIOS interaction is limited to this hal module. Userspace apps call functions from this module (sys.arch class), like sys.arch.reset() or sys.arch.poweroff(). Thanks to this interface, userspace is not aware of how a specific function is done (via APM BIOS, interpreting AML, direct hardware programming or whatever). Also, this hal part can be switched independently to the rest (to switch among platforms on liveusb for example).
Post Reply