15

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.

5
  • 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, 2020 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. Oct 2, 2020 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, 2020 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, 2020 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, 2020 at 19:44

2 Answers 2

15

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. Apparently some kind of driver of this sort was planned at one point: in Linux 1.3.22, the first release to contain the devices.txt documentation file containing device number assignments, major block device numbers 12 and 14 are reserved for ‘MSCDEX CD-ROM callback support’ and ‘BIOS harddrive callback support’ respectively. The reservations have never been claimed by an actual driver, however, or even added to the linux/major.h header file, and they have been removed from devices.txt in Linux 2.6.30. (Thanks to @Joshua for letting me know this reservation existed, prompting me to investigate further.)

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. (This driver does not use the above-mentioned reservations.)


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:

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.

10
  • 2
    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. Oct 3, 2020 at 17:46
  • 2
    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. Oct 4, 2020 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, 2020 at 10:06
  • 1
    @dirkt: I'm confused. Why do the tables get thrown away when they survive when booting MS-DOS? The bottom 4KB of RAM is preserved in both cases as is the shave-off region at the top of 640KB should the memory range call say any was shaved off. As for the rest, I've never seen a Linux disk driver that used bios calls, but the old major/minor tables had reserved device ids for such a device. I think the idea was to not emulate it, but transfer back to real mode, call the BIOS interrupt, and transfer back.
    – Joshua
    Dec 12, 2021 at 22:35
  • 1
    Just ran into this video. I can't verify but it looks like somebody actually did implement it, and that's why there was the reservation. youtu.be/Cynd0guSUvM?t=868
    – Joshua
    Jul 21 at 3:59
6

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.

10
  • 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. Oct 4, 2020 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. Oct 4, 2020 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, 2020 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, 2020 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, 2020 at 10:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .