Sorry about the newbie questions- I still can't get at the FAQ. Pointers to where I can get this document gladly accepted. Or a pointer to the archive of this mailing list. Or the CVS repository for the code.
Why is the bios going into protected mode? This would seem to make life difficult to load an OS. Is there a game plan for dealing with this that I'm not seeing?
The problem is that the linux load sequence is 16-bit code, which loads the idt and gdt and then performs dozens of more instructions before going into protected mode.
The solutions I see are:
1) Don't go into protected mode. So long as addresses stay below 1 meg, this shouldn't be a problem (PCI/AGP configuration is the only reason I know of why we may need to go above 1M).
2) Go into protected mode for initial configuration, then exit it to load the boot code (note that the BIOS service routines would have to run in real mode in this case).
3) Stay in protected mode, run the OS loader in V86 mode, and "cleverly" handle the protection fauls (probably by "emulating" them- on the lidt/gidt instructions we save off their offsets, and on the lmsw instruction doing all three- lidt/gidt/lmsw).
4) Same as above, but instead of emulating the instructions, we exit from protected mode at that point, and retry the instruction (and hope that no one ever tries to use a BIOS service after executing a protected instruction).
5) Beg the OS maintainers to change their code. I dislike this option intensely- while on Linux we could probably do it (by becoming OS maintainers), I doubt Microsoft would listen.
Brian
- To Unsubscribe: send mail to majordomo@freiburg.linux.de with "unsubscribe openbios" in the body of the message
On Wed, 7 Jul 1999, Brian Hurt wrote:
Sorry about the newbie questions- I still can't get at the FAQ.
I can't reach the FAQ for here either.
Pointers to where I can get this document gladly accepted. Or a pointer to the archive of this mailing list.
I think Mircea Ciocan mirceac@interplus.ro was going to put up an archive of this mailing list back in february, but I don't know the current status of it.
Or the CVS repository for the code.
Why is the bios going into protected mode? This would seem to make life difficult to load an OS. Is there a game plan for dealing with this that I'm not seeing?
The problem is that the linux load sequence is 16-bit code, which loads the idt and gdt and then performs dozens of more instructions before going into protected mode.
The solutions I see are:
- Don't go into protected mode. So long as addresses stay below 1 meg,
this shouldn't be a problem (PCI/AGP configuration is the only reason I know of why we may need to go above 1M).
This is not an option. The BIOS needs to access memory above 1MB to be able to detect DRAM timings etc.
- Go into protected mode for initial configuration, then exit it to load
the boot code (note that the BIOS service routines would have to run in real mode in this case).
This is how other BIOSs today do it. That is also how you have to do if you strive for IBM-PC BIOS compability.
- Stay in protected mode, run the OS loader in V86 mode, and "cleverly"
handle the protection fauls (probably by "emulating" them- on the lidt/gidt instructions we save off their offsets, and on the lmsw instruction doing all three- lidt/gidt/lmsw).
I guess this is not an option either. Since V86 runs realmode code you will run into problem directly when the OS wants to do something in protectedmode. Even if it could be done (by "emulating" something) it seems like a really bad idea to me.
- Same as above, but instead of emulating the instructions, we exit from
protected mode at that point, and retry the instruction (and hope that no one ever tries to use a BIOS service after executing a protected instruction).
This looks just like your second solution, only that you run the bootup realmode instructions in V86 mode instead of "real" realmode. Pointless?
- Beg the OS maintainers to change their code. I dislike this option
intensely- while on Linux we could probably do it (by becoming OS maintainers), I doubt Microsoft would listen.
This depends on what changes you ask the OS maintainers for. The BIOS I'm working on will be Multiboot compliant, which means that the OS have to conform to the Multiboot standard [1] in order to be loaded by the BIOS. See the GRand Unified Bootloader (GRUB) homepage [2] for information about what OSs are supported by the standard etc.
You can look at my website [3] for short information about what my BIOS will be like (see the mailinglist archive for the reasons of why I'm working on a BIOS of my own instead of OpenBIOS).
/ Niklas
[1] ftp://flux.cs.utah.edu/flux/multiboot/MultiBoot.html [2] http://www.uruk.org/grub/ [3] http://www.niklas.ekstrom.com/gnubios/
- To Unsubscribe: send mail to majordomo@freiburg.linux.de with "unsubscribe openbios" in the body of the message
Thanks everyone for their comments. I've had another evening to think about things, and have some further thoughts:
On Thu, 8 Jul 1999, [ISO-8859-1] Niklas Ekstr�m wrote:
[snip happens]
- Don't go into protected mode. So long as addresses stay below 1 meg,
this shouldn't be a problem (PCI/AGP configuration is the only reason I know of why we may need to go above 1M).
This is not an option. The BIOS needs to access memory above 1MB to be able to detect DRAM timings etc.
This is what I thought. In addition, gcc really dislikes producing 16-bit code. There is a 16-bit DOS gcc linked to off of D.J. Delorie's site that is being used for the port of Linux to the 8086, but I don't think it's usable. I suppose we could dump gcc totally and go with some other compiler, but A) I _like_ gcc, and would like to keep Linux as my build environment, and B) I don't know of any other free usable 16-bit DOS compilers out there (I'd rather not use an old, properietary, unsupported compiler like Borland C for DOS).
All of these things conspire to strongly encourage the use of protected mode in the BIOS. :-)
- Go into protected mode for initial configuration, then exit it to load
the boot code (note that the BIOS service routines would have to run in real mode in this case).
This is how other BIOSs today do it. That is also how you have to do if you strive for IBM-PC BIOS compability.
Unless I'm missing something, the linux boot sequence uses IBM-PC BIOS functions. I found a number of int 0x13 (diskette services) and int 0x10 (video services) calls in arch/i386/boot/setup.S. Even Grub makes heavy use of BIOS services- a quick grep revealed 23 different BIOS calls, using services 0x13 (disk), 0x10 (video), 0x1a (RTC), and 0x16 (keyboard).
- Stay in protected mode, run the OS loader in V86 mode, and "cleverly"
handle the protection fauls (probably by "emulating" them- on the lidt/gidt instructions we save off their offsets, and on the lmsw instruction doing all three- lidt/gidt/lmsw).
I guess this is not an option either. Since V86 runs realmode code you will run into problem directly when the OS wants to do something in protectedmode. Even if it could be done (by "emulating" something) it seems like a really bad idea to me.
This is actually my leading favorite canidate. The idea is that once the lmsw instruction is executed, the OS takes over. From my 386SX Microprocessor Programmer's Reference Manual (outdated, I know- but I haven't gotten the more advanced documentation yet), the sensitive instructions are: lidt, lgdt, lmsw, mov to/from special control registers, clts, and hlt. The moves to DRx and the hlt instruction should simply be run in priveledged mode. Movs to TRx should be ignored (for now)- I don't think any OS actually uses these. The rest would need to be emulated.
On execution of a lmsw, the bios would perform all the lidts, lgdts, and movs to CRx, and resume the flow of code at the next instruction- i.e. give up and let the OS take over. I'm estimating the total code to do this is only a few hundred lines, most of which would be parsing the instructions. I am, of course, volunteering to write this code. :-)
- Same as above, but instead of emulating the instructions, we exit from
protected mode at that point, and retry the instruction (and hope that no one ever tries to use a BIOS service after executing a protected instruction).
This looks just like your second solution, only that you run the bootup realmode instructions in V86 mode instead of "real" realmode. Pointless?
Not quite. The difference is _when_ do we switch to real mode- 1) just before jumping into the boot loader, 2) the first time the boot loader does something we don't want to deal with emulating, or 3) never (and we just carefully hand over control to the OS when it loads).
- Beg the OS maintainers to change their code. I dislike this option
intensely- while on Linux we could probably do it (by becoming OS maintainers), I doubt Microsoft would listen.
This depends on what changes you ask the OS maintainers for. The BIOS I'm working on will be Multiboot compliant, which means that the OS have to conform to the Multiboot standard [1] in order to be loaded by the BIOS. See the GRand Unified Bootloader (GRUB) homepage [2] for information about what OSs are supported by the standard etc.
So basically you're putting the boot loader into the bios. I'm not 100% comfortable with this idea- it locks you into a boot loader.
This is a viable alternative for me, mind you, and I may do just that. But I have complete control over the OS being loaded (Linux) and how it's loaded, and do not have to coordinate with other distributions, or boot Windows, or anything ugly like that. But I'd like to have a more flexible system- I'd like to see VA-Research be able to use OpenBios.
You can look at my website [3] for short information about what my BIOS will be like (see the mailinglist archive for the reasons of why I'm working on a BIOS of my own instead of OpenBIOS).
Do you have code I can look at? Can you email me (off-line) your reasons?
Thanks for the links- they've given me more things to look at.
- To Unsubscribe: send mail to majordomo@freiburg.linux.de with "unsubscribe openbios" in the body of the message
On Thu, 8 Jul 1999, Brian Hurt wrote:
Unless I'm missing something, the linux boot sequence uses IBM-PC BIOS functions. I found a number of int 0x13 (diskette services) and int 0x10 (video services) calls in arch/i386/boot/setup.S. Even Grub makes heavy use of BIOS services- a quick grep revealed 23 different BIOS calls, using services 0x13 (disk), 0x10 (video), 0x1a (RTC), and 0x16 (keyboard).
That's not a problem -- these are not mandatory and even now there are some people that run Linux on ia32-based embedded systems. They have no BIOS and the kernel is started from flash memory.
This is actually my leading favorite canidate. The idea is that once the lmsw instruction is executed, the OS takes over. From my 386SX Microprocessor Programmer's Reference Manual (outdated, I know- but I haven't gotten the more advanced documentation yet), the sensitive instructions are: lidt, lgdt, lmsw, mov to/from special control registers, clts, and hlt. The moves to DRx and the hlt instruction should simply be run in priveledged mode. Movs to TRx should be ignored (for now)- I don't think any OS actually uses these. The rest would need to be emulated.
Note that some DOS-based programs execute smsw (that's unprivileged), check for the PE bit and bail out if set.
Not quite. The difference is _when_ do we switch to real mode- 1) just before jumping into the boot loader, 2) the first time the boot loader does something we don't want to deal with emulating, or 3) never (and we just carefully hand over control to the OS when it loads).
There is no need to get out of the protected mode -- that should be the job of a legacy boot loader. BIOS has only to provide a generic call to enter the legacy mode.
So basically you're putting the boot loader into the bios. I'm not 100% comfortable with this idea- it locks you into a boot loader.
Well all workstation or server systems I know of have a boot loader embedded into their firmware. They can choose the device to boot from -- usually the choice is to start from a SCSI or a network device.
Booting from SCSI devices involves reading the first block, looking for a magic number and, if set, reading two values treated as an offset and a number of blocks. Then the device is seeked to the offset and the indicated number of blocks is read into a predefined location of memory. Control is then passed to the program read. The program can actually be an OS kernel or a second-stage boot loader with the latter case being more frequent (unless you are booting from tape).
Booting from network devices involves the usual BOOTP (or sometimes DHCP) and TFTP stuff, which results in a program image being loaded into memory, then execution continues as described above. The image is an OS kernel in this case, usually.
This approach simplifies things as there is no need for a second-stage boot loader sitting in the boot block and loading the third-stage boot loader or the kernel and basically duplicating the actions described above. Besides, there needs to be a network loader put into BIOS in this case, anyway...