Option ROM / Expansion Card BIOS Information

       

       

Information Contained Herein:
        This information gives the basics of how to use an 8-bit expansion card with on-board option ROM for your use. The procedure for using a 16-bit expansion card with two ROMs is similar, but there is the added complication of merging the two ROMs into one file, rewriting the code, and then breaking the file into two parts (Even/Odd) again.
        This 5-step procedure is not too complicated. However, you must have access to an EPROM programmer in order to do this stuff. The software used with the programmer must be able to do a checksum on the loaded file, and it is good if it has a binary editor as well. DEBUG.EXE, which comes standard with DOS and Win, is used for making code changes. For Win95, you should be able to find DEBUG.EXE in the C:\WINDOWS\COMMAND directory.
        Note: DEBUG uses numbers in hexadecimal form!

Procedure:
1)        Remove the EPROM chip from the board. Read the chip using a programmer and its software. Save the buffer to disk as CARDROM.BIN. Also, note that the last two digits of the checksum are zeros. This is important. (Code and data are stored in the binary file as numbers. A checksum is the sum of all those numbers. If the last two digits of the checksum are zeros, then the file is considered to be valid.)
2)        Unless you like to take chances or want to read in the chip a second or third time, you should make a backup copy of your file in case you mess it up in the following steps.
3)        Use Debug to make the changes. First, use Debug to look the start of the data in the file – that is, do a data dump. Note that Debug starts the file at an address offset of 0100h. All numbers are in hexadecimal. Here's what I got.

C:\>debug cardrom.bin
-d
2B6F:0100 55 AA 10 EB 03 E9 2A 08-E9 7F 00 28 43 29 20 43 U.....*....(C) C
2B6F:0110 6F 70 79 72 69 67 68 74-20 31 39 38 34 20 57 65 opyright 1984 We
2B6F:0120 73 74 65 72 6E 20 44 69-67 69 74 61 6C 20 43 6F stern Digital Co
2B6F:0130 72 70 6F 72 61 74 69 6F-6E CF 02 25 02 08 2A FF rporation..%..*.
2B6F:0140 50 F6 19 04 64 02 04 65-02 65 02 0B 05 64 02 00 P...d..e.e...d..
2B6F:0150 00 00 00 00 64 02 02 80-00 80 00 0B 05 64 02 00 ....d........d..
2B6F:0160 00 00 00 00 64 02 04 65-02 80 00 0B 05 64 02 00 ....d..e.....d..
2B6F:0170 00 00 00 00 32 01 04 32-01 00 00 0B 05 32 01 00 ....2..2.....2..
-

Note the first two bytes, "55 AA." They tell the main BIOS that the expansion card has a startup routine that it also needs to run, and that the main BIOS needs to give control to the expansion card.
        The third byte ("10" in this case) tells the main BIOS the length of the address space that is taken by the expansion card. The value of the third byte is the number of 512-byte blocks of address space that the card takes up. Here, the amount is (10h) * (512 bytes) = 8 kilobytes. Also, a double-check can be made by noting that the chip itself is a 2764 EPROM. Thus, it is (64 kilobits) / (8 bits/byte) = 8 kilobtyes.
        The code starts with the fourth byte. Let's take a look at it using Debug.



-u 103
2B6F:0103 EB03
2B6F:0105 E92A08
2B6F:0108 E97F00
2B6F:010B 284329
2B6F:010E 20436F
2B6F:0111 7079
2B6F:0113 7269
2B6F:0115 67
2B6F:0116 68
2B6F:0117 7420
2B6F:0119 3139
2B6F:011B 3834
2B6F:011D 205765
2B6F:0120 7374
2B6F:0122 65
-

JMP
JMP
JMP
SUB
AND
JO
JB
DB
DB
JZ
XOR
CMP
AND
JNB
DB

0108
0932
018A
[BP+DI+29],AL
[BP+DI+6F],AL
018C
017E
67
68
0139
[BX+DI],DI
[SI],DH
[BX+65],DL
0196
65



        The first instruction says to jump to the instruction at address 0108h. Note that the opcode for this instruction is "EB03", shown in the second column. This shows that the instruction, "JMP 0108," actually performs a relative jump – that is, a jump is performed based upon the address of the current instruction rather than any certain absolute address. Relative jumps pose no difficulty in Debug, but absolute jumps must be analyzed with care. If a jump statement starts with "EA" then it is an absolute jump and the absolute address is given as the destination. Looking at this address in Debug will not yield the correct result except the case of a wild fluke.
        Well, the instruction at 0108h says to jump to the instruction at 018Ah. If you wish, enter "u 018a" in order to see the instructions starting there.
        Here's something to try in order to illustrate something important.



