• Please review our updated Terms and Rules here

"Fun with BIOS" Programming Thread

cr1901

Veteran Member
Joined
Dec 28, 2011
Messages
817
Location
NJ
For those of you who reading my MASM thread, I pasted some code which showed that I was starting to/want to write my own PC and XT-class BIOS (mostly in C, because it'll be easier for me to keep the code modular should I decide to add clones using different chipsets- the NEAT chipset comes to mind). I know sergey's done one already for his project, and I think it would be a better exercise for me to get acquainted with the PC's hardware... I can go back to DOS internals later (or look at that topic when I get sick of writing this and need a break :p).

I would like to do this without blatantly copying the routines from IBM's listings... for the BIOS interrupt services, that's trivial now that Ralf Brown's Interrupt List exists, but for the actual boot process that seems like contradictory requirements!

I know some code in any BIOS will more-or-less be the same. I imagine that for most- if not all clones- the PIT, DMA controller, PPI, and PIC, and CRT controller all need to have their registers to the same values as IBM's. I also imagine that other tests such as RS-232, LPT, floppy seek test and the 8088 test can be programmed differently.

Any advice on how to go about not just blatantly copying code? Are there any documents that explain the BIOS boot process in detail without using IBM's code? I have a copy of Annabook's BIOSkit, so that is certainly a start, but a lot of the code is not actually explained, and the Makefile for that project is rather impractical to build on a modern machine. http://www.minuszerodegrees.net/5150/misc/5150_post_and_initialisation.htm discusses a high level look at the 5150 3rd revision BIOS (according to that page, mine must be broken or something, because it only moves the floppy heads back to the first track AFTER the 'Everything OK' beep :lol:). It'd be cool if Compaq, what was once Columbia Data Products, or Phoenix still had their Chinese Wall notes!

Currently, my BIOS beeps the PC speaker, then halts... it also has the FONT placed at the correct location (which seems to be constant regardless of the BIOS for some reason. Any particular reason why?)

Thanks in advance for any feedback!
 
The Phoenix BIOS guides very meticulously identify what memory cells are used by what routines, where the entry point for each BIOS routine is assumed to be--if you look at even the 5170 BIOS, you'll see that they work to keep the 5150/5160 corresponding routines in the same place in memory, even if it means a jump right after the entry point.
 
The Phoenix BIOS guides very meticulously identify what memory cells are used by what routines, where the entry point for each BIOS routine is assumed to be--if you look at even the 5170 BIOS, you'll see that they work to keep the 5150/5160 corresponding routines in the same place in memory, even if it means a jump right after the entry point.

Do you happen to know where I could get one of these guides?
According to an old USENET post (https://groups.google.com/forum/#!topic/comp.os.minix/P2CEzwMXCqA), one of these guides is called "System BIOS for IBM PC/XT/AT Computers and Compatibles The Complete Guide to ROM-Based Software"

Surprisingly, it appears to be available on Amazon, but not as a PDF... yet!
http://www.amazon.com/System-BIOS-IBM-Computers-Compatibles/dp/B000ND8DKS

Also, if that is the case the BIOS routines are generally in the same location, then how did IBM not sue the asses off of every clone manufacturer (I imagine they could've argued the clone BIOSes were not sufficiently different, even with Chinese Wall approach)?
 
Last edited:
They are online (or were) . Perhaps the owner of the site hosting them will PM you with the information. I don't feel comfortable disclosing it publicly.

Phoenix used a double-blind approach. One group of people looked at the IBM BIOS listings and took copious notes without actually copying code. A second group, completely isolated from the first, took those notes and wrote the Phoenix BIOS without having access to the IBM BIOS listing. Since they weren't directly copying the code, there was no infringement of copyright. I believe that ERSO took the same approach.

Sort of "one guy read a book and told a second guy about it, whereupon the second guy wrote his version of the book"

Also, for those interested, there's an online copy of "The A to Z of C", which does include an (assembly) BIOS listing here
 
Last edited:
Well I won't count on it, but maybe said site owner will PM me... I already have an idea who it is.

For those wondering:
1. The BIOS in "The A to Z of C" is the 'Generic XT BIOS' that's been floating around the net for 25 years... I know of at least 2 versions- the original, and one which was updated in 2008 to work on an original IBM 5150 (for some reason the original wouldn't work on a PC). I did a binary compare against other BIOSes on minuszerodegrees and it appears that it is an ERSO derivative, with the 'distinction' of having video routines which were improperly coded for V20 motherboards.

2. Based on another multiple-binary compare, all the ERSO bioses appear to come from one original set of source code. IBM attempted to sue ERSO (http://www.taiwantoday.tw/ct.asp?xItem=119839&CtNode=103), so perhaps keeping the BIOS services in the same location may have been infringing.

I doubt I could find someone else willing to take the copious notes for me XD... I'm not going to learn simply by copying code. However, I may cheat on the video routines because I don't want to destroy either of my TTL monitors because I made some stupid coding mistake.
 
Last edited:
... because it only moves the floppy heads back to the first track AFTER the 'Everything OK' beep :lol:).
That's right. The BIOS code indicates that the 601 test does a 'recalibrate' (move heads to track 1) followed by a move to track 34. The drive's spindle motor is then turned off. So then, the heads will remain at track 34 until the next action that moves the drive's heads. That action is the bootstrap routine, which happens after the single beep.
 
I have a copy of Annabook's BIOSkit, so that is certainly a start, but a lot of the code is not actually explained, and the Makefile for that project is rather impractical to build on a modern machine.

I'm wondering if you have the AT version or the PC/XT version of Annabook's BIOSkit? The PC/XT version has been impossible for me to find anywhere! :)

The Anonymous Bios is what is used for the PC-Retro, after the problem you mention was solved by Jon. I really like that BIOS for the quick boot, and the distribution package he created lets users compile the BIOS with selectable options. Really nice. (He even included a utility that automatically makes the ROM images.) Here is a link for anyone that wants to try it (Go to Downloads: Other): http://www.phatcode.net

Michael
 
I'm wondering if you have the AT version or the PC/XT version of Annabook's BIOSkit? The PC/XT version has been impossible for me to find anywhere! :)

