Low-level start another OS than the current OS bypassing the BIOS

Viewed 259

Is it possible, with C / Assembler low-level system calls to start the bootloader of another OS (let's say HDD2, Partition 1) than the currently-running OS (HDD1, Partition 1), thus bypassing the BIOS?

i.e. if Windows is currently running, can we directly ask the system to boot another kernel (let's say Linux) on HDD2, Partition 1, without having to do a full reboot via the BIOS?

Or is this out of reach of what C / Assembler can do?

If so, what prevents us to load HDD2, Partition 1, Offset 0 and the following megabytes into memory, and to run code from there? (i.e. kill the currently-running OS and boot another OS)

2 Answers

Or is this out of reach of what C / Assembler can do?

No, they can do it, but it is what the OS does that, in practical terms, makes this difficult to do.

Caveat: The following is a somewhat loose description of what goes on ...

The BIOS does a certain amount of initialization. It probes for devices, etc. and presents what it finds in the ACPI interface.

The given bootloader (i.e. boot block) for a given OS will get control from the BIOS. It expects to be in 8086/real mode. (i.e. paging turned off) and loaded at a given real mode address.

The bootloader will relocate itself. It will use BIOS calls to read the OS kernel from the disk/partition.

It will then transfer control to the OS startup code.

The OS will expect to be able to use ACPI information. Also, the OS will probably expect to be running in real mode (or whatever mode its bootloader sets up).

The first OS will now do lots of initialization of the hardware.

To be able to give the chain loaded/second OS the environment it expects, when shutting down, the first OS has to restore the state to something like what the BIOS provides.

Some of the device initialization that the first OS does may confuse the second OS. So, it has to do a very clean shutdown/reset to known state for the hardware. For example, disable paging/MMU, return to 8086 real mode, put the second OS's boot block at the known/expected real mode address and transfer control to it.

Not all [or many] OSes are set up to do this because it's not common. Some will use the BIOS during initialization [as I said (e.g.) ACPI]. But, some OSes will eventually dispense with the BIOS.

They would have to ensure that the BIOS can function [again] because the bootloader of the second OS will use the BIOS calls to load the OS code from disk.

It is possible. And, IIRC, some OSes are capable of doing this. But, I'm not sure WinX cooperates on this point.

Getting the bootloader for the second OS is further complicated if the system is a UEFI system [vs. the perennial BIOS]. If using secure boot, the OS boot loader is contained in a [digitally signed] file within a special partition with a simple (e.g. FAT) filesystem.

Is it possible, with C / Assembler low-level system calls to start the bootloader of another OS (let's say HDD2, Partition 1) than the currently-running OS (HDD1, Partition 1) ... without having to do a full reboot via the BIOS?

Indeed, early Linux versions contained a tool named loadlin doing more or less what you describe:

Linux was loaded from MS-DOS or Windows 9x.

However, because MS-DOS and some drivers modified the original BIOS interrupt vectors, you had to make a copy of the original interrupt vectors before using the tool the first time:

This was done by booting a special bootable software from floppy. When you used loadlin later, the copy made by that bootable software was used to restore the interrupt vectors.

... i.e. if Windows is currently running ...

Modern Windows versions are not MS-DOS nor Windows 9x:

The main problem would be that Windows does not allow you to switch the CPU (back) into real mode.

Even under MS-DOS loadlin had problems with certain "EMS" drivers because of this reason.

Next problem would be that Windows (NT, XP, Vista, 7, 8, 10) puts the hardware (e.g. hard disks) into a state that cannot be handled by the BIOS. This was not the case for MS-DOS or Windows 9x.

If so, what prevents us to load HDD2, Partition 1, Offset 0 and the following megabytes into memory, and to run code from there?

Nothing.

According the German language Wikipedia loadlin even loaded the Linux kernel from any file on any drive.

Related