-u 0100
2B6F:0100 55
2B6F:0101 AA
2B6F:0102 10EB
2B6F:0104 03E9
2B6F:0106 2A08
2B6F:0108 E97F00
2B6F:010B 284329
2B6F:010E 20436F
2B6F:0111 7079
2B6F:0113 7269
2B6F:0115 67
2B6F:0116 68
2B6F:0117 7420
2B6F:0119 3139
2B6F:011B 3834
2B6F:011D 205765
-

PUSH
STOSB
ADC
ADD
SUB
JMP
SUB
AND
JO
JB
DB
DB
JZ
XOR
CMP
AND

BP

BL,CH
BP,CX
CL,[BX+SI]
018A
[BP+DI+29],AL
[BP+DI+6F],AL
018C
017E
67
68
0139
[BX+DI],DI
[SI],DH
[BX+65],DL


        Well, now, that doesn't look anything like the instructions we had before. In fact, unlike the previous listing, there is no instruction starting at 0103h in this listing. The reason is that no instructions start at 0100h, but we asked Debug to generate instructions starting there. It did its best. If there were instructions starting at 0100h, it would have given them to us. Instead, it gave us garbage since it tried to interpret data as code. Remember that there is a data byte at 0100h, not an instruction. In fact, the first three bytes are data (55 AA 10); that is why we have to look at code starting at 0103h, the fourth byte.
While we're at it, look at the original code listing which started at 0103h. Look at the code at 010Bh and following. Kind of strange-looking code. Well, if you look at the data dump that we did right at the beginning, you'll see the Western Digital copyright message starts right there at 010Bh. That's why the code looks so strange – it's not code at all.
The moral is that if it looks like you are getting a bunch of garbage code, then you may need to start disassembly at a different instruction (unless you are starting the disassembly at an address that was specifically given in a jump statement, etc.).
        Well, now what are we going to do with this stuff? Let's use Debug to make a change or two for our own personal edification. We can write our own assembly code starting at 0103h. Enter "a 103" in order to start writing your code. Type the first instruction and hit <ENTER>. The next address will automatically be given, and you can keep going until you are done. When you are finished, just hit <ENTER> without typing any code.

-a 103
2B70:0103 mov bx,0
2B70:0106 mov ax,0e0d
2B70:0109 int 10
2B70:010B mov ax,0e48
2B70:010E int 10
2B70:0110 mov ax,0e69
2B70:0113 int 10
2B70:0115 mov ax,0e21
2B70:0118 int 10
2B70:011A mov ax,0e0d
2B70:011D int 10
2B70:011F retf
2B70:0120
-

        In this case, the code will display a message on the screen. Since I am using a monochrome/text-only display, I set BX=0 before calling Int 10h. A carriage return/line feed is executed followed by "Hi!" and then another CR/LF. This is done by putting the appropriate ASCII codes in AL, putting "0e" in AH, and then calling Int 10h. You can do basically anything you want to do. You may want to clear the screen, send a control byte to an output port for a computer-controlled project, or whatever. If you can do it in assembly language, then you can do it here.
Finally, the computer comes to the "retf" command. This returns control back to the main BIOS.
        That's pretty simple, but you get the idea. Make a note of the next unused address. In this case, it is 0120h. Next, we need to write the file to disk. Just type "w" and <ENTER> at the Debug prompt to save the file.

-w
Writing 02000 bytes
-

        It saved the file, the length of which is 2000h bytes (8k). Quit Debug by entering "q". Incidentally, you can get a summary of the Debug commands by entering "?" at the Debug prompt.

4)        The only problem we have now is that the lower two digits of the checksum are probably not "00" any longer. Thus, you must load the new file into the buffer of your EPROM programmer software. It should tell you the checksum. Using your software, you can change that file in order to obtain the necessary checksum. Change any of the numbers that are after the address of your last instruction. In this case, I can change the data at addresses 0120h and following in order to get zeroes in the last two checksum digits. Of course, you only need to change on byte in order to obtain a valid checksum of zeros in the last two digits.

5)        Once accomplished, you can program a chip (must be the same type as the chip you removed) and put it in the expansion card. Power up the computer and see what happens. The computer should run through its regular startup routine before it runs your code. I use an old 80286 computer for testing this sort of thing, just in case something were to go horribly wrong.
For testing, I would suggest that you boot up off drive A: so that the screen with your message will definitely not be erased before you have a chance to see it. If the computer hangs up or does some strange beeping, then you may not have created a valid checksum. Maybe you forgot the last instruction, "retf." Maybe you started at an address other than 0103h.


Home