The Anonymous Bios is what is used for the PC-Retro, after the problem you mention was solved by Jon. I really like that BIOS for the quick boot, and the distribution package he created lets users compile the BIOS with selectable options. Really nice. (He even included a utility that automatically makes the ROM images.) Here is a link for anyone that wants to try it (Go to Downloads: Other): http://www.phatcode.net

Michael

Ahhh, so you're one of the designers of this: http://www.mtmscientific.com/pc-retro.html

I am seriously considering buying one of these kits.
http://www.mtmscientific.com/pc-retro.html
 
2. Based on another multiple-binary compare, all the ERSO bioses appear to come from one original set of source code. IBM attempted to sue ERSO (http://www.taiwantoday.tw/ct.asp?xItem=119839&CtNode=103), so perhaps keeping the BIOS services in the same location may have been infringing.

I've compared 5 BIOSes side by side in a hex editor, examining their IVTs. They all begin at 0xf000:0xff23, but have some differences.

For my initial comparison, I compared an IBM PC 5150 BIOS (82) to my EXCEL Turbo BIOS that died last month. The IVT in the ERSO BIOS is identical to an XT-BIOS and very similar to the original PC BIOS... the only difference being how the dummy ISR is entered. On the IBM PC, the PC-XT dummy ISR is present at 0xf000:0xff23, but doesn't appear to be used, save for the last IRET bat 0xf000:0xff53 being directly jumped to from the IVT when no routine is to be executed. The PC BIOS instead jumps to 0xf000:0xe6dd. Hmmm...

Example, Interrupt 18 on an IBM 5150 and 5160 is redirected to 0x0000, and the BIOS listings imply that the segment (0xf600) will be filled in at BOOT.

The EXCEL ERSO BIOS jumps to the dummy interrupt vector at 0xf000:0xff23.

The Phoenix BIOS 2.51 from MikeS jumps to 0xf000:0xe71a, which does something else I suppose... perhaps some 'goodies'? Identical to another BIOS from an ALCO motherboard hosted on minuszerodegrees

The DTK ERSO BIOS v 2.42, which oddly enough has a date of 1/01/81, NONE of the IVT entries are the same!! The jump at 0xffff:0000 still goes to the same location (0xf000:0xea5b), and the IVT is in the same place. This might warrant me getting my hands on some more BIOSes lol.

The Generic XT BIOS floating around the internet has an IVT identical to the XT.

Conclusions: What that Phoenix Technologies book refer to as BIOS routines and data structures being at the same address seems to be convention, but need not be followed exactly.


Chuck(G)- Since you seem to be the resident-ERSO expert, was ERSO considered an 100% compatible BIOS, meaning it could run Lotus 1-2-3 and Flight Simulator XD?

I just spent 2 hours comparing binary code to one another for the sake of answering a question that 0.0001% of the world cares about... I should question my mental health now. Putting my self-deprecation aside, the goal of me doing this was to get some insight to how much IBM's absolute offsets (or segment:eek:ffset pairs) into the BIOS routines affected how the clones created their own BIOSes. By doing an absolute binary compare, not much code actually matches up... this may a bit misleading to how related all the BIOSes actually are in their various implementations. I tend to be interested in multiple implementations of the same concept, which is why the various BIOS are intriguing to me.
 
The ERSO BIOS/BIOSes (individual vendors did tweak the thing a bit) were considered compatible BIOSes. They do run Flight Simulator; I haven't tried 1-2-3 in maybe 25 or more years, so I'd have to pull it out and see.

I probably have a few BIOSes for the XT that aren't on your list yet. For example, how about the leading Edge Model D BIOS? Or the AT&T 6300?
 
The ERSO BIOS/BIOSes (individual vendors did tweak the thing a bit) were considered compatible BIOSes. They do run Flight Simulator; I haven't tried 1-2-3 in maybe 25 or more years, so I'd have to pull it out and see.

I probably have a few BIOSes for the XT that aren't on your list yet. For example, how about the leading Edge Model D BIOS? Or the AT&T 6300?

Sure, send me a PM if you're able to extract them.
 
I would recommend looking at the Zet soft x86 project. They have an open-source x86 real-mode BIOS mostly written in OpenWatcom C already.

http://zet.aluzina.org/index.php/Zet_processor

Also if you want to open your project up, I have a very complete full featured black-box implementation of printf I can donate. The only draw back is it's fully unrolled so the code size is quite large (~2k). But it does support 8, 16, and 32 bit values with c, s, P, p, X, x, u, d specifiers with +, -, 0, *, and l (32 bit ints, far pointers) modifiers.
 
Last edited:
I would recommend looking at the Zet soft x86 project. They have an open-source x86 real-mode BIOS mostly written in OpenWatcom C already.

http://zet.aluzina.org/index.php/Zet_processor

Also if you want to open your project up, I have a very complete full featured black-box implementation of printf I can donate. The only draw back is it's fully unrolled so the code size is quite large (~2k). But it does support 8, 16, and 32 bit values with c, s, P, p, X, x, u, d specifiers with +, -, 0, *, and l (32 bit ints, far pointers) modifiers.

Well, most often if an implementation already exists, I won't bother... but in this case, I still like the notion of multiple implementations!

I don't have a git repository for this project yet, but I'd be happy to incorporate it in, giving you credit obviously... I could use it as part of a debugging ROM perhaps. It was my intent from the beginning to make it Open Source... just don't see the point of uploading a project with unacceptable functionality (BIOS still only beeps the PC speaker before halting).

Since the Monochrome Display Adapter uses static RAM, I want to initialize that first and then attempt (and likely fail) to set up DMA RAM Refresh properly... I know each row needs to refreshed every 4ms, but this leads to a few questions:

1. According to a book I have on the IBM PC, every DRAM chip on the board/memory expansion cards is accessed during each DMA refresh, but only a single row. Considering that the DMA controller can only access 65,536 bytes in one transfer, and there exists a decoder for lines 17-20 accessed using a specific I/O port, how does the address bus know to permit the DMA controller to access every single DRAM chip and the corresponding chip select simultaneously?

2. What is the destination of the dummy DMA read?
 
1. According to a book I have on the IBM PC, every DRAM chip on the board/memory expansion cards is accessed during each DMA refresh, but only a single row. Considering that the DMA controller can only access 65,536 bytes in one transfer, and there exists a decoder for lines 17-20 accessed using a specific I/O port, how does the address bus know to permit the DMA controller to access every single DRAM chip and the corresponding chip select simultaneously?

The way the RAM is organized, when an address is put on the address bus, the "row" part of the address is fed to all the RAM chips, even those in banks other than the one you are accessing. So accessing addresses 0x00000-0x0FFFF suffices to refresh all RAM. In fact, because refreshing an address also refreshes all the other addresses in the same row on each DRAM chip, addresses 0x00000-0x0007F (for 4116), 0x00000-0x000FF (for 4116 and 4164) and 0x00000-0x001FF (for 4116, 4164 and 41256) would work just as well.

2. What is the destination of the dummy DMA read?

There is no destination, and none is required. The value read from 0x00000-0x0FFFF is just placed on the bus, and every device just ignores it - it's just the reading from RAM that's required, the value doesn't actually have to go anywhere.

What does all this mean for a BIOS author? It just means that you need to set PIT channel 1 to binary mode 2 with a count of 18 cycles, set DMA channel 0 to auto-init, read, single, increment with an address of 0 and a count of 0xFFFF and everything should just work.

I've written more about DRAM refresh on 5150/5160 machines on my blog: http://www.reenigne.org/blog/how-to-get-away-with-disabling-dram-refresh/ .
 
Later versions of the Amstrad PC1512 / 1640 BIOS make certain interrupt handlers (such as INT 10h and INT 13h) start with a far jump to themselves. I suspect the reason is that since the PC1512 BIOS fits in 16k, the handler assumes a CS of FC00h, but ill-behaved programs were making far calls to it with a CS of F000h.
 
To be perfectly honest, I'm not sure why so many offsets were even standardized apart from the way the early BIOS manufacturers took their notes when reverse-engineering it. I've compared 9 BIOSes by doing a one-vs-one binary compare of each BIOS, and summing up the total number of comparisons that matched on a byte-by-byte basis.

The following is a list of BIOSes that I've compared and their origin:
EXCEL BIOS 3.10 (ERSO)
X GOLDEN Turbo BIOS 3.10 (ERSO- very close to EXCEL)
Generic XT BIOS (ERSO)
DTK ERSO BIOS (ERSO- drastically different from the remaining ERSO BIOSes)
IBM PC 5150 BIOS (IBM)
Phoenix BIOS 2.51 (Phoenix)
Alco 8Mhz BIOS (Phoenix)
AWARD BIOS 2.05 (Award)
Samsung Samtron BIOS (Award)

Generic XT BIOS was modified twice, and can be found on phatcode.net...
The remaining are on minuszerodegrees.

Would like to try BIOSes from: Columbia Data Products, Juko Electronics, Compaq, Leading Edge, and AT&T. Please drop me a PM if you have any such ROMs to offer (or any BIOSes in general).
EDIT- Found a Juko BIOS from here: http://www.vintage-computer.com/vcforum/archive/index.php/t-27771.html?


Some initial notes:
314 bytes locations match in EVERY single BIOS. These include the BIOS initial jump and the Serial port Parameters Table.
A further 358 bytes match in all but one BIOS. The DTK_ERSO, AWARD_BIOS, and samtron_bios (which is an AWARD derivative) hosted on minuszerodegrees contain ALL the differences. Portions of the IVT table stored in ROM match in all but DTK_ERSO, but few of the IVTs are identical. I suppose all that matters is the offset.

The DTK ERSO BIOS is an odd ROM. It is much different from the remaining ROMs in that the IVT doesn't match at all, and the BIOS date is invalid (Jan 1, 1981- predates the IBM PC!). My guess is that it is an ERSO ROM from after IBM sued, but that was in 84, and my EXCEL board was from 85. Hmmm...

I'll update this in a bit... but I'm pretty sick of coding in MATLAB right now XD.

Also, I'd like to add... if I can't coerce my C Compiler to add code AROUND the segments which must be positioned absolutely, then it's gonna be extremely difficult to write an appreciable amount of the code in C.

A skimthrough of AnnaBook's AUTOBIOS suggests that the only thing that must be at a specific offset is the reset vector (because of the 8088's behavior)... all other code can at any desired offset within the BIOS segment. Additionally, certain offsets that the Phoenix BIOS manuals suggest are reserved don't even point to the relevant routines reading the IBM BIOS listings.
 
