On Sun, 4 Dec 2016 23:36:14 -0800 (PST)
Hoang Nguyen <
jerry.n...@gmail.com> wrote:
> I have a crazy requirement...that I need to go to Bios Setup from
> pre-boot environment or OS environment without restart the PC. (the
> normal practice is to restart the PC then press the hotkey to force
> system go to Bios setup)
>
> Initially, I am thinking to switch the CPU to v8086 mode and map the
> physical memory from 0x0000 - 0x10000 to some high memory address.
> Then make a call to reset address ( 0xFFFFFFF0 ) ...there will be
> some work to handle when the code tries to access the physical port
> (for example CMOS port, hdd port...)
You'd need to also look at setting values for CMOS 0Fh and 40:72h and
40:67h.
40:72h is the reset flag:
(this has other valid values)
0000h - cold boot
1234h - warm boot
4321h - preserve memory
CMOS 0Fh is the shutdown code:
(this has other valid values)
0 - full reset, POST tests executed
4 - reboot with NMI on, skips POST, int 19h
5 - skip POST, preserve memory, clear keyboard EOIs, clear interrupts,
jump to 40:67h
6 - no EOIs issued, jump to 40:67h
Ah - clear interrupts, no EOIs issued, jump 40:67h
Bh - iret to 40:67h
Ch - retf to 40:67h
Some sources say Ch uses iret instead of Bh.
40:67h is an address pointer to 16-bit resume code after a reboot with
40:72 set to 4321h (preserve memory). I.e., if 40:72h is set to 4321h,
and CMOS 0Fh is set to values (5,6,Ah,Bh,Ch) which jump to the address
at 40:67h, code execution will resume at the address stored at 40:67h.
Jumping to an address at 40:67h is known as a 286 reset. The 80286 uses
this method to switch from protected mode to real mode, since it had no
method to exit protected mode.
Of course, I've not tested this and the information sources I have are
not very reliable. So, you may have to do some experimentation. E.g.,
it might be Ch that uses iret or you might need 1234h instead of 4321h,
etc.
Since this 40:67h functionality was intended for a 80286, it's possible
that this functionality is not available, or has been reduced or
eliminated for some BIOSes. One specification does eliminate it. This
is for Intel EFI CSM (extensible firmware interfaces, compatibility
support module). The specification eliminates usage of 40:67h and CMOS
0Fh. So, if your machine has a EFI/UEFI instead of BIOS, it may not be
able to use this technique to regain control of execution.
However, the 40:67h method is designed to skip the BIOS setup and POST
and return to an executing program in real-mode from protected-mode.
If you don't use 40:67h, you'll need some other way to regain
control of processor execution. Since you want to access the BIOS
setup, you'll have to do a cold boot, which doesn't use 40:67h. The
BIOS setup is not available from a warm boot or a 286 reset. You could
try setting Int 18h and/or Int 19h vectors. However, those vectors are
likely to be reset for a cold boot.
The BIOS hooks most of the vectors from 00h to 1Fh, 70h to 7Fh, and
many in the region of 40h to 6Fh. These are most likely reset during a
cold boot. The BIOS doesn't hook 0h, 1h, 3h, 4h, and 7h. These are
for processor exceptions. So, if you set some of those vectors and are
able to find a way generate such a exception, you may be able to regain
control of execution. I'm not sure how you'd do that without already
having control of execution.
You might be able to enable the TF (trap flag) for single step
execution, set vector 01h, set 40:72h to cold boot for the BIOS setup,
call FFFF:FFF0h, if the BIOS code is v86 clean, and the BIOS doesn't
use PM or SMM, and ports are open in TSS, you might be able to use the
01h interrupt to watch for an Int 18h or Int 19h instruction. Once you
trap the Int 18h or Int 19h instruction, 01h interrupt code can
transfer execution to your code, before the BIOS attempts to boot a
device. Be warned that once the TF is set, every instruction is going
to call the 01h interrupt, i.e., slow. Effectively implementing a
working 01h interrupt routine is difficult as a number of instructions
must be emulated, e.g., INT n, PUSHF, POPF, IRET, INTO, INT3. If
certain PM instructions are seen, e.g., LIDT, SIDT, LGDT, SGDT, SMSW,
LMSW, INVPLG, etc., you must disable the TF. This causes you to lose
control of execution. E.g., for the LIDT instruction, the IVT/IDT is
invalid. So, you can't generate any more interrupts, including for the
01h TF interrupt, as you'll cause a general protection fault, leading to
a triple fault and a processor reset. So, this would only work if your
machine's BIOS is v86 clean, and doesn't use any PM code.
> I would like to check from your expert opinion...Is it possible to do
> that?
Possible, yes. Probable, no.
After protected mode (PM) was introduced with the 80286, most machines
use began using PM during the BIOS hardware setup. This gives the
BIOS full access to memory to program memory-mapped hardware. Some
BIOS are reported to use system management mode (SMM) also.
Some machines have BIOSes which are much larger than the original
BIOS memory regions. So, it's likely they are using PM or SMM to
temporarily unmap memory and map in the extended BIOS regions.
To call the BIOS from v86 mode, the BIOS would likely need to:
1) not use PM
2) not use SMM
3) have x86 code which executes cleanly in v86 mode
4) not be EFI/UEFI
It's not known whether or not the BIOS code is entirely clean for v86
mode. BIOSes may only be v86 clean for code that is expected to be
called from v86 mode. Since the only reasons to call the BIOS reset
are cold-boot, warm-boot, and to exit PM, it's possible the BIOS
reset code isn't clean for v86 mode. It most likely uses PM too. It's
expected that the processor isn't in PM.
I would think you could do this on really old machines, which likely
only have 8086 code in their BIOS, but would be skeptical about using
this on modern machines due to use of PM. Although, maybe a warm boot
or boot which skips POST, instead of a cold boot, would cleanly pass in
v86 mode. The cold boot and/or POST initializes hardware.
So, I think your main problems are:
1) cleanly executing the BIOS cold boot code in v86 mode
2) regaining control of execution near first Int 18h or Int 19h
Please note that this is all somewhat speculative based on what I think
I know.
Good luck,
Rod Pemberton