Hi neon,
I use a very similar technique in my boot code. (
Here is an older version) It is called from unreal mode, allowing the caller to have memory, stack, and code to be anywhere in the 4gig address space. The call, however, requires all memory used by the service to be accessible by a real mode BIOS.
An alternative to your technique, I use the same space for the 'in' registers as I do for the 'out' registers. I don't see any reason to preserve the 'in' state.
Also, I don't worry about calling it after the loader transfers control to the kernel. Once the kernel takes control, the loader is no longer a part of the system. However, I see an advantage to your technique.
In theory, since I use unreal mode through out my loader, I wouldn't need something like this. A real mode BIOS should work just fine in unreal mode. However, with a technique like the one I use, my loader, its stack, and any memory buffer needed, can be anywhere in the 4 gig space, using all of the 32-bits of a register, and still call a BIOS service call without worries.
Another note, my code uses self modifying code just like yours:
Code: Select all
mov ebx, .call_service - NBOOT_IMAGE_BASE
mov byte [ ebx + 1 ], dl
.
.
.
.call_service:
int 0
One problem that I know is that you have to make sure there is enough of a code stream between the self
modifying code and the self
modified code so that the processor hasn't already loaded that code into the cache. Granted on some systems, the processor will see this and compensate. Older machines may not. However, I think you have plenty of space between the two.
I wanted to use a serializing instruction, such as CPUID, to guarentee this, but this assumed I had checked that the CPUID instruction was first available before a call like this. The chicken and the egg scenario here is that I use this "wrapper" to call the BIOS to print a message to the screen. If a CPUID instruction is not found, I would want to print an error message stating so. However, to print the error message, a CPUID instruction would have to be available to do so. Chicken/egg...
Anyway, good point. I think a good loader needs a BIOS wrapper like this.
Ben