Hi,
I think you may want to look at the boot code and dig around a bit. Here's what I know.
In
sys/boot, there's a lot of code already that makes up the loader. As the loader used to be able to boot an ia64 aka Itanium which exclusively has EFI and no BIOS, there's some EFI code available already. This may give a good starting point for 1) and 2).
In my opinion, the real challenge lies in 3). Have a look at
sys/i386/i386/locore.s which is the kernel's entry point. The code goes on to
init386() in
sys/i386/i386/machdep.c and then calls into
mi_startup() in
sys/kern/init_main.c. The former is the machine dependent (MD) start-up code while the latter is the machine independent (MI) code.
As the name implies, the MD code is i386 specific and I wouldn't be surprised if there were a BIOS dependency in there. In fact, it seems
init386() calls
getmemsize() from
sys/i386/i386/machdep.c which looks to me as if it went for the BIOS to query the system's memory size.
Also,
mi_startup() is the core of the
SYSINIT framework which orders and runs the constructors of various kernel subsystems. One of those subsystems is "bios32", declared in
sys/i386/i386/bios.c. It looks like at least the APM functionality depends on that subsystem. I don't know if anything else depends on it.
Anyways, you shouldn't be discouraged by what I'm telling you. I'm merely trying to point you to the right places of the documentation which often times is in fact the code itself.