If there is some piece of PC compatible hardware where there are no (publicly) existing drivers for Linux, the only option is to access the disk with BIOS calls. I'm aware that this imposes restrictions on the maximum size of disk and/or partition to be used.

Has some old Linux Kernel featured such a driver? Searching online yields a lot of irrelevant hits about more modern systems and their particular booting challenges.

My goal is to be able to run Linux from the emulated disk on an old AS/400 IPCS card. OS drivers are available only for Windows NT 4 and 2k.

  • 3
    The issue is PC / PC compatible BIOS disk calls are real mode only so past something like GRUB in the early / pre-boot process they wouldn't be used by Linux. – Brian Oct 2 '20 at 17:10
  • 1
    The kernel cannot, actually; vesafb only calls the video BIOS once at boot, before the kernel is properly started (mode-switching is impossible afterwards), while uvesafb delegates BIOS calls to userspace. – user3840170 Oct 2 '20 at 17:39
  • Some calls can be done using something like ibx86 but mainly it was done for mode setting for displays as that wasn't standardized in hardware and varied a lot between different video chips/cards. – Brian Oct 2 '20 at 17:42
  • @user3840170 in older systems calling video BIOS actually worked fine; the VESA driver for X did this for a long time, and X had to use it to initialize a second graphics card. IIRC it doesn't work for disk BIOS services, because they need some tables that are only present in real mode. – dirkt Oct 2 '20 at 18:16
  • The link you provided suggested it was possible to run Linux on it with a USB floppy... I was also going to suggest looking into whether you could PXE boot is (diskless boot, and then possibly NFS mount if you needed to be able to write stuff) but it doesn't sound like it has a "real" network card to support that (though given it supports Netware, not positive) [Neither of these answer your question, but might be other things to look at for your underlying challenge] – Foon Oct 2 '20 at 19:44

To my knowledge, no such driver has ever been written.

Since the very earliest versions, Linux has been a pure 32-bit protected-mode kernel that drove most devices (including disk controllers) directly, without going through the BIOS. The kernel has never had any facility to invoke 16-bit code from kernel mode during normal operation (after early boot); even the APM driver only ever supported the 32-bit protected-mode entry point. While support for 16-bit protected mode and virtual 8086 mode has been added, it was only ever driven by userspace, i.e. by DOSEMU, Wine and (userspace) VBE video drivers. The closest Linux got to a mechanism to invoke real-mode code from kernel mode is in a patch for the vesafb driver in Linux 2.6.20 that was never merged into the mainline kernel; the patch’s successor, uvesafb, likewise invoked the video BIOS from userspace.

In particular, there has never been a BIOS-based kernel disk driver. Such a driver does exist in ELKS (a fork of Linux focusing on embedded systems), but I assume that ELKS and mainline Linux have already diverged enough to make adapting this driver for the latter a highly non-trivial task.

Your best bet is probably to write a driver for this device yourself: either via reverse-engineering or by creating a virtual 8086 mode monitor/emulator to run the BIOS-based driver in, like userspace VBE drivers do. In the general case, I expect the latter approach to be very fragile, as the ROM BIOS code may assume that it has the entirety of the hardware at its disposal, make all sorts of assumptions about its state, and attempt to perform operations that are difficult to emulate, especially from userspace code. In particular it may try to:

  • raise a System Management Interrupt (the BIOS on a laptop I am writing this on does that),
  • turn off interrupts to guarantee atomicity,
  • reconfigure the Programmable Interrupt Controller and other hardware,
  • perform DMA transfers,

And many other things. Most of these considerations usually do not apply to video BIOSes, as those usually confine themselves to operating on the video hardware itself. As such, they only require access to I/O ports and memory, and those are rather easy to provide.

Also note that the BIOS interrupt calls were not designed to be reentrant or execute under the supervision of a multitasking operating system (they were designed as drivers for DOS, after all). Given that, environments which do provide BIOS-based disk drivers are either single-tasking systems like DOS anyway or take some pains to ensure that BIOS calls have exclusive access to all the hardware (including the CPU) and do not interfere with anything else:

  • GNU GRUB 2, a boot loader containing both BIOS and ‘bare-metal’ disk drivers, is a single-tasking, pure ring-0 environment that contains some logic to ensure firmware-based and native drivers are not used at the same time;
  • The real-mode mapper in Windows 9x (i.e. its DOS/BIOS file system driver) executes real-mode code in ring 0 and guards it by the critical section, which is essentially a global kernel lock (cf. Linux removing the Big Kernel Lock entirely in version 2.6.39)

