68

As I understand, the BIOS code/bitstream that is held in the ROM should be generic (work alongside with multiple CPU types or ISAs). In addition, I saw mentioned on the web that it is possible to dump its code (and to "disassemble" it).

So, in which language, instruction set or machine code is it written? Doesn't it need any kind of processor to perform its operations? If so, I guess that it will use the external CPU, then how does it know the specific instruction set of the employed one?

Maybe it has an internal processor?

Dr. Essen
  • 123
  • 6
Reflection
  • 769
  • 1
  • 6
  • 6
  • 9
    possible duplicate of [How Do Computers Work?](http://programmers.stackexchange.com/questions/81624/how-do-computers-work) – gnat Sep 30 '15 at 13:25
  • 39
    [Cross posting](http://reverseengineering.stackexchange.com/questions/10997/in-which-language-a-bios-is-written) is bad enough, but when it ends up on the Hot Network Questions *in both versions*, that's just beyond the pale... – Mason Wheeler Sep 30 '15 at 15:45
  • 9
    "BIOS code/bitstream that held in the ROM should be generic (work alongside with multiple CPU types or ISAs)." -- I *never* heard of a BIOS that works with multiple ISAs. Do you have an example? – chx Sep 30 '15 at 16:02
  • Part of this is a question I asked (in a much worse way) on cs.SE: http://cs.stackexchange.com/questions/29117/does-the-bios-run-on-the-cpu – Piper McCorkle Sep 30 '15 at 17:45
  • 6
    `As I understand, the BIOS code/bitstream that is held in the ROM should be generic (work alongside with multiple CPU types or ISAs). ` I'd say "No, just the contrary" – edc65 Sep 30 '15 at 17:59
  • 11
    This is not even remotely a duplicate of a question as general as "How Do Computers Work?". Please do not close as dupe. – Andres F. Sep 30 '15 at 19:56
  • To add to Mike Nakis' answer, OP might like to take a look at [avr-libc](http://www.nongnu.org/avr-libc/user-manual/index.html) for a simple example of a C library that provides low-level functionality like direct register access and interrupt vectors. – calvinsykes Oct 01 '15 at 10:16

3 Answers3

107

BIOSes used to be written exclusively in assembly language, but the transition was made a long time ago to write the majority of the code in some higher level language, and leave written in assembly as few portions of it as possible, preferably only the bootstrapper, (the very first few hundreds of instructions that the CPU jumps to after a start / reset,) and whatever routines deal with specific quirks of the underlying architecture.

BIOSes were already being written primarily in C as early as the early nineties. (I wrote a BIOS in 90% C, 10% assembly in the early nineties.)

What has also helped greatly in this direction is:

  • C libraries that target a specific architecture and include functions for dealing with peculiarities of that architecture, for example, functions for reading/writing bytes to/from I/O ports of the x86 architecture. Microsoft C has always offered library functions for that kind of stuff.

  • C compilers that not only target a specific CPU architecture but even offer extensions to the C language that you can use in order to write code which makes use of special CPU features. For example, the x86 architecture supports things known as interrupts, which invoke routines known as interrupt handlers, and it requires them to have special entry/exit instruction sequences. From the very early days, Microsoft C supported special keywords that you could use to mark a function as an interrupt handler, so it could be invoked directly by a CPU interrupt, so you did not have to write any assembly for it.

Nowadays I would assume that most of the BIOS is written in C++, if not in any higher level language.

The vast majority of the code that makes up a BIOS is specific to the underlying hardware, so it does not really need to be portable: it is guaranteed that it will always run on the same type of CPU. The CPU may evolve, but as long as it maintains backwards compatibility with previous versions, it can still run the BIOS unmodified. Plus, you can always recompile the parts of the BIOS written in C to run natively on any new CPU that comes up, if the need arises.

The reason why we write BIOSes in languages of a higher level than assembly is because it is easier to write them this way, not because they really need to be portable.

Mike Nakis
  • 32,003
  • 7
  • 76
  • 111
  • For sure it is written is some assembly, but which? Which instruction set? It's not the x86 specific-set right? – Reflection Sep 30 '15 at 12:43
  • 1
    @Reflection assembly is (by definition) architecture specific. Also, which assembly you use depends on which architecture you target. If the architecture has many steppings, you usually select the most restrictive instruction subset that allows you to target the whole range, like i386 for the x86 family. – Stefano Sanfilippo Sep 30 '15 at 12:47
  • 1
    What @StefanoSanfilippo said. When we say "Assembly" we imply "Assembly for the CPU that we are talking about." So, if it is a x86 architecture, then of course we mean "x86 Assembly". – Mike Nakis Sep 30 '15 at 12:48
  • So, are you saying that a typical motherboard is tight to a specific CPU architecture? – Reflection Sep 30 '15 at 12:49
  • 7
    Yes. Sometimes you may even have a motherboard bound not only to a specific CPU architecture, but even to a specific CPU vendor. Nowadays you can buy an x86 motherboard which is only compatible with Intel x86 CPUs, or an x86 motherboard which is only compatible with AMD x86 CPUs. The BIOS in these motherboards will be identical to a large degree, because in both cases the CPU understands the x86 instruction set, and most of the peripherals are identical, but some peripherals have differences, that the BIOS must account for. – Mike Nakis Sep 30 '15 at 12:52
  • 2
    But of course if it is ***not*** an x86 CPU, then the entire motherboard around it is likely to be very different, so it is probably going to have an entirely different BIOS. – Mike Nakis Sep 30 '15 at 12:54
  • 4
    @Reflection take a close look at what a motherboard physically looks like. The CPU socket will have a certain pin arrangement, which is specific to the family of CPUs it accepts. You physically cannot connect say an Intel P4 to an AMD Opteron motherboard – Caleth Sep 30 '15 at 13:45
  • 14
    The term "BIOS" refers to the "Basic Input/Output System" of a PC, so, having a BIOS implies an x86 CPU. IA64 systems have an EFI instead of a BIOS, PowerPC systems may have an Open Firmware system or a proprietary one, Sparc systems also have OFW (or rather OpenBoot), the OLPC X0 is an x86-based system that uses OFW. Even PCs don't use BIOS anymore, they have switched to (U)EFI. OB/OFW is interesting, because it is designed to not only be portable but cross-platform. OFW drivers will work on *any* OFW system, they are "Write Once Run Anywhere", regardless of CPU ISA. – Jörg W Mittag Sep 30 '15 at 14:05
  • 14
    "Nowadays I would assume that most of the BIOS is written in C++" I wouldn't necessarily assume that, It might be true but I work in that industry and certainly many boot loaders are written in plain C. The people who write that kind of stuff are often the "Old Guard" and tend not to fully trust C++ still. – Sam Sep 30 '15 at 15:52
  • 3
    There is a lot of good content in this answer coupled with a lot of unsupported assumptions. It would be better without the assumptions. –  Sep 30 '15 at 18:09
  • 3
    @TomDworzanski okay, I don't claim infallibility, but I also don't claim clairvoyance, so I cannot tell which parts of my answer you consider as unsupported assumptions. So, please tell me what the unsupported assumptions are, and if I agree, I won't hesitate to remove them. – Mike Nakis Sep 30 '15 at 19:15
  • 1
    @MikeNakis What bothers me after reading this is the impression that something other than assembly and/or C are being used to build BIOSs. The ambiguity in your first paragraph as well as the statement "Nowadays I would assume that most of the BIOS is written in C++, if not in any higher level language." really give me the impression that a wide variety of languages can and are being used for this task. I have a hard time with C++ is being used, let alone something higher level than that. I think your personal insights are wonderful, I would just like to see examples of BIOSs not in assem/C. –  Sep 30 '15 at 19:35
  • @TomDworzanski I believe that my choice of words shows that the part about the use of languages of a higher level than C is not a statement, nor an assumption, but simply a postulation. It would be difficult to discuss the merits of this postulation without falling into one of those endless "which is better, C or C++" arguments. It would be nice if a programmer who has current knowledge of BIOS development could enlighten us on this detail. Let's sleep on it a bit more, and I am still open to the possibility of removing those postulations if I receive any more feedback in this direction. – Mike Nakis Sep 30 '15 at 20:17
  • 2
    @TomDworzanski I hope you understand that if I were to say that BIOSes are written in nothing but C and Assembly, without leaving open the possibility that some BIOSes may be written in higher level languages, that would be more precarious as a statement, and more likely to be proven wrong. – Mike Nakis Sep 30 '15 at 20:20
  • 6
    @TomDworzanski: While technically not BIOS (which refers exclusively to the old 1981 PC-stuff), many implementations of IEEE-1275 Open Firmware (which is used for a similar role as the BIOS on Sparc, the PowerPC Common Hardware Reference Platform (e.g. PowerMac, PowerBook), the 100$ laptop OLPC X0-1) are written partly in languages other than assembly/C. [OpenBoot](http://tracker.coreboot.org/trac/openboot/browser/trunk), [Open Firmware](http://tracker.coreboot.org/trac/openfirmware/browser), [OpenBIOS](http://tracker.coreboot.org/trac/openbios/browser/trunk/openbios-devel) all contain … – Jörg W Mittag Sep 30 '15 at 20:22
  • 4
    … significant amounts of Forth code, and [Smart Firmware](http://tracker.coreboot.org/trac/smartfirmware/browser) contains some C++ code and some Wacco code. – Jörg W Mittag Sep 30 '15 at 20:22
  • 3
    On my latest computer (Z97 chipset with UEFI BIOS) the BIOS settings available by pressing "Del" during boot have a spiffy, feature-complete, raster graphics mouse-driven environment, with dialogs containing complex GUI controls such as drop-down lists, listboxes with checkable entries, tabbed dialogs, etc. It even supports different skins. All this means one thing for sure: **Object Oriented Programming.** It is certainly possible to do OOP using nothing but C, but it would make the life of BIOS developers unbelievably easier if they just used an OOP language instead. – Mike Nakis Sep 30 '15 at 20:38
  • @MikeNakis Yes, I understand it's important to leave the possibility open. I think I have successfully communicated my point and I appreciate your consideration. –  Sep 30 '15 at 21:00
  • @JörgWMittag Hi, can I ask one more question? I would love to ask the same question about the language for the subject of EFIs, UEFIs, Open Firmware, OpenBoot. Are they also tightly written for a specific CPU? – Reflection Sep 30 '15 at 22:43
  • This question was cross-posted. The [accepted answer](http://reverseengineering.stackexchange.com/a/10999) states "It's written in a language that can be compiled to machine code that can be executed by the processor (the CPU). Typically, it's a combination of C and assembly language." If that is true, we can eliminate PerlPythonRubyPHPJavaC#JavascriptSwift and anything else that does not compile to machine code. –  Sep 30 '15 at 23:24
  • 2
    @TomDworzanski: There is no such thing as a language that does not compile to machine code. First off: every language is *already* machine code for its own abstract machine, the abstract machine defined by the language. Ruby is machine code for the Ruby abstract machine, Python is machine code for the Python abstract machine and so on. Secondly, compilation to machine code is a trait of the compiler, not the language. Thirdly, with the (possible) exception of Perl, *all* of the languages you listed have implementations that will eventually compile to machine code. E.g. V8, a pure JavaScript … – Jörg W Mittag Sep 30 '15 at 23:32
  • 1
    … compiler that *always* compiles to native machine code because it doesn't even *have* an interpreter, Rubinius, a Ruby implementation that will eventually compile hotspots to native machine code, PyPy, a Python implementation that will eventually compile hotspots to native machine code, Quercus and P8, two PHP implementations that will eventually compile hotspots to JVM byte code, which (depending on the particular JVM used) will eventually get (at least partly) compiled to native machine code, Microsoft Visual C#, a C# implementation that compiles to CIL bytecode, which (depending on the … – Jörg W Mittag Sep 30 '15 at 23:37
  • 1
    … particular CLI VES used) will eventually get compiled to native machine code, GCJ, a Java implementation that compiles to native machine code, and last but not least, the only currently existing implementation of Swift, which always compiles to native machine code. – Jörg W Mittag Sep 30 '15 at 23:38
  • 1
    @Reflection: I linked to the repositories for 4 different Open Firmware implementations, why don't you take a look for yourself? – Jörg W Mittag Sep 30 '15 at 23:39
  • @Reflection small parts tend to be tightly bound to a specific CPU, most parts are tightly bound to a specific motherboard and associated peripherals, and some parts will always be general purpose code. Most parts are written in languages which are portable, but these languages are not used because they are portable, they are used because they are ***far*** easier to develop and maintain than Assembly. – Mike Nakis Oct 01 '15 at 00:04
  • @Reflection: The language doesn't matter. They're all binary executable programs. Think of it this way - you can write English in ASCII, Unicode, Roman/Latin alphabet (what you write using pen on paper), Morse code, flag semaphore or telegraph code. Each of those writing systems are a different "language" (in syntax). But the message they write is still English. – slebetman Oct 01 '15 at 02:10
  • 1
    @JörgWMittag "Machine language" is specifically [defined](https://en.wikipedia.org/wiki/Machine_code) as "a set of instructions executed directly by a computer's central processing unit (CPU)." You're idea that "every language is already machine code for its own abstract machine" while poetic is technically wrong. The reality is the interpreters for these languages are not available to the BIOS developer (and probably will never be) and so they cannot be used for BIOS. The other reality is interpreted languages lack facilities to directly interact with hardware (by design). –  Oct 01 '15 at 04:53
  • I feel like this discussion has reached the level of my-language-is-better-than-your-language which I find completely fruitless. It's fun to think we can stretch the limits our our favorite high level language to do things it has never done (and there are no technical reason why one would never be able to script BIOS in Ruby), but if we want to be honest and focus on reality, BIOS is and will always (for the foreseeable future) be written in relatively low level languages or at least those that can directly compile comparable, non-dependent, lowest-level, hardware-machine code in advance. –  Oct 01 '15 at 05:05
  • BIOS is a niche, proprietary project almost always created out of necessity for the purpose of complementing a hardware product which took significant monetary capital to produce. Modern BIOS implementations like the one @MikeNakis described are saturated with features that sometimes push past the barrier of what BIOS should be. If we want to dream about BIOS in Ruby, we might first consider the economics of such an idea. This is low-level stuff with limited purpose. If someone wants to push the limits without reason, that's great -- I doubt the hardware maker will see it as worthwhile. –  Oct 01 '15 at 05:17
  • 3
    I like how some people downvoted the answer of someone *who has actually written a BIOS*. I guess the downvoters wrote "better" BIOSes? ;) – Andres F. Oct 01 '15 at 14:20
  • @AndresF. I down-voted this answer because of the factually incorrect statement about most BIOSs being written in C++ and other higher level languages. I down-voted after discussing my concerns with the author and after posting my own answer which I believe proves the statement wrong. The author of this answer has awesome insights, and I fully admit he would be better at writing a BIOS than I would. However, that does not mean, as he states, again eloquently, that he is infallible. If not for the postulations, I would up-vote this, and will if they are removed. It's not a big deal though :) –  Oct 01 '15 at 15:32
  • @TomDworzanski yes, it is not a big deal. I am not offended. Besides, I have learned to expect it here. I have an answer somewhere with a score of -5 or something. I don't care. C-:= – Mike Nakis Oct 01 '15 at 15:35
  • 1
    @TomDworzanski also, I will not downvote your answer, despite the fact that I do not agree with it. You are making a statement about the nonexistence of something, ("there exist no BIOSes that are written in anything other than C and Assembly",) which is essentially [Russell's Teapot (wikipedia)](https://en.wikipedia.org/wiki/Russell's_teapot) all all over again. – Mike Nakis Oct 01 '15 at 15:42
  • @MikeNakis With all due respect I do not say that at all. It's certainly not a quote of mine and never was. What I said was "most BIOS is written using Assembly, C, or a combination of the two." I then later say, "I'm sure over the last few decades, several languages have been used," admitting fully that other BIOSs must exist. It would be ridiculous to think otherwise. It is honestly my hope that people advance all technology, including BIOS. Maximizing what hardware can do is important. However, I prefer answers be strictly objective and verifiable. –  Oct 01 '15 at 15:51
  • 1
    @TomDworzanski It strikes me that people should refrain from downvoting a valuable answer, written by someone who has practical experience in the matter, just because they disagree with a minor aspect. The tooltip for the downvote button says "This answer is not useful"; I think it's useful and if it has any problems, they are minor. But that's just me. – Andres F. Oct 01 '15 at 15:55
  • @MikeNakis And to be clear, I down-voted because I believe your postulation about BIOSs being written in C++ and other higher level languages to be completely unsubstantiated. There is no opinion involved in my approach: `if(it's true) {say it} else {say nothing}`. –  Oct 01 '15 at 15:57
  • @AndresF. I agree that the down-vote standard should be high. But is the statement minor? Someone asking the question the OP asked may not be an experienced developer. He might be a gamer looking to write his own BIOS to further overclock a CPU. Giving him the idea that you can just learn any-old higher level language is detrimental to his interests. What will happen when he finishes the Intro to Python book and comes back to ask how to program a BIOS with it? Based on the original question, the point is very significant, in my opinion. –  Oct 01 '15 at 16:01
  • Again, this is not a big deal. I have more than made my point. There is nothing wrong with disagreeing. I have the utmost respect for the author of the answer and I am glad this answer is useful for many, parts of it certainly were to me. I'm also glad I could give my answer which I hope adds richness to the entire page. –  Oct 01 '15 at 16:05
  • @JörgWMittag - "The term "BIOS" refers to the "Basic Input/Output System" of a PC, so, having a BIOS implies an x86 CPU" - historically, of course, the term BIOS has also been used for other systems, e.g. CP/M, so the CPU could also be, for example, an Intel 8080 or one of its clones. – Jules Aug 13 '18 at 16:33
12

While in theory one can write BIOS in any language, the modern reality is most BIOS is written using Assembly, C, or a combination of the two.

BIOS must be written in a language that can compile to machine code, that is understood by the physical hardware-machine. This eliminates the directly or intermediate-ly interpreted languages (Perl, Python, PHP, Ruby, Java, C#, JavaScript, etc) as being appropriate for writing BIOS. (Though, in theory, one could implement one of these languages to either compile directly to static machine code or one could somehow embed the interpreter in BIOS. There is, for-example, the abandonware GCJ project for Java.)

Most OEMs implement a BIOS by extending proprietary, generic BIOS implementations by companies like American Megatrends and Phoenix Techologies. (You've probably seen one of those companies displayed on the first boot screen of a computer before.) The source code for these implementations is not publicly available, but some of it has been leaked. I do not want to link to this directly to the C and assembly source code, but there are places on the Internet where this source code is discussed for those who care to peek.

Some hardware manufacturers, like those targeting the high-performance and gaming markets, saturate their BIOS implementations with customization features, statistics, and attractive user interfaces designed for their exact implementations. Many of these features go beyond what is offered in the generic products produced by American Megatrends and others. Unfortunately, these companies often see the release of their source code as a security risk, so little is known about these high-end implementations because little is shared about them. One could of course find ways to access and de-compile such BIOS implementations but doing so may be difficult and possibly illegal.

Going back to the original question, because of the need to produce native machine code, a BIOS would have to be implemented in a programming language supported by a native machine code compiler. While there are many such languages and while I'm sure over the last few decades, several languages have been used in experimentation, every open BIOS implementation I have been able to find specifically relies on a combination of C and/or assembly. The open-sourced BIOS implementations I looked at to form this conclusion include OpenBIOS, tinyBIOS, coreboot, Intel BIOS, and Libreboot. I also looked at some very old BIOS implementations that are not relevant today but also followed the C and/or assembly rule.

I think it's also relevant to look at other software built to interact directly with hardware. We know, for example, that the Linux Kernel, the OS X kernel, and the Windows kernel are largely C with some assembly and some higher level languages for specific tasks. We also know that hardware drivers on Linux and hardware drivers on Windows are written largely in C.

Getting back to BIOS, I think it's also important to consider the economics of the programming language chosen. BIOS is generally written as a necessity to complement hardware sales. Modern BIOS systems are known to be largely written in C and/or assembly. A move to some other tool would add significant costs to what are generally considered to be commodity products which could very adversely affect sales. Without getting into Economics 101, I can assure you that it's probably not worth it to an OEM to deviate from tried-and-true tools that have been proven over decades.

Of course there are and will be hobbyist projects to write BIOS as well. These too, thus far, seem to be choosing C and/or assembly. Perhaps one day other technologies will be used. But today, the choice of is well-defined.

Rich Smith
  • 241
  • 1
  • 4
  • 4
    It is a little bit of nit-picking but C# and Java are not interpreted. They compile to byte-code. It is the byte-code that is then handled by an interpreter. Doesn't change the logic of the first paragraph. – Tonny Oct 01 '15 at 09:33
  • 1
    @Tonny That's correct. I added "directly or intermediate-ly interpreted" to be a little more clear. –  Oct 01 '15 at 09:35
  • @Tonny normally a jitter rather than an interpreter, which is an important distinction because it's possible to pre-jit it all to native as long as certain dynamic techniques aren't used. As such it would be just about theoretically possible to write a BIOS in .NET languages or Java, if one did both that and made sure all runtime-support needed was available. I imagine the efforts of doing that would more than dwarf any convenience found though. – Jon Hanna Oct 01 '15 at 12:19
  • 1
    @Tonny Actually C# compiles to native code https://msdn.microsoft.com/en-us/vstudio/dotnetnative.aspx so it's weird to see it in the list of weak/dynamic languages. – Den Oct 06 '15 at 14:23
  • @Den C# is ***not typically*** compiled to native code. This .Net Native product to which you link has not yet been officially released. From what I've read, it will compile the application code and the required framework code into an executable. According to the FAQ, this will be targeted at Windows Store apps initially, so it may take some time for this to be supported more widely. All that being said, it does seem like Microsoft may move away from the virtual machine model some time in the future if all goes well. –  Oct 06 '15 at 20:15
4

The actual BIOS for a computer would be written in some language (probably C or assembly) that is compiled to architecture dependent binary code; this code can't run on any other architecture (and arguably doesn't really need to, as it is already very specific to the machine with which it is shipped).

But are you possibly thinking about Option ROMs (which are sometimes called BIOSes, as in "Video BIOS" for a GPU option ROM)?

For actual, legacy BIOS compatible option ROMs, they would probably be ISA dependent executable code (again generated by any language that can be compiled to target the desired architecture); PCI also allows including code for multiple ISAs and allows the host to select the appropriate binary image during the boot process.

For UEFI compatible option ROMs, there is also an architecture-independent byte code format that can be run on different architectures, but ISA-dependent code can also still be used.

lxgr
  • 149
  • 2