-
Notifications
You must be signed in to change notification settings - Fork 0
AWARD 4.5x hacking notes
This document contains information used to construct modifications in BIOSes on vintage motherboards.
It is the knowledge base for the BIOS modifications released here:
https://github.com/oerg866/TRW-BiosMods
The "New Setup Structure" usually starts at 0xF85C in the F Segment and contains the following items:
- 0xBB identifier
- F85D: Bios Setup Menu List Pointer
- F85F: Rom Table Pointer (Chipset register configuration list)
- F861: Rom Table End Pointer
- F863: "Auto Table" pointer - obsolete and unused IIRC?
- F865: "Auto Table" end pointer
- F867: "Auto Table" String list pointer
This is an array of Register list entries of the following format:
| Offset | Type | Description |
|---|---|---|
| 0 | BYTE | "Register Type" (?) - Not sure what this is. Seems to be 2 for most things, but I've seen 3 as well (might be for Power management regs) |
| 1 | BYTE | Index - Register index in PCI config space. |
| 2 | BYTE | PCI Device Identifier - For PCI this is 5 bits device, 3 bits function (always on bus 0). Not sure of the format for ISA devices. |
| 3 | WORD | Mask Mask of the bits that will be affected by this write. Example: FB would affect all bytes except bit 2 (1111 1X11). Note that this is a word, but for PCI config writes only the least significant byte will be used. I think this can theoretically also be used for 16 bit ISA writes, but I'm not sure. |
| 5 | WORD | Value The value to write to the register. It will be ANDed with the Mask and ORed with the previous value in the register. |
The size of this structure is 7 bytes and is not padded.
Note: The "New Setup Structure" is not usually how the BIOS retreives this table. This structure is there for automatic processing with tools such as CBROM and MODBIN, not for the BIOS' own operation.
It's sadly more "hardcoded" than that.
This is example code pulled from a BIOS ROM.
To relocate this table, both the vector table and the code must be updated.
This table is standardized for all BIOSes that support PCI 2.0.
At FE90 in the F segment you will find the 0xBB marker, along with an offset in the F segment to the PCI slot list.
CK_ORG 0FE90H
db 0bbh
extrn Pci_Slot_Cfg:near
dw offset DGROUP:Pci_Slot_CfgThe corresponding table would look like this:
db 0bh
db 0dh
db 0fh
db 11h
db 0ffhWhere there's 1 byte per slot ID and a list end marker (0xff).
Exception: ASUS PVI-486SP3 - The slot table does exist, but it is empty?!
TODO: Why? I assume ASUS is doing some ASUSian custom shenanigans here - MODBIN also shows the PCI slot table as empty. I have not yet been able to locate where.
Interesting factoid: The latest BIOS version for that board does have an intact interrupt table.
The expectation AWDBEDIT makes is that this table is standardized in the configuration vectors of the AWARD BIOS, at F_SEG:0FE99h.
The leaked AWARD 4.51PG source code confirms this suspicion, prepends it with the 0xAA identification marker.
However, this was previously not the case, as earlier 4.51 variants prove (e.g. SOYO 4SAW).
Generally, there seems to be no standardized way of finding this table, other than finding the code that loads it.
There are two major text rendering functions in any AWARD 4.5x BIOS:
Show_StringShow_CS_String
They take two parameters, the Segment and Offset of the string to show.
The difference between the two is that Show_String uses the ds (data segment) register as input parameter for the segment, whereas Show_CS_String uses the cs (code segment) register (really, it is just a wrapper that saves ds and then sets it to the value of ds before calling the regular Show_String).
The text can have control codes (ASCII < 0x20) in it, which allow you to modify text attributes or do other actions during the printing of the string.
The following table lists them for AWARD 4.50 / 4.51 (later BIOSes may differ slightly).
| Code | Name | Description |
|---|---|---|
| 0x00 | V_DONE | End of string marker. |
| 0x01 | V_DONE1 | End of string marker (OR blank entry marker, see details below.) |
| 0x02 | V_BORDER | Draw border on the screen. |
| 0x03 | V_CLEAR | Clear rectangle on the screen. |
| 0x04 | V_STRSHOW | Prints another sub-string and continues. |
| 0x05 | V_POS | Set absolute cursor position. |
| 0x06 | V_HILITE | Draws text with intensity bit set. |
| 0x07 | V_REVERSE | Draws text with "REVERSE" color of current color scheme (usually inverted to the regular color). |
| 0x08 | V_NORMAL | Resets text attributes (color, etc.) to normal. |
| 0x09 | V_BLINK | Draws text with BLINK attribute. |
| 0x0A | V_WARN | Draws text with "WARN" color of current color scheme. |
| 0x0B | V_NEWLINE | Moves cursor to the beginning of the next line. |
| 0x0C | V_ADDX | Add to X position. |
| 0x0D | V_SUBX | Subtract from X position. |
| 0x0E | V_ADDY | Add to Y position. |
| 0x0F | V_SUBY | Subtract from Y position. |
| 0x10 | V_CALLROUTINE | Calls a subroutine. |
Some control codes take an offset as part of the parameters. This is always an offset within the segment of the string that is currently being displayed.
There is no way to reference data in another segment within the strings.
This is another end of text marker, except for setup menu entry text.
In case of a setup menu entry, this indicates the current item should be skipped in the selection, i.e. not selectable.
Draws a border on the screen.
| Parameters | |
|---|---|
| BYTE | 0x02 (V_BORDER) |
| BYTE | Left X position |
| BYTE | Left Y position |
| BYTE | Right X position |
| BYTE | Right Y position |
| BYTE | Border type (Bitfield) |
| Bit | Border Type |
|---|---|
| 0x01 | ║ Double Border |
| 0x02 | ? Empty Border (?) |
| 0x04 | │ Line Border |
| 0x08 | ? "NO BORDER" (?) |
| 0x10 | Shadow Border (Late 4.51PG ONLY) |
I don't know why this is a bit field because other than shadow border, these seem mutually exclusive :thinking_face:
TODO
Calls the string printing function with another string. Frequently used to print the same string for multiple different options where part of the string remains identical between them all to save space.
| Parameters | |
|---|---|
| BYTE | 0x04 (V_STRSHOW) |
| BYTE | X Position (0xFF = at current position) |
| BYTE | Y Position (0xFF = at current position) |
| WORD | Offset of substring to insert. |
Set absolute cursor position.
| Parameters | |
|---|---|
| BYTE | 0x05 (V_POS) |
| BYTE | X Position |
| BYTE | Y Position |
Adds or subtracts from cursor X or Y position.
| Parameters | |
|---|---|
| BYTE | 0x0C (V_ADDX), 0x0D (V_SUBXX), 0x0E (V_ADDY), 0x0F (V_SUBY) |
| BYTE | Value to add/subtract |
Calls a subroutine before resuming printing
| Parameters | |
|---|---|
| BYTE | 0x05 (V_POS) |
| WORD | Offset of routine to call |
MenuItem struc ; (sizeof=0x19, mappedto_17)
ItemStatus dw ?
ItemName dw ? ; offset
ChipsetReg dw ?
ChipsetRegMask dw ?
CMOSLoc db ?
CMOSMask dw ?
FirstItemString dw ? ; offset
MinVal dw ?
MaxVal dw ?
ItemX db ?
ItemY db ?
PowerOnDefault dw ?
SetupDefault dw ?
HelpString dw ? ; offset
MenuItem ends
| Byte | Description |
|---|---|
| 0x1E-0x25 | USER Drive 1 Configuration |
| Cylinders | |
| Heads | |
| Precomp | |
| Landing | |
| Sectors | |
| 0x26-0x27 | USER Drive 2 Configuration |
| 0x3B | Weitek Coprocessor Config(?) |
| ---- | SETUP DATA START - These are typical and can vary from BIOS to BIOS |
| 0x40 | Chipset Features |
| 0x41 | Chipset Features (cont.) / Memory Timing Config |
| 0x42 | Chipset Features (cont.) |
| 0x43 | Chipset Features (cont.) |
| 0x45-0x46 | IDE/IO-Controller Config |
| 0x47 | USB Controller Config |
| 0x50 | Power Management Config |
| (For AMD K7: MSR Config) | |
| 0x53 | ACPI Suspend Config |
| 0x58-0x5A | Old BIOSes: IDE/IO-Controller Config |
| 0x60 | PCI Features Config |
| 0x62 | Jumperless CPU Config |
| 0x63 | Jumperless CPU Config (also: ICW195 Clockgen config) |
| 0x67 | User Drive 3...something? |
| 0x68-0x6F | User Drive 3 Configuration |
| 0x70 | User Drive 4...something? |
| 0x71-0x79 | User Drive 4 Configuration |
| 0x7A-0x7F | ? |
Generally, it can be said that between 0x40 and 0x66 is fair game for a BIOS to claim as its setup data.
For hacking, it's not really trivial to find a byte to put your own menu item data.