Last edited:
I made plenty of edits to my previous post last night lol... from my understanding- going through a number of BIOSes, the offsets that Phoenix listed as being reserved by IBM are in general just conventions for software writers. I don't know of any software that attempts to call BIOS functions by pointing to a code offset within the BIOS, and even IBM says that 'violates the code philosophy of the BIOS'.

The only three things that remain constant between all the BIOSes I tested are the dummy interrupt return location, the jump to the entry point of POST, and the Baud Rate table. That being said, it's a bit early for me to worry about this for now... I just want to make something that works first of all XD.
 
A thought occurred to me--have to checked to see if the first version of 5150 BASIC-in-ROM makes any unusual BIOS calls? That could be the source of the conventions.

Speaking of conventions, you seem to be just about the only user here of "XD". My urban dictionary defines this as:

Originally used by anime-loving internet addicts, this face can express happiness and laughter, but is also frequently used when being flirtatious.

All I have to say, is "watch yourself, mister!). :)
 
I see you selectively chose the fourth-highest rated definition of 'XD' :p:
http://www.urbandictionary.com/define.php?term=XD

While there is nothing wrong with anime in and of itself (until you reach weeaboo level: http://www.urbandictionary.com/define.php?term=Weaboo), and I've been known to watch it from time to time, I can't say I remember where I started using 'XD', other than for the longest time when I started using YouTube, I thought to pronounce it as 'ecks dee'.

I have no intention of stealing you from your spouse, Chuck. I've been happily single for the past year and a half. Too much drama, not enough time, and it's hard to find a woman interested in old IBM clones, as one friend bluntly puts it lol. Though I respect anyone who's in a relationship and wants to throw their lives awa- err, spend their rest of their lives together in miser- err, marriage!

I haven't checked BASIC yet, but that's a good idea. Currently, from reading the IBM BIOS listings, the only ISRs that are embedded into the POST routine are the NMI, the jump to int 0x13 hard disk services, and the hard disk parameter table (or is supposed to be, according to the Phoenix manual- it isn't in the 256k 5150 BIOS). The POST routine jumps to interrupt 0x19 about 0x550 bytes (hex... too l from the BIOS POST entry point at 0xf000:0xe05b. If that is the case, then the BIOS can still be done in C, taking care to position the interrupts and data structures absolutely.

I'm not having much luck finding the remaining NMI routines in the other BIOSes (I'm looking specifically for where the BIOS code accesses memory location 0x0008 and the data segment points to 0x0000, i.e. the IVT), and this would be immensely quicker if I wasn't looking at the raw machine code to decode the opcodes.
 
The way the RAM is organized, when an address is put on the address bus, the "row" part of the address is fed to all the RAM chips, even those in banks other than the one you are accessing. So accessing addresses 0x00000-0x0FFFF suffices to refresh all RAM. In fact, because refreshing an address also refreshes all the other addresses in the same row on each DRAM chip, addresses 0x00000-0x0007F (for 4116), 0x00000-0x000FF (for 4116 and 4164) and 0x00000-0x001FF (for 4116, 4164 and 41256) would work just as well.



There is no destination, and none is required. The value read from 0x00000-0x0FFFF is just placed on the bus, and every device just ignores it - it's just the reading from RAM that's required, the value doesn't actually have to go anywhere.

What does all this mean for a BIOS author? It just means that you need to set PIT channel 1 to binary mode 2 with a count of 18 cycles, set DMA channel 0 to auto-init, read, single, increment with an address of 0 and a count of 0xFFFF and everything should just work.

I've written more about DRAM refresh on 5150/5160 machines on my blog: http://www.reenigne.org/blog/how-to-get-away-with-disabling-dram-refresh/ .

I wanted to thank you for the advice and wonderful article. Any updates on your cycle accurate emulator? PCem doesn't appear to emulate DRAM Refresh properly, and although your post implies that MESS does, it's going to take me a day just to learn how to use that!
 
Back
Top