Page 1 of 1
SudoBIOS
Posted: Sun May 17, 2015 11:29 am
by mikegonta
SudoBIOS is a completely transparent 32bit protected mode BIOS extender. SudoBIOS uses simple mode switching, address translation and buffering to provide interrupt based classic (Compatibility Support Module) BIOS services while in 32bit protected mode.
A typical application is to have the boot sector or mbr load SudoBIOS as a 2nd stage (to absolute address 0x2000). A far call to that location returns in 32bit protected mode. A subset of the native BIOS functions (the common usable ones) are supported.
SudoBIOS is written in FASM (2200+ lines of Intel syntax x86 assembly language) and will assemble as is in NASM. Both output files are essentially the same (with NASM -O2). The only insignificant difference is the order of the operand (0x66) and address (0x67) override opcode pairing of the 2 assemblers.
There is a SudoBIOS demo. MikeOS32_4.4.img. It's a 1.44MB FAT12 USB flash drive image of the real mode MikeOS converted to 32bit, running in 32bit protected mode and accessing BIOS services transparently through SudoBIOS. It will boot and run as either a floppy disk or hard disk format on real hardware and QEMU. The image is a non standard floppy disk so BOCHS has trouble running it as a floppy image, but will work fine as a disk image.
The source code for MikeOS32 is MikeOS32_4.4.zip
SudoBIOS
Re: SudoBIOS
Posted: Sun May 17, 2015 2:54 pm
by Roman
Having a 32-bit BIOS-like service and running MikeOS in 32-bit mode sound very interesting. Nice work! I will try, when I will get to my computer soon.
Re: SudoBIOS
Posted: Sun May 17, 2015 3:47 pm
by BrightLight
Not working.
Re: SudoBIOS
Posted: Mon May 18, 2015 2:05 am
by Brendan
Hi,
mikegonta wrote:SudoBIOS (my latest project) is a partial rewrite/update of my previous aeBIOS.
I took a quick look at the code, and noticed you've got different code for every single BIOS function. This is completely unnecessary - protected mode interrupt handlers can switch to real mode and transfer control to the BIOS without caring what it is.
The only limitation is that some BIOS functions use segment registers and you can't load "real mode compatible" segment registers in protected mode; but it's enough to have "real mode DS and ES" in global variables that are set and/or read by the caller (if they care); that are loaded after switching to real mode (before passing control to BIOS interrupt handler), and are stored before switching back to protected mode.
The other problem is if you want decent protected mode exception handlers. It's entirely possible to tell the difference between an exception and an IRQ by examining the PIC's "in service" register; and possible to tell the difference between an exception with an error code and a software interrupt by examining the stack (e.g. see if "return CS" and "saved EFLAGS" look sane), and possible to tell the difference between an exception (that has no error code) and a software interrupt (by checking if "return CS:EIP - 2" points to an "int n" instruction).
mikegonta wrote:SudoBIOS is written in FASM (2400+ lines of Intel syntax x86 assembly language)
Exactly - it could be more like 200 lines of Intel syntax x86 assembly language.
Cheers,
Brendan
Re: SudoBIOS
Posted: Mon May 18, 2015 3:07 am
by alexfru
Brendan wrote:
and possible to tell the difference between an exception with an error code and a software interrupt by examining the stack (e.g. see if "return CS" and "saved EFLAGS" look sane), and possible to tell the difference between an exception (that has no error code) and a software interrupt (by checking if "return CS:EIP - 2" points to an "int n" instruction).
But can you do that consistently? The "int n" instruction at CS:EIP could be part of another, larger instruction, e.g. it could be an immediate with the most significant bytes being n and 0xCD. And how much more complex you'd want the heuristics to be in both cases? Checking bits that are hardwired to 0 and 1 in what's supposed to contain EFLAGS? Checking 16 bits of what could be CS against GDT and LDT? And also checking what could be EIP against the segment limit?
Re: SudoBIOS
Posted: Mon May 18, 2015 3:20 am
by mikegonta
Brendan wrote:I took a quick look at the code, and noticed you've got different code for every single BIOS function. This is completely unnecessary -
protected mode interrupt handlers can switch to real mode and transfer control to the BIOS ...
The transfer is handled by the small rm_interrupt routine.
Brendan wrote:... without caring what it is.
SudoBIOS cares.
That would be fine for a simple extender. The user would be required to call setup routines and juggle various aspects of the interface.
SudoBIOS "emulates" a 32bit protected mode BIOS transparently. 32bit input/output use only one register (not two like in RM), user
address buffers are in high memory (SudoBIOS does the translations and buffering) and only those registers and flags in the specification
of the functions are altered (SudoBIOS guarantees this). Even RM interrupts which occur while the RM BIOS is executing are handled in PM
(the default handler merely executes the original RM handler), this is so the user can manage all interrupts (if they choose) totally in PM.
Brendan wrote:mikegonta wrote:SudoBIOS is written in FASM (2400+ lines of Intel syntax x86 assembly language)
Exactly - it could be more like 200 lines of Intel syntax x86 assembly language.
The attention is in the detail.
Re: SudoBIOS
Posted: Mon May 18, 2015 4:41 am
by mikegonta
omarrx024 wrote:Not working.
Thanks for trying it. It works fine in QEMU and of course on a real PC (don't be shy).
The image is a non standard FAT12 "floppy disk". However, it works fine as a FAT12 hard drive image. As a USB flash drive image it
will boot and run as either a floppy disk or hard disk format (on real hardware and QEMU). It works fine when booted as a disk
image in BOCHS.
SudoBIOS (like the RM BIOS) has little to do with the loading of the running program. SudoBIOS is a 2nd stage loaded by the boot sector
or mbr to absolute address 2000h. A far call to that location returns in 32bit protected mode. The boot sector in this case has relocated
itself (like an mbr) and loaded a "fake" 32bit PM boot sector (the one that loads the MikeOS32) before making the call.
Re: SudoBIOS
Posted: Mon May 18, 2015 5:15 am
by Antti
alexfru wrote:The "int n" instruction at CS:EIP could be part of another, larger instruction, e.g. it could be an immediate with the most significant bytes being n and 0xCD.
An excellent point. It is very complex, perhaps impossible to do 100% correctly, to interpret machine instructions "backwards" although it might be "almost always correct". However, it is possible to say "we know for sure that it was NOT a software interrupt".
Re: SudoBIOS
Posted: Mon May 18, 2015 5:20 am
by mikegonta
Roman wrote:Having a 32-bit BIOS-like service and running MikeOS in 32-bit mode sound very interesting. Nice work! I will try, when I will get to my computer soon.
Thanks Roman.
There was a small bug that worked fine in QEMU but failed on real hardware.
The latest version is here:
http://mikegonta.github.io/SudoBIOS/
Re: SudoBIOS
Posted: Mon May 18, 2015 11:25 am
by Brendan
Hi,
alexfru wrote:Brendan wrote:
and possible to tell the difference between an exception with an error code and a software interrupt by examining the stack (e.g. see if "return CS" and "saved EFLAGS" look sane), and possible to tell the difference between an exception (that has no error code) and a software interrupt (by checking if "return CS:EIP - 2" points to an "int n" instruction).
But can you do that consistently? The "int n" instruction at CS:EIP could be part of another, larger instruction, e.g. it could be an immediate with the most significant bytes being n and 0xCD. And how much more complex you'd want the heuristics to be in both cases? Checking bits that are hardwired to 0 and 1 in what's supposed to contain EFLAGS? Checking 16 bits of what could be CS against GDT and LDT? And also checking what could be EIP against the segment limit?
You can split the interrupt vectors into several "bands"; specifically:
- 0x00 to 0x07: Must be an exception
0x08 to 0x0F: Either IRQ or exception
0x10 to 0x1F: Either software interrupt or exception
0x20 to 0x6F: Must be software interrupt
0x70 to 0x77: Must be IRQ
0x78 to 0xFF: Must be software interrupt
This means that the only "interesting" cases are vectors 0x10 to 0x1F. Now take a look at the possible exceptions in this range:
- 0x10 = potential FPU error; however it's impossible for it to be an exception (unless "native FPU error reporting is enabled which is a good idea in general but breaks BIOS compatibility and therefore can't/shouldn't be enabled).
0x11 = potential Alignment Check; however it's likely to be impossible for this to be an exception (as alignment checking must be enabled and nobody ever does that).
0x12 = potential Machine Check; however it's likely to be impossible for this to be an exception (as machine checking must be enabled and nobody using real mode is likely to ever do that).
0x13 = potential SIMD floating point exception; however even if software uses SIMD the causes of this exception are all almost always masked.
0x14 = potential virtualisation exception; however it's likely to be impossible for this to be an exception (as virtualisation need to be "in use" and that's extremely unlikely).
0x15 to 0x1F = never an exception ("reserved" by Intel)
Essentially; while in theory it might be possible for software to have a bug that causes an exception that is mistakenly assumed to be a software interrupt; in practice the risk is extremely close to zero; especially for code that is still using BIOS functions (e.g. boot code and kiddy toys).
Cheers,
Brendan