Hi.

The BIOS is obviously compiled into machine code and AWARE of the components on the motherboard. However, how does the Kernel and Operating System applications become aware of the components on the motherboard? I mean, with you compile you application, what in the assembly is reserved to discover this components?

I'm about to dive into customizing & building Linux for a Nano-ITX board. As an experienced programmer, I should know this but my compiler experience if very limited. I've designed hardware, dealt with some legacy assembly languages, and programmed in many high-level languages.

However, it has ALWAYS confused me about the difference between the assembly recognized but CPU and what gets generated with a program is compiled for Windows.

Can someone explain this to me?

Thanks,
Leon
Posted on 2007-09-07 02:06:13 by spencer_leon
BIOS does very specific things like chipset programming and CPU microcode updates.

The OS kernel will probe the system for available devices, through BIOS and drivers; PCI probing is a lot easier than looking for old ISA devices, because of the vendor/device IDs of PCI.

Your own applications obviously won't have any "awareness" of devices except for what the OS exposes through it's APIs.

What gets programmed when an application is compiled for windows? The answer is: "what you put in the program" :)
Posted on 2007-09-07 07:24:44 by f0dder
:shock: So is a motherboard designed to the BIOS or the other way around? I would like to provide my own BIOS for a Mini-ITX board but I've been advised the boards are design around a particular BIOS manufacturer. So how do I know programmatically, i.e. via assembly/machine code, how to talk to devices on the board if I want to write my own BIOS?

Is this even possible? How are LinuxBIOS and OpenBIOS doing it?
Posted on 2007-11-06 16:51:29 by spencer_leon
Haven't been doing BIOS programming myself, but as I understand it there's a lot of common stuff in each BIOS vendor (Dell (yeah, they have their own for some products, it would seem), Phoenix, Award) - and then there's chipset-specific code for initializing various stuff. It's also the BIOS code that's responsible for setting up SMI mode.

So... if you have specs for everything (or "enough" of it anyway) on the platform you're going to run, you can do your own BIOS. If you have very specific needs, you don't need to provide a full BIOS implementation, just barebones device initialization, and enough interrupt calls to use whatever bootloader for your OS...
Posted on 2007-11-06 17:14:19 by f0dder
So how do I know programmatically, i.e. via assembly/machine code, how to talk to devices on the board if I want to write my own BIOS?

Well, if you don't know how to write a driver (or at least a 'mini' driver) then you DEFINITELY should abandon any ideas like writing a BIOS.
Posted on 2007-11-06 18:04:53 by ti_mo_n

So how do I know programmatically, i.e. via assembly/machine code, how to talk to devices on the board if I want to write my own BIOS?

Well, if you don't know how to write a driver (or at least a 'mini' driver) then you DEFINITELY should abandon any ideas like writing a BIOS.


Come on ti_mo_n, I know how to write a driver. Seriously, are you suggesting I focus on writing custom kernel mods instead of trying to mess with the BIOS? Maybe that will work better.
Posted on 2007-11-06 18:36:19 by spencer_leon
I also think that it's better to simply modify the kernel (or write your own) to suit your needs. Unless you saw something in the chipset docs, that could have been made inoptimal in the current BIOS.
Compiled code... it's put in an .obj file. In that file, the different sections (.data, .text, .reloc,..) are dumped. And relocation-sections are added, with the name of local public or non-public symbols and their offsets in the sections. Then, the linker accepts a bunch of .obj and .lib files (.lib are almost simply zipped .obj files). The linker searches which .obj has a symbol, marked as the program start (i.e our "start:" or "_start:"). The linker marks that .obj file as "used/included". Then, for each imported symbol in that .obj file, includes (marks as "used") all .obj files that have those symbols. Thus, if you specify 100 .obj files as input to the linker, it'll only use those required to build a valid output file (.exe, .dll, .obj or .lib). To build that output file, it merges sections, and updates the relocation-info.
.exe and .dll files also have relocation info. (with several tables: one for internal, non-exported symbols, another for string-named exported symbols, and another for string-named imported symbols). And of course, they also have sections (.bss .data and .text at least).
When Windows loads an .exe/.dll, it does relocations - simply putting a 4-byte address at some offset in a section, or adjusting an instruction's parameters. It does the same for imported symbols (i.e API or any function from any dll).
This is how executables are loaded, more or less. I only have experience in manually building executables for non-x86 OSes, by using GCC, though

P.S. toy with LD(.exe) and OBJ-Dump from GCC's bin tools.
Posted on 2007-11-07 09:18:57 by Ultrano

Haven't been doing BIOS programming myself, but as I understand it there's a lot of common stuff in each BIOS vendor (Dell (yeah, they have their own for some products, it would seem), Phoenix, Award) - and then there's chipset-specific code for initializing various stuff. It's also the BIOS code that's responsible for setting up SMI mode.


From past experience, at various companies, this is exactly how things are done.


So... if you have specs for everything (or "enough" of it anyway) on the platform you're going to run, you can do your own BIOS. If you have very specific needs, you don't need to provide a full BIOS implementation, just barebones device initialization, and enough interrupt calls to use whatever bootloader for your OS...


Again, right on the money.

Posted on 2007-11-07 10:46:14 by madprgmr