Hi, I've already build some option rom of my own to patch my mobo to give it a IOQ of 4, and some memory interleaving patch. I've known the structure of PCI and ISA option rom. My last completed development is a custom OS in my LAN Card , it has an option ROM expansion so I just tested it there and it worked
. Enough with the tale, here is what I've known about it :
/--------------------------------------------------------------------------------------\
PINCZAKKO (a.k.a maman) notes on building an error free .COM file using MASM611
==> Extended March 9th 2003 to build your own .ROM file <==
\--------------------------------------------------------------------------------------/
1. The general form of a com file in MASM611 to generate an x86 ROM file as follows (This is a real working example):
;;----------------------------------------------------------------------------------
.386 ;;Processor type to use (actually) availabe GPR
option segment:use16 ;;USE 66h,67 prefix for 32 bits operand
.MODEL TINY ;;generic com file format
;;This is where you should put your macro declarations
.CODE
org 100h ;;com begins at 100h, then comes the real routine
start:
pushad ;save all GPR
mov eax,dram_reg ;fetch the address of the regs
mov dx,in_port ;fetch the input port addr config space
out dx,eax
mov dx,out_port
in eax,dx
or eax,dram_mask ;mask the regs value
out dx,eax
popad ;restore all GPR
retn ;return near to the header
;;The following part actually not only for equates but possibly also for
;;data declaration
dram_mask equ 00020202h
dram_reg equ 80000064h
in_port equ 0cf8h
out_port equ 0cfch
end start
;;-----------------------------------------------------------------------------------
2. To build *.com file of the routines above (assuming the file named hello.asm), invoke the following :
ML /AT hello.asm /link /TINY
Note: remember to copy the link.exe file to ml.exe directory to execute above. Also remember to place the file to be assembled in the same directory as ML.EXE and link.exe
3. To build *.rom , i.e. expansion rom from the plain binary file (*.com) you've created, is pretty easy. Before proceeding further, let me tell you what a *.rom file really is, based on my recent "research". A *.rom file actually is a binary file that conform the following conditions:
a. It is a plain binary file.
b. Its size is a multiple of 512 bytes.
c. Its header has the following format:
==> 55AAh ;this is the 1st and the 2nd byte, its a bootable code sign, it's actually AA55h, but Intel uses little endian that's why it's reversed.
==> xxh ;this is the 3rd byte, where xx is the hex number that indicate the size of the rom in multiple of 512 bytes, e.g. for a 512 bytes rom it will be 01h.
==> jmp ;Commonly this is the 4th through 6th byte, usually this is a near jump instruction that invoke the real initialization code of the rom.
==> ret (far);this is the last byte in the header, it invokes a far return to pass the program execution back to the main bios (original.tmp).
d. Its byte checksum is exactly zero, i.e. after all of its bytes summed and goes through modulo 100h operation, it's equal to zero. In practice this should be pretty easy, for example if you use Hexworkshop version 3.0, from tools menu choose generate checksum and choose byte (8 bit) checksum to see the checksum of your file, for a valid rom it should be equal to zero, this can be very handy if you want to turn your plain binary file into a valid rom, just open the file using Hexworkshop and then generate the checksum of your *.com file, if it's not zero then substract the remainder of your current checksum from 100h, this is the byte you need to insert into your plain binary file, I usually add this byte into the end of the program to compensate for the checksum needed (after the return instruction, so that it won't interfere with your main code).
O.K. after knowing how the exact format of a rom file we only need to concern about how to implement it. First, the header format should easy to be handled in assembly (masm syntax), we only need to generate a plain binary file i.e. building a *.com file if we're using masm, and then to get the real *.rom file we need a hexeditor i.e. hexworkshop and compensate for the size and checksum so that the expansion rom wouldn't be rejected by cbrom. To compensate for the size, just insert 00h as much as possible until it's a multiple of 512 bytes from Edit|Insert menu in Hexworkshop then proceed to compensate for the checksum as explained above and voila'... you're done
Here's another example of a working source code in plain binary (you still need to adjust the checksum):
;;------------------- TEST.ASM ---------------------------------------------------
.386
;;Macro definition
PATCH_PCI macro reg_addr,mask
mov eax,reg_addr ;fetch the address of the regs to be patched
mov dx,in_port ;fetch the input port addr of PCI cfg space
out dx,eax
mov dx,out_port
in eax,dx
or eax,mask ;mask the regs value (activate certn. bits)
out dx,eax
endm
CSEG SEGMENT PARA PUBLIC USE16 'CODE'
ASSUME CS:CSEG
ORG 0
;;Expansion rom header
DB 55h ;;Rom signature byte 1
DB 0AAh ;;Rom signature byte 2
DB 01h ;;512 bytes
jmp INIT ;;jump to initialization
DW 12h DUP (0) ;;Zero zone
;;equates, have been tested d00d & works fine
in_port equ 0cf8h
out_port equ 0cfch
ioq_mask equ 00000080h
ioq_reg equ 80000050h
bank_mask equ 20000844h
bank_reg equ 80000068h
tlb_mask equ 00000008h
tlb_reg equ 8000006ch
dram_mask equ 00020202h
dram_reg equ 80000064h
INIT PROC FAR
PATCH_PCI ioq_reg, ioq_mask ;patch the ioq reg
PATCH_PCI dram_reg, dram_mask ;patch the DRAM controller
;i.e. the interleaving part
PATCH_PCI bank_reg, bank_mask ;patch bank active page ctl reg
PATCH_PCI tlb_reg, tlb_mask ;Activate Fast TLB lookup
xor al,al ;clean up memory used (set image size to 0)
mov cs:[02h],al ;3rd byte of this bios image file
;not so sure yet, could become bug
retf ;return far to main bios routine (original.tmp)
INIT ENDP
ORG 01FFh
DB 00h
CSEG ENDS
END
;;-------------------------- END OF TEST.ASM -------------------------------------------
That's all I hope this could help you
:D:D