All of the above told, things are not hopeless: if you stick to a narrow goal of writing a driver that works with a specific BIOS whose behaviour is known so that you can apply workarounds specific to your firmware (as opposed to creating a fully general solution), there is a good chance it might actually work quite reliably. Especially if the BIOS comes from an option ROM on an extension card, as those are much less free to assume things about other hardware that may be present.

  • "The kernel has never had any facility to invoke 16-bit code from kernel mode in normal operation" Maybe the kernel didn't, but it was easily possible, as I already wrote above in the comment. For example, have a look at the code for the old VBE X driver, you can see that it calls interrupt 0x10 in the BIOS. – dirkt Oct 3 '20 at 17:33
  • 1
    That’s a userspace driver, using the vm86 syscall; its existence doesn’t refute what I said. Video drivers can get away with executing BIOS calls from userspace, because the video BIOS tends to be relatively isolated from the rest of the firmware (e.g. the SMM handler); running it doesn’t require full ring 0 privileges, just I/O port access. I don’t understand why you downvoted a correct answer: a BIOS-based disk driver has never existed and for the reasons I listed, it’s not going to be trivial to write one. – user3840170 Oct 3 '20 at 17:46
  • And the kernel could equally well get away with calling the BIOS, using it's own implementation of the vm86 syscall (which means "never has had any facility" is just wrong). It doesn't do that, because the problem is that in particular the disk BIOS calls (unlike the video BIOS) need specific tables in memory, which get thrown away after the switch to protected mode. So instead of trying to salvage this across different BIOSes, it was simpler, cleaner and more efficient to just have the kernel provide drivers. And that's the real reason, not because "it cannot be done". – dirkt Oct 4 '20 at 4:41
  • 1
    The ‘kernel could equally well get away’—but didn’t. Were this so easy, uvesafb wouldn’t need a userspace helper. The kernel ‘could equally well get away’ not throwing away any tables (in fact, nothing in conventional memory is thrown away as far as I can see); it can set up any memory map it wants. The real difficulty is in ensuring the BIOS can access all the hardware it needs without disturbing anything else. And I never just said ‘it cannot be done’: I pointed to specific difficulties that will have to be overcome, which aren’t just ensuring some unspecified ‘tables’ are present. – user3840170 Oct 4 '20 at 5:35
  • 1
    Thanks @all for all the explanations and lively discussion! I did not expect to attract that much attention with my question. Apparently I was wrong. :-) – PoC Oct 4 '20 at 10:06

It's perfectly possible for both userspace and the kernel to access the BIOS. In fact, the kernel offers a vm86 syscall, which is an emulation of real mode.

This syscall was used for a long time in the vesa driver for X (before it got replaced with the vesafb kernel driver; see e.g. here for some code), there are projects like Linux Real-Mode Interface which use it to provide a DPMI-like interface to real mode BIOS, etc.

However, the problem with using the BIOS calls for disk access is that those depend on in-memory tables that are not preserved when Linux boots – in particular because different BIOSes do this differently. Therefore it was much easier and cleaner for Linux to just provide its own drivers for disk access than to try to deal with this mess.

That's why the kernel never featured such a driver.

So for your particular case, you'd need to write the drivers in one way or other. You can either go through the trouble to figure out where how the BIOS of the IPCS stores the tables, or you can figure out how your existing drivers work. Both would presumably have some way to communicate with the AS/400 host to transfer blocks from and to the emulated disk. So reverse engineering is needed anyhow, and then you can write the Linux drivers for it.

This looks like a fun project, but it probably can be quite time consuming.

  • Providing in-memory tables is trivial: just mmap /dev/mem. Linux apparently preserves enough conventional memory to make projects like ‘DOS Subsystem for Linux’ actually somewhat viable. Preserving ‘in-memory tables’ is a non-issue. The real problem is keeping the BIOS from stepping on other drivers’ invariants. – user3840170 Oct 4 '20 at 7:48
  • The other thing is, vesafb cannot do mode switching at runtime, so it didn’t fully replace the X driver: X had to do mode switching (i.e. calling the video BIOS) on its own. The predecessor to uvesafb, vesafb-tng required invasive kernel patching to invoke 16-bit code from a kernel thread; this has never made its way upstream. uvesafb just calls vm86 from a userspace helper daemon. – user3840170 Oct 4 '20 at 7:50
  • @user3840170 Providing them is trivial, you don't even need /dev/mem for that. Capturing the existing tables at boot is not, because every BIOS does that differently. Which means the standard Linux boot just throws them out. And as your link shows, it's perfectly possible to invoke 16-bit code from a kernel thread. It's just not something you want in the Linux kernel, for architectural reasons. So the answer is not "it can't be done", the answer is "people don't do it because it's too ugly to make it work". – dirkt Oct 4 '20 at 10:05
  • @dirkt Reverse-Engineering might be fun but it's clearly far beyond my capabilities, in terms of skill, knowledge, patience, and time. Also, since at leat the #2850 is maxed out with 128 MB of ram, the driver in a current kernel (with a current userland) might be somewhat useless: Committed_as shows as little as 50 MB used in a minimal install, but apt-get update itself will not run with less than 256 MB. – PoC Oct 4 '20 at 10:09
  • @PoC Embedded variants of Linux run with a lot less RAM, so you can certainly tweak things. Also, the link you provided mentions that Linux drivers did exists, maybe they (and the Linux version they belonged to) can still be found somewhere? – dirkt Oct 4 '20 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.